@plitzi/sdk-shared 0.37.1 → 0.37.3

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 (195) hide show
  1. package/CHANGELOG.md +1288 -0
  2. package/dist/actions/access.d.ts +12 -0
  3. package/dist/actions/access.mjs +13 -0
  4. package/dist/actions/cron.d.ts +21 -12
  5. package/dist/actions/cron.mjs +48 -17
  6. package/dist/actions/functions.d.ts +27 -0
  7. package/dist/actions/functions.mjs +18 -0
  8. package/dist/actions/index.d.ts +5 -1
  9. package/dist/actions/index.mjs +9 -7
  10. package/dist/actions/triggers.d.ts +4 -0
  11. package/dist/actions/triggers.mjs +4 -1
  12. package/dist/auth/index.d.ts +2 -0
  13. package/dist/auth/index.mjs +2 -1
  14. package/dist/auth/visitorRoles.d.ts +27 -0
  15. package/dist/auth/visitorRoles.mjs +48 -0
  16. package/dist/authoring/builder.mjs +1 -0
  17. package/dist/authoring/declare.d.ts +74 -0
  18. package/dist/authoring/declare.mjs +2 -2
  19. package/dist/authoring/index.mjs +5 -5
  20. package/dist/authoring/paramSpec.d.ts +1 -1
  21. package/dist/authoring/paramSpec.mjs +1 -0
  22. package/dist/authoring/spaceCallbacks.mjs +2 -2
  23. package/dist/dataSource/computed.d.ts +21 -0
  24. package/dist/dataSource/computed.mjs +45 -0
  25. package/dist/dataSource/getBindingsDetails.mjs +35 -33
  26. package/dist/dataSource/index.d.ts +1 -0
  27. package/dist/dataSource/index.mjs +7 -6
  28. package/dist/dataSource/utility/checkboxParams.d.ts +11 -0
  29. package/dist/dataSource/utility/checkboxParams.mjs +12 -0
  30. package/dist/dataSource/utility/not.mjs +4 -7
  31. package/dist/dataSource/utility/stringToArray.mjs +1 -1
  32. package/dist/dataSource/utility/truthiness.d.ts +1 -0
  33. package/dist/dataSource/utility/truthiness.mjs +8 -0
  34. package/dist/dataSource/utility/twigTemplate.d.ts +2 -1
  35. package/dist/dataSource/utility/twigTemplate.mjs +29 -17
  36. package/dist/devTools/utils/PlitziConsole.mjs +22 -22
  37. package/dist/helpers/cookies.d.ts +10 -0
  38. package/dist/helpers/cookies.mjs +19 -0
  39. package/dist/helpers/fetchManifest.d.ts +9 -0
  40. package/dist/helpers/fetchManifest.mjs +3 -6
  41. package/dist/helpers/formatDate.d.ts +5 -3
  42. package/dist/helpers/formatDate.mjs +34 -36
  43. package/dist/helpers/index.d.ts +2 -0
  44. package/dist/helpers/index.mjs +18 -13
  45. package/dist/helpers/isDate.d.ts +7 -0
  46. package/dist/helpers/isDate.mjs +15 -0
  47. package/dist/helpers/keys.d.ts +42 -0
  48. package/dist/helpers/keys.mjs +91 -0
  49. package/dist/helpers/twigWrapper/AST.d.ts +2 -2
  50. package/dist/helpers/twigWrapper/Evaluator/Evaluator.d.ts +12 -2
  51. package/dist/helpers/twigWrapper/Evaluator/Evaluator.mjs +69 -31
  52. package/dist/helpers/twigWrapper/Evaluator/index.d.ts +1 -1
  53. package/dist/helpers/twigWrapper/Evaluator/index.mjs +2 -2
  54. package/dist/helpers/twigWrapper/Parser/ExpressionParser.d.ts +2 -2
  55. package/dist/helpers/twigWrapper/Parser/ExpressionParser.mjs +147 -34
  56. package/dist/helpers/twigWrapper/Parser/Parser.d.ts +2 -1
  57. package/dist/helpers/twigWrapper/Parser/Parser.mjs +21 -20
  58. package/dist/helpers/twigWrapper/filters/filters.mjs +134 -111
  59. package/dist/helpers/twigWrapper/index.d.ts +6 -2
  60. package/dist/helpers/twigWrapper/index.mjs +7 -4
  61. package/dist/helpers/twigWrapper/inspectTemplate.d.ts +23 -0
  62. package/dist/helpers/twigWrapper/inspectTemplate.mjs +110 -0
  63. package/dist/helpers/twigWrapper/processTwig/helpers.d.ts +7 -0
  64. package/dist/helpers/twigWrapper/processTwig/helpers.mjs +2 -1
  65. package/dist/helpers/twigWrapper/processTwig/index.d.ts +2 -1
  66. package/dist/helpers/twigWrapper/processTwig/index.mjs +3 -2
  67. package/dist/helpers/twigWrapper/processTwig/processTwig.d.ts +28 -0
  68. package/dist/helpers/twigWrapper/processTwig/processTwig.mjs +73 -16
  69. package/dist/helpers/twigWrapper/processTwig/resolveStepParam.d.ts +17 -0
  70. package/dist/helpers/twigWrapper/processTwig/resolveStepParam.mjs +14 -0
  71. package/dist/helpers/twigWrapper/templateRoots.d.ts +11 -0
  72. package/dist/helpers/twigWrapper/templateRoots.mjs +4 -4
  73. package/dist/helpers/twigWrapper/tokens/hasTemplateSyntax.d.ts +9 -0
  74. package/dist/helpers/twigWrapper/tokens/hasTemplateSyntax.mjs +4 -0
  75. package/dist/history/describe.d.ts +29 -0
  76. package/dist/history/describe.mjs +93 -0
  77. package/dist/history/diff.d.ts +33 -0
  78. package/dist/history/diff.mjs +73 -0
  79. package/dist/history/index.d.ts +3 -0
  80. package/dist/history/index.mjs +3 -0
  81. package/dist/history/types.d.ts +48 -0
  82. package/dist/history/types.mjs +0 -0
  83. package/dist/hooks/usePlitziServiceContext.d.ts +1 -1
  84. package/dist/index.d.ts +1 -0
  85. package/dist/index.mjs +77 -65
  86. package/dist/navigation/index.d.ts +1 -1
  87. package/dist/navigation/index.mjs +2 -2
  88. package/dist/navigation/routes.d.ts +11 -1
  89. package/dist/navigation/routes.mjs +35 -30
  90. package/dist/network/graphql/builder/Mutations/Space/SpaceFixIssuesMutation.d.ts +14 -0
  91. package/dist/network/graphql/builder/Mutations/Space/SpaceFixIssuesMutation.mjs +16 -0
  92. package/dist/network/graphql/builder/Mutations/Space/SpaceUpdatePluginMutation.d.ts +4 -0
  93. package/dist/network/graphql/builder/Mutations/Space/SpaceUpdatePluginMutation.mjs +2 -2
  94. package/dist/network/graphql/builder/Mutations/Space/actions/SpaceRunActionMutation.mjs +1 -0
  95. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceRemoveFunctionsMutation.d.ts +3 -0
  96. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceRemoveFunctionsMutation.mjs +9 -0
  97. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceSaveFunctionsMutation.d.ts +11 -0
  98. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceSaveFunctionsMutation.mjs +24 -0
  99. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceTryFunctionMutation.d.ts +4 -0
  100. package/dist/network/graphql/builder/Mutations/Space/functions/SpaceTryFunctionMutation.mjs +15 -0
  101. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceRemoveRuntimeMutation.d.ts +2 -0
  102. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceRemoveRuntimeMutation.mjs +9 -0
  103. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceRemoveRuntimeVariableMutation.d.ts +2 -0
  104. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceRemoveRuntimeVariableMutation.mjs +9 -0
  105. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceSetRuntimeSizeMutation.d.ts +2 -0
  106. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceSetRuntimeSizeMutation.mjs +9 -0
  107. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceSetRuntimeVariableMutation.d.ts +2 -0
  108. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceSetRuntimeVariableMutation.mjs +9 -0
  109. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceStartRuntimeMutation.d.ts +2 -0
  110. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceStartRuntimeMutation.mjs +9 -0
  111. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceStopRuntimeMutation.d.ts +2 -0
  112. package/dist/network/graphql/builder/Mutations/Space/runtime/SpaceStopRuntimeMutation.mjs +9 -0
  113. package/dist/network/graphql/builder/Mutations/Space/visitors/SpaceAddVisitorMutation.d.ts +2 -0
  114. package/dist/network/graphql/builder/Mutations/Space/visitors/SpaceAddVisitorMutation.mjs +11 -0
  115. package/dist/network/graphql/builder/Mutations/Space/visitors/SpaceRemoveVisitorMutation.d.ts +2 -0
  116. package/dist/network/graphql/builder/Mutations/Space/visitors/SpaceRemoveVisitorMutation.mjs +11 -0
  117. package/dist/network/graphql/builder/Mutations/index.d.ts +28 -0
  118. package/dist/network/graphql/builder/Mutations/index.mjs +108 -84
  119. package/dist/network/graphql/builder/Queries/Space/SpaceChangesQuery.d.ts +23 -0
  120. package/dist/network/graphql/builder/Queries/Space/SpaceChangesQuery.mjs +49 -0
  121. package/dist/network/graphql/builder/Queries/Space/SpaceFunctionsQuery.d.ts +6 -0
  122. package/dist/network/graphql/builder/Queries/Space/SpaceFunctionsQuery.mjs +13 -0
  123. package/dist/network/graphql/builder/Queries/Space/SpaceIssuesQuery.d.ts +17 -0
  124. package/dist/network/graphql/builder/Queries/Space/SpaceIssuesQuery.mjs +22 -0
  125. package/dist/network/graphql/builder/Queries/Space/SpaceRuntimeQuery.d.ts +6 -0
  126. package/dist/network/graphql/builder/Queries/Space/SpaceRuntimeQuery.mjs +32 -0
  127. package/dist/network/graphql/builder/Queries/Space/SpaceVisitorsQuery.d.ts +6 -0
  128. package/dist/network/graphql/builder/Queries/Space/SpaceVisitorsQuery.mjs +16 -0
  129. package/dist/network/graphql/builder/Queries/index.d.ts +17 -3
  130. package/dist/network/graphql/builder/Queries/index.mjs +30 -22
  131. package/dist/network/graphql/sdk/Mutations/index.d.ts +1 -1
  132. package/dist/network/graphql/sdk/Queries/InitQuery.d.ts +1 -1
  133. package/dist/network/graphql/sdk/Queries/InitQuery.mjs +2 -91
  134. package/dist/network/graphql/sdk/Queries/Segment/SegmentQuery.d.ts +1 -1
  135. package/dist/network/graphql/sdk/Queries/Segment/SegmentQuery.mjs +2 -44
  136. package/dist/network/graphql/sdk/Queries/Segment/SegmentsQuery.d.ts +1 -1
  137. package/dist/network/graphql/sdk/Queries/Segment/SegmentsQuery.mjs +2 -55
  138. package/dist/network/graphql/sdk/Queries/index.d.ts +1 -5
  139. package/dist/network/index.mjs +7 -7
  140. package/dist/network/spaceEvents.d.ts +33 -3
  141. package/dist/network/spaceEvents.mjs +102 -89
  142. package/dist/realtime/client.d.ts +46 -0
  143. package/dist/realtime/client.mjs +192 -0
  144. package/dist/realtime/index.d.ts +6 -0
  145. package/dist/realtime/index.mjs +4 -0
  146. package/dist/realtime/presence.d.ts +38 -0
  147. package/dist/realtime/presence.mjs +70 -0
  148. package/dist/realtime/topics.d.ts +36 -0
  149. package/dist/realtime/topics.mjs +25 -0
  150. package/dist/schema/serverElements.d.ts +5 -0
  151. package/dist/schema/serverElements.mjs +15 -14
  152. package/dist/server/actions/useRealtimeSync.d.ts +9 -0
  153. package/dist/server/actions/useRealtimeSync.mjs +7 -0
  154. package/dist/state/index.d.ts +1 -0
  155. package/dist/state/index.mjs +3 -2
  156. package/dist/state/paintedState.d.ts +52 -0
  157. package/dist/state/paintedState.mjs +37 -0
  158. package/dist/state/runtimeStatePersist.d.ts +24 -0
  159. package/dist/state/runtimeStatePersist.mjs +113 -10
  160. package/dist/store/index.d.ts +45 -45
  161. package/dist/store/renderSettings.d.ts +6 -3
  162. package/dist/store/tracing/index.d.ts +1 -0
  163. package/dist/store/tracing/tracingCollector.d.ts +17 -1
  164. package/dist/store/tracing/tracingCollector.mjs +5 -0
  165. package/dist/style/index.d.ts +1 -0
  166. package/dist/style/index.mjs +3 -2
  167. package/dist/style/runtimeStyle.d.ts +29 -0
  168. package/dist/style/runtimeStyle.mjs +7 -0
  169. package/dist/style/styleConstants.d.ts +3 -2
  170. package/dist/style/styleConstants.mjs +2 -0
  171. package/dist/style/styleStates.d.ts +14 -1
  172. package/dist/style/styleStates.mjs +10 -7
  173. package/dist/theme/ThemeProvider.d.ts +1 -1
  174. package/dist/theme/ThemeProvider.mjs +35 -29
  175. package/dist/theme/themeCookie.mjs +11 -15
  176. package/dist/types/ActionTypes.d.ts +193 -0
  177. package/dist/types/AuthTypes.d.ts +11 -1
  178. package/dist/types/CommonTypes.d.ts +6 -0
  179. package/dist/types/FunctionTypes.d.ts +52 -0
  180. package/dist/types/FunctionTypes.mjs +0 -0
  181. package/dist/types/PluginTypes.d.ts +0 -1
  182. package/dist/types/RealtimeTypes.d.ts +94 -0
  183. package/dist/types/RealtimeTypes.mjs +0 -0
  184. package/dist/types/SchemaTypes.d.ts +54 -0
  185. package/dist/types/SchemaTypes.mjs +8 -0
  186. package/dist/types/ServerTypes.d.ts +310 -15
  187. package/dist/types/SpaceTypes.d.ts +53 -0
  188. package/dist/types/StateTypes.d.ts +6 -0
  189. package/dist/types/StoreTypes.d.ts +12 -1
  190. package/dist/types/index.d.ts +2 -0
  191. package/dist/types/index.mjs +3 -2
  192. package/package.json +190 -21
  193. package/vite.config.ts +0 -12
  194. package/dist/network/graphql/builder/Queries/PluginsQuery.d.ts +0 -9
  195. package/dist/network/graphql/builder/Queries/PluginsQuery.mjs +0 -54
