@plitzi/sdk-server 0.37.2 → 0.37.4

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 (359) hide show
  1. package/CHANGELOG.md +1170 -0
  2. package/README.md +100 -7
  3. package/dist/actions.d.ts +6 -2
  4. package/dist/actions.js +5 -2
  5. package/dist/adapters/cloudAdapters.js +4 -3
  6. package/dist/adapters/jsonAdapters.js +28 -6
  7. package/dist/adapters/jsonAdapters.test.d.ts +1 -0
  8. package/dist/auth.d.ts +7 -4
  9. package/dist/auth.js +8 -6
  10. package/dist/core/auth/api.d.ts +29 -1
  11. package/dist/core/auth/api.js +47 -13
  12. package/dist/core/auth/createAuth.d.ts +4 -0
  13. package/dist/core/auth/createAuth.js +3 -3
  14. package/dist/core/auth/credentials.d.ts +3 -0
  15. package/dist/core/auth/credentials.js +1 -1
  16. package/dist/core/auth/csrf.d.ts +25 -1
  17. package/dist/core/auth/csrf.js +29 -4
  18. package/dist/core/auth/renewal.d.ts +26 -0
  19. package/dist/core/auth/renewal.js +24 -0
  20. package/dist/core/auth/routes.js +8 -6
  21. package/dist/core/auth/session.d.ts +45 -0
  22. package/dist/core/auth/session.js +47 -1
  23. package/dist/core/auth/sessionActivity.d.ts +11 -0
  24. package/dist/core/auth/sessionActivity.js +14 -0
  25. package/dist/core/auth/throttle.d.ts +15 -0
  26. package/dist/core/auth/throttle.js +29 -1
  27. package/dist/core/auth/totp.d.ts +9 -1
  28. package/dist/core/auth/totp.js +11 -6
  29. package/dist/core/createServer.actions.test.d.ts +1 -0
  30. package/dist/core/createServer.d.ts +14 -1
  31. package/dist/core/createServer.functions.test.d.ts +1 -0
  32. package/dist/core/createServer.js +22 -12
  33. package/dist/core/fontStore.js +1 -1
  34. package/dist/core/handlers/authRouteHandlers.d.ts +1 -1
  35. package/dist/core/handlers/authRouteHandlers.js +57 -21
  36. package/dist/core/handlers/csrfMiddleware.d.ts +23 -0
  37. package/dist/core/handlers/csrfMiddleware.js +31 -7
  38. package/dist/core/handlers/csrfMiddleware.test.d.ts +1 -0
  39. package/dist/core/handlers/oauthRouteHandlers.js +5 -3
  40. package/dist/core/handlers/socialRouteHandlers.d.ts +1 -1
  41. package/dist/core/handlers/socialRouteHandlers.js +2 -1
  42. package/dist/core/http/dispatcher.d.ts +9 -1
  43. package/dist/core/http/dispatcher.js +38 -11
  44. package/dist/core/http/navigation.d.ts +5 -2
  45. package/dist/core/http/navigation.js +7 -4
  46. package/dist/core/http/socketResponse.d.ts +18 -0
  47. package/dist/core/http/socketResponse.js +59 -0
  48. package/dist/core/http/sse.d.ts +26 -0
  49. package/dist/core/http/sse.js +78 -0
  50. package/dist/core/http/stages/authRoutes.js +3 -1
  51. package/dist/core/http/stages/exchangeRoute.test.d.ts +1 -0
  52. package/dist/core/http/stages/middlewares.d.ts +1 -1
  53. package/dist/core/http/stages/middlewares.js +16 -10
  54. package/dist/core/http/stages/middlewares.test.d.ts +1 -0
  55. package/dist/core/http/stages/oauth.js +2 -2
  56. package/dist/core/http/stages/sessionRenewal.d.ts +16 -0
  57. package/dist/core/http/stages/sessionRenewal.js +81 -0
  58. package/dist/core/http/stages/sessionRenewal.test.d.ts +1 -0
  59. package/dist/core/http/stages/signInRoute.d.ts +2 -0
  60. package/dist/core/http/stages/signInRoute.js +139 -0
  61. package/dist/core/http/stages/signInRoute.test.d.ts +1 -0
  62. package/dist/core/http/types.d.ts +9 -0
  63. package/dist/core/http/webExchange.d.ts +18 -0
  64. package/dist/core/http/webExchange.js +53 -0
  65. package/dist/core/oauth/authorize.js +37 -13
  66. package/dist/core/oauth/consentPage.js +11 -0
  67. package/dist/core/oauth/issueContext.d.ts +14 -0
  68. package/dist/core/oauth/issueContext.js +32 -0
  69. package/dist/core/oauth/records.d.ts +7 -0
  70. package/dist/core/oauth/register.d.ts +2 -0
  71. package/dist/core/oauth/register.js +32 -11
  72. package/dist/core/oauth/register.test.d.ts +1 -0
  73. package/dist/core/oauth/token.js +21 -6
  74. package/dist/core/oauth/token.test.d.ts +1 -0
  75. package/dist/core/requestParser.d.ts +4 -0
  76. package/dist/core/requestParser.js +14 -7
  77. package/dist/core/sdkAssets.js +1 -1
  78. package/dist/core/server/baseServer.d.ts +10 -0
  79. package/dist/core/server/baseServer.js +42 -11
  80. package/dist/core/server/closeOnSignals.js +4 -3
  81. package/dist/core/server/drain.d.ts +18 -0
  82. package/dist/core/server/drain.js +62 -0
  83. package/dist/core/server/drain.test.d.ts +1 -0
  84. package/dist/core/server/fleet/channel.d.ts +103 -0
  85. package/dist/core/server/fleet/channel.js +191 -0
  86. package/dist/core/server/fleet/channel.test.d.ts +1 -0
  87. package/dist/core/server/fleet/fixtures/fleetServer.d.ts +1 -0
  88. package/dist/core/server/fleet/fleet.integration.test.d.ts +1 -0
  89. package/dist/core/server/fleet/link.d.ts +23 -0
  90. package/dist/core/server/fleet/link.js +70 -0
  91. package/dist/core/server/fleet/relay.d.ts +11 -0
  92. package/dist/core/server/fleet/relay.js +104 -0
  93. package/dist/core/server/fleet/relay.test.d.ts +1 -0
  94. package/dist/core/server/fleet/role.d.ts +46 -0
  95. package/dist/core/server/fleet/role.js +59 -0
  96. package/dist/core/server/fleet/role.test.d.ts +1 -0
  97. package/dist/core/server/fleet/stores.d.ts +7 -0
  98. package/dist/core/server/fleet/stores.js +19 -0
  99. package/dist/core/server/fleet/supervisor.d.ts +26 -0
  100. package/dist/core/server/fleet/supervisor.js +108 -0
  101. package/dist/core/server/fleet/supervisor.test.d.ts +1 -0
  102. package/dist/core/server/pageServer.js +34 -5
  103. package/dist/core/services/action.js +10 -2
  104. package/dist/core/services/functionRoutes.d.ts +9 -0
  105. package/dist/core/services/functionRoutes.js +47 -0
  106. package/dist/core/services/realtime.d.ts +8 -0
  107. package/dist/core/services/realtime.js +57 -0
  108. package/dist/core/services/registry.js +6 -2
  109. package/dist/core/staticFiles.js +12 -4
  110. package/dist/core/staticFiles.test.d.ts +1 -0
  111. package/dist/core/transports.d.ts +13 -3
  112. package/dist/core/transports.js +14 -5
  113. package/dist/functions-api.d.ts +281 -0
  114. package/dist/functions.d.ts +19 -0
  115. package/dist/functions.js +5 -0
  116. package/dist/functionsRunner.d.ts +15 -0
  117. package/dist/functionsRunner.js +6 -0
  118. package/dist/handlers.d.ts +2 -2
  119. package/dist/handlers.js +2 -2
  120. package/dist/helpers/atomicFile.d.ts +10 -0
  121. package/dist/helpers/atomicFile.js +33 -0
  122. package/dist/helpers/atomicFile.test.d.ts +1 -0
  123. package/dist/helpers/buildResponseHelpers.js +35 -11
  124. package/dist/helpers/buildServerInfo.js +4 -2
  125. package/dist/helpers/buildServerInfo.test.d.ts +1 -0
  126. package/dist/helpers/cache/CompressedFileCache.d.ts +18 -0
  127. package/dist/helpers/cache/CompressedFileCache.js +44 -0
  128. package/dist/helpers/cache/CompressedFileCache.test.d.ts +1 -0
  129. package/dist/helpers/cache/cacheManager.d.ts +1 -1
  130. package/dist/helpers/cache/cacheManager.js +2 -1
  131. package/dist/helpers/cache/cacheManager.test.d.ts +1 -0
  132. package/dist/helpers/cache/index.d.ts +1 -1
  133. package/dist/helpers/cache/keys.d.ts +15 -1
  134. package/dist/helpers/cache/keys.js +47 -5
  135. package/dist/helpers/cache/serverCaches.d.ts +7 -1
  136. package/dist/helpers/compress.d.ts +3 -1
  137. package/dist/helpers/compress.js +11 -3
  138. package/dist/helpers/hydrationPayload.d.ts +11 -0
  139. package/dist/helpers/hydrationPayload.js +51 -0
  140. package/dist/helpers/hydrationPayload.test.d.ts +1 -0
  141. package/dist/helpers/metrics.d.ts +1 -1
  142. package/dist/helpers/metrics.js +3 -2
  143. package/dist/helpers/outboundGuard.d.ts +14 -6
  144. package/dist/helpers/outboundGuard.js +132 -8
  145. package/dist/helpers/paintedCookie.d.ts +8 -0
  146. package/dist/helpers/paintedCookie.js +13 -0
  147. package/dist/helpers/reportReactBuild.d.ts +9 -0
  148. package/dist/helpers/reportReactBuild.js +18 -0
  149. package/dist/helpers/reportReactBuild.test.d.ts +1 -0
  150. package/dist/helpers/serverLog.d.ts +25 -1
  151. package/dist/helpers/serverLog.js +68 -3
  152. package/dist/helpers/serverLog.test.d.ts +1 -0
  153. package/dist/helpers/wsFrame.d.ts +3 -0
  154. package/dist/helpers/wsFrame.js +5 -0
  155. package/dist/index.d.ts +6 -1
  156. package/dist/index.js +5 -2
  157. package/dist/kernel.d.ts +2 -1
  158. package/dist/kernel.js +3 -2
  159. package/dist/modules/actions/connectorWrite.js +2 -1
  160. package/dist/modules/actions/index.d.ts +29 -10
  161. package/dist/modules/actions/index.js +43 -6
  162. package/dist/modules/actions/jobs/failureStreak.d.ts +17 -0
  163. package/dist/modules/actions/jobs/failureStreak.js +47 -0
  164. package/dist/modules/actions/jobs/failureStreak.test.d.ts +1 -0
  165. package/dist/modules/actions/jobs/index.d.ts +2 -1
  166. package/dist/modules/actions/jobs/index.js +5 -3
  167. package/dist/modules/actions/jobs/memoryQueue.d.ts +3 -0
  168. package/dist/modules/actions/jobs/memoryQueue.js +17 -1
  169. package/dist/modules/actions/jobs/scheduler.d.ts +2 -0
  170. package/dist/modules/actions/jobs/scheduler.js +12 -7
  171. package/dist/modules/actions/jobs/worker.d.ts +3 -1
  172. package/dist/modules/actions/jobs/worker.js +9 -4
  173. package/dist/modules/actions/moduleFor.js +5 -2
  174. package/dist/modules/actions/runtime/errors.d.ts +12 -0
  175. package/dist/modules/actions/runtime/errors.js +16 -1
  176. package/dist/modules/actions/runtime/kvChange.d.ts +27 -0
  177. package/dist/modules/actions/runtime/kvChange.js +23 -0
  178. package/dist/modules/actions/runtime/kvList.d.ts +51 -0
  179. package/dist/modules/actions/runtime/kvList.js +52 -0
  180. package/dist/modules/actions/runtime/kvStore.d.ts +8 -0
  181. package/dist/modules/actions/runtime/kvStore.js +46 -20
  182. package/dist/modules/actions/runtime/memoryKv.d.ts +3 -0
  183. package/dist/modules/actions/runtime/memoryKv.js +19 -1
  184. package/dist/modules/actions/runtime/namespaceKv.d.ts +4 -6
  185. package/dist/modules/actions/runtime/namespaceKv.js +15 -3
  186. package/dist/modules/actions/runtime/namespaceKv.test.d.ts +1 -0
  187. package/dist/modules/actions/runtime/precheck.js +4 -8
  188. package/dist/modules/actions/runtime/rateLimit.d.ts +19 -0
  189. package/dist/modules/actions/runtime/rateLimit.js +19 -0
  190. package/dist/modules/actions/runtime/redisKv.d.ts +27 -0
  191. package/dist/modules/actions/runtime/redisKv.integration.test.d.ts +1 -0
  192. package/dist/modules/actions/runtime/redisKv.js +46 -0
  193. package/dist/modules/actions/runtime/report.js +2 -1
  194. package/dist/modules/actions/runtime/runAction.d.ts +10 -2
  195. package/dist/modules/actions/runtime/runAction.js +52 -116
  196. package/dist/modules/actions/runtime/runLogger.d.ts +5 -0
  197. package/dist/modules/actions/runtime/runLogger.js +8 -2
  198. package/dist/modules/actions/runtime/signing.d.ts +20 -0
  199. package/dist/modules/actions/runtime/signing.js +25 -0
  200. package/dist/modules/actions/runtime/signing.test.d.ts +1 -0
  201. package/dist/modules/actions/runtime/taskContext.d.ts +33 -0
  202. package/dist/modules/actions/runtime/taskContext.js +124 -0
  203. package/dist/modules/actions/tasks/builtins.js +5 -1
  204. package/dist/modules/actions/tasks/flow.js +81 -10
  205. package/dist/modules/actions/tasks/helpers.js +2 -2
  206. package/dist/modules/actions/tasks/http.js +2 -3
  207. package/dist/modules/actions/tasks/kv.js +39 -0
  208. package/dist/modules/actions/tasks/list.d.ts +2 -0
  209. package/dist/modules/actions/tasks/list.js +145 -0
  210. package/dist/modules/actions/tasks/realtime.d.ts +2 -0
  211. package/dist/modules/actions/tasks/realtime.js +104 -0
  212. package/dist/modules/actions/tasks/registry.d.ts +10 -1
  213. package/dist/modules/actions/tasks/registry.js +17 -6
  214. package/dist/modules/actions/transport/callHandler.js +5 -2
  215. package/dist/modules/actions/transport/catalogHandler.d.ts +5 -2
  216. package/dist/modules/actions/transport/catalogHandler.js +3 -2
  217. package/dist/modules/actions/transport/stream.d.ts +4 -5
  218. package/dist/modules/actions/transport/stream.js +12 -76
  219. package/dist/modules/actions/transport/webhookHandler.js +4 -3
  220. package/dist/modules/actions/types.d.ts +86 -3
  221. package/dist/modules/connectors/engine.js +3 -5
  222. package/dist/modules/functions/build.d.ts +22 -0
  223. package/dist/modules/functions/build.js +122 -0
  224. package/dist/modules/functions/build.test.d.ts +1 -0
  225. package/dist/modules/functions/capabilities.d.ts +22 -0
  226. package/dist/modules/functions/capabilities.js +228 -0
  227. package/dist/modules/functions/config.d.ts +34 -0
  228. package/dist/modules/functions/config.js +24 -0
  229. package/dist/modules/functions/context.d.ts +17 -0
  230. package/dist/modules/functions/context.js +88 -0
  231. package/dist/modules/functions/contract.d.ts +121 -0
  232. package/dist/modules/functions/contract.js +9 -0
  233. package/dist/modules/functions/driver.d.ts +36 -0
  234. package/dist/modules/functions/driver.js +150 -0
  235. package/dist/modules/functions/load.d.ts +15 -0
  236. package/dist/modules/functions/load.js +45 -0
  237. package/dist/modules/functions/load.test.d.ts +1 -0
  238. package/dist/modules/functions/local.d.ts +29 -0
  239. package/dist/modules/functions/local.js +61 -0
  240. package/dist/modules/functions/local.test.d.ts +1 -0
  241. package/dist/modules/functions/manifest.d.ts +24 -0
  242. package/dist/modules/functions/manifest.js +163 -0
  243. package/dist/modules/functions/manifest.test.d.ts +1 -0
  244. package/dist/modules/functions/native.d.ts +8 -0
  245. package/dist/modules/functions/native.js +21 -0
  246. package/dist/modules/functions/native.test.d.ts +1 -0
  247. package/dist/modules/functions/protocol.d.ts +216 -0
  248. package/dist/modules/functions/protocol.js +18 -0
  249. package/dist/modules/functions/routes.d.ts +36 -0
  250. package/dist/modules/functions/routes.js +181 -0
  251. package/dist/modules/functions/routes.test.d.ts +1 -0
  252. package/dist/modules/functions/runner/messages.d.ts +5 -0
  253. package/dist/modules/functions/runner/messages.js +188 -0
  254. package/dist/modules/functions/runner/remote.d.ts +19 -0
  255. package/dist/modules/functions/runner/remote.js +116 -0
  256. package/dist/modules/functions/runner/remote.test.d.ts +1 -0
  257. package/dist/modules/functions/runner/service.d.ts +32 -0
  258. package/dist/modules/functions/runner/service.js +209 -0
  259. package/dist/modules/functions/sandbox/guest.d.ts +45 -0
  260. package/dist/modules/functions/sandbox/guest.js +660 -0
  261. package/dist/modules/functions/sandbox/isolate.d.ts +37 -0
  262. package/dist/modules/functions/sandbox/isolate.js +347 -0
  263. package/dist/modules/functions/sandbox/isolate.test.d.ts +1 -0
  264. package/dist/modules/functions/sandbox/prelude.d.ts +2 -0
  265. package/dist/modules/functions/sandbox/prelude.js +49 -0
  266. package/dist/modules/functions/space.d.ts +40 -0
  267. package/dist/modules/functions/space.js +162 -0
  268. package/dist/modules/functions/testing/tasksOf.d.ts +4 -0
  269. package/dist/modules/functions/tryEntry.d.ts +9 -0
  270. package/dist/modules/functions/tryEntry.js +49 -0
  271. package/dist/modules/mongo/kv.js +31 -0
  272. package/dist/modules/mysql/accounts.js +19 -9
  273. package/dist/modules/mysql/index.d.ts +2 -1
  274. package/dist/modules/mysql/jobs/index.d.ts +1 -1
  275. package/dist/modules/mysql/jobs/kv.js +30 -0
  276. package/dist/modules/mysql/jobs/schema.d.ts +9 -0
  277. package/dist/modules/mysql/jobs/schema.js +21 -4
  278. package/dist/modules/mysql/schema.js +25 -0
  279. package/dist/modules/mysql/sessions.d.ts +1 -11
  280. package/dist/modules/mysql/sessions.js +6 -1
  281. package/dist/modules/realtime/declarations.d.ts +11 -0
  282. package/dist/modules/realtime/declarations.js +26 -0
  283. package/dist/modules/realtime/grants.d.ts +23 -0
  284. package/dist/modules/realtime/grants.js +61 -0
  285. package/dist/modules/realtime/handlers.d.ts +74 -0
  286. package/dist/modules/realtime/handlers.js +224 -0
  287. package/dist/modules/realtime/hub.d.ts +62 -0
  288. package/dist/modules/realtime/hub.js +141 -0
  289. package/dist/modules/realtime/index.d.ts +51 -0
  290. package/dist/modules/realtime/index.js +62 -0
  291. package/dist/modules/realtime/memoryPubSub.d.ts +10 -0
  292. package/dist/modules/realtime/memoryPubSub.js +43 -0
  293. package/dist/modules/realtime/realtime.test.d.ts +1 -0
  294. package/dist/modules/realtime/redisPubSub.d.ts +24 -0
  295. package/dist/modules/realtime/redisPubSub.js +36 -0
  296. package/dist/modules/realtime/redisPubSub.test.d.ts +1 -0
  297. package/dist/modules/realtime/socket.d.ts +25 -0
  298. package/dist/modules/realtime/socket.js +122 -0
  299. package/dist/modules/realtime/socket.test.d.ts +1 -0
  300. package/dist/modules/rsc/handler.d.ts +16 -0
  301. package/dist/modules/rsc/handler.js +17 -10
  302. package/dist/modules/rsc/handler.test.d.ts +1 -0
  303. package/dist/modules/rsc/resolveRscData.js +2 -1
  304. package/dist/modules/runtime/bundle.d.ts +24 -0
  305. package/dist/modules/runtime/bundle.js +102 -0
  306. package/dist/modules/runtime/contract.d.ts +37 -0
  307. package/dist/modules/runtime/contract.js +21 -0
  308. package/dist/modules/runtime/entry.test.d.ts +1 -0
  309. package/dist/modules/runtime/host.d.ts +38 -0
  310. package/dist/modules/runtime/host.js +68 -0
  311. package/dist/modules/runtime/inside.d.ts +15 -0
  312. package/dist/modules/runtime/inside.js +47 -0
  313. package/dist/modules/runtime/inside.test.d.ts +1 -0
  314. package/dist/modules/runtime/runner.d.ts +11 -0
  315. package/dist/modules/runtime/runner.js +38 -0
  316. package/dist/modules/runtime/runtime.test.d.ts +1 -0
  317. package/dist/modules/runtime/stages.d.ts +50 -0
  318. package/dist/modules/runtime/stages.js +117 -0
  319. package/dist/modules/ssr/Component.d.ts +3 -1
  320. package/dist/modules/ssr/Component.js +2 -1
  321. package/dist/modules/ssr/handler.js +10 -2
  322. package/dist/modules/ssr/loadPluginComponents.js +2 -1
  323. package/dist/modules/ssr/prepareRender.js +39 -10
  324. package/dist/modules/ssr/preview.d.ts +3 -0
  325. package/dist/modules/ssr/preview.js +17 -7
  326. package/dist/modules/ssr/redirect.test.d.ts +1 -0
  327. package/dist/modules/ssr/registerExternalPlugins.d.ts +6 -1
  328. package/dist/modules/ssr/registerExternalPlugins.js +19 -16
  329. package/dist/modules/ssr/registerExternalPlugins.test.d.ts +1 -0
  330. package/dist/modules/ssr/reportMissingPlugins.d.ts +9 -0
  331. package/dist/modules/ssr/reportMissingPlugins.js +24 -0
  332. package/dist/modules/ssr/reportMissingPlugins.test.d.ts +1 -0
  333. package/dist/modules/ssr/streamBody.d.ts +2 -2
  334. package/dist/modules/ssr/streamBody.js +4 -1
  335. package/dist/modules/ssr/template.js +1 -1
  336. package/dist/modules/ssr/views/template.ejs +8 -5
  337. package/dist/mysql.d.ts +1 -1
  338. package/dist/mysql.js +2 -2
  339. package/dist/oauth.js +2 -2
  340. package/dist/plugins/compile.js +9 -4
  341. package/dist/plugins/copy.js +3 -3
  342. package/dist/plugins/manager.d.ts +35 -3
  343. package/dist/plugins/manager.js +109 -38
  344. package/dist/runtime.d.ts +15 -0
  345. package/dist/runtime.js +7 -0
  346. package/package.json +39 -8
  347. package/skills/plitzi-authoring/SKILL.md +98 -14
  348. package/skills/plitzi-authoring/reference/accessibility.md +111 -0
  349. package/skills/plitzi-authoring/reference/authoring-errors.md +70 -0
  350. package/skills/plitzi-authoring/reference/data-and-visibility.md +84 -18
  351. package/skills/plitzi-authoring/reference/elements-and-styles.md +61 -7
  352. package/skills/plitzi-authoring/reference/flows.md +108 -17
  353. package/skills/plitzi-authoring/reference/lists.md +74 -0
  354. package/skills/plitzi-authoring/reference/performance.md +67 -0
  355. package/skills/plitzi-authoring/reference/plugins.md +167 -0
  356. package/skills/plitzi-authoring/reference/review-checklist.md +19 -2
  357. package/skills/plitzi-authoring/reference/templates.md +67 -27
  358. package/skills/plitzi-authoring/reference/testing.md +72 -5
  359. package/skills/plitzi-authoring/reference/validation.md +73 -0
