@plitzi/sdk-server 0.33.2 → 0.34.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 (274) hide show
  1. package/CHANGELOG.md +44 -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 +252 -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
package/dist/kernel.js CHANGED
@@ -2,21 +2,8 @@ import { clientIp, parseRequest, readRawBody, requestOrigin } from "./core/reque
2
2
  import { createHttpServer } from "./core/server/baseServer.js";
3
3
  import { PREVIEW_TOKEN_PARAM } from "./core/previewToken.js";
4
4
  import { makeHandler } from "./core/http/dispatcher.js";
5
- import { clearFlowCookie, clearSessionCookies, createSessionCookies, isLocalHost, readFlowCookie, readRefreshToken, readSessionToken, sessionCookieParams, sessionHintValue, writeFlowCookie, writeSessionCookies } from "./core/auth/session.js";
6
5
  import { buildHealthPayload, registerHealthCheck } from "./core/health.js";
7
6
  import { healthStage } from "./core/http/stages/health.js";
8
7
  import { configStaticStage, publicDirStage, wellKnownStage } from "./core/http/stages/static.js";
9
8
  import { consoleLogger, renderLogEvent } from "./helpers/serverLog.js";
10
- import { SCOPES, authFailureMessage, createTokens, userIdOf } from "./core/auth/tokens.js";
11
- import { createCarriers, presentedOrigin } from "./core/auth/credentials.js";
12
- import { ANY_DOMAIN, corsOrigins, domainAllowed, frameAncestors, hostnameOf, normalizeDomain } from "./core/auth/domains.js";
13
- import { createIdentity } from "./core/auth/identity.js";
14
- import { checkPermission, checkSpaceAccess, createAuthorizer, requirementFor } from "./core/auth/authorize.js";
15
- import { createAuthApi } from "./core/auth/api.js";
16
- import { applySessionOutcome, authPolicyRules, authRoutes } from "./core/auth/routes.js";
17
- import { createAuth } from "./core/auth/createAuth.js";
18
- import { createSpaceTokenApi } from "./core/auth/spaceTokens.js";
19
- import { OAuthFailure } from "./core/auth/oauth/types.js";
20
- import { requestProfileJson } from "./core/auth/oauth/client.js";
21
- import { BUILT_IN_PROVIDERS, createSocialAuth } from "./core/auth/oauth/index.js";
22
- export { ANY_DOMAIN, BUILT_IN_PROVIDERS, OAuthFailure, PREVIEW_TOKEN_PARAM, SCOPES, applySessionOutcome, authFailureMessage, authPolicyRules, authRoutes, buildHealthPayload, checkPermission, checkSpaceAccess, clearFlowCookie, clearSessionCookies, clientIp, configStaticStage, consoleLogger, corsOrigins, createAuth, createAuthApi, createAuthorizer, createCarriers, createHttpServer, createIdentity, createSessionCookies, createSocialAuth, createSpaceTokenApi, createTokens, domainAllowed, frameAncestors, healthStage, hostnameOf, isLocalHost, makeHandler, normalizeDomain, parseRequest, presentedOrigin, publicDirStage, readFlowCookie, readRawBody, readRefreshToken, readSessionToken, registerHealthCheck, renderLogEvent, requestOrigin, requestProfileJson, requirementFor, sessionCookieParams, sessionHintValue, userIdOf, wellKnownStage, writeFlowCookie, writeSessionCookies };
9
+ export { PREVIEW_TOKEN_PARAM, buildHealthPayload, clientIp, configStaticStage, consoleLogger, createHttpServer, healthStage, makeHandler, parseRequest, publicDirStage, readRawBody, registerHealthCheck, renderLogEvent, requestOrigin, wellKnownStage };
@@ -1,5 +1,5 @@
1
1
  import { writeConnectorRecord } from "../connectors/engine.js";
