@mulmoclaude/collection-plugin 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/dist/chunk-CKQMccvm.cjs +28 -0
  2. package/dist/core/actionVisible.d.ts +1 -0
  3. package/dist/core/actionVisible.d.ts.map +1 -0
  4. package/dist/core/calendarGrid.d.ts +1 -0
  5. package/dist/core/calendarGrid.d.ts.map +1 -0
  6. package/dist/core/deriveAll.d.ts +2 -1
  7. package/dist/core/deriveAll.d.ts.map +1 -0
  8. package/dist/core/derivedFormula.d.ts +1 -0
  9. package/dist/core/derivedFormula.d.ts.map +1 -0
  10. package/dist/core/draft.d.ts +3 -2
  11. package/dist/core/draft.d.ts.map +1 -0
  12. package/dist/core/enumColors.d.ts +2 -1
  13. package/dist/core/enumColors.d.ts.map +1 -0
  14. package/dist/core/errorMessage.d.ts +5 -0
  15. package/dist/core/errorMessage.d.ts.map +1 -0
  16. package/dist/core/itemLabel.d.ts +2 -1
  17. package/dist/core/itemLabel.d.ts.map +1 -0
  18. package/dist/core/presentCollection.d.ts +2 -1
  19. package/dist/core/presentCollection.d.ts.map +1 -0
  20. package/dist/core/promptSafety.d.ts +2 -0
  21. package/dist/core/promptSafety.d.ts.map +1 -0
  22. package/dist/core/schema.d.ts +1 -0
  23. package/dist/core/schema.d.ts.map +1 -0
  24. package/dist/core/shortHexId.d.ts +9 -0
  25. package/dist/core/shortHexId.d.ts.map +1 -0
  26. package/dist/core/sortItems.d.ts +2 -1
  27. package/dist/core/sortItems.d.ts.map +1 -0
  28. package/dist/core/uiTypes.d.ts +54 -1
  29. package/dist/core/uiTypes.d.ts.map +1 -0
  30. package/dist/{deriveAll-B5spcUIb.js → deriveAll-BHcs1erT.js} +2 -20
  31. package/dist/deriveAll-BHcs1erT.js.map +1 -0
  32. package/dist/{deriveAll-Do0v6Xjb.cjs → deriveAll-BJ0Lvm1Q.cjs} +1 -31
  33. package/dist/deriveAll-BJ0Lvm1Q.cjs.map +1 -0
  34. package/dist/index.cjs +49 -712
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.ts +15 -11
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +4 -670
  39. package/dist/index.js.map +1 -1
  40. package/dist/promptSafety-BSO2gdsg.cjs +961 -0
  41. package/dist/promptSafety-BSO2gdsg.cjs.map +1 -0
  42. package/dist/promptSafety-DShN_VCG.js +698 -0
  43. package/dist/promptSafety-DShN_VCG.js.map +1 -0
  44. package/dist/schema-DyfSfVzh.js +21 -0
  45. package/dist/schema-DyfSfVzh.js.map +1 -0
  46. package/dist/schema-LrmrgW12.cjs +32 -0
  47. package/dist/schema-LrmrgW12.cjs.map +1 -0
  48. package/dist/server/atomic.d.ts +1 -0
  49. package/dist/server/atomic.d.ts.map +1 -0
  50. package/dist/server/delete.d.ts +2 -1
  51. package/dist/server/delete.d.ts.map +1 -0
  52. package/dist/server/derive.d.ts +4 -3
  53. package/dist/server/derive.d.ts.map +1 -0
  54. package/dist/server/discoveredCollection.d.ts +2 -1
  55. package/dist/server/discoveredCollection.d.ts.map +1 -0
  56. package/dist/server/discovery.d.ts +4 -3
  57. package/dist/server/discovery.d.ts.map +1 -0
  58. package/dist/server/host.d.ts +1 -0
  59. package/dist/server/host.d.ts.map +1 -0
  60. package/dist/server/index.d.ts +12 -11
  61. package/dist/server/index.d.ts.map +1 -0
  62. package/dist/server/io.d.ts +3 -2
  63. package/dist/server/io.d.ts.map +1 -0
  64. package/dist/server/paths.d.ts +1 -0
  65. package/dist/server/paths.d.ts.map +1 -0
  66. package/dist/server/spawn.d.ts +3 -2
  67. package/dist/server/spawn.d.ts.map +1 -0
  68. package/dist/server/templatePath.d.ts +1 -0
  69. package/dist/server/templatePath.d.ts.map +1 -0
  70. package/dist/server/util.d.ts +1 -0
  71. package/dist/server/util.d.ts.map +1 -0
  72. package/dist/server/validate.d.ts +3 -2
  73. package/dist/server/validate.d.ts.map +1 -0
  74. package/dist/server/views.d.ts +3 -2
  75. package/dist/server/views.d.ts.map +1 -0
  76. package/dist/server.cjs +6 -26
  77. package/dist/server.cjs.map +1 -1
  78. package/dist/server.js +2 -1
  79. package/dist/server.js.map +1 -1
  80. package/dist/style.css +2664 -0
  81. package/dist/vue/collectionViewMode.d.ts +12 -0
  82. package/dist/vue/collectionViewMode.d.ts.map +1 -0
  83. package/dist/vue/components/CollectionCalendarView.vue.d.ts +27 -0
  84. package/dist/vue/components/CollectionCalendarView.vue.d.ts.map +1 -0
  85. package/dist/vue/components/CollectionCustomView.vue.d.ts +9 -0
  86. package/dist/vue/components/CollectionCustomView.vue.d.ts.map +1 -0
  87. package/dist/vue/components/CollectionDayView.vue.d.ts +40 -0
  88. package/dist/vue/components/CollectionDayView.vue.d.ts.map +1 -0
  89. package/dist/vue/components/CollectionEmbedView.vue.d.ts +9 -0
  90. package/dist/vue/components/CollectionEmbedView.vue.d.ts.map +1 -0
  91. package/dist/vue/components/CollectionKanbanView.vue.d.ts +23 -0
  92. package/dist/vue/components/CollectionKanbanView.vue.d.ts.map +1 -0
  93. package/dist/vue/components/CollectionRecordModal.vue.d.ts +18 -0
  94. package/dist/vue/components/CollectionRecordModal.vue.d.ts.map +1 -0
  95. package/dist/vue/components/CollectionRecordPanel.vue.d.ts +46 -0
  96. package/dist/vue/components/CollectionRecordPanel.vue.d.ts.map +1 -0
  97. package/dist/vue/components/CollectionView.vue.d.ts +41 -0
  98. package/dist/vue/components/CollectionView.vue.d.ts.map +1 -0
  99. package/dist/vue/components/CollectionViewConfigModal.vue.d.ts +16 -0
  100. package/dist/vue/components/CollectionViewConfigModal.vue.d.ts.map +1 -0
  101. package/dist/vue/components/CollectionsIndexView.vue.d.ts +4 -0
  102. package/dist/vue/components/CollectionsIndexView.vue.d.ts.map +1 -0
  103. package/dist/vue/components/FeedsView.vue.d.ts +4 -0
  104. package/dist/vue/components/FeedsView.vue.d.ts.map +1 -0
  105. package/dist/vue/index.d.ts +16 -0
  106. package/dist/vue/index.d.ts.map +1 -0
  107. package/dist/vue/lang/de.d.ts +4 -0
  108. package/dist/vue/lang/de.d.ts.map +1 -0
  109. package/dist/vue/lang/en.d.ts +98 -0
  110. package/dist/vue/lang/en.d.ts.map +1 -0
  111. package/dist/vue/lang/es.d.ts +4 -0
  112. package/dist/vue/lang/es.d.ts.map +1 -0
  113. package/dist/vue/lang/fr.d.ts +4 -0
  114. package/dist/vue/lang/fr.d.ts.map +1 -0
  115. package/dist/vue/lang/index.d.ts +111 -0
  116. package/dist/vue/lang/index.d.ts.map +1 -0
  117. package/dist/vue/lang/ja.d.ts +4 -0
  118. package/dist/vue/lang/ja.d.ts.map +1 -0
  119. package/dist/vue/lang/ko.d.ts +4 -0
  120. package/dist/vue/lang/ko.d.ts.map +1 -0
  121. package/dist/vue/lang/ptBR.d.ts +4 -0
  122. package/dist/vue/lang/ptBR.d.ts.map +1 -0
  123. package/dist/vue/lang/zh.d.ts +4 -0
  124. package/dist/vue/lang/zh.d.ts.map +1 -0
  125. package/dist/vue/uiContext.d.ts +169 -0
  126. package/dist/vue/uiContext.d.ts.map +1 -0
  127. package/dist/vue/useCollectionRendering.d.ts +30 -0
  128. package/dist/vue/useCollectionRendering.d.ts.map +1 -0
  129. package/dist/vue.cjs +4713 -0
  130. package/dist/vue.cjs.map +1 -0
  131. package/dist/vue.js +4693 -0
  132. package/dist/vue.js.map +1 -0
  133. package/package.json +21 -6
  134. package/dist/deriveAll-B5spcUIb.js.map +0 -1
  135. package/dist/deriveAll-Do0v6Xjb.cjs.map +0 -1
