@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,119 @@
|
|
|
1
|
+
{
|
|
2
|
+
"release": "0.6.0-beta.2",
|
|
3
|
+
"tools": {
|
|
4
|
+
"linux-x86_64": {
|
|
5
|
+
"name": "overcrow-creator-tools-0.6.0-beta.2-linux-x86_64.zip",
|
|
6
|
+
"size": 15485097,
|
|
7
|
+
"sha256": "cf31486168ef2f7335eebf78453ce2bc4710cf18772c2a9b58dd8f329a50ac3b",
|
|
8
|
+
"files": [
|
|
9
|
+
{
|
|
10
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-linux-x86_64/README.txt",
|
|
11
|
+
"size": 1636,
|
|
12
|
+
"sha256": "36b87cb468f6e70b7b637b8cfec7652268065cf1ca53ea8fb2cbec3f3da1b4d5"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-linux-x86_64/SHA256SUMS",
|
|
16
|
+
"size": 797,
|
|
17
|
+
"sha256": "600c2d985e32a3db652cd1f7ff49ba39d069d7300eb59ada1e239855423d9901"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-linux-x86_64/cli.json",
|
|
21
|
+
"size": 1014,
|
|
22
|
+
"sha256": "ec1e1bb7fe5b7ce18b64ea41dbfc40c4545c08781158773425dc76077c8db8ce"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-linux-x86_64/overcrow-widget-1.0.0-beta.2-LICENSE.txt",
|
|
26
|
+
"size": 1071,
|
|
27
|
+
"sha256": "c159eef41245fe20d4cd29fc33a0e88a85f47b53ac321f266abfb7b707aee8c3"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-linux-x86_64/overcrow-widget-1.0.0-beta.2-THIRD-PARTY-NOTICES.md",
|
|
31
|
+
"size": 212099,
|
|
32
|
+
"sha256": "8c679481b61f9fb4c8352bd4d1c3bcfc23acf4d51b8252140ed214b1f5b756c4"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-linux-x86_64/overcrow-widget-1.0.0-beta.2-linux-x86_64",
|
|
36
|
+
"size": 8872680,
|
|
37
|
+
"sha256": "22c05cdefc4a9c8fa8efad29451377df19f3e2a8e32af9e14c1a25ffcc055c7e"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-linux-x86_64/overcrow-widget-headless-0.6.0-beta.2-LICENSE.md",
|
|
41
|
+
"size": 217457,
|
|
42
|
+
"sha256": "af6a7c90d1fa394bfaf586daa1afba7b65c07caaec83e70f01af2b93266277dd"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-linux-x86_64/overcrow-widget-headless-0.6.0-beta.2-linux-x86_64",
|
|
46
|
+
"size": 24446088,
|
|
47
|
+
"sha256": "644d05befead961846b402c5012a1460034cf5ef7bbbe38efcee66e883931d56"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-linux-x86_64/runtimes.json",
|
|
51
|
+
"size": 774,
|
|
52
|
+
"sha256": "13917d0506fdc9e91af61a2bdd1ee91adfd5a713807b61ffc94b74557c70914a"
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
"windows-x86_64": {
|
|
57
|
+
"name": "overcrow-creator-tools-0.6.0-beta.2-windows-x86_64.zip",
|
|
58
|
+
"size": 15415211,
|
|
59
|
+
"sha256": "87a8323de96e987eae8c5d4d8d36b90c4fd4f8fe8b64b499c48b77b4faeb3fe0",
|
|
60
|
+
"files": [
|
|
61
|
+
{
|
|
62
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-windows-x86_64/README.txt",
|
|
63
|
+
"size": 1457,
|
|
64
|
+
"sha256": "a4ca866f352b7e39de434c27242234daa8fbbdfbb9b362bfc148ef398ed65da4"
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-windows-x86_64/SHA256SUMS",
|
|
68
|
+
"size": 809,
|
|
69
|
+
"sha256": "e6a0c8e6ffde6d2c5a54fc486f6b1b17f225be1d56bf81b6a165f630df08915d"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-windows-x86_64/cli.json",
|
|
73
|
+
"size": 1014,
|
|
74
|
+
"sha256": "ec1e1bb7fe5b7ce18b64ea41dbfc40c4545c08781158773425dc76077c8db8ce"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-windows-x86_64/overcrow-widget-1.0.0-beta.2-LICENSE.txt",
|
|
78
|
+
"size": 1071,
|
|
79
|
+
"sha256": "c159eef41245fe20d4cd29fc33a0e88a85f47b53ac321f266abfb7b707aee8c3"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-windows-x86_64/overcrow-widget-1.0.0-beta.2-THIRD-PARTY-NOTICES.md",
|
|
83
|
+
"size": 212099,
|
|
84
|
+
"sha256": "8c679481b61f9fb4c8352bd4d1c3bcfc23acf4d51b8252140ed214b1f5b756c4"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-windows-x86_64/overcrow-widget-1.0.0-beta.2-windows-x86_64.exe",
|
|
88
|
+
"size": 8767488,
|
|
89
|
+
"sha256": "c8408f80e9b634cd3bc5f4cdf240179a6314ec847b7d99e4697f9ea47dae1506"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-windows-x86_64/overcrow-widget-headless-0.6.0-beta.2-LICENSE.md",
|
|
93
|
+
"size": 217457,
|
|
94
|
+
"sha256": "af6a7c90d1fa394bfaf586daa1afba7b65c07caaec83e70f01af2b93266277dd"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-windows-x86_64/overcrow-widget-headless-0.6.0-beta.2-windows-x86_64.exe",
|
|
98
|
+
"size": 25101824,
|
|
99
|
+
"sha256": "884b783ff37c594812f9203573668e86582b521dc2d9b145f5afc8955757c1ec"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"path": "overcrow-creator-tools-0.6.0-beta.2-windows-x86_64/runtimes.json",
|
|
103
|
+
"size": 774,
|
|
104
|
+
"sha256": "13917d0506fdc9e91af61a2bdd1ee91adfd5a713807b61ffc94b74557c70914a"
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"npm": {
|
|
110
|
+
"@overcrow/sdk": {
|
|
111
|
+
"version": "1.0.0",
|
|
112
|
+
"integrity": "sha512-akyuynS1TN5QbKyLsgoLOFF6JylVzNpUluEoSfz52xSlFg161kQ9QPLhcfGCptZ1x5/pm9/zPe/6LsHqFofnEA=="
|
|
113
|
+
},
|
|
114
|
+
"typescript": {
|
|
115
|
+
"version": "6.0.3",
|
|
116
|
+
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
// A strict reader of a creator tools ZIP, on the model of the CLI's
|
|
2
|
+
// `cli/src/zipread.rs`. The archive's SHA-256 is checked against the pin
|
|
3
|
+
// before this code sees it; the reader still trusts nothing it declares.
|
|
4
|
+
//
|
|
5
|
+
// Accepted: one disk, no ZIP64, no encryption, no comment, stored or
|
|
6
|
+
// deflated regular files, the central directory right before its end
|
|
7
|
+
// record, local headers that agree with it, entries that do not overlap,
|
|
8
|
+
// and names made of plain components. Refused besides: links, directories,
|
|
9
|
+
// device names Windows reserves, duplicates (case-insensitive) and every
|
|
10
|
+
// byte the format does not account for. Each entry is inflated within its
|
|
11
|
+
// declared size and checked against its CRC-32.
|
|
12
|
+
import { crc32, inflateRawSync } from "node:zlib";
|
|
13
|
+
export class ZipError extends Error {
|
|
14
|
+
kind;
|
|
15
|
+
rule;
|
|
16
|
+
constructor(kind, rule) {
|
|
17
|
+
super(kind === "unsafe_name"
|
|
18
|
+
? `the archive holds an unsafe file name (${rule})`
|
|
19
|
+
: kind === "too_large"
|
|
20
|
+
? `the archive exceeds its size bounds (${rule})`
|
|
21
|
+
: `invalid archive: ${rule}`);
|
|
22
|
+
this.kind = kind;
|
|
23
|
+
this.rule = rule;
|
|
24
|
+
this.name = "ZipError";
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const END_SIGNATURE = 0x06054b50;
|
|
28
|
+
const CENTRAL_SIGNATURE = 0x02014b50;
|
|
29
|
+
const LOCAL_SIGNATURE = 0x04034b50;
|
|
30
|
+
const ZIP64_LOCATOR_SIGNATURE = 0x07064b50;
|
|
31
|
+
const END_BYTES = 22;
|
|
32
|
+
const CENTRAL_BYTES = 46;
|
|
33
|
+
const LOCAL_BYTES = 30;
|
|
34
|
+
/** Encryption (bit 0), strong encryption (bit 6), masked headers (bit 13). */
|
|
35
|
+
const ENCRYPTED_FLAGS = 1 | (1 << 6) | (1 << 13);
|
|
36
|
+
/** Deflate options (bits 1-2), data descriptor (bit 3), UTF-8 names (bit 11). */
|
|
37
|
+
const KNOWN_FLAGS = ENCRYPTED_FLAGS | 0b110 | (1 << 3) | (1 << 11);
|
|
38
|
+
const MAX_DIRECTORY_BYTES = 64 * 1024;
|
|
39
|
+
const MAX_NAME_BYTES = 255;
|
|
40
|
+
const U32_MAX = 0xffffffff;
|
|
41
|
+
const U16_MAX = 0xffff;
|
|
42
|
+
const UNIX_HOST = 3;
|
|
43
|
+
const FILE_TYPE_MASK = 0o170000;
|
|
44
|
+
const REGULAR_FILE = 0o100000;
|
|
45
|
+
const DOS_DIRECTORY = 0x10;
|
|
46
|
+
const COMPONENT = /^[A-Za-z0-9][A-Za-z0-9._+-]*$/;
|
|
47
|
+
const WINDOWS_DEVICE = /^(con|prn|aux|nul|com[0-9¹²³]|lpt[0-9¹²³]|conin\$|conout\$)(\..*)?$/i;
|
|
48
|
+
/**
|
|
49
|
+
* A safe name: relative, components of letters, digits, `.`, `_`, `+` and
|
|
50
|
+
* `-` that start with a letter or digit, no trailing dot, no name that
|
|
51
|
+
* Windows maps to a device. Directories are implied, never entries.
|
|
52
|
+
*/
|
|
53
|
+
export function safeName(name) {
|
|
54
|
+
if (name.length === 0 || Buffer.byteLength(name) > MAX_NAME_BYTES)
|
|
55
|
+
return false;
|
|
56
|
+
return name
|
|
57
|
+
.split("/")
|
|
58
|
+
.every((component) => COMPONENT.test(component) && !component.endsWith(".") && !WINDOWS_DEVICE.test(component));
|
|
59
|
+
}
|
|
60
|
+
/** Reads and checks the whole directory of `archive`. */
|
|
61
|
+
export function readEntries(archive, limits) {
|
|
62
|
+
const length = archive.length;
|
|
63
|
+
if (length < END_BYTES)
|
|
64
|
+
throw new ZipError("invalid", "too short");
|
|
65
|
+
const endOffset = length - END_BYTES;
|
|
66
|
+
if (archive.readUInt32LE(endOffset) !== END_SIGNATURE) {
|
|
67
|
+
throw new ZipError("invalid", "no end record at the end");
|
|
68
|
+
}
|
|
69
|
+
if (archive.readUInt16LE(endOffset + 20) !== 0)
|
|
70
|
+
throw new ZipError("invalid", "archive comment");
|
|
71
|
+
const disk = archive.readUInt16LE(endOffset + 4);
|
|
72
|
+
const directoryDisk = archive.readUInt16LE(endOffset + 6);
|
|
73
|
+
const diskEntries = archive.readUInt16LE(endOffset + 8);
|
|
74
|
+
const totalEntries = archive.readUInt16LE(endOffset + 10);
|
|
75
|
+
const directorySize = archive.readUInt32LE(endOffset + 12);
|
|
76
|
+
const directoryOffset = archive.readUInt32LE(endOffset + 16);
|
|
77
|
+
if (diskEntries === U16_MAX ||
|
|
78
|
+
totalEntries === U16_MAX ||
|
|
79
|
+
directorySize === U32_MAX ||
|
|
80
|
+
directoryOffset === U32_MAX) {
|
|
81
|
+
throw new ZipError("invalid", "ZIP64");
|
|
82
|
+
}
|
|
83
|
+
if (endOffset >= 20 && archive.readUInt32LE(endOffset - 20) === ZIP64_LOCATOR_SIGNATURE) {
|
|
84
|
+
throw new ZipError("invalid", "ZIP64");
|
|
85
|
+
}
|
|
86
|
+
if (disk !== 0 || directoryDisk !== 0 || diskEntries !== totalEntries) {
|
|
87
|
+
throw new ZipError("invalid", "several disks");
|
|
88
|
+
}
|
|
89
|
+
if (totalEntries === 0)
|
|
90
|
+
throw new ZipError("invalid", "no entries");
|
|
91
|
+
if (totalEntries > limits.maxEntries)
|
|
92
|
+
throw new ZipError("too_large", "too many entries");
|
|
93
|
+
if (directorySize > MAX_DIRECTORY_BYTES)
|
|
94
|
+
throw new ZipError("too_large", "central directory");
|
|
95
|
+
if (directoryOffset + directorySize !== endOffset) {
|
|
96
|
+
throw new ZipError("invalid", "central directory not before its end record");
|
|
97
|
+
}
|
|
98
|
+
const directory = archive.subarray(directoryOffset, endOffset);
|
|
99
|
+
const found = [];
|
|
100
|
+
const seen = new Set();
|
|
101
|
+
let total = 0;
|
|
102
|
+
let cursor = 0;
|
|
103
|
+
for (let index = 0; index < totalEntries; index += 1) {
|
|
104
|
+
if (cursor + CENTRAL_BYTES > directory.length) {
|
|
105
|
+
throw new ZipError("invalid", "truncated central directory");
|
|
106
|
+
}
|
|
107
|
+
if (directory.readUInt32LE(cursor) !== CENTRAL_SIGNATURE) {
|
|
108
|
+
throw new ZipError("invalid", "bad central header");
|
|
109
|
+
}
|
|
110
|
+
const madeBy = directory.readUInt16LE(cursor + 4);
|
|
111
|
+
const flags = directory.readUInt16LE(cursor + 8);
|
|
112
|
+
const method = directory.readUInt16LE(cursor + 10);
|
|
113
|
+
const crc = directory.readUInt32LE(cursor + 16);
|
|
114
|
+
const compressed = directory.readUInt32LE(cursor + 20);
|
|
115
|
+
const size = directory.readUInt32LE(cursor + 24);
|
|
116
|
+
const nameLength = directory.readUInt16LE(cursor + 28);
|
|
117
|
+
const extraLength = directory.readUInt16LE(cursor + 30);
|
|
118
|
+
const commentLength = directory.readUInt16LE(cursor + 32);
|
|
119
|
+
const diskStart = directory.readUInt16LE(cursor + 34);
|
|
120
|
+
const externalAttributes = directory.readUInt32LE(cursor + 38);
|
|
121
|
+
const localOffset = directory.readUInt32LE(cursor + 42);
|
|
122
|
+
if ((flags & ENCRYPTED_FLAGS) !== 0)
|
|
123
|
+
throw new ZipError("invalid", "encrypted entry");
|
|
124
|
+
if ((flags & ~KNOWN_FLAGS) !== 0)
|
|
125
|
+
throw new ZipError("invalid", "unknown entry flags");
|
|
126
|
+
if (method !== 0 && method !== 8)
|
|
127
|
+
throw new ZipError("invalid", "unsupported compression method");
|
|
128
|
+
if (compressed === U32_MAX || size === U32_MAX || localOffset === U32_MAX) {
|
|
129
|
+
throw new ZipError("invalid", "ZIP64");
|
|
130
|
+
}
|
|
131
|
+
if (diskStart !== 0)
|
|
132
|
+
throw new ZipError("invalid", "several disks");
|
|
133
|
+
if (method === 0 && compressed !== size)
|
|
134
|
+
throw new ZipError("invalid", "stored entry sizes differ");
|
|
135
|
+
const nameStart = cursor + CENTRAL_BYTES;
|
|
136
|
+
if (nameStart + nameLength > directory.length) {
|
|
137
|
+
throw new ZipError("invalid", "truncated central directory");
|
|
138
|
+
}
|
|
139
|
+
const nameBytes = Buffer.from(directory.subarray(nameStart, nameStart + nameLength));
|
|
140
|
+
let name;
|
|
141
|
+
try {
|
|
142
|
+
name = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(nameBytes);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// Found by test/fuzz-zip.mjs: a name that is not UTF-8 is refused, not thrown.
|
|
146
|
+
throw new ZipError("unsafe_name", "not UTF-8");
|
|
147
|
+
}
|
|
148
|
+
if (!safeName(name))
|
|
149
|
+
throw new ZipError("unsafe_name", name.slice(0, 64));
|
|
150
|
+
// Only regular files: no link, no directory, no device.
|
|
151
|
+
let mode = null;
|
|
152
|
+
if (madeBy >> 8 === UNIX_HOST) {
|
|
153
|
+
const unixMode = externalAttributes >>> 16;
|
|
154
|
+
const type = unixMode & FILE_TYPE_MASK;
|
|
155
|
+
if (type !== 0 && type !== REGULAR_FILE)
|
|
156
|
+
throw new ZipError("unsafe_name", `${name} is not a regular file`);
|
|
157
|
+
mode = unixMode & 0o7777;
|
|
158
|
+
}
|
|
159
|
+
if ((externalAttributes & DOS_DIRECTORY) !== 0) {
|
|
160
|
+
throw new ZipError("unsafe_name", `${name} is a directory`);
|
|
161
|
+
}
|
|
162
|
+
// Case-insensitive file systems would merge two such names.
|
|
163
|
+
const key = name.toLowerCase();
|
|
164
|
+
if (seen.has(key))
|
|
165
|
+
throw new ZipError("invalid", "duplicate entry");
|
|
166
|
+
seen.add(key);
|
|
167
|
+
cursor = nameStart + nameLength + extraLength + commentLength;
|
|
168
|
+
if (cursor > directory.length)
|
|
169
|
+
throw new ZipError("invalid", "truncated central directory");
|
|
170
|
+
if (size > limits.maxEntryBytes)
|
|
171
|
+
throw new ZipError("too_large", "entry size");
|
|
172
|
+
total += size;
|
|
173
|
+
if (total > limits.maxTotalBytes)
|
|
174
|
+
throw new ZipError("too_large", "total size");
|
|
175
|
+
found.push({
|
|
176
|
+
localOffset,
|
|
177
|
+
flags,
|
|
178
|
+
method,
|
|
179
|
+
nameBytes,
|
|
180
|
+
entry: { name, size, mode, compressed, deflated: method === 8, crc32: crc, dataStart: 0 },
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
if (cursor !== directory.length)
|
|
184
|
+
throw new ZipError("invalid", "bytes after the central directory");
|
|
185
|
+
// Local headers repeat the central directory; entries follow one another
|
|
186
|
+
// without overlapping, and nothing lies between them.
|
|
187
|
+
found.sort((a, b) => a.localOffset - b.localOffset);
|
|
188
|
+
let nextFree = 0;
|
|
189
|
+
const checked = [];
|
|
190
|
+
for (const { localOffset, entry, flags, method, nameBytes } of found) {
|
|
191
|
+
if (localOffset !== nextFree) {
|
|
192
|
+
throw new ZipError("invalid", localOffset < nextFree ? "overlapping entries" : "bytes between entries");
|
|
193
|
+
}
|
|
194
|
+
if (localOffset + LOCAL_BYTES > directoryOffset) {
|
|
195
|
+
throw new ZipError("invalid", "local header outside the data");
|
|
196
|
+
}
|
|
197
|
+
if (archive.readUInt32LE(localOffset) !== LOCAL_SIGNATURE) {
|
|
198
|
+
throw new ZipError("invalid", "bad local header");
|
|
199
|
+
}
|
|
200
|
+
const disagree = new ZipError("invalid", "local header disagrees with the directory");
|
|
201
|
+
if (archive.readUInt16LE(localOffset + 6) !== flags ||
|
|
202
|
+
archive.readUInt16LE(localOffset + 8) !== method) {
|
|
203
|
+
throw disagree;
|
|
204
|
+
}
|
|
205
|
+
// A data descriptor (bit 3) is not something the publisher writes.
|
|
206
|
+
if ((flags & (1 << 3)) !== 0)
|
|
207
|
+
throw new ZipError("invalid", "data descriptor");
|
|
208
|
+
if (archive.readUInt32LE(localOffset + 14) !== entry.crc32 ||
|
|
209
|
+
archive.readUInt32LE(localOffset + 18) !== entry.compressed ||
|
|
210
|
+
archive.readUInt32LE(localOffset + 22) !== entry.size) {
|
|
211
|
+
throw disagree;
|
|
212
|
+
}
|
|
213
|
+
const nameLength = archive.readUInt16LE(localOffset + 26);
|
|
214
|
+
const extraLength = archive.readUInt16LE(localOffset + 28);
|
|
215
|
+
if (nameLength !== nameBytes.length)
|
|
216
|
+
throw disagree;
|
|
217
|
+
const localNameEnd = localOffset + LOCAL_BYTES + nameLength;
|
|
218
|
+
if (localNameEnd > directoryOffset ||
|
|
219
|
+
!archive.subarray(localOffset + LOCAL_BYTES, localNameEnd).equals(nameBytes)) {
|
|
220
|
+
throw disagree;
|
|
221
|
+
}
|
|
222
|
+
const dataStart = localNameEnd + extraLength;
|
|
223
|
+
const dataEnd = dataStart + entry.compressed;
|
|
224
|
+
if (dataEnd > directoryOffset)
|
|
225
|
+
throw new ZipError("invalid", "entry data outside the archive");
|
|
226
|
+
nextFree = dataEnd;
|
|
227
|
+
checked.push({ ...entry, dataStart });
|
|
228
|
+
}
|
|
229
|
+
if (nextFree !== directoryOffset)
|
|
230
|
+
throw new ZipError("invalid", "bytes before the central directory");
|
|
231
|
+
return checked;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* The uncompressed bytes of `entry`: exactly its declared size, with its
|
|
235
|
+
* CRC-32. The inflater stops at the declared size, so a bomb never grows.
|
|
236
|
+
*/
|
|
237
|
+
export function extractEntry(archive, entry) {
|
|
238
|
+
const raw = archive.subarray(entry.dataStart, entry.dataStart + entry.compressed);
|
|
239
|
+
let data;
|
|
240
|
+
if (entry.deflated) {
|
|
241
|
+
try {
|
|
242
|
+
data = inflateRawSync(raw, { maxOutputLength: Math.max(1, entry.size) });
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
const tooLarge = error instanceof RangeError || error.code === "ERR_BUFFER_TOO_LARGE";
|
|
246
|
+
throw new ZipError("invalid", tooLarge ? "entry larger than declared" : "corrupt entry data");
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
data = Buffer.from(raw);
|
|
251
|
+
}
|
|
252
|
+
if (data.length !== entry.size) {
|
|
253
|
+
throw new ZipError("invalid", data.length > entry.size ? "entry larger than declared" : "entry smaller than declared");
|
|
254
|
+
}
|
|
255
|
+
if (crc32(data) !== entry.crc32)
|
|
256
|
+
throw new ZipError("invalid", "CRC-32 mismatch");
|
|
257
|
+
return data;
|
|
258
|
+
}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// Calls of the widget CLI (`overcrow-widget`) of the installed creator
|
|
2
|
+
// tools and the reading of its `--format json` output (one JSON object per
|
|
3
|
+
// line). Paths are always absolute: the CLI would read an argument starting
|
|
4
|
+
// with `--` as an option. The CLI never reaches the network here: `test`
|
|
5
|
+
// gets the runtime with `--runtime` and `--offline`. `doctor` and `dev`,
|
|
6
|
+
// which talk to a running OverCrow, are never called.
|
|
7
|
+
import { childEnvironment } from "./env.js";
|
|
8
|
+
import { runProcess } from "./run.js";
|
|
9
|
+
export class CliError extends Error {
|
|
10
|
+
stderr;
|
|
11
|
+
constructor(message, stderr) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.stderr = stderr;
|
|
14
|
+
this.name = "CliError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const MINUTE = 60_000;
|
|
18
|
+
export const TIMEOUTS = {
|
|
19
|
+
version: 15_000,
|
|
20
|
+
init: MINUTE,
|
|
21
|
+
check: 6 * MINUTE,
|
|
22
|
+
package: 6 * MINUTE,
|
|
23
|
+
admit: 2 * MINUTE,
|
|
24
|
+
inspect: MINUTE,
|
|
25
|
+
test: 20 * MINUTE,
|
|
26
|
+
};
|
|
27
|
+
/** Parses the JSON lines of stdout; other lines are ignored. */
|
|
28
|
+
export function jsonLines(stdout, maxLines = 5000) {
|
|
29
|
+
const out = [];
|
|
30
|
+
for (const line of stdout.split("\n")) {
|
|
31
|
+
if (out.length >= maxLines)
|
|
32
|
+
break;
|
|
33
|
+
const trimmed = line.trim();
|
|
34
|
+
if (!trimmed.startsWith("{"))
|
|
35
|
+
continue;
|
|
36
|
+
try {
|
|
37
|
+
const value = JSON.parse(trimmed);
|
|
38
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value))
|
|
39
|
+
out.push(value);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Not a JSON line.
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
const str = (value) => (typeof value === "string" ? value : null);
|
|
48
|
+
const int = (value) => Number.isSafeInteger(value) ? value : null;
|
|
49
|
+
/** A diagnostic object of the CLI, or undefined for any other line. */
|
|
50
|
+
export function asDiagnostic(value) {
|
|
51
|
+
if ("type" in value)
|
|
52
|
+
return undefined;
|
|
53
|
+
const severity = value.severity;
|
|
54
|
+
if ((severity !== "error" && severity !== "warning") || typeof value.code !== "string")
|
|
55
|
+
return undefined;
|
|
56
|
+
return {
|
|
57
|
+
severity,
|
|
58
|
+
code: value.code,
|
|
59
|
+
file: str(value.file),
|
|
60
|
+
line: int(value.line),
|
|
61
|
+
column: int(value.column),
|
|
62
|
+
message: str(value.message) ?? "",
|
|
63
|
+
help: str(value.help),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export class Cli {
|
|
67
|
+
tools;
|
|
68
|
+
constructor(tools) {
|
|
69
|
+
this.tools = tools;
|
|
70
|
+
}
|
|
71
|
+
run(args, cwd, timeoutMs, signal) {
|
|
72
|
+
return runProcess(this.tools.cli, args, {
|
|
73
|
+
cwd,
|
|
74
|
+
env: childEnvironment({ network: false }),
|
|
75
|
+
timeoutMs,
|
|
76
|
+
signal,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
static failure(result, what) {
|
|
80
|
+
if (result.timedOut)
|
|
81
|
+
return new CliError(`${what} took too long and was stopped`, result.stderr);
|
|
82
|
+
if (result.cancelled)
|
|
83
|
+
return new CliError(`${what} was cancelled`, result.stderr);
|
|
84
|
+
const first = result.stderr.split("\n").find((line) => line.trim() !== "") ?? "";
|
|
85
|
+
return new CliError(`${what} failed (exit ${result.code})${first ? `: ${first}` : ""}`, result.stderr);
|
|
86
|
+
}
|
|
87
|
+
/** `check <dir> --format json`: diagnostics, and whether there is no error. */
|
|
88
|
+
async check(directory, signal) {
|
|
89
|
+
const result = await this.run(["check", directory, "--format", "json"], directory, TIMEOUTS.check, signal);
|
|
90
|
+
if (result.code !== 0 && result.code !== 1)
|
|
91
|
+
throw Cli.failure(result, "check");
|
|
92
|
+
const diagnostics = jsonLines(result.stdout)
|
|
93
|
+
.map(asDiagnostic)
|
|
94
|
+
.filter((d) => d !== undefined);
|
|
95
|
+
return { ok: result.code === 0, diagnostics };
|
|
96
|
+
}
|
|
97
|
+
/** `package <dir> --out <file> --format json`. */
|
|
98
|
+
async package(directory, out, signal) {
|
|
99
|
+
const result = await this.run(["package", directory, `--out=${out}`, "--format", "json"], directory, TIMEOUTS.package, signal);
|
|
100
|
+
if (result.code !== 0 && result.code !== 1)
|
|
101
|
+
throw Cli.failure(result, "package");
|
|
102
|
+
const lines = jsonLines(result.stdout);
|
|
103
|
+
const diagnostics = lines.map(asDiagnostic).filter((d) => d !== undefined);
|
|
104
|
+
const summary = lines.find((line) => typeof line.package === "string" && typeof line.sha256 === "string");
|
|
105
|
+
return {
|
|
106
|
+
ok: result.code === 0 && summary !== undefined,
|
|
107
|
+
diagnostics,
|
|
108
|
+
bytes: int(summary?.bytes),
|
|
109
|
+
logicBytes: int(summary?.logicBytes),
|
|
110
|
+
sha256: str(summary?.sha256),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/** `admit <dir> --format json`: the static admission report, as data. */
|
|
114
|
+
async admit(directory, signal) {
|
|
115
|
+
const result = await this.run(["admit", directory, "--format", "json"], directory, TIMEOUTS.admit, signal);
|
|
116
|
+
if (result.code !== 0 && result.code !== 1)
|
|
117
|
+
throw Cli.failure(result, "admit");
|
|
118
|
+
const report = jsonLines(result.stdout).find((line) => line.formatVersion === 1);
|
|
119
|
+
if (!report)
|
|
120
|
+
throw Cli.failure(result, "admit");
|
|
121
|
+
return report;
|
|
122
|
+
}
|
|
123
|
+
/** `inspect <file> --format json`. */
|
|
124
|
+
async inspect(file, cwd, signal) {
|
|
125
|
+
const result = await this.run(["inspect", file, "--format", "json"], cwd, TIMEOUTS.inspect, signal);
|
|
126
|
+
if (result.code === 2)
|
|
127
|
+
throw Cli.failure(result, "inspect");
|
|
128
|
+
const lines = jsonLines(result.stdout);
|
|
129
|
+
const diagnostics = lines.map(asDiagnostic).filter((d) => d !== undefined);
|
|
130
|
+
const report = lines.find((line) => typeof line.id === "string" && typeof line.archive === "object");
|
|
131
|
+
return { ok: result.code === 0 && report !== undefined, diagnostics, report };
|
|
132
|
+
}
|
|
133
|
+
/** `test <dir> --runtime <cached runtime> --offline --format json`. */
|
|
134
|
+
async test(directory, options, signal) {
|
|
135
|
+
const args = [
|
|
136
|
+
"test",
|
|
137
|
+
directory,
|
|
138
|
+
`--runtime=${this.tools.runtime}`,
|
|
139
|
+
"--offline",
|
|
140
|
+
"--format",
|
|
141
|
+
"json",
|
|
142
|
+
];
|
|
143
|
+
if (options.scenario)
|
|
144
|
+
args.push(`--scenario=${options.scenario}`);
|
|
145
|
+
if (options.update)
|
|
146
|
+
args.push("--update");
|
|
147
|
+
const result = await this.run(args, directory, TIMEOUTS.test, signal);
|
|
148
|
+
if (result.timedOut || result.cancelled)
|
|
149
|
+
throw Cli.failure(result, "test");
|
|
150
|
+
const lines = jsonLines(result.stdout);
|
|
151
|
+
const summary = lines.find((line) => line.type === "summary");
|
|
152
|
+
if (result.code === 2 ||
|
|
153
|
+
(result.code !== 0 && !summary && lines.every((line) => line.type !== "scenario"))) {
|
|
154
|
+
// No scenario ran: a usage, project or runtime problem, said on stderr.
|
|
155
|
+
const diagnostics = lines.map(asDiagnostic).filter((d) => d !== undefined);
|
|
156
|
+
if (diagnostics.length === 0 || result.code === 2) {
|
|
157
|
+
return { ran: false, diagnostics, problem: firstLines(result.stderr, 6) };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
ran: true,
|
|
162
|
+
diagnostics: lines.map(asDiagnostic).filter((d) => d !== undefined),
|
|
163
|
+
runtime: lines.find((line) => line.type === "runtime"),
|
|
164
|
+
scenarios: lines.filter((line) => line.type === "scenario"),
|
|
165
|
+
passed: int(summary?.passed),
|
|
166
|
+
failed: int(summary?.failed),
|
|
167
|
+
problem: result.code === 0 ? "" : firstLines(result.stderr, 6),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
/** `init <dir> --template <t> --id <id> --name <name>` (no JSON form). */
|
|
171
|
+
async init(directory, template, id, name, cwd) {
|
|
172
|
+
const result = await this.run(["init", directory, `--template=${template}`, `--id=${id}`, `--name=${name}`], cwd, TIMEOUTS.init);
|
|
173
|
+
return {
|
|
174
|
+
ok: result.code === 0,
|
|
175
|
+
code: result.code,
|
|
176
|
+
stdout: result.stdout,
|
|
177
|
+
stderr: result.stderr,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function firstLines(text, count) {
|
|
182
|
+
return text
|
|
183
|
+
.split("\n")
|
|
184
|
+
.filter((line) => line.trim() !== "")
|
|
185
|
+
.slice(0, count)
|
|
186
|
+
.join("\n");
|
|
187
|
+
}
|
|
188
|
+
/** The `--version --format json` probe used when installing the tools. */
|
|
189
|
+
export async function probeVersion(cli, cwd) {
|
|
190
|
+
const result = await runProcess(cli, ["--version", "--format", "json"], {
|
|
191
|
+
cwd,
|
|
192
|
+
env: childEnvironment({ network: false }),
|
|
193
|
+
timeoutMs: TIMEOUTS.version,
|
|
194
|
+
maxStdoutBytes: 64 * 1024,
|
|
195
|
+
});
|
|
196
|
+
if (result.code !== 0)
|
|
197
|
+
throw new CliError("the CLI did not report its version", result.stderr);
|
|
198
|
+
const [report] = jsonLines(result.stdout);
|
|
199
|
+
return report;
|
|
200
|
+
}
|