2
- //#region src/modules/actions/handler.ts
2
+ //#region src/modules/actions/connectorWrite.ts
3
3
  var parseBody = (body) => {
4
4
  if (!body) return;
5
5
  try {
@@ -44,7 +44,10 @@ var handleAction = async (req, res, config, lookups) => {
44
44
  fail(res, 400, "Element has no connector");
45
45
  return;
46
46
  }
47
- const manifest = await lookups.getConnector(spaceId, connectorId);
47
+ const manifest = await lookups.getConnector(spaceId, connectorId, {
48
+ environment,
49
+ revision
50
+ });
48
51
  if (!manifest) {
49
52
  fail(res, 404, "Unknown connector");
50
53
  return;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ import { RunGuards } from './runtime/guards';
2
+ import { ActionRunner } from './runtime/runAction';
3
+ import { ActionKvStore, ActionsConfig, ActionTaskRegistry, ResolvedActionLimits } from './types';
4
+ import { ActionDocument } from '@plitzi/sdk-shared';
5
+ export type ActionsModule = ActionRunner & {
6
+ registry: ActionTaskRegistry;
7
+ guards: RunGuards;
8
+ /** The key/value store, namespaced to one space — the same one the `kv` tasks write through, so a rate limit the
9
+ * transport keeps and a counter a flow keeps cannot end up in different places. */
10
+ kv: (spaceId: number) => ActionKvStore;
11
+ /** What this server will allow one run of that document to spend — the deployment's ceilings, tightened by it. */
12
+ limitsFor: (document: ActionDocument) => ResolvedActionLimits;
13
+ };
14
+ /**
15
+ * The module's whole public surface: build it once from the deployment's config, then run actions through it.
16
+ *
17
+ * Constructed rather than imported piecemeal so the task registry is validated ONCE, at boot, and so the guards
18
+ * are a single set for the process — two instances would each think they were the only run in flight, which is
19
+ * the same as having no single-flight at all. Nothing outside this folder needs to know how a run is assembled.
20
+ */
21
+ export declare const createActionsModule: (config: ActionsConfig) => ActionsModule;
22
+ export { ActionRunError } from './runtime/errors';
23
+ export { precheckRun } from './runtime/precheck';
24
+ export { checkAction } from './runtime/check';
25
+ export { DEFAULT_LIMITS, resolveLimits } from './runtime/limits';
26
+ export { createRunGuards, deriveRunKey } from './runtime/guards';
27
+ export { createScheduleRunner } from './runtime/schedule';
28
+ export { createMemoryKv } from './runtime/memoryKv';
29
+ export { createRunLogger, createRejectLogger } from './runtime/runLogger';
30
+ export { createTaskRegistry, taskName } from './tasks/registry';
31
+ export { describeCatalog, describeTask } from './taskCatalog';
32
+ export { handleActionCall } from './transport/callHandler';
33
+ export { handleActionCatalog } from './transport/catalogHandler';
34
+ export { handleActionWebhook } from './transport/webhookHandler';
35
+ export { verifySignature } from './transport/verifySignature';
36
+ export { handleActionCancel } from './transport/cancelHandler';
37
+ export type { ActiveRun, RunGuards } from './runtime/guards';
38
+ export type { ScheduleResult, ScheduleRunner, ScheduleTick } from './runtime/schedule';
39
+ export type { ActionTaskDescriptor } from './taskCatalog';
40
+ export type { ActionCredential, ActionDbDriver, ActionKvStore, ActionLookups, ActionRejectRecord, ActionRunRecord, ActionRunRequest, ActionRunResult, ActionsConfig, ActionTask, ActionTaskContext, ActionTaskRegistry, RegisteredTask, ResolvedConnector } from './types';
@@ -0,0 +1,46 @@
1
+ import "./runtime/errors.js";
2
+ import { createRunGuards } from "./runtime/guards.js";
3
+ import { createKvStore } from "./runtime/kvStore.js";
4
+ import { resolveLimits } from "./runtime/limits.js";
5
+ import { createMemoryKv } from "./runtime/memoryKv.js";
6
+ import { namespaceKv } from "./runtime/namespaceKv.js";
7
+ import "./runtime/precheck.js";
8
+ import { createActionRunner } from "./runtime/runAction.js";
9
+ import { createTaskRegistry } from "./tasks/registry.js";
10
+ import "./runtime/check.js";
11
+ import "./runtime/schedule.js";
12
+ import "./runtime/runLogger.js";
13
+ import "./taskCatalog.js";
14
+ import { handleActionCall } from "./transport/callHandler.js";
15
+ import { handleActionCatalog } from "./transport/catalogHandler.js";
16
+ import "./transport/verifySignature.js";
17
+ import { handleActionWebhook } from "./transport/webhookHandler.js";
18
+ import { handleActionCancel } from "./transport/cancelHandler.js";
19
+ //#region src/modules/actions/index.ts
20
+ /**
21
+ * The module's whole public surface: build it once from the deployment's config, then run actions through it.
22
+ *
23
+ * Constructed rather than imported piecemeal so the task registry is validated ONCE, at boot, and so the guards
24
+ * are a single set for the process — two instances would each think they were the only run in flight, which is
25
+ * the same as having no single-flight at all. Nothing outside this folder needs to know how a run is assembled.
26
+ */
27
+ var createActionsModule = (config) => {
28
+ const registry = createTaskRegistry(config.tasks, (config.dbDrivers?.length ?? 0) > 0);
29
+ const { runAction } = createActionRunner(config, registry, config.fetchImpl);
30
+ /**
31
+ * Single-flight over the store the deployment already gave the `kv` tasks — its own Redis, table or whatever it
32
+ * runs — because per process it is not a guarantee: the same double-click behind a load balancer lands on two
33
+ * replicas and both run. With none configured this is one process's Map, which is exactly right for one.
34
+ */
35
+ const guards = createRunGuards(config.concurrency, config.kv, config.idempotency);
36
+ const kv = createKvStore(config.kv ?? createMemoryKv());
37
+ return {
38
+ runAction,
39
+ registry,
40
+ guards,
41
+ kv: (spaceId) => namespaceKv(kv, spaceId),
42
+ limitsFor: (document) => resolveLimits(config.limits, document.limits)
43
+ };
44
+ };
45
+ //#endregion
46
+ export { createActionsModule, handleActionCall, handleActionCancel, handleActionCatalog, handleActionWebhook };
@@ -0,0 +1,3 @@
1
+ import { ActionsModule } from './index';
2
+ import { SSRServerConfig } from '@plitzi/sdk-shared';
3
+ export declare const actionsModuleFor: (config: SSRServerConfig) => ActionsModule | undefined;
@@ -0,0 +1,35 @@
1
+ import { createActionsModule } from "./index.js";
2
+ //#region src/modules/actions/moduleFor.ts
3
+ /**
4
+ * The one actions module for a server, whoever asks first.
5
+ *
6
+ * Two places need it and they are built at different moments: the page pipeline mounts the endpoint, and the RSC
7
+ * adapter is assembled before that to resolve `render` elements. Constructing one each would give a server two
8
+ * guard sets — and two sets each believing they hold the only run in flight is the same as having no single-flight
9
+ * at all.
10
+ *
11
+ * Memoized on the config OBJECT, which is exactly the lifetime wanted: one per `createServer` call, released with
12
+ * it, and a fresh one per server in a test file that builds several.
13
+ */
14
+ var modules = /* @__PURE__ */ new WeakMap();
15
+ var actionsModuleFor = (config) => {
16
+ const lookups = config.action?.lookups;
17
+ if (!lookups) return;
18
+ const existing = modules.get(config);
19
+ if (existing) return existing;
20
+ const module = createActionsModule({
21
+ lookups,
22
+ tasks: config.action?.tasks,
23
+ limits: config.action?.limits,
24
+ concurrency: config.action?.concurrency,
25
+ kv: config.action?.kv,
26
+ rateLimit: config.action?.rateLimit,
27
+ idempotency: config.action?.idempotency,
28
+ dbDrivers: config.action?.dbDrivers,
29
+ onRun: config.action?.onRun
30
+ });
31
+ modules.set(config, module);
32
+ return module;
33
+ };
34
+ //#endregion
35
+ export { actionsModuleFor };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ import { ActionDbDriver, ActionLookups, ActionTaskRegistry } from '../types';
2
+ import { ActionCheckReport, ActionEntry } from '@plitzi/sdk-shared';
3
+ export type ActionCheckDeps = {
4
+ spaceId: number;
5
+ registry: ActionTaskRegistry;
6
+ lookups: ActionLookups;
7
+ dbDrivers?: ActionDbDriver[];
8
+ };
9
+ /**
10
+ * What only THIS deployment can answer about an action.
11
+ *
12
+ * `validateActionDocument` reads the document and nothing else, so it catches a flow that contradicts itself — a
13
+ * step with no task, an output that names a step that does not exist. It cannot catch the other half, which is
14
+ * every way a correct document meets a server that cannot run it: a task this deployment never registered, a
15
+ * credential the space does not have, a key that is not in the credential it does have, a connector that was
16
+ * deleted, a database engine with no driver, a cron that will never fire.
17
+ *
18
+ * Those are the failures that surface at 3am on the first real delivery, and an author has no way to see them
19
+ * from the editor — which is why this runs on the server and answers in the same shape the validator does.
20
+ *
21
+ * It reads credentials to ask WHETHER they exist and whether they carry the key a step names. It never reports a
22
+ * value, and nothing here runs a step.
23
+ */
24
+ export declare const checkAction: (entry: ActionEntry, deps: ActionCheckDeps) => Promise<ActionCheckReport>;
@@ -0,0 +1,111 @@
1
+ import { triggerParams } from "./triggers.js";
2
+ import { hasValidToken } from "@plitzi/sdk-shared/helpers/twigWrapper";
3
+ import { parseCron, triggerHasStaleVerify, triggerVerify } from "@plitzi/sdk-shared/actions";
4
+ //#region src/modules/actions/runtime/check.ts
5
+ /** A value the check can reason about: a literal the author typed, not a template resolved at run time. */
6
+ var literal = (value) => {
7
+ const text = typeof value === "string" ? value.trim() : "";
8
+ return text && !hasValidToken(text) ? text : "";
9
+ };
10
+ /**
11
+ * What only THIS deployment can answer about an action.
12
+ *
13
+ * `validateActionDocument` reads the document and nothing else, so it catches a flow that contradicts itself — a
14
+ * step with no task, an output that names a step that does not exist. It cannot catch the other half, which is
15
+ * every way a correct document meets a server that cannot run it: a task this deployment never registered, a
16
+ * credential the space does not have, a key that is not in the credential it does have, a connector that was
17
+ * deleted, a database engine with no driver, a cron that will never fire.
18
+ *
19
+ * Those are the failures that surface at 3am on the first real delivery, and an author has no way to see them
20
+ * from the editor — which is why this runs on the server and answers in the same shape the validator does.
21
+ *
22
+ * It reads credentials to ask WHETHER they exist and whether they carry the key a step names. It never reports a
23
+ * value, and nothing here runs a step.
24
+ */
25
+ var checkAction = async (entry, deps) => {
26
+ const { spaceId, registry, lookups, dbDrivers = [] } = deps;
27
+ const issues = [];
28
+ const add = (level, path, message, hint) => issues.push({
29
+ level,
30
+ path,
31
+ message,
32
+ ...hint === void 0 ? {} : { hint }
33
+ });
34
+ /** Answers once per identifier: a flow naming the same credential in four steps is one lookup, not four. */
35
+ const credentials = /* @__PURE__ */ new Map();
36
+ const credentialOf = async (identifier) => {
37
+ if (!credentials.has(identifier)) credentials.set(identifier, await lookups.getCredential?.(spaceId, identifier));
38
+ return credentials.get(identifier);
39
+ };
40
+ const checkCredential = async (node, identifier, field) => {
41
+ const path = `nodes.${node.id}.params.credential`;
42
+ const credential = await credentialOf(identifier);
43
+ if (!credential) {
44
+ add("error", path, `This space has no credential called "${identifier}"`, "Add it in Credentials, or name one that exists");
45
+ return;
46
+ }
47
+ if (field && !(field in credential)) add("error", path, `The credential "${identifier}" has no key called "${field}"`, `It holds: ${Object.keys(credential).join(", ") || "nothing"}`);
48
+ return credential;
49
+ };
50
+ const checkTrigger = async (node) => {
51
+ const params = triggerParams(node);
52
+ if (node.action === "webhook") {
53
+ if (triggerHasStaleVerify(params)) {
54
+ add("error", `nodes.${node.id}.params.signatureCredential`, "The signature check is in a format nothing reads any more, so this endpoint is refused outright", "Name the signing credential on the trigger step");
55
+ return;
56
+ }
57
+ const verify = triggerVerify(params);
58
+ if (!verify) {
59
+ add("warning", `nodes.${node.id}.params.signatureCredential`, "This webhook verifies nothing: anyone who learns the URL can start it", "Name the credential holding the sender’s signing secret");
60
+ return;
61
+ }
62
+ const credential = await credentialOf(verify.credential);
63
+ const field = verify.secretField ?? "secret";
64
+ if (!credential) {
65
+ add("error", `nodes.${node.id}.params.signatureCredential`, `This space has no credential called "${verify.credential}"`);
66
+ return;
67
+ }
68
+ if (!(field in credential)) {
69
+ add("error", `nodes.${node.id}.params.signatureSecretField`, `The credential "${verify.credential}" has no key called "${field}"`, `It holds: ${Object.keys(credential).join(", ") || "nothing"}`);
70
+ return;
71
+ }
72
+ if (!credential[field]) add("error", `nodes.${node.id}.params.signatureSecretField`, `The key "${field}" of "${verify.credential}" is empty`);
73
+ }
74
+ if (node.action === "schedule" && !parseCron(params.cron ?? "")) add("error", `nodes.${node.id}.params.cron`, `"${params.cron ?? ""}" is not an expression this server can fire`, "Five fields, UTC — minute hour day-of-month month day-of-week");
75
+ };
76
+ const checkTask = async (node) => {
77
+ if (!registry.get(node.action)) {
78
+ add("error", `nodes.${node.id}.action`, `This server registers no task called "${node.action}"`, `It offers: ${registry.list().map((entry) => entry.name).join(", ")}`);
79
+ return;
80
+ }
81
+ const { params } = node;
82
+ const connector = literal(params.connector);
83
+ if (connector && !await lookups.getConnector?.(spaceId, connector)) add("error", `nodes.${node.id}.params.connector`, `This space has no connector called "${connector}"`, "Add it in Connectors, or name one that exists");
84
+ const identifier = literal(params.credential);
85
+ if (!identifier) return;
86
+ if (node.action === "db.query") {
87
+ const credential = await checkCredential(node, identifier, "dsn");
88
+ const engine = credential?.engine ?? "";
89
+ if (credential && !engine) {
90
+ add("error", `nodes.${node.id}.params.credential`, `The credential "${identifier}" declares no engine`, "Add an `engine` key naming the database, e.g. mysql");
91
+ return;
92
+ }
93
+ if (engine && !dbDrivers.some((driver) => driver.engine === engine)) add("error", `nodes.${node.id}.params.credential`, `This server has no driver for "${engine}"`, dbDrivers.length > 0 ? `It drives: ${dbDrivers.map((driver) => driver.engine).join(", ")}` : "It registers no database drivers at all");
94
+ return;
95
+ }
96
+ await checkCredential(node, identifier);
97
+ };
98
+ for (const node of Object.values(entry.document.nodes)) {
99
+ if (node.type === "trigger") {
100
+ await checkTrigger(node);
101
+ continue;
102
+ }
103
+ if (node.type === "task" && node.action) await checkTask(node);
104
+ }
105
+ return {
106
+ valid: !issues.some((issue) => issue.level === "error"),
107
+ issues
108
+ };
109
+ };
110
+ //#endregion
111
+ export { checkAction };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { ActionErrorReason } from '@plitzi/sdk-shared';
2
+ /**
3
+ * A run that stopped for a reason the caller is entitled to know, as opposed to one whose step threw.
4
+ *
5
+ * Its own file so the precheck and the runner can both raise it without either importing the other — the
6
+ * precheck is called BY the runner and BEFORE it, and a shared error type is the only thing they have in common.
7
+ */
8
+ export declare class ActionRunError extends Error {
9
+ reason: ActionErrorReason;
10
+ constructor(reason: ActionErrorReason, message: string);
11
+ }
@@ -0,0 +1,17 @@
1
+ //#region src/modules/actions/runtime/errors.ts
2
+ /**
3
+ * A run that stopped for a reason the caller is entitled to know, as opposed to one whose step threw.
4
+ *
5
+ * Its own file so the precheck and the runner can both raise it without either importing the other — the
6
+ * precheck is called BY the runner and BEFORE it, and a shared error type is the only thing they have in common.
7
+ */
8
+ var ActionRunError = class extends Error {
9
+ reason;
10
+ constructor(reason, message) {
11
+ super(message);
12
+ this.name = "ActionRunError";
13
+ this.reason = reason;
14
+ }
15
+ };
16
+ //#endregion
17
+ export { ActionRunError };
@@ -0,0 +1,126 @@
1
+ import { ActionCallResult } from '@plitzi/sdk-shared';
2
+ /**
3
+ * Which budget a run draws on.
4
+ *
5
+ * `call` is somebody ASKING for work — a click, a webhook, a schedule — and one space's callers hammering is a
6
+ * problem that belongs to that space. `render` is somebody LOOKING at a page, which is traffic: it scales with
7
+ * how popular the space is, and a ceiling per space would cap a successful page rather than an abusive one.
8
+ */
9
+ export type RunKind = 'call' | 'render';
10
+ /** A run currently holding a slot, and the handle that can stop it. */
11
+ export type ActiveRun = {
12
+ runId: string;
13
+ runKey: string;
14
+ kind: RunKind;
15
+ spaceId: number;
16
+ actionId: string;
17
+ callerId: string;
18
+ controller: AbortController;
19
+ expiresAt: number;
20
+ /**
21
+ * Whether the caller NAMED this run's key rather than having it derived from what they sent.
22
+ *
23
+ * It is what decides whether the answer may be replayed: a sender that stamps a delivery id is telling us which
24
+ * request this is, so answering the retry with the first result is exactly right. A derived key is a hash of
25
+ * the input, and two identical calls a minute apart are usually two things somebody meant to happen twice.
26
+ */
27
+ explicitKey: boolean;
28
+ };
29
+ /**
30
+ * The half of a key/value store the guards need, and nothing more.
31
+ *
32
+ * The same methods `ActionKvAdapter` already declares, so a deployment that configured `action.kv` has already
33
+ * provided this: no second store to stand up, and no adapter change. `increment` is what takes a single-flight
34
+ * key; `get`/`set` are what carry a cancellation and a replayable answer between replicas.
35
+ */
36
+ export type RunKeyStore = {
37
+ get: (key: string) => Promise<string | undefined>;
38
+ set: (key: string, value: string, ttlSeconds?: number) => Promise<void>;
39
+ increment: (key: string, amount: number) => Promise<number>;
40
+ expire: (key: string, ttlSeconds: number) => Promise<void>;
41
+ delete: (key: string) => Promise<void>;
42
+ };
43
+ export type RunGuardsConfig = {
44
+ /** Concurrent CALLS one space may have in flight. Renders are not counted here — see {@link RunKind}. */
45
+ perSpace?: number;
46
+ /** Concurrent calls this process will carry, across every space. */
47
+ perProcess?: number;
48
+ /**
49
+ * Concurrent RENDERS this process will carry, across every space — the only ceiling renders have.
50
+ *
51
+ * What a render threatens is the box, never the space it belongs to: five hundred people reading one page at
52
+ * once is that page working. So this is sized for a machine, and it is the number a deployment tunes when it
53
+ * knows its own — the default is deliberately generous, and each slot is held for at most one run's timeout.
54
+ */
55
+ renderPerProcess?: number;
56
+ };
57
+ export type BeginRunParams = {
58
+ spaceId: number;
59
+ actionId: string;
60
+ callerId: string;
61
+ input: Record<string, unknown>;
62
+ idempotencyKey?: string;
63
+ /**
64
+ * The key names the WORK, not who asked.
65
+ *
66
+ * True only for a webhook, where the key is the SENDER's delivery id and the signature that let the request in
67
+ * is what authenticated it: the same delivery retried from another of a provider's addresses is the same
68
+ * delivery, and scoping it per caller would run it twice.
69
+ *
70
+ * Everywhere else the key is a string the caller made up, so it is scoped to them. Without that, a visitor who
71
+ * learns or guesses another's key collides with their single-flight and — where a deployment set a replay
72
+ * window — is handed the answer their run produced.
73
+ */
74
+ sharedKey?: boolean;
75
+ ttlMs: number;
76
+ /** Which budget this run draws on. Defaults to `call`: a trigger that says nothing is somebody asking. */
77
+ kind?: RunKind;
78
+ };
79
+ /** What a deployment may set about replaying a finished run. Off unless it says otherwise. */
80
+ export type RunIdempotency = {
81
+ replayTtlMs?: number;
82
+ };
83
+ export type RunGuards = {
84
+ begin: (params: BeginRunParams) => Promise<ActiveRun>;
85
+ /** Releases the key, and — for a run the caller keyed itself — remembers the answer for {@link RunIdempotency}. */
86
+ end: (run: ActiveRun, outcome?: ActionCallResult) => Promise<void>;
87
+ get: (runId: string) => ActiveRun | undefined;
88
+ /** The answer a run with this key already produced, when it is still within the replay window. */
89
+ replay: (params: BeginRunParams) => Promise<ActionCallResult | undefined>;
90
+ /** Stops a run: here if this process holds it, and through the store if another one does. */
91
+ cancel: (runId: string, callerId: string) => Promise<boolean>;
92
+ active: () => number;
93
+ };
94
+ /**
95
+ * Where a cancellation is left for whichever replica is actually running the flow.
96
+ *
97
+ * Exported because the RUNNER is what reads it, at every step boundary, and the two must not each spell the key
98
+ * their own way — a cancel written under one name and read under another is a stop button that does nothing.
99
+ */
100
+ export declare const runCancelKey: (runId: string) => string;
101
+ export declare const deriveRunKey: ({ spaceId, actionId, callerId, input, idempotencyKey, sharedKey }: BeginRunParams) => string;
102
+ /**
103
+ * Single-flight, concurrency caps and cancellation, in one place.
104
+ *
105
+ * The client engine already refuses re-entry — `InteractionsManager` drops a trigger that fires while its own flow
106
+ * is still running — and this is the same rule keyed by what identifies a RUN rather than a DOM event. Without it
107
+ * a client that retries, reconnects or simply double-clicks turns one intent into many runs, and a streaming
108
+ * caller can turn it into an unbounded loop.
109
+ *
110
+ * **What is shared and what is not**, when a store is handed over:
111
+ *
112
+ * - **Single-flight is**, because per replica it is not a guarantee at all: the same double-click behind a load
113
+ * balancer lands on two of them and both run. The key is taken with `increment`, which is the one atomic
114
+ * test-and-set every adapter already has to provide — the holder is whoever's increment answered `1` — and it
115
+ * carries the run's own timeout as its lifetime, so a replica that dies holding one frees it by expiring.
116
+ * - **The caps are not.** Counting them across replicas needs a decrementing counter, and a run that dies without
117
+ * decrementing throttles a healthy space until somebody notices. A ceiling that is per replica is a number a
118
+ * deployment can multiply and reason about; one that leaks is not. So `perSpace` is per replica, deliberately,
119
+ * and a cluster's real ceiling is that times the number of them.
120
+ * - **Cancellation is**, in one direction. Only the process running a flow holds the `AbortController` that stops
121
+ * it, so a `DELETE` that lands anywhere else leaves a FLAG in the store and the run reads it at its next step
122
+ * boundary. Behind a load balancer that is the normal case rather than the exotic one: the tab that wants to
123
+ * stop a checkout almost never reaches the replica running it.
124
+ * - **A finished answer is**, when the caller named the key and the deployment set a replay window.
125
+ */
126
+ export declare const createRunGuards: (config?: RunGuardsConfig, store?: RunKeyStore, idempotency?: RunIdempotency) => RunGuards;