@overcrow/mcp 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (461) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +90 -2
  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 +353 -0
  15. package/dist/content/docs/en/dev-channel.md +130 -0
  16. package/dist/content/docs/en/elements.md +469 -0
  17. package/dist/content/docs/en/forms.md +328 -0
  18. package/dist/content/docs/en/guide.md +253 -0
  19. package/dist/content/docs/en/index.md +85 -0
  20. package/dist/content/docs/en/limits.md +241 -0
  21. package/dist/content/docs/en/logic.md +446 -0
  22. package/dist/content/docs/en/manifest.md +381 -0
  23. package/dist/content/docs/en/mcp.md +165 -0
  24. package/dist/content/docs/en/package.md +131 -0
  25. package/dist/content/docs/en/publishing.md +162 -0
  26. package/dist/content/docs/en/reference.md +55 -0
  27. package/dist/content/docs/en/result-shapes.md +332 -0
  28. package/dist/content/docs/en/sdk.md +295 -0
  29. package/dist/content/docs/en/security.md +115 -0
  30. package/dist/content/docs/en/service-reference.md +344 -0
  31. package/dist/content/docs/en/services.md +517 -0
  32. package/dist/content/docs/en/style-properties.md +270 -0
  33. package/dist/content/docs/en/style.md +266 -0
  34. package/dist/content/docs/en/testing.md +400 -0
  35. package/dist/content/docs/en/view.md +338 -0
  36. package/dist/content/docs/en/widgets.md +76 -0
  37. package/dist/content/docs/fr/cli.md +367 -0
  38. package/dist/content/docs/fr/dev-channel.md +140 -0
  39. package/dist/content/docs/fr/elements.md +475 -0
  40. package/dist/content/docs/fr/forms.md +341 -0
  41. package/dist/content/docs/fr/guide.md +264 -0
  42. package/dist/content/docs/fr/index.md +90 -0
  43. package/dist/content/docs/fr/limits.md +244 -0
  44. package/dist/content/docs/fr/logic.md +461 -0
  45. package/dist/content/docs/fr/manifest.md +392 -0
  46. package/dist/content/docs/fr/mcp.md +173 -0
  47. package/dist/content/docs/fr/package.md +139 -0
  48. package/dist/content/docs/fr/publishing.md +172 -0
  49. package/dist/content/docs/fr/reference.md +59 -0
  50. package/dist/content/docs/fr/result-shapes.md +333 -0
  51. package/dist/content/docs/fr/sdk.md +301 -0
  52. package/dist/content/docs/fr/security.md +129 -0
  53. package/dist/content/docs/fr/service-reference.md +346 -0
  54. package/dist/content/docs/fr/services.md +540 -0
  55. package/dist/content/docs/fr/style-properties.md +272 -0
  56. package/dist/content/docs/fr/style.md +281 -0
  57. package/dist/content/docs/fr/testing.md +417 -0
  58. package/dist/content/docs/fr/view.md +352 -0
  59. package/dist/content/docs/fr/widgets.md +81 -0
  60. package/dist/content/examples/clock/LICENSE +21 -0
  61. package/dist/content/examples/clock/README.md +75 -0
  62. package/dist/content/examples/clock/listing.json +19 -0
  63. package/dist/content/examples/clock/locales/en.json +4 -0
  64. package/dist/content/examples/clock/locales/fr.json +4 -0
  65. package/dist/content/examples/clock/logic.ts +85 -0
  66. package/dist/content/examples/clock/manifest.json +44 -0
  67. package/dist/content/examples/clock/package.json +16 -0
  68. package/dist/content/examples/clock/style.ocss +26 -0
  69. package/dist/content/examples/clock/tests/hidden.scenario.json +68 -0
  70. package/dist/content/examples/clock/tests/load-logic.mjs +22 -0
  71. package/dist/content/examples/clock/tests/logic.test.mjs +89 -0
  72. package/dist/content/examples/clock/tests/options.scenario.json +108 -0
  73. package/dist/content/examples/clock/tests/preview.scenario.json +25 -0
  74. package/dist/content/examples/clock/tests/render.scenario.json +94 -0
  75. package/dist/content/examples/clock/tests/summer-time.scenario.json +74 -0
  76. package/dist/content/examples/clock/tests/ticks.scenario.json +120 -0
  77. package/dist/content/examples/clock/tsconfig.json +16 -0
  78. package/dist/content/examples/clock/view.ocml +8 -0
  79. package/dist/content/examples/countdown/LICENSE +20 -0
  80. package/dist/content/examples/countdown/listing.json +10 -0
  81. package/dist/content/examples/countdown/locales/en.json +15 -0
  82. package/dist/content/examples/countdown/locales/fr.json +15 -0
  83. package/dist/content/examples/countdown/logic.ts +179 -0
  84. package/dist/content/examples/countdown/manifest.json +34 -0
  85. package/dist/content/examples/countdown/package.json +15 -0
  86. package/dist/content/examples/countdown/style.ocss +94 -0
  87. package/dist/content/examples/countdown/tsconfig.json +16 -0
  88. package/dist/content/examples/countdown/view.ocml +42 -0
  89. package/dist/content/examples/fps/LICENSE +21 -0
  90. package/dist/content/examples/fps/README.md +64 -0
  91. package/dist/content/examples/fps/listing.json +19 -0
  92. package/dist/content/examples/fps/locales/en.json +11 -0
  93. package/dist/content/examples/fps/locales/fr.json +11 -0
  94. package/dist/content/examples/fps/logic.ts +64 -0
  95. package/dist/content/examples/fps/manifest.json +30 -0
  96. package/dist/content/examples/fps/package.json +16 -0
  97. package/dist/content/examples/fps/style.ocss +31 -0
  98. package/dist/content/examples/fps/tests/label.scenario.json +63 -0
  99. package/dist/content/examples/fps/tests/load-logic.mjs +22 -0
  100. package/dist/content/examples/fps/tests/logic.test.mjs +60 -0
  101. package/dist/content/examples/fps/tests/preview.scenario.json +29 -0
  102. package/dist/content/examples/fps/tests/refused.scenario.json +20 -0
  103. package/dist/content/examples/fps/tests/render.scenario.json +96 -0
  104. package/dist/content/examples/fps/tests/stale.scenario.json +91 -0
  105. package/dist/content/examples/fps/tests/unavailable.scenario.json +111 -0
  106. package/dist/content/examples/fps/tsconfig.json +16 -0
  107. package/dist/content/examples/fps/view.ocml +11 -0
  108. package/dist/content/examples/media/LICENSE +21 -0
  109. package/dist/content/examples/media/README.md +147 -0
  110. package/dist/content/examples/media/listing.json +19 -0
  111. package/dist/content/examples/media/locales/en.json +11 -0
  112. package/dist/content/examples/media/locales/fr.json +11 -0
  113. package/dist/content/examples/media/logic.ts +191 -0
  114. package/dist/content/examples/media/manifest.json +35 -0
  115. package/dist/content/examples/media/package.json +16 -0
  116. package/dist/content/examples/media/style.ocss +148 -0
  117. package/dist/content/examples/media/tests/covers.scenario.json +144 -0
  118. package/dist/content/examples/media/tests/gesture.scenario.json +173 -0
  119. package/dist/content/examples/media/tests/load-logic.mjs +22 -0
  120. package/dist/content/examples/media/tests/logic.test.mjs +176 -0
  121. package/dist/content/examples/media/tests/marquee.scenario.json +127 -0
  122. package/dist/content/examples/media/tests/preview.scenario.json +52 -0
  123. package/dist/content/examples/media/tests/read-only.scenario.json +53 -0
  124. package/dist/content/examples/media/tests/refused.scenario.json +22 -0
  125. package/dist/content/examples/media/tests/refused.test.mjs +31 -0
  126. package/dist/content/examples/media/tests/render.scenario.json +136 -0
  127. package/dist/content/examples/media/tests/states.scenario.json +257 -0
  128. package/dist/content/examples/media/tests/unavailable.scenario.json +120 -0
  129. package/dist/content/examples/media/tsconfig.json +16 -0
  130. package/dist/content/examples/media/view.ocml +41 -0
  131. package/dist/content/examples/notes/LICENSE +21 -0
  132. package/dist/content/examples/notes/README.md +219 -0
  133. package/dist/content/examples/notes/listing.json +19 -0
  134. package/dist/content/examples/notes/locales/en.json +25 -0
  135. package/dist/content/examples/notes/locales/fr.json +25 -0
  136. package/dist/content/examples/notes/logic.ts +799 -0
  137. package/dist/content/examples/notes/manifest.json +40 -0
  138. package/dist/content/examples/notes/package.json +16 -0
  139. package/dist/content/examples/notes/style.ocss +469 -0
  140. package/dist/content/examples/notes/tests/checks.scenario.json +237 -0
  141. package/dist/content/examples/notes/tests/create.scenario.json +260 -0
  142. package/dist/content/examples/notes/tests/delete.scenario.json +342 -0
  143. package/dist/content/examples/notes/tests/drafts.scenario.json +714 -0
  144. package/dist/content/examples/notes/tests/editor.scenario.json +232 -0
  145. package/dist/content/examples/notes/tests/frame.scenario.json +93 -0
  146. package/dist/content/examples/notes/tests/interactive.scenario.json +344 -0
  147. package/dist/content/examples/notes/tests/limits.scenario.json +1351 -0
  148. package/dist/content/examples/notes/tests/load-logic.mjs +22 -0
  149. package/dist/content/examples/notes/tests/logic.test.mjs +514 -0
  150. package/dist/content/examples/notes/tests/preview.scenario.json +99 -0
  151. package/dist/content/examples/notes/tests/read-only.scenario.json +105 -0
  152. package/dist/content/examples/notes/tests/refused.scenario.json +33 -0
  153. package/dist/content/examples/notes/tests/save.scenario.json +378 -0
  154. package/dist/content/examples/notes/tests/states.scenario.json +640 -0
  155. package/dist/content/examples/notes/tests/typing.scenario.json +562 -0
  156. package/dist/content/examples/notes/tests/unavailable.scenario.json +246 -0
  157. package/dist/content/examples/notes/tsconfig.json +16 -0
  158. package/dist/content/examples/notes/view.ocml +154 -0
  159. package/dist/content/examples/performance/LICENSE +21 -0
  160. package/dist/content/examples/performance/README.md +134 -0
  161. package/dist/content/examples/performance/listing.json +19 -0
  162. package/dist/content/examples/performance/locales/en.json +20 -0
  163. package/dist/content/examples/performance/locales/fr.json +20 -0
  164. package/dist/content/examples/performance/logic.ts +210 -0
  165. package/dist/content/examples/performance/manifest.json +83 -0
  166. package/dist/content/examples/performance/package.json +16 -0
  167. package/dist/content/examples/performance/style.ocss +75 -0
  168. package/dist/content/examples/performance/tests/fahrenheit.scenario.json +110 -0
  169. package/dist/content/examples/performance/tests/horizontal.scenario.json +96 -0
  170. package/dist/content/examples/performance/tests/load-logic.mjs +22 -0
  171. package/dist/content/examples/performance/tests/logic.test.mjs +226 -0
  172. package/dist/content/examples/performance/tests/menu.scenario.json +170 -0
  173. package/dist/content/examples/performance/tests/no-fps-source.scenario.json +47 -0
  174. package/dist/content/examples/performance/tests/preview.scenario.json +45 -0
  175. package/dist/content/examples/performance/tests/refused.scenario.json +20 -0
  176. package/dist/content/examples/performance/tests/refused.test.mjs +19 -0
  177. package/dist/content/examples/performance/tests/region.scenario.json +89 -0
  178. package/dist/content/examples/performance/tests/render.scenario.json +112 -0
  179. package/dist/content/examples/performance/tests/sources.scenario.json +151 -0
  180. package/dist/content/examples/performance/tests/stale.scenario.json +111 -0
  181. package/dist/content/examples/performance/tests/telemetry-only.scenario.json +44 -0
  182. package/dist/content/examples/performance/tests/thresholds.scenario.json +147 -0
  183. package/dist/content/examples/performance/tests/waiting.scenario.json +105 -0
  184. package/dist/content/examples/performance/tsconfig.json +16 -0
  185. package/dist/content/examples/performance/view.ocml +18 -0
  186. package/dist/content/examples/playervox-journal/LICENSE +21 -0
  187. package/dist/content/examples/playervox-journal/README.md +150 -0
  188. package/dist/content/examples/playervox-journal/listing.json +19 -0
  189. package/dist/content/examples/playervox-journal/locales/en.json +25 -0
  190. package/dist/content/examples/playervox-journal/locales/fr.json +25 -0
  191. package/dist/content/examples/playervox-journal/logic.ts +556 -0
  192. package/dist/content/examples/playervox-journal/manifest.json +19 -0
  193. package/dist/content/examples/playervox-journal/package.json +16 -0
  194. package/dist/content/examples/playervox-journal/style.ocss +142 -0
  195. package/dist/content/examples/playervox-journal/tests/changes.scenario.json +482 -0
  196. package/dist/content/examples/playervox-journal/tests/delete.scenario.json +432 -0
  197. package/dist/content/examples/playervox-journal/tests/frame.scenario.json +169 -0
  198. package/dist/content/examples/playervox-journal/tests/load-logic.mjs +22 -0
  199. package/dist/content/examples/playervox-journal/tests/logic.test.mjs +349 -0
  200. package/dist/content/examples/playervox-journal/tests/paging.scenario.json +428 -0
  201. package/dist/content/examples/playervox-journal/tests/preview.scenario.json +184 -0
  202. package/dist/content/examples/playervox-journal/tests/read-only.scenario.json +157 -0
  203. package/dist/content/examples/playervox-journal/tests/refused.scenario.json +39 -0
  204. package/dist/content/examples/playervox-journal/tests/scale.scenario.json +286 -0
  205. package/dist/content/examples/playervox-journal/tests/signed-out.scenario.json +134 -0
  206. package/dist/content/examples/playervox-journal/tests/states.scenario.json +741 -0
  207. package/dist/content/examples/playervox-journal/tests/unavailable.scenario.json +183 -0
  208. package/dist/content/examples/playervox-journal/tsconfig.json +16 -0
  209. package/dist/content/examples/playervox-journal/view.ocml +52 -0
  210. package/dist/content/examples/playervox-rating/LICENSE +21 -0
  211. package/dist/content/examples/playervox-rating/README.md +166 -0
  212. package/dist/content/examples/playervox-rating/listing.json +19 -0
  213. package/dist/content/examples/playervox-rating/locales/en.json +35 -0
  214. package/dist/content/examples/playervox-rating/locales/fr.json +35 -0
  215. package/dist/content/examples/playervox-rating/logic.ts +581 -0
  216. package/dist/content/examples/playervox-rating/manifest.json +19 -0
  217. package/dist/content/examples/playervox-rating/package.json +16 -0
  218. package/dist/content/examples/playervox-rating/style.ocss +333 -0
  219. package/dist/content/examples/playervox-rating/tests/account.scenario.json +125 -0
  220. package/dist/content/examples/playervox-rating/tests/bounds.scenario.json +73 -0
  221. package/dist/content/examples/playervox-rating/tests/draft.scenario.json +199 -0
  222. package/dist/content/examples/playervox-rating/tests/form.scenario.json +142 -0
  223. package/dist/content/examples/playervox-rating/tests/load-logic.mjs +22 -0
  224. package/dist/content/examples/playervox-rating/tests/logic.test.mjs +346 -0
  225. package/dist/content/examples/playervox-rating/tests/offline.scenario.json +142 -0
  226. package/dist/content/examples/playervox-rating/tests/preview.scenario.json +44 -0
  227. package/dist/content/examples/playervox-rating/tests/publish-keyboard.scenario.json +221 -0
  228. package/dist/content/examples/playervox-rating/tests/publish-pointer.scenario.json +314 -0
  229. package/dist/content/examples/playervox-rating/tests/read-only.scenario.json +70 -0
  230. package/dist/content/examples/playervox-rating/tests/refused.scenario.json +45 -0
  231. package/dist/content/examples/playervox-rating/tests/states.scenario.json +362 -0
  232. package/dist/content/examples/playervox-rating/tsconfig.json +16 -0
  233. package/dist/content/examples/playervox-rating/view.ocml +62 -0
  234. package/dist/content/examples/playervox-reviews/LICENSE +21 -0
  235. package/dist/content/examples/playervox-reviews/README.md +194 -0
  236. package/dist/content/examples/playervox-reviews/listing.json +19 -0
  237. package/dist/content/examples/playervox-reviews/locales/en.json +32 -0
  238. package/dist/content/examples/playervox-reviews/locales/fr.json +32 -0
  239. package/dist/content/examples/playervox-reviews/logic.ts +822 -0
  240. package/dist/content/examples/playervox-reviews/manifest.json +30 -0
  241. package/dist/content/examples/playervox-reviews/package.json +16 -0
  242. package/dist/content/examples/playervox-reviews/style.ocss +260 -0
  243. package/dist/content/examples/playervox-reviews/tests/account.scenario.json +249 -0
  244. package/dist/content/examples/playervox-reviews/tests/bounds.scenario.json +336 -0
  245. package/dist/content/examples/playervox-reviews/tests/changes.scenario.json +515 -0
  246. package/dist/content/examples/playervox-reviews/tests/filter.scenario.json +400 -0
  247. package/dist/content/examples/playervox-reviews/tests/frame.scenario.json +185 -0
  248. package/dist/content/examples/playervox-reviews/tests/keyboard.scenario.json +188 -0
  249. package/dist/content/examples/playervox-reviews/tests/load-logic.mjs +22 -0
  250. package/dist/content/examples/playervox-reviews/tests/logic.test.mjs +559 -0
  251. package/dist/content/examples/playervox-reviews/tests/offline-start.scenario.json +152 -0
  252. package/dist/content/examples/playervox-reviews/tests/offline.scenario.json +311 -0
  253. package/dist/content/examples/playervox-reviews/tests/paging.scenario.json +497 -0
  254. package/dist/content/examples/playervox-reviews/tests/preview.scenario.json +286 -0
  255. package/dist/content/examples/playervox-reviews/tests/reading.scenario.json +591 -0
  256. package/dist/content/examples/playervox-reviews/tests/refused.scenario.json +54 -0
  257. package/dist/content/examples/playervox-reviews/tests/scale.scenario.json +303 -0
  258. package/dist/content/examples/playervox-reviews/tests/states.scenario.json +700 -0
  259. package/dist/content/examples/playervox-reviews/tests/unavailable.scenario.json +192 -0
  260. package/dist/content/examples/playervox-reviews/tsconfig.json +16 -0
  261. package/dist/content/examples/playervox-reviews/view.ocml +110 -0
  262. package/dist/content/examples/playervox-score/LICENSE +21 -0
  263. package/dist/content/examples/playervox-score/README.md +131 -0
  264. package/dist/content/examples/playervox-score/listing.json +19 -0
  265. package/dist/content/examples/playervox-score/locales/en.json +23 -0
  266. package/dist/content/examples/playervox-score/locales/fr.json +23 -0
  267. package/dist/content/examples/playervox-score/logic.ts +430 -0
  268. package/dist/content/examples/playervox-score/manifest.json +47 -0
  269. package/dist/content/examples/playervox-score/package.json +16 -0
  270. package/dist/content/examples/playervox-score/style.ocss +247 -0
  271. package/dist/content/examples/playervox-score/tests/grades.scenario.json +279 -0
  272. package/dist/content/examples/playervox-score/tests/load-logic.mjs +22 -0
  273. package/dist/content/examples/playervox-score/tests/logic.test.mjs +229 -0
  274. package/dist/content/examples/playervox-score/tests/options.scenario.json +302 -0
  275. package/dist/content/examples/playervox-score/tests/preview.scenario.json +68 -0
  276. package/dist/content/examples/playervox-score/tests/pulse.scenario.json +157 -0
  277. package/dist/content/examples/playervox-score/tests/refused.scenario.json +21 -0
  278. package/dist/content/examples/playervox-score/tests/signed-out.scenario.json +46 -0
  279. package/dist/content/examples/playervox-score/tests/states.scenario.json +450 -0
  280. package/dist/content/examples/playervox-score/tests/unavailable.scenario.json +84 -0
  281. package/dist/content/examples/playervox-score/tsconfig.json +16 -0
  282. package/dist/content/examples/playervox-score/view.ocml +51 -0
  283. package/dist/content/examples/session/LICENSE +21 -0
  284. package/dist/content/examples/session/README.md +57 -0
  285. package/dist/content/examples/session/listing.json +19 -0
  286. package/dist/content/examples/session/locales/en.json +3 -0
  287. package/dist/content/examples/session/locales/fr.json +3 -0
  288. package/dist/content/examples/session/logic.ts +26 -0
  289. package/dist/content/examples/session/manifest.json +19 -0
  290. package/dist/content/examples/session/package.json +16 -0
  291. package/dist/content/examples/session/style.ocss +16 -0
  292. package/dist/content/examples/session/tests/hidden.scenario.json +45 -0
  293. package/dist/content/examples/session/tests/load-logic.mjs +22 -0
  294. package/dist/content/examples/session/tests/logic.test.mjs +37 -0
  295. package/dist/content/examples/session/tests/preview.scenario.json +28 -0
  296. package/dist/content/examples/session/tests/refused.scenario.json +20 -0
  297. package/dist/content/examples/session/tests/refused.test.mjs +16 -0
  298. package/dist/content/examples/session/tests/render.scenario.json +95 -0
  299. package/dist/content/examples/session/tests/ticks.scenario.json +139 -0
  300. package/dist/content/examples/session/tests/unknown.scenario.json +37 -0
  301. package/dist/content/examples/session/tsconfig.json +16 -0
  302. package/dist/content/examples/session/view.ocml +11 -0
  303. package/dist/content/examples/stopwatch/LICENSE +21 -0
  304. package/dist/content/examples/stopwatch/README.md +99 -0
  305. package/dist/content/examples/stopwatch/listing.json +19 -0
  306. package/dist/content/examples/stopwatch/locales/en.json +8 -0
  307. package/dist/content/examples/stopwatch/locales/fr.json +8 -0
  308. package/dist/content/examples/stopwatch/logic.ts +93 -0
  309. package/dist/content/examples/stopwatch/manifest.json +19 -0
  310. package/dist/content/examples/stopwatch/package.json +16 -0
  311. package/dist/content/examples/stopwatch/style.ocss +54 -0
  312. package/dist/content/examples/stopwatch/tests/errors.scenario.json +121 -0
  313. package/dist/content/examples/stopwatch/tests/gesture.scenario.json +154 -0
  314. package/dist/content/examples/stopwatch/tests/hidden.scenario.json +57 -0
  315. package/dist/content/examples/stopwatch/tests/hundredths.scenario.json +173 -0
  316. package/dist/content/examples/stopwatch/tests/load-logic.mjs +22 -0
  317. package/dist/content/examples/stopwatch/tests/logic.test.mjs +99 -0
  318. package/dist/content/examples/stopwatch/tests/preview.scenario.json +36 -0
  319. package/dist/content/examples/stopwatch/tests/read-only.scenario.json +42 -0
  320. package/dist/content/examples/stopwatch/tests/read-only.test.mjs +18 -0
  321. package/dist/content/examples/stopwatch/tests/refused.scenario.json +22 -0
  322. package/dist/content/examples/stopwatch/tests/refused.test.mjs +18 -0
  323. package/dist/content/examples/stopwatch/tests/render.scenario.json +105 -0
  324. package/dist/content/examples/stopwatch/tests/states.scenario.json +246 -0
  325. package/dist/content/examples/stopwatch/tests/unknown.scenario.json +40 -0
  326. package/dist/content/examples/stopwatch/tsconfig.json +16 -0
  327. package/dist/content/examples/stopwatch/view.ocml +29 -0
  328. package/dist/content/examples/twitch-chat/LICENSE +21 -0
  329. package/dist/content/examples/twitch-chat/README.md +283 -0
  330. package/dist/content/examples/twitch-chat/listing.json +19 -0
  331. package/dist/content/examples/twitch-chat/locales/en.json +52 -0
  332. package/dist/content/examples/twitch-chat/locales/fr.json +52 -0
  333. package/dist/content/examples/twitch-chat/logic.ts +887 -0
  334. package/dist/content/examples/twitch-chat/manifest.json +33 -0
  335. package/dist/content/examples/twitch-chat/package.json +16 -0
  336. package/dist/content/examples/twitch-chat/style.ocss +544 -0
  337. package/dist/content/examples/twitch-chat/tests/account.scenario.json +325 -0
  338. package/dist/content/examples/twitch-chat/tests/burst.scenario.json +1866 -0
  339. package/dist/content/examples/twitch-chat/tests/channel-refused.scenario.json +372 -0
  340. package/dist/content/examples/twitch-chat/tests/channel.scenario.json +480 -0
  341. package/dist/content/examples/twitch-chat/tests/draft.scenario.json +279 -0
  342. package/dist/content/examples/twitch-chat/tests/fade.scenario.json +269 -0
  343. package/dist/content/examples/twitch-chat/tests/failures.scenario.json +420 -0
  344. package/dist/content/examples/twitch-chat/tests/favorites.scenario.json +376 -0
  345. package/dist/content/examples/twitch-chat/tests/frame.scenario.json +152 -0
  346. package/dist/content/examples/twitch-chat/tests/lifetime.scenario.json +186 -0
  347. package/dist/content/examples/twitch-chat/tests/load-logic.mjs +22 -0
  348. package/dist/content/examples/twitch-chat/tests/logic.test.mjs +1053 -0
  349. package/dist/content/examples/twitch-chat/tests/passive.scenario.json +536 -0
  350. package/dist/content/examples/twitch-chat/tests/preview.scenario.json +147 -0
  351. package/dist/content/examples/twitch-chat/tests/read-only.scenario.json +202 -0
  352. package/dist/content/examples/twitch-chat/tests/read-only.test.mjs +63 -0
  353. package/dist/content/examples/twitch-chat/tests/refused.scenario.json +65 -0
  354. package/dist/content/examples/twitch-chat/tests/refused.test.mjs +43 -0
  355. package/dist/content/examples/twitch-chat/tests/render.scenario.json +347 -0
  356. package/dist/content/examples/twitch-chat/tests/reply.scenario.json +384 -0
  357. package/dist/content/examples/twitch-chat/tests/send-refused.scenario.json +383 -0
  358. package/dist/content/examples/twitch-chat/tests/send.scenario.json +300 -0
  359. package/dist/content/examples/twitch-chat/tests/states.scenario.json +455 -0
  360. package/dist/content/examples/twitch-chat/tests/unavailable.scenario.json +256 -0
  361. package/dist/content/examples/twitch-chat/tests/unread.scenario.json +997 -0
  362. package/dist/content/examples/twitch-chat/tsconfig.json +16 -0
  363. package/dist/content/examples/twitch-chat/view.ocml +141 -0
  364. package/dist/content/examples/warframe-market/LICENSE +21 -0
  365. package/dist/content/examples/warframe-market/README.md +176 -0
  366. package/dist/content/examples/warframe-market/listing.json +19 -0
  367. package/dist/content/examples/warframe-market/locales/en.json +44 -0
  368. package/dist/content/examples/warframe-market/locales/fr.json +44 -0
  369. package/dist/content/examples/warframe-market/logic.ts +1265 -0
  370. package/dist/content/examples/warframe-market/manifest.json +92 -0
  371. package/dist/content/examples/warframe-market/package.json +16 -0
  372. package/dist/content/examples/warframe-market/style.ocss +422 -0
  373. package/dist/content/examples/warframe-market/tests/bounds.scenario.json +60 -0
  374. package/dist/content/examples/warframe-market/tests/cached.scenario.json +70 -0
  375. package/dist/content/examples/warframe-market/tests/detail.scenario.json +251 -0
  376. package/dist/content/examples/warframe-market/tests/errors.scenario.json +105 -0
  377. package/dist/content/examples/warframe-market/tests/fixtures.json +295 -0
  378. package/dist/content/examples/warframe-market/tests/load-logic.mjs +22 -0
  379. package/dist/content/examples/warframe-market/tests/logic.test.mjs +505 -0
  380. package/dist/content/examples/warframe-market/tests/no-clipboard.scenario.json +104 -0
  381. package/dist/content/examples/warframe-market/tests/passive.scenario.json +87 -0
  382. package/dist/content/examples/warframe-market/tests/preview.scenario.json +146 -0
  383. package/dist/content/examples/warframe-market/tests/refresh.scenario.json +56 -0
  384. package/dist/content/examples/warframe-market/tests/refused.scenario.json +74 -0
  385. package/dist/content/examples/warframe-market/tests/render.scenario.json +210 -0
  386. package/dist/content/examples/warframe-market/tests/search.scenario.json +189 -0
  387. package/dist/content/examples/warframe-market/tests/unavailable.scenario.json +54 -0
  388. package/dist/content/examples/warframe-market/tsconfig.json +16 -0
  389. package/dist/content/examples/warframe-market/view.ocml +116 -0
  390. package/dist/content/examples/weather/LICENSE +20 -0
  391. package/dist/content/examples/weather/listing.json +10 -0
  392. package/dist/content/examples/weather/locales/en.json +9 -0
  393. package/dist/content/examples/weather/locales/fr.json +9 -0
  394. package/dist/content/examples/weather/logic.ts +62 -0
  395. package/dist/content/examples/weather/manifest.json +51 -0
  396. package/dist/content/examples/weather/package.json +15 -0
  397. package/dist/content/examples/weather/style.ocss +29 -0
  398. package/dist/content/examples/weather/tsconfig.json +16 -0
  399. package/dist/content/examples/weather/view.ocml +12 -0
  400. package/dist/content/index.json +3601 -0
  401. package/dist/content/reference/errors.json +1712 -0
  402. package/dist/content/reference/limits.json +1154 -0
  403. package/dist/content/reference/manifest.md +223 -0
  404. package/dist/content/reference/permissions.json +413 -0
  405. package/dist/content/templates/blank/locales/en.json +3 -0
  406. package/dist/content/templates/blank/locales/fr.json +3 -0
  407. package/dist/content/templates/blank/logic.ts +7 -0
  408. package/dist/content/templates/blank/manifest.json +16 -0
  409. package/dist/content/templates/blank/style.ocss +10 -0
  410. package/dist/content/templates/blank/tests/example.scenario.json +10 -0
  411. package/dist/content/templates/blank/view.ocml +6 -0
  412. package/dist/content/templates/chart/locales/en.json +3 -0
  413. package/dist/content/templates/chart/locales/fr.json +3 -0
  414. package/dist/content/templates/chart/logic.ts +27 -0
  415. package/dist/content/templates/chart/manifest.json +16 -0
  416. package/dist/content/templates/chart/style.ocss +27 -0
  417. package/dist/content/templates/chart/tests/example.scenario.json +10 -0
  418. package/dist/content/templates/chart/view.ocml +10 -0
  419. package/dist/content/templates/counter/locales/en.json +4 -0
  420. package/dist/content/templates/counter/locales/fr.json +4 -0
  421. package/dist/content/templates/counter/logic.ts +20 -0
  422. package/dist/content/templates/counter/manifest.json +16 -0
  423. package/dist/content/templates/counter/style.ocss +26 -0
  424. package/dist/content/templates/counter/tests/example.scenario.json +11 -0
  425. package/dist/content/templates/counter/view.ocml +13 -0
  426. package/dist/content/templates/list/locales/en.json +8 -0
  427. package/dist/content/templates/list/locales/fr.json +8 -0
  428. package/dist/content/templates/list/logic.ts +35 -0
  429. package/dist/content/templates/list/manifest.json +16 -0
  430. package/dist/content/templates/list/style.ocss +42 -0
  431. package/dist/content/templates/list/tests/example.scenario.json +10 -0
  432. package/dist/content/templates/list/view.ocml +17 -0
  433. package/dist/content/templates/shared/LICENSE +20 -0
  434. package/dist/content/templates/shared/package.json +14 -0
  435. package/dist/content/templates/shared/tsconfig.json +16 -0
  436. package/dist/content.js +68 -0
  437. package/dist/env.js +156 -0
  438. package/dist/fingerprint.js +32 -0
  439. package/dist/ids.js +27 -0
  440. package/dist/index.js +82 -0
  441. package/dist/knowledge.js +222 -0
  442. package/dist/npm.js +149 -0
  443. package/dist/prompts.js +47 -0
  444. package/dist/resources.js +82 -0
  445. package/dist/run.js +120 -0
  446. package/dist/server.js +43 -0
  447. package/dist/session.js +205 -0
  448. package/dist/sources.js +218 -0
  449. package/dist/text.js +80 -0
  450. package/dist/texts.js +44 -0
  451. package/dist/tools/audit.js +105 -0
  452. package/dist/tools/build.js +453 -0
  453. package/dist/tools/common.js +122 -0
  454. package/dist/tools/docs.js +196 -0
  455. package/dist/tools/preview.js +87 -0
  456. package/dist/tools/project.js +178 -0
  457. package/dist/tools/setup.js +146 -0
  458. package/dist/tools/submission.js +369 -0
  459. package/dist/version.js +3 -0
  460. package/npm-shrinkwrap.json +402 -0
  461. package/package.json +52 -4
