@stonecrop/stonecrop 0.11.7 → 0.11.9

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 (43) hide show
  1. package/dist/{composables → src/composables}/lazy-link.js +1 -1
  2. package/dist/src/registry.d.ts.map +1 -1
  3. package/dist/{registry.js → src/registry.js} +6 -4
  4. package/dist/src/stonecrop.d.ts.map +1 -1
  5. package/dist/src/stonecrop.js +565 -0
  6. package/dist/{stores → src/stores}/hst.js +1 -1
  7. package/dist/src/stores/operation-log.d.ts.map +1 -1
  8. package/dist/{stores → src/stores}/operation-log.js +1 -1
  9. package/dist/src/types/doctype.d.ts +2 -2
  10. package/dist/src/types/doctype.d.ts.map +1 -1
  11. package/dist/stonecrop.d.ts +2 -1
  12. package/dist/stonecrop.js +17 -10
  13. package/dist/stonecrop.js.map +1 -1
  14. package/dist/stonecrop.tsbuildinfo +1 -1
  15. package/dist/tsdoc-metadata.json +1 -1
  16. package/package.json +23 -23
  17. package/src/composables/lazy-link.ts +1 -1
  18. package/src/composables/stonecrop.ts +1 -1
  19. package/src/field-triggers.ts +1 -1
  20. package/src/registry.ts +10 -7
  21. package/src/stonecrop.ts +0 -1
  22. package/src/stores/hst.ts +1 -1
  23. package/src/stores/operation-log.ts +11 -9
  24. package/src/types/doctype.ts +2 -2
  25. /package/dist/{composables → src/composables}/operation-log.js +0 -0
  26. /package/dist/{composables → src/composables}/stonecrop.js +0 -0
  27. /package/dist/{doctype.js → src/doctype.js} +0 -0
  28. /package/dist/{exceptions.js → src/exceptions.js} +0 -0
  29. /package/dist/{field-triggers.js → src/field-triggers.js} +0 -0
  30. /package/dist/{index.js → src/index.js} +0 -0
  31. /package/dist/{plugins → src/plugins}/index.js +0 -0
  32. /package/dist/{schema-validator.js → src/schema-validator.js} +0 -0
  33. /package/dist/{stores → src/stores}/index.js +0 -0
  34. /package/dist/{types → src/types}/composable.js +0 -0
  35. /package/dist/{types → src/types}/doctype.js +0 -0
  36. /package/dist/{types → src/types}/field-triggers.js +0 -0
  37. /package/dist/{types → src/types}/hst.js +0 -0
  38. /package/dist/{types → src/types}/index.js +0 -0
  39. /package/dist/{types → src/types}/operation-log.js +0 -0
  40. /package/dist/{types → src/types}/plugin.js +0 -0
  41. /package/dist/{types → src/types}/registry.js +0 -0
  42. /package/dist/{types → src/types}/schema-validator.js +0 -0
  43. /package/dist/{types → src/types}/stonecrop.js +0 -0
@@ -59,7 +59,7 @@ export function useLazyLink(doctype, recordId, linkFieldname) {
59
59
  return await fn(stonecropInstance, getLinkPath(), hstStore);
60
60
  }