@@ -4,43 +4,77 @@ Plitzi's templates are Twig, run by Plitzi's own interpreter. What a `{{ … }}`
4
4
 
5
5
  ## Where a template runs
6
6
 
7
- | Written in | What is evaluated | Use it for |
7
+ | Written in | What is evaluated | What it can read |
8
8
  | --- | --- | --- |
9
- | a binding's `twigTemplate` transformer | the whole template: conditions, filters, `{% set %}`, loops, tests | anything computed — this is where logic goes |
10
- | a flow step's params | the whole template | values a step sends or stores |
11
- | an ATTRIBUTE (`href`, `src`, `content`…) | only `{{ name }}` and `{{ name|filter }}` tokens | dropping a value into a string |
9
+ | a binding's `twigTemplate` transformer | the whole template: conditions, filters, `{% set %}`, loops, tests | `source` (the bound value), `sourceTo`, the globals, the variables by bare name, and every source around the element |
10
+ | a flow step's params | the whole template | the trigger's payload and earlier steps by name, the globals, sources around the element |
11
+ | an ATTRIBUTE (`href`, `src`, `content`…) | only `{{ name }}` tokens (a filter after the name is allowed) | the globals, the variables and the page's route params by bare name (`{{ apiUrl }}`, `{{ slug }}`), and every source around the element (`{{ list_games.item.slug }}`) |
12
12
 