@@ -1,9 +1,12 @@
1
- import { ActionEmailConfig, ActionEntry, ActionLimits, ActionRejectReason, ActionRunSummary, ActionRejectRecord, ActionRunRecord, ActionRunStatus, ActionTaskDescriptor, ActionTriggerType } from './ActionTypes';
1
+ import { ActionEmailConfig, ActionEntry, ActionJobQueue, ActionLimits, ActionRejectReason, ActionRunSummary, ActionRejectRecord, ActionRunRecord, ActionRunReport, ActionRunStatus, ActionTaskDescriptor, ActionTriggerType } from './ActionTypes';
2
2
  import { Environment } from './CommonTypes';
3
3
  import { ConnectorEntry } from './ConnectorTypes';
4
+ import { FunctionsDraft, FunctionsSaveResult } from './FunctionTypes';
5
+ import { SSRRealtimeConfig } from './RealtimeTypes';
4
6
  import { Schema } from './SchemaTypes';
5
7
  import { AnalyticsConfig, OfflineDataRaw } from './SdkTypes';
6
8
  import { FontHead, Style } from './StyleTypes';
9
+ import { SpaceChange } from '../history/types';
7
10
  import { IncomingHttpHeaders } from 'node:http';
8
11
  import { FC } from 'react';
9
12
  export type ServerEnvironment = 'development' | 'production' | 'staging' | 'local';
