@stonecrop/stonecrop 0.11.0 → 0.11.1

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 (49) hide show
  1. package/package.json +4 -4
  2. package/dist/composable.js +0 -1
  3. package/dist/composables/use-lazy-link-state.js +0 -125
  4. package/dist/composables/use-stonecrop.js +0 -476
  5. package/dist/operation-log-DB-dGNT9.js +0 -593
  6. package/dist/operation-log-DB-dGNT9.js.map +0 -1
  7. package/dist/src/composable.d.ts +0 -11
  8. package/dist/src/composable.d.ts.map +0 -1
  9. package/dist/src/composable.js +0 -477
  10. package/dist/src/composables/operation-log.js +0 -224
  11. package/dist/src/composables/stonecrop.js +0 -574
  12. package/dist/src/composables/use-lazy-link-state.d.ts +0 -25
  13. package/dist/src/composables/use-lazy-link-state.d.ts.map +0 -1
  14. package/dist/src/composables/use-stonecrop.d.ts +0 -93
  15. package/dist/src/composables/use-stonecrop.d.ts.map +0 -1
  16. package/dist/src/composables/useNestedSchema.d.ts +0 -110
  17. package/dist/src/composables/useNestedSchema.d.ts.map +0 -1
  18. package/dist/src/composables/useNestedSchema.js +0 -155
  19. package/dist/src/doctype.js +0 -234
  20. package/dist/src/exceptions.js +0 -16
  21. package/dist/src/field-triggers.js +0 -567
  22. package/dist/src/index.js +0 -23
  23. package/dist/src/plugins/index.js +0 -96
  24. package/dist/src/registry.js +0 -246
  25. package/dist/src/schema-validator.js +0 -315
  26. package/dist/src/stonecrop.js +0 -339
  27. package/dist/src/stores/data.d.ts +0 -11
  28. package/dist/src/stores/data.d.ts.map +0 -1
  29. package/dist/src/stores/hst.js +0 -495
  30. package/dist/src/stores/index.js +0 -12
  31. package/dist/src/stores/operation-log.js +0 -568
  32. package/dist/src/stores/xstate.d.ts +0 -31
  33. package/dist/src/stores/xstate.d.ts.map +0 -1
  34. package/dist/src/tsdoc-metadata.json +0 -11
  35. package/dist/src/types/field-triggers.js +0 -4
  36. package/dist/src/types/index.js +0 -4
  37. package/dist/src/types/operation-log.js +0 -0
  38. package/dist/src/types/registry.js +0 -0
  39. package/dist/src/utils.d.ts +0 -24
  40. package/dist/src/utils.d.ts.map +0 -1
  41. package/dist/stonecrop.css +0 -1
  42. package/dist/stonecrop.umd.cjs +0 -6
  43. package/dist/stonecrop.umd.cjs.map +0 -1
  44. package/dist/stores/data.js +0 -7
  45. package/dist/stores/xstate.js +0 -29
  46. package/dist/tests/setup.d.ts +0 -5
  47. package/dist/tests/setup.d.ts.map +0 -1
  48. package/dist/tests/setup.js +0 -15
  49. package/dist/utils.js +0 -46
