@overcrow/mcp 0.0.0 → 0.1.1

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.
Files changed (489) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +91 -1
  3. package/dist/audit/index.js +103 -0
  4. package/dist/audit/lexer.js +417 -0
  5. package/dist/audit/project.js +200 -0
  6. package/dist/audit/rules.js +661 -0
  7. package/dist/bootstrap/download.js +229 -0
  8. package/dist/bootstrap/install.js +280 -0
  9. package/dist/bootstrap/pin.js +85 -0
  10. package/dist/bootstrap/pin.json +119 -0
  11. package/dist/bootstrap/zip.js +258 -0
  12. package/dist/cli.js +200 -0
  13. package/dist/confine.js +244 -0
  14. package/dist/content/docs/en/cli.md +768 -0
  15. package/dist/content/docs/en/creator-space.md +78 -0
  16. package/dist/content/docs/en/dev-channel.md +130 -0
  17. package/dist/content/docs/en/elements.md +469 -0
  18. package/dist/content/docs/en/forms.md +328 -0
  19. package/dist/content/docs/en/guide.md +252 -0
  20. package/dist/content/docs/en/index.md +85 -0
  21. package/dist/content/docs/en/limits.md +241 -0
  22. package/dist/content/docs/en/logic.md +446 -0
  23. package/dist/content/docs/en/manifest.md +388 -0
  24. package/dist/content/docs/en/mcp.md +165 -0
  25. package/dist/content/docs/en/package.md +131 -0
  26. package/dist/content/docs/en/publish-a-widget.md +94 -0
  27. package/dist/content/docs/en/publish-keys.md +95 -0
  28. package/dist/content/docs/en/publishing.md +167 -0
  29. package/dist/content/docs/en/reference.md +55 -0
  30. package/dist/content/docs/en/result-shapes.md +332 -0
  31. package/dist/content/docs/en/sdk.md +295 -0
  32. package/dist/content/docs/en/security.md +115 -0
  33. package/dist/content/docs/en/service-reference.md +344 -0
  34. package/dist/content/docs/en/services.md +517 -0
  35. package/dist/content/docs/en/style-properties.md +270 -0
  36. package/dist/content/docs/en/style.md +266 -0
  37. package/dist/content/docs/en/testing.md +400 -0
  38. package/dist/content/docs/en/verified-domain.md +46 -0
  39. package/dist/content/docs/en/view.md +338 -0
  40. package/dist/content/docs/en/widget-listing.md +65 -0
  41. package/dist/content/docs/en/widget-review.md +57 -0
  42. package/dist/content/docs/en/widget-statistics.md +134 -0
  43. package/dist/content/docs/en/widgets.md +76 -0
  44. package/dist/content/docs/fr/cli.md +802 -0
  45. package/dist/content/docs/fr/creator-space.md +83 -0
  46. package/dist/content/docs/fr/dev-channel.md +140 -0
  47. package/dist/content/docs/fr/elements.md +475 -0
  48. package/dist/content/docs/fr/forms.md +341 -0
  49. package/dist/content/docs/fr/guide.md +263 -0
  50. package/dist/content/docs/fr/index.md +90 -0
  51. package/dist/content/docs/fr/limits.md +244 -0
  52. package/dist/content/docs/fr/logic.md +461 -0
  53. package/dist/content/docs/fr/manifest.md +401 -0
  54. package/dist/content/docs/fr/mcp.md +173 -0
  55. package/dist/content/docs/fr/package.md +139 -0
  56. package/dist/content/docs/fr/publish-a-widget.md +101 -0
  57. package/dist/content/docs/fr/publish-keys.md +97 -0
  58. package/dist/content/docs/fr/publishing.md +177 -0
  59. package/dist/content/docs/fr/reference.md +59 -0
  60. package/dist/content/docs/fr/result-shapes.md +333 -0
  61. package/dist/content/docs/fr/sdk.md +301 -0
  62. package/dist/content/docs/fr/security.md +129 -0
  63. package/dist/content/docs/fr/service-reference.md +346 -0
  64. package/dist/content/docs/fr/services.md +540 -0
  65. package/dist/content/docs/fr/style-properties.md +272 -0
  66. package/dist/content/docs/fr/style.md +281 -0
  67. package/dist/content/docs/fr/testing.md +417 -0
  68. package/dist/content/docs/fr/verified-domain.md +49 -0
  69. package/dist/content/docs/fr/view.md +352 -0
  70. package/dist/content/docs/fr/widget-listing.md +69 -0
  71. package/dist/content/docs/fr/widget-review.md +59 -0
  72. package/dist/content/docs/fr/widget-statistics.md +141 -0
  73. package/dist/content/docs/fr/widgets.md +81 -0
  74. package/dist/content/examples/clock/LICENSE +21 -0
  75. package/dist/content/examples/clock/README.md +75 -0
  76. package/dist/content/examples/clock/listing.json +19 -0
  77. package/dist/content/examples/clock/locales/en.json +4 -0
  78. package/dist/content/examples/clock/locales/fr.json +4 -0
  79. package/dist/content/examples/clock/logic.ts +85 -0
  80. package/dist/content/examples/clock/manifest.json +44 -0
  81. package/dist/content/examples/clock/package.json +16 -0
  82. package/dist/content/examples/clock/style.ocss +26 -0
  83. package/dist/content/examples/clock/tests/hidden.scenario.json +68 -0
  84. package/dist/content/examples/clock/tests/load-logic.mjs +22 -0
  85. package/dist/content/examples/clock/tests/logic.test.mjs +89 -0
  86. package/dist/content/examples/clock/tests/options.scenario.json +108 -0
  87. package/dist/content/examples/clock/tests/preview.scenario.json +25 -0
  88. package/dist/content/examples/clock/tests/render.scenario.json +94 -0
  89. package/dist/content/examples/clock/tests/summer-time.scenario.json +74 -0
  90. package/dist/content/examples/clock/tests/ticks.scenario.json +120 -0
  91. package/dist/content/examples/clock/tsconfig.json +16 -0
  92. package/dist/content/examples/clock/view.ocml +8 -0
  93. package/dist/content/examples/countdown/LICENSE +20 -0
  94. package/dist/content/examples/countdown/listing.json +10 -0
  95. package/dist/content/examples/countdown/locales/en.json +15 -0
  96. package/dist/content/examples/countdown/locales/fr.json +15 -0
  97. package/dist/content/examples/countdown/logic.ts +179 -0
  98. package/dist/content/examples/countdown/manifest.json +34 -0
  99. package/dist/content/examples/countdown/package.json +15 -0
  100. package/dist/content/examples/countdown/style.ocss +94 -0
  101. package/dist/content/examples/countdown/tsconfig.json +16 -0
  102. package/dist/content/examples/countdown/view.ocml +42 -0
  103. package/dist/content/examples/fps/LICENSE +21 -0
  104. package/dist/content/examples/fps/README.md +64 -0
  105. package/dist/content/examples/fps/listing.json +19 -0
  106. package/dist/content/examples/fps/locales/en.json +11 -0
  107. package/dist/content/examples/fps/locales/fr.json +11 -0
  108. package/dist/content/examples/fps/logic.ts +64 -0
  109. package/dist/content/examples/fps/manifest.json +30 -0
  110. package/dist/content/examples/fps/package.json +16 -0
  111. package/dist/content/examples/fps/style.ocss +31 -0
  112. package/dist/content/examples/fps/submission.json +8 -0
  113. package/dist/content/examples/fps/tests/label.scenario.json +63 -0
  114. package/dist/content/examples/fps/tests/load-logic.mjs +22 -0
  115. package/dist/content/examples/fps/tests/logic.test.mjs +60 -0
  116. package/dist/content/examples/fps/tests/preview.scenario.json +29 -0
  117. package/dist/content/examples/fps/tests/refused.scenario.json +20 -0
  118. package/dist/content/examples/fps/tests/render.scenario.json +96 -0
  119. package/dist/content/examples/fps/tests/stale.scenario.json +91 -0
  120. package/dist/content/examples/fps/tests/unavailable.scenario.json +111 -0
  121. package/dist/content/examples/fps/tsconfig.json +16 -0
  122. package/dist/content/examples/fps/view.ocml +11 -0
  123. package/dist/content/examples/media/LICENSE +21 -0
  124. package/dist/content/examples/media/README.md +147 -0
  125. package/dist/content/examples/media/listing.json +19 -0
  126. package/dist/content/examples/media/locales/en.json +11 -0
  127. package/dist/content/examples/media/locales/fr.json +11 -0
  128. package/dist/content/examples/media/logic.ts +191 -0
  129. package/dist/content/examples/media/manifest.json +35 -0
  130. package/dist/content/examples/media/package.json +16 -0
  131. package/dist/content/examples/media/style.ocss +148 -0
  132. package/dist/content/examples/media/submission.json +12 -0
  133. package/dist/content/examples/media/tests/covers.scenario.json +144 -0
  134. package/dist/content/examples/media/tests/gesture.scenario.json +173 -0
  135. package/dist/content/examples/media/tests/load-logic.mjs +22 -0
  136. package/dist/content/examples/media/tests/logic.test.mjs +176 -0
  137. package/dist/content/examples/media/tests/marquee.scenario.json +127 -0
  138. package/dist/content/examples/media/tests/preview.scenario.json +52 -0
  139. package/dist/content/examples/media/tests/read-only.scenario.json +53 -0
  140. package/dist/content/examples/media/tests/refused.scenario.json +22 -0
  141. package/dist/content/examples/media/tests/refused.test.mjs +31 -0
  142. package/dist/content/examples/media/tests/render.scenario.json +136 -0
  143. package/dist/content/examples/media/tests/states.scenario.json +257 -0
  144. package/dist/content/examples/media/tests/unavailable.scenario.json +120 -0
  145. package/dist/content/examples/media/tsconfig.json +16 -0
  146. package/dist/content/examples/media/view.ocml +41 -0
  147. package/dist/content/examples/notes/LICENSE +21 -0
  148. package/dist/content/examples/notes/README.md +219 -0
  149. package/dist/content/examples/notes/listing.json +19 -0
  150. package/dist/content/examples/notes/locales/en.json +25 -0
  151. package/dist/content/examples/notes/locales/fr.json +25 -0
  152. package/dist/content/examples/notes/logic.ts +799 -0
  153. package/dist/content/examples/notes/manifest.json +40 -0
  154. package/dist/content/examples/notes/package.json +16 -0
  155. package/dist/content/examples/notes/style.ocss +469 -0
  156. package/dist/content/examples/notes/submission.json +12 -0
  157. package/dist/content/examples/notes/tests/checks.scenario.json +237 -0
  158. package/dist/content/examples/notes/tests/create.scenario.json +260 -0
  159. package/dist/content/examples/notes/tests/delete.scenario.json +342 -0
  160. package/dist/content/examples/notes/tests/drafts.scenario.json +714 -0
  161. package/dist/content/examples/notes/tests/editor.scenario.json +232 -0
  162. package/dist/content/examples/notes/tests/frame.scenario.json +93 -0
  163. package/dist/content/examples/notes/tests/interactive.scenario.json +344 -0
  164. package/dist/content/examples/notes/tests/limits.scenario.json +1351 -0
  165. package/dist/content/examples/notes/tests/load-logic.mjs +22 -0
  166. package/dist/content/examples/notes/tests/logic.test.mjs +514 -0
  167. package/dist/content/examples/notes/tests/preview.scenario.json +99 -0
  168. package/dist/content/examples/notes/tests/read-only.scenario.json +105 -0
  169. package/dist/content/examples/notes/tests/refused.scenario.json +33 -0
  170. package/dist/content/examples/notes/tests/save.scenario.json +378 -0
  171. package/dist/content/examples/notes/tests/states.scenario.json +640 -0
  172. package/dist/content/examples/notes/tests/typing.scenario.json +562 -0
  173. package/dist/content/examples/notes/tests/unavailable.scenario.json +246 -0
  174. package/dist/content/examples/notes/tsconfig.json +16 -0
  175. package/dist/content/examples/notes/view.ocml +154 -0
  176. package/dist/content/examples/performance/LICENSE +21 -0
  177. package/dist/content/examples/performance/README.md +134 -0
  178. package/dist/content/examples/performance/listing.json +19 -0
  179. package/dist/content/examples/performance/locales/en.json +20 -0
  180. package/dist/content/examples/performance/locales/fr.json +20 -0
  181. package/dist/content/examples/performance/logic.ts +210 -0
  182. package/dist/content/examples/performance/manifest.json +83 -0
  183. package/dist/content/examples/performance/package.json +16 -0
  184. package/dist/content/examples/performance/style.ocss +75 -0
  185. package/dist/content/examples/performance/submission.json +12 -0
  186. package/dist/content/examples/performance/tests/fahrenheit.scenario.json +110 -0
  187. package/dist/content/examples/performance/tests/horizontal.scenario.json +96 -0
  188. package/dist/content/examples/performance/tests/load-logic.mjs +22 -0
  189. package/dist/content/examples/performance/tests/logic.test.mjs +226 -0
  190. package/dist/content/examples/performance/tests/menu.scenario.json +170 -0
  191. package/dist/content/examples/performance/tests/no-fps-source.scenario.json +47 -0
  192. package/dist/content/examples/performance/tests/preview.scenario.json +45 -0
  193. package/dist/content/examples/performance/tests/refused.scenario.json +20 -0
  194. package/dist/content/examples/performance/tests/refused.test.mjs +19 -0
  195. package/dist/content/examples/performance/tests/region.scenario.json +89 -0
  196. package/dist/content/examples/performance/tests/render.scenario.json +112 -0
  197. package/dist/content/examples/performance/tests/sources.scenario.json +151 -0
  198. package/dist/content/examples/performance/tests/stale.scenario.json +111 -0
  199. package/dist/content/examples/performance/tests/telemetry-only.scenario.json +44 -0
  200. package/dist/content/examples/performance/tests/thresholds.scenario.json +147 -0
  201. package/dist/content/examples/performance/tests/waiting.scenario.json +105 -0
  202. package/dist/content/examples/performance/tsconfig.json +16 -0
  203. package/dist/content/examples/performance/view.ocml +18 -0
  204. package/dist/content/examples/playervox-journal/LICENSE +21 -0
  205. package/dist/content/examples/playervox-journal/README.md +150 -0
  206. package/dist/content/examples/playervox-journal/listing.json +19 -0
  207. package/dist/content/examples/playervox-journal/locales/en.json +25 -0
  208. package/dist/content/examples/playervox-journal/locales/fr.json +25 -0
  209. package/dist/content/examples/playervox-journal/logic.ts +556 -0
  210. package/dist/content/examples/playervox-journal/manifest.json +19 -0
  211. package/dist/content/examples/playervox-journal/package.json +16 -0
  212. package/dist/content/examples/playervox-journal/style.ocss +142 -0
  213. package/dist/content/examples/playervox-journal/submission.json +12 -0
  214. package/dist/content/examples/playervox-journal/tests/changes.scenario.json +482 -0
  215. package/dist/content/examples/playervox-journal/tests/delete.scenario.json +432 -0
  216. package/dist/content/examples/playervox-journal/tests/frame.scenario.json +169 -0
  217. package/dist/content/examples/playervox-journal/tests/load-logic.mjs +22 -0
  218. package/dist/content/examples/playervox-journal/tests/logic.test.mjs +349 -0
  219. package/dist/content/examples/playervox-journal/tests/paging.scenario.json +428 -0
  220. package/dist/content/examples/playervox-journal/tests/preview.scenario.json +184 -0
  221. package/dist/content/examples/playervox-journal/tests/read-only.scenario.json +157 -0
  222. package/dist/content/examples/playervox-journal/tests/refused.scenario.json +39 -0
  223. package/dist/content/examples/playervox-journal/tests/scale.scenario.json +286 -0
  224. package/dist/content/examples/playervox-journal/tests/signed-out.scenario.json +134 -0
  225. package/dist/content/examples/playervox-journal/tests/states.scenario.json +741 -0
  226. package/dist/content/examples/playervox-journal/tests/unavailable.scenario.json +183 -0
  227. package/dist/content/examples/playervox-journal/tsconfig.json +16 -0
  228. package/dist/content/examples/playervox-journal/view.ocml +52 -0
  229. package/dist/content/examples/playervox-rating/LICENSE +21 -0
  230. package/dist/content/examples/playervox-rating/README.md +166 -0
  231. package/dist/content/examples/playervox-rating/listing.json +19 -0
  232. package/dist/content/examples/playervox-rating/locales/en.json +35 -0
  233. package/dist/content/examples/playervox-rating/locales/fr.json +35 -0
  234. package/dist/content/examples/playervox-rating/logic.ts +581 -0
  235. package/dist/content/examples/playervox-rating/manifest.json +19 -0
  236. package/dist/content/examples/playervox-rating/package.json +16 -0
  237. package/dist/content/examples/playervox-rating/style.ocss +333 -0
  238. package/dist/content/examples/playervox-rating/submission.json +12 -0
  239. package/dist/content/examples/playervox-rating/tests/account.scenario.json +125 -0
  240. package/dist/content/examples/playervox-rating/tests/bounds.scenario.json +73 -0
  241. package/dist/content/examples/playervox-rating/tests/draft.scenario.json +199 -0
  242. package/dist/content/examples/playervox-rating/tests/form.scenario.json +142 -0
  243. package/dist/content/examples/playervox-rating/tests/load-logic.mjs +22 -0
  244. package/dist/content/examples/playervox-rating/tests/logic.test.mjs +346 -0
  245. package/dist/content/examples/playervox-rating/tests/offline.scenario.json +142 -0
  246. package/dist/content/examples/playervox-rating/tests/preview.scenario.json +44 -0
  247. package/dist/content/examples/playervox-rating/tests/publish-keyboard.scenario.json +221 -0
  248. package/dist/content/examples/playervox-rating/tests/publish-pointer.scenario.json +314 -0
  249. package/dist/content/examples/playervox-rating/tests/read-only.scenario.json +70 -0
  250. package/dist/content/examples/playervox-rating/tests/refused.scenario.json +45 -0
  251. package/dist/content/examples/playervox-rating/tests/states.scenario.json +362 -0
  252. package/dist/content/examples/playervox-rating/tsconfig.json +16 -0
  253. package/dist/content/examples/playervox-rating/view.ocml +62 -0
  254. package/dist/content/examples/playervox-reviews/LICENSE +21 -0
  255. package/dist/content/examples/playervox-reviews/README.md +194 -0
  256. package/dist/content/examples/playervox-reviews/listing.json +19 -0
  257. package/dist/content/examples/playervox-reviews/locales/en.json +32 -0
  258. package/dist/content/examples/playervox-reviews/locales/fr.json +32 -0
  259. package/dist/content/examples/playervox-reviews/logic.ts +822 -0
  260. package/dist/content/examples/playervox-reviews/manifest.json +30 -0
  261. package/dist/content/examples/playervox-reviews/package.json +16 -0
  262. package/dist/content/examples/playervox-reviews/style.ocss +260 -0
  263. package/dist/content/examples/playervox-reviews/submission.json +8 -0
  264. package/dist/content/examples/playervox-reviews/tests/account.scenario.json +249 -0
  265. package/dist/content/examples/playervox-reviews/tests/bounds.scenario.json +336 -0
  266. package/dist/content/examples/playervox-reviews/tests/changes.scenario.json +515 -0
  267. package/dist/content/examples/playervox-reviews/tests/filter.scenario.json +400 -0
  268. package/dist/content/examples/playervox-reviews/tests/frame.scenario.json +185 -0
  269. package/dist/content/examples/playervox-reviews/tests/keyboard.scenario.json +188 -0
  270. package/dist/content/examples/playervox-reviews/tests/load-logic.mjs +22 -0
  271. package/dist/content/examples/playervox-reviews/tests/logic.test.mjs +559 -0
  272. package/dist/content/examples/playervox-reviews/tests/offline-start.scenario.json +152 -0
  273. package/dist/content/examples/playervox-reviews/tests/offline.scenario.json +311 -0
  274. package/dist/content/examples/playervox-reviews/tests/paging.scenario.json +497 -0
  275. package/dist/content/examples/playervox-reviews/tests/preview.scenario.json +286 -0
  276. package/dist/content/examples/playervox-reviews/tests/reading.scenario.json +591 -0
  277. package/dist/content/examples/playervox-reviews/tests/refused.scenario.json +54 -0
  278. package/dist/content/examples/playervox-reviews/tests/scale.scenario.json +303 -0
  279. package/dist/content/examples/playervox-reviews/tests/states.scenario.json +700 -0
  280. package/dist/content/examples/playervox-reviews/tests/unavailable.scenario.json +192 -0
  281. package/dist/content/examples/playervox-reviews/tsconfig.json +16 -0
  282. package/dist/content/examples/playervox-reviews/view.ocml +110 -0
  283. package/dist/content/examples/playervox-score/LICENSE +21 -0
  284. package/dist/content/examples/playervox-score/README.md +131 -0
  285. package/dist/content/examples/playervox-score/listing.json +19 -0
  286. package/dist/content/examples/playervox-score/locales/en.json +23 -0
  287. package/dist/content/examples/playervox-score/locales/fr.json +23 -0
  288. package/dist/content/examples/playervox-score/logic.ts +430 -0
  289. package/dist/content/examples/playervox-score/manifest.json +47 -0
  290. package/dist/content/examples/playervox-score/package.json +16 -0
  291. package/dist/content/examples/playervox-score/style.ocss +247 -0
  292. package/dist/content/examples/playervox-score/submission.json +8 -0
  293. package/dist/content/examples/playervox-score/tests/grades.scenario.json +279 -0
  294. package/dist/content/examples/playervox-score/tests/load-logic.mjs +22 -0
  295. package/dist/content/examples/playervox-score/tests/logic.test.mjs +229 -0
  296. package/dist/content/examples/playervox-score/tests/options.scenario.json +302 -0
  297. package/dist/content/examples/playervox-score/tests/preview.scenario.json +68 -0
  298. package/dist/content/examples/playervox-score/tests/pulse.scenario.json +157 -0
  299. package/dist/content/examples/playervox-score/tests/refused.scenario.json +21 -0
  300. package/dist/content/examples/playervox-score/tests/signed-out.scenario.json +46 -0
  301. package/dist/content/examples/playervox-score/tests/states.scenario.json +450 -0
  302. package/dist/content/examples/playervox-score/tests/unavailable.scenario.json +84 -0
  303. package/dist/content/examples/playervox-score/tsconfig.json +16 -0
  304. package/dist/content/examples/playervox-score/view.ocml +51 -0
  305. package/dist/content/examples/session/LICENSE +21 -0
  306. package/dist/content/examples/session/README.md +57 -0
  307. package/dist/content/examples/session/listing.json +19 -0
  308. package/dist/content/examples/session/locales/en.json +3 -0
  309. package/dist/content/examples/session/locales/fr.json +3 -0
  310. package/dist/content/examples/session/logic.ts +26 -0
  311. package/dist/content/examples/session/manifest.json +19 -0
  312. package/dist/content/examples/session/package.json +16 -0
  313. package/dist/content/examples/session/style.ocss +16 -0
  314. package/dist/content/examples/session/submission.json +8 -0
  315. package/dist/content/examples/session/tests/hidden.scenario.json +45 -0
  316. package/dist/content/examples/session/tests/load-logic.mjs +22 -0
  317. package/dist/content/examples/session/tests/logic.test.mjs +37 -0
  318. package/dist/content/examples/session/tests/preview.scenario.json +28 -0
  319. package/dist/content/examples/session/tests/refused.scenario.json +20 -0
  320. package/dist/content/examples/session/tests/refused.test.mjs +16 -0
  321. package/dist/content/examples/session/tests/render.scenario.json +95 -0
  322. package/dist/content/examples/session/tests/ticks.scenario.json +139 -0
  323. package/dist/content/examples/session/tests/unknown.scenario.json +37 -0
  324. package/dist/content/examples/session/tsconfig.json +16 -0
  325. package/dist/content/examples/session/view.ocml +11 -0
  326. package/dist/content/examples/stopwatch/LICENSE +21 -0
  327. package/dist/content/examples/stopwatch/README.md +99 -0
  328. package/dist/content/examples/stopwatch/listing.json +19 -0
  329. package/dist/content/examples/stopwatch/locales/en.json +8 -0
  330. package/dist/content/examples/stopwatch/locales/fr.json +8 -0
  331. package/dist/content/examples/stopwatch/logic.ts +93 -0
  332. package/dist/content/examples/stopwatch/manifest.json +19 -0
  333. package/dist/content/examples/stopwatch/package.json +16 -0
  334. package/dist/content/examples/stopwatch/style.ocss +54 -0
  335. package/dist/content/examples/stopwatch/submission.json +12 -0
  336. package/dist/content/examples/stopwatch/tests/errors.scenario.json +121 -0
  337. package/dist/content/examples/stopwatch/tests/gesture.scenario.json +154 -0
  338. package/dist/content/examples/stopwatch/tests/hidden.scenario.json +57 -0
  339. package/dist/content/examples/stopwatch/tests/hundredths.scenario.json +173 -0
  340. package/dist/content/examples/stopwatch/tests/load-logic.mjs +22 -0
  341. package/dist/content/examples/stopwatch/tests/logic.test.mjs +99 -0
  342. package/dist/content/examples/stopwatch/tests/preview.scenario.json +36 -0
  343. package/dist/content/examples/stopwatch/tests/read-only.scenario.json +42 -0
  344. package/dist/content/examples/stopwatch/tests/read-only.test.mjs +18 -0
  345. package/dist/content/examples/stopwatch/tests/refused.scenario.json +22 -0
  346. package/dist/content/examples/stopwatch/tests/refused.test.mjs +18 -0
  347. package/dist/content/examples/stopwatch/tests/render.scenario.json +105 -0
  348. package/dist/content/examples/stopwatch/tests/states.scenario.json +246 -0
  349. package/dist/content/examples/stopwatch/tests/unknown.scenario.json +40 -0
  350. package/dist/content/examples/stopwatch/tsconfig.json +16 -0
  351. package/dist/content/examples/stopwatch/view.ocml +29 -0
  352. package/dist/content/examples/twitch-chat/LICENSE +21 -0
  353. package/dist/content/examples/twitch-chat/README.md +283 -0
  354. package/dist/content/examples/twitch-chat/listing.json +19 -0
  355. package/dist/content/examples/twitch-chat/locales/en.json +52 -0
  356. package/dist/content/examples/twitch-chat/locales/fr.json +52 -0
  357. package/dist/content/examples/twitch-chat/logic.ts +887 -0
  358. package/dist/content/examples/twitch-chat/manifest.json +33 -0
  359. package/dist/content/examples/twitch-chat/package.json +16 -0
  360. package/dist/content/examples/twitch-chat/style.ocss +544 -0
  361. package/dist/content/examples/twitch-chat/submission.json +12 -0
  362. package/dist/content/examples/twitch-chat/tests/account.scenario.json +325 -0
  363. package/dist/content/examples/twitch-chat/tests/burst.scenario.json +1866 -0
  364. package/dist/content/examples/twitch-chat/tests/channel-refused.scenario.json +372 -0
  365. package/dist/content/examples/twitch-chat/tests/channel.scenario.json +480 -0
  366. package/dist/content/examples/twitch-chat/tests/draft.scenario.json +279 -0
  367. package/dist/content/examples/twitch-chat/tests/fade.scenario.json +269 -0
  368. package/dist/content/examples/twitch-chat/tests/failures.scenario.json +420 -0
  369. package/dist/content/examples/twitch-chat/tests/favorites.scenario.json +376 -0
  370. package/dist/content/examples/twitch-chat/tests/frame.scenario.json +152 -0
  371. package/dist/content/examples/twitch-chat/tests/lifetime.scenario.json +186 -0
  372. package/dist/content/examples/twitch-chat/tests/load-logic.mjs +22 -0
  373. package/dist/content/examples/twitch-chat/tests/logic.test.mjs +1053 -0
  374. package/dist/content/examples/twitch-chat/tests/passive.scenario.json +536 -0
  375. package/dist/content/examples/twitch-chat/tests/preview.scenario.json +147 -0
  376. package/dist/content/examples/twitch-chat/tests/read-only.scenario.json +202 -0
  377. package/dist/content/examples/twitch-chat/tests/read-only.test.mjs +63 -0
  378. package/dist/content/examples/twitch-chat/tests/refused.scenario.json +65 -0
  379. package/dist/content/examples/twitch-chat/tests/refused.test.mjs +43 -0
  380. package/dist/content/examples/twitch-chat/tests/render.scenario.json +347 -0
  381. package/dist/content/examples/twitch-chat/tests/reply.scenario.json +384 -0
  382. package/dist/content/examples/twitch-chat/tests/send-refused.scenario.json +383 -0
  383. package/dist/content/examples/twitch-chat/tests/send.scenario.json +300 -0
  384. package/dist/content/examples/twitch-chat/tests/states.scenario.json +455 -0
  385. package/dist/content/examples/twitch-chat/tests/unavailable.scenario.json +256 -0
  386. package/dist/content/examples/twitch-chat/tests/unread.scenario.json +997 -0
  387. package/dist/content/examples/twitch-chat/tsconfig.json +16 -0
  388. package/dist/content/examples/twitch-chat/view.ocml +141 -0
  389. package/dist/content/examples/warframe-market/LICENSE +21 -0
  390. package/dist/content/examples/warframe-market/README.md +176 -0
  391. package/dist/content/examples/warframe-market/listing.json +19 -0
  392. package/dist/content/examples/warframe-market/locales/en.json +44 -0
  393. package/dist/content/examples/warframe-market/locales/fr.json +44 -0
  394. package/dist/content/examples/warframe-market/logic.ts +1265 -0
  395. package/dist/content/examples/warframe-market/manifest.json +92 -0
  396. package/dist/content/examples/warframe-market/package.json +16 -0
  397. package/dist/content/examples/warframe-market/style.ocss +422 -0
  398. package/dist/content/examples/warframe-market/submission.json +24 -0
  399. package/dist/content/examples/warframe-market/tests/bounds.scenario.json +60 -0
  400. package/dist/content/examples/warframe-market/tests/cached.scenario.json +70 -0
  401. package/dist/content/examples/warframe-market/tests/detail.scenario.json +251 -0
  402. package/dist/content/examples/warframe-market/tests/errors.scenario.json +105 -0
  403. package/dist/content/examples/warframe-market/tests/fixtures.json +295 -0
  404. package/dist/content/examples/warframe-market/tests/load-logic.mjs +22 -0
  405. package/dist/content/examples/warframe-market/tests/logic.test.mjs +505 -0
  406. package/dist/content/examples/warframe-market/tests/no-clipboard.scenario.json +104 -0
  407. package/dist/content/examples/warframe-market/tests/passive.scenario.json +87 -0
  408. package/dist/content/examples/warframe-market/tests/preview.scenario.json +146 -0
  409. package/dist/content/examples/warframe-market/tests/refresh.scenario.json +56 -0
  410. package/dist/content/examples/warframe-market/tests/refused.scenario.json +74 -0
  411. package/dist/content/examples/warframe-market/tests/render.scenario.json +210 -0
  412. package/dist/content/examples/warframe-market/tests/search.scenario.json +189 -0
  413. package/dist/content/examples/warframe-market/tests/unavailable.scenario.json +54 -0
  414. package/dist/content/examples/warframe-market/tsconfig.json +16 -0
  415. package/dist/content/examples/warframe-market/view.ocml +116 -0
  416. package/dist/content/examples/weather/LICENSE +20 -0
  417. package/dist/content/examples/weather/listing.json +10 -0
  418. package/dist/content/examples/weather/locales/en.json +9 -0
  419. package/dist/content/examples/weather/locales/fr.json +9 -0
  420. package/dist/content/examples/weather/logic.ts +62 -0
  421. package/dist/content/examples/weather/manifest.json +51 -0
  422. package/dist/content/examples/weather/package.json +15 -0
  423. package/dist/content/examples/weather/style.ocss +29 -0
  424. package/dist/content/examples/weather/submission.json +17 -0
  425. package/dist/content/examples/weather/tsconfig.json +16 -0
  426. package/dist/content/examples/weather/view.ocml +12 -0
  427. package/dist/content/index.json +3705 -0
  428. package/dist/content/reference/errors.json +1924 -0
  429. package/dist/content/reference/limits.json +1154 -0
  430. package/dist/content/reference/manifest.md +223 -0
  431. package/dist/content/reference/permissions.json +413 -0
  432. package/dist/content/templates/blank/locales/en.json +3 -0
  433. package/dist/content/templates/blank/locales/fr.json +3 -0
  434. package/dist/content/templates/blank/logic.ts +7 -0
  435. package/dist/content/templates/blank/manifest.json +16 -0
  436. package/dist/content/templates/blank/style.ocss +10 -0
  437. package/dist/content/templates/blank/tests/example.scenario.json +10 -0
  438. package/dist/content/templates/blank/view.ocml +6 -0
  439. package/dist/content/templates/chart/locales/en.json +3 -0
  440. package/dist/content/templates/chart/locales/fr.json +3 -0
  441. package/dist/content/templates/chart/logic.ts +27 -0
  442. package/dist/content/templates/chart/manifest.json +16 -0
  443. package/dist/content/templates/chart/style.ocss +27 -0
  444. package/dist/content/templates/chart/tests/example.scenario.json +10 -0
  445. package/dist/content/templates/chart/view.ocml +10 -0
  446. package/dist/content/templates/counter/locales/en.json +4 -0
  447. package/dist/content/templates/counter/locales/fr.json +4 -0
  448. package/dist/content/templates/counter/logic.ts +20 -0
  449. package/dist/content/templates/counter/manifest.json +16 -0
  450. package/dist/content/templates/counter/style.ocss +26 -0
  451. package/dist/content/templates/counter/tests/example.scenario.json +11 -0
  452. package/dist/content/templates/counter/view.ocml +13 -0
  453. package/dist/content/templates/list/locales/en.json +8 -0
  454. package/dist/content/templates/list/locales/fr.json +8 -0
  455. package/dist/content/templates/list/logic.ts +35 -0
  456. package/dist/content/templates/list/manifest.json +16 -0
  457. package/dist/content/templates/list/style.ocss +42 -0
  458. package/dist/content/templates/list/tests/example.scenario.json +10 -0
  459. package/dist/content/templates/list/view.ocml +17 -0
  460. package/dist/content/templates/shared/LICENSE +20 -0
  461. package/dist/content/templates/shared/package.json +14 -0
  462. package/dist/content/templates/shared/tsconfig.json +16 -0
  463. package/dist/content.js +68 -0
  464. package/dist/env.js +156 -0
  465. package/dist/fingerprint.js +32 -0
  466. package/dist/hidden.js +47 -0
  467. package/dist/ids.js +27 -0
  468. package/dist/index.js +82 -0
  469. package/dist/knowledge.js +222 -0
  470. package/dist/npm.js +149 -0
  471. package/dist/prompts.js +47 -0
  472. package/dist/resources.js +82 -0
  473. package/dist/run.js +120 -0
  474. package/dist/server.js +43 -0
  475. package/dist/session.js +205 -0
  476. package/dist/sources.js +218 -0
  477. package/dist/text.js +80 -0
  478. package/dist/texts.js +44 -0
  479. package/dist/tools/audit.js +105 -0
  480. package/dist/tools/build.js +453 -0
  481. package/dist/tools/common.js +122 -0
  482. package/dist/tools/docs.js +196 -0
  483. package/dist/tools/preview.js +87 -0
  484. package/dist/tools/project.js +183 -0
  485. package/dist/tools/setup.js +146 -0
  486. package/dist/tools/submission.js +369 -0
  487. package/dist/version.js +3 -0
  488. package/npm-shrinkwrap.json +402 -0
  489. package/package.json +50 -4