13
- An attribute holding only a condition — `href: "/x/{{ on ? 'a' : 'b' }}"` — is used **as written** (`authorSpace` warns
14
- `template-never-resolved`). Move the expression into a binding:
13
+ A **query parameter** is `navigation.queryParams.<name>` everywhere — never a bare name.
14
+
15
+ An attribute holding a condition — `href: "/x/{{ on ? 'a' : 'b' }}"` — is used **as written** (`authorSpace` warns
16
+ `template-never-resolved`). Move the expression into a binding with `bindTemplate`:
17
+
18
+ ```ts
19
+ link({ href: '/', mode: 'internal', bind: [bindTemplate('href', 'state.workspace.id', "{{ source ? '/workspace/' ~ source : '/' }}")] })
20
+ ```
21
+
22
+ A value that came from a BINDING is data, never a template: a comment reading `{{ auth.accessToken }}` prints those
23
+ characters. Only what you authored is interpolated.
24
+
25
+ ### A template's value, not its text
26
+
27
+ A binding's template renders TEXT by default. For an attribute that holds a list, a number or a flag — a list's
28
+ `items` above all — hand over the VALUE with `returns: 'value'` (`returnMode: 'value'` on the transformer). The
29
+ template must be a single `{{ expression }}`:
15
30
 