61
61
  catch (err) {
62
- throw new Error(`Custom handler failed: ${err instanceof Error ? err.message : String(err)}`);
62
+ throw new Error(`Custom handler failed: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
63
63
  }
64
64
  };
65
65
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,kBAAkB,CAAA;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAEnC,OAAO,OAAO,MAAM,WAAW,CAAA;AAE/B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE/C;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC5B;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAA;IAEtB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAa;IAElC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAK;IAE/C;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc,CAAqE;IAE3F;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB,CAAgB;IAE3C;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IAExB;;;;OAIG;gBACS,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IASjG;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAEpE;;;;;OAKG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO;IAuB3B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,WAAW,EAAE;IA4FrE;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAmDrB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IA6BxB;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAqD5D;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI7C;;;;;;;;;;;;;OAaG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC,eAAe,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAUvF;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC,eAAe,GAAG;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAwBtG;;;OAGG;IACH,OAAO,CAAC,oBAAoB;CAgC5B"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,kBAAkB,CAAA;AAChE,OAAO,KAAK,EAAa,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AAEnC,OAAO,OAAO,MAAM,WAAW,CAAA;AAE/B,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAE/C;;;GAGG;AACH,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC5B;;OAEG;IACH,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAA;IAEtB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAa;IAElC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAK;IAE/C;;;;;;;OAOG;IACH,OAAO,CAAC,cAAc,CAAqE;IAE3F;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB,CAAgB;IAE3C;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IAExB;;;;OAIG;gBACS,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IASjG;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAEpE;;;;;OAKG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO;IAuB3B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,WAAW,EAAE;IAgGrE;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAkDrB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IA6BxB;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAqD5D;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI7C;;;;;;;;;;;;;OAaG;IACH,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC,eAAe,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAUvF;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,KAAK,CAAC,eAAe,GAAG;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAwBtG;;;OAGG;IACH,OAAO,CAAC,oBAAoB;CAgC5B"}
@@ -139,8 +139,12 @@ export default class Registry {
139
139
  if ('fieldtype' in field && field.fieldtype === 'Link') {
140
140
  const link = linksByFieldname.get(field.fieldname);
141
141
  if (!link) {
142
- // Link field without corresponding link declaration - copy as-is
143
- resolvedFields.push({ ...field });
142
+ const doctype = typeof field.options === 'string' ? field.options : undefined;
143
+ resolvedFields.push({
144
+ ...field,
145
+ component: 'AFormLink',
146
+ ...(doctype !== undefined ? { doctype } : {}),
147
+ });
144
148
  continue;
145
149
  }
146
150
  const targetDoctype = this.registry[link.target];
@@ -160,7 +164,6 @@ export default class Registry {
160
164
  }
161
165
  else {
162
166
  // One relationship — embed form schema
163
- // TODO: remove assertion once resolved link output has a dedicated type separate from input schema
164
167
  resolvedFields.push({
165
168
  ...fieldRest,
166
169
  label: fieldRest.label || field.fieldname,
@@ -207,7 +210,6 @@ export default class Registry {
207
210
  resolved.push(this.buildTableConfig({ ...fieldRest, label: fieldRest.label || field.fieldname }, childSchema, link.component));
208
211
  }
209
212
  else {
210
- // TODO: remove assertion once resolved link output has a dedicated type separate from input schema
211
213
  resolved.push({
212
214
  ...fieldRest,
213
215
  label: fieldRest.label || field.fieldname,
@@ -1 +1 @@
1
- {"version":3,"file":"stonecrop.d.ts","sourceRoot":"","sources":["../../src/stonecrop.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stonecrop.d.ts","sourceRoot":"","sources":["../../src/stonecrop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,565 @@
1
+ import { reactive } from 'vue';
2
+ import { getGlobalTriggerEngine } from './field-triggers';
3
+ import { createHST } from './stores/hst';
4
+ import { useOperationLogStore } from './stores/operation-log';
5
+ /**
6
+ * Main Stonecrop class with HST integration and built-in Operation Log
7
+ * @public
8
+ */
9
+ export class Stonecrop {
10
+ /**
11
+ * Singleton instance of Stonecrop. Only one Stonecrop instance can exist
12
+ * per application, ensuring consistent HST state and registry access.
13
+ * Subsequent constructor calls return this instance instead of creating new ones.
14
+ * @internal
15
+ */
16
+ static _root;
17
+ /** The HST store instance for reactive state management */
18
+ hstStore;
19
+ _operationLogStore;
20
+ _operationLogConfig;
21
+ _client;
22
+ /** The registry instance containing all doctype definitions */
23
+ registry;
24
+ /**
25
+ * Creates a new Stonecrop instance with HST integration (singleton pattern)
26
+ * @param registry - The Registry instance containing doctype definitions
27
+ * @param operationLogConfig - Optional configuration for the operation log
28
+ * @param options - Options including the data client (can be set later via setClient)
29
+ */
30
+ constructor(registry, operationLogConfig, options) {
31
+ if (Stonecrop._root) {
32
+ return Stonecrop._root;
33
+ }
34
+ Stonecrop._root = this;
35
+ this.registry = registry;
36
+ // Store config for lazy initialization
37
+ this._operationLogConfig = operationLogConfig;
38
+ // Store data client (can be set later via setClient)
39
+ this._client = options?.client;
40
+ // Initialize HST store with auto-sync to Registry
41
+ this.initializeHSTStore();
42
+ this.setupRegistrySync();
43
+ }
44
+ /**
45
+ * Set the data client for fetching doctype metadata and records.
46
+ * Use this for deferred configuration in Nuxt/Vue plugin setups.
47
+ *
48
+ * @param client - DataClient implementation (e.g., StonecropClient from \@stonecrop/graphql-client)
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * const { setClient } = useStonecropRegistry()
53
+ * const client = new StonecropClient({ endpoint: '/graphql' })
54
+ * setClient(client)
55
+ * ```
56
+ */
57
+ setClient(client) {
58
+ this._client = client;
59
+ }
60
+ /**
61
+ * Get the current data client
62
+ * @returns The DataClient instance or undefined if not set
63
+ */
64
+ getClient() {
65
+ return this._client;
66
+ }
67
+ /**
68
+ * Get the operation log store (lazy initialization)
69
+ * @internal
70
+ */
71
+ getOperationLogStore() {
72
+ if (!this._operationLogStore) {
73
+ this._operationLogStore = useOperationLogStore();
74
+ if (this._operationLogConfig) {
75
+ this._operationLogStore.configure(this._operationLogConfig);
76
+ }
77
+ }
78
+ return this._operationLogStore;
79
+ }
80
+ /**
81
+ * Initialize the HST store structure
82
+ */
83
+ initializeHSTStore() {
84
+ const initialStoreStructure = {};
85
+ // Auto-populate from existing Registry doctypes
86
+ Object.keys(this.registry.registry).forEach(doctypeSlug => {
87
+ initialStoreStructure[doctypeSlug] = {};
88
+ });
89
+ // Wrap the store in Vue's reactive() for automatic change detection
90
+ // This enables Vue computed properties to track HST store changes
91
+ this.hstStore = createHST(reactive(initialStoreStructure), 'StonecropStore');
92
+ }
93
+ /**
94
+ * Setup automatic sync with Registry when doctypes are added
95
+ */
96
+ setupRegistrySync() {
97
+ // Extend Registry.addDoctype to auto-create HST store sections
98
+ const originalAddDoctype = this.registry.addDoctype.bind(this.registry);
99
+ this.registry.addDoctype = (doctype) => {
100
+ // Call original method
101
+ originalAddDoctype(doctype);
102
+ // Auto-create HST store section for new doctype
103
+ if (!this.hstStore.has(doctype.slug)) {
104
+ this.hstStore.set(doctype.slug, {});
105
+ }
106
+ };
107
+ }
108
+ /**
109
+ * Get records hash for a doctype
110
+ * @param doctype - The doctype to get records for
111
+ * @returns HST node containing records hash
112
+ */
113
+ records(doctype) {
114
+ const slug = typeof doctype === 'string' ? doctype : doctype.slug;
115
+ this.ensureDoctypeExists(slug);
116
+ return this.hstStore.getNode(slug);
117
+ }
118
+ /**
119
+ * Add a record to the store
120
+ * @param doctype - The doctype
121
+ * @param recordId - The record ID
122
+ * @param recordData - The record data
123
+ */
124
+ addRecord(doctype, recordId, recordData) {
125
+ const slug = typeof doctype === 'string' ? doctype : doctype.slug;
126
+ this.ensureDoctypeExists(slug);
127
+ // Store raw record data - let HST handle wrapping with proper hierarchy
128
+ this.hstStore.set(`${slug}.${recordId}`, recordData);
129
+ }
130
+ /**
131
+ * Get a specific record
132
+ * @param doctype - The doctype
133
+ * @param recordId - The record ID
134
+ * @returns HST node for the record or undefined
135
+ */
136
+ getRecordById(doctype, recordId) {
137
+ const slug = typeof doctype === 'string' ? doctype : doctype.slug;
138
+ this.ensureDoctypeExists(slug);
139
+ // First check if the record exists
140
+ const recordExists = this.hstStore.has(`${slug}.${recordId}`);
141
+ if (!recordExists) {
142
+ return undefined;
143
+ }
144
+ // Check if the actual value is undefined (i.e., record was removed)
145
+ const recordValue = this.hstStore.get(`${slug}.${recordId}`);
146
+ if (recordValue === undefined) {
147
+ return undefined;
148
+ }
149
+ // Use getNode to get the properly wrapped HST node with correct ancestor relationships
150
+ return this.hstStore.getNode(`${slug}.${recordId}`);
151
+ }
152
+ /**
153
+ * Remove a record from the store
154
+ * @param doctype - The doctype
155
+ * @param recordId - The record ID
156
+ */
157
+ removeRecord(doctype, recordId) {
158
+ const slug = typeof doctype === 'string' ? doctype : doctype.slug;
159
+ this.ensureDoctypeExists(slug);
160
+ // Remove the specific record directly by setting to undefined
161
+ if (this.hstStore.has(`${slug}.${recordId}`)) {
162
+ this.hstStore.set(`${slug}.${recordId}`, undefined);
163
+ }
164
+ }
165
+ /**
166
+ * Get all record IDs for a doctype
167
+ * @param doctype - The doctype
168
+ * @returns Array of record IDs
169
+ */
170
+ getRecordIds(doctype) {
171
+ const slug = typeof doctype === 'string' ? doctype : doctype.slug;
172
+ this.ensureDoctypeExists(slug);
173
+ const doctypeNode = this.hstStore.get(slug);
174
+ if (!doctypeNode || typeof doctypeNode !== 'object') {
175
+ return [];
176
+ }
177
+ return Object.keys(doctypeNode).filter(key => doctypeNode[key] !== undefined);
178
+ }
179
+ /**
180
+ * Clear all records for a doctype
181
+ * @param doctype - The doctype
182
+ */
183
+ clearRecords(doctype) {
184
+ const slug = typeof doctype === 'string' ? doctype : doctype.slug;
185
+ this.ensureDoctypeExists(slug);
186
+ // Get all record IDs and remove them
187
+ const recordIds = this.getRecordIds(slug);
188
+ recordIds.forEach(recordId => {
189
+ this.hstStore.set(`${slug}.${recordId}`, undefined);
190
+ });
191
+ }
192
+ /**
193
+ * Setup method for doctype initialization
194
+ * @param doctype - The doctype to setup
195
+ */
196
+ setup(doctype) {
197
+ // Ensure doctype exists in store
198
+ this.ensureDoctypeExists(doctype.slug);
199
+ }
200
+ /**
201
+ * Run action on doctype
202
+ * Executes the action and logs it to the operation log for audit tracking
203
+ * @param doctype - The doctype
204
+ * @param action - The action to run
205
+ * @param args - Action arguments (typically record IDs)
206
+ */
207
+ runAction(doctype, action, args) {
208
+ const registry = this.registry.registry[doctype.slug];
209
+ const actions = registry?.actions?.get(action);
210
+ const recordIds = Array.isArray(args) ? args.filter((arg) => typeof arg === 'string') : undefined;
211
+ const recordId = recordIds?.[0];
212
+ // Check if workflow is ready (all blocked links have data)
213
+ const workflowStatus = recordId ? this.isWorkflowReady(doctype, recordId) : { ready: true };
214
+ if (!workflowStatus.ready) {
215
+ const opLogStore = this.getOperationLogStore();
216
+ opLogStore.logAction(doctype.doctype, action, recordIds, 'failure', `BLOCKED: missing data for links: ${workflowStatus.blockedLinks?.join(', ')}`);
217
+ throw new Error(`Workflow blocked: missing data for links: ${workflowStatus.blockedLinks?.join(', ')}`);
218
+ }
219
+ // Log action execution start
220
+ const opLogStore = this.getOperationLogStore();
221
+ let actionResult = 'success';
222
+ let actionError;
223
+ try {
224
+ // Execute action functions
225
+ if (actions && actions.length > 0) {
226
+ const engine = getGlobalTriggerEngine();
227
+ actions.forEach(actionStr => {
228
+ try {
229
+ const actionFn = engine.getAction(actionStr);
230
+ if (!actionFn)
231
+ throw new Error(`Action "${actionStr}" is not registered in FieldTriggerEngine`);
232
+ const context = {
233
+ path: `${doctype.slug}.${recordIds?.[0] ?? ''}`,
234
+ fieldname: action,
235
+ beforeValue: undefined,
236
+ afterValue: args,
237
+ operation: 'set',
238
+ doctype: doctype.doctype,
239
+ recordId: recordId,
240
+ timestamp: new Date(),
241
+ };
242
+ void actionFn(context);
243
+ }
244
+ catch (error) {
245
+ actionResult = 'failure';
246
+ actionError = error instanceof Error ? error.message : 'Unknown error';
247
+ throw error;
248
+ }
249
+ });
250
+ }
251
+ }
252
+ catch {
253
+ // Error already set in inner catch
254
+ }
255
+ finally {
256
+ // Log the action execution to operation log
257
+ opLogStore.logAction(doctype.doctype, action, recordIds, actionResult, actionError);
258
+ }
259
+ }
260
+ /**
261
+ * Get the effective blockWorkflows value for a link.
262
+ * Returns true if blockWorkflows is explicitly true, or if it's absent and fetch method is 'sync'.
263
+ * @param link - The link declaration
264
+ * @returns Whether workflows should be blocked until this link is loaded
265
+ */
266
+ getEffectiveBlockWorkflows(link) {
267
+ if (link.blockWorkflows !== undefined) {
268
+ return link.blockWorkflows;
269
+ }
270
+ // TODO: For custom fetch handlers, this returns false (not blocking), but the custom handler
271
+ // may still be invoked by useLazyLink. Future: custom handlers should be able to declare they
272
+ // satisfy blockWorkflows, or validation should reject custom + blockWorkflows: true.
273
+ // See: relationships.md Phase 6 "Open Question: blockWorkflows + custom fetch"
274
+ return link.fetch?.method === 'sync';
275
+ }
276
+ /**
277
+ * Check if workflow actions are ready to run (all required link data is loaded).
278
+ * A link's data is considered loaded if it exists in HST at `slug.recordId.linkname`.
279
+ * @param doctype - The doctype to check
280
+ * @param recordId - The record ID
281
+ * @returns Object with `ready: true` if all blocked links are loaded, or `ready: false` with `blockedLinks` array
282
+ */
283
+ isWorkflowReady(doctype, recordId) {
284
+ // New records don't block workflows - they haven't been saved yet
285
+ if (recordId === 'new') {
286
+ return { ready: true };
287
+ }
288
+ const links = this.registry.getDescendantLinks(doctype.slug);
289
+ const blockedLinks = [];
290
+ for (const link of links) {
291
+ if (this.getEffectiveBlockWorkflows(link)) {
292
+ const linkPath = `${doctype.slug}.${recordId}.${link.fieldname}`;
293
+ if (!this.hstStore.has(linkPath)) {
294
+ blockedLinks.push(link.fieldname);
295
+ }
296
+ }
297
+ }
298
+ if (blockedLinks.length > 0) {
299
+ return { ready: false, blockedLinks };
300
+ }
301
+ return { ready: true };
302
+ }
303
+ /**
304
+ * Get records from server using the configured data client.
305
+ * @param doctype - The doctype
306
+ * @throws Error if no data client has been configured
307
+ */
308
+ async getRecords(doctype) {
309
+ if (!this._client) {
310
+ throw new Error('No data client configured. Call setClient() with a DataClient implementation ' +
311
+ '(e.g., StonecropClient from @stonecrop/graphql-client) before fetching records.');
312
+ }
313
+ const records = await this._client.getRecords(doctype);
314
+ // Store each record in HST
315
+ records.forEach(record => {
316
+ if (record.id) {
317
+ this.addRecord(doctype, record.id, record);
318
+ }
319
+ });
320
+ }
321
+ /**
322
+ * Get single record from server using the configured data client.
323
+ * @param doctype - The doctype
324
+ * @param recordId - The record ID
325
+ * @throws Error if no data client has been configured
326
+ */
327
+ async getRecord(doctype, recordId) {
328
+ if (!this._client) {
329
+ throw new Error('No data client configured. Call setClient() with a DataClient implementation ' +
330
+ '(e.g., StonecropClient from @stonecrop/graphql-client) before fetching records.');
331
+ }
332
+ const record = await this._client.getRecord(doctype, recordId);
333
+ if (record) {
334
+ this.addRecord(doctype, recordId, record);
335
+ }
336
+ }
337
+ /**
338
+ * Dispatch an action to the server via the configured data client.
339
+ * All state changes flow through this single mutation endpoint.
340
+ *
341
+ * @param doctype - The doctype
342
+ * @param action - Action name to execute (e.g., 'SUBMIT', 'APPROVE', 'save')
343
+ * @param args - Action arguments (typically record ID and/or form data)
344
+ * @returns Action result with success status, response data, and any error
345
+ * @throws Error if no data client has been configured
346
+ */
347
+ async dispatchAction(doctype, action, args) {
348
+ if (!this._client) {
349
+ throw new Error('No data client configured. Call setClient() with a DataClient implementation ' +
350
+ '(e.g., StonecropClient from @stonecrop/graphql-client) before dispatching actions.');
351
+ }
352
+ return this._client.runAction(doctype, action, args);
353
+ }
354
+ /**
355
+ * Ensure doctype section exists in HST store
356
+ * @param slug - The doctype slug
357
+ */
358
+ ensureDoctypeExists(slug) {
359
+ if (!this.hstStore.has(slug)) {
360
+ this.hstStore.set(slug, {});
361
+ }
362
+ }
363
+ /**
364
+ * Get doctype metadata from the registry
365
+ * @param context - The route context
366
+ * @returns The doctype metadata
367
+ */
368
+ async getMeta(context) {
369
+ if (!this.registry.getMeta) {
370
+ throw new Error('No getMeta function provided to Registry');
371
+ }
372
+ return await this.registry.getMeta(context);
373
+ }
374
+ /**
375
+ * Get the root HST store node for advanced usage
376
+ * @returns Root HST node
377
+ */
378
+ getStore() {
379
+ return this.hstStore;
380
+ }
381
+ /**
382
+ * Determine the current workflow state for a record.
383
+ *
384
+ * Reads the record's `status` field from the HST store. If the field is absent or
385
+ * empty the doctype's declared `workflow.initial` state is used as the fallback,
386
+ * giving callers a reliable state name without having to duplicate that logic.
387
+ *
388
+ * @param doctype - The doctype slug or Doctype instance
389
+ * @param recordId - The record identifier
390
+ * @returns The current state name, or an empty string if the doctype has no workflow
391
+ *
392
+ * @public
393
+ */
394
+ getRecordState(doctype, recordId) {
395
+ const slug = typeof doctype === 'string' ? doctype : doctype.slug;
396
+ const meta = this.registry.getDoctype(slug);
397
+ if (!meta?.workflow)
398
+ return '';
399
+ const record = this.getRecordById(slug, recordId);
400
+ const status = record?.get('status');
401
+ // Handle both XState format and WorkflowMeta format
402
+ const workflow = meta.workflow;
403
+ let initialState;
404
+ if (Array.isArray(workflow.states)) {
405
+ // WorkflowMeta format: states is a string array
406
+ initialState = workflow.states[0] ?? '';
407
+ }
408
+ else {
409
+ // XState format: states is an object, use initial or first key
410
+ initialState =
411
+ typeof workflow.initial === 'string'
412
+ ? workflow.initial
413
+ : Object.keys(workflow.states ?? {})[0] ?? '';
414
+ }
415
+ return status || initialState;
416
+ }
417
+ /**
418
+ * Collect a record payload with all nested doctype fields from HST
419
+ * @param doctype - The doctype metadata
420
+ * @param recordId - The record ID to collect
421
+ * @returns The complete record payload ready for API submission
422
+ * @public
423
+ */
424
+ collectRecordPayload(doctype, recordId) {
425
+ const recordPath = `${doctype.slug}.${recordId}`;
426
+ const recordData = this.hstStore.get(recordPath) || {};
427
+ const payload = { ...recordData };
428
+ // Collect nested data from links
429
+ if (doctype.links) {
430
+ for (const [fieldname, link] of Object.entries(doctype.links)) {
431
+ const fieldPath = `${recordPath}.${fieldname}`;
432
+ const isMany = link.cardinality === 'noneOrMany' || link.cardinality === 'atLeastOne';
433
+ if (isMany) {
434
+ const arrayData = this.hstStore.get(fieldPath);
435
+ if (Array.isArray(arrayData)) {
436
+ payload[fieldname] = arrayData;
437
+ }
438
+ }
439
+ else {
440
+ const targetDoctype = this.registry.getDoctype(link.target);
441
+ if (targetDoctype?.links) {
442
+ payload[fieldname] = this.collectNestedData(fieldPath, targetDoctype);
443
+ }
444
+ else {
445
+ payload[fieldname] = this.hstStore.get(fieldPath) || {};
446
+ }
447
+ }
448
+ }
449
+ }
450
+ return payload;
451
+ }
452
+ /**
453
+ * Scaffold empty descendant records from defaults for all descendant links.
454
+ *
455
+ * Initializes all scalar and link fields at their HST paths with default values.
456
+ * For new records, call this after setting up the doctype to ensure all paths exist.
457
+ *
458
+ * @param path - HST path (e.g., "customer.new")
459
+ * @param doctype - The doctype to initialize
460
+ * @public
461
+ */
462
+ initializeNestedData(path, doctype) {
463
+ const slug = doctype.slug;
464
+ this.ensureDoctypeExists(slug);
465
+ // Resolve schema and initialize with defaults
466
+ const resolvedSchema = this.registry.resolveSchema(doctype);
467
+ const record = this.registry.initializeRecord(resolvedSchema);
468
+ // Ensure the ancestor path exists in HST before setting descendant fields
469
+ const existingData = this.hstStore.get(path);
470
+ if (!existingData) {
471
+ this.hstStore.set(path, {}, 'system');
472
+ }
473
+ // Store each field at its own HST path
474
+ for (const [key, value] of Object.entries(record)) {
475
+ this.hstStore.set(`${path}.${key}`, value, 'system');
476
+ }
477
+ }
478
+ /**
479
+ * Fetch a record and its nested data from the server.
480
+ *
481
+ * Calls `_client.getRecord()` with nested sub-selections and stores each scalar field at its own HST path
482
+ * (`slug.recordId.fieldname`), descendants at the link-level path (`slug.recordId.linkname`).
483
+ *
484
+ * @param path - HST path (e.g., "recipe.r1")
485
+ * @param doctype - The doctype to fetch
486
+ * @param recordId - Record ID to fetch
487
+ * @param options - Query options (includeNested to control which links are fetched)
488
+ * @throws Error with code `"CLIENT_REQUIRED"` if no data client is configured
489
+ * @throws Error with code `"RECORD_NOT_FOUND"` if the server returns null
490
+ * @public
491
+ */
492
+ async fetchNestedData(path, doctype, recordId, options) {
493
+ if (!this._client) {
494
+ throw createCodedError('No data client configured. Call setClient() with a DataClient implementation ' +
495
+ '(e.g., StonecropClient from @stonecrop/graphql-client) before fetching records.', 'CLIENT_REQUIRED');
496
+ }
497
+ const record = await this._client.getRecord({ name: doctype.doctype }, recordId, {
498
+ includeNested: options?.includeNested ?? true,
499
+ });
500
+ if (!record) {
501
+ throw createCodedError(`Record not found: ${doctype.doctype} ${recordId}`, 'RECORD_NOT_FOUND');
502
+ }
503
+ // Store each scalar field at its own HST path, descendants at link-level path
504
+ const slug = doctype.slug;
505
+ this.ensureDoctypeExists(slug);
506
+ // Ensure the ancestor path exists in HST before setting descendant fields
507
+ const existingData = this.hstStore.get(`${slug}.${recordId}`);
508
+ if (!existingData) {
509
+ this.hstStore.set(`${slug}.${recordId}`, {}, 'system');
510
+ }
511
+ for (const [key, value] of Object.entries(record)) {
512
+ this.hstStore.set(`${slug}.${recordId}.${key}`, value, 'system');
513
+ }
514
+ }
515
+ /**
516
+ * Recursively collect nested data from HST
517
+ * @param basePath - The base path in HST (e.g., "customer.123.address")
518
+ * @param doctype - The doctype whose links drive the recursive traversal
519
+ * @returns The collected data object
520
+ */
521
+ collectNestedData(basePath, doctype) {
522
+ const data = this.hstStore.get(basePath) || {};
523
+ const payload = { ...data };
524
+ if (!doctype.links)
525
+ return payload;
526
+ for (const [fieldname, link] of Object.entries(doctype.links)) {
527
+ const fieldPath = `${basePath}.${fieldname}`;
528
+ const isMany = link.cardinality === 'noneOrMany' || link.cardinality === 'atLeastOne';
529
+ if (isMany) {
530
+ const arrayData = this.hstStore.get(fieldPath);
531
+ if (Array.isArray(arrayData)) {
532
+ payload[fieldname] = arrayData;
533
+ }
534
+ }
535
+ else {
536
+ const targetDoctype = this.registry.getDoctype(link.target);
537
+ if (targetDoctype?.links) {
538
+ payload[fieldname] = this.collectNestedData(fieldPath, targetDoctype);
539
+ }
540
+ else {
541
+ payload[fieldname] = this.hstStore.get(fieldPath) || {};
542
+ }
543
+ }
544
+ }
545
+ return payload;
546
+ }
547
+ }
548
+ /**
549
+ * Returns the global Stonecrop singleton instance, or `undefined` if no
550
+ * instance has been created yet.
551
+ *
552
+ * Use this when you need the Stonecrop instance outside a Vue component
553
+ * context (e.g., in workflow action handlers, plugin setup code, or
554
+ * non-component utilities). Inside a component, prefer `useStonecrop()`.
555
+ *
556
+ * @public
557
+ */
558
+ export function getStonecrop() {
559
+ return Stonecrop._root;
560
+ }
561
+ function createCodedError(message, code) {
562
+ const error = new Error(message);
563
+ error.code = code;
564
+ return error;
565
+ }
@@ -91,7 +91,7 @@ class HSTProxy {
91
91
  get(hst, prop) {
92
92
  // Return HST methods directly
93
93
  if (prop in hst)
94
- return hst[prop];
94
+ return Reflect.get(hst, prop);
95
95
  // Handle property access - return tree nodes for navigation
96
96
  const path = String(prop);
97
97
  return hst.getNode(path);
@@ -1 +1 @@
1
- {"version":3,"file":"operation-log.d.ts","sourceRoot":"","sources":["../../../src/stores/operation-log.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACpC,OAAO,KAAK,EAEX,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,MAAM,wBAAwB,CAAA;AA4E/B;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA0DJ,OAAO,CAAC,kBAAkB,CAAC;8BAkBtB,iBAAiB,WAAU,eAAe;;gCA0DxC,MAAM,KAAG,MAAM,GAAG,IAAI;;kBA2EpC,OAAO,KAAG,OAAO;kBAmDjB,OAAO,KAAG,OAAO;;gCA2FH,MAAM,aAAa,MAAM,KAAG,YAAY,EAAE;uBA1BrD,oBAAoB;oCAmCL,MAAM,UAAU,MAAM;yBAmBnD,MAAM,cACH,MAAM,cACN,MAAM,EAAE,WACZ,SAAS,GAAG,SAAS,GAAG,SAAS,UACjC,MAAM,KACZ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAtUmB,OAAO,CAAC,kBAAkB,CAAC;8BAkBtB,iBAAiB,WAAU,eAAe;;gCA0DxC,MAAM,KAAG,MAAM,GAAG,IAAI;;kBA2EpC,OAAO,KAAG,OAAO;kBAmDjB,OAAO,KAAG,OAAO;;gCA2FH,MAAM,aAAa,MAAM,KAAG,YAAY,EAAE;uBA1BrD,oBAAoB;oCAmCL,MAAM,UAAU,MAAM;yBAmBnD,MAAM,cACH,MAAM,cACN,MAAM,EAAE,WACZ,SAAS,GAAG,SAAS,GAAG,SAAS,UACjC,MAAM,KACZ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAtUmB,OAAO,CAAC,kBAAkB,CAAC;8BAkBtB,iBAAiB,WAAU,eAAe;;gCA0DxC,MAAM,KAAG,MAAM,GAAG,IAAI;;kBA2EpC,OAAO,KAAG,OAAO;kBAmDjB,OAAO,KAAG,OAAO;;gCA2FH,MAAM,aAAa,MAAM,KAAG,YAAY,EAAE;uBA1BrD,oBAAoB;oCAmCL,MAAM,UAAU,MAAM;yBAmBnD,MAAM,cACH,MAAM,cACN,MAAM,EAAE,WACZ,SAAS,GAAG,SAAS,GAAG,SAAS,UACjC,MAAM,KACZ,MAAM;oLA0MR,CAAA"}
1
+ {"version":3,"file":"operation-log.d.ts","sourceRoot":"","sources":["../../../src/stores/operation-log.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACpC,OAAO,KAAK,EAEX,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,MAAM,wBAAwB,CAAA;AA4E/B;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA4DJ,OAAO,CAAC,kBAAkB,CAAC;8BAkBtB,iBAAiB,WAAU,eAAe;;gCA0DxC,MAAM,KAAG,MAAM,GAAG,IAAI;;kBA2EpC,OAAO,KAAG,OAAO;kBAmDjB,OAAO,KAAG,OAAO;;gCA2FH,MAAM,aAAa,MAAM,KAAG,YAAY,EAAE;uBA1BrD,oBAAoB;oCAmCL,MAAM,UAAU,MAAM;yBAmBnD,MAAM,cACH,MAAM,cACN,MAAM,EAAE,WACZ,SAAS,GAAG,SAAS,GAAG,SAAS,UACjC,MAAM,KACZ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAtUmB,OAAO,CAAC,kBAAkB,CAAC;8BAkBtB,iBAAiB,WAAU,eAAe;;gCA0DxC,MAAM,KAAG,MAAM,GAAG,IAAI;;kBA2EpC,OAAO,KAAG,OAAO;kBAmDjB,OAAO,KAAG,OAAO;;gCA2FH,MAAM,aAAa,MAAM,KAAG,YAAY,EAAE;uBA1BrD,oBAAoB;oCAmCL,MAAM,UAAU,MAAM;yBAmBnD,MAAM,cACH,MAAM,cACN,MAAM,EAAE,WACZ,SAAS,GAAG,SAAS,GAAG,SAAS,UACjC,MAAM,KACZ,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAtUmB,OAAO,CAAC,kBAAkB,CAAC;8BAkBtB,iBAAiB,WAAU,eAAe;;gCA0DxC,MAAM,KAAG,MAAM,GAAG,IAAI;;kBA2EpC,OAAO,KAAG,OAAO;kBAmDjB,OAAO,KAAG,OAAO;;gCA2FH,MAAM,aAAa,MAAM,KAAG,YAAY,EAAE;uBA1BrD,oBAAoB;oCAmCL,MAAM,UAAU,MAAM;yBAmBnD,MAAM,cACH,MAAM,cACN,MAAM,EAAE,WACZ,SAAS,GAAG,SAAS,GAAG,SAAS,UACjC,MAAM,KACZ,MAAM;oLA0MR,CAAA"}
@@ -436,7 +436,7 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
436
436
  }
437
437
  else if (message.type === 'operation' && message.operations) {
438
438
  // Add batch operations from another tab
439
- operations.value.push(...message.operations.map(op => ({ ...op, source: 'sync' })));
439
+ operations.value.push(...message.operations.map((op) => ({ ...op, source: 'sync' })));
440
440
  currentIndex.value = operations.value.length - 1;
441
441
  }
442
442
  });