@@ -0,0 +1,81 @@
1
+ # Widgets de référence
2
+
3
+ Les widgets intégrés de PlayerVox OverCrow sont des widgets ordinaires,
4
+ écrits avec le SDK public, empaquetés par `overcrow-widget` et publiés dans
5
+ le catalogue signé comme les vôtres. Leurs sources se trouvent dans
6
+ [`widgets/`](../../../widgets/), dans le dépôt public, sous licence MIT :
7
+ lisez-les, copiez-les et servez-vous-en comme point de départ.
8
+
9
+ <!-- generated:widgets -->
10
+ | Widget | Description | ID | Permissions | Sources |
11
+ | --- | --- | --- | --- | --- |
12
+ | **Horloge** | Affiche l’heure locale et, en option, la date, au format 24 heures. | `com.playervox.overcrow.clock` | aucune | [widgets/clock/](../../../widgets/clock/) |
13
+ | **FPS** | Affiche la fréquence d’images présentée par le jeu, quand l’hôte dispose d’une source. | `com.playervox.overcrow.fps` | `fps.read` | [widgets/fps/](../../../widgets/fps/) |
14
+ | **Média** | Le morceau que joue votre lecteur de musique, avec sa pochette, et les boutons précédent, lecture/pause et suivant en mode interactif. | `com.playervox.overcrow.media` | `media.read`, `media.control` | [widgets/media/](../../../widgets/media/) |
15
+ | **Notes** | Vos notes et listes de tâches par-dessus le jeu : jusqu’à huit notes, chacune avec un texte libre et une liste de tâches, les mêmes pour tous les jeux. Lisez-les en mode passif ; en mode interactif, choisissez, créez, supprimez et modifiez-les dans le widget, et cochez les éléments. Elles restent sur cet ordinateur. | `com.playervox.overcrow.notes` | `notes.read`, `notes.write` | [widgets/notes/](../../../widgets/notes/) |
16
+ | **Performances** | CPU et mémoire du jeu, et les températures que cet ordinateur expose. | `com.playervox.overcrow.performance` | `telemetry.read`, `fps.read` | [widgets/performance/](../../../widgets/performance/) |
17
+ | **Journal de sessions** | Les sessions de jeu terminées de votre jeu, de la plus récente à la plus ancienne : date, heure de début et durée, cinq par page. Enregistrées sur votre appareil sans compte, fusionnées avec votre journal PlayerVox si vous synchronisez. Supprimez une session après confirmation. | `com.playervox.overcrow.playervox.journal` | `journal.read`, `journal.delete` | [widgets/playervox-journal/](../../../widgets/playervox-journal/) |
18
+ | **Ma note** | Votre note PlayerVox du jeu Steam auquel vous jouez : son grade et son score, et en mode interactif trois critères et un avis facultatif à publier ou mettre à jour. Nécessite votre compte PlayerVox. | `com.playervox.overcrow.playervox.rating` | `playervox.rating.read`, `playervox.rating.write` | [widgets/playervox-rating/](../../../widgets/playervox-rating/) |
19
+ | **Avis des joueurs** | Ce que les joueurs de PlayerVox pensent du jeu auquel vous jouez : trois avis par page avec la note et le score de chaque joueur, dans votre langue quand une traduction existe. Limitez-les aux joueurs que vous suivez depuis le menu du widget. Nécessite votre compte PlayerVox. | `com.playervox.overcrow.playervox.reviews` | `playervox.reviews.read` | [widgets/playervox-reviews/](../../../widgets/playervox-reviews/) |
20
+ | **Note PlayerVox** | La note de la communauté PlayerVox pour votre jeu Steam, avec son score, son nombre de votes et trois critères. Sans compte ; le badge reste toujours visible. | `com.playervox.overcrow.playervox.score` | `playervox.score.read` | [widgets/playervox-score/](../../../widgets/playervox-score/) |
21
+ | **Session** | Affiche la durée de la session de jeu en cours. | `com.playervox.overcrow.session` | `session.read` | [widgets/session/](../../../widgets/session/) |
22
+ | **Chronomètre** | Un chronomètre au centième de seconde, démarré, mis en pause et réinitialisé par ses boutons ou les raccourcis de l’hôte. | `com.playervox.overcrow.stopwatch` | `stopwatch.read`, `stopwatch.control` | [widgets/stopwatch/](../../../widgets/stopwatch/) |
23
+ | **Chat Twitch** | Lisez et envoyez des messages dans le chat Twitch public de votre choix : vos chaînes favorites, l’historique défilant avec emotes et réponses en mode interactif, les derniers messages qui s’effacent en mode passif. Nécessite votre compte Twitch. | `com.playervox.overcrow.twitch.chat` | `twitch.chat.read`, `twitch.chat.compose` | [widgets/twitch-chat/](../../../widgets/twitch-chat/) |
24
+ | **Marché Warframe** | Recherche les objets PC publics dans un catalogue en cache, affiche les vendeurs et acheteurs en ligne d’un objet dans deux onglets et copie un message d’échange sur un clic. | `com.playervox.overcrow.warframe.market` | `network`, `storage`, `clipboardWrite` | [widgets/warframe-market/](../../../widgets/warframe-market/) |
25
+ <!-- /generated:widgets -->
26
+
27
+ ## Ce que contient le dossier d’un widget
28
+
29
+ - les sources du paquet : `manifest.json`, `view.ocml`, `style.ocss`,
30
+ `logic.ts`, `locales/`, `LICENSE` ;
31
+ - `listing.json`, son texte pour la marketplace ;
32
+ - `assets/preview.png`, son aperçu dans la marketplace : l’image de son
33
+ scénario `preview`, cadrée et mise en scène par
34
+ `node scripts/compose-previews.mjs` ;
35
+ - `tests/` : les tests unitaires de la logique, et des scénarios avec leurs
36
+ images de référence dans les deux thèmes, les deux langues et deux
37
+ échelles, joués par `overcrow-widget test` dans le runtime headless
38
+ d’OverCrow ;
39
+ - `README.md` : ce qu’il affiche, son menu, ses permissions, son
40
+ fonctionnement et son coût.
41
+
42
+ ## Ce que chacun montre
43
+
44
+ | Pour voir comment… | Lisez |
45
+ | --- | --- |
46
+ | se déclencher à chaque minute ou seconde de l’heure locale, suivre une option du menu | Horloge |
47
+ | s’abonner à un service et afficher une valeur manquante | FPS, Session |
48
+ | disposer une liste de valeurs en grille, masquer une ligne du menu que la machine ne peut pas alimenter | Performances |
49
+ | afficher une image fournie par OverCrow, relancer un abonnement qui s’est terminé | Média |
50
+ | commander un service sur une action de l’utilisateur, laisser OverCrow faire avancer une durée | Chronomètre |
51
+ | modifier du texte avec un formulaire lié à un intent d’écriture, conserver des brouillons | Notes, Ma note |
52
+ | dessiner sur un canvas | Note PlayerVox, Ma note |
53
+ | parcourir un service page par page et réagir à une révision | Avis des joueurs, Journal de sessions |
54
+ | maintenir une longue liste défilante sur sa fin, envoyer un message | Chat Twitch |
55
+ | appeler une API HTTP, la mettre en cache dans le stockage, copier dans le presse-papiers | Marché Warframe |
56
+
57
+ Marché Warframe n’est pas un widget intégré : widget PlayerVox du catalogue,
58
+ installé à la demande, il montre des routes réseau avec une limite de
59
+ réponse déclarée, le stockage pour un catalogue en cache et une copie dans
60
+ le presse-papiers sur un clic.
61
+
62
+ ## Travailler sur l’un d’eux
63
+
64
+ Depuis une copie de travail du dépôt, liez aux widgets le SDK de cette
65
+ révision, puis vérifiez l’un d’eux, empaquetez-le et lancez ses tests
66
+ unitaires :
67
+
68
+ ```sh
69
+ node scripts/prepare-widgets.mjs
70
+ overcrow-widget check widgets/clock
71
+ overcrow-widget package widgets/clock
72
+ node --test widgets/clock/tests/logic.test.mjs
73
+ ```
74
+
75
+ `prepare-widgets.mjs` demande que le SDK soit construit d’abord (`npm ci`
76
+ puis `npm run build` dans `sdk/`). Les quatre templates
77
+ d’`overcrow-widget init` se trouvent dans
78
+ [`templates/`](../../../templates/), et deux exemples complets, écrits pour
79
+ ces pages, dans [`docs/content/examples/`](../examples/) : `weather` appelle
80
+ une API HTTP et `countdown` utilise un minuteur, un canvas, un menu
81
+ contextuel et le stockage.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Valhallab SASU
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,75 @@
1
+ # Clock
2
+
3
+ `com.playervox.overcrow.clock` — the local time of day and, optionally, the
4
+ date on a second line. A built-in of OverCrow, written against the public
5
+ `@overcrow/sdk` and packaged with `overcrow-widget` like any creator's
6
+ widget. MIT.
7
+
8
+ ## What it shows
9
+
10
+ | State | Shows |
11
+ | --- | --- |
12
+ | Default | `14:08` over `17/07/2026` |
13
+ | Seconds on | `14:08:42` |
14
+ | Date off | the time alone |
15
+ | Date format | `dd/mm/yyyy` (default), `yyyy-mm-dd` or `mm/dd/yyyy`, whatever the user's regional date order |
16
+
17
+ Always 24-hour and zero padded, in English and French alike. The time is
18
+ local: the VM's clock is UTC, and the SDK applies the host's UTC offset
19
+ (`host.region`), which the host sends again at each summer time change.
20
+
21
+ ## Menu
22
+
23
+ | Row | Type | Default |
24
+ | --- | --- | --- |
25
+ | Show seconds / Afficher les secondes | toggle `show-seconds` | off |
26
+ | Show date / Afficher la date | toggle `show-date` | on |
27
+ | Date format / Format de date | choice `date-format`, shown while the date is | `day-month-year` |
28
+
29
+ ## Permissions
30
+
31
+ None. The widget reads no service.
32
+
33
+ ## How it works
34
+
35
+ - `timers.atEach("minute" | "second", tick)`: one repeating host timer
36
+ aligned on the local boundary, one VM turn per tick; a tick that drifted
37
+ re-aligns it. No tick while hidden; the time is current at once when the
38
+ widget is shown again.
39
+ - `onHost`: a menu change re-arms the timer at the new unit at once, and a
40
+ new UTC offset shows at once.
41
+ - The accessible label is "Local time {time}, {date}" /
42
+ "Heure locale {time}, {date}".
43
+
44
+ ## Tests
45
+
46
+ - `tests/logic.test.mjs`: the logic on `@overcrow/sdk/testing` (formats,
47
+ defaults, the timer and its re-arming).
48
+ - Scenarios, played by `overcrow-widget test` in OverCrow's headless
49
+ runtime, with their reference images: `render` (both themes and
50
+ languages at 100 and 150 %), `options` (each menu row), `ticks` (minutes,
51
+ seconds, midnight), `hidden`, `summer-time` (both changes).
52
+
53
+ ```sh
54
+ node ../../scripts/prepare-widgets.mjs
55
+ overcrow-widget check && overcrow-widget package
56
+ node --test tests/*.test.mjs
57
+ overcrow-widget test --runtime <overcrow-widget-headless>
58
+ ```
59
+
60
+ ## Cost
61
+
62
+ Measured on 2026-09-30 with OverCrow's release build, on an AMD Ryzen 7
63
+ 5800X3D Linux workstation and in a Windows 11 virtual machine (2 vCPU):
64
+
65
+ | | Linux | Windows (VM) |
66
+ | --- | --- | --- |
67
+ | VM start (spawn → ready) | 1.9 ms | 13.5–14.5 ms, sandboxed |
68
+ | Widget start, warm, into the overlay's runtime | 7 ms at most | — |
69
+ | VM memory | 0.55 MiB anonymous | 0.83 MiB private working set |
70
+ | VM CPU per tick, seconds shown | about 95 µs, one VM turn | — |
71
+ | Overlay frames | one each minute (each second with seconds) | — |
72
+
73
+ With the Session and FPS widgets beside it, the overlay's process grows by
74
+ about 2 MB per widget and stays at 0.1 % of one core; nothing runs while
75
+ the overlay is hidden.
@@ -0,0 +1,19 @@
1
+ {
2
+ "author": "PlayerVox",
3
+ "spdxLicense": "MIT",
4
+ "sourceUrl": "https://github.com/Valhallab/playervox-overcrow-releases/tree/main/widgets/clock",
5
+ "preview": "assets/preview.png",
6
+ "defaultLocale": "en",
7
+ "localizations": [
8
+ {
9
+ "locale": "en",
10
+ "name": "Clock",
11
+ "description": "Shows the local time of day and, optionally, the date, in a 24-hour format."
12
+ },
13
+ {
14
+ "locale": "fr",
15
+ "name": "Horloge",
16
+ "description": "Affiche l’heure locale et, en option, la date, au format 24 heures."
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "Local time {time}",
3
+ "label-date": "Local time {time}, {date}"
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "label": "Heure locale {time}",
3
+ "label-date": "Heure locale {time}, {date}"
4
+ }
@@ -0,0 +1,85 @@
1
+ // Clock: the local time of day, 24-hour, and the date in the order the user
2
+ // chose in the widget menu. The VM's clock is UTC: the SDK formats from the
3
+ // host's UTC offset, and its timer wakes at each minute (or second) of local
4
+ // time.
5
+ import {
6
+ formatDate,
7
+ formatTime,
8
+ initState,
9
+ onHost,
10
+ option,
11
+ t,
12
+ timers,
13
+ type DateOrder,
14
+ type Timer,
15
+ } from "@overcrow/sdk";
16
+
17
+ /** The `date-format` menu values and the date order each one means. */
18
+ export const DATE_ORDERS: Readonly<Record<string, DateOrder>> = {
19
+ "day-month-year": "dmy",
20
+ "year-month-day": "ymd",
21
+ "month-day-year": "mdy",
22
+ };
23
+
24
+ declare module "@overcrow/sdk" {
25
+ interface WidgetState {
26
+ now: number;
27
+ seconds: boolean;
28
+ showDate: boolean;
29
+ order: DateOrder;
30
+ }
31
+ }
32
+
33
+ /** The menu values, with their defaults. */
34
+ export function menuValues(): { seconds: boolean; showDate: boolean; order: DateOrder } {
35
+ return {
36
+ seconds: option("show-seconds", false),
37
+ showDate: option("show-date", true),
38
+ order: DATE_ORDERS[option("date-format", "day-month-year")] ?? "dmy",
39
+ };
40
+ }
41
+
42
+ const state = initState({ now: Date.now(), ...menuValues() });
43
+
44
+ export function clockTime(now: number, seconds: boolean): string {
45
+ return formatTime(now, { seconds });
46
+ }
47
+
48
+ export function clockDate(now: number, order: DateOrder): string {
49
+ return formatDate(now, { order });
50
+ }
51
+
52
+ export function clockLabel(now: number, seconds: boolean, showDate: boolean, order: DateOrder): string {
53
+ const time = clockTime(now, seconds);
54
+ return showDate ? t("label-date", { time, date: clockDate(now, order) }) : t("label", { time });
55
+ }
56
+
57
+ let clock: Timer | undefined;
58
+
59
+ function tick(): void {
60
+ state.now = Date.now();
61
+ }
62
+
63
+ /** Ticks at each second or minute of local time, and shows the time now. */
64
+ function start(): void {
65
+ clock?.cancel();
66
+ clock = timers.atEach(state.seconds ? "second" : "minute", tick);
67
+ tick();
68
+ }
69
+
70
+ onHost((changed) => {
71
+ if (changed.includes("options")) {
72
+ const values = menuValues();
73
+ const unitChanged = values.seconds !== state.seconds;
74
+ Object.assign(state, values);
75
+ if (unitChanged) {
76
+ start();
77
+ }
78
+ }
79
+ // A new UTC offset (time zone or summer time) shows at once.
80
+ if (changed.includes("region")) {
81
+ tick();
82
+ }
83
+ });
84
+
85
+ start();
@@ -0,0 +1,44 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "apiVersion": 1,
4
+ "id": "com.playervox.overcrow.clock",
5
+ "version": "1.0.2",
6
+ "name": {
7
+ "en": "Clock",
8
+ "fr": "Horloge"
9
+ },
10
+ "sizing": {
11
+ "fit": "both",
12
+ "preferred": { "width": 110, "height": 60 },
13
+ "min": { "width": 40, "height": 24 },
14
+ "max": { "width": 480, "height": 240 }
15
+ },
16
+ "wrapper": {
17
+ "menu": [
18
+ {
19
+ "type": "toggle",
20
+ "id": "show-seconds",
21
+ "label": { "en": "Show seconds", "fr": "Afficher les secondes" },
22
+ "default": false
23
+ },
24
+ {
25
+ "type": "toggle",
26
+ "id": "show-date",
27
+ "label": { "en": "Show date", "fr": "Afficher la date" },
28
+ "default": true
29
+ },
30
+ {
31
+ "type": "choice",
32
+ "id": "date-format",
33
+ "label": { "en": "Date format", "fr": "Format de date" },
34
+ "visibleWhen": "show-date",
35
+ "choices": [
36
+ { "value": "day-month-year", "label": { "en": "dd/mm/yyyy", "fr": "jj/mm/aaaa" } },
37
+ { "value": "year-month-day", "label": { "en": "yyyy-mm-dd", "fr": "aaaa-mm-jj" } },
38
+ { "value": "month-day-year", "label": { "en": "mm/dd/yyyy", "fr": "mm/jj/aaaa" } }
39
+ ],
40
+ "default": "day-month-year"
41
+ }
42
+ ]
43
+ }
44
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "overcrow-widget-clock",
3
+ "version": "1.0.2",
4
+ "private": true,
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "scripts": {
8
+ "check": "overcrow-widget check",
9
+ "package": "overcrow-widget package",
10
+ "test": "node --test tests/*.test.mjs"
11
+ },
12
+ "devDependencies": {
13
+ "@overcrow/sdk": "1.0.0",
14
+ "typescript": "6.0.3"
15
+ }
16
+ }
@@ -0,0 +1,26 @@
1
+ /* One compact column: the time over the date, 1 px apart. The wrapper
2
+ draws the panel and its 8 px margin; the content adds 2 px on the
3
+ sides: the built-in's 10 × 8 px margin. */
4
+ .clock {
5
+ flex-direction: column;
6
+ align-items: start;
7
+ row-gap: 1px;
8
+ padding: 0 2px;
9
+ }
10
+
11
+ /* Values use the UI font with tabular figures, so they never shift. */
12
+ .time {
13
+ font-family: var(--font-ui);
14
+ font-size: var(--font-size-value);
15
+ font-variant-numeric: tabular-nums;
16
+ color: var(--color-text);
17
+ white-space: nowrap;
18
+ }
19
+
20
+ .date {
21
+ font-family: var(--font-ui);
22
+ font-size: var(--font-size-small);
23
+ font-variant-numeric: tabular-nums;
24
+ color: var(--color-text-muted);
25
+ white-space: nowrap;
26
+ }
@@ -0,0 +1,68 @@
1
+ {
2
+ "scenarioVersion": 1,
3
+ "name": "hidden",
4
+ "description": "Hidden, the clock gets no tick; shown again, it shows the current time at once.",
5
+ "host": {
6
+ "zone": {
7
+ "offsetMinutes": 120
8
+ },
9
+ "startAt": 1784290122000,
10
+ "options": {
11
+ "show-seconds": true
12
+ }
13
+ },
14
+ "steps": [
15
+ {
16
+ "expect": {
17
+ "text": [
18
+ "14:08:42"
19
+ ]
20
+ }
21
+ },
22
+ {
23
+ "host": {
24
+ "visible": false
25
+ }
26
+ },
27
+ {
28
+ "advance": {
29
+ "ms": 300000
30
+ }
31
+ },
32
+ {
33
+ "expect": {
34
+ "text": [
35
+ "14:08:42"
36
+ ],
37
+ "noText": [
38
+ "14:13:42"
39
+ ]
40
+ }
41
+ },
42
+ {
43
+ "host": {
44
+ "visible": true
45
+ }
46
+ },
47
+ {
48
+ "expect": {
49
+ "text": [
50
+ "14:13:42"
51
+ ]
52
+ }
53
+ },
54
+ {
55
+ "advance": {
56
+ "ms": 1000
57
+ }
58
+ },
59
+ {
60
+ "expect": {
61
+ "text": [
62
+ "14:13:43"
63
+ ],
64
+ "fault": "none"
65
+ }
66
+ }
67
+ ]
68
+ }
@@ -0,0 +1,22 @@
1
+ // Compiles this widget's logic.ts with the project's TypeScript into
2
+ // dist/ and imports it, after the test installed its runtime
3
+ // (`@overcrow/sdk/testing`), as the VM runs logic.js after its prelude.
4
+ import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
5
+ import ts from "typescript";
6
+
7
+ export async function loadLogic() {
8
+ const root = new URL("../", import.meta.url);
9
+ const source = readFileSync(new URL("logic.ts", root), "utf8");
10
+ const { outputText } = ts.transpileModule(source, {
11
+ compilerOptions: {
12
+ module: ts.ModuleKind.ES2022,
13
+ target: ts.ScriptTarget.ES2023,
14
+ verbatimModuleSyntax: true,
15
+ },
16
+ });
17
+ mkdirSync(new URL("dist/", root), { recursive: true });
18
+ // One file per test process: test files run in parallel.
19
+ const output = new URL(`dist/logic-${process.pid}.mjs`, root);
20
+ writeFileSync(output, outputText);
21
+ return import(output.href);
22
+ }
@@ -0,0 +1,89 @@
1
+ // Unit tests of the Clock's logic on @overcrow/sdk/testing: virtual time,
2
+ // the host's region and menu values, no VM.
3
+ import assert from "node:assert/strict";
4
+ import { test } from "node:test";
5
+ import { installRuntime } from "@overcrow/sdk/testing";
6
+
7
+ import { loadLogic } from "./load-logic.mjs";
8
+
9
+ // 14:08:42.250 in UTC+2, 2026-07-17.
10
+ const START = Date.UTC(2026, 6, 17, 12, 8, 42, 250);
11
+ const vm = installRuntime({
12
+ now: START,
13
+ host: {
14
+ region: { numberFormat: "us", dateOrder: "mdy", offsetMinutes: 120 },
15
+ messages: { label: "Local time {time}", "label-date": "Local time {time}, {date}" },
16
+ },
17
+ });
18
+ const logic = await loadLogic();
19
+ const { state } = await import("@overcrow/sdk");
20
+
21
+ test("defaults: date on, day/month/year, no seconds, whatever the region's order", () => {
22
+ assert.deepEqual(
23
+ { seconds: state.seconds, showDate: state.showDate, order: state.order },
24
+ { seconds: false, showDate: true, order: "dmy" },
25
+ );
26
+ assert.equal(logic.clockTime(state.now, state.seconds), "14:08");
27
+ assert.equal(logic.clockDate(state.now, state.order), "17/07/2026");
28
+ assert.equal(
29
+ logic.clockLabel(state.now, false, true, "dmy"),
30
+ "Local time 14:08, 17/07/2026",
31
+ );
32
+ assert.equal(logic.clockLabel(state.now, true, false, "dmy"), "Local time 14:08:42");
33
+ });
34
+
35
+ test("the three date formats and an unknown stored value", () => {
36
+ const formats = {};
37
+ for (const [value, order] of Object.entries(logic.DATE_ORDERS)) {
38
+ formats[value] = logic.clockDate(START, order);
39
+ }
40
+ assert.deepEqual(formats, {
41
+ "day-month-year": "17/07/2026",
42
+ "year-month-day": "2026-07-17",
43
+ "month-day-year": "07/17/2026",
44
+ });
45
+ vm.setHost({ options: { "date-format": "week-day" } });
46
+ assert.equal(state.order, "dmy", "an unknown value falls back to the default");
47
+ vm.setHost({ options: {} });
48
+ });
49
+
50
+ test("24-hour, zero padded", () => {
51
+ const night = Date.UTC(2026, 0, 1, 23, 5, 9);
52
+ assert.equal(logic.clockTime(night, true), "01:05:09");
53
+ assert.equal(logic.clockTime(Date.UTC(2026, 0, 1, 11, 0, 0), false), "13:00");
54
+ });
55
+
56
+ test("one timer at the next local minute, then each minute", () => {
57
+ assert.equal(vm.timers.length, 1);
58
+ assert.equal(vm.timers[0].dueAt, Date.UTC(2026, 6, 17, 12, 9));
59
+ vm.advance(Date.UTC(2026, 6, 17, 12, 9) - vm.now);
60
+ assert.equal(logic.clockTime(state.now, state.seconds), "14:09");
61
+ assert.deepEqual(
62
+ vm.timers.map(({ intervalMs, repeat }) => ({ intervalMs, repeat })),
63
+ [{ intervalMs: 60_000, repeat: true }],
64
+ );
65
+ assert.equal(vm.advance(120_000), 2);
66
+ assert.equal(logic.clockTime(state.now, state.seconds), "14:11");
67
+ });
68
+
69
+ test("turning seconds on re-arms at once on seconds, and off again on minutes", () => {
70
+ vm.advance(7_500);
71
+ vm.setHost({ options: { "show-seconds": true } });
72
+ assert.equal(state.seconds, true);
73
+ assert.equal(logic.clockTime(state.now, state.seconds), "14:11:07", "shown at once");
74
+ assert.equal(vm.timers.length, 1, "the minute timer is gone");
75
+ vm.advance(500);
76
+ assert.equal(logic.clockTime(state.now, state.seconds), "14:11:08");
77
+ vm.advance(1_000);
78
+ assert.equal(logic.clockTime(state.now, state.seconds), "14:11:09");
79
+ vm.setHost({ options: { "show-seconds": false, "show-date": false } });
80
+ assert.equal(state.showDate, false);
81
+ assert.equal(vm.timers.length, 1);
82
+ assert.equal(vm.timers[0].dueAt, Date.UTC(2026, 6, 17, 12, 12));
83
+ vm.setHost({ options: {} });
84
+ });
85
+
86
+ test("a new UTC offset shows at once", () => {
87
+ vm.setHost({ region: { numberFormat: "us", dateOrder: "mdy", offsetMinutes: -240 } });
88
+ assert.equal(logic.clockTime(state.now, state.seconds), "08:11");
89
+ });
@@ -0,0 +1,108 @@
1
+ {
2
+ "scenarioVersion": 1,
3
+ "name": "options",
4
+ "description": "Each menu row, applied from the menu at 14:08:42 local time: seconds, the three date orders, the date hidden.",
5
+ "host": {
6
+ "zone": {
7
+ "offsetMinutes": 120
8
+ },
9
+ "startAt": 1784290122000
10
+ },
11
+ "steps": [
12
+ {
13
+ "menu": {
14
+ "id": "show-seconds",
15
+ "value": true
16
+ }
17
+ },
18
+ {
19
+ "expect": {
20
+ "text": [
21
+ "14:08:42",
22
+ "17/07/2026"
23
+ ],
24
+ "image": "seconds-dark"
25
+ }
26
+ },
27
+ {
28
+ "host": {
29
+ "theme": "light"
30
+ }
31
+ },
32
+ {
33
+ "expect": {
34
+ "image": "seconds-light"
35
+ }
36
+ },
37
+ {
38
+ "host": {
39
+ "theme": "dark"
40
+ }
41
+ },
42
+ {
43
+ "menu": {
44
+ "id": "show-seconds",
45
+ "value": false
46
+ }
47
+ },
48
+ {
49
+ "menu": {
50
+ "id": "date-format",
51
+ "value": "year-month-day"
52
+ }
53
+ },
54
+ {
55
+ "expect": {
56
+ "text": [
57
+ "14:08",
58
+ "2026-07-17"
59
+ ],
60
+ "image": "year-month-day"
61
+ }
62
+ },
63
+ {
64
+ "menu": {
65
+ "id": "date-format",
66
+ "value": "month-day-year"
67
+ }
68
+ },
69
+ {
70
+ "expect": {
71
+ "text": [
72
+ "14:08",
73
+ "07/17/2026"
74
+ ],
75
+ "image": "month-day-year"
76
+ }
77
+ },
78
+ {
79
+ "menu": {
80
+ "id": "show-date",
81
+ "value": false
82
+ }
83
+ },
84
+ {
85
+ "expect": {
86
+ "text": [
87
+ "14:08"
88
+ ],
89
+ "noText": [
90
+ "07/17/2026"
91
+ ],
92
+ "image": "time-only-dark"
93
+ }
94
+ },
95
+ {
96
+ "host": {
97
+ "theme": "light",
98
+ "scale": 1500
99
+ }
100
+ },
101
+ {
102
+ "expect": {
103
+ "image": "time-only-light-150",
104
+ "fault": "none"
105
+ }
106
+ }
107
+ ]
108
+ }