16
31
  ```ts
17
- link({ href: '/', bind: [{ to: 'href', source: 'state.workspace.id',
18
- transformers: [{ action: 'twigTemplate', params: { template: "{{ source ? '/workspace/' ~ source : '/' }}" } }] }] })
32
+ list({ id: 'shown', source: 'controlled',
33
+ bind: [bindTemplate('items', 'games.data.games', '{{ source|filter(g => state.genre == "" or g.genre == state.genre) }}', { returns: 'value' })],
34
+ children: [ … ] })
19
35
  ```
20
36
 
21
- In a binding, `source` is the value at the binding's `source`; everything else in scope is a source named in full.
37
+ A text template feeding `items` is refused: the list would receive the array written out as JSON and render nothing.
22
38
 
23
39
  ## Naming sources inside a template
24
40
 
25
41
  Always the full name — the element's kind, an underscore, its id: `apiContainer_stats`, `list_rows`,
26
- `modalContainer_credits`. The globals (`state`, `auth`, `navigation`, `variables`, `theme`) are named as themselves. In
27
- a flow, an earlier step is read by the name given with `named('quote', …)`: `{{ quote.output.total }}`.
42
+ `modalContainer_credits`. The globals (`state`, `auth`, `navigation`, `variables`, `host`, `theme`, `computed`) are named
43
+ as themselves. In a flow, an earlier step is read by the name given with `named('quote', …)`: `{{ quote.output.total }}`.
44
+
45
+ An id with a hyphen is one name inside a template — `{{ apiContainer_tn-data.data.total }}` reads that provider. So
46
+ subtraction is written with spaces: `{{ total - used }}`, never `total-used`.
28
47
 
