@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
@@ -0,0 +1,110 @@
1
+ import { filters as e } from "./filters/filters.mjs";
2
+ import { lex as t } from "./Lexer/Lexer.mjs";
3
+ import { parse as n } from "./Parser/Parser.mjs";
4
+ //#region src/helpers/twigWrapper/inspectTemplate.ts
5
+ var r = /* @__PURE__ */ new Set([
6
+ "cycle",
7
+ "max",
8
+ "min",
9
+ "range"
10
+ ]), i = "loop", a = class {
11
+ issues = [];
12
+ freeNames = /* @__PURE__ */ new Set();
13
+ nodes(e, t) {
14
+ let n = new Set(t);
15
+ for (let t of e) switch (t.type) {
16
+ case "text":
17
+ case "break":
18
+ case "continue": break;
19
+ case "variable":
20
+ this.expression(t.expression, n);
21
+ break;
22
+ case "if":
23
+ this.expression(t.condition, n), this.nodes(t.body, n);
24
+ for (let e of t.elseifClauses) this.expression(e.condition, n), this.nodes(e.body, n);
25
+ t.elseBody && this.nodes(t.elseBody, n);
26
+ break;
27
+ case "for": {
28
+ this.expression(t.collection, n);
29
+ let e = /* @__PURE__ */ new Set([
30
+ ...n,
31
+ t.valueVar,
32
+ i,
33
+ ...t.keyVar ? [t.keyVar] : []
34
+ ]);
35
+ this.nodes(t.body, e), n = /* @__PURE__ */ new Set([...n, ...this.setsIn(t.body)]), t.elseBody && this.nodes(t.elseBody, n);
36
+ break;
37
+ }
38
+ case "set":
39
+ Array.isArray(t.value) ? this.nodes(t.value, n) : this.expression(t.value, n), n = /* @__PURE__ */ new Set([...n, t.name]);
40
+ break;
41
+ case "apply":
42
+ this.filterNames(t.filters.map((e) => e.name));
43
+ for (let e of t.filters) e.args.forEach((e) => this.expression(e, n));
44
+ this.nodes(t.body, n);
45
+ }
46
+ return n;
47
+ }
48
+ setsIn(e) {
49
+ return e.flatMap((e) => e.type === "set" ? [e.name] : []);
50
+ }
51
+ filterNames(t) {
52
+ for (let n of t) n && !Object.hasOwn(e, n) && this.issues.push(`Unknown filter "${n}"`);
53
+ }
54
+ expression(e, t) {
55
+ switch (e.type) {
56
+ case "literal": return;
57
+ case "array":
58
+ e.elements.forEach((e) => this.expression(e, t));
59
+ return;
60
+ case "object":
61
+ for (let n of e.entries) this.expression(n.key, t), this.expression(n.value, t);
62
+ return;
63
+ case "range":
64
+ this.expression(e.start, t), this.expression(e.end, t);
65
+ return;
66
+ case "path":
67
+ t.has(e.segments[0]) || this.freeNames.add(e.segments[0]);
68
+ return;
69
+ case "index":
70
+ this.expression(e.object, t), this.expression(e.index, t);
71
+ return;
72
+ case "function":
73
+ r.has(e.name) || this.issues.push(`Unknown function "${e.name}()": the functions are ${[...r].join(", ")}`), e.args.forEach((e) => this.expression(e, t));
74
+ return;
75
+ case "filter":
76
+ this.expression(e.subject, t), this.filterNames(e.filters.map((e) => e.name));
77
+ for (let n of e.filters) n.args.forEach((e) => this.expression(e, t));
78
+ return;
79
+ case "concat":
80
+ e.parts.forEach((e) => this.expression(e, t));
81
+ return;
82
+ case "unary":
83
+ this.expression(e.operand, t);
84
+ return;
85
+ case "binary":
86
+ this.expression(e.left, t), (e.operator !== "is" && e.operator !== "is not" || e.right.type !== "path") && this.expression(e.right, t);
87
+ return;
88
+ case "default":
89
+ this.expression(e.value, t), this.expression(e.defaultExpr, t);
90
+ return;
91
+ case "ternary":
92
+ this.expression(e.condition, t), e.trueExpr && this.expression(e.trueExpr, t), this.expression(e.falseExpr, t);
93
+ return;
94
+ case "arrow": this.expression(e.body, /* @__PURE__ */ new Set([...t, ...e.params]));
95
+ }
96
+ }
97
+ }, o = (e) => {
98
+ let r = t(e);
99
+ if (r.error) return {
100
+ issues: [r.error],
101
+ freeNames: []
102
+ };
103
+ let i = new a(), { nodes: o, error: s } = n(r.tokens, !1, i.issues);
104
+ return s && i.issues.push(s), i.nodes(o, /* @__PURE__ */ new Set()), {
105
+ issues: [...new Set(i.issues)],
106
+ freeNames: [...i.freeNames]
107
+ };
108
+ };
109
+ //#endregion
110
+ export { o as inspectTemplate };
@@ -2,6 +2,13 @@ import { CacheEntry } from '../TemplateCache';
2
2
  export declare const resolveSimplePath: (context: Record<string, unknown>, name: string) => unknown;
