@plitzi/sdk-server 0.33.2 → 0.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +283 -8
  3. package/dist/actions.d.ts +62 -0
  4. package/dist/actions.js +12 -0
  5. package/dist/adapters/cloudAdapters.d.ts +72 -0
  6. package/dist/adapters/cloudAdapters.js +303 -0
  7. package/dist/adapters/space/index.d.ts +93 -0
  8. package/dist/adapters/space/index.js +122 -0
  9. package/dist/adapters/space/resolvers.d.ts +69 -0
  10. package/dist/adapters/space/resolvers.js +79 -0
  11. package/dist/adapters/space/space.test.d.ts +1 -0
  12. package/dist/adapters/space/types.d.ts +64 -0
  13. package/dist/adapters/space/types.js +41 -0
  14. package/dist/auth.d.ts +50 -0
  15. package/dist/auth.js +19 -0
  16. package/dist/core/auth/api.d.ts +400 -11
  17. package/dist/core/auth/api.js +1044 -50
  18. package/dist/core/auth/createAuth.d.ts +135 -30
  19. package/dist/core/auth/createAuth.js +96 -24
  20. package/dist/core/auth/credentials.d.ts +9 -3
  21. package/dist/core/auth/credentials.js +10 -4
  22. package/dist/core/auth/csrf.d.ts +89 -0
  23. package/dist/core/auth/csrf.js +234 -0
  24. package/dist/core/auth/csrf.test.d.ts +1 -0
  25. package/dist/core/auth/identity.d.ts +6 -0
  26. package/dist/core/auth/identity.js +37 -8
  27. package/dist/core/auth/lifecycle.test.d.ts +1 -0
  28. package/dist/core/auth/oauth/index.d.ts +8 -0
  29. package/dist/core/auth/oauth/index.js +13 -15
  30. package/dist/core/auth/passwords.d.ts +15 -0
  31. package/dist/core/auth/passwords.js +32 -0
  32. package/dist/core/auth/redirects.d.ts +18 -0
  33. package/dist/core/auth/redirects.js +31 -0
  34. package/dist/core/auth/redirects.test.d.ts +1 -0
  35. package/dist/core/auth/routes.d.ts +4 -2
  36. package/dist/core/auth/routes.js +234 -9
  37. package/dist/core/auth/session.d.ts +11 -0
  38. package/dist/core/auth/session.js +1 -1
  39. package/dist/core/auth/spaceTokens.d.ts +38 -2
  40. package/dist/core/auth/spaceTokens.js +54 -2
  41. package/dist/core/auth/throttle.d.ts +5 -0
  42. package/dist/core/auth/throttle.js +81 -0
  43. package/dist/core/auth/throttle.test.d.ts +1 -0
  44. package/dist/core/auth/tokens.d.ts +83 -12
  45. package/dist/core/auth/tokens.js +51 -9
  46. package/dist/core/auth/totp.d.ts +48 -0
  47. package/dist/core/auth/totp.js +118 -0
  48. package/dist/core/auth/totp.test.d.ts +1 -0
  49. package/dist/core/createServer.d.ts +0 -6
  50. package/dist/core/createServer.js +35 -3
  51. package/dist/core/fontStore.d.ts +33 -0
  52. package/dist/core/fontStore.js +53 -0
  53. package/dist/core/fontStore.test.d.ts +1 -0
  54. package/dist/core/handlers/authMiddleware.js +1 -1
  55. package/dist/core/handlers/authRouteHandlers.d.ts +9 -1
  56. package/dist/core/handlers/authRouteHandlers.js +4 -3
  57. package/dist/core/handlers/csrfMiddleware.d.ts +20 -0
  58. package/dist/core/handlers/csrfMiddleware.js +32 -0
  59. package/dist/core/handlers/oauthRouteHandlers.d.ts +46 -0
  60. package/dist/core/handlers/oauthRouteHandlers.js +159 -0
  61. package/dist/core/handlers/socialRouteHandlers.d.ts +40 -0
  62. package/dist/core/handlers/socialRouteHandlers.js +129 -0
  63. package/dist/core/handlers/socialRouteHandlers.test.d.ts +1 -0
  64. package/dist/core/handlers/types.d.ts +22 -5
  65. package/dist/core/health.d.ts +11 -1
  66. package/dist/core/health.js +27 -3
  67. package/dist/core/http/dispatcher.d.ts +1 -1
  68. package/dist/core/http/dispatcher.js +20 -1
  69. package/dist/core/http/stages/authApi.js +1 -1
  70. package/dist/core/http/stages/fontAssets.d.ts +9 -0
  71. package/dist/core/http/stages/fontAssets.js +27 -0
  72. package/dist/core/http/stages/oauth.d.ts +19 -0
  73. package/dist/core/http/stages/oauth.js +118 -0
  74. package/dist/core/http/types.d.ts +12 -0
  75. package/dist/core/oauth/authorize.d.ts +22 -0
  76. package/dist/core/oauth/authorize.js +254 -0
  77. package/dist/core/oauth/authorize.test.d.ts +1 -0
  78. package/dist/core/oauth/challenge.d.ts +11 -0
  79. package/dist/core/oauth/challenge.js +33 -0
  80. package/dist/core/oauth/consentPage.d.ts +12 -0
  81. package/dist/core/oauth/consentPage.js +131 -0
  82. package/dist/core/oauth/metadata.d.ts +41 -0
  83. package/dist/core/oauth/metadata.js +71 -0
  84. package/dist/core/oauth/params.d.ts +5 -0
  85. package/dist/core/oauth/params.js +5 -0
  86. package/dist/core/oauth/pkce.d.ts +6 -0
  87. package/dist/core/oauth/pkce.js +15 -0
  88. package/dist/core/oauth/records.d.ts +72 -0
  89. package/dist/core/oauth/records.js +49 -0
  90. package/dist/core/oauth/register.d.ts +5 -0
  91. package/dist/core/oauth/register.js +55 -0
  92. package/dist/core/oauth/respond.d.ts +21 -0
  93. package/dist/core/oauth/respond.js +59 -0
  94. package/dist/core/oauth/token.d.ts +14 -0
  95. package/dist/core/oauth/token.js +130 -0
  96. package/dist/core/previewToken.d.ts +20 -0
  97. package/dist/core/previewToken.js +29 -1
  98. package/dist/core/server/pageServer.js +4 -1
  99. package/dist/core/services/action.d.ts +6 -4
  100. package/dist/core/services/action.js +103 -10
  101. package/dist/core/services/registry.js +2 -0
  102. package/dist/core/services/resolve.d.ts +8 -0
  103. package/dist/core/services/resolve.js +12 -1
  104. package/dist/core/staticFiles.js +1 -2
  105. package/dist/handlers.d.ts +7 -1
  106. package/dist/handlers.js +4 -1
  107. package/dist/helpers/buildResponseHelpers.d.ts +8 -0
  108. package/dist/helpers/buildResponseHelpers.js +9 -1
  109. package/dist/helpers/buildServerInfo.d.ts +8 -3
  110. package/dist/helpers/buildServerInfo.js +18 -14
  111. package/dist/helpers/cache/keys.d.ts +13 -0
  112. package/dist/helpers/cache/keys.js +12 -1
  113. package/dist/helpers/onAbort.d.ts +12 -0
  114. package/dist/helpers/onAbort.js +22 -0
  115. package/dist/helpers/onAbort.test.d.ts +1 -0
  116. package/dist/helpers/outboundGuard.d.ts +27 -0
  117. package/dist/helpers/outboundGuard.js +49 -0
  118. package/dist/helpers/outboundGuard.test.d.ts +1 -0
  119. package/dist/helpers/serverLog.d.ts +6 -3
  120. package/dist/helpers/serverLog.js +20 -3
  121. package/dist/index.d.ts +6 -0
  122. package/dist/index.js +9 -4
  123. package/dist/kernel.d.ts +5 -22
  124. package/dist/kernel.js +1 -14
  125. package/dist/modules/actions/{handler.js → connectorWrite.js} +5 -2
  126. package/dist/modules/actions/connectorWrite.test.d.ts +1 -0
  127. package/dist/modules/actions/index.d.ts +40 -0
  128. package/dist/modules/actions/index.js +46 -0
  129. package/dist/modules/actions/moduleFor.d.ts +3 -0
  130. package/dist/modules/actions/moduleFor.js +35 -0
  131. package/dist/modules/actions/moduleFor.test.d.ts +1 -0
  132. package/dist/modules/actions/runtime/check.d.ts +24 -0
  133. package/dist/modules/actions/runtime/check.js +111 -0
  134. package/dist/modules/actions/runtime/check.test.d.ts +1 -0
  135. package/dist/modules/actions/runtime/errors.d.ts +11 -0
  136. package/dist/modules/actions/runtime/errors.js +17 -0
  137. package/dist/modules/actions/runtime/guards.d.ts +126 -0
  138. package/dist/modules/actions/runtime/guards.js +246 -0
  139. package/dist/modules/actions/runtime/guards.test.d.ts +1 -0
  140. package/dist/modules/actions/runtime/kvStore.d.ts +27 -0
  141. package/dist/modules/actions/runtime/kvStore.js +41 -0
  142. package/dist/modules/actions/runtime/kvStore.test.d.ts +1 -0
  143. package/dist/modules/actions/runtime/limits.d.ts +11 -0
  144. package/dist/modules/actions/runtime/limits.js +35 -0
  145. package/dist/modules/actions/runtime/memoryKv.d.ts +2 -0
  146. package/dist/modules/actions/runtime/memoryKv.js +77 -0
  147. package/dist/modules/actions/runtime/namespaceKv.d.ts +9 -0
  148. package/dist/modules/actions/runtime/namespaceKv.js +19 -0
  149. package/dist/modules/actions/runtime/precheck.d.ts +27 -0
  150. package/dist/modules/actions/runtime/precheck.js +45 -0
  151. package/dist/modules/actions/runtime/renderResolver.d.ts +15 -0
  152. package/dist/modules/actions/runtime/renderResolver.js +130 -0
  153. package/dist/modules/actions/runtime/renderResolver.test.d.ts +1 -0
  154. package/dist/modules/actions/runtime/renderShare.d.ts +29 -0
  155. package/dist/modules/actions/runtime/renderShare.js +36 -0
  156. package/dist/modules/actions/runtime/renderShare.test.d.ts +1 -0
  157. package/dist/modules/actions/runtime/report.d.ts +14 -0
  158. package/dist/modules/actions/runtime/report.js +22 -0
  159. package/dist/modules/actions/runtime/runAction.d.ts +12 -0
  160. package/dist/modules/actions/runtime/runAction.js +405 -0
  161. package/dist/modules/actions/runtime/runAction.test.d.ts +1 -0
  162. package/dist/modules/actions/runtime/runLogger.d.ts +31 -0
  163. package/dist/modules/actions/runtime/runLogger.js +66 -0
  164. package/dist/modules/actions/runtime/runLogger.test.d.ts +1 -0
  165. package/dist/modules/actions/runtime/schedule.d.ts +35 -0
  166. package/dist/modules/actions/runtime/schedule.js +76 -0
  167. package/dist/modules/actions/runtime/schedule.test.d.ts +1 -0
  168. package/dist/modules/actions/runtime/scope.d.ts +40 -0
  169. package/dist/modules/actions/runtime/scope.js +103 -0
  170. package/dist/modules/actions/runtime/triggers.d.ts +12 -0
  171. package/dist/modules/actions/runtime/triggers.js +14 -0
  172. package/dist/modules/actions/taskCatalog.d.ts +26 -0
  173. package/dist/modules/actions/taskCatalog.js +24 -0
  174. package/dist/modules/actions/taskCatalog.test.d.ts +1 -0
  175. package/dist/modules/actions/tasks/auth.d.ts +2 -0
  176. package/dist/modules/actions/tasks/auth.js +40 -0
  177. package/dist/modules/actions/tasks/builtins.d.ts +8 -0
  178. package/dist/modules/actions/tasks/builtins.js +24 -0
  179. package/dist/modules/actions/tasks/connector.d.ts +2 -0
  180. package/dist/modules/actions/tasks/connector.js +141 -0
  181. package/dist/modules/actions/tasks/db.d.ts +2 -0
  182. package/dist/modules/actions/tasks/db.js +59 -0
  183. package/dist/modules/actions/tasks/db.test.d.ts +1 -0
  184. package/dist/modules/actions/tasks/flow.d.ts +3 -0
  185. package/dist/modules/actions/tasks/flow.js +109 -0
  186. package/dist/modules/actions/tasks/helpers.d.ts +16 -0
  187. package/dist/modules/actions/tasks/helpers.js +30 -0
  188. package/dist/modules/actions/tasks/http.d.ts +2 -0
  189. package/dist/modules/actions/tasks/http.js +111 -0
  190. package/dist/modules/actions/tasks/http.test.d.ts +1 -0
  191. package/dist/modules/actions/tasks/kv.d.ts +2 -0
  192. package/dist/modules/actions/tasks/kv.js +102 -0
  193. package/dist/modules/actions/tasks/kv.test.d.ts +1 -0
  194. package/dist/modules/actions/tasks/registry.d.ts +10 -0
  195. package/dist/modules/actions/tasks/registry.js +36 -0
  196. package/dist/modules/actions/tasks/transform.d.ts +2 -0
  197. package/dist/modules/actions/tasks/transform.js +34 -0
  198. package/dist/modules/actions/transport/callHandler.d.ts +24 -0
  199. package/dist/modules/actions/transport/callHandler.js +233 -0
  200. package/dist/modules/actions/transport/callHandler.test.d.ts +1 -0
  201. package/dist/modules/actions/transport/cancelHandler.d.ts +23 -0
  202. package/dist/modules/actions/transport/cancelHandler.js +23 -0
  203. package/dist/modules/actions/transport/catalogHandler.d.ts +18 -0
  204. package/dist/modules/actions/transport/catalogHandler.js +21 -0
  205. package/dist/modules/actions/transport/stream.d.ts +23 -0
  206. package/dist/modules/actions/transport/stream.js +100 -0
  207. package/dist/modules/actions/transport/verifySignature.d.ts +16 -0
  208. package/dist/modules/actions/transport/verifySignature.js +72 -0
  209. package/dist/modules/actions/transport/webhookHandler.d.ts +25 -0
  210. package/dist/modules/actions/transport/webhookHandler.js +206 -0
  211. package/dist/modules/actions/transport/webhookHandler.test.d.ts +1 -0
  212. package/dist/modules/actions/types.d.ts +234 -0
  213. package/dist/modules/connectors/engine.js +4 -1
  214. package/dist/modules/connectors/resolver.d.ts +10 -2
  215. package/dist/modules/connectors/resolver.js +8 -3
  216. package/dist/modules/mysql/accounts.d.ts +5 -0
  217. package/dist/modules/mysql/accounts.js +365 -0
  218. package/dist/modules/mysql/accounts.test.d.ts +1 -0
  219. package/dist/modules/mysql/admin.d.ts +58 -0
  220. package/dist/modules/mysql/admin.js +133 -0
  221. package/dist/modules/mysql/config.d.ts +82 -0
  222. package/dist/modules/mysql/config.js +30 -0
  223. package/dist/modules/mysql/identities.d.ts +35 -0
  224. package/dist/modules/mysql/identities.js +43 -0
  225. package/dist/modules/mysql/index.d.ts +67 -0
  226. package/dist/modules/mysql/index.js +62 -0
  227. package/dist/modules/mysql/pool.d.ts +3 -0
  228. package/dist/modules/mysql/pool.js +88 -0
  229. package/dist/modules/mysql/query.d.ts +12 -0
  230. package/dist/modules/mysql/query.js +21 -0
  231. package/dist/modules/mysql/schema.d.ts +43 -0
  232. package/dist/modules/mysql/schema.js +340 -0
  233. package/dist/modules/mysql/schema.test.d.ts +1 -0
  234. package/dist/modules/mysql/sessions.d.ts +33 -0
  235. package/dist/modules/mysql/sessions.js +46 -0
  236. package/dist/modules/mysql/spaceTokens.d.ts +11 -0
  237. package/dist/modules/mysql/spaceTokens.js +59 -0
  238. package/dist/modules/mysql/store.integration.test.d.ts +1 -0
  239. package/dist/modules/rsc/connectorRscData.d.ts +25 -0
  240. package/dist/modules/rsc/connectorRscData.js +51 -0
  241. package/dist/modules/rsc/connectorRscData.test.d.ts +1 -0
  242. package/dist/modules/rsc/handler.js +16 -3
  243. package/dist/modules/rsc/matchRscPage.d.ts +14 -0
  244. package/dist/modules/rsc/matchRscPage.js +26 -0
  245. package/dist/modules/rsc/resolveRscData.d.ts +14 -1
  246. package/dist/modules/rsc/resolveRscData.js +23 -34
  247. package/dist/modules/ssr/Component.d.ts +6 -2
  248. package/dist/modules/ssr/Component.js +3 -1
  249. package/dist/modules/ssr/draftSession.test.d.ts +1 -0
  250. package/dist/modules/ssr/handler.js +15 -2
  251. package/dist/modules/ssr/loadPluginComponents.js +22 -5
  252. package/dist/modules/ssr/prepareRender.js +87 -8
  253. package/dist/modules/ssr/prepareRender.test.d.ts +1 -0
  254. package/dist/modules/ssr/preview.d.ts +21 -8
  255. package/dist/modules/ssr/preview.js +38 -14
  256. package/dist/modules/ssr/registerExternalPlugins.js +2 -2
  257. package/dist/modules/ssr/resolvePageSeo.d.ts +18 -0
  258. package/dist/modules/ssr/resolvePageSeo.js +26 -0
  259. package/dist/modules/ssr/resolvePageSeo.test.d.ts +1 -0
  260. package/dist/modules/ssr/template.test.d.ts +1 -0
  261. package/dist/modules/ssr/views/template.ejs +71 -5
  262. package/dist/mysql.d.ts +26 -0
  263. package/dist/mysql.js +4 -0
  264. package/dist/oauth.d.ts +24 -0
  265. package/dist/oauth.js +10 -0
  266. package/dist/plugins/compile.d.ts +1 -0
  267. package/dist/plugins/compile.js +37 -3
  268. package/dist/plugins/manager.d.ts +40 -0
  269. package/dist/plugins/manager.js +113 -13
  270. package/dist/plugins/manager.test.d.ts +1 -0
  271. package/package.json +43 -14
  272. package/skills/plitzi-authoring/SKILL.md +259 -0
  273. /package/dist/{modules/actions/handler.test.d.ts → adapters/cloudAdapters.test.d.ts} +0 -0
  274. /package/dist/modules/actions/{handler.d.ts → connectorWrite.d.ts} +0 -0