29
- A list publishes one scope per row: inside a row, `list_rows.item` is THAT row.
48
+ A source reaches only the elements **inside** the element that publishes it (a layout's providers reach every page in
49
+ it). A list publishes one scope per row: inside a row, `list_rows.item` is THAT row and `list_rows.index` its position;
50
+ a nested list's rows still see the outer row.
51
+
52
+ `authorSpace` refuses a name nothing answers to, a short name where the full one is needed, and a source read from
53
+ outside the element that publishes it — each with the name it should have been.
30
54
 
31
55
  ## The language
32
56
 
33
- - Operators: `~` (concat), `+ - * / %`, `== != < > <= >=`, `and or not`, `in`, `a ? b : c`, `a ?? b`.
34
- - Access: `a.b`, `a.0`, `a[i]`, `(expr).key`, `(expr)[i]`.
35
- - Blocks: `{% set x = … %}`, `{% if %}…{% elseif %}…{% else %}…{% endif %}`, `{% for item in list %}…{% endfor %}`.
36
- - Arrow functions in filters: `rows|sort(r => r.at)|first`, `rows|filter(r => r.active)`, `rows|map(r => r.name)`.
37
- - Tests: `is defined`, `is empty`, `is null`, `is iterable`, `is even`, `is odd`, and their `is not` forms.
57
+ - Operators: `~` (concat), `+ - * / // % **`, `== != < > <= >=`, `and or not`, `in`, `starts with`, `ends with`,
58
+ `a ? b : c`, `a ? b` (empty when false), `a ?: b` (a when truthy), `a ?? b` (a when defined).
59
+ - Access: `a.b`, `a.0`, `a[i]`, `(expr).key`, `(expr)[i]`, `['x', 'y'][i]`, `{ k: 1 }.k`.
60
+ - Blocks: `{% set x = … %}`, `{% if %}…{% elseif %}…{% else %}…{% endif %}`, `{% for item in list %}…{% endfor %}`,
61
+ `{% apply upper %}…{% endapply %}`, `{% break %}`, `{% continue %}`.
62
+ - Arrow functions in filters, closing over `{% set %}` variables: `rows|sort(r => r.at)|first`,
63
+ `rows|sort((a, b) => b.score - a.score)`, `rows|filter(r => r.score >= min)`, `rows|map(r => r.name)`.
64
+ - Tests: `is defined`, `is empty`, `is null`, `is iterable`, `is even`, `is odd`, `is same as(x)` (strict: `false` is
65
+ not `'false'`, `0` or an unset value), `is divisible by(n)`, and their `is not` forms. `null` and `none` are literals.
38
66
  - Functions: `range`, `min`, `max`, `cycle`.