3
3
  export declare const resolveDottedPath: (context: Record<string, unknown>, path: string) => unknown;
4
4
  export declare const serializeValue: (value: unknown) => string;
5
+ /**
6
+ * A rendered template as the value it reads as: `30` the number, `true`, an object from its JSON.
7
+ *
8
+ * Except a number that would not read back as the text it came from — `012345`, a code with a leading zero, or a
9
+ * 20-digit id past what a number can hold exactly. Those were handed on as `12345` and as the nearest double, which is
10
+ * a different second-factor code, PIN or id by the time anything sends it; they stay the text they were.
11
+ */
5
12
  export declare const finalizeRaw: (output: string) => unknown;
6
13
  export declare const flattenContext: (variables: Record<string, unknown>) => Record<string, unknown>;
7
14
  export declare const renderSimpleTokens: (entry: CacheEntry, context: Record<string, unknown>) => string;
@@ -12,7 +12,8 @@ var e = (e, t) => e[t], t = (e, t) => {
12
12
  return r;
13
13
  }, n = (e) => e == null ? "" : typeof e == "object" ? JSON.stringify(e) : String(e), r = (e) => {
14
14
  try {
15
- return JSON.parse(e) || e;
15
+ let t = JSON.parse(e);
16
+ return typeof t == "number" && String(t) !== e.trim() ? e : t || e;
16
17
  } catch {
17
18
  return e;
18
19
  }
@@ -1 +1,2 @@
1
- export { processTwig } from './processTwig';
1
+ export { processTwig, processTwigParam, processTwigValue } from './processTwig';
2
+ export { MAX_PARAM_PASSES, resolveStepParam } from './resolveStepParam';
@@ -1,2 +1,3 @@
1
- import { processTwig as e } from "./processTwig.mjs";
2
- export { e as processTwig };
1
+ import { processTwig as e, processTwigParam as t, processTwigValue as n } from "./processTwig.mjs";
2
+ import { MAX_PARAM_PASSES as r, resolveStepParam as i } from "./resolveStepParam.mjs";
3
+ export { r as MAX_PARAM_PASSES, e as processTwig, t as processTwigParam, n as processTwigValue, i as resolveStepParam };
@@ -1 +1,29 @@
1
1
  export declare const processTwig: (template: string, variables?: Record<string, unknown>, keepEmptyTokens?: boolean, asRaw?: boolean) => unknown;
2
+ /**
3
+ * A template's VALUE, where it has one: `{{ rows|filter(r => r.open) }}` is the filtered array, `{{ count > 0 }}` a
4
+ * boolean, `{{ total }}` the number it holds.
5
+ *
6
+ * A template that is one `{{ expression }}` and nothing else (surrounding whitespace aside) answers that expression's
7
+ * value untouched. Anything with text around it, or tags, is text by nature and renders as {@link processTwig}.
8
+ *
9
+ * Unlike `processTwig`'s `asRaw`, nothing goes through JSON on the way: `0`, `false` and `null` come back as
10
+ * themselves, and a string that looks like a number stays a string.
11
+ */
12
+ export declare const processTwigValue: (template: string, variables?: Record<string, unknown>) => unknown;
13
+ /**
14
+ * A flow step's param — in the browser's flows and in a server action's — as the value the step is handed.
15
+ *
16
+ * A param that is one `{{ expression }}` is that expression's value, exactly: a string stays a string however it
17
+ * looks. The type is the VALUE's, never guessed from its text — which is what the step params used to do, rendering
18
+ * the value to text and reading the text back as JSON: a password typed as `1234` reached the server as a number, and
19
+ * a text field declared `text` on the far side then saw no password at all. What a param should be converted to is
20
+ * the business of whoever declares its type — `setState`'s `type`, an action's input fields — not of the resolver.
21
+ *
22
+ * Two readings of JSON stay, because in both the author wrote JSON on purpose: a param that is nothing but a JSON
23
+ * filter (`{{ saved|json_encode }}`) is the value it encodes, and text around the tokens that makes a JSON object or
24
+ * array (`{ "id": "{{ id }}" }`, an `input` written as a document) is that document. A value printed inside one of
25
+ * the document's string literals is escaped for it: a visitor's `Say "hi"` or a note on two lines used to break the
26
+ * document, and the step was handed its raw text instead. Any other text is text. A value that is not there reads as
27
+ * an empty string, as it renders.
28
+ */
29
+ export declare const processTwigParam: (template: string, variables?: Record<string, unknown>) => unknown;
@@ -1,24 +1,81 @@
1
- import { evaluate as e } from "../Evaluator/Evaluator.mjs";
2
- import { finalizeRaw as t, flattenContext as n, renderSimpleTokens as r } from "./helpers.mjs";
3
- import { getNodes as i, resolveTokens as a } from "../TemplateCache/TemplateCache.mjs";
1
+ import { finalizeRaw as e, flattenContext as t, renderSimpleTokens as n } from "./helpers.mjs";
2
+ import { evaluate as r, evaluateExpression as i } from "../Evaluator/Evaluator.mjs";
3
+ import { getNodes as a, resolveTokens as o } from "../TemplateCache/TemplateCache.mjs";
4
4
  //#region src/helpers/twigWrapper/processTwig/processTwig.ts
5
- var o = (o, s = {}, c = !1, l = !1) => {
6
- if (typeof o != "string") return o;
5
+ var s = (i, s = {}, c = !1, l = !1) => {
6
+ if (typeof i != "string") return i;
7
7
  try {
8
- if (o.indexOf("{%") === -1 && o.indexOf("{{") === -1) return o;
9
- let u = "variables" in s ? n(s) : s, d = a(o);
10
- if (!d) return o;
8
+ if (i.indexOf("{%") === -1 && i.indexOf("{{") === -1) return i;
9
+ let u = "variables" in s ? t(s) : s, d = o(i);
10
+ if (!d) return i;
11
11
  if (!c && !d.hasTags && d.allSimpleOrDotted) {
12
- let e = r(d, u);
13
- return l ? t(e) : e;
12
+ let t = n(d, u);
13
+ return l ? e(t) : t;
14
14
  }
15
- let f = i(d, c);
16
- if (!f) return o;
17
- let { output: p, variables: m, hasSet: h } = e(f, u, c);
18
- return h && Object.assign(s, m), c && p === o ? o : l ? t(p) : p;
15
+ let f = a(d, c);
16
+ if (!f) return i;
17
+ let { output: p, variables: m, hasSet: h } = r(f, u, c);
18
+ return h && Object.assign(s, m), c && p === i ? i : l ? e(p) : p;
19
19
  } catch {
20
- return o;
20
+ return i;
21
+ }
22
+ }, c = (e) => {
23
+ let t = e.trimStart();
24
+ return t.startsWith("{") || t.startsWith("[");
25
+ }, l = (e, n) => {
26
+ let i = o(e), a = i ? i.nodes ?? i.nodesWithSource : null;
27
+ if (a) try {
28
+ let e = "variables" in n ? t(n) : n, { output: i, variables: o, hasSet: s } = r(a, e, !1, !0);
29
+ if (!c(i)) return;
30
+ let l = JSON.parse(i);
31
+ return s && Object.assign(n, o), l;
32
+ } catch {
33
+ return;
34
+ }
35
+ }, u = (e, n = {}) => {
36
+ if (typeof e != "string") return e;
37
+ let r = o(e), a = (r ? r.nodes ?? r.nodesWithSource : null)?.filter((e) => e.type !== "text" || e.value.trim() !== "");
38
+ if (a?.length !== 1 || a[0].type !== "variable") return s(e, n);
39
+ try {
40
+ let e = "variables" in n ? t(n) : n;
41
+ return i(a[0].expression, e);
42
+ } catch {
43
+ return e;
44
+ }
45
+ }, d = /* @__PURE__ */ new Set([
46
+ "json_encode",
47
+ "to_json",
48
+ "object_as_json"
49
+ ]), f = (e) => e.type === "filter" && d.has(e.filters[e.filters.length - 1]?.name ?? ""), p = (e) => {
50
+ let t = e.trim();
51
+ if (!t.startsWith("{") && !t.startsWith("[")) return e;
52
+ try {
53
+ return JSON.parse(t);
54
+ } catch {
55
+ return e;
56
+ }
57
+ }, m = (e, n = {}) => {
58
+ if (typeof e != "string") return e;
59
+ let r = o(e), a = (r ? r.nodes ?? r.nodesWithSource : null)?.filter((e) => e.type !== "text" || e.value.trim() !== "");
60
+ if (a?.length !== 1 || a[0].type !== "variable") {
61
+ let t = e.includes("\"") ? l(e, n) : void 0;
62
+ if (t !== void 0) return t;
63
+ let r = s(e, n);
64
+ return typeof r == "string" ? p(r) : r;
65
+ }
66
+ let { expression: c } = a[0];
67
+ try {
68
+ let e = "variables" in n ? t(n) : n, r = i(c, e);
69
+ if (r === void 0) return "";
70
+ if (typeof r == "string" && f(c)) try {
71
+ return JSON.parse(r);
72
+ } catch {
73
+ return r;
74
+ }
75
+ return r;
76
+ } catch {
77
+ return e;
21
78
  }
22
79
  };
23
80
  //#endregion
24
- export { o as processTwig };
81
+ export { s as processTwig, m as processTwigParam, u as processTwigValue };
@@ -0,0 +1,17 @@
1
+ /** How many times a value may resolve to another template before the resolver stops and says so. */
2
+ export declare const MAX_PARAM_PASSES = 5;
3
+ /**
4
+ * One step param, resolved against the flow's scope — the ONE resolver for the browser's flows and a server action's
5
+ * steps, so a param means the same on both sides.
6
+ *
7
+ * The param as written is a template whatever it holds: a condition, a loop or an object literal as much as a name —
8
+ * which is why the first pass runs on any template syntax, not only on what `hasValidToken` recognises (it answers a
9
+ * narrower question, for attributes, where the text around a token is prose). The server used to skip that first pass,
10
+ * so `{{ { "id": run.id } }}` reached its task as the template text. What a pass RETURNS is data, and is read again only
11
+ * when it carries a well-formed token — so text a visitor typed that happens to contain braces is not evaluated — up to
12
+ * {@link MAX_PARAM_PASSES}. `unresolved` says the ceiling was hit with tokens left, for the caller to report.
13
+ */
14
+ export declare const resolveStepParam: (template: string, scope: Record<string, unknown>) => {
15
+ value: unknown;
16
+ unresolved: boolean;
17
+ };
@@ -0,0 +1,14 @@
1
+ import { processTwigParam as e } from "./processTwig.mjs";
2
+ import { hasTemplateSyntax as t } from "../tokens/hasTemplateSyntax.mjs";
3
+ import { hasValidToken as n } from "../tokens/hasValidToken.mjs";
4
+ //#region src/helpers/twigWrapper/processTwig/resolveStepParam.ts
5
+ var r = 5, i = (r, i) => {
6
+ let a = r, o = 5;
7
+ for (t(a) && !n(r) && (a = e(r, i), o--); typeof a == "string" && n(a) && o > 0;) a = e(a, i), o--;
8
+ return {
9
+ value: a,
10
+ unresolved: typeof a == "string" && n(a)
11
+ };
12
+ };
13
+ //#endregion
14
+ export { r as MAX_PARAM_PASSES, i as resolveStepParam };
@@ -1,3 +1,14 @@
1
+ /**
2
+ * Every path a template reads, as far as it is known before it runs: `{{ computed.tool == 'pen' }}` gives
3
+ * `computed.tool`, `{{ state.owned[source.id] }}` gives `state.owned` and `source.id` — a bracket whose key is only
4
+ * known at run time ends the path at what came before it.
5
+ *
6
+ * What a caller SUBSCRIBES to, where the root alone would be too much: an element whose template reads
7
+ * `computed.tool` has no reason to render again when `computed.selectionCount` changes, and every element on a page
8
+ * reads some computed value. Names the template binds itself — a loop variable, a `set`, an arrow's parameter —
9
+ * come back too: they resolve to no source, and asking for a path that is not there costs nothing.
10
+ */
11
+ export declare const templatePaths: (template: string) => string[];
1
12
  /**
2
13
  * Every top-level name a template reads: `{{ theme.resolved }}` and `{% if state.open %}` both give their first segment.
3
14
  *
@@ -7,8 +7,8 @@ var t = (e, n) => {
7
7
  }
8
8
  if (typeof e == "object" && e) {
9
9
  if ("type" in e && e.type === "path" && "segments" in e && Array.isArray(e.segments)) {
10
- let t = e.segments[0];
11
- typeof t == "string" && n.add(t);
10
+ let t = e.segments.filter((e) => typeof e == "string");
11
+ t.length > 0 && n.add(t.join("."));
12
12
  return;
13
13
  }
14
14
  for (let r of Object.values(e)) t(r, n);
@@ -18,6 +18,6 @@ var t = (e, n) => {
18
18
  if (!r) return [];
19
19
  let i = /* @__PURE__ */ new Set();
20
20
  return t(r.nodes ?? r.nodesWithSource, i), [...i];
21
- };
21
+ }, r = (e) => [...new Set(n(e).map((e) => e.split(".")[0]))];
22
22
  //#endregion