@@ -1,574 +0,0 @@
1
- import { isDoctypeMany, } from '@stonecrop/aform';
2
- import { storeToRefs } from 'pinia';
3
- import { inject, onMounted, ref, watch, provide, computed } from 'vue';
4
- import { Stonecrop } from '../stonecrop';
5
- /**
6
- * @public
7
- */
8
- export function useStonecrop(options) {
9
- if (!options)
10
- options = {};
11
- const registry = options.registry || inject('$registry');
12
- const providedStonecrop = inject('$stonecrop');
13
- const stonecrop = ref();
14
- const hstStore = ref();
15
- const formData = ref({});
16
- // Use refs for router-loaded doctype to maintain reactivity
17
- const routerDoctype = ref();
18
- const routerRecordId = ref();
19
- // Resolved schema with nested Doctype fields expanded
20
- const resolvedSchema = ref([]);
21
- // Loading state for lazy-loaded doctypes
22
- const isLoading = ref(false);
23
- const error = ref(null);
24
- const resolvedDoctype = ref();
25
- // If doctype is a Doctype instance (not string), set resolved immediately
26
- if (options?.doctype && typeof options.doctype !== 'string') {
27
- resolvedDoctype.value = options.doctype;
28
- }
29
- // Operation log state and methods - will be populated after stonecrop instance is created
30
- const operations = ref([]);
31
- const currentIndex = ref(-1);
32
- const canUndo = computed(() => stonecrop.value?.getOperationLogStore().canUndo ?? false);
33
- const canRedo = computed(() => stonecrop.value?.getOperationLogStore().canRedo ?? false);
34
- const undoCount = computed(() => stonecrop.value?.getOperationLogStore().undoCount ?? 0);
35
- const redoCount = computed(() => stonecrop.value?.getOperationLogStore().redoCount ?? 0);
36
- const undoRedoState = computed(() => stonecrop.value?.getOperationLogStore().undoRedoState ?? {
37
- canUndo: false,
38
- canRedo: false,
39
- undoCount: 0,
40
- redoCount: 0,
41
- currentIndex: -1,
42
- });
43
- // Operation log methods
44
- const undo = (hstStore) => {
45
- return stonecrop.value?.getOperationLogStore().undo(hstStore) ?? false;
46
- };
47
- const redo = (hstStore) => {
48
- return stonecrop.value?.getOperationLogStore().redo(hstStore) ?? false;
49
- };
50
- const startBatch = () => {
51
- stonecrop.value?.getOperationLogStore().startBatch();
52
- };
53
- const commitBatch = (description) => {
54
- return stonecrop.value?.getOperationLogStore().commitBatch(description) ?? null;
55
- };
56
- const cancelBatch = () => {
57
- stonecrop.value?.getOperationLogStore().cancelBatch();
58
- };
59
- const clear = () => {
60
- stonecrop.value?.getOperationLogStore().clear();
61
- };
62
- const getOperationsFor = (doctype, recordId) => {
63
- return stonecrop.value?.getOperationLogStore().getOperationsFor(doctype, recordId) ?? [];
64
- };
65
- const getSnapshot = () => {
66
- return (stonecrop.value?.getOperationLogStore().getSnapshot() ?? {
67
- operations: [],
68
- currentIndex: -1,
69
- totalOperations: 0,
70
- reversibleOperations: 0,
71
- irreversibleOperations: 0,
72
- });
73
- };
74
- const markIrreversible = (operationId, reason) => {
75
- stonecrop.value?.getOperationLogStore().markIrreversible(operationId, reason);
76
- };
77
- const logAction = (doctype, actionName, recordIds, result = 'success', error) => {
78
- return stonecrop.value?.getOperationLogStore().logAction(doctype, actionName, recordIds, result, error) ?? '';
79
- };
80
- const configure = (config) => {
81
- stonecrop.value?.getOperationLogStore().configure(config);
82
- };
83
- // Initialize Stonecrop instance
84
- onMounted(async () => {
85
- if (!registry) {
86
- return;
87
- }
88
- stonecrop.value = providedStonecrop || new Stonecrop(registry);
89
- // Set up reactive refs from operation log store - only if Pinia is available
90
- try {
91
- const opLogStore = stonecrop.value.getOperationLogStore();
92
- const opLogRefs = storeToRefs(opLogStore);
93
- operations.value = opLogRefs.operations.value;
94
- currentIndex.value = opLogRefs.currentIndex.value;
95
- // Watch for changes in operation log state
96
- watch(() => opLogRefs.operations.value, newOps => {
97
- operations.value = newOps;
98
- });
99
- watch(() => opLogRefs.currentIndex.value, newIndex => {
100
- currentIndex.value = newIndex;
101
- });
102
- }
103
- catch {
104
- // Pinia not available (e.g., in tests) - operation log features will not be available
105
- // Silently fail - operation log is optional
106
- }
107
- // Handle router-based setup if no specific doctype provided
108
- if (!options.doctype && registry.router) {
109
- const route = registry.router.currentRoute.value;
110
- // Parse route path - let the application determine the doctype from the route
111
- if (!route.path)
112
- return; // Early return if no path available
113
- const pathSegments = route.path.split('/').filter(segment => segment.length > 0);
114
- const recordId = pathSegments[1]?.toLowerCase();
115
- if (pathSegments.length > 0) {
116
- // Create route context for getMeta function
117
- const routeContext = {
118
- path: route.path,
119
- segments: pathSegments,
120
- };
121
- const doctype = await registry.getMeta?.(routeContext);
122
- if (doctype) {
123
- registry.addDoctype(doctype);
124
- stonecrop.value.setup(doctype);
125
- // Set reactive refs for router-based doctype
126
- routerDoctype.value = doctype;
127
- routerRecordId.value = recordId;
128
- hstStore.value = stonecrop.value.getStore();
129
- // Resolve schema for router-loaded doctype
130
- if (registry) {
131
- const schemaArray = doctype.schema
132
- ? Array.isArray(doctype.schema)
133
- ? doctype.schema
134
- : Array.from(doctype.schema)
135
- : [];
136
- resolvedSchema.value = registry.resolveSchema(schemaArray);
137
- }
138
- if (recordId && recordId !== 'new') {
139
- const existingRecord = stonecrop.value.getRecordById(doctype, recordId);
140
- if (existingRecord) {
141
- formData.value = existingRecord.get('') || {};
142
- }
143
- else {
144
- try {
145
- await stonecrop.value.getRecord(doctype, recordId);
146
- const loadedRecord = stonecrop.value.getRecordById(doctype, recordId);
147
- if (loadedRecord) {
148
- formData.value = loadedRecord.get('') || {};
149
- }
150
- }
151
- catch {
152
- formData.value = initializeNewRecord(doctype);
153
- }
154
- }
155
- }
156
- else {
157
- formData.value = initializeNewRecord(doctype);
158
- }
159
- if (hstStore.value) {
160
- setupDeepReactivity(doctype, recordId || 'new', formData, hstStore.value);
161
- }
162
- stonecrop.value.runAction(doctype, 'load', recordId ? [recordId] : undefined);
163
- }
164
- }
165
- }
166
- // Handle HST integration if doctype is provided explicitly
167
- if (options.doctype) {
168
- hstStore.value = stonecrop.value.getStore();
169
- const recordId = options.recordId;
170
- // Resolve doctype - handle string (lazy-load) or Doctype instance
171
- let doctype;
172
- if (typeof options.doctype === 'string') {
173
- // String doctype - check registry first, then lazy-load
174
- const doctypeSlug = options.doctype;
175
- isLoading.value = true;
176
- error.value = null;
177
- try {
178
- // Check if already in registry
179
- doctype = registry.getDoctype(doctypeSlug);
180
- if (!doctype && registry.getMeta) {
181
- // Lazy-load via getMeta
182
- const routeContext = {
183
- path: `/${doctypeSlug}`,
184
- segments: [doctypeSlug],
185
- };
186
- doctype = await registry.getMeta(routeContext);
187
- if (doctype) {
188
- registry.addDoctype(doctype);
189
- }
190
- }
191
- if (!doctype) {
192
- error.value = new Error(`Doctype '${doctypeSlug}' not found in registry and getMeta returned no result`);
193
- }
194
- }
195
- catch (e) {
196
- error.value = e instanceof Error ? e : new Error(String(e));
197
- }
198
- finally {
199
- isLoading.value = false;
200
- }
201
- }
202
- else {
203
- // Doctype instance provided directly
204
- doctype = options.doctype;
205
- }
206
- // Set resolved doctype for consumers
207
- resolvedDoctype.value = doctype;
208
- if (!doctype) {
209
- // Error already set above, just return
210
- return;
211
- }
212
- // Resolve schema for the doctype
213
- const schemaArray = doctype.schema
214
- ? Array.isArray(doctype.schema)
215
- ? doctype.schema
216
- : Array.from(doctype.schema)
217
- : [];
218
- resolvedSchema.value = registry.resolveSchema(schemaArray);
219
- if (recordId && recordId !== 'new') {
220
- const existingRecord = stonecrop.value.getRecordById(doctype, recordId);
221
- if (existingRecord) {
222
- formData.value = existingRecord.get('') || {};
223
- }
224
- else {
225
- try {
226
- await stonecrop.value.getRecord(doctype, recordId);
227
- const loadedRecord = stonecrop.value.getRecordById(doctype, recordId);
228
- if (loadedRecord) {
229
- formData.value = loadedRecord.get('') || {};
230
- }
231
- }
232
- catch {
233
- formData.value = initializeNewRecord(doctype);
234
- }
235
- }
236
- }
237
- else {
238
- formData.value = initializeNewRecord(doctype);
239
- }
240
- if (hstStore.value) {
241
- setupDeepReactivity(doctype, recordId || 'new', formData, hstStore.value);
242
- }
243
- }
244
- });
245
- // HST integration functions - always created but only populated when HST is available
246
- const provideHSTPath = (fieldname, customRecordId) => {
247
- const doctype = resolvedDoctype.value || routerDoctype.value;
248
- if (!doctype)
249
- return '';
250
- const actualRecordId = customRecordId || options.recordId || routerRecordId.value || 'new';
251
- return `${doctype.slug}.${actualRecordId}.${fieldname}`;
252
- };
253
- const handleHSTChange = (changeData) => {
254
- const doctype = resolvedDoctype.value || routerDoctype.value;
255
- if (!hstStore.value || !stonecrop.value || !doctype) {
256
- return;
257
- }
258
- try {
259
- const pathParts = changeData.path.split('.');
260
- if (pathParts.length >= 2) {
261
- const doctypeSlug = pathParts[0];
262
- const recordId = pathParts[1];
263
- if (!hstStore.value.has(`${doctypeSlug}.${recordId}`)) {
264
- stonecrop.value.addRecord(doctype, recordId, { ...formData.value });
265
- }
266
- if (pathParts.length > 3) {
267
- const recordPath = `${doctypeSlug}.${recordId}`;
268
- const nestedParts = pathParts.slice(2);
269
- let currentPath = recordPath;
270
- for (let i = 0; i < nestedParts.length - 1; i++) {
271
- currentPath += `.${nestedParts[i]}`;
272
- if (!hstStore.value.has(currentPath)) {
273
- const nextPart = nestedParts[i + 1];
274
- const isArray = !isNaN(Number(nextPart));
275
- hstStore.value.set(currentPath, isArray ? [] : {});
276
- }
277
- }
278
- }
279
- }
280
- hstStore.value.set(changeData.path, changeData.value);
281
- const fieldParts = changeData.fieldname.split('.');
282
- const newFormData = { ...formData.value };
283
- if (fieldParts.length === 1) {
284
- newFormData[fieldParts[0]] = changeData.value;
285
- }
286
- else {
287
- updateNestedObject(newFormData, fieldParts, changeData.value);
288
- }
289
- formData.value = newFormData;
290
- }
291
- catch {
292
- // Silently handle errors
293
- }
294
- };
295
- // Provide injection tokens if HST will be available
296
- if (options.doctype || registry?.router) {
297
- provide('hstPathProvider', provideHSTPath);
298
- provide('hstChangeHandler', handleHSTChange);
299
- }
300
- /**
301
- * Load nested doctype data from API or initialize empty structure
302
- * @param parentPath - The parent path (e.g., "customer.123.address")
303
- * @param childDoctype - The child doctype metadata
304
- * @param recordId - Optional record ID to load
305
- * @returns Promise resolving to the loaded or initialized data
306
- */
307
- const loadNestedData = (parentPath, childDoctype, recordId) => {
308
- if (!stonecrop.value) {
309
- return initializeNewRecord(childDoctype);
310
- }
311
- // If recordId provided, try to load existing data
312
- if (recordId) {
313
- try {
314
- // Check if data already exists in HST
315
- const existingData = hstStore.value?.get(parentPath);
316
- if (existingData && typeof existingData === 'object') {
317
- return existingData;
318
- }
319
- // TODO: Add API fetch logic here if needed
320
- // For now, initialize new record
321
- return initializeNewRecord(childDoctype);
322
- }
323
- catch {
324
- return initializeNewRecord(childDoctype);
325
- }
326
- }
327
- // Initialize new record
328
- return initializeNewRecord(childDoctype);
329
- };
330
- /**
331
- * Collect a record payload with all nested doctype fields from HST
332
- * @param doctype - The doctype metadata
333
- * @param recordId - The record ID to collect
334
- * @returns The complete record payload ready for API submission
335
- */
336
- const collectRecordPayload = (doctype, recordId) => {
337
- if (!hstStore.value || !stonecrop.value) {
338
- throw new Error('HST store not initialized');
339
- }
340
- const recordPath = `${doctype.slug}.${recordId}`;
341
- const recordData = hstStore.value.get(recordPath) || {};
342
- // Build the save payload using resolved schema
343
- const payload = { ...recordData };
344
- // Use resolveSchema to get the full resolved tree, then walk Doctype fields
345
- const schemaArray = doctype.schema
346
- ? Array.isArray(doctype.schema)
347
- ? doctype.schema
348
- : Array.from(doctype.schema)
349
- : [];
350
- const resolved = registry ? registry.resolveSchema(schemaArray) : schemaArray;
351
- // 1:1 nested Doctype fields (cardinality: 'one' or undefined)
352
- const doctypeFields = resolved.filter(field => 'fieldtype' in field &&
353
- field.fieldtype === 'Doctype' &&
354
- !isDoctypeMany(field) &&
355
- 'schema' in field &&
356
- Array.isArray(field.schema));
357
- // Recursively collect nested data from HST using resolved schemas
358
- for (const field of doctypeFields) {
359
- const doctypeField = field;
360
- const fieldPath = `${recordPath}.${doctypeField.fieldname}`;
361
- const nestedData = collectNestedData(doctypeField.schema, fieldPath, hstStore.value);
362
- payload[doctypeField.fieldname] = nestedData;
363
- }
364
- // 1:many child tables (cardinality: 'many')
365
- const doctypeManyFields = resolved.filter(field => 'fieldtype' in field && field.fieldtype === 'Doctype' && isDoctypeMany(field));
366
- // Read array data from HST for cardinality: 'many' fields
367
- for (const field of doctypeManyFields) {
368
- const doctypeField = field;
369
- const fieldPath = `${recordPath}.${doctypeField.fieldname}`;
370
- const arrayData = hstStore.value.get(fieldPath);
371
- if (Array.isArray(arrayData)) {
372
- payload[doctypeField.fieldname] = arrayData;
373
- }
374
- }
375
- return payload;
376
- };
377
- /**
378
- * Create a nested context for child forms
379
- * @param basePath - The base path for the nested context (e.g., "customer.123.address")
380
- * @param _childDoctype - The child doctype metadata (unused but kept for API consistency)
381
- * @returns Object with scoped provideHSTPath and handleHSTChange
382
- */
383
- const createNestedContext = (basePath, _childDoctype) => {
384
- const nestedProvideHSTPath = (fieldname) => {
385
- return `${basePath}.${fieldname}`;
386
- };
387
- const nestedHandleHSTChange = (changeData) => {
388
- // Update the path to be relative to the nested base path
389
- const nestedPath = changeData.path.startsWith(basePath) ? changeData.path : `${basePath}.${changeData.fieldname}`;
390
- handleHSTChange({
391
- ...changeData,
392
- path: nestedPath,
393
- });
394
- };
395
- return {
396
- provideHSTPath: nestedProvideHSTPath,
397
- handleHSTChange: nestedHandleHSTChange,
398
- };
399
- };
400
- // Create operation log API object
401
- const operationLog = {
402
- operations,
403
- currentIndex,
404
- undoRedoState,
405
- canUndo,
406
- canRedo,
407
- undoCount,
408
- redoCount,
409
- undo,
410
- redo,
411
- startBatch,
412
- commitBatch,
413
- cancelBatch,
414
- clear,
415
- getOperationsFor,
416
- getSnapshot,
417
- markIrreversible,
418
- logAction,
419
- configure,
420
- };
421
- // Always return HST functions if doctype is provided or will be loaded from router
422
- if (options.doctype) {
423
- // Explicit doctype - return HST immediately
424
- return {
425
- stonecrop,
426
- operationLog,
427
- provideHSTPath,
428
- handleHSTChange,
429
- hstStore,
430
- formData,
431
- resolvedSchema,
432
- loadNestedData,
433
- collectRecordPayload,
434
- createNestedContext,
435
- isLoading,
436
- error,
437
- resolvedDoctype,
438
- };
439
- }
440
- else if (!options.doctype && registry?.router) {
441
- // Router-based - return HST (will be populated after mount)
442
- return {
443
- stonecrop,
444
- operationLog,
445
- provideHSTPath,
446
- handleHSTChange,
447
- hstStore,
448
- formData,
449
- resolvedSchema,
450
- loadNestedData,
451
- collectRecordPayload,
452
- createNestedContext,
453
- isLoading,
454
- error,
455
- resolvedDoctype,
456
- };
457
- }
458
- // No doctype and no router - basic mode
459
- return {
460
- stonecrop,
461
- operationLog,
462
- };
463
- }
464
- /**
465
- * Initialize new record structure based on doctype schema
466
- */
467
- function initializeNewRecord(doctype) {
468
- const initialData = {};
469
- if (!doctype.schema) {
470
- return initialData;
471
- }
472
- doctype.schema.forEach(field => {
473
- const fieldtype = 'fieldtype' in field ? field.fieldtype : 'Data';
474
- switch (fieldtype) {
475
- case 'Data':
476
- case 'Text':
477
- initialData[field.fieldname] = '';
478
- break;
479
- case 'Check':
480
- initialData[field.fieldname] = false;
481
- break;
482
- case 'Int':
483
- case 'Float':
484
- initialData[field.fieldname] = 0;
485
- break;
486
- case 'JSON':
487
- initialData[field.fieldname] = {};
488
- break;
489
- case 'Doctype': {
490
- // Check cardinality to determine initial value
491
- const cardinality = 'cardinality' in field ? field.cardinality : undefined;
492
- if (cardinality === 'many') {
493
- // 1:many child table - initialize as empty array
494
- initialData[field.fieldname] = [];
495
- }
496
- else {
497
- // 1:1 nested form - initialize as empty object
498
- initialData[field.fieldname] = {};
499
- }
500
- break;
501
- }
502
- default:
503
- initialData[field.fieldname] = null;
504
- }
505
- });
506
- return initialData;
507
- }
508
- /**
509
- * Setup deep reactivity between form data and HST store
510
- */
511
- function setupDeepReactivity(doctype, recordId, formData, hstStore) {
512
- watch(formData, newData => {
513
- const recordPath = `${doctype.slug}.${recordId}`;
514
- Object.keys(newData).forEach(fieldname => {
515
- const path = `${recordPath}.${fieldname}`;
516
- try {
517
- hstStore.set(path, newData[fieldname]);
518
- }
519
- catch {
520
- // Silently handle errors
521
- }
522
- });
523
- }, { deep: true });
524
- }
525
- /**
526
- * Update nested object with dot-notation path
527
- */
528
- function updateNestedObject(obj, path, value) {
529
- let current = obj;
530
- for (let i = 0; i < path.length - 1; i++) {
531
- const key = path[i];
532
- if (!(key in current) || typeof current[key] !== 'object') {
533
- current[key] = isNaN(Number(path[i + 1])) ? {} : [];
534
- }
535
- current = current[key];
536
- }
537
- const finalKey = path[path.length - 1];
538
- current[finalKey] = value;
539
- }
540
- /**
541
- * Recursively collect nested data from HST using pre-resolved schemas
542
- * @param resolvedSchema - The already-resolved schema (with nested schemas embedded)
543
- * @param basePath - The base path in HST (e.g., "customer.123.address")
544
- * @param hstStore - The HST store instance
545
- * @returns The collected data object
546
- */
547
- function collectNestedData(resolvedSchema, basePath, hstStore) {
548
- const data = hstStore.get(basePath) || {};
549
- const payload = { ...data };
550
- // Find Doctype fields that have resolved child schemas (1:1 only, not cardinality: 'many')
551
- const doctypeFields = resolvedSchema.filter(field => 'fieldtype' in field &&
552
- field.fieldtype === 'Doctype' &&
553
- !isDoctypeMany(field) &&
554
- 'schema' in field &&
555
- Array.isArray(field.schema));
556
- // Recursively collect nested data
557
- for (const field of doctypeFields) {
558
- const doctypeField = field;
559
- const fieldPath = `${basePath}.${doctypeField.fieldname}`;
560
- const nestedData = collectNestedData(doctypeField.schema, fieldPath, hstStore);
561
- payload[doctypeField.fieldname] = nestedData;
562
- }
563
- // Also collect array data for cardinality: 'many' fields
564
- const doctypeManyFields = resolvedSchema.filter(field => 'fieldtype' in field && field.fieldtype === 'Doctype' && isDoctypeMany(field));
565
- for (const field of doctypeManyFields) {
566
- const doctypeField = field;
567
- const fieldPath = `${basePath}.${doctypeField.fieldname}`;
568
- const arrayData = hstStore.get(fieldPath);
569
- if (Array.isArray(arrayData)) {
570
- payload[doctypeField.fieldname] = arrayData;
571
- }
572
- }
573
- return payload;
574
- }
@@ -1,25 +0,0 @@
1
- import Doctype from '../doctype';
2
- import type { LazyLinkState } from '../types/composable';
3
- /**
4
- * Get the lazy link state for a specific link field on a doctype record.
5
- *
6
- * This composable provides reactive state for lazy-loaded links:
7
- * - `loading`: true while fetching
8
- * - `loaded`: true after successful fetch (permanent until reload)
9
- * - `error`: error state if any
10
- * - `reload()`: explicitly trigger a fetch
11
- * - `data`: computed from HST, or undefined if not loaded
12
- *
13
- * The reload() function respects the link's fetch strategy:
14
- * - `sync`: fetches via GraphQL query through fetchNestedData
15
- * - `lazy`: fetches via GraphQL query through fetchNestedData
16
- * - `custom`: invokes the serialized handler function directly
17
- *
18
- * @param doctype - The doctype instance
19
- * @param recordId - The record ID
20
- * @param linkFieldname - The link fieldname to load
21
- * @returns LazyLinkState with loading, loaded, error, reload, and data
22
- * @public
23
- */
24
- export declare function useLazyLinkState(doctype: Doctype, recordId: string, linkFieldname: string): LazyLinkState;
25
- //# sourceMappingURL=use-lazy-link-state.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"use-lazy-link-state.d.ts","sourceRoot":"","sources":["../../../src/composables/use-lazy-link-state.ts"],"names":[],"mappings":"AAGA,OAAO,OAAO,MAAM,YAAY,CAAA;AAEhC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAExD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,aAAa,CAqHzG"}
@@ -1,93 +0,0 @@
1
- import { Ref, ComputedRef } from 'vue';
2
- import Registry from '../registry';
3
- import { Stonecrop } from '../stonecrop';
4
- import DoctypeMeta from '../doctype';
5
- import type { HSTNode } from '../stores/hst';
6
- import type { HSTOperation, OperationLogConfig, OperationLogSnapshot } from '../types/operation-log';
7
- import { SchemaTypes } from '@stonecrop/aform';
8
- /**
9
- * Operation Log API - nested object containing all operation log functionality
10
- * @public
11
- */
12
- export type OperationLogAPI = {
13
- operations: Ref<HSTOperation[]>;
14
- currentIndex: Ref<number>;
15
- undoRedoState: ComputedRef<{
16
- canUndo: boolean;
17
- canRedo: boolean;
18
- undoCount: number;
19
- redoCount: number;
20
- currentIndex: number;
21
- }>;
22
- canUndo: ComputedRef<boolean>;
23
- canRedo: ComputedRef<boolean>;
24
- undoCount: ComputedRef<number>;
25
- redoCount: ComputedRef<number>;
26
- undo: (hstStore: HSTNode) => boolean;
27
- redo: (hstStore: HSTNode) => boolean;
28
- startBatch: () => void;
29
- commitBatch: (description?: string) => string | null;
30
- cancelBatch: () => void;
31
- clear: () => void;
32
- getOperationsFor: (doctype: string, recordId?: string) => HSTOperation[];
33
- getSnapshot: () => OperationLogSnapshot;
34
- markIrreversible: (operationId: string, reason: string) => void;
35
- logAction: (doctype: string, actionName: string, recordIds?: string[], result?: 'success' | 'failure' | 'pending', error?: string) => string;
36
- configure: (options: Partial<OperationLogConfig>) => void;
37
- };
38
- /**
39
- * Base Stonecrop composable return type - includes operation log functionality
40
- * @public
41
- */
42
- export type BaseStonecropReturn = {
43
- stonecrop: Ref<Stonecrop | undefined>;
44
- operationLog: OperationLogAPI;
45
- };
46
- /**
47
- * HST-enabled Stonecrop composable return type
48
- * @public
49
- */
50
- export type HSTStonecropReturn = BaseStonecropReturn & {
51
- provideHSTPath: (fieldname: string, recordId?: string) => string;
52
- handleHSTChange: (changeData: HSTChangeData) => void;
53
- hstStore: Ref<HSTNode | undefined>;
54
- formData: Ref<Record<string, any>>;
55
- resolvedSchema: Ref<SchemaTypes[]>;
56
- loadNestedData: (parentPath: string, childDoctype: DoctypeMeta, recordId?: string) => Record<string, any>;
57
- saveRecursive: (doctype: DoctypeMeta, recordId: string) => Promise<Record<string, any>>;
58
- createNestedContext: (basePath: string, childDoctype: DoctypeMeta) => {
59
- provideHSTPath: (fieldname: string) => string;
60
- handleHSTChange: (changeData: HSTChangeData) => void;
61
- };
62
- };
63
- /**
64
- * HST Change data structure
65
- * @public
66
- */
67
- export type HSTChangeData = {
68
- path: string;
69
- value: any;
70
- fieldname: string;
71
- recordId?: string;
72
- };
73
- /**
74
- * Unified Stonecrop composable - handles both general operations and HST reactive integration
75
- *
76
- * @param options - Configuration options for the composable
77
- * @returns Stonecrop instance and optional HST integration utilities
78
- * @public
79
- */
80
- export declare function useStonecrop(): BaseStonecropReturn | HSTStonecropReturn;
81
- /**
82
- * Unified Stonecrop composable with HST integration for a specific doctype and record
83
- *
84
- * @param options - Configuration with doctype and optional recordId
85
- * @returns Stonecrop instance with full HST integration utilities
86
- * @public
87
- */
88
- export declare function useStonecrop(options: {
89
- registry?: Registry;
90
- doctype: DoctypeMeta;
91
- recordId?: string;
92
- }): HSTStonecropReturn;
93
- //# sourceMappingURL=use-stonecrop.d.ts.map