@@ -1,14 +1,80 @@
1
1
  <!doctype html>
2
- <html lang="en">
2
+ <html lang="en"<% if (locals.themeClass) { %> class="<%= locals.themeClass %>"<% } %>>
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
5
  <title><%= locals.title || '' %></title>
6
+ <% if (locals.description) { %>
7
+ <meta name="description" content="<%= locals.description %>" />
8
+ <% } %>
9
+ <meta property="og:type" content="website" />
10
+ <% if (locals.title) { %>
11
+ <meta property="og:title" content="<%= locals.title %>" />
12
+ <meta name="twitter:title" content="<%= locals.title %>" />
13
+ <% } %>
14
+ <% if (locals.description) { %>
15
+ <meta property="og:description" content="<%= locals.description %>" />
16
+ <meta name="twitter:description" content="<%= locals.description %>" />
17
+ <% } %>
6
18
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
19
  <link rel="shortcut icon" href="https://cdn.plitzi.com/resources/img/favicon.svg" />
8
20
 
9
- <link rel="preconnect" href="https://fonts.gstatic.com" />
10
- <link rel="preconnect" href="https://fonts.googleapis.com" />
11
- <link rel="preconnect" href="https://cdn.plitzi.com" />
21
+ <%
22
+ /*
23
+ The visitor's theme is on <html> above, and there is nothing to run here for it.
24
+
25
+ A page paints long before its JavaScript has mounted anything, so the theme cannot be settled by anything the
26
+ SDK does at mount — a visitor who chose light on a machine set to dark would watch the dark page for about
27
+ four hundred milliseconds. This document used to ship a blocking script in the head to beat that paint.
28
+
29
+ It no longer has to. The choice is in a COOKIE, which is the one place a browser keeps a preference that the
30
+ SERVER can read too: `prepareRender` takes it off the request and hands the class down as `themeClass`.
31
+ Nothing blocks, nothing is measured, and the markup is right the first time.
32
+ */
33
+ %>
34
+
35
+ <%
36
+ /*
37
+ Two origins the document reaches for whatever the space declares: the icon font below, and the favicon.
38
+ Named here so the space's own fonts can skip whichever of them it would otherwise ask for twice.
39
+ */
40
+ const staticOrigins = ['https://fonts.googleapis.com', 'https://fonts.gstatic.com', 'https://cdn.plitzi.com'];
41
+ %>
42
+ <% for (const origin of staticOrigins) { %>
43
+ <link rel="preconnect" href="<%= origin %>" crossorigin />
44
+ <% } %>
45
+
46
+ <%
47
+ /*
48
+ The space's web fonts, in the document rather than fetched by the SDK once it mounts.
49
+
50
+ A page paints long before its JavaScript exists. A face asked for at hydration arrives after the text it
51
+ was meant for has already been drawn in a fallback, and the visitor watches it reflow — which is exactly
52
+ what happened while the only thing that requested a family was the SDK's client-side asset rail.
53
+
54
+ The value is `fontsToHead(style.fonts, ...)` from @plitzi/sdk-shared: one place decides what a manifest
55
+ means, because SSR, the client, the builder canvas and the static export must all decide it the same way.
56
+ */
57
+ %>
58
+ <% if (locals.fonts) { %>
59
+ <% for (const origin of locals.fonts.preconnect.filter(item => !staticOrigins.includes(item.href))) { %>
60
+ <link rel="preconnect" href="<%= origin.href %>" <%- origin.crossorigin ? 'crossorigin' : '' %> />
61
+ <% } %>
62
+ <% for (const link of locals.fonts.links) { %>
63
+ <link
64
+ rel="<%= link.rel %>"
65
+ href="<%= link.href %>"
66
+ <%- link.as ? `as="${link.as}"` : '' %>
67
+ <%- link.type ? `type="${link.type}"` : '' %>
68
+ <%- link.crossorigin ? 'crossorigin' : '' %>
69
+ />
70
+ <% } %>
71
+ <% if (locals.fonts.faces) { %>
72
+ <%
73
+ /* Marked so the SDK can tell the document already carries them and does not declare a second copy. */
74
+ %>
75
+ <style data-plitzi-fonts><%- locals.fonts.faces %></style>
76
+ <% } %>
77
+ <% } %>
12
78
 