@@ -24,8 +27,15 @@ export type SSRRequest = {
24
27
  query: Record<string, string>;
25
28
  /** Raw request body. Populated only for endpoints that consume it (e.g. the login/logout handlers). */
26
29
  body?: string;
30
+ /**
31
+ * The client's address, when the host resolved one — through the proxies it sits behind. Forgeable by a direct
32
+ * client like every forwarded header, so it names things (a session in a device list) and never decides anything.
33
+ */
34
+ ip?: string;
27
35
  ctx: SSRContext;
28
36
  };
37
+ /** A body's compressed forms, by content encoding — filled as they are first asked for. */
38
+ export type CompressedBodies = Partial<Record<'br' | 'gzip', Buffer>>;
29
39
  export type SSRResponseHelpers = {
30
40
  status: number;
31
41
  /** Multi-valued for the headers that genuinely are, `Set-Cookie` above all — see `setHeader`. */
@@ -37,8 +47,18 @@ export type SSRResponseHelpers = {
37
47
  /**
38
48
  * A `Buffer` is sent byte for byte and never compressed: it is how a binary reaches the wire — a font file, an
39
49
  * image — and what it holds is usually compressed already. A string keeps the encoding negotiation.
50
+ *
51
+ * `compressed` is where this body's compressed forms are kept, for a body that is sent again unchanged — a cached
52
+ * page, a static file. The first send of each encoding compresses and stores it; every later one sends the stored
53
+ * bytes. Without it a cache hit recompressed the same page on every request, which was nearly all the CPU a cached
54
+ * page cost.
55
+ *
56
+ * A function is a body read only when it is needed: when the stored form for this request's encoding is missing, or
57
+ * the client takes no compression. A static file is then read from disk once per encoding, not on every request.
40
58
  */
41
- send: (body: string | Buffer) => void;
59
+ send: (body: string | Buffer | (() => string), options?: {
60
+ compressed?: CompressedBodies;
61
+ }) => void;
42
62
  write: (chunk: string | Buffer) => void;
43
63
  end: () => void;
44
64
  };
@@ -170,6 +190,23 @@ export type SSRGrant = {
170
190
  userId?: number;
171
191
  canWrite: boolean;
172
192
  };
193
+ /** A page of a space's change history, newest first; `nextBefore` reads further back, null at the end. */
194
+ export type SSRChangePage = {
195
+ changes: SpaceChange[];
196
+ nextBefore: number | null;
197
+ };
198
+ /** What to read of the history: older than `before`, only the changes that touched `entityId`, `limit` at a time. */
199
+ export type SSRChangeQuery = {
200
+ before?: number;
201
+ entityId?: string;
202
+ limit: number;
203
+ };
204
+ /** Who a write is made for and which request made it, for a consumer that records its changes. Every document one
205
+ * request writes shares its `batch`: one `plitzi_apply`, read back as one change. */
206
+ export type SSRWriteContext = {
207
+ userId?: number;
208
+ batch: string;
209
+ };
173
210
  /**
174
211
  * A session, as the thing that issued it describes it. Deliberately free of transport: whoever mints one says what
175
212
  * the credentials are and when they die, and the server decides how they are carried — which is what lets a
@@ -325,13 +362,25 @@ export type SSRAdapters = {
325
362
  saveAction?: (spaceId: number, entry: ActionEntry) => Promise<void>;
326
363
  /** Remove one action by its identifier. Omitted alongside `saveAction` for a read-only deployment. */
327
364
  deleteAction?: (spaceId: number, actionId: string) => Promise<void>;
365
+ /** The space's own functions: the draft's source files, which copy of them it is and what they declare.
366
+ * Server-side code like the actions it serves — never a browser payload. When omitted, the MCP offers no functions
367
+ * resource and refuses the function ops. */
368
+ getFunctions?: (spaceId: number) => Promise<FunctionsDraft | undefined>;
369
+ /** Save the draft's functions, whole. The deployment builds and checks them and answers what is wrong where it is;
370
+ * `base` is the version the agent read, and a draft that moved on since is refused rather than overwritten. */
371
+ saveFunctions?: (spaceId: number, files: Record<string, string>, base: string, write: SSRWriteContext) => Promise<FunctionsSaveResult>;
372
+ /** Run one task of the draft's functions in the sandbox for the person behind the agent — the builder's Try. */
373
+ tryFunction?: (spaceId: number, task: string, params: Record<string, unknown>, write: SSRWriteContext) => Promise<ActionRunReport>;
328
374
  /** Persist the element schema mutated by the MCP `apply` tool. When omitted, `apply` reports `persisted: false`. */
329
- saveSchema?: (spaceId: number, environment: Environment, schema: Schema) => Promise<void>;
375
+ saveSchema?: (spaceId: number, environment: Environment, schema: Schema, write: SSRWriteContext) => Promise<void>;
330
376
  /** Persist the style document mutated by the MCP `apply` tool — store it as given. `style.cache` arrives already
331
377
  * compiled: the renderer serves that string and nothing else, so recomputing it is not a detail to delegate, and
332
378
  * asking every deployment to remember it was one bug each of them could write alone. When omitted, `apply`
333
379
  * reports `persisted: false`. */
334
- saveStyle?: (spaceId: number, environment: Environment, style: Style) => Promise<void>;
380
+ saveStyle?: (spaceId: number, environment: Environment, style: Style, write: SSRWriteContext) => Promise<void>;
381
+ /** The space's change history, read-only: what every writer saved, and for whom. When omitted, the MCP offers no
382
+ * history resource. */
383
+ getChanges?: (spaceId: number, environment: Environment, query: SSRChangeQuery) => Promise<SSRChangePage>;
335
384
  /** Who this request carries, if anyone. The adapter reads the credential and resolves it; the cookie it arrived
336
385
  * in was written by the server, from {@link SSRAuthCookie}. */
337
386
  getUser?: (req: SSRRequest) => Promise<SSRUser | undefined>;
@@ -465,8 +514,12 @@ export type SpaceRevision = {
465
514
  export type ActionLookupsConfig = {
466
515
  getAction: (spaceId: number, actionId: string, at?: SpaceRevision) => Promise<unknown>;
467
516
  listActions?: (spaceId: number, at?: SpaceRevision) => Promise<unknown[]>;
517
+ /** Which spaces have something scheduled — the periodic reconcile's safety net. See `ActionLookups`. */
518
+ listScheduledSpaces?: () => Promise<number[]>;
468
519
  getCredential?: (spaceId: number, identifier: string) => Promise<Record<string, string> | undefined>;
469
520
  getConnector?: (spaceId: number, connectorId: string, at?: SpaceRevision) => Promise<unknown>;
521
+ /** The space's own functions as of that revision — `SpaceFunctions` in `@plitzi/sdk-server/functions`. */
522
+ getFunctions?: (spaceId: number, at?: SpaceRevision) => Promise<unknown>;
470
523
  };
471
524
  export type SSRActionConfig = {
472
525
  /** URL path for the write endpoint, and the base for the action-addressed routes. Defaults to '/_action'. */
@@ -476,8 +529,6 @@ export type SSRActionConfig = {
476
529
  * the endpoint keeps answering element-addressed connector writes alone.
477
530
  */
478
531
  lookups?: ActionLookupsConfig;
479
- /** Deployment-owned tasks, shaped as `ActionTask` in `@plitzi/sdk-server/actions`. Validated at boot. */
480
- tasks?: unknown[];
481
532
  /** Ceilings for every run this server accepts. A document may tighten them, never widen them. */
482
533
  limits?: ActionLimits;
483
534
  /**
@@ -537,10 +588,15 @@ export type SSRActionConfig = {
537
588
  idempotency?: {
538
589
  replayTtlMs?: number;
539
590
  };
591
+ /**
592
+ * What each space's functions sign with (`ctx.sign` / `ctx.verify`): at least 32 characters, the same on every
593
+ * replica. Each space and environment signs with a key derived from it. Absent, spaces sign nothing.
594
+ */
595
+ signingSecret?: string;
540
596
  /**
541
597
  * Where the `kv` tasks keep things — shaped as `ActionKvAdapter` in `@plitzi/sdk-server/actions`.
542
598
  *
543
- * Five operations over strings, with no rule to obey: Redis, Memcached, a table, whatever this deployment
599
+ * Six operations over strings, with no rule to obey: Redis, Memcached, a table, whatever this deployment
544
600
  * already runs. How a counter BEHAVES — the key prefixing, the JSON round trip, and the rule that a window's
545
601
  * lifetime is set once by whoever created it — belongs to the server, not to the thing it writes into.
546
602
  *
@@ -553,7 +609,58 @@ export type SSRActionConfig = {
553
609
  delete: (key: string) => Promise<void>;
554
610
  increment: (key: string, amount: number) => Promise<number>;
555
611
  expire: (key: string, ttlSeconds: number) => Promise<void>;
612
+ /** Writes `next` only if the key holds `expected` (nothing, when undefined); answers whether it wrote. Atomic. */
613
+ swap: (key: string, expected: string | undefined, next: string, ttlSeconds?: number) => Promise<boolean>;
614
+ };
615
+ /**
616
+ * Scheduled runs: the durable queue they wait in, how many this replica runs at once, and whether it produces.
617
+ *
618
+ * On wherever `lookups.listActions` is answerable — a `schedule` trigger the editor offers is a trigger the
619
+ * server honours, which before this it only did if the deployment wrote a timer and a distributed lock of its
620
+ * own. With no `queue` it runs over this process's memory: right for one replica, and wrong for two, because
621
+ * each then keeps its own schedules and the nightly email goes out once per replica.
622
+ *
623
+ * `false` turns it off for a replica that must only serve pages.
624
+ */
625
+ jobs?: SSRActionJobsConfig | false;
626
+ };
627
+ /**
628
+ * How this deployment runs what a clock starts.
629
+ *
630
+ * Every default here is a safe one for a single machine; the two a cluster has to think about are `queue` — which
631
+ * must be shared, or the replicas do not see each other's work — and `workers`, which is how fast a backlog
632
+ * drains. Nothing in this config is a clock: the queue's own is the only one the scheduling path reads, so
633
+ * replicas in different countries agree about what has run without agreeing about what time it is.
634
+ */
635
+ export type SSRActionJobsConfig = {
636
+ /** Shaped as `ActionJobQueue`. Omitted → this process's memory. */
637
+ queue?: ActionJobQueue;
638
+ /** Jobs this replica runs at once. Default 4; `0` produces without consuming. */
639
+ workers?: number;
640
+ /** Whether this replica sweeps due schedules into the queue. Default true. */
641
+ produce?: boolean;
642
+ /** The spaces this server schedules for, when it serves a known few — the self-hosted shape. */
643
+ spaces?: number[];
644
+ /** How often a free worker looks for a job. Default 1s. */
645
+ pollMs?: number;
646
+ /** How often this replica looks for due schedules. Default 15s. */
647
+ schedulePollMs?: number;
648
+ /** How long a claim is held before another replica may take the job over — the failover window. Default 30s. */
649
+ leaseMs?: number;
650
+ /** Attempts a job gets before it is left for an operator as `dead`. Default 3. */
651
+ maxAttempts?: number;
652
+ /** First retry delay, doubling per attempt, up to `maxMs`. Defaults to 30s and 15 minutes. */
653
+ backoff?: {
654
+ baseMs?: number;
655
+ maxMs?: number;
556
656
  };
657
+ /** Which environment scheduled runs execute in. Default `main`. */
658
+ environment?: Environment;
659
+ /** How often schedules are re-derived from documents. Default 15 minutes. */
660
+ reconcileMs?: number;
661
+ /** Names this replica in the job history. Defaults to the pid and a random suffix. */
662
+ workerId?: string;
663
+ onError?: (error: unknown) => void;
557
664
  };
558
665
  /**
559
666
  * How the server reaches a space's connectors: the manifest that describes one, and the credential it authenticates
@@ -599,8 +706,18 @@ export type SSRCompressionConfig = {
599
706
  encodings?: ('br' | 'gzip')[];
600
707
  /** Responses smaller than this many bytes go out uncompressed. Default 1024. */
601
708
  threshold?: number;
602
- /** Brotli quality, 0–11. Default 4 — past that the CPU cost outgrows the bytes saved on HTML. */
709
+ /**
710
+ * Brotli quality, 0–11, for a body compressed on every request — a page rendered for this request alone. Default 2:
711
+ * measured on a quarter core, going to 4 cost a tenth of the pages a second to save half a kilobyte on each.
712
+ */
603
713
  brotliQuality?: number;
714
+ /**
715
+ * Brotli quality, 0–11, for a body compressed once and kept — a cached page, a static file such as the SDK bundle.
716
+ * Default 6: paid once, and every later response is that much smaller (the SDK bundle 10% under quality 4), for
717
+ * the same memory as 4. 9 needs ~40 MB more to compress the bundle, which a 128 MB server does not have; 10 and
718
+ * 11 cost seconds, which the request that fills the cache would wait for.
719
+ */
720
+ keptBrotliQuality?: number;
604
721
  /** Gzip level, 0–9. Default 6. */
605
722
  gzipLevel?: number;
606
723
  };
@@ -625,6 +742,12 @@ export type SSRRscConfig = {
625
742
  elementTimeoutMs?: number;
626
743
  };
627
744
  /** What every log event carries, whatever layer it came from. */
745
+ /**
746
+ * How much a server says, from least to most: each level includes every one above it. `error` is what a production
747
+ * server shows unless told otherwise — something went wrong — and `warn`, `info` (every request answered, every
748
+ * plugin built) and `debug` are asked for. `silent` says nothing at all.
749
+ */
750
+ export type LogLevel = 'error' | 'warn' | 'info' | 'debug';
628
751
  type ServerLogEventBase = {
629
752
  /** Wall-clock duration of the work the event describes, in milliseconds. */
630
753
  durationMs: number;
@@ -720,7 +843,18 @@ export type ActionRejectLogEvent = ServerLogEventBase & {
720
843
  * are stripped from paths, tool arguments are reduced to their shape and a run to its steps. Two fields are NOT
721
844
  * anonymous and a consumer shipping these events must handle them accordingly: `clientIp` on a request event, and
722
845
  * the request path, which is kept verbatim because it is what makes the log usable. */
723
- export type ServerLogEvent = ServerRequestLogEvent | McpToolLogEvent | McpResourceLogEvent | ActionRunLogEvent | ActionRejectLogEvent;
846
+ /** Anything else the server has to say — a plugin rebuilt, a manifest that would not load — at its own level. */
847
+ export type ServerMessageLogEvent = {
848
+ kind: 'message';
849
+ level: LogLevel;
850
+ /** What is speaking: `SSR`, `RSC`, `Actions`, `auth`… — what a line used to start with in brackets. */
851
+ scope: string;
852
+ message: string;
853
+ ok: boolean;
854
+ error?: string;
855
+ timestamp: string;
856
+ };
857
+ export type ServerLogEvent = ServerRequestLogEvent | McpToolLogEvent | McpResourceLogEvent | ActionRunLogEvent | ActionRejectLogEvent | ServerMessageLogEvent;
724
858
  /** The sink a consumer provides to receive every {@link ServerLogEvent} (see `SSRServerConfig.logger`). */
725
859
  export type ServerLogger = (event: ServerLogEvent) => void;
726
860
  export type SSRServerConfig = {
@@ -749,6 +883,11 @@ export type SSRServerConfig = {
749
883
  /** Where a browser-obtained credential is handed over. Defaults to `/auth/exchange`; served only when the
750
884
  * `exchangeCredential` adapter is supplied. */
751
885
  exchangePath?: string | false;
886
+ /**
887
+ * Signing visitors in by redirect, through an OAuth 2.1 authorization server — see {@link SSRSignInConfig}. Served
888
+ * only with the `exchangeCredential` adapter, which is what turns what comes back into a session on this host.
889
+ */
890
+ signIn?: SSRSignInConfig;
752
891
  /** Naming and scope of the session cookies this server writes. See {@link SSRAuthCookie}. */
753
892
  authCookie?: SSRAuthCookie;
754
893
  templateFn?: SSRTemplateFn;
@@ -757,6 +896,13 @@ export type SSRServerConfig = {
757
896
  pluginsTtlMs?: number;
758
897
  /** Auto-download and cache plugins declared in the schema's offlineData.plugins list. Default: true. */
759
898
  autoLoadSchemaPlugins?: boolean;
899
+ /**
900
+ * Whether a schema plugin may be read from a private address — `localhost`, the network this server runs in. A
901
+ * plugin's address is typed by whoever edits a space and read from inside this server, so it answers to the rule
902
+ * every authored request does and is refused there; turn this on only on a development machine whose bucket is on
903
+ * localhost. Default: false.
904
+ */
905
+ allowPrivatePluginHosts?: boolean;
760
906
  /** Where this deployment serves the font files a space uploaded — see {@link SSRFontsConfig}. */
761
907
  fonts?: SSRFontsConfig;
762
908
  /** Omit client-side JS from the rendered page — useful for verifying SSR HTML without hydration. Default: false. */
@@ -773,13 +919,34 @@ export type SSRServerConfig = {
773
919
  rsc?: SSRRscConfig;
774
920
  /** Write endpoint for server-driven providers. Absent means the server serves reads only. */
775
921
  action?: SSRActionConfig;
922
+ /**
923
+ * Code of this server's own, and the sandbox for the spaces' — shaped as `FunctionsConfig` in
924
+ * `@plitzi/sdk-server/functions`. `native` is trusted code loaded in the process (a self-hosted server's tasks, or a
925
+ * platform's own); `runner` runs each space's functions, isolated.
926
+ */
927
+ functions?: {
928
+ native?: unknown[];
929
+ runner?: unknown;
930
+ limits?: Record<string, number>;
931
+ };
932
+ /** Realtime channels the spaces declare — see {@link SSRRealtimeConfig}. On, in memory, when absent. */
933
+ realtime?: SSRRealtimeConfig;
776
934
  /** Connector manifest and credential lookups — see {@link ConnectorLookupsConfig}. They serve the RSC read path
777
935
  * and the `/_action` write endpoint alike; without them neither can reach a connector. */
778
936
  connectors?: ConnectorLookupsConfig;
779
937
  /** Receives a {@link ServerLogEvent} for every HTTP request this server answers — whatever stage answered it
780
938
  * and whatever the outcome — plus every MCP tool call and resource read inside those requests. Without it the
781
- * server reports nothing per request (the MCP events still reach the console when `MCP_DEBUG=1`). */
939
+ * server reports nothing per request (the MCP events still reach the console when `MCP_DEBUG=1`). Everything
940
+ * else the server has to say — a failure, a plugin rebuilt — comes here too as a `message` event, and goes to the
941
+ * console when there is no logger. */
782
942
  logger?: ServerLogger;
943
+ /**
944
+ * The least severe thing worth saying — see {@link LogLevel}. `error` by default, `info` with `devMode`: a server
945
+ * in production reports what went wrong and nothing else, unless asked. A request that was answered is `info`, one
946
+ * that failed `error`; a refused action is `warn`. Below the level nothing is built, so a quiet server pays nothing
947
+ * per request for the log it is not keeping.
948
+ */
949
+ logLevel?: LogLevel | 'silent';
783
950
  /**
784
951
  * How responses are compressed. Omit for Brotli where the client takes it and gzip otherwise; `false` never
785
952
  * compresses, which is what to use when a proxy or CDN in front already does it.
@@ -798,6 +965,32 @@ export type SSRServerConfig = {
798
965
  host: string;
799
966
  label: string;
800
967
  }) => void;
968
+ /**
969
+ * How many processes serve this port. Node runs JavaScript on one thread, so one process renders on one core however
970
+ * many the machine has; each worker is a whole server of its own, and the connections are spread between them —
971
+ * more requests a second, and less time waiting behind another render.
972
+ *
973
+ * `true` / `'auto'`: one per core the process may actually use (a container's CPU quota included). `false`: one
974
+ * process. A number: that many, lowered to the cores there are (more only take turns on the same cores). Default: on
975
+ * under `NODE_ENV=production`, off otherwise — a development server and a test runner stay one process. The
976
+ * `SDK_SERVER_WORKERS` environment variable sets it when this does not.
977
+ *
978
+ * The workers are one server — one replica — and behave as one:
979
+ *
980
+ * - The stores kept in memory by default (an action's `kv`, the job queue, draft previews, the sign-in rate
981
+ * limit) are the primary's, and each worker reaches them over the cluster channel. A store the deployment
982
+ * supplies (Redis, a table) is used as it is.
983
+ * - The scheduler and the job consumers run in one worker only, so a schedule fires once and `jobs.workers` is the
984
+ * whole server's concurrency; if that worker dies, its replacement takes them over.
985
+ * - `server.cache.invalidate()`, `server.plugins.register()` and `server.plugins.invalidate()` reach every worker,
986
+ * whichever process calls them.
987
+ *
988
+ * Per worker: the rendered-page cache (each renders a page once), the plugin components, and the action run caps
989
+ * (`action.concurrency`: `perSpace`, `perProcess`, `renderPerProcess`), which a cluster of replicas already counts
990
+ * per replica. A plugin registered with a `component` stays in the process that registered it — register those
991
+ * where the server is created.
992
+ */
993
+ workers?: boolean | number | 'auto';
801
994
  adapters: SSRAdapters;
802
995
  /** Which request-handling services this server mounts: `ssr` on by default, `rsc` whenever
803
996
  * `adapters.getRscData` exists. Stages a companion package contributes are deliberately NOT flags here —
@@ -824,6 +1017,28 @@ export type SSRServerConfig = {
824
1017
  * `createServer` from `@plitzi/sdk-server` takes and what the SSR stages are handed, so a page stage reaches
825
1018
  * `getOfflineData` without asking whether it is there — while a stage typed to the bare context (anything from
826
1019
  * `@plitzi/sdk-mcp`, which also runs in servers that have neither) still has to check. */
1020
+ /**
1021
+ * A visitor signs in somewhere else and comes back signed in HERE: `GET <path>?return=/somewhere` sends them to the
1022
+ * authorization server, and `GET <path>/callback` takes the code it answers with, redeems it server to server and
1023
+ * hands the token to `exchangeCredential` — which is what makes the session, on this host, for this space.
1024
+ *
1025
+ * This server registers itself with the authorization server (RFC 7591) as the host the visitor is on, and proves the
1026
+ * exchange with PKCE. The state travels in a `__Host-` cookie, which no sibling host can set: a sign-in somebody else
1027
+ * started cannot be finished in this browser.
1028
+ */
1029
+ export type SSRSignInConfig = {
1030
+ /** What `exchangeCredential` knows the tokens by. */
1031
+ provider: string;
1032
+ /** Where the visitor's browser is sent: the authorization server's `/authorize`, as the public reaches it. */
1033
+ authorizeUrl: string;
1034
+ /** Where this server registers itself and redeems codes — reachable from here, which may be a private address. */
1035
+ registerUrl: string;
1036
+ tokenUrl: string;
1037
+ /** What to ask for, for the space being signed into. */
1038
+ scope: (spaceId: number) => string;
1039
+ /** Where the flow answers. Default `/auth/sign-in`; the authorization server sends people back to `<path>/callback`. */
1040
+ path?: string;
1041
+ };
827
1042
  export type SSRPageServerConfig = SSRServerConfig & {
828
1043
  adapters: SSRPageAdapters;
829
1044
  };
@@ -910,8 +1125,15 @@ export type OAuthAdapters = {
910
1125
  * first visit.
911
1126
  */
912
1127
  identify: (req: SSRRequest) => Promise<OAuthUser | undefined>;
913
- /** What this user may grant access to. An empty list ends the flow with `access_denied`. */
914
- grantTargets: (user: OAuthUser) => Promise<OAuthGrantTarget[]>;
1128
+ /**
1129
+ * What this user may grant access to. An empty list ends the flow with `access_denied`.
1130
+ *
1131
+ * `request.scope` is what the client asked for, so one deployment can offer different choices to different
1132
+ * clients — a native client signing in as the person, and the same client asking which space to work in.
1133
+ */
1134
+ grantTargets: (user: OAuthUser, request: {
1135
+ scope?: string;
1136
+ }) => Promise<OAuthGrantTarget[]>;
915
1137
  /**
916
1138
  * End whatever session {@link OAuthAdapters.identify} was reading, so the person can connect as somebody else.
917
1139
  *
@@ -923,13 +1145,53 @@ export type OAuthAdapters = {
923
1145
  * that does not mean abandoning the connection and starting over from the host.
924
1146
  */
925
1147
  signOut?: (req: SSRRequest, res: SSRResponseHelpers) => void | Promise<void>;
926
- /** Mint the bearer the client will send on every MCP request. Return undefined to deny the grant. */
927
- issueToken: (user: OAuthUser, target: OAuthGrantTarget) => Promise<{
1148
+ /** Mint the bearer the client will send on every request. Return undefined to deny the grant. */
1149
+ issueToken: (user: OAuthUser, target: OAuthGrantTarget, context: OAuthIssueContext) => Promise<{
928
1150
  token: string;
929
1151
  expiresInSeconds?: number;
930
1152
  } | undefined>;
1153
+ /**
1154
+ * End a credential {@link OAuthAdapters.issueToken} minted, when its grant is revoked (RFC 7009).
1155
+ *
1156
+ * Optional, for a credential that ends on its own. Without it, revoking a grant stops it being RENEWED, and what
1157
+ * was already issued keeps working until it expires — which a person who just signed a device out reads as the
1158
+ * sign-out not having happened, because the device is still there in their list.
1159
+ */
1160
+ revokeToken?: (credential: string) => Promise<void>;
931
1161
  store: OAuthStore;
932
1162
  };
1163
+ /**
1164
+ * Who a credential is being issued to, beyond the person: which application, from where, and — on a renewal — which
1165
+ * credential it takes the place of.
1166
+ *
1167
+ * This is what lets a deployment tell its user WHICH of their devices a credential lives on. The application names
1168
+ * itself when it registers (RFC 7591 `client_name`, `software_id`); the request is the one the credential is being
1169
+ * issued on — at consent, the person's browser, which for a loopback client is the same machine.
1170
+ */
1171
+ export type OAuthIssueContext = {
1172
+ client: {
1173
+ clientId: string;
1174
+ /** What the application registered as: `Plitzi CLI on carlos-mbp`, `Claude`. */
1175
+ name: string;
1176
+ /** RFC 7591 `software_id`, when it sent one: a stable name for the SOFTWARE, the same on every machine. */
1177
+ softwareId?: string;
1178
+ };
1179
+ request?: {
1180
+ userAgent?: string;
1181
+ ip?: string;
1182
+ };
1183
+ /**
1184
+ * Where the code of THIS grant is sent: the `redirect_uri` of the authorization request, at consent. A deployment
1185
+ * whose credential is only good at certain addresses checks it here — registering a client is open to anybody, and
1186
+ * the address it names is the one thing that says who will receive what the person agreed to. Absent on a renewal.
1187
+ */
1188
+ redirectUri?: string;
1189
+ /**
1190
+ * The credential this grant last issued, on a renewal. A deployment that keeps a row per credential updates that
1191
+ * row rather than adding one, so a device renewing every hour stays one device.
1192
+ */
1193
+ replaces?: string;
1194
+ };
933
1195
  /** A connection a visitor may take WITHOUT signing in, for a server whose public surface needs no identity — the
934
1196
  * MCP App, the tool and resource listings, the guide. The consent screen offers it as a second button beside the
935
1197
  * sign-in, and the grant is whatever `target` grants: point it at a target that carries no space, never at one
@@ -992,6 +1254,21 @@ export type OAuthConsentView = {
992
1254
  canSwitchUser?: boolean;
993
1255
  /** A message to show the user. */
994
1256
  error?: string;
1257
+ /**
1258
+ * Who is asking, and where the grant goes if the person says yes.
1259
+ *
1260
+ * Anybody can register a client, call it anything and send somebody this screen on the deployment's own domain, so
1261
+ * the name alone proves nothing. The host the code is sent back to is the one fact the requester cannot choose
1262
+ * freely, and it is what tells "the app I just opened" apart from a stranger's server.
1263
+ */
1264
+ client: {
1265
+ /** What the client registered itself as. Chosen by the client, so it is shown as a claim. */
1266
+ name: string;
1267
+ /** The host of the `redirect_uri` the grant is delivered to. */
1268
+ redirectHost: string;
1269
+ /** The grant goes back to an app listening on this computer (RFC 8252 loopback), not to a server. */
1270
+ loopback: boolean;
1271
+ };
995
1272
  branding: OAuthBranding;
996
1273
  };
997
1274
  /** OAuth 2.1 authorization for the MCP server (RFC 9728 discovery + RFC 7591 dynamic client registration +
@@ -1040,6 +1317,15 @@ export type OAuthConfig = {
1040
1317
  * holds, and wrapping it costs a store read on every request and gives a second thing to revoke.
1041
1318
  */
1042
1319
  directTokens?: boolean;
1320
+ /**
1321
+ * Accept only loopback `redirect_uri`s (`http://127.0.0.1:<port>/…`, RFC 8252 §7.3), at registration and again at
1322
+ * `/authorize`.
1323
+ *
1324
+ * Turn it on when every client is a native app on the person's own machine — a CLI, a desktop app — and above all
1325
+ * with {@link directTokens}, where the grant IS the person's session. Registration is open to anybody, so with https
1326
+ * redirects allowed a stranger's server can register, send somebody the link, and collect what they approve.
1327
+ */
1328
+ loopbackRedirectsOnly?: boolean;
1043
1329
  };
1044
1330
  /** A short-TTL, one-shot store for unsaved draft offline-data behind a preview token. The SDK ships an
1045
1331
  * in-memory default (fine for a single replica); a multi-replica deployment injects a shared (e.g. Redis)
@@ -1056,11 +1342,15 @@ export type OAuthConfig = {
1056
1342
  export type DraftPutOptions = {
1057
1343
  ttlMs: number;
1058
1344
  reusable?: boolean;
1345
+ /** The space the draft was made from. It is only ever rendered for that space. */
1346
+ spaceId: number;
1059
1347
  };
1060
1348
  /** A stashed draft, and whether the read that resolved it left it there. */
1061
1349
  export type DraftEntry = {
1062
1350
  data: OfflineDataRaw;
1063
1351
  reusable: boolean;
1352
+ /** The space the draft was made from — see {@link DraftPutOptions.spaceId}. */
1353
+ spaceId: number;
1064
1354
  };
1065
1355
  export type DraftStore = {
1066
1356
  put: (token: string, data: OfflineDataRaw, options: DraftPutOptions) => void | Promise<void>;
@@ -1082,7 +1372,12 @@ export type SSRPreviewConfig = {
1082
1372
  enabled?: boolean;
1083
1373
  /** Internal endpoint path that mints a preview token. Default '/__preview'. */
1084
1374
  path?: string;
1085
- /** Shared secret required in the `x-preview-secret` header; requests without it are rejected. */
1375
+ /**
1376
+ * Shared secret required in the `x-preview-secret` header; requests without it are rejected.
1377
+ *
1378
+ * Required for the endpoint to answer at all: the page server that hosts it is the one the public reaches, so an
1379
+ * enabled endpoint with no secret refuses every request rather than serving anyone.
1380
+ */
1086
1381
  secret?: string;
1087
1382
  /** One-shot token time-to-live in milliseconds. Default 60000. */
1088
1383
  ttlMs?: number;
@@ -44,6 +44,59 @@ export type SpaceCredential = {
44
44
  createdAt: number;
45
45
  updatedAt: number;
46
46
  };
47
+ /**
48
+ * A person given one of the space's visitor roles (`settings.visitorRoles`), by email. `claimed` says whether an
49
+ * account has taken it yet: a role given to an address waits for somebody to sign in with it, verified.
50
+ */
51
+ export type SpaceVisitor = {
52
+ id: number;
53
+ email: string;
54
+ role: string;
55
+ claimed: boolean;
56
+ createdAt: number;
57
+ updatedAt: number;
58
+ };
59
+ /** One environment's runtime — the space's own server code run beside the platform — and how it last was. */
60
+ export type SpaceRuntimeEnvironment = {
61
+ environment: string;
62
+ /** 0 for the draft. */
63
+ revision: number;
64
+ /** The packed code it runs, by what its bytes are. */
65
+ digest: string;
66
+ status: 'waiting' | 'starting' | 'ready' | 'failed' | 'stopping' | 'stopped';
67
+ /** Why it is not running, for whoever manages the space. */
68
+ error: string | null;
69
+ /** Why it is kept stopped: `idle` (unused for too long) or `manual`. */
70
+ stoppedReason: 'idle' | 'manual' | null;
71
+ /** When a running one stops for being unused, unless something uses it before — unix seconds. */
72
+ idleStopsAt: number | null;
73
+ /** The paths of the space it answers itself (`/mcp`). */
74
+ endpoints: string[];
75
+ /** Its tasks, as flows name them (`board.create`). */
76
+ tasks: string[];
77
+ startedAt: number | null;
78
+ /** The size it runs at — or will start at — by name (`SpaceRuntimeSizeOption['name']`). */
79
+ size: string;
80
+ };
81
+ /** A size a runtime may run at: what its pod may spend, and whether the space's plan includes it. */
82
+ export type SpaceRuntimeSizeOption = {
83
+ name: string;
84
+ label: string;
85
+ /** As Kubernetes reads it: `250m` is a quarter of a core. */
86
+ cpu: string;
87
+ /** As Kubernetes reads it: `256Mi`. */
88
+ memory: string;
89
+ included: boolean;
90
+ };
91
+ /** A space's runtime: every environment's, and the names of the variables it starts with — never their values. */
92
+ export type SpaceRuntime = {
93
+ environments: SpaceRuntimeEnvironment[];
94
+ variables: string[];
95
+ /** Every size there is, smallest first. */
96
+ sizes: SpaceRuntimeSizeOption[];
97
+ /** How long a runtime may go unused before it is stopped; 0 when the platform never stops one. */
98
+ idleMinutes: number;
99
+ };
47
100
  export type SpaceDeployment = {
48
101
  id: number;
49
102
  environment: Environment;
@@ -4,4 +4,10 @@ export type RuntimeStateInstance = {
4
4
  setState: (value: RuntimeState | ((prev: RuntimeState) => RuntimeState)) => void;
5
5
  setStateByKey: (key: string, value: unknown) => void;
6
6
  clearState: () => void;
7
+ /**
8
+ * Called with the whole state after every change to it, until the returned function is called. What a host or a
9
+ * plugin that keeps the state somewhere of its own — a store, a URL, an analytics call — listens to instead of
10
+ * polling `state`.
11
+ */
12
+ subscribe: (listener: (state: RuntimeState) => void) => () => void;
7
13
  };
@@ -3,6 +3,7 @@ import { SubscriptionCollaborator, SubscriptionCollaboratorPointer } from './Bui
3
3
  import { Environment, RenderMode } from './CommonTypes';
4
4
  import { Source } from './DataSourceTypes';
5
5
  import { QueryParams, RouteParams } from './NavigationTypes';
6
+ import { RealtimeTransport } from './RealtimeTypes';
6
7
  import { Schema, Element } from './SchemaTypes';
7
8
  import { Segment } from './SegmentTypes';
8
9
  import { SpaceConnector } from './SpaceTypes';
@@ -44,6 +45,11 @@ export type CommonState = {
44
45
  sources?: Record<string, Source>;
45
46
  rsc?: RscState;
46
47
  actions?: ActionsState;
48
+ /** Where this origin's realtime channels answer — absent in a render with no server, where no channel opens. */
49
+ realtime?: {
50
+ endpoint?: string;
51
+ transport?: RealtimeTransport;
52
+ };
47
53
  render?: RenderSettings;
48
54
  /**
49
55
  * The theme, mirrored from `themeStore` so the devtools store viewer answers "which theme is this" in one line.
@@ -72,6 +78,11 @@ export type CommonState = {
72
78
  /** Scheme, host AND port — what a link needs to name this page absolutely. `hostname` has no port, which is why
73
79
  * it answers `when` rules and cannot answer this. */
74
80
  origin: string;
81
+ /**
82
+ * The page's whole address — origin, path and query — as the server was asked for it and the browser shows it: what
83
+ * a link that shares THIS page is. Known in the first paint, so a text built from it is right before hydration.
84
+ */
85
+ href: string;
75
86
  currentPageId: string;
76
87
  navigate: (url: string, isExternal?: boolean) => void;
77
88
  };
@@ -102,7 +113,7 @@ export type RenderSettings = {
102
113
  *
103
114
  * Not the visitor's business and not the page's either — it is a fact about the account behind the site, which is
104
115
  * why it rides the render surface rather than the schema: nothing an author writes can set it, and nothing in the
105
- * space's settings can turn it off. `branding` is forced on by the same state; this is what says WHY.
116
+ * space's settings can turn it off.
106
117
  */
107
118
  overQuota?: boolean;
108
119
  /**
@@ -12,6 +12,8 @@ export * from './NavigationTypes';
12
12
  export * from './CollectionTypes';
13
13
  export * from './ConnectorTypes';
14
14
  export * from './ActionTypes';
15
+ export * from './FunctionTypes';
16
+ export * from './RealtimeTypes';
15
17
  export * from './ComponentTypes';
16
18
  export * from './StateTypes';
17
19
  export * from './CommonTypes';
@@ -1,2 +1,3 @@
1
- import { StyleVariableCategory as e } from "./StyleTypes.mjs";
2
- export { e as StyleVariableCategory };
1
+ import { WHILE_RUNNING_MODES as e } from "./SchemaTypes.mjs";
2
+ import { StyleVariableCategory as t } from "./StyleTypes.mjs";
3
+ export { t as StyleVariableCategory, e as WHILE_RUNNING_MODES };