23
- export { n as templateRootNames };
23
+ export { n as templatePaths, r as templateRootNames };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Whether a string is written in template syntax at all — any `{{ … }}` or `{% … %}`, well-formed token or not.
3
+ *
4
+ * `hasValidToken` answers a narrower question on purpose: whether an ATTRIBUTE holds a token worth resolving, where
5
+ * the text around it is often prose and a stray `{{` must not be evaluated. A step's params are the other case: they
6
+ * are templates by construction, so a condition (`{{ admin ? '1' : '' }}`) or a loop (`{% for %}…{% endfor %}`) is
7
+ * meant to run — read by the narrow test they were handed on as written, and a flag stored its own template text.
8
+ */
9
+ export declare const hasTemplateSyntax: (value: unknown) => boolean;
@@ -0,0 +1,4 @@
1
+ //#region src/helpers/twigWrapper/tokens/hasTemplateSyntax.ts
2
+ var e = (e) => typeof e == "string" && /\{\{[\s\S]*?\}\}|\{%[\s\S]*?%\}/.test(e);
3
+ //#endregion
4
+ export { e as hasTemplateSyntax };
@@ -0,0 +1,29 @@
1
+ import { ChangeEntry } from './types';
2
+ export type FieldChange = {
3
+ path: string;
4
+ before?: unknown;
5
+ after?: unknown;
6
+ };
7
+ /** What a line says was done, for a reader who scans the icon before the words. */
8
+ export type ChangeAction = 'add' | 'remove' | 'move' | 'update' | 'reorder';
9
+ /** One thing a save did, in words, and the element it is about when it is about one. */
10
+ export type ChangeLine = {
11
+ text: string;
12
+ action: ChangeAction;
13
+ elementId?: string;
14
+ };
15
+ /**
16
+ * What changed inside one entity, field by field (`attributes.content`, `definition.items`). Objects are walked; a list
17
+ * or a value is compared whole, since "the third item moved" reads worse than the list before and after.
18
+ */
19
+ export declare const fieldChanges: (before: unknown, after: unknown, path?: string) => FieldChange[];
20
+ /** Each line once, the first time it is said. */
21
+ export declare const uniqueLines: (lines: ChangeLine[]) => ChangeLine[];
22
+ /**
23
+ * One save, as lines a person reads: each thing it did, said once and in words.
24
+ *
25
+ * Adding an element also rewrites its parent's list of children, and a move rewrites two; those are the consequence of
26
+ * the add or the move, so they are not said again. A parent whose children changed for no other reason in the same
27
+ * save — a reorder — is said as that.
28
+ */
29
+ export declare const describeChange: (entries: ChangeEntry[]) => ChangeLine[];
@@ -0,0 +1,93 @@
1
+ //#region src/history/describe.ts
2
+ var e = (e) => typeof e == "object" && !!e && !Array.isArray(e), t = (n, r, i = "") => e(n) && e(r) ? [.../* @__PURE__ */ new Set([...Object.keys(n), ...Object.keys(r)])].flatMap((e) => t(n[e], r[e], i ? `${i}.${e}` : e)) : JSON.stringify(n) === JSON.stringify(r) ? [] : [{
3
+ path: i,
4
+ ...n === void 0 ? {} : { before: n },
5
+ ...r === void 0 ? {} : { after: r }
6
+ }], n = (t) => e(t) ? t : {}, r = (e) => {
7
+ let t = n(e).definition?.type;
8
+ return t ? t === "layoutContainer" ? "layout" : t.replace(/([a-z])([A-Z])/gu, "$1 $2").toLowerCase() : "element";
9
+ }, i = (e) => n(e).definition?.parentId ?? void 0, a = (e, t) => {
10
+ let n = t.get(e);
11
+ return n === void 0 ? `“${e}”` : `${r(n)} “${e}”`;
12
+ }, o = (e) => {
13
+ let t = e.split("."), n = t[0], r = t.length > 1 ? t[1] : n;
14
+ if (n === "attributes") return r;
15
+ let i = {
16
+ label: "label",
17
+ styleSelectors: "classes",
18
+ bindings: "bindings",
19
+ interactions: "interactions",
20
+ initialState: "initial state",
21
+ items: void 0,
22
+ parentId: void 0,
23
+ rootId: void 0,
24
+ type: "type"
25
+ };
26
+ return Object.hasOwn(i, r) ? i[r] : r;
27
+ }, s = (e, t = 3) => e.length > t ? `${e.slice(0, t).join(", ")} and ${e.length - t} more` : e.join(", "), c = {
28
+ folder: "folder",
29
+ variable: "variable",
30
+ setting: "setting",
31
+ selector: "class",
32
+ globalStyle: "global style for",
33
+ idStyle: "id style",
34
+ token: "token",
35
+ font: "font",
36
+ file: "function file"
37
+ }, l = {
38
+ add: "Added",
39
+ update: "Changed",
40
+ remove: "Removed"
41
+ }, u = (t, n) => {
42
+ let r = e(t) ? t : {}, i = e(n) ? n : {};
43
+ return [.../* @__PURE__ */ new Set([...Object.keys(r), ...Object.keys(i)])].filter((e) => JSON.stringify(r[e]) !== JSON.stringify(i[e]));
44
+ }, d = (e) => e.kind !== "element", f = (e) => {
45
+ let { kind: t } = e;
46
+ if (t === "setting" && e.id === "pages") return {
47
+ text: "Reordered the pages",
48
+ action: "reorder"
49
+ };
50
+ let n = `${l[e.op]} ${c[t]} “${e.id}”`;
51
+ if (e.op === "update" && (t === "selector" || t === "globalStyle" || t === "idStyle")) {
52
+ let t = u(e.before, e.after);
53
+ return {
54
+ text: t.length > 0 ? `${n} on ${t.join(", ")}` : n,
55
+ action: e.op
56
+ };
57
+ }
58
+ return {
59
+ text: n,
60
+ action: e.op
61
+ };
62
+ }, p = (e) => {
63
+ let t = /* @__PURE__ */ new Set();
64
+ return e.filter((e) => !t.has(e.text) && (t.add(e.text), !0));
65
+ }, m = (e) => {
66
+ let r = e.filter((e) => e.kind === "element"), c = new Map(r.map((e) => [e.id, e.after ?? e.before])), l = new Set(r.filter((e) => e.op !== "update" || i(e.before) !== i(e.after)).map((e) => e.id)), u = [];
67
+ for (let e of r) {
68
+ let r = a(e.id, c), d = (t, n) => u.push({
69
+ text: t,
70
+ action: n,
71
+ elementId: e.id
72
+ });
73
+ if (e.op === "add") {
74
+ let t = i(e.after);
75
+ d(t ? `Added ${r} to ${a(t, c)}` : `Added ${r}`, "add");
76
+ continue;
77
+ }
78
+ if (e.op === "remove") {
79
+ let t = i(e.before);
80
+ d(t ? `Removed ${r} from ${a(t, c)}` : `Removed ${r}`, "remove");
81
+ continue;
82
+ }
83
+ let f = i(e.before), p = i(e.after);
84
+ f !== p && f && p && d(`Moved ${r} from ${a(f, c)} to ${a(p, c)}`, "move");
85
+ let m = t(e.before, e.after), h = [...new Set(m.map((e) => o(e.path)).filter((e) => e !== void 0))];
86
+ h.length > 0 && d(`Changed ${s(h)} of ${r}`, "update");
87
+ let g = (e) => (n(e).definition?.items ?? []).filter((e) => !l.has(e)), _ = m.some((e) => e.path === "definition.items");
88
+ _ && JSON.stringify(g(e.before)) !== JSON.stringify(g(e.after)) && d(`Reordered the children of ${r}`, "reorder"), (m.length === 0 || h.length === 0 && !_ && f === p) && d(`Changed ${r}`, "update");
89
+ }
90
+ return u.push(...e.filter(d).map(f)), p(u);
91
+ };
92
+ //#endregion
93
+ export { m as describeChange, t as fieldChanges, p as uniqueLines };
@@ -0,0 +1,33 @@
1
+ import { ChangeEntry } from './types';
2
+ import { Schema, Style } from '../types';
3
+ /**
4
+ * Structural equality for documents as they are stored: JSON — objects, arrays and scalars, nothing else.
5
+ *
6
+ * Written out rather than borrowed because it runs on every save of a space, over every element of it, and almost
7
+ * every pair it compares is equal: what it has to be is a walk that stops at the first difference, with nothing to
8
+ * set up per call.
9
+ */
10
+ export declare const sameValue: (a: unknown, b: unknown) => boolean;
11
+ /**
12
+ * A copy of a stored document, for the model that has to remember what it last saved.
13
+ *
14
+ * JSON rather than a structural clone: documents are JSON by definition, and the round trip measures about half of
15
+ * `cloneDeep` on a 5 000-element schema — a cost every save of a space pays.
16
+ */
17
+ export declare const jsonCopy: <T>(value: T) => T;
18
+ /** The part of a schema a history reads: what is stored, never what the runtime derives from it. */
19
+ export type HistorySchema = Pick<Schema, 'flat' | 'pages' | 'pageFolders' | 'variables' | 'settings' | 'definition'>;
20
+ /**
21
+ * What changed between two versions of a schema, entity by entity.
22
+ *
23
+ * An element is one entity: whatever changed inside it — an attribute, a binding, a flow, its place in the tree —
24
+ * the entry carries it whole, before and after. Pages are elements; their ORDER is the setting `pages`.
25
+ */
26
+ export declare const diffSchema: (before: Partial<HistorySchema>, after: Partial<HistorySchema>) => ChangeEntry[];
27
+ /** The part of a style a history reads. Its `cache` is not: it is the whole stylesheet, compiled from the rest. */
28
+ export type HistoryStyle = Pick<Style, 'platform' | 'variables' | 'fonts' | 'theme' | 'mode'>;
29
+ /**
30
+ * What changed between two versions of a style. A selector is one entity across the display modes, so "tablet only"
31
+ * reads as one change to it, with the modes compared inside the entry.
32
+ */
33
+ export declare const diffStyle: (before: Partial<HistoryStyle>, after: Partial<HistoryStyle>) => ChangeEntry[];
@@ -0,0 +1,73 @@
1
+ //#region src/history/diff.ts
2
+ var e = (t, n) => {
3
+ if (t === n) return !0;
4
+ if (typeof t != "object" || typeof n != "object" || t === null || n === null || Array.isArray(t) !== Array.isArray(n)) return !1;
5
+ if (Array.isArray(t) && Array.isArray(n)) return t.length === n.length && t.every((t, r) => e(t, n[r]));
6
+ let r = t, i = n, a = Object.keys(r).filter((e) => r[e] !== void 0);
7
+ return a.length === Object.keys(i).filter((e) => i[e] !== void 0).length && a.every((t) => Object.hasOwn(i, t) && e(r[t], i[t]));
8
+ }, t = (e) => JSON.parse(JSON.stringify(e)), n = (t, n, r) => {
9
+ let i = [];
10
+ for (let [a, o] of Object.entries(r)) Object.hasOwn(n, a) ? e(n[a], o) || i.push({
11
+ kind: t,
12
+ id: a,
13
+ op: "update",
14
+ before: n[a],
15
+ after: o
16
+ }) : i.push({
17
+ kind: t,
18
+ id: a,
19
+ op: "add",
20
+ after: o
21
+ });
22
+ for (let [e, a] of Object.entries(n)) Object.hasOwn(r, e) || i.push({
23
+ kind: t,
24
+ id: e,
25
+ op: "remove",
26
+ before: a
27
+ });
28
+ return i;
29
+ }, r = (e, t) => Object.fromEntries((e ?? []).map((e) => [t(e), e])), i = (e, t) => Object.fromEntries(Object.entries(t ?? {}).map(([t, n]) => [`${e}.${t}`, n])), a = (e, t) => [
30
+ ...n("element", e.flat ?? {}, t.flat ?? {}),
31
+ ...n("folder", r(e.pageFolders, (e) => e.id), r(t.pageFolders, (e) => e.id)),
32
+ ...n("variable", r(e.variables, (e) => e.name), r(t.variables, (e) => e.name)),
33
+ ...n("setting", {
34
+ ...i("settings", e.settings),
35
+ ...i("definition", e.definition),
36
+ pages: e.pages
37
+ }, {
38
+ ...i("settings", t.settings),
39
+ ...i("definition", t.definition),
40
+ pages: t.pages
41
+ })
42
+ ], o = {
43
+ class: "selector",
44
+ element: "globalStyle",
45
+ id: "idStyle"
46
+ }, s = (e) => {
47
+ let t = {};
48
+ for (let [n, r] of Object.entries(e ?? {})) for (let [e, i] of Object.entries(r)) {
49
+ let r = o[i.type], a = t[r] ??= {};
50
+ (a[e] ??= {})[n] = i;
51
+ }
52
+ return t;
53
+ }, c = (e) => Object.fromEntries(Object.entries(e ?? {}).flatMap(([e, t]) => Object.entries(t).map(([t, n]) => [`${e}/${t}`, n]))), l = (e, t) => {
54
+ let i = s(e.platform), a = s(t.platform);
55
+ return [
56
+ ...[
57
+ "selector",
58
+ "globalStyle",
59
+ "idStyle"
60
+ ].flatMap((e) => n(e, i[e] ?? {}, a[e] ?? {})),
61
+ ...n("token", c(e.variables), c(t.variables)),
62
+ ...n("font", r(e.fonts, (e) => e.family), r(t.fonts, (e) => e.family)),
63
+ ...n("setting", {
64
+ theme: e.theme,
65
+ mode: e.mode
66
+ }, {
67
+ theme: t.theme,
68
+ mode: t.mode
69
+ })
70
+ ];
71
+ };
72
+ //#endregion
73
+ export { a as diffSchema, l as diffStyle, t as jsonCopy, e as sameValue };
@@ -0,0 +1,3 @@
1
+ export * from './describe';
2
+ export * from './diff';
3
+ export * from './types';
@@ -0,0 +1,3 @@
1
+ import { describeChange as e, fieldChanges as t, uniqueLines as n } from "./describe.mjs";
2
+ import { diffSchema as r, diffStyle as i, jsonCopy as a, sameValue as o } from "./diff.mjs";
3
+ export { e as describeChange, r as diffSchema, i as diffStyle, t as fieldChanges, a as jsonCopy, o as sameValue, n as uniqueLines };
@@ -0,0 +1,48 @@
1
+ /** Which of a space's documents a change was made to: its schema, its style, or its functions' source. */
2
+ export type ChangeDocument = 'schema' | 'style' | 'functions';
3
+ /**
4
+ * Where a change came from: a person in the builder, an agent over MCP, the builder's co-worker, the autofix, a GraphQL
5
+ * client that is not a person, or a writer with nothing to say (a seed, a script).
6
+ */
7
+ export type ChangeOrigin = 'builder' | 'mcp' | 'coworker' | 'autofix' | 'api' | 'system';
8
+ /**
9
+ * What one entry is about. Schema: an element (pages and layouts are elements too), a page folder, a schema variable,
10
+ * a setting (`settings.<key>`, `definition.<key>`, the page order `pages`). Style: a class selector, a global style
11
+ * (a bare element selector), an id style, a design token (`<category>/<name>`), a font family, a style setting
12
+ * (`theme`, `mode`). Functions: a file of their source, by its path (`index.ts`, `lib/feed.ts`).
13
+ */
14
+ export type ChangeKind = 'element' | 'folder' | 'variable' | 'setting' | 'selector' | 'globalStyle' | 'idStyle' | 'token' | 'font' | 'file';
15
+ /** One entity that changed, whole, before and after: the field-level difference is derived from the two. */
16
+ export type ChangeEntry = {
17
+ kind: ChangeKind;
18
+ id: string;
19
+ op: 'add' | 'remove' | 'update';
20
+ /** Absent on `add`. */
21
+ before?: unknown;
22
+ /** Absent on `remove`. */
23
+ after?: unknown;
24
+ };
25
+ export type ChangeAuthor = {
26
+ userId: number | null;
27
+ name: string;
28
+ };
29
+ /** One save that changed something: who, from where, and every entity it touched. */
30
+ export type SpaceChange = {
31
+ spaceId: number;
32
+ environment: string;
33
+ /** Monotonic per space and environment: the timeline's order and the address of a point in it. */
34
+ seq: number;
35
+ /** Milliseconds. */
36
+ at: number;
37
+ document: ChangeDocument;
38
+ author: ChangeAuthor;
39
+ origin: ChangeOrigin;
40
+ /** The MCP client's name, or the builder tab's instance id. */
41
+ client?: string;
42
+ /** Everything one request wrote shares it: one builder request, one `plitzi_apply`, one autofix. */
43
+ batch: string;
44
+ entries: ChangeEntry[];
45
+ summary: string;
46
+ /** The entries name what changed but carry no values: the whole change was too large to store as one record. */
47
+ truncated?: boolean;
48
+ };
File without changes