13
79
  <% if (!locals.ssrOnly) { %>
14
80
  <link rel="modulepreload" href="<%= locals.react || '' %>" crossorigin />
@@ -63,7 +129,7 @@
63
129
  <% for (const plugin of activePlugins) { %>
64
130
  import { default as <%= plugin.varName %> } from '<%= plugin.js %>';
65
131
  <% } %>
66
- const __plitziPlugins = { <%- activePlugins.map(p => `'${p.keyName}': {component: ${p.varName}, props: ${JSON.stringify(p.props)}}`).join(', ') %> };
132
+ const __plitziPlugins = { <%- activePlugins.map(p => `'${p.keyName}': {component: ${p.varName}, props: ${JSON.stringify(p.props)}, clientOnly: ${p.ssr === false}}`).join(', ') %> };
67
133
  render('plitzi', <%- locals.offlineData || '{}' %>, __plitziPlugins, <%= locals.debugMode ? true : false %>, true);
68
134
  <% } else { %>
69
135
  render('plitzi', <%- locals.offlineData || '{}' %>, {}, <%= locals.debugMode ? true : false %>, true);
@@ -0,0 +1,26 @@
1
+ /** An account store on MySQL, implemented. Import it as `@plitzi/sdk-server/mysql`.
2
+ *
3
+ * `@plitzi/sdk-server/auth` says what auth needs to know — the accounts, the roles, the memberships, the space
4
+ * credentials — and leaves answering it to the deployment, which is right for one that already has a user table
5
+ * and pure ceremony for one that does not. This entry is the other case: the tables, the queries and the seeding,
6
+ * so standing up a space with your own users is a connection string rather than a schema design.
7
+ *
8
+ * ```ts
9
+ * import { createServer } from '@plitzi/sdk-server';
10
+ * import { createAuth } from '@plitzi/sdk-server/auth';
11
+ * import { createMysqlStore } from '@plitzi/sdk-server/mysql';
12
+ *
13
+ * const store = await createMysqlStore({ url: process.env.DATABASE_URL });
14
+ * const auth = createAuth({ tokens: { secret, issuer }, adapters: store.authAdapters });
15
+ *
16
+ * createServer({ adapters: space, auth }).listen(3000);
17
+ * ```
18
+ *
19
+ * Its own entry, and its own optional peer dependency (`mysql2`), because it is the only part of the package that
20
+ * touches a database: a deployment bringing its own store neither loads a driver nor downloads one.
21
+ *
22
+ * The tables are documented in `docs/auth/mysql-schema.md` — what each one is for, and what a deployment mapping
23
+ * its existing schema onto the adapters has to be able to answer. */
24
+ export { createMysqlStore, mysqlSchemaStatements } from './modules/mysql';
25
+ export { SCHEMA_VERSION, TABLE_NAMES, tableNames } from './modules/mysql';
26
+ export type { AccountSeed, MysqlAdmin, MysqlConfig, IdentityStore, LinkedIdentity, MysqlStore, SessionStore, SessionSummary, SpaceTokenSeed, TableKey, Tables } from './modules/mysql';
package/dist/mysql.js ADDED
@@ -0,0 +1,4 @@
1
+ import { TABLE_NAMES, tableNames } from "./modules/mysql/config.js";
2
+ import { SCHEMA_VERSION } from "./modules/mysql/schema.js";
3
+ import { createMysqlStore, mysqlSchemaStatements } from "./modules/mysql/index.js";
4
+ export { SCHEMA_VERSION, TABLE_NAMES, createMysqlStore, mysqlSchemaStatements, tableNames };
@@ -0,0 +1,24 @@
1
+ /**
2
+ * OAuth 2.1 authorization, as a mechanism.
3
+ *
4
+ * Discovery, dynamic client registration, PKCE, the one-shot code and the token endpoint — the whole protocol,
5
+ * and none of the policy. A deployment supplies {@link OAuthAdapters}: who the browser already is, what they may
6
+ * grant, and the credential to mint. What that credential IS decides what the flow is FOR, and this server is
7
+ * mounted more than once for exactly that reason — the MCP connector grants a space-scoped agent token, while the
8
+ * platform's own native clients (the desktop app, the CLI) grant a user session. Same protocol, same screens,
9
+ * different `issueToken`.
10
+ *
11
+ * It lived inside the MCP server while it had one caller. It is here now because the line this repo draws is that
12
+ * sdk-server owns the MECHANISM and a consumer owns the data — and a grant flow that only one app can mount is a
13
+ * mechanism trapped in a consumer.
14
+ */
15
+ export { handleAuthorizeStart, handleAuthorizeSubmit } from './core/oauth/authorize';
16
+ export { bearerOf, sendChallenge } from './core/oauth/challenge';
17
+ export { authorizationServerMetadata, AUTHORIZATION_SERVER_PATH, AUTHORIZE_PATH, protectedResourceMetadata, PROTECTED_RESOURCE_PATH, REGISTER_PATH, TOKEN_PATH } from './core/oauth/metadata';
18
+ export { randomId, verifyChallenge } from './core/oauth/pkce';
19
+ export { dropPending, getAccess, getClient, getPending, putCode, putPending } from './core/oauth/records';
20
+ export { handleRegister } from './core/oauth/register';
21
+ export { redirectToSignIn, redirectWithCode, redirectWithError, sendErrorJson, sendJson } from './core/oauth/respond';
22
+ export { handleRevoke, handleToken } from './core/oauth/token';
23
+ export { createOAuthGuardStage, createOAuthStage } from './core/http/stages/oauth';
24
+ export type { OAuthParams } from './core/oauth/params';
package/dist/oauth.js ADDED
@@ -0,0 +1,10 @@
1
+ import { AUTHORIZATION_SERVER_PATH, AUTHORIZE_PATH, PROTECTED_RESOURCE_PATH, REGISTER_PATH, TOKEN_PATH, authorizationServerMetadata, protectedResourceMetadata } from "./core/oauth/metadata.js";
2
+ import { randomId, verifyChallenge } from "./core/oauth/pkce.js";
3
+ import { dropPending, getAccess, getClient, getPending, putCode, putPending } from "./core/oauth/records.js";
4
+ import { redirectToSignIn, redirectWithCode, redirectWithError, sendErrorJson, sendJson } from "./core/oauth/respond.js";
5
+ import { handleAuthorizeStart, handleAuthorizeSubmit } from "./core/oauth/authorize.js";
6
+ import { bearerOf, sendChallenge } from "./core/oauth/challenge.js";
7
+ import { handleRegister } from "./core/oauth/register.js";
8
+ import { handleRevoke, handleToken } from "./core/oauth/token.js";
9
+ import { createOAuthGuardStage, createOAuthStage } from "./core/http/stages/oauth.js";
10
+ export { AUTHORIZATION_SERVER_PATH, AUTHORIZE_PATH, PROTECTED_RESOURCE_PATH, REGISTER_PATH, TOKEN_PATH, authorizationServerMetadata, bearerOf, createOAuthGuardStage, createOAuthStage, dropPending, getAccess, getClient, getPending, handleAuthorizeStart, handleAuthorizeSubmit, handleRegister, handleRevoke, handleToken, protectedResourceMetadata, putCode, putPending, randomId, redirectToSignIn, redirectWithCode, redirectWithError, sendChallenge, sendErrorJson, sendJson, verifyChallenge };
@@ -1,3 +1,4 @@
1
1
  export declare const compilePlugin: (jsPath: string, outDir: string, devMode?: boolean) => Promise<{
2
2
  hasCSS: boolean;
3
+ inputs: string[];
3
4
  }>;
@@ -10,20 +10,54 @@ var EXTERNAL = [
10
10
  "@plitzi/plitzi-sdk",
11
11
  "@plitzi/sdk-shared"
12
12
  ];
13
+ /**
14
+ * Assets a stylesheet drags in with it, inlined.
15
+ *
16
+ * A plugin that imports a library's CSS — a map, a date picker, an editor — imports its images too, and without a
17
+ * loader for them the build fails on a file the author never wrote. Inlined as data URIs rather than emitted
18
+ * beside the bundle, because the plugin is served as exactly two files and a third that nothing routes to would
19
+ * be a stylesheet with broken references in it.
20
+ */
21
+ var ASSET_LOADERS = {
22
+ ".png": "dataurl",
23
+ ".jpg": "dataurl",
24
+ ".jpeg": "dataurl",
25
+ ".gif": "dataurl",
26
+ ".svg": "dataurl",
27
+ ".webp": "dataurl",
28
+ ".woff": "dataurl",
29
+ ".woff2": "dataurl"
30
+ };
31
+ /**
32
+ * Everything that went into the bundle, so a dev server can tell when any of it has moved on.
33
+ *
34
+ * The entry file is one file and a plugin is a directory: a component edited beside its `index.ts` leaves the entry's
35
+ * timestamp exactly where it was, and a watcher looking only at that never rebuilds. esbuild already knows the answer
36
+ * — this is its own list of inputs — so nothing has to be guessed from the file system.
37
+ *
38
+ * Dependencies are left out. They change when something is installed, which is not an edit anybody is waiting to see,
39
+ * and stat'ing a few thousand files on every cache miss to find that out is a real cost for no answer.
40
+ */
41
+ var sourceInputs = (metafile) => metafile ? Object.keys(metafile.inputs).filter((input) => !input.includes("node_modules")).map((input) => path.resolve(input)) : [];
13
42
  var compilePlugin = async (jsPath, outDir, devMode = false) => {
14
- await esbuild.build({
43
+ const result = await esbuild.build({
15
44
  entryPoints: [jsPath],
16
45
  bundle: true,
17
46
  format: "esm",
18
47
  external: EXTERNAL,
48
+ loader: ASSET_LOADERS,
19
49
  outdir: outDir,
20
50
  entryNames: "index",
21
51
  jsx: "automatic",
22
52
  minify: !devMode,
23
53
  splitting: false,
24
- logLevel: "warning"
54
+ logLevel: "warning",
55
+ metafile: devMode
25
56
  });
26
- return { hasCSS: await fs.access(path.join(outDir, "index.css")).then(() => true).catch(() => false) };
57
+ return {
58
+ hasCSS: await fs.access(path.join(outDir, "index.css")).then(() => true).catch(() => false),
59
+ inputs: sourceInputs(result.metafile)
60
+ };
27
61
  };
28
62
  //#endregion
29
63
  export { compilePlugin };
@@ -26,7 +26,47 @@ export declare class PluginManager {
26
26
  private resolveKey;
27
27
  private pluginDir;
28
28
  private isExpired;
29
+ /**
30
+ * Whether anything the bundle was built from has moved on since. Dev mode only.
31
+ *
32
+ * The cache is keyed on time and version, neither of which changes when somebody edits a component: a versioned
33
+ * plugin never expires and an unversioned one lasts a week, so a change to the source showed up nowhere and the
34
+ * server kept serving the bundle it built the first time. In production that is exactly right — a deployment's
35
+ * plugins do not change under it — and while somebody is writing one it is a file that appears to do nothing.
36
+ *
37
+ * Every INPUT, not the entry file. A plugin is a directory and the entry is usually a barrel that re-exports it, so
38
+ * watching only `source.js` answers "nothing has changed" to every edit anybody actually makes — the file whose
39
+ * timestamp moves is the component next to it. The list comes from the build itself (see `compilePlugin`), so it is
40
+ * exactly what went in, including a file imported from another plugin's folder. A bundle built before this existed
41
+ * has no list, and falls back to the entry file rather than claiming to be fresh.
42
+ */
43
+ /**
44
+ * The same question of the entry this process is holding, asked at most once a second.
45
+ *
46
+ * `checkedAt` is stamped on the cached entry rather than kept in a second map, so it cannot outlive what it is about.
47
+ */
48
+ private isStaleInMemory;
49
+ private isStale;
50
+ /**
51
+ * The bundle's URL, stamped with when it was built.
52
+ *
53
+ * Plugin assets are served `immutable` for a year, which is right for a file whose URL identifies its contents
54
+ * and catastrophic for one whose URL never changes: a browser told a resource is immutable does not revalidate
55
+ * it at all — no conditional request, no ETag — so a rebuilt plugin never reaches anyone who had already loaded
56
+ * the old one. Not a stale render either: the page's own CSS is fresh while the plugin's is a year old, and the
57
+ * two disagree in ways nobody can read. The stamp is what makes the promise true.
58
+ */
59
+ private assetUrl;
29
60
  private toEntry;
61
+ /**
62
+ * A plugin served from where it was published, with nothing on this server's disk.
63
+ *
64
+ * No `filePath`, which is the whole point: `loadPluginComponents` only imports entries that have one, so a
65
+ * bundle this server did not build never enters the render process — and cannot bring a second copy of React
66
+ * in with it. The template already imports `js` in the browser, so the plugin still renders, just on the
67
+ * client.
68
+ */
69
+ private toRemoteEntry;
30
70
  private isWebUrl;
31
71
  prepare(name: string): Promise<PluginEntry | null>;
32
72
  private build;
@@ -8,6 +8,13 @@ import fs from "node:fs/promises";
8
8
  var META_FILE = "meta.json";
9
9
  var DEFAULT_TTL_MS = 6048e5;
10
10
  var DEFAULT_CACHE_DIR = ".sdk-plugins";
11
+ /**
12
+ * How often a dev server re-asks whether a cached plugin is still current.
13
+ *
14
+ * The check is a handful of `stat`s and this runs on every render, so it is throttled rather than free — a second is
15
+ * far below what anybody notices between saving a file and reloading a page, and far above per-request.
16
+ */
17
+ var STALE_CHECK_MS = 1e3;
11
18
  var PluginManager = class {
12
19
  urlPrefix = "/sdk-plugins";
13
20
  outputDir;
@@ -66,18 +73,83 @@ var PluginManager = class {
66
73
  isExpired(compiledAt) {
67
74
  return Date.now() - compiledAt > this.ttlMs;
68
75
  }
69
- toEntry(name, hasJS, cssUrl, props = {}) {
76
+ /**
77
+ * Whether anything the bundle was built from has moved on since. Dev mode only.
78
+ *
79
+ * The cache is keyed on time and version, neither of which changes when somebody edits a component: a versioned
80
+ * plugin never expires and an unversioned one lasts a week, so a change to the source showed up nowhere and the
81
+ * server kept serving the bundle it built the first time. In production that is exactly right — a deployment's
82
+ * plugins do not change under it — and while somebody is writing one it is a file that appears to do nothing.
83
+ *
84
+ * Every INPUT, not the entry file. A plugin is a directory and the entry is usually a barrel that re-exports it, so
85
+ * watching only `source.js` answers "nothing has changed" to every edit anybody actually makes — the file whose
86
+ * timestamp moves is the component next to it. The list comes from the build itself (see `compilePlugin`), so it is
87
+ * exactly what went in, including a file imported from another plugin's folder. A bundle built before this existed
88
+ * has no list, and falls back to the entry file rather than claiming to be fresh.
89
+ */
90
+ /**
91
+ * The same question of the entry this process is holding, asked at most once a second.
92
+ *
93
+ * `checkedAt` is stamped on the cached entry rather than kept in a second map, so it cannot outlive what it is about.
94
+ */
95
+ async isStaleInMemory(cached, source) {
96
+ if (!this.devMode) return false;
97
+ const now = Date.now();
98
+ if (cached.checkedAt && now - cached.checkedAt < STALE_CHECK_MS) return false;
99
+ cached.checkedAt = now;
100
+ return this.isStale({
101
+ compiledAt: cached.compiledAt,
102
+ inputs: cached.inputs
103
+ }, source);
104
+ }
105
+ async isStale(meta, source) {
106
+ if (!this.devMode || !source.js || /^https?:\/\//.test(source.js) || isComponentSource(source)) return false;
107
+ const watched = meta.inputs?.length ? meta.inputs : [source.js];
108
+ return (await Promise.all(watched.map((file) => fs.stat(file).then((stats) => stats.mtimeMs).catch(() => 0)))).some((modifiedAt) => modifiedAt > meta.compiledAt);
109
+ }
110
+ /**
111
+ * The bundle's URL, stamped with when it was built.
112
+ *
113
+ * Plugin assets are served `immutable` for a year, which is right for a file whose URL identifies its contents
114
+ * and catastrophic for one whose URL never changes: a browser told a resource is immutable does not revalidate
115
+ * it at all — no conditional request, no ETag — so a rebuilt plugin never reaches anyone who had already loaded
116
+ * the old one. Not a stale render either: the page's own CSS is fresh while the plugin's is a year old, and the
117
+ * two disagree in ways nobody can read. The stamp is what makes the promise true.
118
+ */
119
+ assetUrl(name, file, compiledAt) {
120
+ return `${this.urlPrefix}/${name}/${file}?v=${compiledAt.toString(36)}`;
121
+ }
122
+ toEntry(name, hasJS, cssUrl, props = {}, compiledAt = 0) {
70
123
  const keyName = name.split("@")[0];
71
124
  return {
72
125
  name,
73
126
  varName: keyName.split("-").join("_").split(".").join("_"),
74
127
  keyName,
75
- js: hasJS ? `${this.urlPrefix}/${name}/index.js` : void 0,
128
+ js: hasJS ? this.assetUrl(name, "index.js", compiledAt) : void 0,
76
129
  filePath: hasJS ? path.join(this.outputDir, name, "index.js") : void 0,
77
130
  css: cssUrl,
78
131
  props
79
132
  };
80
133
  }
134
+ /**
135
+ * A plugin served from where it was published, with nothing on this server's disk.
136
+ *
137
+ * No `filePath`, which is the whole point: `loadPluginComponents` only imports entries that have one, so a
138
+ * bundle this server did not build never enters the render process — and cannot bring a second copy of React
139
+ * in with it. The template already imports `js` in the browser, so the plugin still renders, just on the
140
+ * client.
141
+ */
142
+ toRemoteEntry(name, source) {
143
+ const keyName = name.split("@")[0];
144
+ return {
145
+ name,
146
+ varName: keyName.split("-").join("_").split(".").join("_"),
147
+ keyName,
148
+ js: source.js,
149
+ css: source.css,
150
+ props: source.props ?? {}
151
+ };
152
+ }
81
153
  isWebUrl(s) {
82
154
  return s.startsWith("/") || s.startsWith("http://") || s.startsWith("https://");
83
155
  }
@@ -89,16 +161,38 @@ var PluginManager = class {
89
161
  const source = this.plugins[key];
90
162
  if (source === void 0) return null;
91
163
  if (isComponentSource(source) && !source.js) return this.toEntry(key, false, void 0, source.props);
164
+ if (!isComponentSource(source) && source.action === "cdn") return this.toRemoteEntry(key, source);
92
165
  const cached = this.mem.get(key);
93
166
  if (cached && !this.isExpired(cached.compiledAt)) {
94
- if (await this.fileExists(path.join(this.pluginDir(key), "index.js"))) return cached.entry;
95
- console.warn(`[SSR] Plugin "${key}" cache invalidated: output file missing, rebuilding…`);
96
- this.mem.delete(key);
167
+ if (await this.fileExists(path.join(this.pluginDir(key), "index.js"))) {
168
+ /**
169
+ * The disk check below never runs while this process holds the entry in memory, and a versioned plugin never
170
+ * expires — so without this a dev server serves the bundle it built when it started, for as long as it runs.
171
+ * Nothing else brings it back either: the components are named by PATH rather than imported, so editing one
172
+ * does not even restart the watcher.
173
+ */
174
+ if (!await this.isStaleInMemory(cached, source)) return cached.entry;
175
+ console.log(`[SSR] Plugin "${key}" source changed since it was built, rebuilding…`);
176
+ this.mem.delete(key);
177
+ await fs.rm(this.pluginDir(key), {
178
+ recursive: true,
179
+ force: true
180
+ });
181
+ } else {
182
+ console.warn(`[SSR] Plugin "${key}" cache invalidated: output file missing, rebuilding…`);
183
+ this.mem.delete(key);
184
+ }
97
185
  }
98
186
  const meta = await this.readMeta(key);
99
187
  if (meta) {
100
188
  const sourceVersion = source.version;
101
- if (sourceVersion && meta.version !== sourceVersion) {
189
+ if (await this.isStale(meta, source)) {
190
+ console.log(`[SSR] Plugin "${key}" source changed since it was built, rebuilding…`);
191
+ await fs.rm(this.pluginDir(key), {
192
+ recursive: true,
193
+ force: true
194
+ });
195
+ } else if (sourceVersion && meta.version !== sourceVersion) {
102
196
  console.log(`[SSR] Plugin "${key}" version changed (${meta.version ?? "none"} → ${sourceVersion}), rebuilding…`);
103
197
  await fs.rm(this.pluginDir(key), {
104
198
  recursive: true,
@@ -108,12 +202,13 @@ var PluginManager = class {
108
202
  if (await this.fileExists(path.join(this.pluginDir(key), "index.js"))) {
109
203
  const sourceCss = source.css;
110
204
  let cssUrl;
111
- if (await this.fileExists(path.join(this.pluginDir(key), "index.css"))) cssUrl = `${this.urlPrefix}/${key}/index.css`;
205
+ if (await this.fileExists(path.join(this.pluginDir(key), "index.css"))) cssUrl = this.assetUrl(key, "index.css", meta.compiledAt);
112
206
  else if (sourceCss && this.isWebUrl(sourceCss)) cssUrl = sourceCss;
113
- const entry = this.toEntry(key, true, cssUrl, source.props);
207
+ const entry = this.toEntry(key, true, cssUrl, source.props, meta.compiledAt);
114
208
  this.mem.set(key, {
115
209
  compiledAt: meta.compiledAt,
116
- entry
210
+ entry,
211
+ inputs: meta.inputs
117
212
  });
118
213
  return entry;
119
214
  }
@@ -133,8 +228,10 @@ var PluginManager = class {
133
228
  console.log(`[SSR] Plugin "${name}" building (${action}: ${jsPath})…`);
134
229
  try {
135
230
  let cssUrl;
231
+ let buildInputs = [];
136
232
  if (action === "compile") {
137
- const { hasCSS } = await compilePlugin(jsPath, dir, this.devMode);
233
+ const { hasCSS, inputs } = await compilePlugin(jsPath, dir, this.devMode);
234
+ buildInputs = inputs;
138
235
  if (hasCSS) cssUrl = `${this.urlPrefix}/${name}/index.css`;
139
236
  else if (cssPath) {
140
237
  if (this.isWebUrl(cssPath)) cssUrl = cssPath;
@@ -169,12 +266,15 @@ var PluginManager = class {
169
266
  const compiledAt = Date.now();
170
267
  await this.writeMeta(name, {
171
268
  compiledAt,
172
- version: source.version
269
+ version: source.version,
270
+ inputs: buildInputs
173
271
  });
174
- const entry = this.toEntry(name, true, cssUrl, source.props);
272
+ if (cssUrl?.startsWith(this.urlPrefix)) cssUrl = this.assetUrl(name, "index.css", compiledAt);
273
+ const entry = this.toEntry(name, true, cssUrl, source.props, compiledAt);
175
274
  this.mem.set(name, {
176
275
  compiledAt,
177
- entry
276
+ entry,
277
+ inputs: buildInputs
178
278
  });
179
279
  console.log(`[SSR] Plugin "${name}" ready → ${entry.js}`);
180
280
  return entry;
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@plitzi/sdk-server",
3
- "version": "0.33.2",
3
+ "version": "0.34.1",
4
4
  "license": "AGPL-3.0",
5
5
  "files": [
6
- "dist"
6
+ "dist",
7
+ "skills"
7
8
  ],
8
9
  "main": "dist/index.js",
9
10
  "module": "dist/index.js",
@@ -14,11 +15,26 @@
14
15
  "import": "./dist/index.js",
15
16
  "default": "./dist/index.js"
16
17
  },
18
+ "./auth": {
19
+ "types": "./dist/auth.d.ts",
20
+ "import": "./dist/auth.js",
21
+ "default": "./dist/auth.js"
22
+ },
23
+ "./oauth": {
24
+ "types": "./dist/oauth.d.ts",
25
+ "import": "./dist/oauth.js",
26
+ "default": "./dist/oauth.js"
27
+ },
17
28
  "./kernel": {
18
29
  "types": "./dist/kernel.d.ts",
19
30
  "import": "./dist/kernel.js",
20
31
  "default": "./dist/kernel.js"
21
32
  },
33
+ "./mysql": {
34
+ "types": "./dist/mysql.d.ts",
35
+ "import": "./dist/mysql.js",
36
+ "default": "./dist/mysql.js"
37
+ },
22
38
  "./handlers": {
23
39
  "types": "./dist/handlers.d.ts",
24
40
  "import": "./dist/handlers.js",
@@ -28,6 +44,11 @@
28
44
  "types": "./dist/ssr.d.ts",
29
45
  "import": "./dist/ssr.js",
30
46
  "default": "./dist/ssr.js"
47
+ },
48
+ "./actions": {
49
+ "types": "./dist/actions.d.ts",
50
+ "import": "./dist/actions.js",
51
+ "default": "./dist/actions.js"
31
52
  }
32
53
  },
33
54
  "repository": {
@@ -37,34 +58,42 @@
37
58
  "type": "module",
38
59
  "sideEffects": false,
39
60
  "dependencies": {
40
- "@plitzi/plitzi-sdk": "0.33.2",
41
- "@plitzi/sdk-shared": "0.33.2",
61
+ "@plitzi/plitzi-sdk": "0.34.1",
62
+ "@plitzi/sdk-shared": "0.34.1",
42
63
  "ejs": "^6.0.1",
43
64
  "esbuild": "^0.28.2",
44
65
  "jsonwebtoken": "^9.0.3"
45
66
  },
46
67
  "peerDependencies": {
68
+ "mysql2": "^3",
47
69
  "react": "^19",
48
70
  "react-dom": "^19"
49
71
  },
72
+ "peerDependenciesMeta": {
73
+ "mysql2": {
74
+ "optional": true
75
+ }
76
+ },
50
77
  "devDependencies": {
51
78
  "@types/ejs": "^3.1.5",
52
79
  "@types/jsonwebtoken": "^9.0.10",
53
- "@types/node": "^26.2.0",
54
- "@types/react": "^19.2.18",
55
- "@vitejs/plugin-react": "^6.0.5",
56
- "@vitest/coverage-v8": "^4.1.10",
80
+ "@types/node": "^26.5.1",
81
+ "@types/react": "^19.3.0",
82
+ "@vitejs/plugin-react": "^6.1.1",
83
+ "@vitest/coverage-v8": "^5.0.0",
57
84
  "eslint": "^9.39.5",
58
85
  "eslint-plugin-import": "^2.32.0",
59
- "react": "^19.2.8",
60
- "react-dom": "^19.2.8",
61
- "tsx": "^4.23.12",
86
+ "mysql2": "^3.24.4",
87
+ "react": "^19.3.0",
88
+ "react-dom": "^19.3.0",
89
+ "tsx": "^4.23.13",
62
90
  "typescript": "^6.0.3",
63
- "vite": "^8.2.1",
64
- "vite-plugin-dts": "^5.0.3",
65
- "vitest": "^4.1.10"
91
+ "vite": "^8.3.0",
92
+ "vite-plugin-dts": "^5.1.0",
93
+ "vitest": "^5.0.0"
66
94
  },
67
95
  "scripts": {
96
+ "prepack": "node scripts/copy-authoring-skill.mjs",
68
97
  "start:dev": "node --import ./dev/register-alias.mjs --watch dev/main.ts",
69
98
  "start": "TSX_TSCONFIG_PATH=tsconfig.app.json node --import tsx dev/main.ts",
70
99
  "start:watch": "TSX_TSCONFIG_PATH=tsconfig.app.json node --import tsx --watch dev/main.ts",