chore(tools): harden package and dependency checks

This commit is contained in:
Danila Poyarkov 2026-07-01 12:56:45 +03:00
parent b5665afab5
commit 9498dc203d
39 changed files with 598 additions and 301 deletions

527
bun.lock

File diff suppressed because it is too large Load diff

15
knip.json Normal file
View file

@ -0,0 +1,15 @@
{
"$schema": "https://unpkg.com/knip@6/schema.json",
"ignore": [
"desktop/target/**",
"**/dist/**",
"**/node_modules/**"
],
"ignoreWorkspaces": ["packages/acp", "packages/demos"],
"ignoreUnresolved": [
"~icons/*",
"/packages/core/src/text/fonts.ts",
"#core/*"
],
"ignoreBinaries": ["figma-use", "identify", "magick", "open", "osascript"]
}

View file

@ -219,6 +219,7 @@
"block-scoped-var": "error",
"default-case-last": "error",
"default-param-last": "error",
"guard-for-in": "error",
"no-array-constructor": "error",
"no-case-declarations": "error",
"no-caller": "error",
@ -310,6 +311,8 @@
"import/no-dynamic-require": "error",
"import/no-empty-named-blocks": "error",
"import/no-webpack-loader-syntax": "error",
"promise/always-return": "error",
"promise/catch-or-return": "error",
"promise/no-callback-in-promise": "error",
"promise/no-multiple-resolved": "error",
"promise/no-new-statics": "error",

View file

@ -4,8 +4,18 @@
"private": true,
"license": "MIT",
"workspaces": [
"packages/*"
"packages/scene-graph",
"packages/pen",
"packages/kiwi",
"packages/fig",
"packages/core",
"packages/dom-css",
"packages/vue",
"packages/cli",
"packages/mcp",
"packages/docs"
],
"packageManager": "bun@1.3.10",
"type": "module",
"scripts": {
"dev": "vite",
@ -16,9 +26,12 @@
"lint:structure": "oxlint -c oxlint.json vite.config.ts vite/ src/ packages/scene-graph/src/ packages/scene-graph/scripts/ packages/core/src/ packages/vue/src/ packages/cli/src/ packages/mcp/src/ packages/dom-css/src/ packages/dom-css/tests/ packages/dom-css/scripts/ packages/pen/src/ packages/pen/scripts/ packages/kiwi/src/ packages/kiwi/tests/ packages/kiwi/scripts/ packages/fig/src/ packages/fig/tests/ packages/fig/scripts/ tests/ scripts/ tools/",
"format": "oxfmt --write .oxfmtrc.json vite.config.ts vite/ src/ packages/scene-graph/src/ packages/scene-graph/scripts/ packages/core/src/ packages/cli/src/ packages/mcp/src/ packages/vue/src/ packages/dom-css/src/ packages/dom-css/tests/ packages/dom-css/scripts/ packages/pen/src/ packages/pen/scripts/ packages/kiwi/src/ packages/kiwi/tests/ packages/kiwi/scripts/ packages/fig/src/ packages/fig/tests/ packages/fig/scripts/ tests scripts/ tools/",
"format:check": "bun run format && status=$(git status --porcelain -uall) && test -z \"$status\" || (echo \"$status\" && exit 1)",
"check": "bun run build:packages && bun run lint && tsgo --noEmit && bun run check:vue && bun run check:i18n && bun run check:packages && bun run check:arch && bun run test:type-shapes && bun run test:tools && bun run test:dupes",
"check": "bun run build:packages && bun run lint && tsgo --noEmit && bun run check:vue && bun run check:i18n && bun run check:packages && bun run check:deps && bun run check:audit && bun run check:monorepo && bun run check:arch && bun run test:type-shapes && bun run test:tools && bun run test:dupes",
"check:deps": "knip --include unlisted,unresolved,binaries",
"check:audit": "bun audit --audit-level=critical",
"check:monorepo": "sherif --ignore-rule root-package-dependencies",
"check:i18n": "bun tools/i18n/src/check-locales.ts",
"check:packages": "bun tools/package-quality/src/check-metadata.ts",
"check:packages": "bun tools/package-quality/src/check/metadata.ts && bun tools/package-quality/src/check/publint.ts && bun tools/package-quality/src/check/attw.ts",
"check:arch": "steiger .",
"check:vue": "vue-tsc --noEmit -p tsconfig.json && vue-tsc --noEmit -p packages/vue/tsconfig.json",
"test": "playwright test --project=openpencil",
@ -32,7 +45,7 @@
"test:type-shapes": "bun tools/type-shapes/src/index.ts",
"test:tools": "bun tools/test.ts",
"test:dupes": "jscpd packages/scene-graph/src packages/pen/src packages/core/src packages/cli/src packages/dom-css/src src --min-lines 5 --min-tokens 50 --format typescript --threshold 0",
"test:packages": "bun tools/package-quality/src/check-metadata.ts && bun tools/package-quality/src/smoke.ts",
"test:packages": "bun tools/package-quality/src/check/metadata.ts && bun tools/package-quality/src/check/publint.ts && bun tools/package-quality/src/check/attw.ts && bun tools/package-quality/src/smoke.ts",
"build:packages": "bun --filter @open-pencil/scene-graph build && bun --filter @open-pencil/pen build && bun --filter @open-pencil/kiwi build && bun --filter @open-pencil/fig build && bun --filter @open-pencil/core build && bun --filter @open-pencil/dom-css build && bun --filter @open-pencil/vue build && bun --filter @open-pencil/mcp build && bun --filter @open-pencil/cli build",
"open-pencil": "bun packages/cli/src/index.ts",
"docs:dev": "bun --filter @open-pencil/docs dev",
@ -102,6 +115,7 @@
},
"devDependencies": {
"@agentclientprotocol/sdk": "^0.14.1",
"@arethetypeswrong/cli": "0.18.4",
"@feature-sliced/steiger-plugin": "^0.5.8",
"@figma/plugin-typings": "^1.126.0",
"@hono/node-server": "^1.19.11",
@ -120,12 +134,15 @@
"esbuild": "^0.27.3",
"hono": "^4.12.5",
"jscpd": "^4.0.8",
"knip": "6.20.0",
"mitata": "^1.0.34",
"oxfmt": "^0.35.0",
"oxlint": "^1.50.0",
"oxlint-tsgolint": "^0.16.0",
"publint": "0.3.20",
"sherif": "1.12.0",
"steiger": "^0.5.12",
"tsdown": "^0.21.7",
"tsdown": "^0.22.3",
"tw-animate-css": "^1.4.0",
"typescript": "~5.8.3",
"unplugin-icons": "^23.0.1",
@ -139,6 +156,7 @@
"ws": "^8.19.0"
},
"overrides": {
"brace-expansion": "5.0.6"
"brace-expansion": "5.0.6",
"protobufjs": "7.5.5"
}
}

