openpencil/package.json
Danila Poyarkov 8131401ead
fix: explain unsupported browsers instead of a blank window (#745)
* fix: explain unsupported browsers instead of a blank window

The desktop app on macOS 13 with WebKit older than Safari 17.4 opened an
empty window because startup called Promise.withResolvers, which Vite lowers
nothing for: build.target only rewrites syntax and never polyfills APIs, and
the target itself was an implicit Vite default (#744).

Make the supported baseline explicit in src/app/shell/support/baseline.ts and
feed it to build.target, a lint rule that rejects newer static built-ins in
browser-shipped sources, and the documented system requirements. Replace
Promise.withResolvers with a createDeferred() helper.

Turn src/main.ts into a small gate that checks sentinel features before
dynamically importing the app, so an old engine still evaluates enough code
to render platform-specific update guidance: macOS/Safari via Software
Update, WebKitGTK and WebView2 on Linux and Windows, and each browser's
own update path on the web, with a prefilled bug report link. Render-blocking
errors during the first route are captured through app.config.errorHandler
and shown the same way instead of leaving the window blank.

Desktop facts come from tauri-plugin-os and a webview_version command; the
bundle now declares macOS 13 as its minimum system version.

* build: enforce the browser baseline from compatibility data

Replace the hand-maintained list of built-ins newer than the baseline with
two data-driven checks. The app and browser-shipped packages pin their
TypeScript lib to ES2023, the last edition Chrome 111, Firefox 128 and
Safari 16.4 implement in full, so a newer built-in such as
Promise.withResolvers fails type-checking. Web APIs, which lib.dom does not
version, go through eslint-plugin-compat under oxlint with the same browsers
in settings.browsers, scoped to sources that ship to a browser.

A unit test keeps the oxlint browser list and the tsconfig libs derived from
src/app/shell/support/baseline.ts, so the three cannot drift apart.

* fix: recognise production error codes in the boot observer

Vue passes the error reference URL as the errorHandler info argument in
production builds instead of the development string, so the observer never
classified a setup or render failure as fatal in the shipped app and the
boot-failure notice only appeared on the dev server. Match Vue's exported
ErrorCodes in both forms, and cover the component-setup path in the E2E
spec; the scenario was also verified against a production build.
2026-09-22 14:40:59 +04:00

247 lines
11 KiB
JSON

{
"name": "open-pencil-app",
"version": "0.15.1",
"private": true,
"license": "MIT",
"workspaces": [
"packages/scene-graph",
"packages/pen",
"packages/kiwi",
"packages/fig",
"packages/core",
"packages/dom-css",
"packages/vue",
"packages/cli",
"packages/mcp",
"packages/harness",
"packages/docs",
"tools/brand",
"tools/docs",
"tools/lint",
"tools/package-artifacts",
"tools/authoring-reference",
"tools/package-quality",
"tools/release-packages",
"tools/tauri-menu",
"tools/visual-oracles"
],
"type": "module",
"scripts": {
"dev": "vite",
"dev:portless": "portless run vite",
"build": "bun run build:packages && bun run lint && vite build",
"preview": "vite preview",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build",
"tauri": "tauri",
"build:native-test": "bun run generate:icons --target desktop && bun run build:packages && bun tauri build --debug --no-bundle --features native-test --config desktop/tauri.native-test.conf.json",
"benchmark:navigation": "bun tools/navigation-benchmark/src/cli.ts run",
"benchmark:navigation:test": "bun test tools/navigation-benchmark/tests",
"test:native": "bun run build:native-test && wdio run wdio.conf.ts",
"lint": "bun run lint:structure && oxlint -c oxlint.json --type-aware --type-check src/ packages/scene-graph/src/ packages/core/src/ packages/vue/src/ packages/cli/src/ packages/mcp/src/ packages/harness/src/ packages/dom-css/src/ packages/pen/src/ packages/kiwi/src/ packages/fig/src/",
"lint:structure": "oxlint -c oxlint.json commitlint.config.ts vite.config.ts vite/ .storybook/ src/ packages/scene-graph/src/ packages/scene-graph/scripts/ packages/core/src/ packages/vue/src/ packages/cli/src/ packages/mcp/src/ packages/harness/src/ packages/harness/tests/ 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 commitlint.config.ts vite.config.ts vite/ .storybook/ src/ packages/scene-graph/src/ packages/scene-graph/scripts/ packages/core/src/ packages/cli/src/ packages/mcp/src/ packages/harness/src/ packages/harness/tests/ 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 check:icons && bun run build:packages && bun run lint && tsgo --noEmit && bun run check:vue && bun run check:native-test && bun run check:i18n && bun run check:docs && bun run check:changelog && bun run check:packages && bun run check:deps && bun run check:audit && bun run check:secrets && bun run check:monorepo && bun run check:arch && bun run test:type-shapes && bun run test:tools && bun run test:dupes",
"check:commits": "commitlint",
"check:changelog": "bun tools/release-packages/src/check-changelog.ts",
"check:deps": "knip --include unlisted,unresolved,binaries",
"check:docs": "bun --filter @open-pencil/docs check && bun run check:authoring-reference",
"check:authoring-reference": "bun tools/authoring-reference/src/check.ts",
"generate:authoring-reference": "bun tools/authoring-reference/src/generate.ts",
"check:audit": "bun audit --audit-level=critical",
"check:secrets": "bun tools/secret-scan/src/index.ts",
"check:monorepo": "sherif --ignore-rule root-package-dependencies",
"check:native-test": "tsc --noEmit -p tests/e2e/native/tsconfig.json",
"check:i18n": "bun tools/i18n/src/check-locales.ts",
"check:packages": "bun tools/package-quality/src/cli.ts check",
"check:arch": "steiger .",
"check:vue": "vue-tsc --noEmit -p tsconfig.json && vue-tsc --noEmit -p packages/vue/tsconfig.json",
"test": "OPENPENCIL_TEST_SERVER=app playwright test --project=openpencil --grep-invert @real-llm",
"test:storybook": "OPENPENCIL_TEST_SERVER=storybook playwright test --project=storybook-chromium",
"test:real-llm": "OPENPENCIL_TEST_SERVER=app playwright test --project=openpencil --grep @real-llm",
"test:update": "OPENPENCIL_TEST_SERVER=app playwright test --project=openpencil --update-snapshots",
"test:figma": "OPENPENCIL_TEST_SERVER=app playwright test --project=figma",
"figma:debug": "open -a Figma --args --remote-debugging-port=9222",
"typecheck": "tsgo --noEmit && bun run check:vue",
"test:unit": "bun tools/unit-tests/src/run.ts all --include-heavy",
"test:unit:quick": "bun tools/unit-tests/src/run.ts all -- --parallel",
"test:unit:isolated": "bun tools/unit-tests/src/run.ts all -- --isolate",
"test:unit:heavy": "bun tools/unit-tests/src/run.ts all --heavy-only -- --timeout 180000",
"test:coverage": "bun tools/unit-tests/src/run.ts all --include-heavy -- --coverage",
"test:type-shapes": "bun tools/type-shapes/src/index.ts",
"test:tools": "bun tools/test.ts && bun --filter @open-pencil/harness test",
"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/cli.ts verify",
"build:packages": "bun tools/package-artifacts/src/build.ts",
"open-pencil": "bun packages/cli/src/index.ts",
"docs:dev": "bun --filter @open-pencil/docs dev",
"docs:build": "bun --filter @open-pencil/docs build",
"docs:build:production": "bun --filter @open-pencil/docs build:production",
"docs:preview": "bun --filter @open-pencil/docs preview",
"generate:icons": "bun tools/brand/src/cli.ts generate",
"check:icons": "bun tools/brand/src/cli.ts check && bun --filter @open-pencil/brand-tools check",
"generate:tauri-menu": "bun tools/tauri-menu/src/generate.ts"
},
"dependencies": {
"@ai-sdk/anthropic": "^4.0.39",
"@ai-sdk/deepseek": "^3.0.28",
"@ai-sdk/google": "^4.0.44",
"@ai-sdk/openai": "^4.0.42",
"@ai-sdk/valibot": "^3.0.27",
"@ai-sdk/vue": "^4.0.66",
"@atlaskit/pragmatic-drag-and-drop": "^1.8.1",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.2.0",
"@chenglou/pretext": "^0.0.7",
"@codemirror/autocomplete": "^6.20.3",
"@codemirror/commands": "^6.11.0",
"@codemirror/lang-html": "^6.4.12",
"@codemirror/lang-javascript": "^6.2.5",
"@codemirror/language": "^6.12.4",
"@codemirror/lint": "^6.9.7",
"@codemirror/search": "^6.7.1",
"@codemirror/state": "^6.7.1",
"@codemirror/view": "^6.43.9",
"@lezer/highlight": "^1.2.3",
"@nanostores/i18n": "^1.3.3",
"@nanostores/vue": "^1.1.0",
"@open-pencil/cli": "workspace:*",
"@open-pencil/core": "workspace:*",
"@open-pencil/dom-css": "workspace:*",
"@open-pencil/fig": "workspace:*",
"@open-pencil/harness": "workspace:*",
"@open-pencil/kiwi": "workspace:*",
"@open-pencil/pen": "workspace:*",
"@open-pencil/scene-graph": "workspace:*",
"@open-pencil/vue": "workspace:*",
"@openrouter/ai-sdk-provider": "^3.0.0",
"@stream-markdown/code": "2.0.0-beta.5",
"@tailwindcss/vite": "^4.3.3",
"@tanstack/vue-table": "^8.21.3",
"@tauri-apps/api": "^2.11.1",
"@tauri-apps/plugin-clipboard-manager": "^2.3.2",
"@tauri-apps/plugin-dialog": "^2.7.2",
"@tauri-apps/plugin-fs": "^2.5.1",
"@tauri-apps/plugin-opener": "^2.5.4",
"@tauri-apps/plugin-os": "^2.3.2",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-shell": "^2.3.5",
"@tauri-apps/plugin-updater": "^2.10.1",
"@unhead/vue": "^2.1.17",
"@valibot/to-json-schema": "^1.8.0",
"@vueuse/core": "^14.4.0",
"@xmldom/xmldom": "^0.9.11",
"ai": "^7.0.66",
"aws4fetch": "^1.0.20",
"canvaskit-wasm": "^0.41.1",
"copy-to-clipboard": "^4.0.2",
"culori": "^4.0.2",
"dedent": "^1.7.2",
"es-toolkit": "^1.51.0",
"fflate": "^0.8.3",
"fuse.js": "^7.5.0",
"fzstd": "^0.1.1",
"hast-util-to-html": "^9.0.5",
"idb": "^8.0.3",
"jspdf": "^4.2.1",
"lib0": "^0.2.117",
"motion-v": "^2.4.0",
"nanostores": "^1.5.0",
"opentype.js": "^2.0.0",
"reka-ui": "^2.10.3",
"svg2pdf.js": "^2.7.0",
"tailwind-merge": "^3.6.0",
"tailwind-variants": "^3.3.1",
"tailwindcss": "^4.3.3",
"tinykeys": "^3.1.0",
"trystero": "^0.22.0",
"valibot": "^1.4.2",
"vee-validate": "5.0.0-beta.0",
"vue": "^3.5.41",
"vue-router": "^5.2.0",
"vue-stream-markdown": "2.0.0-beta.5",
"y-indexeddb": "^9.0.12",
"y-protocols": "^1.0.7",
"yjs": "^13.6.32",
"yoga-layout": "npm:@open-pencil/yoga-layout@3.3.0-grid.3",
"zod": "^4.4.3"
},
"devDependencies": {
"@agentclientprotocol/sdk": "^0.14.1",
"@arethetypeswrong/cli": "0.18.4",
"@commitlint/cli": "^21.2.2",
"@commitlint/config-conventional": "^21.2.2",
"@commitlint/is-ignored": "^21.2.2",
"@commitlint/types": "^21.2.0",
"@feature-sliced/steiger-plugin": "^0.5.8",
"@figma/plugin-typings": "^1.134.0",
"@hono/node-server": "^1.19.17",
"@iconify-json/lucide": "^1.2.123",
"@modelcontextprotocol/client": "^2.0.0",
"@open-pencil/brand-tools": "workspace:*",
"@open-pencil/mcp": "workspace:*",
"@oxlint/plugins": "1.57.0",
"@playwright/test": "^1.62.1",
"@storybook/addon-a11y": "^10.5.8",
"@storybook/addon-docs": "^10.5.8",
"@storybook/addon-themes": "^10.5.8",
"@storybook/vue3-vite": "^10.5.8",
"@tauri-apps/cli": "2.11.4",
"@types/culori": "^4.0.1",
"@types/node": "^25.9.5",
"@types/opentype.js": "^1.3.10",
"@types/ws": "^8.18.1",
"@typescript-eslint/utils": "^8.67.0",
"@typescript/native-preview": "^7.0.0-dev.20260707.2",
"@vitejs/plugin-vue": "^6.0.8",
"@vue/compiler-core": "^3.5.41",
"@wdio/cli": "9.30.1",
"@wdio/globals": "9.29.1",
"@wdio/local-runner": "9.30.1",
"@wdio/mocha-framework": "9.30.1",
"@wdio/spec-reporter": "9.30.1",
"@wdio/tauri-service": "1.3.0",
"changelog-parser": "^4.1.0",
"cloudflare-redirect-parser": "^1.0.0",
"esbuild": "^0.27.7",
"eslint-plugin-compat": "^7.0.2",
"expect-webdriverio": "5.7.0",
"fake-indexeddb": "^6.2.5",
"franc": "^6.2.0",
"hono": "^4.13.2",
"jscpd": "^4.3.0",
"knip": "6.20.0",
"mdast": "^3.0.0",
"mdast-util-from-markdown": "^2.0.3",
"mitata": "^1.0.34",
"oxfmt": "^0.67.0",
"oxlint": "1.57.0",
"oxlint-tsgolint": "^0.16.0",
"portless": "0.15.5",
"publint": "0.3.20",
"sherif": "1.12.0",
"steiger": "^0.5.13",
"storybook": "^10.5.8",
"tsdown": "^0.22.14",
"tw-animate-css": "^1.4.0",
"typescript": "~5.8.3",
"unist-util-visit": "^5.1.0",
"unplugin-icons": "^23.0.1",
"unplugin-raw": "^0.7.0",
"unplugin-vue": "^7.2.0",
"unplugin-vue-components": "^31.1.0",
"vite": "8.1.4",
"vite-plugin-pwa": "^1.3.0",
"vue-tsc": "^3.3.10",
"webmcp-types": "^0.1.7",
"workbox-window": "^7.4.1",
"ws": "^8.21.3"
},
"overrides": {
"@codemirror/view": "6.43.9",
"protobufjs": "7.5.5",
"websocket-driver": "0.7.5"
},
"packageManager": "bun@1.4.2"
}