67
+ - **Not supported**: `matches` (no regular expressions are evaluated — use `starts with`, `ends with`, `in`), macros,
68
+ `include`/`extends`, and any filter or function not listed here. `authorSpace` refuses them, and anything else the
69
+ interpreter would read past, rather than letting a template render a value nobody wrote.
70
+
71
+ Filters: `default upper lower trim capitalize title camelize kebab snake ltrim rtrim pad padRight replace slice split
72
+ join reverse length first last contains startswith endswith number number_format round abs format sort batch chunk map
73
+ reduce merge keys values filter column find pluck unique flatten sum without only index_by group_by url_encode nl2br
74
+ striptags spaceless json_encode to_json object_as_json raw date base64_encode base64_decode md5 random`.
39
75
 
40
- Filters: `default upper lower trim capitalize title camelize kebab snake ltrim rtrim pad replace slice split join
41
- reverse length first last contains startswith endswith number number_format round abs format sort batch chunk map
42
- reduce merge keys values filter column find pluck unique flatten sum without only index_by group_by url_encode
43
- striptags spaceless json_encode to_json raw date year month day hours minutes seconds weekday random`.
76
+ `format` is sprintf: `'%02d'|format(n)` → `05`, `'%.1f'|format(x)`, `'%-8s'|format(name)`, `'%+d'|format(delta)`. A bare
77
+ `%f` keeps the number's own digits.
44
78
 
45
79
  A lookup across two sources — a row joined to the stats around it:
46
80
 
@@ -54,16 +88,22 @@ A lookup across two sources — a row joined to the stats around it:
54
88
 
55
89
  - **An empty list is false**, like an absent one. To tell "arrived and empty" from "not arrived":
56
90
  `{{ items is defined and items is empty }}`.
