@overcrow/mcp 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (461) 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 +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 +50 -4
@@ -0,0 +1,540 @@
1
+ # Services et permissions
2
+
3
+ Un widget PlayerVox OverCrow n’a aucun accès par lui-même : ni réseau, ni
4
+ fichier, ni presse-papiers, ni donnée sur le jeu. Tout ce qui sort de son
5
+ propre état vient d’un **service** d’OverCrow, que la logique appelle par
6
+ `@overcrow/sdk`. Un service ne répond que si le widget a déclaré la
7
+ permission correspondante dans son manifeste et que l’utilisateur l’a
8
+ accordée.
9
+
10
+ <!-- source: widgets/session/logic.ts -->
11
+ ```ts
12
+ // Without the grant the host would refuse the subscription: show the
13
+ // unknown duration instead of asking.
14
+ if (hasGrant("session.read")) {
15
+ session.subscribe((update) => {
16
+ state.session = anchor(update);
17
+ });
18
+ }
19
+ ```
20
+
21
+ C’est tout l’usage d’un service dans le widget Session : il déclare la
22
+ capability `session.read`, vérifie que l’utilisateur l’a accordée, puis
23
+ s’abonne.
24
+
25
+ ## Déclarer, puis demander à l’utilisateur
26
+
27
+ Il existe deux sortes d’autorité, toutes deux déclarées dans `permissions`
28
+ du [manifeste](manifest.md#permissions) :
29
+
30
+ - quatre **permissions** pour les services généraux : `network`, `storage`,
31
+ `clipboardWrite` et `gameEvents` ;
32
+ - des **capabilities**, listées sous `permissions.capabilities`, pour les
33
+ données et les actions d’OverCrow lui-même et des comptes de
34
+ l’utilisateur : la fréquence d’images, le lecteur multimédia, les notes de
35
+ l’utilisateur, la note qu’il donne à un jeu sur PlayerVox, le chat
36
+ Twitch…
37
+
38
+ <!-- source: docs/content/examples/weather/manifest.json -->
39
+ ```json
40
+ "permissions": {
41
+ "network": [
42
+ {
43
+ "origin": "https://api.example.com",
44
+ "method": "GET",
45
+ "path": "/v1/forecast/{city}",
46
+ "pathParams": { "city": { "type": "slug", "maxLength": 32 } },
47
+ "queryParams": {
48
+ "units": { "type": "enum", "values": ["metric", "imperial"], "required": true }
49
+ }
50
+ }
51
+ ],
52
+ "storage": true
53
+ },
54
+ ```
55
+
56
+ Une déclaration n’accorde rien à elle seule. Le Centre de contrôle montre
57
+ à l’utilisateur ce que le widget demande ; celui-ci peut en décocher un
58
+ élément, ou le retirer plus tard, ce qui redémarre le widget sans lui. Les widgets marqués `built-in` dans le catalogue signé (widgets
59
+ PlayerVox uniquement) démarrent avec leurs permissions déclarées accordées.
60
+ Déclarez le strict nécessaire : les relecteurs lisent chaque permission, et
61
+ les utilisateurs les voient avant de donner leur accord.
62
+
63
+ `hasGrant(capability)` indique si une capability a été accordée.
64
+ Vérifiez-le avant de vous abonner, et affichez un état utile quand elle
65
+ manque : même après un refus, le widget doit rester présentable.
66
+
67
+ <!-- source: widgets/fps/logic.ts -->
68
+ ```ts
69
+ if (hasGrant("fps.read")) {
70
+ fps.subscribe((update) => {
71
+ Object.assign(state, reading(update));
72
+ });
73
+ } else {
74
+ state.status = "unavailable";
75
+ }
76
+ ```
77
+
78
+ ## Appels et abonnements
79
+
80
+ Il existe deux sortes de services.
81
+
82
+ **Un appel** pose sa question une fois et renvoie une promesse :
83
+
84
+ <!-- source: widgets/warframe-market/logic.ts -->
85
+ ```ts
86
+ async function readStored(key: string): Promise<JsonValue | undefined> {
87
+ try {
88
+ return await storage.get({ key });
89
+ } catch {
90
+ state.error = "storage_unavailable";
91
+ return undefined;
92
+ }
93
+ }
94
+ ```
95
+
96
+ **Un abonnement** prend un écouteur. OverCrow l’appelle aussitôt avec la
97
+ valeur courante, puis à chaque nouvelle valeur, jusqu’à ce que vous
98
+ l’annuliez avec `cancel()` ou qu’il se termine par un échec. L’écouteur
99
+ vient en dernier ; un service qui a des paramètres les prend en premier.
100
+
101
+ <!-- source: widgets/media/logic.ts -->
102
+ ```ts
103
+ const current = media.subscribe({ cover: state.showCover }, (update) => {
104
+ if (update.ok) {
105
+ state.media = update.value;
106
+ state.unavailable = false;
107
+ return;
108
+ }
109
+ // The subscription ended: the host's source failed. Show it and ask
110
+ // again later; hidden, the timer waits until the widget shows.
111
+ if (subscription === current) {
112
+ subscription = null;
113
+ state.media = null;
114
+ state.unavailable = true;
115
+ retry = timers.after(RETRY_MS, subscribe);
116
+ }
117
+ });
118
+ ```
119
+
120
+ Chaque mise à jour vaut `{ ok: true, value, final }` ou
121
+ `{ ok: false, error, final: true }`. Une mise à jour en échec est toujours
122
+ la dernière : l’abonnement est terminé.
123
+
124
+ Les services sont regroupés dans des espaces de noms du SDK : `storage`,
125
+ `http`, `clipboard`, `gameEvents`, et un par source de données (`fps`,
126
+ `telemetry`, `session`, `media`, `stopwatch`, `notes`, `playervox`,
127
+ `journal`, `twitch`). Chaque service figure, avec ses paramètres et son
128
+ résultat, dans la [référence des services](service-reference.md).
129
+
130
+ OverCrow vérifie chaque appel à son arrivée, dans cet ordre : la permission
131
+ ou la capability, les paramètres, l’action de l’utilisateur quand le
132
+ service en demande une, puis le compte quand il en faut un. Les types du
133
+ SDK vous aident à appeler correctement un service ; ce ne sont pas eux qui
134
+ font respecter les règles.
135
+
136
+ ## Erreurs
137
+
138
+ Un appel qui échoue rejette sa promesse avec une `ServiceError`, dont le
139
+ `code` dit pourquoi. Un abonnement qui échoue livre la même erreur dans sa
140
+ dernière mise à jour.
141
+
142
+ <!-- source: docs/content/examples/weather/logic.ts -->
143
+ ```ts
144
+ try {
145
+ const url = `https://api.example.com/v1/forecast/${state.city}?units=${state.units}`;
146
+ const { status, body } = await http.fetch(url, { as: "json" });
147
+ const value = (body as { temperature?: unknown } | null)?.temperature;
148
+ if (status !== 200 || typeof value !== "number") {
149
+ state.status = "unavailable";
150
+ return;
151
+ }
152
+ state.temperature = value;
153
+ state.status = "updated";
154
+ await storage.set({ key, value });
155
+ } catch (error) {
156
+ // permission_denied until the user consents, transport_failed offline…
157
+ state.status = error instanceof ServiceError ? "unavailable" : "failed";
158
+ }
159
+ ```
160
+
161
+ <!-- generated:error-codes -->
162
+ | Code | Signification |
163
+ | --- | --- |
164
+ | `invalid_request` | Les paramètres ne sont pas ceux que le service attend : un membre manque ou est inconnu, n’a pas le bon type ou sort de ses limites. |
165
+ | `permission_denied` | La permission ou la capability n’est pas déclarée dans le manifeste, ou l’utilisateur ne l’a pas accordée. Pour `http.fetch`, aucune règle réseau n’autorise cette URL et cette méthode. Une écriture par formulaire peut aussi le recevoir du fournisseur du compte, pour une écriture qu’il n’autorise pas. |
166
+ | `gesture_required` | Le service ne peut être appelé que pendant une action de l’utilisateur, et cet appel n’a pas eu lieu pendant le traitement d’une telle action, ou cette action a déjà autorisé un autre appel. |
167
+ | `not_connected` | Le service a besoin du compte PlayerVox ou Twitch de l’utilisateur, qui n’est pas connecté pour le moment. |
168
+ | `stale_context` | Ce sur quoi portait l’appel a changé avant la réponse : un autre jeu, un autre compte, un autre lecteur multimédia, un objet supprimé entre-temps. Relisez l’état courant. |
169
+ | `unavailable` | La source d’OverCrow pour ces données a échoué, ou ne peut pas agir pour l’instant. Un abonnement qui se termine ainsi peut être relancé plus tard. |
170
+ | `busy` | Trop d’opérations sont en cours : une confirmation est déjà ouverte, une file ou le budget des réponses réseau est plein, ou le fournisseur demande d’attendre. Réessayez plus tard. |
171
+ | `cancelled` | L’utilisateur a refusé la confirmation, ou a quitté le mode interactif pendant qu’elle était ouverte. |
172
+ | `quota_exceeded` | Un quota est atteint : le stockage, les minuteurs, les notes, les chaînes favorites. |
173
+ | `unsupported` | La cible ne sait pas le faire : un lecteur multimédia qui ne propose pas la commande, par exemple. |
174
+ | `url_invalid` | `http.fetch` : l’URL n’est pas une URL HTTPS absolue qu’OverCrow accepte. |
175
+ | `resolve_failed` | `http.fetch` : le nom d’hôte n’a pas pu être résolu. |
176
+ | `address_denied` | `http.fetch` : le nom d’hôte se résout en une adresse locale, privée ou non publique. |
177
+ | `too_many_addresses` | `http.fetch` : le nom d’hôte se résout en plus d’adresses qu’OverCrow n’en accepte. |
178
+ | `peer_mismatch` | `http.fetch` : le serveur qui a répondu n’est pas à l’une des adresses résolues et vérifiées. |
179
+ | `redirect_denied` | `http.fetch` : le serveur a répondu par une redirection. OverCrow n’en suit aucune : déclarez et demandez l’URL finale. |
180
+ | `encoding_denied` | `http.fetch` : la réponse est compressée ou encodée d’une façon qu’OverCrow n’accepte pas, ou son corps ne se décode pas comme `as` le demande (JSON ou texte invalide). |
181
+ | `content_type_denied` | `http.fetch` : le type de média de la réponse n’est pas de ceux qu’OverCrow accepte pour cette requête. |
182
+ | `response_metadata_limit` | `http.fetch` : la ligne d’état ou les en-têtes de la réponse sont mal formés ou dépassent les limites d’OverCrow. |
183
+ | `request_body_limit` | `http.fetch` : le corps de la requête dépasse 256 Kio. |
184
+ | `response_body_limit` | `http.fetch` : le corps de la réponse dépasse la limite de la règle réseau (`maxResponseBytes`, ou 1 Mio sans lui et pour `as: "image"`). |
185
+ | `image_invalid` | `http.fetch` avec `as: "image"` : la réponse n’est pas une image PNG, JPEG ou WebP dans les limites des images. |
186
+ | `timeout` | `http.fetch` : l’échange a duré plus de 30 secondes. |
187
+ | `transport_failed` | `http.fetch` : la connexion a échoué : pas de réseau, erreur TLS, connexion fermée par le serveur. |
188
+ <!-- /generated:error-codes -->
189
+
190
+ Trois habitudes couvrent la plupart des cas :
191
+
192
+ - **Affichez un état, pas un message d’erreur.** Les codes servent à votre
193
+ logique ; l’utilisateur voit « Prévisions indisponibles », pas
194
+ `transport_failed`.
195
+ - **Réabonnez-vous quand un abonnement s’est terminé.** Une source
196
+ d’OverCrow peut échouer pendant que le widget tourne (la session du
197
+ lecteur multimédia, par exemple) : l’abonnement se termine avec
198
+ `unavailable`. Réabonnez-vous quelques secondes plus tard avec
199
+ `timers.after` ; OverCrow relance la source pour le nouvel abonnement. Le
200
+ widget Média attend cinq secondes :
201
+
202
+ <!-- source: widgets/media/logic.ts -->
203
+ ```ts
204
+ // The subscription ended: the host's source failed. Show it and ask
205
+ // again later; hidden, the timer waits until the widget shows.
206
+ if (subscription === current) {
207
+ subscription = null;
208
+ state.media = null;
209
+ state.unavailable = true;
210
+ retry = timers.after(RETRY_MS, subscribe);
211
+ }
212
+ ```
213
+
214
+ - **Ne réessayez pas en boucle.** `busy` et `quota_exceeded` signalent
215
+ qu’une limite est atteinte : attendez, ou faites-en moins.
216
+
217
+ ## Les appels qui demandent une action de l’utilisateur
218
+
219
+ Les services qui changent quelque chose pour l’utilisateur, ou qui déposent
220
+ quelque chose là où d’autres programmes le lisent, s’appellent **seulement
221
+ pendant une action de l’utilisateur** : pendant que la logique traite l’un
222
+ de ces événements de la vue.
223
+
224
+ <!-- generated:gesture-events -->
225
+ `activate`, `contextmenu`, `keydown`, `input`, `change`, `submit`.
226
+ <!-- /generated:gesture-events -->
227
+
228
+ <!-- source: widgets/stopwatch/logic.ts -->
229
+ ```ts
230
+ export function toggle(): void {
231
+ command(() => stopwatch.toggle());
232
+ }
233
+ ```
234
+
235
+ `toggle` est le gestionnaire `on:activate` du bouton du chronomètre : le
236
+ clic est l’action de l’utilisateur, et `stopwatch.toggle()` est appelé
237
+ pendant son traitement. Le même appel depuis un minuteur, depuis la réponse
238
+ d’un autre service, depuis `onHost` ou depuis une ligne du menu d’options
239
+ est refusé avec `gesture_required`.
240
+
241
+ - Une action de l’utilisateur autorise un seul appel protégé. Appelez le
242
+ service directement dans le gestionnaire, pas après un `await` sur autre
243
+ chose.
244
+ - Les widgets ne reçoivent d’entrées qu’en mode interactif d’OverCrow : un
245
+ appel protégé ne peut donc avoir lieu que dans ce mode.
246
+ - `notes.delete` et `journal.delete` demandent en plus une confirmation à
247
+ l’utilisateur, dans une boîte de dialogue dessinée par OverCrow ; une
248
+ confirmation refusée donne `cancelled`.
249
+
250
+ Les tableaux ci-dessous indiquent, pour chaque service, quand l’appeler.
251
+
252
+ ## Permissions
253
+
254
+ <!-- generated:permission-list -->
255
+ | Permission | Signification | Avec une capability sensible |
256
+ | --- | --- | --- |
257
+ | `network` | Routes HTTPS exactes, joignables par le broker de l’hôte ; au plus 32 règles. | manifeste refusé |
258
+ | `storage` | Stockage clé-valeur tenu par l’hôte, cloisonné par ID de widget, dans la limite de 256 Kio. | données conservées le temps du processus seulement |
259
+ | `clipboardWrite` | Écriture de texte dans le presse-papiers, pendant une action de l’utilisateur en mode interactif. | manifeste refusé |
260
+ | `gameEvents` | Événements de jeu sémantiques nommés `overcrow.game.<name>.v1`, au plus 32. | admis |
261
+ | `capabilities` | Services de l’hôte listés avec les capabilities. | admis |
262
+ <!-- /generated:permission-list -->
263
+
264
+ <!-- generated:permissions -->
265
+ | Permission | Service | Quand l’appeler |
266
+ | --- | --- | --- |
267
+ | `network` | `http.fetch` | À tout moment |
268
+ | `storage` | `storage.get` | À tout moment |
269
+ | `storage` | `storage.set` | À tout moment |
270
+ | `storage` | `storage.remove` | À tout moment |
271
+ | `storage` | `storage.keys` | À tout moment |
272
+ | `clipboardWrite` | `clipboard.writeText` | Seulement pendant une action de l’utilisateur |
273
+ | `gameEvents` | `gameEvents.subscribe` | À tout moment |
274
+
275
+ « Seulement pendant une action de l’utilisateur » est expliqué dans [Les appels qui demandent une action de l’utilisateur](services.md#les-appels-qui-demandent-une-action-de-lutilisateur).
276
+ <!-- /generated:permissions -->
277
+
278
+ ### Règles réseau
279
+
280
+ `network` est une liste de règles. Une règle autorise les requêtes vers
281
+ exactement une origine HTTPS, une méthode et un chemin ; un segment
282
+ `{name}` du chemin est un paramètre typé, et seuls les paramètres de
283
+ requête déclarés sont acceptés.
284
+
285
+ <!-- source: widgets/warframe-market/manifest.json -->
286
+ ```json
287
+ "permissions": {
288
+ "network": [
289
+ {
290
+ "origin": "https://api.warframe.market",
291
+ "method": "GET",
292
+ "path": "/v2/versions",
293
+ "maxResponseBytes": 4096
294
+ },
295
+ {
296
+ "origin": "https://api.warframe.market",
297
+ "method": "GET",
298
+ "path": "/v2/items",
299
+ "maxResponseBytes": 3145728
300
+ },
301
+ {
302
+ "origin": "https://api.warframe.market",
303
+ "method": "GET",
304
+ "path": "/v2/orders/item/{slug}",
305
+ "pathParams": {
306
+ "slug": {
307
+ "type": "slug",
308
+ "maxLength": 96
309
+ }
310
+ },
311
+ "maxResponseBytes": 2097152
312
+ }
313
+ ],
314
+ "storage": true,
315
+ "clipboardWrite": true
316
+ },
317
+ ```
318
+
319
+ <!-- generated:network-rule-fields -->
320
+ | Champ | Type | Obligatoire | Signification |
321
+ | --- | --- | --- | --- |
322
+ | `origin` | `origin` | oui | Origine canonique `https://host[:port]`, hôte ≤ 253 octets avec des labels ≤ 63 octets ; ni identifiants, ni adresse IP littérale, ni nom local. |
323
+ | `method` | `GET` \| `POST` \| `PUT` \| `PATCH` \| `DELETE` | oui | Une seule méthode. |
324
+ | `path` | texte ≤ 1 Kio | oui | Chemin complet ; les segments `{name}` sont des paramètres de chemin typés. |
325
+ | `pathParams` | `name → ParameterConstraint` | non | Contrainte de chaque segment `{name}`, au plus 8. |
326
+ | `queryParams` | `name → ParameterConstraint` | non | Paramètres de requête admis, au plus 16, chacun éventuellement `required` ; les autres sont refusés. |
327
+ | `maxResponseBytes` | entier de 1 à 3145728 | non | Plus grand corps de réponse de cette route, de 1 à 3 Mio ; 1 Mio quand il est absent. Sans effet pour `as: "image"`, qui garde 1 Mio. Quand plusieurs règles autorisent une requête, la plus grande limite s’applique. |
328
+ <!-- /generated:network-rule-fields -->
329
+
330
+ Chaque paramètre de chemin ou de requête porte une contrainte :
331
+
332
+ <!-- generated:parameter-constraints -->
333
+ | Type | Forme | Accepte |
334
+ | --- | --- | --- |
335
+ | `integer` | `{ min, max }` | Entier décimal sans zéro initial, de 0 à 2^53 - 1. |
336
+ | `slug` | `{ maxLength }` | Lettres ASCII majuscules ou minuscules, chiffres, `_` et `-`, au moins un caractère ; `maxLength` de 1 à 128 octets. |
337
+ | `enum` | liste de `literal segment` ≤ 32 | L’une des valeurs listées, chacune ≤ 128 octets. |
338
+ | `string` | `{ maxLength }` | Paramètres de requête seulement ; tout texte sans caractère de contrôle ; `maxLength` de 1 à 256 octets. |
339
+ <!-- /generated:parameter-constraints -->
340
+
341
+ La requête sort par le broker d’OverCrow, jamais du processus du widget.
342
+ Le broker :
343
+
344
+ - refuse toute URL qu’aucune règle n’autorise (`permission_denied`), avant
345
+ toute requête DNS ;
346
+ - ne suit aucune redirection, et n’envoie ni cookie, ni identifiant, ni
347
+ en-tête de proxy ;
348
+ - refuse les adresses locales et privées : un widget ne peut donc pas
349
+ joindre le routeur de l’utilisateur ni un autre programme de la machine ;
350
+ - limite chaque échange : 256 Kio pour le corps d’une requête, 30 secondes
351
+ en tout, et 1 Mio pour le corps d’une réponse, sauf si la règle déclare
352
+ un `maxResponseBytes` plus grand, jusqu’à 3 Mio. Les relecteurs et les
353
+ utilisateurs voient cette limite.
354
+
355
+ `http.fetch(url, { as })` décode le corps comme vous le demandez :
356
+ `"json"`, `"text"`, `"bytes"` (un `ArrayBuffer`) ou `"image"`, qui donne, à
357
+ la place des octets, un identifiant d’image à lier à un élément `image`. Un
358
+ `body` de type chaîne est envoyé en `text/plain`, et toute autre valeur en
359
+ JSON, sauf si `contentType` en décide autrement. Un statut HTTP d’erreur
360
+ n’est pas un échec de l’appel : vérifiez `status`.
361
+
362
+ <!-- source: docs/content/examples/weather/logic.ts -->
363
+ ```ts
364
+ const url = `https://api.example.com/v1/forecast/${state.city}?units=${state.units}`;
365
+ const { status, body } = await http.fetch(url, { as: "json" });
366
+ const value = (body as { temperature?: unknown } | null)?.temperature;
367
+ if (status !== 200 || typeof value !== "number") {
368
+ state.status = "unavailable";
369
+ return;
370
+ }
371
+ ```
372
+
373
+ Un widget a au plus quatre requêtes en cours à la fois, et elles partagent
374
+ un budget d’octets de réponse : une requête qui n’y tient pas échoue
375
+ aussitôt avec `busy`.
376
+
377
+ ### Stockage
378
+
379
+ `storage` est un stockage clé-valeur qu’OverCrow tient pour votre seul
380
+ widget : `storage.get({ key })`, `storage.set({ key, value })`,
381
+ `storage.remove({ key })` et `storage.keys()`. Une valeur est n’importe
382
+ quelle valeur JSON. Il n’y a aucun accès aux fichiers.
383
+
384
+ <!-- source: docs/content/examples/countdown/logic.ts -->
385
+ ```ts
386
+ function setRounds(rounds: number): void {
387
+ state.rounds = rounds;
388
+ paint();
389
+ // Storage needs the user's consent: without it the count lasts as long
390
+ // as the widget runs.
391
+ storage.set({ key: "rounds", value: rounds }).catch(() => {});
392
+ }
393
+ ```
394
+
395
+ Le stockage contient au plus 512 clés et 256 Kio en tout, 64 Kio par
396
+ valeur ; au-delà, `storage.set` échoue avec `quota_exceeded` et ne change
397
+ rien. Une écriture reçoit sa réponse une fois qu’elle est sur le disque.
398
+ Désinstaller le widget efface son stockage, et une session de développement
399
+ (`overcrow-widget dev`) ne lit ni n’écrit jamais le stockage d’un widget
400
+ installé.
401
+
402
+ ### Presse-papiers
403
+
404
+ `clipboard.writeText({ text })` place du texte dans le presse-papiers,
405
+ seulement pendant une action de l’utilisateur. Un widget ne peut pas lire
406
+ le presse-papiers.
407
+
408
+ <!-- source: widgets/warframe-market/logic.ts -->
409
+ ```ts
410
+ clipboard.writeText({ text: whisperLine(order, detail.name) }).then(
411
+ () => {
412
+ if (mine === selection) state.copy = { side, id, state: "copied" };
413
+ },
414
+ () => {
415
+ if (mine === selection) state.copy = { side, id, state: "failed" };
416
+ },
417
+ );
418
+ ```
419
+
420
+ Le texte que l’utilisateur sélectionne dans un élément `text` doté de
421
+ l’attribut `selectable` est copié par OverCrow lui-même, sans aucune
422
+ permission.
423
+
424
+ ### Événements de jeu
425
+
426
+ `gameEvents` liste les événements de jeu nommés que le widget veut
427
+ recevoir, chacun de la forme `overcrow.game.<name>.v1`.
428
+ `gameEvents.subscribe(listener)` livre ensuite `{ event, at }` chaque fois
429
+ que l’un d’eux se produit.
430
+
431
+ ## Capabilities
432
+
433
+ Une capability donne accès à des données ou à des actions que détient
434
+ OverCrow : les ressources qu’utilise le jeu, le lecteur multimédia, les
435
+ notes de l’utilisateur, ses comptes PlayerVox et Twitch.
436
+
437
+ <!-- generated:capability-list -->
438
+ | Capability | Sensible | Compte | Signification |
439
+ | --- | --- | --- | --- |
440
+ | `telemetry.read` | non | — | Mesures de CPU, de mémoire et de température du jeu actif. |
441
+ | `fps.read` | non | — | Fréquence d’images du jeu actif, quand l’hôte dispose d’une source. |
442
+ | `media.read` | **oui** | — | Métadonnées du morceau en cours de lecture, et l’image de sa pochette. |
443
+ | `media.control` | **oui** | — | Précédent, lecture/pause et suivant. |
444
+ | `session.read` | non | — | Durée de la session du jeu actif, sans l’identité du jeu. |
445
+ | `stopwatch.read` | non | — | État du chronomètre manuel de l’hôte, unique, et de ses raccourcis. |
446
+ | `stopwatch.control` | non | — | Démarrer, mettre en pause et réinitialiser le chronomètre manuel de l’hôte, unique. |
447
+ | `notes.read` | **oui** | — | Les notes et listes de tâches de l’utilisateur : un seul document, commun à tous les jeux. |
448
+ | `notes.write` | **oui** | — | Créer, sélectionner, enregistrer, cocher et supprimer des notes ; le texte ne passe que par un formulaire lié à un intent d’écriture. |
449
+ | `playervox.score.read` | **oui** | — | Note publique PlayerVox du jeu actif ; sensible parce qu’elle révèle le jeu. |
450
+ | `playervox.rating.read` | **oui** | PlayerVox | La note que l’utilisateur a lui-même donnée au jeu actif. |
451
+ | `playervox.rating.write` | **oui** | PlayerVox | Publier une note et un avis, par un formulaire lié à un intent d’écriture. |
452
+ | `playervox.reviews.read` | **oui** | PlayerVox | Avis des joueurs sur le jeu actif, par pages, limités sur demande aux joueurs suivis. |
453
+ | `journal.read` | **oui** | — | Sessions de jeu du jeu actif : les sessions locales, plus celles du cloud tant que PlayerVox est connecté. |
454
+ | `journal.delete` | **oui** | — | Supprimer une session du journal, après une confirmation demandée par l’hôte ; les sessions du cloud exigent PlayerVox. |
455
+ | `twitch.chat.read` | **oui** | Twitch | Rejoindre, lire et quitter le chat d’une chaîne Twitch, et conserver des chaînes favorites. |
456
+ | `twitch.chat.compose` | **oui** | Twitch | Envoyer un message dans le chat, par un formulaire lié à un intent d’écriture ; l’hôte admet 20 messages par 30 s et répond `busy` au-delà. |
457
+ <!-- /generated:capability-list -->
458
+
459
+ <!-- generated:capabilities -->
460
+ | Capability | Sensible | Service | Quand l’appeler |
461
+ | --- | --- | --- | --- |
462
+ | `telemetry.read` | non | `telemetry.subscribe` | À tout moment |
463
+ | `fps.read` | non | `fps.subscribe` | À tout moment |
464
+ | `media.read` | **oui** | `media.subscribe` | À tout moment |
465
+ | `media.control` | **oui** | `media.previous` | Seulement pendant une action de l’utilisateur |
466
+ | `media.control` | **oui** | `media.playPause` | Seulement pendant une action de l’utilisateur |
467
+ | `media.control` | **oui** | `media.next` | Seulement pendant une action de l’utilisateur |
468
+ | `session.read` | non | `session.subscribe` | À tout moment |
469
+ | `stopwatch.read` | non | `stopwatch.subscribe` | À tout moment |
470
+ | `stopwatch.control` | non | `stopwatch.toggle` | Seulement pendant une action de l’utilisateur |
471
+ | `stopwatch.control` | non | `stopwatch.reset` | Seulement pendant une action de l’utilisateur |
472
+ | `notes.read` | **oui** | `notes.subscribe` | À tout moment |
473
+ | `notes.write` | **oui** | `notes.create` | Seulement pendant une action de l’utilisateur |
474
+ | `notes.write` | **oui** | `notes.select` | Seulement pendant une action de l’utilisateur |
475
+ | `notes.write` | **oui** | `notes.setItem` | Seulement pendant une action de l’utilisateur |
476
+ | `notes.write` | **oui** | `notes.delete` | Seulement pendant une action de l’utilisateur |
477
+ | `notes.write` | **oui** | [formulaire `notes.save`](forms.md#notessave) | Quand l’utilisateur valide le formulaire |
478
+ | `playervox.score.read` | **oui** | `playervox.score.subscribe` | À tout moment |
479
+ | `playervox.rating.read` | **oui** | `playervox.rating.subscribe` | À tout moment |
480
+ | `playervox.rating.write` | **oui** | [formulaire `playervox.rating.publish`](forms.md#playervoxratingpublish) | Quand l’utilisateur valide le formulaire |
481
+ | `playervox.reviews.read` | **oui** | `playervox.reviews.subscribe` | À tout moment |
482
+ | `playervox.reviews.read` | **oui** | `playervox.reviews.page` | À tout moment |
483
+ | `journal.read` | **oui** | `journal.subscribe` | À tout moment |
484
+ | `journal.read` | **oui** | `journal.page` | À tout moment |
485
+ | `journal.delete` | **oui** | `journal.delete` | Seulement pendant une action de l’utilisateur |
486
+ | `twitch.chat.read` | **oui** | `twitch.chat.subscribe` | À tout moment |
487
+ | `twitch.chat.read` | **oui** | `twitch.chat.join` | Seulement pendant une action de l’utilisateur |
488
+ | `twitch.chat.read` | **oui** | `twitch.chat.leave` | Seulement pendant une action de l’utilisateur |
489
+ | `twitch.chat.read` | **oui** | `twitch.chat.favorite` | Seulement pendant une action de l’utilisateur |
490
+ | `twitch.chat.compose` | **oui** | [formulaire `twitch.chat.send`](forms.md#twitchchatsend) | Quand l’utilisateur valide le formulaire |
491
+
492
+ « Seulement pendant une action de l’utilisateur » est expliqué dans [Les appels qui demandent une action de l’utilisateur](services.md#les-appels-qui-demandent-une-action-de-lutilisateur).
493
+ <!-- /generated:capabilities -->
494
+
495
+ Une ligne dont le service est un formulaire correspond à une écriture que
496
+ l’utilisateur saisit lui-même : voir
497
+ [les formulaires qui écrivent des données de l’utilisateur](forms.md#les-formulaires-qui-écrivent-des-données-de-lutilisateur).
498
+
499
+ ### Capabilities sensibles
500
+
501
+ Une capability **sensible** révèle des données personnelles ou le jeu en
502
+ cours. Un widget qui en déclare une :
503
+
504
+ - ne peut pas déclarer aussi `network` ni `clipboardWrite` : le manifeste
505
+ est refusé ;
506
+ - a un stockage qui ne dure que le temps de son processus, et qui est vidé
507
+ quand le widget redémarre.
508
+
509
+ Ce qu’un tel widget lit ne peut donc pas quitter la machine par son
510
+ intermédiaire. Si votre widget a besoin à la fois d’une API HTTP et d’une
511
+ capability sensible, faites deux widgets.
512
+
513
+ ### Comptes
514
+
515
+ Certaines capabilities ont besoin du compte PlayerVox ou Twitch de
516
+ l’utilisateur. La connexion appartient à OverCrow : c’est lui qui dessine
517
+ l’écran de connexion, conserve les jetons et affiche son propre panneau
518
+ par-dessus le widget tant que le compte est déconnecté. Un widget ne voit
519
+ jamais un jeton ; il ne reçoit que les données que décrit sa capability, et
520
+ ses appels échouent avec `not_connected` tant que le compte n’est pas
521
+ connecté.
522
+
523
+ ### Des données qui changent
524
+
525
+ - Un abonnement peut livrer `null` (aucun jeu actif, aucun lecteur
526
+ multimédia) : affichez un état vide.
527
+ - Certains abonnements indiquent *quoi relire* plutôt que les données
528
+ elles-mêmes. `playervox.reviews.subscribe` et `journal.subscribe` livrent
529
+ une `revision` : quand elle change, relisez votre page avec
530
+ `playervox.reviews.page` ou `journal.page`.
531
+ - `twitch.chat.subscribe` livre des changements plutôt que le chat entier,
532
+ au plus toutes les 100 ms : les nouveaux messages, les messages modifiés
533
+ (même `id`), les IDs des messages supprimés, et la liste entière quand
534
+ `reset` vaut `true`.
535
+ - Un horodatage fourni avec son propre `offsetMinutes` doit être formaté
536
+ avec celui-ci ; voir
537
+ [heure, dates et nombres](logic.md#heure-dates-et-nombres).
538
+
539
+ La forme de chaque résultat figure dans les
540
+ [formes de résultat](result-shapes.md).