@@ -0,0 +1,28 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ Object.defineProperty(exports, "__toESM", {
24
+ enumerable: true,
25
+ get: function() {
26
+ return __toESM;
27
+ }
28
+ });
@@ -32,3 +32,4 @@ export interface FieldWithWhen {
32
32
  * Purely presentational — a hidden field's stored value is never
33
33
  * altered, so toggling the gate back on restores it. */
34
34
  export declare function fieldVisible(field: FieldWithWhen, record: Record<string, unknown>): boolean;
35
+ //# sourceMappingURL=actionVisible.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actionVisible.d.ts","sourceRoot":"","sources":["../../src/core/actionVisible.ts"],"names":[],"mappings":"AAOA;;oCAEoC;AACpC,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,EAAE,CAAC;CACd;AAED;;;;;;wBAMwB;AACxB,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAKrG;AAED;+DAC+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED;yBACyB;AACzB,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAE9F;AAED;iEACiE;AACjE,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,aAAa,CAAC;CACtB;AAED;;;;yDAIyD;AACzD,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAE3F"}
@@ -118,3 +118,4 @@ export declare function assignLanes(blocks: readonly LaneSpan[]): LaneAssignment
118
118
  * component can feed it to `Intl.DateTimeFormat(locale, …)` for a localized
119
119
  * "April 2026" header without this module taking a locale dependency. */
120
120
  export declare function monthAnchorDate(year: number, month: number): Date;
121
+ //# sourceMappingURL=calendarGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendarGrid.d.ts","sourceRoot":"","sources":["../../src/core/calendarGrid.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { FormulaContext } from './derivedFormula';
1
+ import { type FormulaContext } from "./derivedFormula";
2
2
  /** Minimal field shape the derive loop needs — accepts both the client
3
3
  * FieldSpec and the server CollectionFieldSpec. */
4
4
  export interface DerivableFieldSpec {
@@ -36,3 +36,4 @@ export declare function resolveRowRefs(schema: DerivableSchema, record: Derivabl
36
36
  * formula would silently surface that value as if the host computed
37
37
  * it. */
38
38
  export declare function deriveAll(schema: DerivableSchema, base: DerivableRecord, refRecords: DeriveRefRecords): DerivableRecord;
39
+ //# sourceMappingURL=deriveAll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deriveAll.d.ts","sourceRoot":"","sources":["../../src/core/deriveAll.ts"],"names":[],"mappings":"AAaA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAExE;oDACoD;AACpD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC5C;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtD;;kEAEkE;AAClE,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC;AAE/E;;oEAEoE;AACpE,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,GAAG,WAAW,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAQlJ;AAED;;;;;;;;;;;;;UAaU;AACV,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,GAAG,eAAe,CAkBvH"}
@@ -16,3 +16,4 @@ export interface FormulaContext {
16
16
  refs?: Record<string, Record<string, unknown> | null>;
17
17
  }
18
18
  export declare function evaluateDerived(formula: string, ctx: FormulaContext): number | null;
19
+ //# sourceMappingURL=derivedFormula.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derivedFormula.d.ts","sourceRoot":"","sources":["../../src/core/derivedFormula.ts"],"names":[],"mappings":"AAkCA,MAAM,WAAW,cAAc;IAC7B;;;sCAGkC;IAClC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC;;;;;;;;qEAQiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;CACvD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAkBnF"}
@@ -1,5 +1,5 @@
1
- import { CollectionFieldSpec as FieldSpec, CollectionItem, CollectionSchema } from './schema';
2
- import { EditState, TableRowDraft } from './uiTypes';
1
+ import type { CollectionFieldSpec as FieldSpec, CollectionItem, CollectionSchema } from "./schema";
2
+ import type { EditState, TableRowDraft } from "./uiTypes";
3
3
  /** A fresh, empty row draft for a `table` field's sub-schema. */
4
4
  export declare function emptyRow(subFields: Record<string, FieldSpec>): TableRowDraft;
5
5
  /** Build a row draft from an existing persisted row. */
@@ -16,3 +16,4 @@ export declare function coerceInlineValue(field: FieldSpec, raw: boolean | strin
16
16
  export declare function buildUpdatedRecord(item: CollectionItem, key: string, value: unknown): CollectionItem;
17
17
  /** Human-readable label of the first missing required field, or null. */
18
18
  export declare function firstMissingRequiredField(draft: EditState, schema: CollectionSchema): string | null;
19
+ //# sourceMappingURL=draft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draft.d.ts","sourceRoot":"","sources":["../../src/core/draft.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,mBAAmB,IAAI,SAAS,EAAoC,cAAc,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACrI,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1D,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,aAAa,CAe5E;AAED,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,aAAa,CAkB9G;AAiCD,0DAA0D;AAC1D,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,GAAG,cAAc,CAiBxF;AAED;;gFAEgF;AAChF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAGlF;AAED;;qDAEqD;AACrD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,cAAc,CAMpG;AAmCD,yEAAyE;AACzE,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAOnG"}
@@ -1,4 +1,4 @@
1
- import { CollectionSchema } from './schema';
1
+ import type { CollectionSchema } from "./schema";
2
2
  export interface EnumColorClasses {
3
3
  /** Stat-card style: border + fill + text + hover. */
4
4
  card: string;
@@ -31,3 +31,4 @@ export declare function enumValueIndex(values: readonly string[] | undefined, va
31
31
  * amber, and every non-flagged value neutral grey.
32
32
  * - Any other enum: the standard palette by the value's declared index. */
33
33
  export declare function resolveEnumColor(schema: CollectionSchema, fieldKey: string, value: unknown): EnumColorClasses;
34
+ //# sourceMappingURL=enumColors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enumColors.d.ts","sourceRoot":"","sources":["../../src/core/enumColors.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAC;IACd,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;CAChB;AAsCD;4EAC4E;AAC5E,eAAO,MAAM,YAAY,EAAE,gBAK1B,CAAC;AAEF;0EAC0E;AAC1E,eAAO,MAAM,UAAU,EAAE,gBAKxB,CAAC;AAEF;uEACuE;AACvE,eAAO,MAAM,UAAU,EAAE,gBAKxB,CAAC;AAEF;;eAEe;AACf,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAGhE;AAED;4CAC4C;AAC5C,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAG5F;AASD;;;;4EAI4E;AAC5E,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAS7G"}
@@ -0,0 +1,5 @@
1
+ /** Normalise an unknown thrown value to a display string. The view layer's host
2
+ * capabilities already return normalised `{ ok: false, error }` results, so this
3
+ * only backs the defensive `catch` around an unexpected throw. */
4
+ export declare function errorMessage(err: unknown): string;
5
+ //# sourceMappingURL=errorMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errorMessage.d.ts","sourceRoot":"","sources":["../../src/core/errorMessage.ts"],"names":[],"mappings":"AAAA;;mEAEmE;AACnE,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEjD"}
@@ -1,4 +1,4 @@
1
- import { CollectionItem, CollectionSchema } from './schema';
1
+ import type { CollectionItem, CollectionSchema } from "./schema";
2
2
  /** Which field labels a record: the schema's explicit `displayField`, else the
3
3
  * first non-primary text-like field (so a collection without a displayField
4
4
  * shows e.g. the title rather than the opaque primaryKey), else null → the
@@ -10,3 +10,4 @@ export declare function itemIdOf(item: CollectionItem, schema: CollectionSchema)
10
10
  * primary key. Pass the result of `labelFieldFor(schema)` as `labelField`
11
11
  * (compute it once per render rather than per item). */
12
12
  export declare function itemLabelOf(item: CollectionItem, schema: CollectionSchema, labelField: string | null): string;
13
+ //# sourceMappingURL=itemLabel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"itemLabel.d.ts","sourceRoot":"","sources":["../../src/core/itemLabel.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAKjE;;;kDAGkD;AAClD,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,GAAG,IAAI,CAMrE;AAED,gDAAgD;AAChD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAE/E;AAED;;yDAEyD;AACzD,wBAAgB,WAAW,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAY7G"}
@@ -1,4 +1,4 @@
1
- import { ToolContext, ToolDefinition, ToolResult } from 'gui-chat-protocol';
1
+ import type { ToolContext, ToolDefinition, ToolResult } from "gui-chat-protocol";
2
2
  export declare const TOOL_NAME = "presentCollection";
3
3
  /** Render payload carried in the tool result's `data` field; the View mounts
4
4
  * off these. Same shape as the tool args. */
@@ -11,3 +11,4 @@ export interface PresentCollectionData {
11
11
  export type PresentCollectionArgs = PresentCollectionData;
12
12
  export declare const TOOL_DEFINITION: ToolDefinition;
13
13
  export declare const executePresentCollection: (_context: ToolContext, args: PresentCollectionArgs) => Promise<ToolResult<PresentCollectionData, PresentCollectionData>>;
14
+ //# sourceMappingURL=presentCollection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentCollection.d.ts","sourceRoot":"","sources":["../../src/core/presentCollection.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEjF,eAAO,MAAM,SAAS,sBAAsB,CAAC;AAE7C;8CAC8C;AAC9C,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,cAAc,EAAE,MAAM,CAAC;IACvB,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAE1D,eAAO,MAAM,eAAe,EAAE,cAoB7B,CAAC;AAEF,eAAO,MAAM,wBAAwB,GACnC,UAAU,WAAW,EACrB,MAAM,qBAAqB,KAC1B,OAAO,CAAC,UAAU,CAAC,qBAAqB,EAAE,qBAAqB,CAAC,CAoBlE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function defangForPrompt(value: string): string;
2
+ //# sourceMappingURL=promptSafety.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptSafety.d.ts","sourceRoot":"","sources":["../../src/core/promptSafety.ts"],"names":[],"mappings":"AAUA,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD"}
@@ -331,3 +331,4 @@ export interface CollectionDetail extends CollectionSummary {
331
331
  schema: CollectionSchema;
332
332
  }
333
333
  export type CollectionItem = Record<string, unknown>;
334
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/core/schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 8-char hex id — short, slug-safe, and editable. Produces the same id *shape*
3
+ * as the server's `generateItemId()` (8 hex chars) so a UI-created collection
4
+ * record looks like one the server would have generated for a form submitted
5
+ * with a blank primary key. The source of randomness differs (UUID-derived here
6
+ * vs `randomBytes` on the server); only the shape is intentionally shared.
7
+ */
8
+ export declare function shortHexId(): string;
9
+ //# sourceMappingURL=shortHexId.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shortHexId.d.ts","sourceRoot":"","sources":["../../src/core/shortHexId.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC"}
@@ -1,4 +1,4 @@
1
- import { CollectionItem, CollectionFieldSpec } from './schema';
1
+ import type { CollectionItem, CollectionFieldSpec } from "./schema";
2
2
  export type SortDirection = "asc" | "desc";
3
3
  export interface SortState {
4
4
  /** Field key of the single active sort column. */
@@ -27,3 +27,4 @@ export declare function compareSortValues(left: SortValue, right: SortValue): nu
27
27
  /** Stable sort of `items` by `valueOf`. Empties always last; ties hold
28
28
  * source order. Returns a new array (does not mutate `items`). */
29
29
  export declare function sortItems(items: readonly CollectionItem[], direction: SortDirection, valueOf: (item: CollectionItem) => SortValue): CollectionItem[];
30
+ //# sourceMappingURL=sortItems.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sortItems.d.ts","sourceRoot":"","sources":["../../src/core/sortItems.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAuB,MAAM,UAAU,CAAC;AAEzF,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED;kEACkE;AAClE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAOD,wBAAgB,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAEnE;AAED,0DAA0D;AAC1D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,GAAG,aAAa,GAAG,IAAI,CAIrF;AAID,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,CAIxD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,CAIvD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,CAKrD;AAED;8DAC8D;AAC9D,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAAE,GAAG,EAAE,OAAO,GAAG,SAAS,CAI5F;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,CAEzD;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAK3E;AAED;mEACmE;AACnE,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,cAAc,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,SAAS,GAAG,cAAc,EAAE,CAapJ"}
@@ -1,4 +1,4 @@
1
- import { CollectionDetail, CollectionItem, CollectionSchema } from './schema';
1
+ import type { CollectionDetail, CollectionItem, CollectionSchema, CollectionSummary } from "./schema";
2
2
  /** A record file the server couldn't load or that violates the schema —
3
3
  * silently skipped at read time (mirror of the server `RecordIssue`). */
4
4
  export interface CollectionRecordIssue {
@@ -52,3 +52,56 @@ export interface RefOption {
52
52
  slug: string;
53
53
  display: string;
54
54
  }
55
+ export interface EmbedRow {
56
+ /** Sub-field key (used for `:key` + testids). */
57
+ key: string;
58
+ label: string;
59
+ /** Sub-field type — the renderer branches on "boolean" / "markdown". */
60
+ type: string;
61
+ /** Raw value, used only for the boolean check / em-dash. */
62
+ value: unknown;
63
+ /** Pre-formatted string for every non-boolean render path. */
64
+ display: string;
65
+ }
66
+ export interface EmbedView {
67
+ /** False when the target collection has no record with the embed's `id`
68
+ * (or the target couldn't be loaded) — the renderer shows a "missing"
69
+ * message + a link to create it. */
70
+ found: boolean;
71
+ rows: EmbedRow[];
72
+ /** Target collection slug, for the "create it" link + message. */
73
+ targetSlug: string;
74
+ /** The fixed record id the embed points at, for the message. */
75
+ recordId: string;
76
+ }
77
+ /** Active-notification severity for a record, used to accent flagged cards
78
+ * (kanban left-stripe, etc.). The host computes these from its notifier and
79
+ * passes them in; this is the structural type the view layer accepts. The host's
80
+ * own `NotifierSeverity` is the identical union, so its maps pass through. */
81
+ export type CollectionNotifySeverity = "info" | "nudge" | "urgent";
82
+ /** Response of the collections list endpoint (`API_ROUTES.collections.list`). */
83
+ export interface CollectionsListResponse {
84
+ collections: CollectionSummary[];
85
+ }
86
+ /** A row in the feeds index — a data-source collection from the workspace's
87
+ * `feeds/` registry. */
88
+ export interface FeedSummary {
89
+ slug: string;
90
+ title: string;
91
+ icon: string;
92
+ kind: string;
93
+ schedule: string;
94
+ lastFetchedAt: string | null;
95
+ }
96
+ /** Response of the feeds list endpoint (`API_ROUTES.feeds.list`). */
97
+ export interface FeedsListResponse {
98
+ feeds: FeedSummary[];
99
+ }
100
+ /** The `{slug,title,icon}` triple the index pages reconcile pinned shortcuts
101
+ * against (prune dead slugs, refresh stale labels). */
102
+ export interface CollectionShortcutInfo {
103
+ slug: string;
104
+ title: string;
105
+ icon: string;
106
+ }
107
+ //# sourceMappingURL=uiTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uiTypes.d.ts","sourceRoot":"","sources":["../../src/core/uiTypes.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,3 @@
1
- //#region src/core/schema.ts
2
- /** Retriever kinds a Feed's `ingest.kind` may declare. The host's feeds engine
3
- * dispatches on these; they live here (with the schema contract) so the schema
4
- * validator can enforce them. The host re-exports these from
5
- * `server/workspace/feeds/ingestTypes.ts`. */
6
- var INGEST_KINDS = [
7
- "rss",
8
- "atom",
9
- "http-json"
10
- ];
11
- /** Refresh cadences a Feed's `ingest.schedule` may declare. */
12
- var FEED_SCHEDULES = [
13
- "hourly",
14
- "daily",
15
- "weekly",
16
- "on-demand"
17
- ];
18
- //#endregion
19
1
  //#region src/core/derivedFormula.ts
20
2
  function evaluateDerived(formula, ctx) {
21
3
  let tokens;
@@ -355,6 +337,6 @@ function deriveAll(schema, base, refRecords) {
355
337
  return enriched;
356
338
  }
357
339
  //#endregion
358
- export { INGEST_KINDS as a, FEED_SCHEDULES as i, resolveRowRefs as n, evaluateDerived as r, deriveAll as t };
340
+ export { resolveRowRefs as n, evaluateDerived as r, deriveAll as t };
359
341
 
360
- //# sourceMappingURL=deriveAll-B5spcUIb.js.map
342
+ //# sourceMappingURL=deriveAll-BHcs1erT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deriveAll-BHcs1erT.js","names":[],"sources":["../src/core/derivedFormula.ts","../src/core/deriveAll.ts"],"sourcesContent":["// Tiny expression evaluator for the `derived` field type on\n// schema-driven collections (see plans/done/feat-mc-invoice.md).\n//\n// Grammar (recursive-descent, no precedence climbing — six\n// non-terminals total):\n//\n// expr := term (('+' | '-') term)*\n// term := factor (('*' | '/') factor)*\n// factor := number | sumCall | refAccess | identifier | '(' expr ')'\n// sumCall:= 'sum' '(' sumArg ')'\n// sumArg := tableCol (('*' | '/') tableCol)* // e.g. lineItems[].quantity * lineItems[].rate\n// tableCol := identifier '[]' '.' identifier\n// refAccess := identifier '.' identifier // e.g. ticker.price — deref a ref field into its target record\n//\n// `identifier` accepts top-level field names (single segment).\n// Inside `sumArg`, identifiers are the `<table>[].col` form.\n// A two-segment `<field>.<col>` at factor level is a *ref deref*:\n// `<field>` must be a `ref`-typed field on this record (its stored\n// value is the target item's slug), and `<col>` is a numeric column\n// read from that target record. The caller resolves the target into\n// `ctx.refs` (it owns the schema + the loaded target collection);\n// the evaluator stays pure and never does I/O.\n//\n// What's deliberately NOT supported (and would parse-error rather\n// than silently misbehave):\n// - String literals, boolean operators, comparisons, conditionals\n// - Nested function calls beyond `sum(...)`\n// - Anything in the record that isn't a number / table-of-objects\n//\n// All evaluation is pure — no eval(), no Function constructor.\n// Returns `null` on any failure (parse error, unbound identifier,\n// non-finite arithmetic). The caller renders `null` as em-dash in\n// the table cell + form display.\n\nexport interface FormulaContext {\n /** The record being evaluated. For derived fields in the form,\n * this is the live draft (text + table both converted via the\n * same `draftToRecord` pipeline). For the main table cell,\n * this is the persisted item. */\n record: Record<string, unknown>;\n /** Resolved ref-target records for THIS row, keyed by the local\n * `ref` field name. The caller (which has the schema + the linked\n * collection's items loaded) maps each ref field's stored slug to\n * the full target record and passes it here, so a `<field>.<col>`\n * formula can read a numeric column off the referenced record\n * (e.g. `shares * ticker.price`). A missing key or `null` value\n * (unknown field / dangling slug) makes that deref evaluate to\n * NaN → the whole formula returns `null` → em-dash, consistent\n * with every other failure mode. Absent ⇒ no refs available. */\n refs?: Record<string, Record<string, unknown> | null>;\n}\n\nexport function evaluateDerived(formula: string, ctx: FormulaContext): number | null {\n let tokens: Token[];\n try {\n tokens = tokenize(formula);\n } catch {\n return null;\n }\n // eslint-disable-next-line @typescript-eslint/no-use-before-define -- Parser class is defined later in the file (grouped with its AST + evaluator); evaluateDerived runs after module init so the TDZ concern doesn't apply.\n const parser = new Parser(tokens);\n let ast: Node;\n try {\n ast = parser.parseExpr();\n if (!parser.atEnd()) return null; // trailing junk\n } catch {\n return null;\n }\n const value = evaluate(ast, ctx);\n return Number.isFinite(value) ? value : null;\n}\n\n// ─── Tokens ────────────────────────────────────────────────\n\ntype TokenKind = \"number\" | \"ident\" | \"(\" | \")\" | \"+\" | \"-\" | \"*\" | \"/\" | \"[]\" | \".\";\n\ninterface Token {\n kind: TokenKind;\n value?: string | number;\n}\n\nconst SINGLE_CHAR_PUNCT = new Set<TokenKind>([\"(\", \")\", \"+\", \"-\", \"*\", \"/\", \".\"]);\n\ninterface Cursor {\n input: string;\n index: number;\n}\n\nfunction consumeWhitespace(cur: Cursor): boolean {\n const char = cur.input[cur.index];\n if (char === \" \" || char === \"\\t\" || char === \"\\n\") {\n cur.index++;\n return true;\n }\n return false;\n}\n\nfunction consumeNumber(cur: Cursor): Token | null {\n const char = cur.input[cur.index] ?? \"\";\n const next = cur.input[cur.index + 1] ?? \"\";\n if (!isDigit(char) && !(char === \".\" && isDigit(next))) return null;\n let raw = \"\";\n while (cur.index < cur.input.length) {\n const here = cur.input[cur.index] ?? \"\";\n if (!isDigit(here) && here !== \".\") break;\n raw += here;\n cur.index++;\n }\n const num = Number(raw);\n if (!Number.isFinite(num)) throw new Error(\"bad number\");\n return { kind: \"number\", value: num };\n}\n\nfunction consumeIdent(cur: Cursor): Token | null {\n const char = cur.input[cur.index] ?? \"\";\n if (!isIdentStart(char)) return null;\n let raw = \"\";\n while (cur.index < cur.input.length && isIdentChar(cur.input[cur.index] ?? \"\")) {\n raw += cur.input[cur.index];\n cur.index++;\n }\n return { kind: \"ident\", value: raw };\n}\n\nfunction consumePunct(cur: Cursor): Token | null {\n const char = cur.input[cur.index] ?? \"\";\n if (char === \"[\" && cur.input[cur.index + 1] === \"]\") {\n cur.index += 2;\n return { kind: \"[]\" };\n }\n if (SINGLE_CHAR_PUNCT.has(char as TokenKind)) {\n cur.index++;\n return { kind: char as TokenKind };\n }\n return null;\n}\n\nfunction tokenize(input: string): Token[] {\n const tokens: Token[] = [];\n const cur: Cursor = { input, index: 0 };\n while (cur.index < input.length) {\n if (consumeWhitespace(cur)) continue;\n // Number FIRST so a leading-dot literal (`.25`) isn't split by\n // the `.` punctuation branch.\n const numTok = consumeNumber(cur);\n if (numTok) {\n tokens.push(numTok);\n continue;\n }\n const punctTok = consumePunct(cur);\n if (punctTok) {\n tokens.push(punctTok);\n continue;\n }\n const identTok = consumeIdent(cur);\n if (identTok) {\n tokens.push(identTok);\n continue;\n }\n throw new Error(`unexpected char ${input[cur.index]}`);\n }\n return tokens;\n}\n\nfunction isDigit(char: string): boolean {\n return char >= \"0\" && char <= \"9\";\n}\nfunction isIdentStart(char: string): boolean {\n return (char >= \"a\" && char <= \"z\") || (char >= \"A\" && char <= \"Z\") || char === \"_\";\n}\nfunction isIdentChar(char: string): boolean {\n return isIdentStart(char) || isDigit(char);\n}\n\n// ─── AST + Parser ───────────────────────────────────────────\n\ntype Node =\n | { kind: \"num\"; value: number }\n | { kind: \"ident\"; name: string }\n | { kind: \"ref\"; field: string; col: string }\n | { kind: \"binop\"; operator: \"+\" | \"-\" | \"*\" | \"/\"; left: Node; right: Node }\n | { kind: \"sum\"; arg: SumArg };\n\ninterface SumArg {\n // factors multiplied/divided together; each is a (tableName, colName) ref into a row.\n factors: { table: string; col: string }[];\n /** Operators between factors: length = factors.length - 1; each\n * is \"*\" or \"/\". For a single-factor sum (`sum(lineItems[].amount)`)\n * this is empty. */\n operators: (\"*\" | \"/\")[];\n}\n\nclass Parser {\n private cursor = 0;\n constructor(private readonly tokens: Token[]) {}\n\n atEnd(): boolean {\n return this.cursor >= this.tokens.length;\n }\n private peek(): Token | undefined {\n return this.tokens[this.cursor];\n }\n private consume(): Token {\n const tok = this.tokens[this.cursor++];\n if (!tok) throw new Error(\"unexpected end of input\");\n return tok;\n }\n private expect(kind: TokenKind): Token {\n const tok = this.consume();\n if (tok.kind !== kind) throw new Error(`expected ${kind}, got ${tok.kind}`);\n return tok;\n }\n\n parseExpr(): Node {\n let left = this.parseTerm();\n while (this.peek()?.kind === \"+\" || this.peek()?.kind === \"-\") {\n const operator = this.consume().kind as \"+\" | \"-\";\n const right = this.parseTerm();\n left = { kind: \"binop\", operator, left, right };\n }\n return left;\n }\n\n private parseTerm(): Node {\n let left = this.parseFactor();\n while (this.peek()?.kind === \"*\" || this.peek()?.kind === \"/\") {\n const operator = this.consume().kind as \"*\" | \"/\";\n const right = this.parseFactor();\n left = { kind: \"binop\", operator, left, right };\n }\n return left;\n }\n\n private parseFactor(): Node {\n const tok = this.peek();\n if (!tok) throw new Error(\"unexpected end in factor\");\n if (tok.kind === \"number\") {\n this.consume();\n return { kind: \"num\", value: tok.value as number };\n }\n if (tok.kind === \"(\") {\n this.consume();\n const inner = this.parseExpr();\n this.expect(\")\");\n return inner;\n }\n if (tok.kind === \"ident\") {\n const name = (tok.value as string) ?? \"\";\n // sum(...) — only function call we support\n if (name === \"sum\" && this.tokens[this.cursor + 1]?.kind === \"(\") {\n this.consume(); // ident\n this.expect(\"(\");\n const arg = this.parseSumArg();\n this.expect(\")\");\n return { kind: \"sum\", arg };\n }\n this.consume(); // ident\n // ref deref: `<field>.<col>` (e.g. ticker.price). The table-row\n // form `<table>[].col` only appears inside sum(), so a `.`\n // immediately after a top-level ident is unambiguously a ref\n // dereference here.\n if (this.peek()?.kind === \".\") {\n this.consume(); // '.'\n const col = this.expect(\"ident\");\n return { kind: \"ref\", field: name, col: col.value as string };\n }\n return { kind: \"ident\", name };\n }\n throw new Error(`unexpected token ${tok.kind} in factor`);\n }\n\n private parseSumArg(): SumArg {\n const factors: { table: string; col: string }[] = [];\n const operators: (\"*\" | \"/\")[] = [];\n factors.push(this.parseTableCol());\n while (this.peek()?.kind === \"*\" || this.peek()?.kind === \"/\") {\n const operator = this.consume().kind as \"*\" | \"/\";\n operators.push(operator);\n factors.push(this.parseTableCol());\n }\n return { factors, operators };\n }\n\n private parseTableCol(): { table: string; col: string } {\n const tableTok = this.expect(\"ident\");\n this.expect(\"[]\");\n this.expect(\".\");\n const colTok = this.expect(\"ident\");\n return { table: tableTok.value as string, col: colTok.value as string };\n }\n}\n\n// ─── Evaluator ──────────────────────────────────────────────\n\nfunction evaluate(node: Node, ctx: FormulaContext): number {\n if (node.kind === \"num\") return node.value;\n if (node.kind === \"ident\") {\n const raw = ctx.record[node.name];\n return toFiniteNumber(raw);\n }\n if (node.kind === \"ref\") {\n // `<field>.<col>`: read `col` off the resolved target record the\n // caller put in ctx.refs. Unknown field / dangling slug → null →\n // NaN, so the whole formula fails soft to an em-dash.\n const target = ctx.refs?.[node.field] ?? null;\n if (!target) return Number.NaN;\n return toFiniteNumber(target[node.col]);\n }\n if (node.kind === \"binop\") {\n const left = evaluate(node.left, ctx);\n const right = evaluate(node.right, ctx);\n return applyBinop(node.operator, left, right);\n }\n if (node.kind === \"sum\") {\n return evaluateSum(node.arg, ctx);\n }\n // Exhaustive — TS narrows above branches but throw keeps runtime honest.\n throw new Error(`unknown node`);\n}\n\nfunction applyBinop(operator: \"+\" | \"-\" | \"*\" | \"/\", left: number, right: number): number {\n if (!Number.isFinite(left) || !Number.isFinite(right)) return Number.NaN;\n if (operator === \"+\") return left + right;\n if (operator === \"-\") return left - right;\n if (operator === \"*\") return left * right;\n // operator === \"/\"\n if (right === 0) return Number.NaN;\n return left / right;\n}\n\nfunction evaluateSum(arg: SumArg, ctx: FormulaContext): number {\n if (arg.factors.length === 0) return 0;\n const tableName = arg.factors[0].table;\n // All factors must reference the SAME table (you can't multiply\n // a row from lineItems against a row from another table — the\n // semantics would be ambiguous). Reject mismatch.\n for (const factor of arg.factors) {\n if (factor.table !== tableName) return Number.NaN;\n }\n const rows = ctx.record[tableName];\n if (!Array.isArray(rows)) return 0;\n let total = 0;\n for (const row of rows) {\n if (!row || typeof row !== \"object\") continue;\n let product = toFiniteNumber((row as Record<string, unknown>)[arg.factors[0].col]);\n if (!Number.isFinite(product)) return Number.NaN;\n for (let i = 1; i < arg.factors.length; i++) {\n const value = toFiniteNumber((row as Record<string, unknown>)[arg.factors[i].col]);\n if (!Number.isFinite(value)) return Number.NaN;\n product = applyBinop(arg.operators[i - 1], product, value);\n }\n total += product;\n }\n return total;\n}\n\nfunction toFiniteNumber(value: unknown): number {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : Number.NaN;\n if (typeof value === \"string\" && value.length > 0) {\n const num = Number(value);\n return Number.isFinite(num) ? num : Number.NaN;\n }\n return Number.NaN;\n}\n","// The derived-field saturation loop for schema-driven collections,\n// extracted from `composables/collections/useCollectionRendering.ts` so\n// the server (manageCollection getItems enrichment) and the client\n// (table cells, form display) evaluate formulas through ONE\n// implementation — if the two ever diverged, the UI and the LLM would\n// disagree on a number. Pure module: no Vue, no I/O.\n//\n// Like `actionVisible.ts`, the input types are minimal structural\n// shapes so both the client `FieldSpec`/`CollectionSchema`\n// (src/components/collectionTypes.ts) and the server\n// `CollectionFieldSpec`/`CollectionSchema`\n// (server/workspace/collections/types.ts) satisfy them as-is.\n\nimport { evaluateDerived, type FormulaContext } from \"./derivedFormula\";\n\n/** Minimal field shape the derive loop needs — accepts both the client\n * FieldSpec and the server CollectionFieldSpec. */\nexport interface DerivableFieldSpec {\n type: string;\n /** When type === \"ref\": slug of the target collection. */\n to?: string;\n /** When type === \"derived\": formula evaluated against the record. */\n formula?: string;\n}\n\n/** Minimal schema shape: just the ordered field map. */\nexport interface DerivableSchema {\n fields: Record<string, DerivableFieldSpec>;\n}\n\nexport type DerivableRecord = Record<string, unknown>;\n\n/** Per-target-collection cache of loaded referenced records:\n * target collection slug → item slug → full record. Mirrors the\n * client's `RefRecordCache` / the server's enrichment loader. */\nexport type DeriveRefRecords = Record<string, Record<string, DerivableRecord>>;\n\n/** Map each `ref` field's stored slug to its loaded target record (or\n * null when dangling / not loaded), keyed by the LOCAL field name —\n * the shape `evaluateDerived` reads for `<field>.<col>` derefs. */\nexport function resolveRowRefs(schema: DerivableSchema, record: DerivableRecord, refRecords: DeriveRefRecords): NonNullable<FormulaContext[\"refs\"]> {\n const refs: NonNullable<FormulaContext[\"refs\"]> = {};\n for (const [key, field] of Object.entries(schema.fields)) {\n if (field.type !== \"ref\" || !field.to) continue;\n const slug = record[key];\n refs[key] = typeof slug === \"string\" ? (refRecords[field.to]?.[slug] ?? null) : null;\n }\n return refs;\n}\n\n/** Evaluate every `derived` field against `base`, saturating so a\n * derived field can read another derived field computed in an earlier\n * pass (`subtotal → tax → total` converges in ≤ field-count passes).\n * Cycles can't loop forever — passes are bounded by the number of\n * derived fields and the loop breaks as soon as a pass changes\n * nothing. Failed formulas stay ABSENT (the UI renders them as\n * em-dash). Returns a copy; `base` is never mutated.\n *\n * Derived keys already present in `base` are stripped before\n * evaluation: computed output is host-truth, never persisted-input\n * fallback. A record JSON can carry a stale (or forged) derived value\n * — raw Write/Edit, legacy data — and without the strip, a failing\n * formula would silently surface that value as if the host computed\n * it. */\nexport function deriveAll(schema: DerivableSchema, base: DerivableRecord, refRecords: DeriveRefRecords): DerivableRecord {\n const derivedKeys = new Set(Object.keys(schema.fields).filter((key) => schema.fields[key]?.type === \"derived\"));\n const enriched: DerivableRecord = Object.fromEntries(Object.entries(base).filter(([key]) => !derivedKeys.has(key)));\n const refs = resolveRowRefs(schema, base, refRecords);\n const maxPasses = Object.values(schema.fields).filter((field) => field.type === \"derived\").length;\n for (let pass = 0; pass < maxPasses; pass++) {\n let mutated = false;\n for (const [key, field] of Object.entries(schema.fields)) {\n if (field.type !== \"derived\" || !field.formula) continue;\n const next = evaluateDerived(field.formula, { record: enriched, refs });\n if (next !== null && enriched[key] !== next) {\n enriched[key] = next;\n mutated = true;\n }\n }\n if (!mutated) break;\n }\n return enriched;\n}\n"],"mappings":"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"}
@@ -1,21 +1,3 @@
1
- //#region src/core/schema.ts
2
- /** Retriever kinds a Feed's `ingest.kind` may declare. The host's feeds engine
3
- * dispatches on these; they live here (with the schema contract) so the schema
4
- * validator can enforce them. The host re-exports these from
5
- * `server/workspace/feeds/ingestTypes.ts`. */
6
- var INGEST_KINDS = [
7
- "rss",
8
- "atom",
9
- "http-json"
10
- ];
11
- /** Refresh cadences a Feed's `ingest.schedule` may declare. */
12
- var FEED_SCHEDULES = [
13
- "hourly",
14
- "daily",
15
- "weekly",
16
- "on-demand"
17
- ];
18
- //#endregion
19
1
  //#region src/core/derivedFormula.ts
20
2
  function evaluateDerived(formula, ctx) {
21
3
  let tokens;
@@ -355,18 +337,6 @@ function deriveAll(schema, base, refRecords) {
355
337
  return enriched;
356
338
  }
357
339
  //#endregion
358
- Object.defineProperty(exports, "FEED_SCHEDULES", {
359
- enumerable: true,
360
- get: function() {
361
- return FEED_SCHEDULES;
362
- }
363
- });
364
- Object.defineProperty(exports, "INGEST_KINDS", {
365
- enumerable: true,
366
- get: function() {
367
- return INGEST_KINDS;
368
- }
369
- });
370
340
  Object.defineProperty(exports, "deriveAll", {
371
341
  enumerable: true,
372
342
  get: function() {
@@ -386,4 +356,4 @@ Object.defineProperty(exports, "resolveRowRefs", {
386
356
  }
387
357
  });
388
358
 
389
- //# sourceMappingURL=deriveAll-Do0v6Xjb.cjs.map
359
+ //# sourceMappingURL=deriveAll-BJ0Lvm1Q.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deriveAll-BJ0Lvm1Q.cjs","names":[],"sources":["../src/core/derivedFormula.ts","../src/core/deriveAll.ts"],"sourcesContent":["// Tiny expression evaluator for the `derived` field type on\n// schema-driven collections (see plans/done/feat-mc-invoice.md).\n//\n// Grammar (recursive-descent, no precedence climbing — six\n// non-terminals total):\n//\n// expr := term (('+' | '-') term)*\n// term := factor (('*' | '/') factor)*\n// factor := number | sumCall | refAccess | identifier | '(' expr ')'\n// sumCall:= 'sum' '(' sumArg ')'\n// sumArg := tableCol (('*' | '/') tableCol)* // e.g. lineItems[].quantity * lineItems[].rate\n// tableCol := identifier '[]' '.' identifier\n// refAccess := identifier '.' identifier // e.g. ticker.price — deref a ref field into its target record\n//\n// `identifier` accepts top-level field names (single segment).\n// Inside `sumArg`, identifiers are the `<table>[].col` form.\n// A two-segment `<field>.<col>` at factor level is a *ref deref*:\n// `<field>` must be a `ref`-typed field on this record (its stored\n// value is the target item's slug), and `<col>` is a numeric column\n// read from that target record. The caller resolves the target into\n// `ctx.refs` (it owns the schema + the loaded target collection);\n// the evaluator stays pure and never does I/O.\n//\n// What's deliberately NOT supported (and would parse-error rather\n// than silently misbehave):\n// - String literals, boolean operators, comparisons, conditionals\n// - Nested function calls beyond `sum(...)`\n// - Anything in the record that isn't a number / table-of-objects\n//\n// All evaluation is pure — no eval(), no Function constructor.\n// Returns `null` on any failure (parse error, unbound identifier,\n// non-finite arithmetic). The caller renders `null` as em-dash in\n// the table cell + form display.\n\nexport interface FormulaContext {\n /** The record being evaluated. For derived fields in the form,\n * this is the live draft (text + table both converted via the\n * same `draftToRecord` pipeline). For the main table cell,\n * this is the persisted item. */\n record: Record<string, unknown>;\n /** Resolved ref-target records for THIS row, keyed by the local\n * `ref` field name. The caller (which has the schema + the linked\n * collection's items loaded) maps each ref field's stored slug to\n * the full target record and passes it here, so a `<field>.<col>`\n * formula can read a numeric column off the referenced record\n * (e.g. `shares * ticker.price`). A missing key or `null` value\n * (unknown field / dangling slug) makes that deref evaluate to\n * NaN → the whole formula returns `null` → em-dash, consistent\n * with every other failure mode. Absent ⇒ no refs available. */\n refs?: Record<string, Record<string, unknown> | null>;\n}\n\nexport function evaluateDerived(formula: string, ctx: FormulaContext): number | null {\n let tokens: Token[];\n try {\n tokens = tokenize(formula);\n } catch {\n return null;\n }\n // eslint-disable-next-line @typescript-eslint/no-use-before-define -- Parser class is defined later in the file (grouped with its AST + evaluator); evaluateDerived runs after module init so the TDZ concern doesn't apply.\n const parser = new Parser(tokens);\n let ast: Node;\n try {\n ast = parser.parseExpr();\n if (!parser.atEnd()) return null; // trailing junk\n } catch {\n return null;\n }\n const value = evaluate(ast, ctx);\n return Number.isFinite(value) ? value : null;\n}\n\n// ─── Tokens ────────────────────────────────────────────────\n\ntype TokenKind = \"number\" | \"ident\" | \"(\" | \")\" | \"+\" | \"-\" | \"*\" | \"/\" | \"[]\" | \".\";\n\ninterface Token {\n kind: TokenKind;\n value?: string | number;\n}\n\nconst SINGLE_CHAR_PUNCT = new Set<TokenKind>([\"(\", \")\", \"+\", \"-\", \"*\", \"/\", \".\"]);\n\ninterface Cursor {\n input: string;\n index: number;\n}\n\nfunction consumeWhitespace(cur: Cursor): boolean {\n const char = cur.input[cur.index];\n if (char === \" \" || char === \"\\t\" || char === \"\\n\") {\n cur.index++;\n return true;\n }\n return false;\n}\n\nfunction consumeNumber(cur: Cursor): Token | null {\n const char = cur.input[cur.index] ?? \"\";\n const next = cur.input[cur.index + 1] ?? \"\";\n if (!isDigit(char) && !(char === \".\" && isDigit(next))) return null;\n let raw = \"\";\n while (cur.index < cur.input.length) {\n const here = cur.input[cur.index] ?? \"\";\n if (!isDigit(here) && here !== \".\") break;\n raw += here;\n cur.index++;\n }\n const num = Number(raw);\n if (!Number.isFinite(num)) throw new Error(\"bad number\");\n return { kind: \"number\", value: num };\n}\n\nfunction consumeIdent(cur: Cursor): Token | null {\n const char = cur.input[cur.index] ?? \"\";\n if (!isIdentStart(char)) return null;\n let raw = \"\";\n while (cur.index < cur.input.length && isIdentChar(cur.input[cur.index] ?? \"\")) {\n raw += cur.input[cur.index];\n cur.index++;\n }\n return { kind: \"ident\", value: raw };\n}\n\nfunction consumePunct(cur: Cursor): Token | null {\n const char = cur.input[cur.index] ?? \"\";\n if (char === \"[\" && cur.input[cur.index + 1] === \"]\") {\n cur.index += 2;\n return { kind: \"[]\" };\n }\n if (SINGLE_CHAR_PUNCT.has(char as TokenKind)) {\n cur.index++;\n return { kind: char as TokenKind };\n }\n return null;\n}\n\nfunction tokenize(input: string): Token[] {\n const tokens: Token[] = [];\n const cur: Cursor = { input, index: 0 };\n while (cur.index < input.length) {\n if (consumeWhitespace(cur)) continue;\n // Number FIRST so a leading-dot literal (`.25`) isn't split by\n // the `.` punctuation branch.\n const numTok = consumeNumber(cur);\n if (numTok) {\n tokens.push(numTok);\n continue;\n }\n const punctTok = consumePunct(cur);\n if (punctTok) {\n tokens.push(punctTok);\n continue;\n }\n const identTok = consumeIdent(cur);\n if (identTok) {\n tokens.push(identTok);\n continue;\n }\n throw new Error(`unexpected char ${input[cur.index]}`);\n }\n return tokens;\n}\n\nfunction isDigit(char: string): boolean {\n return char >= \"0\" && char <= \"9\";\n}\nfunction isIdentStart(char: string): boolean {\n return (char >= \"a\" && char <= \"z\") || (char >= \"A\" && char <= \"Z\") || char === \"_\";\n}\nfunction isIdentChar(char: string): boolean {\n return isIdentStart(char) || isDigit(char);\n}\n\n// ─── AST + Parser ───────────────────────────────────────────\n\ntype Node =\n | { kind: \"num\"; value: number }\n | { kind: \"ident\"; name: string }\n | { kind: \"ref\"; field: string; col: string }\n | { kind: \"binop\"; operator: \"+\" | \"-\" | \"*\" | \"/\"; left: Node; right: Node }\n | { kind: \"sum\"; arg: SumArg };\n\ninterface SumArg {\n // factors multiplied/divided together; each is a (tableName, colName) ref into a row.\n factors: { table: string; col: string }[];\n /** Operators between factors: length = factors.length - 1; each\n * is \"*\" or \"/\". For a single-factor sum (`sum(lineItems[].amount)`)\n * this is empty. */\n operators: (\"*\" | \"/\")[];\n}\n\nclass Parser {\n private cursor = 0;\n constructor(private readonly tokens: Token[]) {}\n\n atEnd(): boolean {\n return this.cursor >= this.tokens.length;\n }\n private peek(): Token | undefined {\n return this.tokens[this.cursor];\n }\n private consume(): Token {\n const tok = this.tokens[this.cursor++];\n if (!tok) throw new Error(\"unexpected end of input\");\n return tok;\n }\n private expect(kind: TokenKind): Token {\n const tok = this.consume();\n if (tok.kind !== kind) throw new Error(`expected ${kind}, got ${tok.kind}`);\n return tok;\n }\n\n parseExpr(): Node {\n let left = this.parseTerm();\n while (this.peek()?.kind === \"+\" || this.peek()?.kind === \"-\") {\n const operator = this.consume().kind as \"+\" | \"-\";\n const right = this.parseTerm();\n left = { kind: \"binop\", operator, left, right };\n }\n return left;\n }\n\n private parseTerm(): Node {\n let left = this.parseFactor();\n while (this.peek()?.kind === \"*\" || this.peek()?.kind === \"/\") {\n const operator = this.consume().kind as \"*\" | \"/\";\n const right = this.parseFactor();\n left = { kind: \"binop\", operator, left, right };\n }\n return left;\n }\n\n private parseFactor(): Node {\n const tok = this.peek();\n if (!tok) throw new Error(\"unexpected end in factor\");\n if (tok.kind === \"number\") {\n this.consume();\n return { kind: \"num\", value: tok.value as number };\n }\n if (tok.kind === \"(\") {\n this.consume();\n const inner = this.parseExpr();\n this.expect(\")\");\n return inner;\n }\n if (tok.kind === \"ident\") {\n const name = (tok.value as string) ?? \"\";\n // sum(...) — only function call we support\n if (name === \"sum\" && this.tokens[this.cursor + 1]?.kind === \"(\") {\n this.consume(); // ident\n this.expect(\"(\");\n const arg = this.parseSumArg();\n this.expect(\")\");\n return { kind: \"sum\", arg };\n }\n this.consume(); // ident\n // ref deref: `<field>.<col>` (e.g. ticker.price). The table-row\n // form `<table>[].col` only appears inside sum(), so a `.`\n // immediately after a top-level ident is unambiguously a ref\n // dereference here.\n if (this.peek()?.kind === \".\") {\n this.consume(); // '.'\n const col = this.expect(\"ident\");\n return { kind: \"ref\", field: name, col: col.value as string };\n }\n return { kind: \"ident\", name };\n }\n throw new Error(`unexpected token ${tok.kind} in factor`);\n }\n\n private parseSumArg(): SumArg {\n const factors: { table: string; col: string }[] = [];\n const operators: (\"*\" | \"/\")[] = [];\n factors.push(this.parseTableCol());\n while (this.peek()?.kind === \"*\" || this.peek()?.kind === \"/\") {\n const operator = this.consume().kind as \"*\" | \"/\";\n operators.push(operator);\n factors.push(this.parseTableCol());\n }\n return { factors, operators };\n }\n\n private parseTableCol(): { table: string; col: string } {\n const tableTok = this.expect(\"ident\");\n this.expect(\"[]\");\n this.expect(\".\");\n const colTok = this.expect(\"ident\");\n return { table: tableTok.value as string, col: colTok.value as string };\n }\n}\n\n// ─── Evaluator ──────────────────────────────────────────────\n\nfunction evaluate(node: Node, ctx: FormulaContext): number {\n if (node.kind === \"num\") return node.value;\n if (node.kind === \"ident\") {\n const raw = ctx.record[node.name];\n return toFiniteNumber(raw);\n }\n if (node.kind === \"ref\") {\n // `<field>.<col>`: read `col` off the resolved target record the\n // caller put in ctx.refs. Unknown field / dangling slug → null →\n // NaN, so the whole formula fails soft to an em-dash.\n const target = ctx.refs?.[node.field] ?? null;\n if (!target) return Number.NaN;\n return toFiniteNumber(target[node.col]);\n }\n if (node.kind === \"binop\") {\n const left = evaluate(node.left, ctx);\n const right = evaluate(node.right, ctx);\n return applyBinop(node.operator, left, right);\n }\n if (node.kind === \"sum\") {\n return evaluateSum(node.arg, ctx);\n }\n // Exhaustive — TS narrows above branches but throw keeps runtime honest.\n throw new Error(`unknown node`);\n}\n\nfunction applyBinop(operator: \"+\" | \"-\" | \"*\" | \"/\", left: number, right: number): number {\n if (!Number.isFinite(left) || !Number.isFinite(right)) return Number.NaN;\n if (operator === \"+\") return left + right;\n if (operator === \"-\") return left - right;\n if (operator === \"*\") return left * right;\n // operator === \"/\"\n if (right === 0) return Number.NaN;\n return left / right;\n}\n\nfunction evaluateSum(arg: SumArg, ctx: FormulaContext): number {\n if (arg.factors.length === 0) return 0;\n const tableName = arg.factors[0].table;\n // All factors must reference the SAME table (you can't multiply\n // a row from lineItems against a row from another table — the\n // semantics would be ambiguous). Reject mismatch.\n for (const factor of arg.factors) {\n if (factor.table !== tableName) return Number.NaN;\n }\n const rows = ctx.record[tableName];\n if (!Array.isArray(rows)) return 0;\n let total = 0;\n for (const row of rows) {\n if (!row || typeof row !== \"object\") continue;\n let product = toFiniteNumber((row as Record<string, unknown>)[arg.factors[0].col]);\n if (!Number.isFinite(product)) return Number.NaN;\n for (let i = 1; i < arg.factors.length; i++) {\n const value = toFiniteNumber((row as Record<string, unknown>)[arg.factors[i].col]);\n if (!Number.isFinite(value)) return Number.NaN;\n product = applyBinop(arg.operators[i - 1], product, value);\n }\n total += product;\n }\n return total;\n}\n\nfunction toFiniteNumber(value: unknown): number {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : Number.NaN;\n if (typeof value === \"string\" && value.length > 0) {\n const num = Number(value);\n return Number.isFinite(num) ? num : Number.NaN;\n }\n return Number.NaN;\n}\n","// The derived-field saturation loop for schema-driven collections,\n// extracted from `composables/collections/useCollectionRendering.ts` so\n// the server (manageCollection getItems enrichment) and the client\n// (table cells, form display) evaluate formulas through ONE\n// implementation — if the two ever diverged, the UI and the LLM would\n// disagree on a number. Pure module: no Vue, no I/O.\n//\n// Like `actionVisible.ts`, the input types are minimal structural\n// shapes so both the client `FieldSpec`/`CollectionSchema`\n// (src/components/collectionTypes.ts) and the server\n// `CollectionFieldSpec`/`CollectionSchema`\n// (server/workspace/collections/types.ts) satisfy them as-is.\n\nimport { evaluateDerived, type FormulaContext } from \"./derivedFormula\";\n\n/** Minimal field shape the derive loop needs — accepts both the client\n * FieldSpec and the server CollectionFieldSpec. */\nexport interface DerivableFieldSpec {\n type: string;\n /** When type === \"ref\": slug of the target collection. */\n to?: string;\n /** When type === \"derived\": formula evaluated against the record. */\n formula?: string;\n}\n\n/** Minimal schema shape: just the ordered field map. */\nexport interface DerivableSchema {\n fields: Record<string, DerivableFieldSpec>;\n}\n\nexport type DerivableRecord = Record<string, unknown>;\n\n/** Per-target-collection cache of loaded referenced records:\n * target collection slug → item slug → full record. Mirrors the\n * client's `RefRecordCache` / the server's enrichment loader. */\nexport type DeriveRefRecords = Record<string, Record<string, DerivableRecord>>;\n\n/** Map each `ref` field's stored slug to its loaded target record (or\n * null when dangling / not loaded), keyed by the LOCAL field name —\n * the shape `evaluateDerived` reads for `<field>.<col>` derefs. */\nexport function resolveRowRefs(schema: DerivableSchema, record: DerivableRecord, refRecords: DeriveRefRecords): NonNullable<FormulaContext[\"refs\"]> {\n const refs: NonNullable<FormulaContext[\"refs\"]> = {};\n for (const [key, field] of Object.entries(schema.fields)) {\n if (field.type !== \"ref\" || !field.to) continue;\n const slug = record[key];\n refs[key] = typeof slug === \"string\" ? (refRecords[field.to]?.[slug] ?? null) : null;\n }\n return refs;\n}\n\n/** Evaluate every `derived` field against `base`, saturating so a\n * derived field can read another derived field computed in an earlier\n * pass (`subtotal → tax → total` converges in ≤ field-count passes).\n * Cycles can't loop forever — passes are bounded by the number of\n * derived fields and the loop breaks as soon as a pass changes\n * nothing. Failed formulas stay ABSENT (the UI renders them as\n * em-dash). Returns a copy; `base` is never mutated.\n *\n * Derived keys already present in `base` are stripped before\n * evaluation: computed output is host-truth, never persisted-input\n * fallback. A record JSON can carry a stale (or forged) derived value\n * — raw Write/Edit, legacy data — and without the strip, a failing\n * formula would silently surface that value as if the host computed\n * it. */\nexport function deriveAll(schema: DerivableSchema, base: DerivableRecord, refRecords: DeriveRefRecords): DerivableRecord {\n const derivedKeys = new Set(Object.keys(schema.fields).filter((key) => schema.fields[key]?.type === \"derived\"));\n const enriched: DerivableRecord = Object.fromEntries(Object.entries(base).filter(([key]) => !derivedKeys.has(key)));\n const refs = resolveRowRefs(schema, base, refRecords);\n const maxPasses = Object.values(schema.fields).filter((field) => field.type === \"derived\").length;\n for (let pass = 0; pass < maxPasses; pass++) {\n let mutated = false;\n for (const [key, field] of Object.entries(schema.fields)) {\n if (field.type !== \"derived\" || !field.formula) continue;\n const next = evaluateDerived(field.formula, { record: enriched, refs });\n if (next !== null && enriched[key] !== next) {\n enriched[key] = next;\n mutated = true;\n }\n }\n if (!mutated) break;\n }\n return enriched;\n}\n"],"mappings":"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"}