@@ -0,0 +1,341 @@
1
+ # Formulaires et intents d’écriture
2
+
3
+ Un widget PlayerVox OverCrow reçoit ses entrées par des contrôles
4
+ qu’OverCrow dessine et édite lui-même : boutons, bascules, cases à cocher,
5
+ curseurs, listes déroulantes, champs de texte. La logique en est informée
6
+ par des événements. Un `form` regroupe des contrôles et les valide ensemble.
7
+ Un formulaire lié à un **intent d’écriture** est le moyen, pour un widget,
8
+ de laisser l’utilisateur écrire dans ses notes, publier sa note d’un jeu sur
9
+ PlayerVox ou envoyer un message de chat, sans que le texte passe jamais par
10
+ le code du widget.
11
+
12
+ Les widgets ne reçoivent d’entrées qu’en mode interactif d’OverCrow. En mode
13
+ passif, un clic traverse le widget jusqu’au jeu : masquez ou désactivez ce
14
+ qui est inutilisable, comme le font les widgets intégrés avec `host.mode`.
15
+
16
+ ## Contrôles
17
+
18
+ | Élément | Valeur | Événements |
19
+ | --- | --- | --- |
20
+ | `button` | aucune | `activate` |
21
+ | `toggle`, `checkbox` | `checked` | `change` |
22
+ | `slider` | `value`, entre `min` et `max` | `input` pendant le glissement, `change` au relâchement |
23
+ | `select` avec des enfants `option` | `value` de l’option choisie | `change` |
24
+ | `field` | une ligne de texte | `input` à chaque modification, `change` sur Entrée ou quand le focus quitte le champ, `submit` sur Entrée |
25
+ | `textarea` | plusieurs lignes de texte | `input`, `change`, `submit` sur Ctrl+Entrée |
26
+
27
+ Chacun prend un `label`, son nom accessible, et `disabled`. Leurs attributs
28
+ sont décrits dans [Éléments et attributs](elements.md).
29
+
30
+ <!-- source: docs/content/examples/countdown/view.ocml -->
31
+ ```xml
32
+ <select class="duration" value={minutesValue(state.minutes)} label={t("duration")} disabled={state.running} on:change={setMinutes}>
33
+ <for each={state.durations} as="minutes" key={minutes}>
34
+ <option value={minutesValue(minutes)}>{t("minutes", { count: minutes })}</option>
35
+ </for>
36
+ </select>
37
+ ```
38
+
39
+ <!-- source: docs/content/examples/countdown/logic.ts -->
40
+ ```ts
41
+ export function setMinutes(event: { value: unknown }): void {
42
+ const minutes = Number(event.value);
43
+ if (state.durations.includes(minutes)) {
44
+ state.minutes = minutes;
45
+ state.remainingMs = total(minutes);
46
+ }
47
+ }
48
+ ```
49
+
50
+ La vue lie le contrôle à l’état (`value={…}`, `checked={…}`), et le
51
+ gestionnaire y réécrit la nouvelle valeur. Le détail de `input` et de
52
+ `change` est `{ value }` : un booléen pour une bascule ou une case à cocher,
53
+ un nombre pour un curseur, du texte pour les autres.
54
+
55
+ <!-- source: docs/content/examples/countdown/view.ocml -->
56
+ ```xml
57
+ <toggle class="repeat" label={t("repeat")} tooltip={t("repeat")} checked={state.repeat} on:change={setRepeat}/>
58
+ ```
59
+
60
+ ### Champs de texte
61
+
62
+ OverCrow édite lui-même le texte d’un `field` ou d’un `textarea` : le point
63
+ d’insertion, la sélection, le copier-coller et les méthodes de saisie des
64
+ langues qui composent leurs caractères. La logique reçoit une copie du texte
65
+ dans chaque événement `input`.
66
+
67
+ <!-- source: widgets/warframe-market/view.ocml -->
68
+ ```xml
69
+ <field class="query" label={t("search-field")} value={state.query} placeholder={t("placeholder")} max-length="256" on:input={search}/>
70
+ ```
71
+
72
+ <!-- source: widgets/warframe-market/logic.ts -->
73
+ ```ts
74
+ export function search(detail: { value: unknown }): void {
75
+ state.query = typeof detail.value === "string" ? detail.value : "";
76
+ state.results = searchItems(items, lowered, state.query);
77
+ state.detail = null;
78
+ state.loadingOrders = false;
79
+ state.refreshing = false;
80
+ state.copy = null;
81
+ if (state.error === "orders_unavailable") {
82
+ state.error = null;
83
+ }
84
+ selection += 1;
85
+ stopRefresh();
86
+ saveQuery();
87
+ }
88
+ ```
89
+
90
+ Lier `value` remplace le contenu du champ : liez-le à l’état qu’écrit votre
91
+ gestionnaire `input`, comme ci-dessus, ou omettez-le et contentez-vous
92
+ d’écouter. `max-length` limite le texte en octets, et `placeholder` affiche
93
+ une indication tant que le champ est vide.
94
+
95
+ Un champ envoie aussi `keydown` quand vous le demandez, avec la touche et
96
+ ses modificateurs, pour des raccourcis comme Échap pour annuler. Les touches
97
+ qu’OverCrow se réserve (Tab pour déplacer le focus, ses propres raccourcis,
98
+ une composition en cours) ne sont pas transmises.
99
+
100
+ ### Le focus à l’ouverture d’un éditeur
101
+
102
+ La logique ne peut pas déplacer le focus clavier. Un `field` ou un
103
+ `textarea` qui porte `autofocus` le prend de lui-même quand il apparaît
104
+ pendant que la logique traite une action de l’utilisateur : un clic sur un
105
+ bouton Modifier qui ouvre un éditeur place le point d’insertion dans le
106
+ champ, après son texte, comme le ferait un clic dans ce champ.
107
+
108
+ <!-- source: widgets/notes/view.ocml -->
109
+ ```xml
110
+ <field class="title-field" name="title" autofocus placeholder={t("title-hint")} label={t("title-hint")} on:input={titleInput(editor.key, event.value)} on:keydown={keyed(editor.key, event.key, event.ctrl)}/>
111
+ ```
112
+
113
+ OverCrow ne donne ce focus que si l’élément apparaît pendant une
114
+ [action de l’utilisateur](services.md#les-appels-qui-demandent-une-action-de-lutilisateur),
115
+ en mode interactif, dans le widget sur lequel l’utilisateur a agi ; quand
116
+ plusieurs de ces éléments apparaissent ensemble, le premier de la vue le
117
+ prend. Un élément qui apparaît au démarrage du widget, depuis un minuteur
118
+ ou depuis la réponse d’un service (y compris après un `await` dans le
119
+ gestionnaire du clic) ne prend pas le focus, pas plus qu’un élément déjà
120
+ affiché : `autofocus` est lu quand l’élément apparaît. Donnez-le à un seul
121
+ champ d’un éditeur, et pas à un champ qui apparaît pendant que
122
+ l’utilisateur saisit, comme une nouvelle ligne d’une liste.
123
+
124
+ ## Formulaires
125
+
126
+ Un `form` regroupe des contrôles et leur donne un seul événement `submit`.
127
+ On le valide par Entrée dans un `field`, par Ctrl+Entrée dans un `field` ou
128
+ un `textarea`, ou en activant un bouton doté de l’attribut `submit`.
129
+
130
+ <!-- source: widgets/twitch-chat/view.ocml -->
131
+ ```xml
132
+ <form class="selector" on:submit={join}>
133
+ <field class="input channel" max-length="26" autofocus placeholder={t("channel-name")} label={t("channel-name")} on:input={channelTyped(event.value)}/>
134
+ <button class="action" submit disabled={!canJoin(state)}>
135
+ <text class="action-label">{t("join")}</text>
136
+ </button>
137
+ </form>
138
+ ```
139
+
140
+ <!-- source: widgets/twitch-chat/logic.ts -->
141
+ ```ts
142
+ export function join(): void {
143
+ const channel = normalizeChannel(state.channelDraft);
144
+ if (channel !== null) {
145
+ joinChannel(channel);
146
+ }
147
+ }
148
+ ```
149
+
150
+ Ce formulaire n’a pas d’intent : son gestionnaire `submit` lit ce que le
151
+ gestionnaire `input` a gardé dans l’état, puis appelle un service. `submit`
152
+ est une action de l’utilisateur : le gestionnaire peut donc appeler un
153
+ service qui en demande une (`twitch.chat.join` ici).
154
+
155
+ Un formulaire garde ce que l’utilisateur a saisi tant qu’il reste dans la
156
+ vue. Masquez-le avec `display: none` pour garder un brouillon ; retirez-le
157
+ de la vue pour l’abandonner. Pour repartir de champs vides, donnez au
158
+ formulaire une nouvelle clé dans un `for` : une nouvelle clé, c’est un
159
+ nouveau formulaire.
160
+
161
+ ## Les formulaires qui écrivent des données de l’utilisateur
162
+
163
+ Trois opérations d’un widget écrivent, dans les données de l’utilisateur, un
164
+ texte que celui-ci a saisi : enregistrer une note, publier la note d’un jeu
165
+ sur PlayerVox avec son avis, et envoyer un message dans un chat Twitch. Ce ne
166
+ sont pas des appels de service. C’est un formulaire doté d’un attribut
167
+ `intent` qui les envoie :
168
+
169
+ <!-- source: widgets/twitch-chat/view.ocml -->
170
+ ```xml
171
+ <form class={composerClass(state)} intent="twitch.chat.send" target={replyTarget(state)} on:submit={submitted(event.outcome, event.error)}>
172
+ <if test={state.reply}>
173
+ <box class="replying">
174
+ <text class="replying-label">{replyingTo(state)}</text>
175
+ <button class="icon-button small" label={t("cancel-reply")} tooltip={t("cancel-reply")} on:activate={cancelReply}>
176
+ <icon name="x"/>
177
+ </button>
178
+ </box>
179
+ </if>
180
+ <if test={state.sendError != ""}>
181
+ <text class="error">{t(state.sendError)}</text>
182
+ </if>
183
+ <box class="compose">
184
+ <field class="input message-field" name="message" max-length="500" placeholder={t(composerHint(state))} label={t("message-label")} disabled={!state.canSend} on:input={drafted(event.value)} on:keydown={keyed(event.key)}/>
185
+ <if test={sendMark(state) != ""}>
186
+ <text class={sendMarkClass(state)}>{t(sendMark(state))}</text>
187
+ </if>
188
+ <button class="action" submit disabled={!canSubmit(state)} on:activate={sendPressed}>
189
+ <text class="action-label">{t("send")}</text>
190
+ </button>
191
+ </box>
192
+ </form>
193
+ ```
194
+
195
+ Quand l’utilisateur valide un tel formulaire, **OverCrow lit les valeurs des
196
+ contrôles de ce formulaire et les envoie lui-même**. La logique du widget ne
197
+ fournit jamais le texte : un widget ne peut donc ni écrire ce que
198
+ l’utilisateur n’a pas saisi, ni valider sans lui. Le formulaire ne part que
199
+ sur une action de l’utilisateur, en mode interactif, avec la capability
200
+ accordée.
201
+
202
+ Ce que cela change pour la vue et la logique :
203
+
204
+ - **Les contrôles appartiennent à OverCrow.** Les contrôles `field`,
205
+ `textarea` et `slider` du formulaire ne prennent pas de `value` :
206
+ `overcrow-widget check` le refuse (`view.bound_value`), et OverCrow arrête
207
+ un widget qui en définit un à l’exécution. Leur attribut `name` indique à
208
+ quel champ de l’intent chacun correspond.
209
+ - **OverCrow les remplit** là où l’intent le prévoit : le titre, le corps et
210
+ la liste de tâches de la note, la note publiée par l’utilisateur. Un
211
+ remplissage envoie l’événement `input` du contrôle avec la valeur, pour
212
+ que la logique sache ce qui est affiché ; cet événement n’est pas une
213
+ action de l’utilisateur.
214
+ - **La logique suit par les événements `input`**, pour afficher un compteur
215
+ ou activer le bouton, et peut désactiver les contrôles.
216
+ - **L’issue arrive dans l’événement `submit` du formulaire** :
217
+ `event.outcome` vaut `accepted`, `rejected` (avec le
218
+ [code d’erreur](services.md#erreurs) dans `event.error`) ou `cancelled`.
219
+ Un formulaire sans intent donne `submitted`.
220
+
221
+ <!-- source: widgets/playervox-rating/view.ocml -->
222
+ ```xml
223
+ <slider class="criterion-slider" name="gameplay" min="0" max="100" step="1" label={t("gameplay")} disabled={!editable(state)} on:input={scored("gameplay", event.value)}/>
224
+ ```
225
+
226
+ <!-- source: widgets/playervox-rating/logic.ts -->
227
+ ```ts
228
+ export function scored(key: CriterionKey, value: number): void {
229
+ state[key] = value;
230
+ edited();
231
+ }
232
+ ```
233
+
234
+ <!-- source: widgets/playervox-rating/logic.ts -->
235
+ ```ts
236
+ export function submitted(outcome: string, error: ServiceErrorPayload | undefined): void {
237
+ state.pending = Math.max(0, state.pending - 1);
238
+ if (state.pending === 0) {
239
+ answer?.cancel();
240
+ answer = null;
241
+ }
242
+ if (outcome === "accepted") {
243
+ // The subscription sends the stored rating; nothing is read again.
244
+ state.saved = true;
245
+ state.error = "";
246
+ } else if (outcome !== "cancelled") {
247
+ state.error = errorKey(error?.code ?? null);
248
+ }
249
+ }
250
+ ```
251
+
252
+ Une écriture ne change pas d’elle-même ce que dit un abonnement : après une
253
+ note PlayerVox acceptée, `playervox.rating.subscribe` livre la note
254
+ enregistrée, et c’est elle que le widget affiche.
255
+
256
+ ### Les intents
257
+
258
+ <!-- generated:write-intents -->
259
+ ### `notes.save`
260
+
261
+ Capability `notes.write` ; attribut `target` obligatoire (l’ID de la note ; l’hôte remplit les contrôles liés à partir de cette note). Entrée dans un `field` du formulaire fait passer le focus à son `field` ou `textarea` suivant et ne valide pas ; Ctrl+Entrée et un bouton `submit` valident.
262
+
263
+ | Champ | Type | Obligatoire | Signification |
264
+ | --- | --- | --- | --- |
265
+ | `title` | texte ≤ 96 octets | oui | `field` ; enregistré sans espaces en début ni en fin, et non vide. |
266
+ | `body` | texte ≤ 8 Kio | non | `textarea` ; enregistré tel qu’il est écrit. |
267
+ | `item` | liste de `NoteItem` ≤ 64 | non | Un `field` par ligne de la liste de tâches, dans l’ordre, chacun ≤ 256 octets. L’hôte retient avec quelle entrée il a rempli chaque champ : une ligne garde l’ID et la coche de cette entrée quelles que soient les lignes que le widget retire ou déplace, et un champ apparu depuis est une nouvelle entrée, non cochée. Les lignes sont enregistrées sans espaces en début ni en fin ; une ligne vide est abandonnée. Une note enregistrée telle qu’elle est déjà stockée est acceptée sans écriture. |
268
+
269
+ ### `playervox.rating.publish`
270
+
271
+ Capability `playervox.rating.write` ; attribut `target` refusé.
272
+
273
+ | Champ | Type | Obligatoire | Signification |
274
+ | --- | --- | --- | --- |
275
+ | `gameplay` | entier de 0 à 100 | oui | `slider` ; rempli à partir de la note de l’utilisateur, 50 avant la première. |
276
+ | `art` | entier de 0 à 100 | oui | `slider` ; rempli comme `gameplay`. |
277
+ | `tech` | entier de 0 à 100 | oui | `slider` ; rempli comme `gameplay`. |
278
+ | `review` | texte ≤ 2000 caractères | non | `textarea` ; rempli à partir de l’avis publié. Un avis inchangé n’est pas renvoyé ; un avis vidé est retiré. |
279
+
280
+ ### `twitch.chat.send`
281
+
282
+ Capability `twitch.chat.compose` ; attribut `target` facultatif (l’ID du message auquel on répond).
283
+
284
+ | Champ | Type | Obligatoire | Signification |
285
+ | --- | --- | --- | --- |
286
+ | `message` | texte ≤ 500 caractères | oui | `field` ; l’hôte le vide après un envoi réussi. |
287
+ <!-- /generated:write-intents -->
288
+
289
+ `target` est l’attribut du formulaire qui désigne l’objet écrit :
290
+ l’identifiant de la note pour `notes.save`, l’identifiant du message auquel
291
+ on répond pour `twitch.chat.send`.
292
+
293
+ ### Plusieurs lignes d’un même champ
294
+
295
+ L’intent `notes.save` prend un champ `item` par ligne de la liste de tâches.
296
+ La logique décide des lignes du formulaire, avec un `for` ; OverCrow remplit
297
+ le champ de chaque ligne à partir de la note enregistrée et retient quelle
298
+ entrée de la liste de tâches il y a placée. Une ligne que la logique retire
299
+ ou déplace garde son entrée, et une ligne ajoutée depuis est une nouvelle
300
+ entrée.
301
+
302
+ <!-- source: widgets/notes/view.ocml -->
303
+ ```xml
304
+ <for each={editor.rows} as="row" key={row.key}>
305
+ <box class="row">
306
+ <if test={rowStored(state, editor, row)}>
307
+ <checkbox class="row-check" checked={rowChecked(state, editor, row)} label={rowLabel(row)} on:change={check(editor.note, row.id, event.value)}/>
308
+ </if>
309
+ <else>
310
+ <icon class="row-new" name="circle"/>
311
+ </else>
312
+ <field class="row-field" name="item" placeholder={rowHint(editor, row)} label={t("item-hint")} on:input={rowInput(editor.key, row.key, event.value)} on:keydown={keyed(editor.key, event.key, event.ctrl)}/>
313
+ ```
314
+
315
+ Dans ce formulaire, Entrée passe au champ suivant au lieu de valider ;
316
+ Ctrl+Entrée ou le bouton `submit` enregistre.
317
+
318
+ ## Confirmations
319
+
320
+ Deux services suppriment des données de l’utilisateur : `notes.delete` et
321
+ `journal.delete`. Ce sont des appels ordinaires qui demandent une action de
322
+ l’utilisateur. OverCrow demande ensuite à l’utilisateur de confirmer, dans
323
+ une boîte de dialogue qu’il dessine lui-même, hors du widget. L’appel
324
+ aboutit quand l’utilisateur confirme et échoue avec `cancelled` quand il
325
+ refuse. Ne dessinez pas votre propre « Êtes-vous sûr ? » : seule la
326
+ confirmation d’OverCrow compte.
327
+
328
+ ## Points à vérifier pour un formulaire
329
+
330
+ - Chaque contrôle a un `label`.
331
+ - Les boutons qui ne peuvent pas agir sont `disabled`, et rien de ce qui
332
+ demande une entrée ne s’affiche en mode passif.
333
+ - Le gestionnaire `submit` traite un refus : `not_connected` quand le compte
334
+ est déconnecté, `busy` quand l’utilisateur envoie trop vite,
335
+ `unavailable`.
336
+ - Un formulaire lié à un intent n’a pas de `value` sur ses champs de texte
337
+ ni sur ses curseurs, et chaque contrôle nommé est un champ de l’intent.
338
+ - Testez-le avec un scénario : les étapes `text` saisissent du texte dans le
339
+ champ qui a le focus, les étapes `key` appuient sur Entrée, et
340
+ `expect.intents` vérifie exactement ce qu’OverCrow a envoyé. Voir
341
+ [Tester un widget](testing.md#steps).
@@ -0,0 +1,264 @@
1
+ # Guide du créateur
2
+
3
+ Ce guide mène un widget PlayerVox OverCrow d’un dossier vide à une
4
+ soumission : créer un projet, modifier sa vue, son style et sa logique, le
5
+ lancer dans OverCrow, le tester, l’empaqueter et le soumettre. Chaque étape
6
+ renvoie à la page qui la traite en détail.
7
+
8
+ Pour travailler plutôt avec un assistant IA, ajoutez-lui le serveur MCP
9
+ d’OverCrow : voir [MCP](mcp.md).
10
+
11
+ ## 1. Installer les outils
12
+
13
+ - **`overcrow-widget`**, la CLI des widgets, un seul binaire pour Linux et
14
+ Windows. Voir [installer la CLI](cli.md#installation).
15
+ - **Node.js 22 ou plus récent** et npm, pour que `check` vérifie les types
16
+ de votre logique avec le TypeScript du projet et le SDK de npm. Sans lui, la CLI vérifie et
17
+ empaquette quand même, mais signale que les types n’ont pas été vérifiés.
18
+ - **OverCrow**, pour lancer le widget pendant que vous l’écrivez.
19
+
20
+ `overcrow-widget doctor` indique ce que votre installation a et ce qui lui
21
+ manque.
22
+
23
+ ## 2. Créer un projet
24
+
25
+ ```sh
26
+ overcrow-widget init my-counter --template counter
27
+ cd my-counter
28
+ npm install
29
+ ```
30
+
31
+ `npm install` installe TypeScript et `@overcrow/sdk` 1.0.0, nommés dans le
32
+ `package.json` du projet.
33
+
34
+ Les templates sont `blank`, `counter`, `list` et `chart`. L’ID vaut par
35
+ défaut `com.example.<dir>` : passez `--id` avec un nom DNS inversé que vous
36
+ contrôlez (`com.playervox.*` est réservé).
37
+ [Fichiers d’un projet](cli.md#fichiers-dun-projet) liste chaque fichier et
38
+ indique lesquels sont empaquetés ;
39
+ [les types du SDK](cli.md#les-types-du-sdk) explique comment ajouter le SDK
40
+ à un autre projet.
41
+
42
+ ## 3. La vue
43
+
44
+ `view.ocml` est du balisage : des éléments, des attributs, des expressions
45
+ `{…}` liées à l’état, et des gestionnaires `on:<event>` qui appellent des
46
+ fonctions exportées par la logique.
47
+
48
+ <!-- source: templates/counter/view.ocml -->
49
+ ```xml
50
+ <box class="counter">
51
+ <text class="value">{state.count}</text>
52
+ <box class="actions">
53
+ <button class="step" label={t("decrement")} on:activate={decrement}>
54
+ <icon name="minus"/>
55
+ </button>
56
+ <button class="step" label={t("increment")} on:activate={increment}>
57
+ <icon name="plus"/>
58
+ </button>
59
+ </box>
60
+ </box>
61
+ ```
62
+
63
+ La vue offre aussi `if`, `for` avec une clé obligatoire, et des composants
64
+ locaux : voir [la vue](view.md). Chaque élément et chaque attribut figure
65
+ dans [éléments et attributs](elements.md).
66
+
67
+ ## 4. Le style
68
+
69
+ `style.ocss` est un sous-ensemble borné de CSS : sélecteurs de classe,
70
+ d’élément, de descendant et d’enfant, états `:hover`, `:active`, `:focus`,
71
+ `:disabled` et `:checked`, mise en page flex et grid, et les tokens du thème
72
+ en `var(--…)`, qui suivent le thème clair ou sombre de l’utilisateur.
73
+
74
+ <!-- source: templates/counter/style.ocss -->
75
+ ```css
76
+ .step {
77
+ width: var(--icon-button-size);
78
+ height: var(--icon-button-size);
79
+ border-radius: var(--radius-md);
80
+ background: var(--color-surface-raised);
81
+ }
82
+ ```
83
+
84
+ <!-- source: templates/counter/style.ocss -->
85
+ ```css
86
+ .step:hover {
87
+ background: var(--color-surface-hover);
88
+ }
89
+ ```
90
+
91
+ Il n’y a ni `@media`, ni `@import`, ni `url()`, ni `calc()` : une
92
+ propriété ou un sélecteur inconnu est une erreur, il n’est pas ignoré en
93
+ silence. Voir [le style](style.md) et
94
+ [propriétés de style et tokens](style-properties.md).
95
+
96
+ ## 5. La logique
97
+
98
+ `logic.ts` possède l’état. Déclarez son type une fois, modifiez-le dans vos
99
+ gestionnaires, et la vue suit : après chaque tour, la VM évalue de nouveau
100
+ la vue et n’envoie que ce qui a changé.
101
+
102
+ <!-- source: templates/counter/logic.ts -->
103
+ ```ts
104
+ import { initState } from "@overcrow/sdk";
105
+
106
+ declare module "@overcrow/sdk" {
107
+ interface WidgetState {
108
+ count: number;
109
+ }
110
+ }
111
+ ```
112
+
113
+ <!-- source: templates/counter/logic.ts -->
114
+ ```ts
115
+ export function increment(): void {
116
+ state.count += 1;
117
+ }
118
+ ```
119
+
120
+ La logique tourne dans une VM enfermée dans un sandbox, pas dans un
121
+ navigateur : il n’y a ni DOM, ni `fetch`, ni `setTimeout`, ni `console`, ni
122
+ `Intl`. Le SDK fournit les minuteurs, les services, des fonctions de
123
+ formatage des heures et des nombres au format régional de l’utilisateur, les
124
+ messages et le dessin. Voir [la logique](logic.md) et la
125
+ [référence du SDK](sdk.md).
126
+
127
+ ## 6. Les messages
128
+
129
+ `t("key")`, dans la vue ou la logique, lit `locales/en.json` ou
130
+ `locales/fr.json` selon la langue de l’utilisateur et remplit les paramètres
131
+ `{name}`.
132
+
133
+ <!-- source: templates/counter/locales/en.json -->
134
+ ```json
135
+ {
136
+ "decrement": "Decrease",
137
+ "increment": "Increase"
138
+ }
139
+ ```
140
+
141
+ Fournissez les deux fichiers ou aucun, avec les mêmes clés. Voir
142
+ [messages](logic.md#messages).
143
+
144
+ ## 7. Vérifier
145
+
146
+ ```sh
147
+ overcrow-widget check
148
+ ```
149
+
150
+ `check` exécute les mêmes validateurs qu’OverCrow : manifeste, vue, style,
151
+ messages, une analyse de la logique selon ce que la VM exécute, le
152
+ TypeScript du projet, et un paquet construit en mémoire puis relu. Chaque
153
+ problème a un code stable, une position et une ligne d’aide ; voir les
154
+ [diagnostics](cli.md#diagnostics).
155
+
156
+ ## 8. Le lancer dans OverCrow
157
+
158
+ ```sh
159
+ overcrow-widget dev
160
+ ```
161
+
162
+ `dev` envoie le widget à l’overlay OverCrow qui tourne sur votre machine et
163
+ le recharge à chaque enregistrement. OverCrow ne le propose que s’il a été
164
+ lancé avec les installations de développement autorisées
165
+ (`OVERCROW_WIDGET_DEVELOPMENT=1` ; `overcrow-widget doctor` affiche les
166
+ commandes). Le widget porte la mention
167
+ **Unverified · development package** ; ses permissions déclarées sont
168
+ accordées pour la session seulement, et rien n’est conservé. Les
169
+ `log.info(…)` de votre logique s’affichent dans le terminal. Voir
170
+ [le canal de développement](dev-channel.md).
171
+
172
+ ## 9. Le tester
173
+
174
+ Deux sortes de tests, décrites dans [tester un widget](testing.md) :
175
+
176
+ - des tests unitaires de la logique avec `@overcrow/sdk/testing`, qui
177
+ exécute votre module avec un temps virtuel et des services simulés ;
178
+ - des scénarios joués par `overcrow-widget test` dans le runtime headless
179
+ d’OverCrow : la vraie VM et le vrai rendu, des services qui répondent avec
180
+ des fixtures (des données simulées), et des images comparées à des images
181
+ de référence.
182
+
183
+ <!-- source: templates/counter/tests/example.scenario.json -->
184
+ ```json
185
+ "host": { "mode": "interactive" },
186
+ "steps": [
187
+ { "expect": { "state": "running", "text": ["0"], "image": "initial" } },
188
+ { "pointer": { "click": { "label": "Increase" } } },
189
+ { "expect": { "text": ["1"], "noText": ["0"], "image": "increased", "fault": "none" } }
190
+ ]
191
+ ```
192
+
193
+ ```sh
194
+ overcrow-widget test
195
+ ```
196
+
197
+ ## 10. Demander ce dont vous avez besoin
198
+
199
+ Un widget n’obtient rien par défaut. Pour appeler une API, conserver des
200
+ données ou lire des informations de jeu, déclarez-le dans `manifest.json` ;
201
+ l’utilisateur donne son accord dans le Centre de contrôle avant que le
202
+ widget n’y ait accès. Une règle
203
+ réseau nomme une origine HTTPS, une méthode et un chemin complet, avec des
204
+ paramètres typés :
205
+
206
+ <!-- source: docs/content/examples/weather/manifest.json -->
207
+ ```json
208
+ "permissions": {
209
+ "network": [
210
+ {
211
+ "origin": "https://api.example.com",
212
+ "method": "GET",
213
+ "path": "/v1/forecast/{city}",
214
+ "pathParams": { "city": { "type": "slug", "maxLength": 32 } },
215
+ "queryParams": {
216
+ "units": { "type": "enum", "values": ["metric", "imperial"], "required": true }
217
+ }
218
+ }
219
+ ],
220
+ "storage": true
221
+ },
222
+ ```
223
+
224
+ <!-- source: docs/content/examples/weather/logic.ts -->
225
+ ```ts
226
+ const url = `https://api.example.com/v1/forecast/${state.city}?units=${state.units}`;
227
+ const { status, body } = await http.fetch(url, { as: "json" });
228
+ ```
229
+
230
+ Les données du jeu et du système viennent d’abonnements (`fps.subscribe`,
231
+ `media.subscribe`…), qui mettent votre état à jour jusqu’à ce que vous les
232
+ annuliez. [Services et permissions](services.md) explique ce que chaque
233
+ permission autorise, et [sécurité](security.md) ce qu’un widget ne peut
234
+ jamais faire. L’exemple complet se trouve dans
235
+ [`docs/content/examples/weather`](../examples/weather/).
236
+
237
+ ## 11. Empaqueter
238
+
239
+ ```sh
240
+ overcrow-widget package
241
+ overcrow-widget inspect dist/com.example.my-counter-0.1.0.ocpkg
242
+ ```
243
+
244
+ `package` écrit un `.ocpkg` déterministe dans `dist/` : les mêmes sources
245
+ et la même version de la CLI donnent les mêmes octets sur tous les systèmes.
246
+ `inspect` montre ce qu’un paquet contient et demande, comme le voit un
247
+ relecteur. Un paquet installé localement reste non vérifié ; les
248
+ utilisateurs obtiennent les widgets par le catalogue signé. Voir
249
+ [le paquet](package.md).
250
+
251
+ ## 12. Soumettre
252
+
253
+ Ajoutez un `listing.json` avec le texte de la marketplace, lancez vous-même
254
+ l’admission, puis ouvrez une pull request qui ajoute votre widget sous
255
+ `widgets/<dir>/`, sur la branche `candidate` du
256
+ [dépôt public](https://github.com/Valhallab/playervox-overcrow-releases) :
257
+
258
+ ```sh
259
+ overcrow-widget admit
260
+ ```
261
+
262
+ `admit` exécute exactement les contrôles de la CI de la marketplace. La
263
+ suite, de la revue au catalogue signé, est décrite dans
264
+ [publication et revue](publishing.md).