View file

@ -35,6 +35,6 @@
"citty": "^0.1.6"
},
"devDependencies": {
"@types/bun": "^1.2.9"
"@types/bun": "^1.3.14"
}
}

View file

@ -54,12 +54,14 @@ export async function loadFonts(
r.invalidateAllPictures()
onFallbackFontsLoaded?.()
}
return undefined
})
void fontManager.ensureArabicFallback().then((families) => {
if (!r.isDestroyed() && families.length > 0) {
r.invalidateAllPictures()
onFallbackFontsLoaded?.()
}
return undefined
})
}

View file

@ -61,5 +61,7 @@ export { createElement } from './mini-react'
export { renderJSX, renderTreeNode, buildComponent } from './render'
import jsxReference from '#core/tools/prompts/jsx-reference.md'
export { sceneNodeToJSX, selectionToJSX, type JSXFormat } from '#core/io/formats/jsx'
export { default as JSX_REFERENCE } from '#core/tools/prompts/jsx-reference.md'
export const JSX_REFERENCE: string = jsxReference

View file

@ -1,3 +1,6 @@
import codegenPrompt from './tools/prompts/codegen.md'
import jsxReference from './tools/prompts/jsx-reference.md'
export { randomHex, randomInt, randomIndex } from './random'
export * from './constants'
@ -418,8 +421,8 @@ export {
export * from './io'
export * from './lint'
export { default as CODEGEN_PROMPT } from './tools/prompts/codegen.md'
export { default as JSX_REFERENCE } from './tools/prompts/jsx-reference.md'
export const CODEGEN_PROMPT: string = codegenPrompt
export const JSX_REFERENCE: string = jsxReference
export {
setPexelsApiKey,
setUnsplashAccessKey,

View file

@ -1,5 +1,7 @@
import codegenPrompt from './prompts/codegen.md'
export { ALL_TOOLS, CORE_TOOLS, EXTENDED_TOOLS } from './registry'
export { default as CODEGEN_PROMPT } from './prompts/codegen.md'
export const CODEGEN_PROMPT: string = codegenPrompt
export { exportImage } from './vector'
export { defineTool, nodeToResult, nodeSummary, requireNode, NodeNotFoundError } from './schema'
export type { ToolDef, ParamDef, ParamType } from './schema'

View file

@ -1,13 +1,13 @@
import { readFileSync } from 'node:fs'
import { defineConfig } from 'tsdown'
import type { Plugin } from 'rolldown'
import type { Rolldown } from 'tsdown'
const packageJson = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8')) as {
dependencies?: Record<string, string>
}
function rawText(): Plugin {
function rawText(): Rolldown.Plugin {
return {
name: 'raw-text',
load(id) {

View file

@ -12,39 +12,39 @@
},
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"types": "./dist/index.d.ts",
"bun": "./src/index.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
},
"./browser": {
"types": "./dist/src/browser.d.ts",
"types": "./dist/browser.d.ts",
"bun": "./src/browser.ts",
"import": "./dist/browser.js",
"default": "./dist/browser.js"
},
"./jsx-runtime": {
"types": "./dist/src/jsx/runtime.d.ts",
"types": "./dist/jsx-runtime.d.ts",
"bun": "./src/jsx/runtime.ts",
"import": "./dist/jsx-runtime.js",
"default": "./dist/jsx-runtime.js"
},
"./jsx-dev-runtime": {
"types": "./dist/src/jsx/dev-runtime.d.ts",
"types": "./dist/jsx-dev-runtime.d.ts",
"bun": "./src/jsx/dev-runtime.ts",
"import": "./dist/jsx-dev-runtime.js",
"default": "./dist/jsx-dev-runtime.js"
}
},
"main": "./dist/index.js",
"types": "./dist/src/index.d.ts",
"types": "./dist/index.d.ts",
"sideEffects": false,
"files": [
"dist",
"README.md"
],
"scripts": {
"build": "bunx tsdown --config tsdown.config.ts && bunx tsc --emitDeclarationOnly -p tsconfig.json",
"build": "bunx tsdown --config tsdown.config.ts",
"check": "bun run typecheck && bun run test && bun run build && bun run smoke:dist",
"prepack": "bun run build",
"smoke:dist": "bun scripts/smoke-dist.ts",
@ -66,7 +66,7 @@
},
"devDependencies": {
"@types/bun": "^1.3.14",
"tsdown": "^0.21.7",
"tsdown": "^0.22.3",
"typescript": "~5.8.3"
},
"dependencies": {

View file

@ -1,3 +1,5 @@
import type * as DesignTypes from './types'
export { serializeHTML, serializeNode } from './serialize'
export { createBrowserCSSRuntime, createCSSRuntime, createHeadlessCSSRuntime } from './runtime'
export {
@ -60,13 +62,11 @@ export type {
} from './browser'
export type { CompileTailwindCSSOptions } from './tailwind'
export type { ToSceneGraphOptions } from './to-scene-graph'
export type {
CSSComputeOptions,
CSSRuntime,
DesignDocument,
DesignElement,
DesignNode,
DesignStyleDeclaration,
DesignStyleSheet,
DesignText
} from './types'
export type CSSComputeOptions = DesignTypes.CSSComputeOptions
export type CSSRuntime = DesignTypes.CSSRuntime
export type DesignDocument = DesignTypes.DesignDocument
export type DesignElement = DesignTypes.DesignElement
export type DesignNode = DesignTypes.DesignNode
export type DesignStyleDeclaration = DesignTypes.DesignStyleDeclaration
export type DesignStyleSheet = DesignTypes.DesignStyleSheet
export type DesignText = DesignTypes.DesignText

View file

@ -9,7 +9,7 @@ export default defineConfig({
},
platform: 'neutral',
format: ['esm'],
dts: false,
dts: true,
sourcemap: true,
hash: false,
clean: true,

View file

@ -5,21 +5,21 @@
"type": "module",
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"types": "./dist/index.d.ts",
"bun": "./src/index.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
},
"main": "./dist/index.js",
"types": "./dist/src/index.d.ts",
"types": "./dist/index.d.ts",
"sideEffects": false,
"files": [
"dist",
"README.md"
],
"scripts": {
"build": "bunx tsdown --config tsdown.config.ts && bunx tsc --emitDeclarationOnly -p tsconfig.json",
"build": "bunx tsdown --config tsdown.config.ts",
"check": "bun run typecheck && bun run test && bun run build && bun run smoke:dist",
"prepack": "bun run build",
"smoke:dist": "bun scripts/smoke-dist.ts",
@ -40,7 +40,7 @@
},
"devDependencies": {
"@types/bun": "^1.3.14",
"tsdown": "^0.21.7",
"tsdown": "^0.22.3",
"typescript": "~5.8.3"
}
}

View file

@ -6,6 +6,7 @@
"declaration": true,
"declarationMap": true,
"emitDeclarationOnly": true,
"noEmit": false,
"tsBuildInfoFile": "dist/tsconfig.tsbuildinfo",
"types": ["bun"]
},

View file

@ -6,7 +6,7 @@ export default defineConfig({
},
platform: 'neutral',
format: ['esm'],
dts: false,
dts: true,
sourcemap: true,
hash: false,
clean: true,

View file

@ -5,57 +5,57 @@
"type": "module",
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"types": "./dist/index.d.ts",
"bun": "./src/index.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
},
"./schema-runtime": {
"types": "./dist/src/schema-runtime/index.d.ts",
"types": "./dist/schema-runtime.d.ts",
"bun": "./src/schema-runtime/index.ts",
"import": "./dist/schema-runtime.js",
"default": "./dist/schema-runtime.js"
},
"./fig": {
"types": "./dist/src/fig/index.d.ts",
"types": "./dist/fig.d.ts",
"bun": "./src/fig/index.ts",
"import": "./dist/fig.js",
"default": "./dist/fig.js"
},
"./fig/codec": {
"types": "./dist/src/fig/codec.d.ts",
"types": "./dist/fig/codec.d.ts",
"bun": "./src/fig/codec.ts",
"import": "./dist/fig/codec.js",
"default": "./dist/fig/codec.js"
},
"./fig/container": {
"types": "./dist/src/fig/container.d.ts",
"types": "./dist/fig/container.d.ts",
"bun": "./src/fig/container.ts",
"import": "./dist/fig/container.js",
"default": "./dist/fig/container.js"
},
"./fig/guid": {
"types": "./dist/src/fig/guid.d.ts",
"types": "./dist/fig/guid.d.ts",
"bun": "./src/fig/guid.ts",
"import": "./dist/fig/guid.js",
"default": "./dist/fig/guid.js"
},
"./fig/parse": {
"types": "./dist/src/fig/parse.d.ts",
"types": "./dist/fig/parse.d.ts",
"bun": "./src/fig/parse.ts",
"import": "./dist/fig/parse.js",
"default": "./dist/fig/parse.js"
}
},
"main": "./dist/index.js",
"types": "./dist/src/index.d.ts",
"types": "./dist/index.d.ts",
"sideEffects": false,
"files": [
"dist",
"README.md"
],
"scripts": {
"build": "bunx tsdown --config tsdown.config.ts && bunx tsc --emitDeclarationOnly -p tsconfig.json",
"build": "bunx tsdown --config tsdown.config.ts",
"check": "bun run typecheck && bun run test && bun run build && bun run smoke:dist",
"prepack": "bun run build",
"smoke:dist": "bun scripts/smoke-dist.ts",
@ -77,7 +77,7 @@
},
"devDependencies": {
"@types/bun": "^1.3.14",
"tsdown": "^0.21.7",
"tsdown": "^0.22.3",
"typescript": "~5.8.3"
}
}

