@overcrow/mcp 0.0.0 → 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 +91 -1
- 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 +50 -4
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
# La logique
|
|
2
|
+
|
|
3
|
+
`logic.ts` est le code d’un widget PlayerVox OverCrow : il détient l’état du
|
|
4
|
+
widget, exporte les fonctions que la vue appelle et dialogue avec OverCrow
|
|
5
|
+
par `@overcrow/sdk`. C’est un seul module TypeScript (ou JavaScript),
|
|
6
|
+
assemblé avec le SDK dans l’unique script du paquet, `logic.js`.
|
|
7
|
+
|
|
8
|
+
<!-- source: templates/counter/logic.ts -->
|
|
9
|
+
```ts
|
|
10
|
+
// A counter. The view reads `state.count` and calls `increment` and
|
|
11
|
+
// `decrement` on activation; after each handler the VM renders the view
|
|
12
|
+
// again and sends only what changed.
|
|
13
|
+
import { initState } from "@overcrow/sdk";
|
|
14
|
+
|
|
15
|
+
declare module "@overcrow/sdk" {
|
|
16
|
+
interface WidgetState {
|
|
17
|
+
count: number;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const state = initState({ count: 0 });
|
|
22
|
+
|
|
23
|
+
export function increment(): void {
|
|
24
|
+
state.count += 1;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function decrement(): void {
|
|
28
|
+
state.count -= 1;
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Voilà un module de logique complet : un état à un seul membre, et deux
|
|
33
|
+
gestionnaires que la vue appelle avec `on:activate={increment}`.
|
|
34
|
+
|
|
35
|
+
## Comment la logique s’exécute
|
|
36
|
+
|
|
37
|
+
- Le module s’exécute une fois, au démarrage du widget, dans sa propre VM
|
|
38
|
+
JavaScript, à l’intérieur d’un processus placé dans un sandbox. Ce n’est
|
|
39
|
+
ni un navigateur ni Node.js : il n’y a ni DOM, ni `window`, ni `fetch`, ni
|
|
40
|
+
`setTimeout`, ni `console`, ni `Intl`, ni `require`. Les objets standard
|
|
41
|
+
d’ECMAScript sont là (`Math`, `JSON`, `Date`, `Map`, `Promise`…), et le
|
|
42
|
+
SDK est la seule porte de sortie.
|
|
43
|
+
- Tout le reste se passe par **tours**. OverCrow envoie un événement, un
|
|
44
|
+
déclenchement de minuteur, une réponse de service ou un changement de ses
|
|
45
|
+
propres données ; votre code s’exécute ; puis la VM réévalue la vue et
|
|
46
|
+
n’envoie à OverCrow que ce qui a changé. Vous ne mettez jamais la vue à
|
|
47
|
+
jour à la main.
|
|
48
|
+
- Un tour a un budget de temps, et la VM un plafond de mémoire. OverCrow
|
|
49
|
+
arrête et relance, quelques fois, un widget qui dépasse l’un ou l’autre ;
|
|
50
|
+
voir [ce qui se passe en cas d’échec](#ce-qui-se-passe-en-cas-déchec).
|
|
51
|
+
|
|
52
|
+
Le seul import permis à un module de logique est `@overcrow/sdk`. Tout ce
|
|
53
|
+
dont il a besoin par ailleurs se trouve dans le module lui-même.
|
|
54
|
+
|
|
55
|
+
## L’état
|
|
56
|
+
|
|
57
|
+
`state` est un objet ordinaire. Déclarez une fois le type de ses membres en
|
|
58
|
+
étendant l’interface `WidgetState` du SDK, donnez-lui sa première valeur
|
|
59
|
+
avec `initState`, puis modifiez-le par simple affectation.
|
|
60
|
+
|
|
61
|
+
<!-- source: templates/list/logic.ts -->
|
|
62
|
+
```ts
|
|
63
|
+
interface Item {
|
|
64
|
+
id: number;
|
|
65
|
+
text: string;
|
|
66
|
+
done: boolean;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
declare module "@overcrow/sdk" {
|
|
70
|
+
interface WidgetState {
|
|
71
|
+
items: Item[];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const state = initState({
|
|
76
|
+
items: [
|
|
77
|
+
{ id: 1, text: t("first"), done: false },
|
|
78
|
+
{ id: 2, text: t("second"), done: false },
|
|
79
|
+
{ id: 3, text: t("third"), done: true },
|
|
80
|
+
] as Item[],
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Après chaque tour, la VM réévalue toute la vue et envoie les différences. Il
|
|
85
|
+
n’y a ni abonnement à prendre ni setter à appeler : modifier un membre en
|
|
86
|
+
place ou le remplacer, les deux fonctionnent.
|
|
87
|
+
|
|
88
|
+
<!-- source: templates/list/logic.ts -->
|
|
89
|
+
```ts
|
|
90
|
+
export function setDone(id: number, done: unknown): void {
|
|
91
|
+
state.items = state.items.map((item) => (item.id === id ? { ...item, done: done === true } : item));
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Gardez dans l’état ce que la vue affiche, et dans des variables ordinaires
|
|
96
|
+
ce qui ne sert qu’à la logique (un minuteur, un abonnement). Une valeur de
|
|
97
|
+
l’état doit être une donnée simple : nombres, chaînes, booléens, `null`, et
|
|
98
|
+
tableaux ou objets qui en sont composés.
|
|
99
|
+
|
|
100
|
+
## Des fonctions pour la vue
|
|
101
|
+
|
|
102
|
+
La vue ne peut appeler que ce que le module de logique exporte par son nom :
|
|
103
|
+
|
|
104
|
+
- dans une **expression**, une fonction qui renvoie ce qu’il faut afficher :
|
|
105
|
+
`{remaining(state.items)}` ;
|
|
106
|
+
- comme **gestionnaire**, une fonction qui modifie l’état :
|
|
107
|
+
`on:activate={remove(item.id)}`.
|
|
108
|
+
|
|
109
|
+
<!-- source: templates/list/logic.ts -->
|
|
110
|
+
```ts
|
|
111
|
+
export function remove(id: number): void {
|
|
112
|
+
state.items = state.items.filter((item) => item.id !== id);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
<!-- source: templates/list/logic.ts -->
|
|
117
|
+
```ts
|
|
118
|
+
export function remaining(items: readonly Item[]): number {
|
|
119
|
+
return items.filter((item) => !item.done).length;
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Les fonctions d’expression s’exécutent à chaque évaluation de la vue :
|
|
124
|
+
gardez-les légères et sans effet de bord. Un gestionnaire nommé sans
|
|
125
|
+
arguments (`on:change={setRepeat}`) reçoit le détail de l’événement :
|
|
126
|
+
|
|
127
|
+
<!-- source: docs/content/examples/countdown/logic.ts -->
|
|
128
|
+
```ts
|
|
129
|
+
export function setRepeat(event: { value: unknown }): void {
|
|
130
|
+
state.repeat = event.value === true;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`export default` est refusé : la vue appelle des exports nommés. `t` n’a pas
|
|
135
|
+
besoin d’être exporté : une vue qui appelle `t(…)` obtient celui du SDK,
|
|
136
|
+
sauf si la logique exporte le sien.
|
|
137
|
+
|
|
138
|
+
## Les données d’OverCrow : `host`
|
|
139
|
+
|
|
140
|
+
`host` contient ce qu’OverCrow sait de l’utilisateur et du widget. Ses
|
|
141
|
+
membres donnent toujours la dernière valeur.
|
|
142
|
+
|
|
143
|
+
| Membre | Valeur |
|
|
144
|
+
| --- | --- |
|
|
145
|
+
| `host.locale` | Langue de l’interface, `"en"` ou `"fr"`. |
|
|
146
|
+
| `host.theme` | `"dark"` ou `"light"`. |
|
|
147
|
+
| `host.mode` | `"passive"` ou `"interactive"` : le widget ne reçoit d’entrées qu’en mode interactif. |
|
|
148
|
+
| `host.visible` | Indique si le widget est affiché. |
|
|
149
|
+
| `host.scale` | Échelle du contenu en millièmes : `1000` vaut 100 %. |
|
|
150
|
+
| `host.viewport` | `{ width, height }` du contenu du widget, en pixels logiques. |
|
|
151
|
+
| `host.region` | Les formats régionaux et le décalage UTC de l’utilisateur ; les fonctions de formatage les lisent. |
|
|
152
|
+
| `host.options` | Les valeurs du menu d’options ; lisez-les avec `option`. |
|
|
153
|
+
| `host.grants` | Les capabilities accordées par l’utilisateur ; lisez-les avec `hasGrant`. |
|
|
154
|
+
| `host.messages` | Les messages de la langue active ; lisez-les avec `t`. |
|
|
155
|
+
|
|
156
|
+
`onHost(listener)` appelle votre écouteur quand OverCrow envoie de nouvelles
|
|
157
|
+
valeurs, avec les noms des membres qui ont changé, avant la réévaluation de
|
|
158
|
+
la vue. Utilisez-le quand un changement demande plus que l’affichage de la
|
|
159
|
+
nouvelle valeur : réarmer un minuteur, se réabonner, redessiner un canvas.
|
|
160
|
+
Un membre peut être renvoyé avec la même valeur : comparez-la à celle que
|
|
161
|
+
vous avez gardée quand cela compte.
|
|
162
|
+
|
|
163
|
+
<!-- source: widgets/stopwatch/logic.ts -->
|
|
164
|
+
```ts
|
|
165
|
+
onHost((changed) => {
|
|
166
|
+
if (changed.includes("mode")) {
|
|
167
|
+
state.interactive = host.mode === "interactive";
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
La plupart des widgets n’affichent que les boutons utilisables : en mode
|
|
173
|
+
passif, un clic traverse le widget jusqu’au jeu. Le chronomètre masque donc
|
|
174
|
+
ses boutons tant que `host.mode` ne vaut pas `"interactive"`.
|
|
175
|
+
|
|
176
|
+
## Le menu d’options
|
|
177
|
+
|
|
178
|
+
OverCrow dessine et enregistre les lignes déclarées dans `wrapper.menu` du
|
|
179
|
+
[manifeste](manifest.md#le-menu-doptions). La logique les lit :
|
|
180
|
+
|
|
181
|
+
- `option(id, fallback)` renvoie la valeur enregistrée d’une ligne de type
|
|
182
|
+
bascule, curseur ou choix, ou `fallback` quand il n’y en a pas ou qu’elle
|
|
183
|
+
est d’un autre type ;
|
|
184
|
+
- `onHost` signale `"options"` quand l’utilisateur modifie une ligne ;
|
|
185
|
+
- `onMenu(handler)` reçoit l’identifiant d’une ligne `action` quand
|
|
186
|
+
l’utilisateur la choisit.
|
|
187
|
+
|
|
188
|
+
<!-- source: widgets/clock/logic.ts -->
|
|
189
|
+
```ts
|
|
190
|
+
export function menuValues(): { seconds: boolean; showDate: boolean; order: DateOrder } {
|
|
191
|
+
return {
|
|
192
|
+
seconds: option("show-seconds", false),
|
|
193
|
+
showDate: option("show-date", true),
|
|
194
|
+
order: DATE_ORDERS[option("date-format", "day-month-year")] ?? "dmy",
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
<!-- source: docs/content/examples/countdown/logic.ts -->
|
|
200
|
+
```ts
|
|
201
|
+
onMenu((row) => {
|
|
202
|
+
if (row === "reset-rounds") {
|
|
203
|
+
resetRounds();
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Choisir une ligne du menu n’est pas une
|
|
209
|
+
[action de l’utilisateur](services.md#les-appels-qui-demandent-une-action-de-lutilisateur)
|
|
210
|
+
pour un service protégé : une ligne `action` peut modifier l’état, pas
|
|
211
|
+
écrire dans le presse-papiers.
|
|
212
|
+
|
|
213
|
+
## Minuteurs
|
|
214
|
+
|
|
215
|
+
Il n’y a pas de `setTimeout`. Les minuteurs appartiennent à OverCrow et
|
|
216
|
+
passent par `timers` :
|
|
217
|
+
|
|
218
|
+
| Fonction | Se déclenche |
|
|
219
|
+
| --- | --- |
|
|
220
|
+
| `timers.after(ms, callback)` | une fois, après `ms` |
|
|
221
|
+
| `timers.every(ms, callback)` | toutes les `ms` |
|
|
222
|
+
| `timers.atEach(unit, callback)` | à chaque `"second"`, `"minute"`, `"hour"` ou `"day"` de l’heure locale de l’utilisateur |
|
|
223
|
+
|
|
224
|
+
Chacune renvoie un `Timer` doté de `cancel()`.
|
|
225
|
+
|
|
226
|
+
<!-- source: templates/chart/logic.ts -->
|
|
227
|
+
```ts
|
|
228
|
+
timers.every(1000, () => {
|
|
229
|
+
const previous = state.values.at(-1) ?? 50;
|
|
230
|
+
state.values = [...state.values.slice(1 - POINTS), sample(previous)];
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Puisque les minuteurs appartiennent à OverCrow, trois règles s’appliquent :
|
|
235
|
+
|
|
236
|
+
- **Aucun minuteur de moins de 100 ms.** Un intervalle plus court est porté
|
|
237
|
+
à cette valeur. Le mouvement relève du
|
|
238
|
+
[style](style.md#transitions-et-animations), pas des minuteurs.
|
|
239
|
+
- **Rien ne se déclenche dans un widget masqué.** Un minuteur répétitif
|
|
240
|
+
saute les déclenchements tombés pendant que le widget était masqué ; un
|
|
241
|
+
minuteur à usage unique arrivé à échéance pendant ce temps se déclenche
|
|
242
|
+
une fois quand le widget réapparaît. Calculez le temps écoulé à partir de
|
|
243
|
+
`Date.now()`, jamais en comptant les déclenchements :
|
|
244
|
+
|
|
245
|
+
<!-- source: docs/content/examples/countdown/logic.ts -->
|
|
246
|
+
```ts
|
|
247
|
+
// A timer does not tick while the widget is hidden: the time left comes
|
|
248
|
+
// from the clock, not from the number of ticks.
|
|
249
|
+
function tick(): void {
|
|
250
|
+
state.remainingMs = Math.max(0, endsAt - Date.now());
|
|
251
|
+
if (state.remainingMs > 0) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
stop();
|
|
255
|
+
setRounds(state.rounds + 1);
|
|
256
|
+
log.info(`round ${state.rounds} finished`);
|
|
257
|
+
if (state.repeat) {
|
|
258
|
+
start();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
- **16 minuteurs au plus** à la fois.
|
|
264
|
+
|
|
265
|
+
Pour une horloge, `timers.atEach` est le bon outil : un seul minuteur
|
|
266
|
+
répétitif, calé sur les changements d’unité de l’heure locale, qui se
|
|
267
|
+
réveille aussi quand le décalage UTC change (heure d’été) et une fois quand
|
|
268
|
+
le widget réapparaît.
|
|
269
|
+
|
|
270
|
+
<!-- source: widgets/clock/logic.ts -->
|
|
271
|
+
```ts
|
|
272
|
+
/** Ticks at each second or minute of local time, and shows the time now. */
|
|
273
|
+
function start(): void {
|
|
274
|
+
clock?.cancel();
|
|
275
|
+
clock = timers.atEach(state.seconds ? "second" : "minute", tick);
|
|
276
|
+
tick();
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Une durée qui doit seulement avancer à l’écran n’a besoin d’aucun minuteur :
|
|
281
|
+
OverCrow fait avancer l’élément `elapsed` à partir d’un point de départ que
|
|
282
|
+
la logique lui donne. Voir l’[élément `elapsed`](elements.md#elapsed).
|
|
283
|
+
|
|
284
|
+
## Heure, dates et nombres
|
|
285
|
+
|
|
286
|
+
Dans la VM, l’heure locale est UTC : `Date` ne donne jamais l’heure de
|
|
287
|
+
l’utilisateur, et il n’y a pas d’`Intl`. C’est le SDK qui formate, à partir
|
|
288
|
+
de `host.region` :
|
|
289
|
+
|
|
290
|
+
| Fonction | Donne |
|
|
291
|
+
| --- | --- |
|
|
292
|
+
| `formatTime(ms, { seconds })` | `14:08`, ou `14:08:42` : sur 24 heures, dans le fuseau horaire de l’utilisateur |
|
|
293
|
+
| `formatDate(ms, { order })` | `17/07/2026`, `07/17/2026` ou `2026-07-17`, par défaut dans l’ordre de date de l’utilisateur |
|
|
294
|
+
| `formatNumber(value, options)` | `1,234.5`, `1 234,5` ou `1.234,5` : les séparateurs de l’utilisateur, quelle que soit la langue de l’interface |
|
|
295
|
+
| `formatDuration(ms, options)` | `04:05`, `1:02:03`, ou `04:05.67` avec les centièmes |
|
|
296
|
+
| `localTime(ms)` | les champs de l’instant dans le fuseau horaire de l’utilisateur : `year`, `month`, `day`, `weekday`, `hour`… |
|
|
297
|
+
|
|
298
|
+
<!-- source: widgets/clock/logic.ts -->
|
|
299
|
+
```ts
|
|
300
|
+
export function clockTime(now: number, seconds: boolean): string {
|
|
301
|
+
return formatTime(now, { seconds });
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
<!-- source: templates/chart/logic.ts -->
|
|
306
|
+
```ts
|
|
307
|
+
export function latest(values: readonly number[]): string {
|
|
308
|
+
const last = values.at(-1);
|
|
309
|
+
return last === undefined ? "" : formatNumber(last, { maximumFractionDigits: 0 });
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Un horodatage qui vient d’un service porte son propre `offsetMinutes` :
|
|
314
|
+
passez-le à la fonction (`formatTime(at, { offsetMinutes })`) pour qu’une
|
|
315
|
+
session enregistrée dans un autre fuseau horaire affiche l’heure qu’il y
|
|
316
|
+
était. Les noms de mois et de jours de la semaine et l’affichage sur
|
|
317
|
+
12 heures ne sont pas fournis.
|
|
318
|
+
|
|
319
|
+
## Messages
|
|
320
|
+
|
|
321
|
+
Placez les textes du widget dans `locales/en.json` et `locales/fr.json` :
|
|
322
|
+
deux objets plats de chaînes, aux mêmes clés. Les deux fichiers, ou aucun.
|
|
323
|
+
|
|
324
|
+
<!-- source: templates/list/locales/en.json -->
|
|
325
|
+
```json
|
|
326
|
+
{
|
|
327
|
+
"first": "Warm up",
|
|
328
|
+
"remaining": "{count} left",
|
|
329
|
+
"remove": "Remove",
|
|
330
|
+
"second": "Play three matches",
|
|
331
|
+
"third": "Update the drivers",
|
|
332
|
+
"title": "Today"
|
|
333
|
+
}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
`t(key, params)` renvoie le message dans la langue de l’utilisateur et
|
|
337
|
+
remplace chaque `{name}` par `params.name` ; une clé absente donne la clé
|
|
338
|
+
elle-même. La fonction s’utilise dans la vue comme dans la logique :
|
|
339
|
+
|
|
340
|
+
<!-- source: templates/list/view.ocml -->
|
|
341
|
+
```xml
|
|
342
|
+
<text class="summary">{t("remaining", { count: remaining(state.items) })}</text>
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
<!-- source: widgets/stopwatch/logic.ts -->
|
|
346
|
+
```ts
|
|
347
|
+
export function toggleLabel(running: boolean): string {
|
|
348
|
+
return t(running ? "pause" : "start");
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Quand l’utilisateur change la langue d’OverCrow, la vue est réévaluée avec
|
|
353
|
+
les nouveaux messages. En revanche, un texte que la logique a calculé puis
|
|
354
|
+
rangé dans l’état ne change pas : calculez les textes dans des fonctions que
|
|
355
|
+
la vue appelle, ou rafraîchissez-les dans `onHost` quand `"locale"` change.
|
|
356
|
+
Le nom du widget et les libellés de son menu se trouvent dans le manifeste,
|
|
357
|
+
pas dans les fichiers de langue.
|
|
358
|
+
|
|
359
|
+
`overcrow-widget check` avertit quand la vue appelle `t("key")` avec une clé
|
|
360
|
+
sans message, et refuse deux fichiers dont les clés diffèrent.
|
|
361
|
+
|
|
362
|
+
## Dessin
|
|
363
|
+
|
|
364
|
+
Pour ce que les éléments ne savent pas afficher, l’élément `canvas` offre
|
|
365
|
+
une surface que la logique peint avec une liste de commandes : chemins,
|
|
366
|
+
remplissages, contours, texte et images. `draw(ref, commands)` remplace tout
|
|
367
|
+
le contenu du canvas nommé `ref`.
|
|
368
|
+
|
|
369
|
+
<!-- source: docs/content/examples/countdown/logic.ts -->
|
|
370
|
+
```ts
|
|
371
|
+
/** One dot per finished round, on the `dots` canvas. */
|
|
372
|
+
function paint(): void {
|
|
373
|
+
const dots: DrawCommand[] = [];
|
|
374
|
+
for (let index = 0; index < Math.min(state.rounds, MAX_DOTS); index += 1) {
|
|
375
|
+
dots.push(["circle", 6 + index * 14, 6, 4], ["fill", "var(--color-accent)"]);
|
|
376
|
+
}
|
|
377
|
+
draw("dots", dots);
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Les coordonnées sont en pixels logiques, depuis le coin supérieur gauche du
|
|
382
|
+
canvas ; les couleurs sont des littéraux (`#rrggbb`) ou des tokens de
|
|
383
|
+
couleur. OverCrow vérifie chaque commande et les dessine lui-même : il n’y a
|
|
384
|
+
ni accès aux pixels ni shader. Redessinez quand ce que vous affichez change,
|
|
385
|
+
et quand `host.theme` change si vous utilisez des couleurs littérales.
|
|
386
|
+
|
|
387
|
+
<!-- generated:draw-commands -->
|
|
388
|
+
| Commande | Arguments | Signification |
|
|
389
|
+
| --- | --- | --- |
|
|
390
|
+
| `moveTo` | `x` : nombre de -16384 à 16384 ; `y` : nombre de -16384 à 16384 | Commence un sous-chemin. |
|
|
391
|
+
| `lineTo` | `x` : nombre de -16384 à 16384 ; `y` : nombre de -16384 à 16384 | Segment de droite. |
|
|
392
|
+
| `quadTo` | `cx` : nombre de -16384 à 16384 ; `cy` : nombre de -16384 à 16384 ; `x` : nombre de -16384 à 16384 ; `y` : nombre de -16384 à 16384 | Segment de Bézier quadratique. |
|
|
393
|
+
| `cubicTo` | `c1x` : nombre de -16384 à 16384 ; `c1y` : nombre de -16384 à 16384 ; `c2x` : nombre de -16384 à 16384 ; `c2y` : nombre de -16384 à 16384 ; `x` : nombre de -16384 à 16384 ; `y` : nombre de -16384 à 16384 | Segment de Bézier cubique. |
|
|
394
|
+
| `arc` | `cx` : nombre de -16384 à 16384 ; `cy` : nombre de -16384 à 16384 ; `r` : nombre de -16384 à 16384 ; `start` : nombre de -720 à 720 ; `end` : nombre de -720 à 720 | Arc de cercle, en degrés, dans le sens horaire. |
|
|
395
|
+
| `rect` | `x` : nombre de -16384 à 16384 ; `y` : nombre de -16384 à 16384 ; `w` : nombre de -16384 à 16384 ; `h` : nombre de -16384 à 16384 ; `radius` : nombre de -16384 à 16384 | Sous-chemin fermé : un rectangle aux coins arrondis. |
|
|
396
|
+
| `circle` | `cx` : nombre de -16384 à 16384 ; `cy` : nombre de -16384 à 16384 ; `r` : nombre de -16384 à 16384 | Sous-chemin fermé : un cercle. |
|
|
397
|
+
| `close` | aucune | Ferme le sous-chemin. |
|
|
398
|
+
| `fill` | `color` : `<color>` | Remplit le chemin courant, puis l’efface. |
|
|
399
|
+
| `stroke` | `color` : `<color>` ; `width` : nombre de 0 à 256 | Trace le contour du chemin courant, puis l’efface. |
|
|
400
|
+
| `text` | `x` : nombre de -16384 à 16384 ; `y` : nombre de -16384 à 16384 ; `text` : texte ≤ 1 Kio ; `size` : nombre de 6 à 96 ; `color` : `<color>` ; `align` : `start` \| `center` \| `end` ; `family` : `ui` \| `mono` \| `display` ; `weight` : `400` \| `500` \| `600` \| `700` | Une ligne de texte, posée sur sa ligne de base. |
|
|
401
|
+
| `image` | `src` : source d’image ; `x` : nombre de -16384 à 16384 ; `y` : nombre de -16384 à 16384 ; `w` : nombre de -16384 à 16384 ; `h` : nombre de -16384 à 16384 | Dessine une image mise à l’échelle du rectangle. |
|
|
402
|
+
| `save` | aucune | Empile la transformation, le rognage et l’opacité, ≤ 16. |
|
|
403
|
+
| `restore` | aucune | Dépile l’état ; un `restore` sans `save` est une erreur. |
|
|
404
|
+
| `clip` | `x` : nombre de -16384 à 16384 ; `y` : nombre de -16384 à 16384 ; `w` : nombre de -16384 à 16384 ; `h` : nombre de -16384 à 16384 | Réduit le rectangle de rognage à son intersection avec celui-ci. |
|
|
405
|
+
| `translate` | `x` : nombre de -16384 à 16384 ; `y` : nombre de -16384 à 16384 | Translation. |
|
|
406
|
+
| `rotate` | `degrees` : nombre de -360 à 360 | Rotation. |
|
|
407
|
+
| `scale` | `x` : nombre de 0 à 8 ; `y` : nombre de 0 à 8 | Mise à l’échelle. |
|
|
408
|
+
| `alpha` | `value` : nombre de 0 à 1 | Multiplie l’opacité. |
|
|
409
|
+
<!-- /generated:draw-commands -->
|
|
410
|
+
|
|
411
|
+
Un graphique, une jauge ou une barre de progression n’ont pas besoin de
|
|
412
|
+
canvas : les éléments `chart`, `gauge` et `progress` les dessinent à partir
|
|
413
|
+
de valeurs.
|
|
414
|
+
|
|
415
|
+
## Journalisation
|
|
416
|
+
|
|
417
|
+
`log.debug`, `log.info`, `log.warn` et `log.error` prennent un texte. Leur
|
|
418
|
+
sortie apparaît dans le terminal de `overcrow-widget dev` et nulle part
|
|
419
|
+
ailleurs : les journaux d’un widget installé sont ignorés. Ne journalisez
|
|
420
|
+
jamais de données de l’utilisateur.
|
|
421
|
+
|
|
422
|
+
<!-- source: docs/content/examples/countdown/logic.ts -->
|
|
423
|
+
```ts
|
|
424
|
+
log.info(`round ${state.rounds} finished`);
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
## Ce que la logique ne peut pas utiliser
|
|
428
|
+
|
|
429
|
+
`overcrow-widget check` confronte la logique à ce que la VM exécute et
|
|
430
|
+
indique par quoi le SDK remplace ce qui manque :
|
|
431
|
+
|
|
432
|
+
| Code | Règle |
|
|
433
|
+
| --- | --- |
|
|
434
|
+
| `logic.syntax` | Le module s’analyse comme de l’ES2023 ; les types TypeScript sont permis. |
|
|
435
|
+
| `logic.import` | Son seul import est `@overcrow/sdk` : aucun autre module, fichier ou paquet, pas de `export *`. |
|
|
436
|
+
| `logic.dynamic_import`, `logic.import_meta` | Ni `import()` ni `import.meta`. |
|
|
437
|
+
| `logic.eval`, `logic.function_constructor` | Ni `eval`, ni `Function(…)`, ni `new Function(…)`. |
|
|
438
|
+
| `logic.unavailable_global` | Chaque globale lue existe dans la VM. `Intl`, `setTimeout`, `console`, `fetch`, `WebAssembly`, `SharedArrayBuffer`, `performance`, `WeakRef`, les globales du navigateur et de Node.js n’y existent pas. |
|
|
439
|
+
| `logic.top_level_await`, `logic.top_level_this` | Ni `await` ni `for await` au niveau supérieur, ni `this` au niveau supérieur. |
|
|
440
|
+
| `logic.syntax_version` | Rien de plus récent qu’ES2023 : décorateurs, `using`, drapeau `v` des expressions régulières, attributs d’import. |
|
|
441
|
+
| `logic.default_export` | La vue appelle des exports nommés ; `export default` est refusé. |
|
|
442
|
+
| `logic.missing_export` | Chaque fonction que la vue appelle est exportée. |
|
|
443
|
+
| `logic.debugger` | `debugger` donne un avertissement. |
|
|
444
|
+
|
|
445
|
+
Ce contrôle vous aide ; ce n’est pas lui qui protège l’utilisateur. C’est le
|
|
446
|
+
rôle du sandbox, des budgets de la VM et de la vérification par OverCrow de
|
|
447
|
+
tout ce que le widget envoie.
|
|
448
|
+
|
|
449
|
+
## Ce qui se passe en cas d’échec
|
|
450
|
+
|
|
451
|
+
- Une exception dans un gestionnaire met fin à ce tour ; le widget continue
|
|
452
|
+
de tourner, et `overcrow-widget dev` affiche la faute.
|
|
453
|
+
- Un tour plus long que son budget (50 ms), un tas au-dessus de son plafond
|
|
454
|
+
ou trop de messages dans un tour arrêtent le widget. OverCrow affiche une
|
|
455
|
+
erreur fixe dans son cadre et le relance après 1, 5 puis 15 secondes,
|
|
456
|
+
trois fois au plus.
|
|
457
|
+
- La promesse rejetée d’un appel de service est une erreur ordinaire de
|
|
458
|
+
votre code : interceptez-la. Voir les [erreurs](services.md#erreurs).
|
|
459
|
+
|
|
460
|
+
Les valeurs chiffrées figurent dans les [limites](limits.md#logique). Toute
|
|
461
|
+
l’API du SDK est décrite dans la [référence du SDK](sdk.md).
|