@overcrow/mcp 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +90 -2
- package/dist/audit/index.js +103 -0
- package/dist/audit/lexer.js +417 -0
- package/dist/audit/project.js +200 -0
- package/dist/audit/rules.js +661 -0
- package/dist/bootstrap/download.js +229 -0
- package/dist/bootstrap/install.js +280 -0
- package/dist/bootstrap/pin.js +85 -0
- package/dist/bootstrap/pin.json +119 -0
- package/dist/bootstrap/zip.js +258 -0
- package/dist/cli.js +200 -0
- package/dist/confine.js +244 -0
- package/dist/content/docs/en/cli.md +353 -0
- package/dist/content/docs/en/dev-channel.md +130 -0
- package/dist/content/docs/en/elements.md +469 -0
- package/dist/content/docs/en/forms.md +328 -0
- package/dist/content/docs/en/guide.md +253 -0
- package/dist/content/docs/en/index.md +85 -0
- package/dist/content/docs/en/limits.md +241 -0
- package/dist/content/docs/en/logic.md +446 -0
- package/dist/content/docs/en/manifest.md +381 -0
- package/dist/content/docs/en/mcp.md +165 -0
- package/dist/content/docs/en/package.md +131 -0
- package/dist/content/docs/en/publishing.md +162 -0
- package/dist/content/docs/en/reference.md +55 -0
- package/dist/content/docs/en/result-shapes.md +332 -0
- package/dist/content/docs/en/sdk.md +295 -0
- package/dist/content/docs/en/security.md +115 -0
- package/dist/content/docs/en/service-reference.md +344 -0
- package/dist/content/docs/en/services.md +517 -0
- package/dist/content/docs/en/style-properties.md +270 -0
- package/dist/content/docs/en/style.md +266 -0
- package/dist/content/docs/en/testing.md +400 -0
- package/dist/content/docs/en/view.md +338 -0
- package/dist/content/docs/en/widgets.md +76 -0
- package/dist/content/docs/fr/cli.md +367 -0
- package/dist/content/docs/fr/dev-channel.md +140 -0
- package/dist/content/docs/fr/elements.md +475 -0
- package/dist/content/docs/fr/forms.md +341 -0
- package/dist/content/docs/fr/guide.md +264 -0
- package/dist/content/docs/fr/index.md +90 -0
- package/dist/content/docs/fr/limits.md +244 -0
- package/dist/content/docs/fr/logic.md +461 -0
- package/dist/content/docs/fr/manifest.md +392 -0
- package/dist/content/docs/fr/mcp.md +173 -0
- package/dist/content/docs/fr/package.md +139 -0
- package/dist/content/docs/fr/publishing.md +172 -0
- package/dist/content/docs/fr/reference.md +59 -0
- package/dist/content/docs/fr/result-shapes.md +333 -0
- package/dist/content/docs/fr/sdk.md +301 -0
- package/dist/content/docs/fr/security.md +129 -0
- package/dist/content/docs/fr/service-reference.md +346 -0
- package/dist/content/docs/fr/services.md +540 -0
- package/dist/content/docs/fr/style-properties.md +272 -0
- package/dist/content/docs/fr/style.md +281 -0
- package/dist/content/docs/fr/testing.md +417 -0
- package/dist/content/docs/fr/view.md +352 -0
- package/dist/content/docs/fr/widgets.md +81 -0
- package/dist/content/examples/clock/LICENSE +21 -0
- package/dist/content/examples/clock/README.md +75 -0
- package/dist/content/examples/clock/listing.json +19 -0
- package/dist/content/examples/clock/locales/en.json +4 -0
- package/dist/content/examples/clock/locales/fr.json +4 -0
- package/dist/content/examples/clock/logic.ts +85 -0
- package/dist/content/examples/clock/manifest.json +44 -0
- package/dist/content/examples/clock/package.json +16 -0
- package/dist/content/examples/clock/style.ocss +26 -0
- package/dist/content/examples/clock/tests/hidden.scenario.json +68 -0
- package/dist/content/examples/clock/tests/load-logic.mjs +22 -0
- package/dist/content/examples/clock/tests/logic.test.mjs +89 -0
- package/dist/content/examples/clock/tests/options.scenario.json +108 -0
- package/dist/content/examples/clock/tests/preview.scenario.json +25 -0
- package/dist/content/examples/clock/tests/render.scenario.json +94 -0
- package/dist/content/examples/clock/tests/summer-time.scenario.json +74 -0
- package/dist/content/examples/clock/tests/ticks.scenario.json +120 -0
- package/dist/content/examples/clock/tsconfig.json +16 -0
- package/dist/content/examples/clock/view.ocml +8 -0
- package/dist/content/examples/countdown/LICENSE +20 -0
- package/dist/content/examples/countdown/listing.json +10 -0
- package/dist/content/examples/countdown/locales/en.json +15 -0
- package/dist/content/examples/countdown/locales/fr.json +15 -0
- package/dist/content/examples/countdown/logic.ts +179 -0
- package/dist/content/examples/countdown/manifest.json +34 -0
- package/dist/content/examples/countdown/package.json +15 -0
- package/dist/content/examples/countdown/style.ocss +94 -0
- package/dist/content/examples/countdown/tsconfig.json +16 -0
- package/dist/content/examples/countdown/view.ocml +42 -0
- package/dist/content/examples/fps/LICENSE +21 -0
- package/dist/content/examples/fps/README.md +64 -0
- package/dist/content/examples/fps/listing.json +19 -0
- package/dist/content/examples/fps/locales/en.json +11 -0
- package/dist/content/examples/fps/locales/fr.json +11 -0
- package/dist/content/examples/fps/logic.ts +64 -0
- package/dist/content/examples/fps/manifest.json +30 -0
- package/dist/content/examples/fps/package.json +16 -0
- package/dist/content/examples/fps/style.ocss +31 -0
- package/dist/content/examples/fps/tests/label.scenario.json +63 -0
- package/dist/content/examples/fps/tests/load-logic.mjs +22 -0
- package/dist/content/examples/fps/tests/logic.test.mjs +60 -0
- package/dist/content/examples/fps/tests/preview.scenario.json +29 -0
- package/dist/content/examples/fps/tests/refused.scenario.json +20 -0
- package/dist/content/examples/fps/tests/render.scenario.json +96 -0
- package/dist/content/examples/fps/tests/stale.scenario.json +91 -0
- package/dist/content/examples/fps/tests/unavailable.scenario.json +111 -0
- package/dist/content/examples/fps/tsconfig.json +16 -0
- package/dist/content/examples/fps/view.ocml +11 -0
- package/dist/content/examples/media/LICENSE +21 -0
- package/dist/content/examples/media/README.md +147 -0
- package/dist/content/examples/media/listing.json +19 -0
- package/dist/content/examples/media/locales/en.json +11 -0
- package/dist/content/examples/media/locales/fr.json +11 -0
- package/dist/content/examples/media/logic.ts +191 -0
- package/dist/content/examples/media/manifest.json +35 -0
- package/dist/content/examples/media/package.json +16 -0
- package/dist/content/examples/media/style.ocss +148 -0
- package/dist/content/examples/media/tests/covers.scenario.json +144 -0
- package/dist/content/examples/media/tests/gesture.scenario.json +173 -0
- package/dist/content/examples/media/tests/load-logic.mjs +22 -0
- package/dist/content/examples/media/tests/logic.test.mjs +176 -0
- package/dist/content/examples/media/tests/marquee.scenario.json +127 -0
- package/dist/content/examples/media/tests/preview.scenario.json +52 -0
- package/dist/content/examples/media/tests/read-only.scenario.json +53 -0
- package/dist/content/examples/media/tests/refused.scenario.json +22 -0
- package/dist/content/examples/media/tests/refused.test.mjs +31 -0
- package/dist/content/examples/media/tests/render.scenario.json +136 -0
- package/dist/content/examples/media/tests/states.scenario.json +257 -0
- package/dist/content/examples/media/tests/unavailable.scenario.json +120 -0
- package/dist/content/examples/media/tsconfig.json +16 -0
- package/dist/content/examples/media/view.ocml +41 -0
- package/dist/content/examples/notes/LICENSE +21 -0
- package/dist/content/examples/notes/README.md +219 -0
- package/dist/content/examples/notes/listing.json +19 -0
- package/dist/content/examples/notes/locales/en.json +25 -0
- package/dist/content/examples/notes/locales/fr.json +25 -0
- package/dist/content/examples/notes/logic.ts +799 -0
- package/dist/content/examples/notes/manifest.json +40 -0
- package/dist/content/examples/notes/package.json +16 -0
- package/dist/content/examples/notes/style.ocss +469 -0
- package/dist/content/examples/notes/tests/checks.scenario.json +237 -0
- package/dist/content/examples/notes/tests/create.scenario.json +260 -0
- package/dist/content/examples/notes/tests/delete.scenario.json +342 -0
- package/dist/content/examples/notes/tests/drafts.scenario.json +714 -0
- package/dist/content/examples/notes/tests/editor.scenario.json +232 -0
- package/dist/content/examples/notes/tests/frame.scenario.json +93 -0
- package/dist/content/examples/notes/tests/interactive.scenario.json +344 -0
- package/dist/content/examples/notes/tests/limits.scenario.json +1351 -0
- package/dist/content/examples/notes/tests/load-logic.mjs +22 -0
- package/dist/content/examples/notes/tests/logic.test.mjs +514 -0
- package/dist/content/examples/notes/tests/preview.scenario.json +99 -0
- package/dist/content/examples/notes/tests/read-only.scenario.json +105 -0
- package/dist/content/examples/notes/tests/refused.scenario.json +33 -0
- package/dist/content/examples/notes/tests/save.scenario.json +378 -0
- package/dist/content/examples/notes/tests/states.scenario.json +640 -0
- package/dist/content/examples/notes/tests/typing.scenario.json +562 -0
- package/dist/content/examples/notes/tests/unavailable.scenario.json +246 -0
- package/dist/content/examples/notes/tsconfig.json +16 -0
- package/dist/content/examples/notes/view.ocml +154 -0
- package/dist/content/examples/performance/LICENSE +21 -0
- package/dist/content/examples/performance/README.md +134 -0
- package/dist/content/examples/performance/listing.json +19 -0
- package/dist/content/examples/performance/locales/en.json +20 -0
- package/dist/content/examples/performance/locales/fr.json +20 -0
- package/dist/content/examples/performance/logic.ts +210 -0
- package/dist/content/examples/performance/manifest.json +83 -0
- package/dist/content/examples/performance/package.json +16 -0
- package/dist/content/examples/performance/style.ocss +75 -0
- package/dist/content/examples/performance/tests/fahrenheit.scenario.json +110 -0
- package/dist/content/examples/performance/tests/horizontal.scenario.json +96 -0
- package/dist/content/examples/performance/tests/load-logic.mjs +22 -0
- package/dist/content/examples/performance/tests/logic.test.mjs +226 -0
- package/dist/content/examples/performance/tests/menu.scenario.json +170 -0
- package/dist/content/examples/performance/tests/no-fps-source.scenario.json +47 -0
- package/dist/content/examples/performance/tests/preview.scenario.json +45 -0
- package/dist/content/examples/performance/tests/refused.scenario.json +20 -0
- package/dist/content/examples/performance/tests/refused.test.mjs +19 -0
- package/dist/content/examples/performance/tests/region.scenario.json +89 -0
- package/dist/content/examples/performance/tests/render.scenario.json +112 -0
- package/dist/content/examples/performance/tests/sources.scenario.json +151 -0
- package/dist/content/examples/performance/tests/stale.scenario.json +111 -0
- package/dist/content/examples/performance/tests/telemetry-only.scenario.json +44 -0
- package/dist/content/examples/performance/tests/thresholds.scenario.json +147 -0
- package/dist/content/examples/performance/tests/waiting.scenario.json +105 -0
- package/dist/content/examples/performance/tsconfig.json +16 -0
- package/dist/content/examples/performance/view.ocml +18 -0
- package/dist/content/examples/playervox-journal/LICENSE +21 -0
- package/dist/content/examples/playervox-journal/README.md +150 -0
- package/dist/content/examples/playervox-journal/listing.json +19 -0
- package/dist/content/examples/playervox-journal/locales/en.json +25 -0
- package/dist/content/examples/playervox-journal/locales/fr.json +25 -0
- package/dist/content/examples/playervox-journal/logic.ts +556 -0
- package/dist/content/examples/playervox-journal/manifest.json +19 -0
- package/dist/content/examples/playervox-journal/package.json +16 -0
- package/dist/content/examples/playervox-journal/style.ocss +142 -0
- package/dist/content/examples/playervox-journal/tests/changes.scenario.json +482 -0
- package/dist/content/examples/playervox-journal/tests/delete.scenario.json +432 -0
- package/dist/content/examples/playervox-journal/tests/frame.scenario.json +169 -0
- package/dist/content/examples/playervox-journal/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-journal/tests/logic.test.mjs +349 -0
- package/dist/content/examples/playervox-journal/tests/paging.scenario.json +428 -0
- package/dist/content/examples/playervox-journal/tests/preview.scenario.json +184 -0
- package/dist/content/examples/playervox-journal/tests/read-only.scenario.json +157 -0
- package/dist/content/examples/playervox-journal/tests/refused.scenario.json +39 -0
- package/dist/content/examples/playervox-journal/tests/scale.scenario.json +286 -0
- package/dist/content/examples/playervox-journal/tests/signed-out.scenario.json +134 -0
- package/dist/content/examples/playervox-journal/tests/states.scenario.json +741 -0
- package/dist/content/examples/playervox-journal/tests/unavailable.scenario.json +183 -0
- package/dist/content/examples/playervox-journal/tsconfig.json +16 -0
- package/dist/content/examples/playervox-journal/view.ocml +52 -0
- package/dist/content/examples/playervox-rating/LICENSE +21 -0
- package/dist/content/examples/playervox-rating/README.md +166 -0
- package/dist/content/examples/playervox-rating/listing.json +19 -0
- package/dist/content/examples/playervox-rating/locales/en.json +35 -0
- package/dist/content/examples/playervox-rating/locales/fr.json +35 -0
- package/dist/content/examples/playervox-rating/logic.ts +581 -0
- package/dist/content/examples/playervox-rating/manifest.json +19 -0
- package/dist/content/examples/playervox-rating/package.json +16 -0
- package/dist/content/examples/playervox-rating/style.ocss +333 -0
- package/dist/content/examples/playervox-rating/tests/account.scenario.json +125 -0
- package/dist/content/examples/playervox-rating/tests/bounds.scenario.json +73 -0
- package/dist/content/examples/playervox-rating/tests/draft.scenario.json +199 -0
- package/dist/content/examples/playervox-rating/tests/form.scenario.json +142 -0
- package/dist/content/examples/playervox-rating/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-rating/tests/logic.test.mjs +346 -0
- package/dist/content/examples/playervox-rating/tests/offline.scenario.json +142 -0
- package/dist/content/examples/playervox-rating/tests/preview.scenario.json +44 -0
- package/dist/content/examples/playervox-rating/tests/publish-keyboard.scenario.json +221 -0
- package/dist/content/examples/playervox-rating/tests/publish-pointer.scenario.json +314 -0
- package/dist/content/examples/playervox-rating/tests/read-only.scenario.json +70 -0
- package/dist/content/examples/playervox-rating/tests/refused.scenario.json +45 -0
- package/dist/content/examples/playervox-rating/tests/states.scenario.json +362 -0
- package/dist/content/examples/playervox-rating/tsconfig.json +16 -0
- package/dist/content/examples/playervox-rating/view.ocml +62 -0
- package/dist/content/examples/playervox-reviews/LICENSE +21 -0
- package/dist/content/examples/playervox-reviews/README.md +194 -0
- package/dist/content/examples/playervox-reviews/listing.json +19 -0
- package/dist/content/examples/playervox-reviews/locales/en.json +32 -0
- package/dist/content/examples/playervox-reviews/locales/fr.json +32 -0
- package/dist/content/examples/playervox-reviews/logic.ts +822 -0
- package/dist/content/examples/playervox-reviews/manifest.json +30 -0
- package/dist/content/examples/playervox-reviews/package.json +16 -0
- package/dist/content/examples/playervox-reviews/style.ocss +260 -0
- package/dist/content/examples/playervox-reviews/tests/account.scenario.json +249 -0
- package/dist/content/examples/playervox-reviews/tests/bounds.scenario.json +336 -0
- package/dist/content/examples/playervox-reviews/tests/changes.scenario.json +515 -0
- package/dist/content/examples/playervox-reviews/tests/filter.scenario.json +400 -0
- package/dist/content/examples/playervox-reviews/tests/frame.scenario.json +185 -0
- package/dist/content/examples/playervox-reviews/tests/keyboard.scenario.json +188 -0
- package/dist/content/examples/playervox-reviews/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-reviews/tests/logic.test.mjs +559 -0
- package/dist/content/examples/playervox-reviews/tests/offline-start.scenario.json +152 -0
- package/dist/content/examples/playervox-reviews/tests/offline.scenario.json +311 -0
- package/dist/content/examples/playervox-reviews/tests/paging.scenario.json +497 -0
- package/dist/content/examples/playervox-reviews/tests/preview.scenario.json +286 -0
- package/dist/content/examples/playervox-reviews/tests/reading.scenario.json +591 -0
- package/dist/content/examples/playervox-reviews/tests/refused.scenario.json +54 -0
- package/dist/content/examples/playervox-reviews/tests/scale.scenario.json +303 -0
- package/dist/content/examples/playervox-reviews/tests/states.scenario.json +700 -0
- package/dist/content/examples/playervox-reviews/tests/unavailable.scenario.json +192 -0
- package/dist/content/examples/playervox-reviews/tsconfig.json +16 -0
- package/dist/content/examples/playervox-reviews/view.ocml +110 -0
- package/dist/content/examples/playervox-score/LICENSE +21 -0
- package/dist/content/examples/playervox-score/README.md +131 -0
- package/dist/content/examples/playervox-score/listing.json +19 -0
- package/dist/content/examples/playervox-score/locales/en.json +23 -0
- package/dist/content/examples/playervox-score/locales/fr.json +23 -0
- package/dist/content/examples/playervox-score/logic.ts +430 -0
- package/dist/content/examples/playervox-score/manifest.json +47 -0
- package/dist/content/examples/playervox-score/package.json +16 -0
- package/dist/content/examples/playervox-score/style.ocss +247 -0
- package/dist/content/examples/playervox-score/tests/grades.scenario.json +279 -0
- package/dist/content/examples/playervox-score/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-score/tests/logic.test.mjs +229 -0
- package/dist/content/examples/playervox-score/tests/options.scenario.json +302 -0
- package/dist/content/examples/playervox-score/tests/preview.scenario.json +68 -0
- package/dist/content/examples/playervox-score/tests/pulse.scenario.json +157 -0
- package/dist/content/examples/playervox-score/tests/refused.scenario.json +21 -0
- package/dist/content/examples/playervox-score/tests/signed-out.scenario.json +46 -0
- package/dist/content/examples/playervox-score/tests/states.scenario.json +450 -0
- package/dist/content/examples/playervox-score/tests/unavailable.scenario.json +84 -0
- package/dist/content/examples/playervox-score/tsconfig.json +16 -0
- package/dist/content/examples/playervox-score/view.ocml +51 -0
- package/dist/content/examples/session/LICENSE +21 -0
- package/dist/content/examples/session/README.md +57 -0
- package/dist/content/examples/session/listing.json +19 -0
- package/dist/content/examples/session/locales/en.json +3 -0
- package/dist/content/examples/session/locales/fr.json +3 -0
- package/dist/content/examples/session/logic.ts +26 -0
- package/dist/content/examples/session/manifest.json +19 -0
- package/dist/content/examples/session/package.json +16 -0
- package/dist/content/examples/session/style.ocss +16 -0
- package/dist/content/examples/session/tests/hidden.scenario.json +45 -0
- package/dist/content/examples/session/tests/load-logic.mjs +22 -0
- package/dist/content/examples/session/tests/logic.test.mjs +37 -0
- package/dist/content/examples/session/tests/preview.scenario.json +28 -0
- package/dist/content/examples/session/tests/refused.scenario.json +20 -0
- package/dist/content/examples/session/tests/refused.test.mjs +16 -0
- package/dist/content/examples/session/tests/render.scenario.json +95 -0
- package/dist/content/examples/session/tests/ticks.scenario.json +139 -0
- package/dist/content/examples/session/tests/unknown.scenario.json +37 -0
- package/dist/content/examples/session/tsconfig.json +16 -0
- package/dist/content/examples/session/view.ocml +11 -0
- package/dist/content/examples/stopwatch/LICENSE +21 -0
- package/dist/content/examples/stopwatch/README.md +99 -0
- package/dist/content/examples/stopwatch/listing.json +19 -0
- package/dist/content/examples/stopwatch/locales/en.json +8 -0
- package/dist/content/examples/stopwatch/locales/fr.json +8 -0
- package/dist/content/examples/stopwatch/logic.ts +93 -0
- package/dist/content/examples/stopwatch/manifest.json +19 -0
- package/dist/content/examples/stopwatch/package.json +16 -0
- package/dist/content/examples/stopwatch/style.ocss +54 -0
- package/dist/content/examples/stopwatch/tests/errors.scenario.json +121 -0
- package/dist/content/examples/stopwatch/tests/gesture.scenario.json +154 -0
- package/dist/content/examples/stopwatch/tests/hidden.scenario.json +57 -0
- package/dist/content/examples/stopwatch/tests/hundredths.scenario.json +173 -0
- package/dist/content/examples/stopwatch/tests/load-logic.mjs +22 -0
- package/dist/content/examples/stopwatch/tests/logic.test.mjs +99 -0
- package/dist/content/examples/stopwatch/tests/preview.scenario.json +36 -0
- package/dist/content/examples/stopwatch/tests/read-only.scenario.json +42 -0
- package/dist/content/examples/stopwatch/tests/read-only.test.mjs +18 -0
- package/dist/content/examples/stopwatch/tests/refused.scenario.json +22 -0
- package/dist/content/examples/stopwatch/tests/refused.test.mjs +18 -0
- package/dist/content/examples/stopwatch/tests/render.scenario.json +105 -0
- package/dist/content/examples/stopwatch/tests/states.scenario.json +246 -0
- package/dist/content/examples/stopwatch/tests/unknown.scenario.json +40 -0
- package/dist/content/examples/stopwatch/tsconfig.json +16 -0
- package/dist/content/examples/stopwatch/view.ocml +29 -0
- package/dist/content/examples/twitch-chat/LICENSE +21 -0
- package/dist/content/examples/twitch-chat/README.md +283 -0
- package/dist/content/examples/twitch-chat/listing.json +19 -0
- package/dist/content/examples/twitch-chat/locales/en.json +52 -0
- package/dist/content/examples/twitch-chat/locales/fr.json +52 -0
- package/dist/content/examples/twitch-chat/logic.ts +887 -0
- package/dist/content/examples/twitch-chat/manifest.json +33 -0
- package/dist/content/examples/twitch-chat/package.json +16 -0
- package/dist/content/examples/twitch-chat/style.ocss +544 -0
- package/dist/content/examples/twitch-chat/tests/account.scenario.json +325 -0
- package/dist/content/examples/twitch-chat/tests/burst.scenario.json +1866 -0
- package/dist/content/examples/twitch-chat/tests/channel-refused.scenario.json +372 -0
- package/dist/content/examples/twitch-chat/tests/channel.scenario.json +480 -0
- package/dist/content/examples/twitch-chat/tests/draft.scenario.json +279 -0
- package/dist/content/examples/twitch-chat/tests/fade.scenario.json +269 -0
- package/dist/content/examples/twitch-chat/tests/failures.scenario.json +420 -0
- package/dist/content/examples/twitch-chat/tests/favorites.scenario.json +376 -0
- package/dist/content/examples/twitch-chat/tests/frame.scenario.json +152 -0
- package/dist/content/examples/twitch-chat/tests/lifetime.scenario.json +186 -0
- package/dist/content/examples/twitch-chat/tests/load-logic.mjs +22 -0
- package/dist/content/examples/twitch-chat/tests/logic.test.mjs +1053 -0
- package/dist/content/examples/twitch-chat/tests/passive.scenario.json +536 -0
- package/dist/content/examples/twitch-chat/tests/preview.scenario.json +147 -0
- package/dist/content/examples/twitch-chat/tests/read-only.scenario.json +202 -0
- package/dist/content/examples/twitch-chat/tests/read-only.test.mjs +63 -0
- package/dist/content/examples/twitch-chat/tests/refused.scenario.json +65 -0
- package/dist/content/examples/twitch-chat/tests/refused.test.mjs +43 -0
- package/dist/content/examples/twitch-chat/tests/render.scenario.json +347 -0
- package/dist/content/examples/twitch-chat/tests/reply.scenario.json +384 -0
- package/dist/content/examples/twitch-chat/tests/send-refused.scenario.json +383 -0
- package/dist/content/examples/twitch-chat/tests/send.scenario.json +300 -0
- package/dist/content/examples/twitch-chat/tests/states.scenario.json +455 -0
- package/dist/content/examples/twitch-chat/tests/unavailable.scenario.json +256 -0
- package/dist/content/examples/twitch-chat/tests/unread.scenario.json +997 -0
- package/dist/content/examples/twitch-chat/tsconfig.json +16 -0
- package/dist/content/examples/twitch-chat/view.ocml +141 -0
- package/dist/content/examples/warframe-market/LICENSE +21 -0
- package/dist/content/examples/warframe-market/README.md +176 -0
- package/dist/content/examples/warframe-market/listing.json +19 -0
- package/dist/content/examples/warframe-market/locales/en.json +44 -0
- package/dist/content/examples/warframe-market/locales/fr.json +44 -0
- package/dist/content/examples/warframe-market/logic.ts +1265 -0
- package/dist/content/examples/warframe-market/manifest.json +92 -0
- package/dist/content/examples/warframe-market/package.json +16 -0
- package/dist/content/examples/warframe-market/style.ocss +422 -0
- package/dist/content/examples/warframe-market/tests/bounds.scenario.json +60 -0
- package/dist/content/examples/warframe-market/tests/cached.scenario.json +70 -0
- package/dist/content/examples/warframe-market/tests/detail.scenario.json +251 -0
- package/dist/content/examples/warframe-market/tests/errors.scenario.json +105 -0
- package/dist/content/examples/warframe-market/tests/fixtures.json +295 -0
- package/dist/content/examples/warframe-market/tests/load-logic.mjs +22 -0
- package/dist/content/examples/warframe-market/tests/logic.test.mjs +505 -0
- package/dist/content/examples/warframe-market/tests/no-clipboard.scenario.json +104 -0
- package/dist/content/examples/warframe-market/tests/passive.scenario.json +87 -0
- package/dist/content/examples/warframe-market/tests/preview.scenario.json +146 -0
- package/dist/content/examples/warframe-market/tests/refresh.scenario.json +56 -0
- package/dist/content/examples/warframe-market/tests/refused.scenario.json +74 -0
- package/dist/content/examples/warframe-market/tests/render.scenario.json +210 -0
- package/dist/content/examples/warframe-market/tests/search.scenario.json +189 -0
- package/dist/content/examples/warframe-market/tests/unavailable.scenario.json +54 -0
- package/dist/content/examples/warframe-market/tsconfig.json +16 -0
- package/dist/content/examples/warframe-market/view.ocml +116 -0
- package/dist/content/examples/weather/LICENSE +20 -0
- package/dist/content/examples/weather/listing.json +10 -0
- package/dist/content/examples/weather/locales/en.json +9 -0
- package/dist/content/examples/weather/locales/fr.json +9 -0
- package/dist/content/examples/weather/logic.ts +62 -0
- package/dist/content/examples/weather/manifest.json +51 -0
- package/dist/content/examples/weather/package.json +15 -0
- package/dist/content/examples/weather/style.ocss +29 -0
- package/dist/content/examples/weather/tsconfig.json +16 -0
- package/dist/content/examples/weather/view.ocml +12 -0
- package/dist/content/index.json +3601 -0
- package/dist/content/reference/errors.json +1712 -0
- package/dist/content/reference/limits.json +1154 -0
- package/dist/content/reference/manifest.md +223 -0
- package/dist/content/reference/permissions.json +413 -0
- package/dist/content/templates/blank/locales/en.json +3 -0
- package/dist/content/templates/blank/locales/fr.json +3 -0
- package/dist/content/templates/blank/logic.ts +7 -0
- package/dist/content/templates/blank/manifest.json +16 -0
- package/dist/content/templates/blank/style.ocss +10 -0
- package/dist/content/templates/blank/tests/example.scenario.json +10 -0
- package/dist/content/templates/blank/view.ocml +6 -0
- package/dist/content/templates/chart/locales/en.json +3 -0
- package/dist/content/templates/chart/locales/fr.json +3 -0
- package/dist/content/templates/chart/logic.ts +27 -0
- package/dist/content/templates/chart/manifest.json +16 -0
- package/dist/content/templates/chart/style.ocss +27 -0
- package/dist/content/templates/chart/tests/example.scenario.json +10 -0
- package/dist/content/templates/chart/view.ocml +10 -0
- package/dist/content/templates/counter/locales/en.json +4 -0
- package/dist/content/templates/counter/locales/fr.json +4 -0
- package/dist/content/templates/counter/logic.ts +20 -0
- package/dist/content/templates/counter/manifest.json +16 -0
- package/dist/content/templates/counter/style.ocss +26 -0
- package/dist/content/templates/counter/tests/example.scenario.json +11 -0
- package/dist/content/templates/counter/view.ocml +13 -0
- package/dist/content/templates/list/locales/en.json +8 -0
- package/dist/content/templates/list/locales/fr.json +8 -0
- package/dist/content/templates/list/logic.ts +35 -0
- package/dist/content/templates/list/manifest.json +16 -0
- package/dist/content/templates/list/style.ocss +42 -0
- package/dist/content/templates/list/tests/example.scenario.json +10 -0
- package/dist/content/templates/list/view.ocml +17 -0
- package/dist/content/templates/shared/LICENSE +20 -0
- package/dist/content/templates/shared/package.json +14 -0
- package/dist/content/templates/shared/tsconfig.json +16 -0
- package/dist/content.js +68 -0
- package/dist/env.js +156 -0
- package/dist/fingerprint.js +32 -0
- package/dist/ids.js +27 -0
- package/dist/index.js +82 -0
- package/dist/knowledge.js +222 -0
- package/dist/npm.js +149 -0
- package/dist/prompts.js +47 -0
- package/dist/resources.js +82 -0
- package/dist/run.js +120 -0
- package/dist/server.js +43 -0
- package/dist/session.js +205 -0
- package/dist/sources.js +218 -0
- package/dist/text.js +80 -0
- package/dist/texts.js +44 -0
- package/dist/tools/audit.js +105 -0
- package/dist/tools/build.js +453 -0
- package/dist/tools/common.js +122 -0
- package/dist/tools/docs.js +196 -0
- package/dist/tools/preview.js +87 -0
- package/dist/tools/project.js +178 -0
- package/dist/tools/setup.js +146 -0
- package/dist/tools/submission.js +369 -0
- package/dist/version.js +3 -0
- package/npm-shrinkwrap.json +402 -0
- package/package.json +52 -4
package/dist/confine.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// Where the server may act: the roots (folders given with --root, or the
|
|
2
|
+
// client's roots, or the working directory) and the paths inside them.
|
|
3
|
+
// Every path is resolved through its real location: a link that leads out
|
|
4
|
+
// of a root is refused like any outside path. System folders, a disk's root
|
|
5
|
+
// and the home folder itself are never roots; hidden folders and
|
|
6
|
+
// node_modules inside a root are never targets.
|
|
7
|
+
import { lstat, realpath } from "node:fs/promises";
|
|
8
|
+
import { basename, dirname, isAbsolute, join, parse, relative, resolve, sep } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { homeDirectory, windowsSystemDirectories } from "./env.js";
|
|
11
|
+
export class ConfinementError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "ConfinementError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const WINDOWS = process.platform === "win32";
|
|
18
|
+
const POSIX_SYSTEM = [
|
|
19
|
+
"/bin",
|
|
20
|
+
"/boot",
|
|
21
|
+
"/dev",
|
|
22
|
+
"/etc",
|
|
23
|
+
"/lib",
|
|
24
|
+
"/lib32",
|
|
25
|
+
"/lib64",
|
|
26
|
+
"/libx32",
|
|
27
|
+
"/proc",
|
|
28
|
+
"/run",
|
|
29
|
+
"/sbin",
|
|
30
|
+
"/snap",
|
|
31
|
+
"/srv",
|
|
32
|
+
"/sys",
|
|
33
|
+
"/usr",
|
|
34
|
+
"/var/cache",
|
|
35
|
+
"/var/lib",
|
|
36
|
+
"/var/log",
|
|
37
|
+
"/System",
|
|
38
|
+
"/Library",
|
|
39
|
+
"/Applications",
|
|
40
|
+
"/private/etc",
|
|
41
|
+
"/private/var/db",
|
|
42
|
+
];
|
|
43
|
+
const POSIX_EXACT = [
|
|
44
|
+
"/tmp",
|
|
45
|
+
"/var",
|
|
46
|
+
"/var/tmp",
|
|
47
|
+
"/home",
|
|
48
|
+
"/Users",
|
|
49
|
+
"/opt",
|
|
50
|
+
"/mnt",
|
|
51
|
+
"/media",
|
|
52
|
+
"/private",
|
|
53
|
+
"/root",
|
|
54
|
+
];
|
|
55
|
+
function samePath(a, b) {
|
|
56
|
+
return WINDOWS ? a.toLowerCase() === b.toLowerCase() : a === b;
|
|
57
|
+
}
|
|
58
|
+
/** True when `child` is `parent` or inside it. */
|
|
59
|
+
export function isInside(parent, child) {
|
|
60
|
+
const path = relative(parent, child);
|
|
61
|
+
if (path === "")
|
|
62
|
+
return true;
|
|
63
|
+
return !path.startsWith(`..${sep}`) && path !== ".." && !isAbsolute(path);
|
|
64
|
+
}
|
|
65
|
+
async function realOrSelf(path) {
|
|
66
|
+
try {
|
|
67
|
+
return await realpath(path);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return path;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** Why `path` (a real path) cannot be a root, or undefined when it can. */
|
|
74
|
+
export async function rootRefusal(path) {
|
|
75
|
+
if (samePath(parse(path).root, path))
|
|
76
|
+
return "it is the root of a disk";
|
|
77
|
+
const home = await realOrSelf(homeDirectory());
|
|
78
|
+
if (samePath(home, path))
|
|
79
|
+
return "it is your whole home folder";
|
|
80
|
+
if (WINDOWS) {
|
|
81
|
+
if (samePath(dirname(home), path))
|
|
82
|
+
return "it is the folder of every user";
|
|
83
|
+
for (const system of windowsSystemDirectories()) {
|
|
84
|
+
const real = await realOrSelf(system);
|
|
85
|
+
if (isInside(real, path) || isInside(system, path))
|
|
86
|
+
return "it is a system folder";
|
|
87
|
+
}
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
if (isInside(home, path))
|
|
91
|
+
return undefined;
|
|
92
|
+
if (POSIX_EXACT.some((system) => samePath(system, path)))
|
|
93
|
+
return "it is a system folder";
|
|
94
|
+
if (POSIX_SYSTEM.some((system) => isInside(system, path)))
|
|
95
|
+
return "it is a system folder";
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
/** Checks a candidate root and returns its real path. */
|
|
99
|
+
export async function checkRoot(candidate) {
|
|
100
|
+
const absolute = resolve(candidate);
|
|
101
|
+
let real;
|
|
102
|
+
try {
|
|
103
|
+
real = await realpath(absolute);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
throw new ConfinementError(`The folder ${candidate} does not exist.`);
|
|
107
|
+
}
|
|
108
|
+
if (!(await lstat(real)).isDirectory())
|
|
109
|
+
throw new ConfinementError(`${candidate} is not a folder.`);
|
|
110
|
+
const refusal = await rootRefusal(real);
|
|
111
|
+
if (refusal) {
|
|
112
|
+
throw new ConfinementError(`The server cannot work in ${real}: ${refusal}. Open a project folder, or start the server with --root <your widgets folder>.`);
|
|
113
|
+
}
|
|
114
|
+
return real;
|
|
115
|
+
}
|
|
116
|
+
/** The local path of a client root (`file://` URIs only). */
|
|
117
|
+
export function rootUriToPath(uri) {
|
|
118
|
+
try {
|
|
119
|
+
const url = new URL(uri);
|
|
120
|
+
return url.protocol === "file:" ? fileURLToPath(url) : undefined;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** Labels the roots: `.` when there is one, else each folder's name. */
|
|
127
|
+
export function labelRoots(paths) {
|
|
128
|
+
if (paths.length === 1)
|
|
129
|
+
return [{ path: paths[0], label: "." }];
|
|
130
|
+
const seen = new Map();
|
|
131
|
+
return paths.map((path) => {
|
|
132
|
+
const name = basename(path) || path;
|
|
133
|
+
const count = (seen.get(name) ?? 0) + 1;
|
|
134
|
+
seen.set(name, count);
|
|
135
|
+
return { path, label: count === 1 ? name : `${name}-${count}` };
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
// biome-ignore lint/suspicious/noControlCharactersInRegex: the point is to refuse them
|
|
139
|
+
const UNSAFE_INPUT = /[\u0000-\u001f\u007f]/;
|
|
140
|
+
/** Paths inside the roots. */
|
|
141
|
+
export class Confinement {
|
|
142
|
+
roots;
|
|
143
|
+
constructor(roots) {
|
|
144
|
+
this.roots = roots;
|
|
145
|
+
}
|
|
146
|
+
/** The path as results show it: relative to its root, with `/`. */
|
|
147
|
+
display(path) {
|
|
148
|
+
for (const root of this.roots) {
|
|
149
|
+
if (isInside(root.path, path)) {
|
|
150
|
+
const inside = relative(root.path, path).split(sep).join("/");
|
|
151
|
+
if (root.label === ".")
|
|
152
|
+
return inside === "" ? "." : inside;
|
|
153
|
+
return inside === "" ? root.label : `${root.label}/${inside}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return "<outside the project>";
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Resolves `input` (relative to the first root, or absolute inside a
|
|
160
|
+
* root) to a real path inside a root, and checks what it must be.
|
|
161
|
+
*/
|
|
162
|
+
async resolve(input, target) {
|
|
163
|
+
if (this.roots.length === 0)
|
|
164
|
+
throw new ConfinementError("No project folder is open.");
|
|
165
|
+
if (input.length === 0 || input.length > 1024 || UNSAFE_INPUT.test(input)) {
|
|
166
|
+
throw new ConfinementError("The path is empty, too long, or holds control characters.");
|
|
167
|
+
}
|
|
168
|
+
if (WINDOWS && (/^[\\/]{2}/.test(input) || /:/.test(input.replace(/^[A-Za-z]:/, "")))) {
|
|
169
|
+
throw new ConfinementError("Network paths, device paths and alternate streams are refused.");
|
|
170
|
+
}
|
|
171
|
+
const first = this.roots[0];
|
|
172
|
+
const absolute = isAbsolute(input) ? resolve(input) : resolve(first.path, input);
|
|
173
|
+
// Labelled roots: `<label>/rest` names a path in that root.
|
|
174
|
+
const labelled = this.labelledPath(input);
|
|
175
|
+
const wanted = labelled ?? absolute;
|
|
176
|
+
const real = await this.realLocation(wanted);
|
|
177
|
+
const root = this.roots.find((candidate) => isInside(candidate.path, real));
|
|
178
|
+
if (!root) {
|
|
179
|
+
throw new ConfinementError(`${input} is outside the project folders the server may use (${this.roots.map((r) => r.label).join(", ")}).`);
|
|
180
|
+
}
|
|
181
|
+
const inside = relative(root.path, real);
|
|
182
|
+
const parts = inside === "" ? [] : inside.split(sep);
|
|
183
|
+
for (const part of parts) {
|
|
184
|
+
if (part.startsWith("."))
|
|
185
|
+
throw new ConfinementError("Hidden folders and files are refused.");
|
|
186
|
+
if (part === "node_modules")
|
|
187
|
+
throw new ConfinementError("node_modules is refused.");
|
|
188
|
+
if (WINDOWS && /[. ]$/.test(part))
|
|
189
|
+
throw new ConfinementError("A name ending with a dot or a space is refused.");
|
|
190
|
+
}
|
|
191
|
+
await this.checkTarget(real, target, root, input);
|
|
192
|
+
return real;
|
|
193
|
+
}
|
|
194
|
+
labelledPath(input) {
|
|
195
|
+
if (this.roots.length < 2 || isAbsolute(input))
|
|
196
|
+
return undefined;
|
|
197
|
+
const [head, ...rest] = input.split(/[\\/]/);
|
|
198
|
+
const root = this.roots.find((candidate) => candidate.label === head);
|
|
199
|
+
return root ? resolve(root.path, ...rest) : undefined;
|
|
200
|
+
}
|
|
201
|
+
/** The real path of `path`, or of its deepest existing parent plus the rest. */
|
|
202
|
+
async realLocation(path) {
|
|
203
|
+
const missing = [];
|
|
204
|
+
let current = path;
|
|
205
|
+
for (;;) {
|
|
206
|
+
try {
|
|
207
|
+
const real = await realpath(current);
|
|
208
|
+
return missing.length === 0 ? real : join(real, ...missing.reverse());
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
const code = error.code;
|
|
212
|
+
if (code !== "ENOENT" && code !== "ENOTDIR")
|
|
213
|
+
throw new ConfinementError(`${path} cannot be read.`);
|
|
214
|
+
const parent = dirname(current);
|
|
215
|
+
if (parent === current)
|
|
216
|
+
throw new ConfinementError(`${path} cannot be resolved.`);
|
|
217
|
+
missing.push(basename(current));
|
|
218
|
+
current = parent;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
async checkTarget(real, target, root, input) {
|
|
223
|
+
let info;
|
|
224
|
+
try {
|
|
225
|
+
info = await lstat(real);
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
info = undefined;
|
|
229
|
+
}
|
|
230
|
+
if (target === "new-directory") {
|
|
231
|
+
if (samePath(real, root.path))
|
|
232
|
+
throw new ConfinementError("Create the widget in a new folder inside the project.");
|
|
233
|
+
if (info && !info.isDirectory())
|
|
234
|
+
throw new ConfinementError(`${input} exists and is not a folder.`);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
if (!info)
|
|
238
|
+
throw new ConfinementError(`${input} does not exist.`);
|
|
239
|
+
if (target === "directory" && !info.isDirectory())
|
|
240
|
+
throw new ConfinementError(`${input} is not a folder.`);
|
|
241
|
+
if (target === "file" && !info.isFile())
|
|
242
|
+
throw new ConfinementError(`${input} is not a file.`);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# The command-line tool
|
|
2
|
+
|
|
3
|
+
`overcrow-widget` creates, checks and packages PlayerVox OverCrow widgets,
|
|
4
|
+
runs them in OverCrow while you write them, and tests them. It is one
|
|
5
|
+
program for Linux and Windows, and it contains the same validators that
|
|
6
|
+
OverCrow runs when it installs and starts a widget: a package it accepts is
|
|
7
|
+
a package OverCrow reads.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
overcrow-widget init my-widget --template counter
|
|
11
|
+
cd my-widget
|
|
12
|
+
overcrow-widget check
|
|
13
|
+
overcrow-widget package
|
|
14
|
+
overcrow-widget inspect dist/com.example.my-widget-0.1.0.ocpkg
|
|
15
|
+
overcrow-widget doctor
|
|
16
|
+
overcrow-widget dev
|
|
17
|
+
overcrow-widget test
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
| Command | Does |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| [`init`](#init) | Creates a project from a template. |
|
|
23
|
+
| [`check`](#check) | Validates a project without writing anything. |
|
|
24
|
+
| [`package`](#package) | Checks, then writes the `.ocpkg` package. |
|
|
25
|
+
| [`inspect`](#inspect) | Shows what a package holds and asks for. |
|
|
26
|
+
| [`dev`](#dev) | Runs the widget in OverCrow and reloads it when you save. |
|
|
27
|
+
| [`test`](#test) | Plays the project's test scenarios and compares their images. |
|
|
28
|
+
| [`doctor`](#doctor) | Says what your setup has and lacks. |
|
|
29
|
+
| [`admit`](#admit) | Runs the admission of the marketplace on your submission. |
|
|
30
|
+
|
|
31
|
+
Every command takes the project directory as its argument and uses the
|
|
32
|
+
current directory without one.
|
|
33
|
+
|
|
34
|
+
## Installing
|
|
35
|
+
|
|
36
|
+
Each [OverCrow release](https://github.com/Valhallab/playervox-overcrow-releases/releases)
|
|
37
|
+
carries the creator tools in one ZIP per platform: the tool with its
|
|
38
|
+
license and third-party notices, OverCrow's headless runtime that
|
|
39
|
+
[`test`](#test) uses, a `README.txt` and a `SHA256SUMS` of every file.
|
|
40
|
+
|
|
41
|
+
| Platform | ZIP | Tool in the ZIP |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| Linux x86-64 | `overcrow-creator-tools-VERSION-linux-x86_64.zip` | `overcrow-widget-VERSION-linux-x86_64` |
|
|
44
|
+
| Windows x64 | `overcrow-creator-tools-VERSION-windows-x86_64.zip` | `overcrow-widget-VERSION-windows-x86_64.exe` |
|
|
45
|
+
|
|
46
|
+
Unzip it, check the files, rename the tool `overcrow-widget`
|
|
47
|
+
(`overcrow-widget.exe` on Windows), make it executable on Linux
|
|
48
|
+
(`chmod +x`) and put it on your `PATH`. It needs nothing else to check and
|
|
49
|
+
package a widget. `overcrow-widget --version` gives its version and the SDK
|
|
50
|
+
it embeds.
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
unzip overcrow-creator-tools-VERSION-linux-x86_64.zip
|
|
54
|
+
cd overcrow-creator-tools-VERSION-linux-x86_64
|
|
55
|
+
sha256sum --check SHA256SUMS
|
|
56
|
+
install -m 755 overcrow-widget-*-linux-x86_64 ~/.local/bin/overcrow-widget
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The tool also builds from the
|
|
60
|
+
[public repository](https://github.com/Valhallab/playervox-overcrow-releases)
|
|
61
|
+
with Rust; the repository pins the toolchain it needs. The program is then
|
|
62
|
+
`target/dist/overcrow-widget`.
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
cargo build -p overcrow-widget-cli --profile dist --locked
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### The SDK types
|
|
69
|
+
|
|
70
|
+
`check` type-checks your logic with the project's own TypeScript, when
|
|
71
|
+
Node.js 22 or later and `node_modules/typescript` are there; otherwise it
|
|
72
|
+
warns that types were not checked (`typecheck.skipped`) and goes on. The
|
|
73
|
+
SDK itself is inside the tool, so packaging never depends on
|
|
74
|
+
`node_modules`.
|
|
75
|
+
|
|
76
|
+
`@overcrow/sdk` is on [npm](https://www.npmjs.com/package/@overcrow/sdk).
|
|
77
|
+
The `package.json` of a project made by `init` names TypeScript and the SDK
|
|
78
|
+
version the tool embeds: run `npm install` in the project. In another
|
|
79
|
+
project, install the SDK with:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
npm install --save-dev --save-exact @overcrow/sdk@1.0.0
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Keep the version the tool embeds (`overcrow-widget --version`).
|
|
86
|
+
`overcrow-widget doctor` reports a missing TypeScript, and an SDK in
|
|
87
|
+
`node_modules` whose version differs from the one the tool embeds.
|
|
88
|
+
|
|
89
|
+
## Files of a project
|
|
90
|
+
|
|
91
|
+
| File | Role | Packaged |
|
|
92
|
+
| --- | --- | --- |
|
|
93
|
+
| `manifest.json` | [The manifest](manifest.md), packaged as written. | yes |
|
|
94
|
+
| `view.ocml` | [The view](view.md), compiled to `view.json`. | compiled |
|
|
95
|
+
| `style.ocss` | [The style](style.md); optional. | yes |
|
|
96
|
+
| `logic.ts` or `logic.js` | [The logic](logic.md), one module; bundled with the SDK into `logic.js`. | bundled |
|
|
97
|
+
| `locales/en.json`, `locales/fr.json` | [Messages](logic.md#messages); both or neither, with the same keys. | yes |
|
|
98
|
+
| `LICENSE` | The license text of the package. The templates start with MIT; choose your own. | yes |
|
|
99
|
+
| `assets/` | PNG, JPEG or WebP images; optional. | yes |
|
|
100
|
+
| `package.json`, `tsconfig.json` | Tooling only: TypeScript and the SDK types. | no |
|
|
101
|
+
| `listing.json` | The marketplace text of a [submission](publishing.md#the-listing); read by `admit`. | no |
|
|
102
|
+
| `tests/` | [Scenarios](testing.md#scenarios) (`tests/<name>.scenario.json`), their reference images (`tests/reference/`) and your unit tests. `tests/output/` holds the images of failed runs. | no |
|
|
103
|
+
|
|
104
|
+
## init
|
|
105
|
+
|
|
106
|
+
```sh
|
|
107
|
+
overcrow-widget init my-widget --template list --id com.example.my-widget --name "My widget"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Writes a new project into the directory, which must not exist or must be
|
|
111
|
+
empty: `init` never overwrites a file.
|
|
112
|
+
|
|
113
|
+
| Template | Shows |
|
|
114
|
+
| --- | --- |
|
|
115
|
+
| `blank` (default) | A title from the locales and an empty state. |
|
|
116
|
+
| `counter` | A value and two buttons whose handlers the logic exports. |
|
|
117
|
+
| `list` | A keyed checklist: `for`, handlers with arguments, `t()` with parameters. |
|
|
118
|
+
| `chart` | A live chart updated by a timer. |
|
|
119
|
+
|
|
120
|
+
The ID defaults to `com.example.<dir>`; pass `--id` with a reverse-DNS ID
|
|
121
|
+
under a domain you control (`com.playervox.*` is reserved). Every template
|
|
122
|
+
comes with a test scenario, `tests/example.scenario.json`, and `counter`,
|
|
123
|
+
`list` and `chart` with its reference images.
|
|
124
|
+
|
|
125
|
+
## check
|
|
126
|
+
|
|
127
|
+
```sh
|
|
128
|
+
overcrow-widget check
|
|
129
|
+
overcrow-widget check --deny-warnings --format json
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Runs every check, in this order, and writes nothing:
|
|
133
|
+
|
|
134
|
+
1. **Project files**: the required files are there and within their size
|
|
135
|
+
bounds, one logic module, both locale files or neither.
|
|
136
|
+
2. **Manifest**: OverCrow's own manifest validator.
|
|
137
|
+
3. **View**: `view.ocml` is compiled and the result validated; static
|
|
138
|
+
images must exist in `assets/`.
|
|
139
|
+
4. **Style**: `style.ocss` is parsed with OverCrow's parser.
|
|
140
|
+
5. **Locales**: objects of strings with valid keys, the same keys in both
|
|
141
|
+
files. A `t("key")` of the view whose key has no message is a warning.
|
|
142
|
+
6. **Logic**: the [lint](logic.md#what-the-logic-cannot-use), and the
|
|
143
|
+
exports the view calls.
|
|
144
|
+
7. **Types**: the project's `tsc --noEmit -p tsconfig.json`.
|
|
145
|
+
8. **Package**: `logic.js` is built, the package is written in memory and
|
|
146
|
+
read back exactly as OverCrow will read it.
|
|
147
|
+
|
|
148
|
+
Options: `--no-typecheck`, `--deny-warnings` (a warning fails the command),
|
|
149
|
+
`--format json`.
|
|
150
|
+
|
|
151
|
+
## package
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
overcrow-widget package
|
|
155
|
+
overcrow-widget package --out build/my-widget.ocpkg
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Runs `check`, then writes the package to `dist/<id>-<version>.ocpkg`, or to
|
|
159
|
+
`--out`. It prints the path, the size and the SHA-256 of the archive.
|
|
160
|
+
|
|
161
|
+
Packaging is deterministic: the same sources and the same version of the
|
|
162
|
+
tool give the same bytes on every run and every system. What the package
|
|
163
|
+
holds is described in [the package](package.md).
|
|
164
|
+
|
|
165
|
+
## inspect
|
|
166
|
+
|
|
167
|
+
```sh
|
|
168
|
+
overcrow-widget inspect dist/com.example.my-widget-0.1.0.ocpkg
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Validates a package as OverCrow does, then shows it as a reviewer sees it:
|
|
172
|
+
the ID, version and names; the size and SHA-256 of the archive; the SDK
|
|
173
|
+
version its `logic.js` contains; each permission in words (network routes
|
|
174
|
+
with their parameter constraints and declared response bound, storage,
|
|
175
|
+
clipboard, game events); each capability with its summary and whether it is
|
|
176
|
+
sensitive or needs an account; the number of menu rows; and every file with
|
|
177
|
+
its size and SHA-256. A package that OverCrow would refuse is reported
|
|
178
|
+
instead, with the reason.
|
|
179
|
+
|
|
180
|
+
## dev
|
|
181
|
+
|
|
182
|
+
```sh
|
|
183
|
+
overcrow-widget dev
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Runs the widget in the OverCrow overlay running on your machine, while you
|
|
187
|
+
edit it:
|
|
188
|
+
|
|
189
|
+
1. it connects to the overlay, which must have been started with
|
|
190
|
+
development installs allowed;
|
|
191
|
+
2. it builds the package as `package` does and sends it to the overlay,
|
|
192
|
+
which validates it in full and shows it marked
|
|
193
|
+
**Unverified · development package**, with the permissions of its
|
|
194
|
+
manifest granted for the session only;
|
|
195
|
+
3. it watches the project's files and, 200 ms after the last change,
|
|
196
|
+
rebuilds and reloads the widget. A build with errors is not sent: the
|
|
197
|
+
widget keeps running its last good build;
|
|
198
|
+
4. it prints what the overlay reports: the widget's states (`starting`,
|
|
199
|
+
`running`, `restarting` with the failure, `failed`…) and the `log.*`
|
|
200
|
+
output of its logic;
|
|
201
|
+
5. on **Ctrl+C**, it removes the widget from the overlay.
|
|
202
|
+
|
|
203
|
+
Options: `--no-typecheck`, `--format json` (one JSON object per line).
|
|
204
|
+
Exit status: 0 after Ctrl+C, 1 when the overlay ends the session, 2 when no
|
|
205
|
+
overlay is reachable. [The development channel](dev-channel.md) says how to
|
|
206
|
+
start OverCrow for it, and what each state and refusal means.
|
|
207
|
+
|
|
208
|
+
## test
|
|
209
|
+
|
|
210
|
+
```sh
|
|
211
|
+
overcrow-widget test
|
|
212
|
+
overcrow-widget test --scenario example
|
|
213
|
+
overcrow-widget test --update
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Plays the scenarios of `tests/` in OverCrow's headless runtime and compares
|
|
217
|
+
the images it renders with the references:
|
|
218
|
+
|
|
219
|
+
1. it builds the package as `package` does;
|
|
220
|
+
2. it reads every `tests/<name>.scenario.json` and checks it against the
|
|
221
|
+
manifest before anything runs; a mistake in a scenario is a
|
|
222
|
+
`test.scenario` diagnostic in its file;
|
|
223
|
+
3. it runs each scenario in the [headless runtime](testing.md#the-headless-runtime)
|
|
224
|
+
this tool pins, or the one given by `--runtime`, and prints the
|
|
225
|
+
runtime's version and SHA-256. The first time, it downloads the pinned
|
|
226
|
+
runtime;
|
|
227
|
+
4. it compares each captured image with
|
|
228
|
+
`tests/reference/<name>/<image>.png`. A difference, a size change or a
|
|
229
|
+
missing reference fails the scenario and writes
|
|
230
|
+
`tests/output/<name>/<image>.actual.png` and, for a difference,
|
|
231
|
+
`<image>.diff.png`.
|
|
232
|
+
|
|
233
|
+
Options: `--runtime <path>` (another `overcrow-widget-headless` program),
|
|
234
|
+
`--offline` (never download the runtime), `--scenario <name>` (only that one), `--update` (records the captured
|
|
235
|
+
images as the references: review them before you commit them),
|
|
236
|
+
`--format json`, `--no-typecheck`.
|
|
237
|
+
|
|
238
|
+
Exit status: 0 when every scenario passed, 1 when one failed, 2 when no
|
|
239
|
+
runtime can run. Scenarios are described in
|
|
240
|
+
[testing a widget](testing.md).
|
|
241
|
+
|
|
242
|
+
## doctor
|
|
243
|
+
|
|
244
|
+
```sh
|
|
245
|
+
overcrow-widget doctor
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
| Line | Checked |
|
|
249
|
+
| --- | --- |
|
|
250
|
+
| `cli`, `sdk` | The version of the tool, its widget API, and the `@overcrow/sdk` it embeds. |
|
|
251
|
+
| `platform` | Operating system and architecture. |
|
|
252
|
+
| `overcrow` | An installed OverCrow. |
|
|
253
|
+
| `development` | A running overlay that allows development installs, and its version. |
|
|
254
|
+
| `node`, `typescript`, `project sdk` | In a widget project: Node.js on `PATH`, `node_modules/typescript`, and the version of `node_modules/@overcrow/sdk`. |
|
|
255
|
+
|
|
256
|
+
| Code | Severity | Meaning |
|
|
257
|
+
| --- | --- | --- |
|
|
258
|
+
| `doctor.overcrow_missing` | warning | OverCrow is not installed. |
|
|
259
|
+
| `doctor.development_off` | warning | No overlay allows development installs; the help gives the commands to restart OverCrow with them. |
|
|
260
|
+
| `doctor.channel_busy` | warning | The overlay already serves its maximum of `dev` sessions. |
|
|
261
|
+
| `doctor.channel_io` | warning | The connection to the overlay failed. |
|
|
262
|
+
| `doctor.channel_untrusted` | error | What answers is not this user's overlay. |
|
|
263
|
+
| `doctor.protocol_version` | error | The overlay and the tool do not speak the same version of the development channel. |
|
|
264
|
+
| `doctor.node_missing`, `doctor.node_version` | warning | No Node.js, or older than 22: `check` cannot type-check. |
|
|
265
|
+
| `doctor.typescript_missing`, `doctor.sdk_missing` | warning | TypeScript or the SDK types are not installed in the project. |
|
|
266
|
+
| `doctor.sdk_version` | warning | `node_modules/@overcrow/sdk` differs from the SDK in the tool. |
|
|
267
|
+
|
|
268
|
+
Options: `--format json`, `--deny-warnings`.
|
|
269
|
+
|
|
270
|
+
## admit
|
|
271
|
+
|
|
272
|
+
```sh
|
|
273
|
+
overcrow-widget admit
|
|
274
|
+
overcrow-widget admit --package dist/com.example.my-widget-0.1.0.ocpkg
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Runs the static admission that a marketplace submission goes through,
|
|
278
|
+
exactly as the marketplace runs it. It never runs your code or `tsc`:
|
|
279
|
+
|
|
280
|
+
1. the directory is built as `package` builds it;
|
|
281
|
+
2. with `--package`, that archive's compiled view must be byte for byte
|
|
282
|
+
what `view.ocml` compiles to;
|
|
283
|
+
3. the ID is not reserved, `listing.json` is valid, its preview is a
|
|
284
|
+
packaged PNG of at most 256 KiB;
|
|
285
|
+
4. the authority the widget asks for is listed for the reviewer:
|
|
286
|
+
capabilities (the sensitive ones marked), network routes with their
|
|
287
|
+
response bound, clipboard writes, storage and game events.
|
|
288
|
+
|
|
289
|
+
| Code | Severity | Meaning |
|
|
290
|
+
| --- | --- | --- |
|
|
291
|
+
| `admission.reserved_id` | error | A `com.playervox.*` ID, reserved for PlayerVox. |
|
|
292
|
+
| `admission.listing_missing`, `admission.listing` | error | No `listing.json`, or one that breaks the listing's rules. |
|
|
293
|
+
| `admission.preview` | error | `preview` does not name a packaged PNG within bounds. |
|
|
294
|
+
| `admission.license` | error | A PlayerVox widget whose license is not MIT. |
|
|
295
|
+
| `admission.view_not_reproducible` | error | The submitted compiled view differs from what `view.ocml` compiles to. |
|
|
296
|
+
| `admission.package_rebuilt` | warning | The submitted archive differs from the rebuild in other files. |
|
|
297
|
+
| `admission.not_rebuilt` | warning | An archive was admitted without its sources. |
|
|
298
|
+
|
|
299
|
+
Options: `--package FILE`, `--out DIR` (writes the admitted package, its
|
|
300
|
+
listing and a report into an empty directory), `--format json`,
|
|
301
|
+
`--deny-warnings`. `admit <file.ocpkg> --listing FILE` checks an archive
|
|
302
|
+
without its sources. Exit status: 0 admitted, 1 refused, 2 on a usage or
|
|
303
|
+
file error. See [publishing and review](publishing.md).
|
|
304
|
+
|
|
305
|
+
## Diagnostics
|
|
306
|
+
|
|
307
|
+
Every problem is one diagnostic, with a stable code, a position and, when
|
|
308
|
+
there is one, a suggestion:
|
|
309
|
+
|
|
310
|
+
```text
|
|
311
|
+
error[view.unknown_attribute]: `clas` is not an attribute of <text>
|
|
312
|
+
--> view.ocml:4:9
|
|
313
|
+
|
|
|
314
|
+
4 | <text clas="value">{state.count}</text>
|
|
315
|
+
| ^
|
|
316
|
+
= help: did you mean `class`?
|
|
317
|
+
check: 1 error(s), 0 warning(s)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
The code is `<domain>.<category>`:
|
|
321
|
+
|
|
322
|
+
| Domain | From | Codes |
|
|
323
|
+
| --- | --- | --- |
|
|
324
|
+
| `project` | The files of the project | `missing_file`, `file_size`, `encoding`, `ambiguous_logic`, `asset_path`, `entry_limit`, `read` |
|
|
325
|
+
| `manifest` | `manifest.json` | see [the manifest](manifest.md#how-the-manifest-is-checked) |
|
|
326
|
+
| `view` | `view.ocml` | see [the view](view.md#when-the-view-is-wrong) |
|
|
327
|
+
| `style` | `style.ocss` | see [the style](style.md#when-the-style-is-wrong) |
|
|
328
|
+
| `locales` | `locales/*.json` | `missing_file`, `json`, `shape`, `key`, `value`, `keys`, `entry_limit`, `unknown_key` |
|
|
329
|
+
| `logic` | `logic.ts` | see [the logic](logic.md#what-the-logic-cannot-use) |
|
|
330
|
+
| `typecheck` | TypeScript | `tsc` (TypeScript's own message), `skipped`, `sdk_version`, `timeout` |
|
|
331
|
+
| `package` | The package read back | `archive_size`, `file_size` and the categories of OverCrow's package reader |
|
|
332
|
+
| `test` | Scenarios | `scenario`, `scenario_name`, `too_many_scenarios` |
|
|
333
|
+
| `init`, `doctor`, `admission` | Those commands | listed above |
|
|
334
|
+
|
|
335
|
+
- Lines and columns start at 1; a column counts characters, not bytes.
|
|
336
|
+
- An unknown name comes with the closest name that exists.
|
|
337
|
+
- With `--format json`, each diagnostic is one JSON object on a line of the
|
|
338
|
+
standard output:
|
|
339
|
+
`{"severity","code","file","line","column","message","help"}`, with
|
|
340
|
+
`null` for what is unknown. `package --format json` ends with one
|
|
341
|
+
`{"package","bytes","sha256","logicBytes"}` object.
|
|
342
|
+
- Texts that come from a widget (its logs, its names) are shown with
|
|
343
|
+
terminal control characters neutralized.
|
|
344
|
+
|
|
345
|
+
Scripts should match the codes: messages and help texts may be reworded.
|
|
346
|
+
|
|
347
|
+
## Exit status
|
|
348
|
+
|
|
349
|
+
| Status | Meaning |
|
|
350
|
+
| --- | --- |
|
|
351
|
+
| 0 | Success. Warnings are allowed unless `--deny-warnings`. |
|
|
352
|
+
| 1 | Errors were found; `admit` refused the submission; a scenario of `test` failed; the overlay ended a `dev` session. |
|
|
353
|
+
| 2 | A usage or file error; no overlay for `dev`; no runtime for `test`. |
|