View file

@ -1,9 +1,9 @@
import { readFileSync } from 'node:fs'
import { defineConfig } from 'tsdown'
import type { Plugin } from 'rolldown'
import type { Rolldown } from 'tsdown'
function rawText(): Plugin {
function rawText(): Rolldown.Plugin {
return {
name: 'raw-text',
load(id) {
@ -28,7 +28,7 @@ export default defineConfig({
plugins: [rawText()],
platform: 'neutral',
format: ['esm'],
dts: false,
dts: true,
sourcemap: true,
hash: false,
clean: true,

View file

@ -44,16 +44,16 @@
"provenance": true
},
"dependencies": {
"@hono/node-server": "^1.19.9",
"@modelcontextprotocol/sdk": "^1.25.2",
"@hono/node-server": "^1.19.11",
"@modelcontextprotocol/sdk": "^1.27.1",
"@open-pencil/core": "workspace:*",
"hono": "^4.11.4",
"hono": "^4.12.5",
"package-manager-detector": "^1.6.0",
"zod": "^4.3.6",
"ws": "^8.19.0"
"ws": "^8.19.0",
"zod": "^4.3.6"
},
"devDependencies": {
"@types/node": "^22.0.0",
"@types/node": "^25.3.2",
"@types/ws": "^8.18.1"
}
}

View file

@ -5,21 +5,21 @@
"type": "module",
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"types": "./dist/index.d.ts",
"bun": "./src/index.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
}
},
"main": "./dist/index.js",
"types": "./dist/src/index.d.ts",
"types": "./dist/index.d.ts",
"sideEffects": false,
"files": [
"dist",
"README.md"
],
"scripts": {
"build": "bunx tsdown --config tsdown.config.ts && bunx tsc --emitDeclarationOnly -p tsconfig.json",
"build": "bunx tsdown --config tsdown.config.ts",
"check": "bun run typecheck && bun run build && bun run smoke:dist",
"prepack": "bun run build",
"smoke:dist": "bun scripts/smoke-dist.ts",
@ -43,7 +43,7 @@
"devDependencies": {
"@types/bun": "^1.3.14",
"@types/culori": "^4.0.1",
"tsdown": "^0.21.7",
"tsdown": "^0.22.3",
"typescript": "~5.8.3"
}
}

View file

@ -6,7 +6,7 @@ export default defineConfig({
},
platform: 'neutral',
format: ['esm'],
dts: false,
dts: true,
sourcemap: true,
hash: false,
clean: true,

View file

@ -5,141 +5,141 @@
"type": "module",
"exports": {
".": {
"types": "./dist/src/index.d.ts",
"types": "./dist/index.d.ts",
"bun": "./src/index.ts",
"import": "./dist/index.js",
"default": "./dist/index.js"
},
"./copy": {
"types": "./dist/src/copy.d.ts",
"types": "./dist/copy.d.ts",
"bun": "./src/copy.ts",
"import": "./dist/copy.js",
"default": "./dist/copy.js"
},
"./node-defaults": {
"types": "./dist/src/node-defaults.d.ts",
"types": "./dist/node-defaults.d.ts",
"bun": "./src/node-defaults.ts",
"import": "./dist/node-defaults.js",
"default": "./dist/node-defaults.js"
},
"./instances": {
"types": "./dist/src/instances.d.ts",
"types": "./dist/instances.d.ts",
"bun": "./src/instances.ts",
"import": "./dist/instances.js",
"default": "./dist/instances.js"
},
"./snap": {
"types": "./dist/src/snap.d.ts",
"types": "./dist/snap.d.ts",
"bun": "./src/snap.ts",
"import": "./dist/snap.js",
"default": "./dist/snap.js"
},
"./source-metadata": {
"types": "./dist/src/source-metadata.d.ts",
"types": "./dist/source-metadata.d.ts",
"bun": "./src/source-metadata.ts",
"import": "./dist/source-metadata.js",
"default": "./dist/source-metadata.js"
},
"./undo": {
"types": "./dist/src/undo.d.ts",
"types": "./dist/undo.d.ts",
"bun": "./src/undo.ts",
"import": "./dist/undo.js",
"default": "./dist/undo.js"
},
"./variant-name": {
"types": "./dist/src/variant-name.d.ts",
"types": "./dist/variant-name.d.ts",
"bun": "./src/variant-name.ts",
"import": "./dist/variant-name.js",
"default": "./dist/variant-name.js"
},
"./vector-network": {
"types": "./dist/src/vector-network.d.ts",
"types": "./dist/vector-network.d.ts",
"bun": "./src/vector-network.ts",
"import": "./dist/vector-network.js",
"default": "./dist/vector-network.js"
},
"./types": {
"types": "./dist/src/types.d.ts",
"types": "./dist/types.d.ts",
"bun": "./src/types.ts",
"import": "./dist/types.js",
"default": "./dist/types.js"
},
"./primitives": {
"types": "./dist/src/primitives.d.ts",
"types": "./dist/primitives.d.ts",
"bun": "./src/primitives.ts",
"import": "./dist/primitives.js",
"default": "./dist/primitives.js"
},
"./constants": {
"types": "./dist/src/constants.d.ts",
"types": "./dist/constants.d.ts",
"bun": "./src/constants.ts",
"import": "./dist/constants.js",
"default": "./dist/constants.js"
},
"./hit-test": {
"types": "./dist/src/hit-test.d.ts",
"types": "./dist/hit-test.d.ts",
"bun": "./src/hit-test.ts",
"import": "./dist/hit-test.js",
"default": "./dist/hit-test.js"
},
"./preview": {
"types": "./dist/src/preview.d.ts",
"types": "./dist/preview.d.ts",
"bun": "./src/preview.ts",
"import": "./dist/preview.js",
"default": "./dist/preview.js"
},
"./text-picture": {
"types": "./dist/src/text-picture.d.ts",
"types": "./dist/text-picture.d.ts",
"bun": "./src/text-picture.ts",
"import": "./dist/text-picture.js",
"default": "./dist/text-picture.js"
},
"./variables": {
"types": "./dist/src/variables.d.ts",
"types": "./dist/variables.d.ts",
"bun": "./src/variables.ts",
"import": "./dist/variables.js",
"default": "./dist/variables.js"
},
"./images": {
"types": "./dist/src/images.d.ts",
"types": "./dist/images.d.ts",
"bun": "./src/images.ts",
"import": "./dist/images.js",
"default": "./dist/images.js"
},
"./coordinate": {
"types": "./dist/src/coordinate.d.ts",
"types": "./dist/coordinate.d.ts",
"bun": "./src/coordinate.ts",
"import": "./dist/coordinate.js",
"default": "./dist/coordinate.js"
},
"./matrix": {
"types": "./dist/src/matrix.d.ts",
"types": "./dist/matrix.d.ts",
"bun": "./src/matrix.ts",
"import": "./dist/matrix.js",
"default": "./dist/matrix.js"
},
"./geometry": {
"types": "./dist/src/geometry.d.ts",
"types": "./dist/geometry.d.ts",
"bun": "./src/geometry.ts",
"import": "./dist/geometry.js",
"default": "./dist/geometry.js"
},
"./parse-path": {
"types": "./dist/src/parse-path.d.ts",
"types": "./dist/parse-path.d.ts",
"bun": "./src/parse-path.ts",
"import": "./dist/parse-path.js",
"default": "./dist/parse-path.js"
}
},
"main": "./dist/index.js",
"types": "./dist/src/index.d.ts",
"types": "./dist/index.d.ts",
"sideEffects": false,
"files": [
"dist",
"README.md"
],
"scripts": {
"build": "bunx tsdown --config tsdown.config.ts && bunx tsc --emitDeclarationOnly -p tsconfig.json",
"build": "bunx tsdown --config tsdown.config.ts",
"check": "bun run typecheck && bun run build && bun run smoke:dist",
"prepack": "bun run build",
"smoke:dist": "bun scripts/smoke-dist.ts",
@ -161,7 +161,7 @@
},
"devDependencies": {
"@types/bun": "^1.3.14",
"tsdown": "^0.21.7",
"tsdown": "^0.22.3",
"typescript": "~5.8.3"
}
}

View file

@ -26,7 +26,7 @@ export default defineConfig({
},
platform: 'neutral',
format: ['esm'],
dts: false,
dts: true,
sourcemap: true,
hash: false,
clean: true,

View file

@ -38,9 +38,9 @@
"provenance": true
},
"peerDependencies": {
"vue": "^3.4.0",
"@open-pencil/core": "workspace:*",
"canvaskit-wasm": ">=0.39.0"
"canvaskit-wasm": ">=0.39.0",
"vue": "^3.4.0"
},
"peerDependenciesMeta": {
"canvaskit-wasm": {
@ -59,7 +59,7 @@
"reka-ui": "^2.9.0"
},
"devDependencies": {
"tsdown": "^0.21.7",
"tsdown": "^0.22.3",
"unplugin-raw": "^0.6.4",
"unplugin-vue": "^7.1.1"
}

View file

@ -74,6 +74,7 @@ export function createCanvasSurfaceManager({
if (reloadFonts && !isDestroyed()) {
void state.renderer.loadFonts(renderNow).then(() => {
if (!isDestroyed()) renderNow()
return undefined
})
}
}

View file

@ -178,9 +178,8 @@ export function getHitHandleByMatrix(
const CORNER_R = HANDLE_HIT_RADIUS / zoom
const rotation = getAbsoluteRotation(node, graph)
for (const key in handles) {
for (const [key, p] of Object.entries(handles)) {
const handleKey = key as HandlePosition
const p = handles[handleKey]
const dx = cx - p.x
const dy = cy - p.y

View file

@ -191,6 +191,7 @@ export class ACPChatTransport implements ChatTransport<UIMessage> {
})
.then((result) => {
finish(result.stopReason === 'end_turn' ? 'stop' : 'other')
return undefined
})
.catch((e) => {
finish('error', formatConnectionError(e, this.agentDef))

View file

@ -32,5 +32,6 @@ export function createDemoShapes(store: EditorStore) {
store.clearSelection()
void store.loadFontsForNodes(graph.getPages().flatMap((page) => page.childIds)).then(() => {
store.requestRender()
return undefined
})
}

View file

@ -26,6 +26,7 @@ export function createCanvasMenuActions(store: EditorStore, selectedIds: Ref<Set
function execCommand(cmd: 'copy' | 'cut' | 'paste') {
void executeClipboardCommand(store, cmd).then((ok) => {
if (!ok) toast.error('Clipboard access is blocked in this browser context')
return undefined
})
}

View file

@ -32,6 +32,7 @@ export function bindEditorClipboard(store: EditorStore) {
if (isTauri()) {
void copySelectionToTauriClipboard(store).then((copied) => {
if (copied) store.deleteSelected()
return undefined
})
return
}

View file

@ -83,7 +83,7 @@ export function useMenu() {
}
void import('@tauri-apps/api/event').then(({ listen }) => {
void listen<string>('menu-event', (event) => {
return listen<string>('menu-event', (event) => {
if (COMMAND_MENU_IDS.has(event.payload)) {
runCommand(event.payload as EditorCommandId)
return
@ -91,6 +91,7 @@ export function useMenu() {
actions[event.payload]?.()
}).then((fn) => {
unlisten = fn
return undefined
})
})

View file

@ -27,9 +27,14 @@ const { dialogs } = useI18n()
const chat = ref<Chat<UIMessage> | null>(null)
ensureChat().then((c) => {
if (c) chat.value = markRaw(c)
})
void ensureChat()
.then((c) => {
if (c) chat.value = markRaw(c)
return undefined
})
.catch((error: unknown) => {
toast.error(error instanceof Error ? error.message : 'Failed to initialize chat')
})
const messagesEnd = ref<HTMLDivElement>()
const debugCopied = refAutoReset(false, 1500)
const acpLogCopied = refAutoReset(false, 1500)

View file

@ -15,5 +15,6 @@ createApp(App).use(router).use(head).mount('#app')
if (!IS_TAURI) {
void import('virtual:pwa-register').then(({ registerSW }) => {
registerSW({ immediate: true })
return undefined
})
}

View file

@ -105,6 +105,7 @@ async function createStdioClient(wsPort: number) {
}
void client.connect(transport).then(() => {
setTimeout(resolve, 1000)
return undefined
})
})

View file

@ -0,0 +1,39 @@
import { publicPackageDirs } from '../packages'
const excludedPackages = new Map([
[
'packages/vue',
'tsdown currently emits declaration imports through generated #vue/scene-graph/dist/*2.js names'
]
])
let failed = false
for (const packageDir of publicPackageDirs) {
const exclusionReason = excludedPackages.get(packageDir)
if (exclusionReason) {
console.warn(`Skipping ATTW for ${packageDir}: ${exclusionReason}`)
continue
}
const proc = Bun.spawnSync(
['bun', 'attw', '--pack', packageDir, '--profile', 'esm-only', '--format', 'ascii'],
{
stdout: 'pipe',
stderr: 'pipe'
}
)
const stdout = proc.stdout.toString()
const stderr = proc.stderr.toString()
if (!proc.success) {
console.error(`ATTW failed for ${packageDir}`)
if (stdout) console.error(stdout)
if (stderr) console.error(stderr)
failed = true
}
}
if (failed) process.exit(1)
console.log('ATTW package type-resolution checks passed.')

View file

@ -1,20 +1,11 @@
import { readFileSync } from 'node:fs'
import { join } from 'node:path'
const publicPackages = [
'packages/scene-graph',
'packages/pen',
'packages/core',
'packages/dom-css',
'packages/kiwi',
'packages/fig',
'packages/cli',
'packages/mcp',
'packages/vue'
]
import { publicPackageDirs } from '../packages'
interface PackageJson {
name: string
version: string
main?: string
types?: string
files?: string[]
@ -29,6 +20,9 @@ function readPackageJson(packageDir: string): PackageJson {
return JSON.parse(readFileSync(join(packageDir, 'package.json'), 'utf8'))
}
const rootPackage = readPackageJson('.')
const expectedVersion = rootPackage.version
function checkRuntimePath(packageName: string, field: string, value: string): void {
if (value.endsWith('.ts') && !value.endsWith('.d.ts')) {
errors.push(`${packageName}: ${field} must not point to runtime TypeScript (${value})`)
@ -67,9 +61,13 @@ function walkExports(packageName: string, value: unknown, path: string[] = []):
}
}
for (const packageDir of publicPackages) {
for (const packageDir of publicPackageDirs) {
const pkg = readPackageJson(packageDir)
if (pkg.version !== expectedVersion) {
errors.push(`${pkg.name}: version ${pkg.version} must match root version ${expectedVersion}`)
}
if (!pkg.files?.includes('dist')) {
errors.push(`${pkg.name}: files must include dist`)
}

View file

@ -0,0 +1,24 @@
import { fileURLToPath } from 'node:url'
import { publicPackageDirs } from '../packages'
const rootDir = fileURLToPath(new URL('../../../..', import.meta.url))
for (const packageDir of publicPackageDirs) {
const proc = Bun.spawnSync(['bun', 'publint', packageDir, '--strict'], {
cwd: rootDir,
stdout: 'pipe',
stderr: 'pipe'
})
const stdout = proc.stdout.toString()
const stderr = proc.stderr.toString()
if (!proc.success) {
console.error(`publint failed for ${packageDir}`)
if (stdout) console.error(stdout)
if (stderr) console.error(stderr)
process.exit(proc.exitCode || 1)
}
}
console.log('Publint package checks passed.')

View file

@ -0,0 +1,26 @@
import { readFileSync } from 'node:fs'
import { join } from 'node:path'
import { fileURLToPath } from 'node:url'
interface RootPackageJson {
workspaces?: string[]
}
interface WorkspacePackageJson {
private?: boolean
}
const rootDir = fileURLToPath(new URL('../../..', import.meta.url))
function readJson<T>(path: string): T {
return JSON.parse(readFileSync(path, 'utf8')) as T
}
const rootPackage = readJson<RootPackageJson>(join(rootDir, 'package.json'))
export const publicPackageDirs = (rootPackage.workspaces ?? []).filter((workspaceDir) => {
const workspacePackage = readJson<WorkspacePackageJson>(
join(rootDir, workspaceDir, 'package.json')
)
return workspacePackage.private !== true
})

View file

@ -3,18 +3,9 @@ import { tmpdir } from 'node:os'
import { basename, join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { publicPackageDirs } from './packages'
const rootDir = fileURLToPath(new URL('../../..', import.meta.url))
const packageDirs = [
'packages/scene-graph',
'packages/pen',
'packages/kiwi',
'packages/fig',
'packages/core',
'packages/dom-css',
'packages/vue',
'packages/mcp',
'packages/cli'
]
function run(command: string[], cwd = rootDir): string {
const proc = Bun.spawnSync(command, { cwd, stdout: 'pipe', stderr: 'pipe' })
@ -39,7 +30,7 @@ try {
run(['bun', 'run', 'build:packages'])
const tarballs: string[] = []
for (const packageDir of packageDirs) {
for (const packageDir of publicPackageDirs) {
const output = run(
['bun', 'pm', 'pack', '--destination', tempDir, '--quiet'],
join(rootDir, packageDir)