57
- - **`json_encode` of a string is the string**, unquoted. Do not build JSON by interpolating text a visitor typed —
58
- pass objects as step params instead.
91
+ - **`json_encode` prints JSON for any value** — a string quoted and escaped, nothing as `null` — so a JSON document
92
+ is built by encoding each value: `'{ "board": {{ id|json_encode }}, "timer": {{ timer|json_encode }} }'`. In a flow
93
+ step's params and an action's output, `"{{ text }}"` in quotes is safe too — a value inside a string literal of a
94
+ param written as a JSON document is escaped for it. Anywhere else (an attribute, a binding's template) it is not:
95
+ encode.
59
96
  - **Numbers**: `number_format(decimals, point, thousands)`; `round(precision)`.
60
- - **A template that renders a number hands on a number** in step params (`'1'` → `1`).
97
+ - **A step param that is one `{{ expression }}` is that value, with its type**: a number stays a number, and a
98
+ string stays a string however it looks — a password typed `1234` arrives as `"1234"`. Nothing is guessed from the
99
+ text: to convert, declare the type where the value lands (`setState`'s `type`, the action's input field). Text around
100
+ the tokens is text, unless it makes a JSON object or array — then it is that document (see `json_encode` above).
61
101
 
62
102
  ## Dates
63
103
 
64
- - `|date(format, zone)` — tokens `Y m n d j H G i s l F M N w U`. **Always pass a zone** (`'UTC'`) and print it: with
65
- no zone the date is formatted in the local time of whoever renders it — the server's for the HTML, the visitor's
66
- after hydration — and the two disagree.
104
+ - `|date(format, zone)` — tokens `Y y m n d j H G h g A a i s l D F M N w U`; a backslash prints the next character
105
+ as it is (`\T`). **Always pass a zone** (`'UTC'`) and print it: with no zone the date is formatted in the local time
106
+ of whoever renders it — the server's for the HTML, the visitor's after hydration — and the two disagree.
67
107
  - A timestamp can be seconds or milliseconds, a number or a string of digits — all read.
68
108
  - For "3 minutes ago", the `dateConverter` transformer with `{ asAge: true }`; give it `isUnix: false` for an ISO
69
109
  string. Its checkbox params accept real booleans (and `'true'`/`'false'`).
@@ -1,19 +1,78 @@
1
1
  # Testing what you authored
2
2
 
3
+ ## One call: `inspectPage`
4
+
5
+ ```ts
6
+ import { authorSpace, inspectPage } from '@plitzi/sdk-authoring';
7
+
8
+ const { handles } = authorSpace(space);
9
+ await page.goto('/');
10
+ expect((await inspectPage(page, handles)).problems).toEqual([]);
11
+ ```
12
+
13
+ It checks the open page and returns EVERY problem at once, one sentence each, naming the element and the reason:
14
+
15
+ - every element the page owes is present and visible — its own and those of the layouts around it
16
+ (`heading "hero-title" is on the page but not visible: display:none on "hero"`);
17
+ - every image arrived — an image element that failed says so (`data-plitzi-failed`), though its fallback loads;
18
+ - nothing scrolls sideways (`the page scrolls sideways by 37px — widest: "cards"`);
19
+ - no text is drawn in the colour painted behind it.
20
+
21
+ It retries for up to 5 s like an assertion does (`timeout`), so a provider still answering is not a failure. Options:
22
+ `page` (id or slug; the home page by default), `elements: 'all'` to owe the unnamed elements too, `ignore: ['id']` for
23
+ what a test knows is not there yet (a typo is refused), `skip: ['images']` for a check a page breaks on purpose.
24
+ `inspectDocument(page)` runs the page checks alone, for a page whose space is not in hand.
25
+
3
26
  ## Handles
4
27
 
5
28
  `authorSpace` returns `handles`: every element by id, with the selector that finds it in the rendered page
6
29
  (`[data-plitzi-el="<id>"]`). `handles.element(id)` throws on a name that does not exist, and `locate(page, handles)`
7
- turns an id into a Playwright locator. Pages are in `handles.pages` (each with its `path` and `elements`); a layout's
8
- elements are in `handles.layouts` and render on every page that names the layout.
30
+ turns an id into a Playwright locator. Pages are in `handles.pages` (each with its `path`, `elements` and `layout`); a
31
+ layout's elements are in `handles.layouts` and render on every page that names the layout. `onScreen(handles, page)` is
32
+ the list `inspectPage` holds a page to.
33
+
34
+ Three flags say what a bare visit cannot promise, and `onScreen` leaves out:
9
35
 
10
- An element marked `conditional` is on screen only under a condition of its own or of an ancestor — skip it in an
11
- "every named element is visible" check. A `formControl`'s id names its wrapper: type into
12
- `locate('email').locator('input')`.
36
+ - `conditional` — on screen only under a condition of its own or of an ancestor;
37
+ - `repeated` — inside a list row, so rendered once per row: several copies, or none while the list is empty. Address
38
+ one with `.first()` / `.nth(i)`, in a test that knows the data;
39
+ - `boxless` — a provider with no tag, which renders its children and no element of its own.
40
+
41
+ A `formControl`'s id names its wrapper: type into `locate('email').locator('input')`.
13
42
 
14
43
  Select by `data-plitzi-el`, never by a generated class name: authoring derives `<type>-<hash>` for an element's own
15
44
  rules, and that name changes when the rules do.
16
45
 
46
+ ## Pressing a shortcut
47
+
48
+ `pressShortcut(page, 'mod+z')` presses a shortcut written the way `onKey` writes it, with the keys the PAGE listens
49
+ for: `mod` is ⌘ where the page's user agent is a Mac and Ctrl anywhere else. A driver's own "Control or Meta" asks the
50
+ machine running the suite instead, so a suite on a Mac driving an emulated desktop Chrome presses ⌘ at a page waiting
51
+ for Ctrl — the flow never runs and nothing says why. Point at the page first (a click on it) so it has the keys.
52
+
53
+ ## Counting what an interaction renders
54
+
55
+ `inspectRenders(page, act, { max })` runs `act` and answers every element that rendered, how often and what changed
56
+ for it; over `max`, `problems` says so. It reads the SDK's render tracing, which is on only under `debugMode` — render
57
+ the space with it (the e2e harness: `renderSpace(page, space, { debugMode: true })`). What to do with the answer is in
58
+ [performance](performance.md).
59
+
60
+ ## Spaces written for a test
61
+
62
+ Author them like any space — never as JSON: the validator is what tells a fixture that tests something from one that
63
+ tests nothing.
64
+
65
+ ```ts
66
+ import { authorSpace, heading, singlePageSpace, withElement } from '@plitzi/sdk-authoring';
67
+
68
+ const space = singlePageSpace([heading('Hi', { id: 'title', subType: 'h1' })]); // one page, nothing else
69
+ const edited = withElement(space, 'title', { attributes: { content: 'Changed' } }); // same page, one thing different
70
+ ```
71
+
72
+ A fixture that must break a check ON PURPOSE — the runtime's answer to a document no author would write is the
73
+ subject — names the break: `authorSpace(spec, { allow: [{ code: 'template-unknown-name', element: 'feed', why: '…' }] })`.
74
+ One code on one element; it comes back in `warnings` with the reason, and an entry that no longer matches is refused.
75
+
17
76
  ## What to check
18
77
 
19
78
  - **Every viewport and both themes.** Desktop, tablet (48–64rem) and mobile (below 48rem); `colorScheme: 'dark'` as well
@@ -50,3 +109,11 @@ expect(await page.evaluate(() => (window as unknown as { __painted: string[] }).
50
109
  - **Navigation lands on the new page's content.** After `waitForURL`, wait for an element of the NEW page before typing:
51
110
  for a frame the previous page is still mounted, and a form field with the same name there takes the keystrokes.
52
111
  - **Console errors are failures.** Collect them and assert the list is empty.
112
+
113
+ ## Screenshots and scrolling
114
+
115
+ The page scrolls the document in development exactly as in production while the dev-tools panel is folded away (the
116
+ badge). With the panel OPEN, the page shares the window with it and scrolls inside its own pane — close the panel, or
117
+ run with `debugMode: false`, before a `fullPage` screenshot or a scroll measurement. For a screenshot at a width and a
118
+ theme: `page.setViewportSize({ width: 390, height: 844 })`, `page.emulateMedia({ colorScheme: 'dark' })`, and seed state
119
+ with `render(…, { state })` or a flow the test drives.
@@ -0,0 +1,73 @@
1
+ # How `authorSpace` checks — and the loop that wastes no attempts
2
+
3
+ `authorSpace(space, options)` is the whole check. It either returns `{ schema, style, handles, warnings }` or throws, and
4
+ knowing HOW it throws is what turns ten attempts into two.
5
+
6
+ ## Three stages, two ways of failing
7
+
8
+ | Stage | What it checks | How it fails |
9
+ | --- | --- | --- |
10
+ | 1. Assembly | Each spec as it is turned into a document: fields that exist, CSS properties the editor can read, a class declared twice with different rules, fonts, selector names | **Throws at the FIRST problem**, naming where it was written (`Element "text" (price) at shop/home/0/2`) |
11
+ | 2. Structure | The documents: parents, roots, pages, cycles, style targets | Collected, then thrown together |
12
+ | 3. Linter | What the documents MEAN: every template, binding, flow step, trigger, callback, attribute and link, read the way the runtime reads them | **All errors at once**, one line each: `Invalid space (…):\n - [code] message` |
13
+
14
+ The linter only runs once stage 2 holds, so the pattern of a session is: a few single refusals (fix, re-run), then one
15
+ list — **fix every line of the list in one pass** before running again. Each message says what to write instead; do
16
+ exactly that (see [authoring-errors](authoring-errors.md) for every code).
17
+
18
+ Warnings come back in `warnings` and never throw. Each one is written code that will not do what it says — zero is the
19
+ bar.
20
+
21
+ ## The loop
22
+
23
+ 0. **Before writing an element you have not used, print what it takes.** One command answers attributes, values,
24
+ triggers, callbacks and slots, and saves a refusal per guess:
25
+
26
+ ```bash
27
+ node --input-type=module -e "import * as a from '@plitzi/sdk-authoring'; const t = 'dropdown'; console.log({ attributes: a.elementDefaultAttributes[t], values: a.elementAttributeValues[t], triggers: a.elementTriggers[t], callbacks: a.elementCallbacks[t], slots: a.elementSlots[t] })"
28
+ ```
29
+
30
+ 1. **Author once, print everything.** In a project `plitzi create` wrote, `npm run author`. Anywhere else, a file you run
31
+ with `node` (≥ 22.18 strips the types) — outside the project's source, never committed:
32
+
33
+ ```ts
34
+ import { authorSpace } from '@plitzi/sdk-authoring';
35
+
36
+ import { space } from './src/space.ts';
37
+
38
+ try {
39
+ const { schema, warnings } = authorSpace(space, { plugins: [] /* your declarations */ });
40
+ console.log(`${Object.keys(schema.flat).length} elements, ${warnings.length} warnings`);
41
+ warnings.forEach(warning => console.log(`[${warning.code}] ${warning.message}`));
42
+ } catch (error) {
43
+ console.log((error as Error).message);
44
+ }
45
+ ```
46
+
47
+ 2. **Fix, re-run, until it prints zero warnings.** Then typecheck the project.
48
+ 3. **Look at it** — in a browser, at desktop and phone width, in both themes (see [testing](testing.md)). Stage 3 is
49
+ thorough about MEANING and blind to what follows.
50
+
51
+ ## What it cannot see
52
+
53
+ A space that authors cleanly can still render wrong. These are the places to look with your own eyes:
54
+
55
+ - **The shape of data it does not have.** A binding to `feed.records` is checked to name a provider; whether the
56
+ action's output HAS `records`, or its rows a `magnitude`, is known only at run time. Render with real data.
57
+ - **Layout and cascade.** Overflow, stacking, a type's default style under your class (a `button` or `text` default
58
+ applies beneath your rules), a `gap` holding a slot for a hidden element.
59
+ - **A plugin's inside** — and, unless you hand its declaration over (`plugins: [declaration]`, see
60
+ [plugins](plugins.md)), its events, actions and attributes too.
61
+ - **Anything positioned by a component.** A map marker, a dropdown popup, a tooltip: the component sets `position` on
62
+ its root. A class that sets `position` on it (a panel preset spread into it, say) takes that away, and it lands in
63
+ the page flow — offset, or holding its container open while hidden.
64
+ - **What an ancestor's `backdrop-filter`, `filter` or `transform` does**: it becomes the containing block of every
65
+ `position: fixed` descendant and a stacking context of its own, so a popup inside it opens offset and paints UNDER
66
+ its siblings.
67
+
68
+ ## When a CSS property is refused
69
+
70
+ The style vocabulary is the closed list the editor can read back. What is outside it — `zoom`, `mask`, a custom
71
+ property (`--seismic-accent`), a pseudo-element, a keyframe — is not an error to work around: it goes in the space's
72
+ `customCss`, addressed by the class name (`.panel`, and `.panel--open` for a variant `variantFrom` applies). Shorthands
73
+ inside it ARE accepted and expanded: `inset`, `grid-area`, `outline`, `border`, `padding` all work in `css`.