@stonecrop/stonecrop 0.10.11 → 0.10.13
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.
- package/dist/composables/stonecrop.js +26 -110
- package/dist/field-triggers.js +5 -6
- package/dist/index.js +9 -6
- package/dist/plugins/index.js +4 -1
- package/dist/registry.js +62 -61
- package/dist/schema-validator.js +1 -13
- package/dist/src/composables/stonecrop.d.ts +2 -74
- package/dist/src/composables/stonecrop.d.ts.map +1 -1
- package/dist/src/doctype.d.ts +1 -27
- package/dist/src/doctype.d.ts.map +1 -1
- package/dist/src/field-triggers.d.ts.map +1 -1
- package/dist/src/index.d.ts +6 -9
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/plugins/index.d.ts.map +1 -1
- package/dist/src/registry.d.ts +13 -10
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/schema-validator.d.ts +1 -62
- package/dist/src/schema-validator.d.ts.map +1 -1
- package/dist/src/stonecrop.d.ts +38 -17
- package/dist/src/stonecrop.d.ts.map +1 -1
- package/dist/src/stores/operation-log.d.ts +1 -1
- package/dist/src/types/composable.d.ts +230 -0
- package/dist/src/types/composable.d.ts.map +1 -0
- package/dist/src/types/doctype.d.ts +57 -0
- package/dist/src/types/doctype.d.ts.map +1 -0
- package/dist/src/types/index.d.ts +6 -67
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/plugin.d.ts +37 -0
- package/dist/src/types/plugin.d.ts.map +1 -0
- package/dist/src/types/schema-validator.d.ts +64 -0
- package/dist/src/types/schema-validator.d.ts.map +1 -0
- package/dist/src/types/stonecrop.d.ts +17 -0
- package/dist/src/types/stonecrop.d.ts.map +1 -0
- package/dist/stonecrop.css +1 -0
- package/dist/stonecrop.d.ts +206 -14
- package/dist/stonecrop.js +1751 -1631
- package/dist/stonecrop.js.map +1 -1
- package/dist/types/composable.js +0 -0
- package/dist/types/doctype.js +0 -0
- package/dist/types/index.js +7 -2
- package/dist/types/plugin.js +0 -0
- package/dist/types/schema-validator.js +13 -0
- package/dist/types/stonecrop.js +0 -0
- package/package.json +4 -4
- package/src/composables/stonecrop.ts +34 -218
- package/src/doctype.ts +2 -29
- package/src/field-triggers.ts +5 -6
- package/src/index.ts +12 -19
- package/src/plugins/index.ts +4 -1
- package/src/registry.ts +61 -66
- package/src/schema-validator.ts +3 -66
- package/src/stonecrop.ts +148 -17
- package/src/types/composable.ts +245 -0
- package/src/types/doctype.ts +60 -0
- package/src/types/index.ts +7 -74
- package/src/types/plugin.ts +38 -0
- package/src/types/schema-validator.ts +67 -0
- package/src/types/stonecrop.ts +17 -0
|
File without changes
|
|
File without changes
|
package/dist/types/index.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
// Re-export
|
|
1
|
+
// Re-export all type files
|
|
2
|
+
export * from './composable';
|
|
3
|
+
export * from './doctype';
|
|
2
4
|
export * from './field-triggers';
|
|
3
|
-
export * from './registry';
|
|
4
5
|
export * from './operation-log';
|
|
6
|
+
export * from './plugin';
|
|
7
|
+
export * from './registry';
|
|
8
|
+
export * from './schema-validator';
|
|
9
|
+
export * from './stonecrop';
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation severity levels
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
export var ValidationSeverity;
|
|
6
|
+
(function (ValidationSeverity) {
|
|
7
|
+
/** Blocking error that prevents save */
|
|
8
|
+
ValidationSeverity["ERROR"] = "error";
|
|
9
|
+
/** Advisory warning that allows save */
|
|
10
|
+
ValidationSeverity["WARNING"] = "warning";
|
|
11
|
+
/** Informational message */
|
|
12
|
+
ValidationSeverity["INFO"] = "info";
|
|
13
|
+
})(ValidationSeverity || (ValidationSeverity = {}));
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/stonecrop",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.13",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"pinia-shared-state": "^1.0.1",
|
|
35
35
|
"pinia-xstate": "^3.0.0",
|
|
36
36
|
"xstate": "^5.25.0",
|
|
37
|
-
"@stonecrop/schema": "0.10.
|
|
37
|
+
"@stonecrop/schema": "0.10.13"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"pinia": "^3.0.4",
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
"vue-router": "^5.0.2",
|
|
61
61
|
"vite": "^7.3.1",
|
|
62
62
|
"vitest": "^4.0.18",
|
|
63
|
-
"@stonecrop/atable": "0.10.11",
|
|
64
63
|
"stonecrop-rig": "0.7.0",
|
|
65
|
-
"@stonecrop/
|
|
64
|
+
"@stonecrop/atable": "0.10.13",
|
|
65
|
+
"@stonecrop/aform": "0.10.13"
|
|
66
66
|
},
|
|
67
67
|
"description": "Schema-driven framework with XState workflows and HST state management",
|
|
68
68
|
"publishConfig": {
|
|
@@ -1,94 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type SchemaTypes } from '@stonecrop/aform'
|
|
2
|
+
import { storeToRefs } from 'pinia'
|
|
3
|
+
import { inject, onMounted, Ref, ref, watch, provide, computed } from 'vue'
|
|
2
4
|
|
|
5
|
+
import Doctype from '../doctype'
|
|
3
6
|
import Registry from '../registry'
|
|
4
7
|
import { Stonecrop } from '../stonecrop'
|
|
5
|
-
import Doctype from '../doctype'
|
|
6
8
|
import type { HSTNode } from '../stores/hst'
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import type {
|
|
10
|
-
import { SchemaTypes, DoctypeSchema } from '@stonecrop/aform'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Operation Log API - nested object containing all operation log functionality
|
|
14
|
-
* @public
|
|
15
|
-
*/
|
|
16
|
-
export type OperationLogAPI = {
|
|
17
|
-
operations: Ref<HSTOperation[]>
|
|
18
|
-
currentIndex: Ref<number>
|
|
19
|
-
undoRedoState: ComputedRef<{
|
|
20
|
-
canUndo: boolean
|
|
21
|
-
canRedo: boolean
|
|
22
|
-
undoCount: number
|
|
23
|
-
redoCount: number
|
|
24
|
-
currentIndex: number
|
|
25
|
-
}>
|
|
26
|
-
canUndo: ComputedRef<boolean>
|
|
27
|
-
canRedo: ComputedRef<boolean>
|
|
28
|
-
undoCount: ComputedRef<number>
|
|
29
|
-
redoCount: ComputedRef<number>
|
|
30
|
-
undo: (hstStore: HSTNode) => boolean
|
|
31
|
-
redo: (hstStore: HSTNode) => boolean
|
|
32
|
-
startBatch: () => void
|
|
33
|
-
commitBatch: (description?: string) => string | null
|
|
34
|
-
cancelBatch: () => void
|
|
35
|
-
clear: () => void
|
|
36
|
-
getOperationsFor: (doctype: string, recordId?: string) => HSTOperation[]
|
|
37
|
-
getSnapshot: () => OperationLogSnapshot
|
|
38
|
-
markIrreversible: (operationId: string, reason: string) => void
|
|
39
|
-
logAction: (
|
|
40
|
-
doctype: string,
|
|
41
|
-
actionName: string,
|
|
42
|
-
recordIds?: string[],
|
|
43
|
-
result?: 'success' | 'failure' | 'pending',
|
|
44
|
-
error?: string
|
|
45
|
-
) => string
|
|
46
|
-
configure: (options: Partial<OperationLogConfig>) => void
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Base Stonecrop composable return type - includes operation log functionality
|
|
51
|
-
* @public
|
|
52
|
-
*/
|
|
53
|
-
export type BaseStonecropReturn = {
|
|
54
|
-
stonecrop: Ref<Stonecrop | undefined>
|
|
55
|
-
operationLog: OperationLogAPI
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* HST-enabled Stonecrop composable return type
|
|
60
|
-
* @public
|
|
61
|
-
*/
|
|
62
|
-
export type HSTStonecropReturn = BaseStonecropReturn & {
|
|
63
|
-
provideHSTPath: (fieldname: string, recordId?: string) => string
|
|
64
|
-
handleHSTChange: (changeData: HSTChangeData) => void
|
|
65
|
-
hstStore: Ref<HSTNode | undefined>
|
|
66
|
-
formData: Ref<Record<string, any>>
|
|
67
|
-
resolvedSchema: Ref<SchemaTypes[]>
|
|
68
|
-
loadNestedData: (parentPath: string, childDoctype: Doctype, recordId?: string) => Record<string, any>
|
|
69
|
-
saveRecursive: (doctype: Doctype, recordId: string) => Promise<Record<string, any>>
|
|
70
|
-
createNestedContext: (
|
|
71
|
-
basePath: string,
|
|
72
|
-
childDoctype: Doctype
|
|
73
|
-
) => {
|
|
74
|
-
provideHSTPath: (fieldname: string) => string
|
|
75
|
-
handleHSTChange: (changeData: HSTChangeData) => void
|
|
76
|
-
}
|
|
77
|
-
isLoading: Ref<boolean>
|
|
78
|
-
error: Ref<Error | null>
|
|
79
|
-
resolvedDoctype: Ref<Doctype | undefined>
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* HST Change data structure
|
|
84
|
-
* @public
|
|
85
|
-
*/
|
|
86
|
-
export type HSTChangeData = {
|
|
87
|
-
path: string
|
|
88
|
-
value: any
|
|
89
|
-
fieldname: string
|
|
90
|
-
recordId?: string
|
|
91
|
-
}
|
|
9
|
+
import type { BaseStonecropReturn, HSTStonecropReturn, HSTChangeData, OperationLogAPI } from '../types/composable'
|
|
10
|
+
import type { HSTOperation, OperationLogConfig } from '../types/operation-log'
|
|
11
|
+
import type { RouteContext } from '../types/registry'
|
|
92
12
|
|
|
93
13
|
/**
|
|
94
14
|
* Unified Stonecrop composable - handles both general operations and HST reactive integration
|
|
@@ -122,7 +42,7 @@ export function useStonecrop(options?: {
|
|
|
122
42
|
|
|
123
43
|
const registry = options.registry || inject<Registry>('$registry')
|
|
124
44
|
const providedStonecrop = inject<Stonecrop>('$stonecrop')
|
|
125
|
-
const stonecrop = ref<Stonecrop>()
|
|
45
|
+
const stonecrop = ref<Stonecrop | undefined>()
|
|
126
46
|
const hstStore = ref<HSTNode>()
|
|
127
47
|
const formData = ref<Record<string, any>>({})
|
|
128
48
|
|
|
@@ -138,6 +58,13 @@ export function useStonecrop(options?: {
|
|
|
138
58
|
const error = ref<Error | null>(null)
|
|
139
59
|
const resolvedDoctype = ref<Doctype | undefined>()
|
|
140
60
|
|
|
61
|
+
// Initialize stonecrop instance synchronously using singleton pattern
|
|
62
|
+
// Use injected instance if available, otherwise fall back to the singleton root
|
|
63
|
+
const stonecropInstance = providedStonecrop || Stonecrop._root
|
|
64
|
+
if (stonecropInstance) {
|
|
65
|
+
stonecrop.value = stonecropInstance
|
|
66
|
+
}
|
|
67
|
+
|
|
141
68
|
// If doctype is a Doctype instance (not string), set resolved immediately
|
|
142
69
|
if (options?.doctype && typeof options.doctype !== 'string') {
|
|
143
70
|
resolvedDoctype.value = options.doctype
|
|
@@ -222,12 +149,10 @@ export function useStonecrop(options?: {
|
|
|
222
149
|
|
|
223
150
|
// Initialize Stonecrop instance
|
|
224
151
|
onMounted(async () => {
|
|
225
|
-
if (!registry) {
|
|
152
|
+
if (!registry || !stonecrop.value) {
|
|
226
153
|
return
|
|
227
154
|
}
|
|
228
155
|
|
|
229
|
-
stonecrop.value = providedStonecrop || new Stonecrop(registry)
|
|
230
|
-
|
|
231
156
|
// Set up reactive refs from operation log store - only if Pinia is available
|
|
232
157
|
try {
|
|
233
158
|
const opLogStore = stonecrop.value.getOperationLogStore()
|
|
@@ -302,11 +227,11 @@ export function useStonecrop(options?: {
|
|
|
302
227
|
formData.value = loadedRecord.get('') || {}
|
|
303
228
|
}
|
|
304
229
|
} catch {
|
|
305
|
-
formData.value =
|
|
230
|
+
formData.value = registry.initializeRecord(resolvedSchema.value)
|
|
306
231
|
}
|
|
307
232
|
}
|
|
308
233
|
} else {
|
|
309
|
-
formData.value =
|
|
234
|
+
formData.value = registry.initializeRecord(resolvedSchema.value)
|
|
310
235
|
}
|
|
311
236
|
|
|
312
237
|
if (hstStore.value) {
|
|
@@ -389,11 +314,11 @@ export function useStonecrop(options?: {
|
|
|
389
314
|
formData.value = loadedRecord.get('') || {}
|
|
390
315
|
}
|
|
391
316
|
} catch {
|
|
392
|
-
formData.value =
|
|
317
|
+
formData.value = registry.initializeRecord(resolvedSchema.value)
|
|
393
318
|
}
|
|
394
319
|
}
|
|
395
320
|
} else {
|
|
396
|
-
formData.value =
|
|
321
|
+
formData.value = registry.initializeRecord(resolvedSchema.value)
|
|
397
322
|
}
|
|
398
323
|
|
|
399
324
|
if (hstStore.value) {
|
|
@@ -469,74 +394,31 @@ export function useStonecrop(options?: {
|
|
|
469
394
|
|
|
470
395
|
/**
|
|
471
396
|
* Load nested doctype data from API or initialize empty structure
|
|
397
|
+
* Delegates to Stonecrop.loadNestedData method
|
|
472
398
|
* @param parentPath - The parent path (e.g., "customer.123.address")
|
|
473
399
|
* @param childDoctype - The child doctype metadata
|
|
474
400
|
* @param recordId - Optional record ID to load
|
|
475
|
-
* @returns
|
|
401
|
+
* @returns The loaded or initialized data
|
|
476
402
|
*/
|
|
477
403
|
const loadNestedData = (parentPath: string, childDoctype: Doctype, recordId?: string): Record<string, any> => {
|
|
478
404
|
if (!stonecrop.value) {
|
|
479
|
-
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// If recordId provided, try to load existing data
|
|
483
|
-
if (recordId) {
|
|
484
|
-
try {
|
|
485
|
-
// Check if data already exists in HST
|
|
486
|
-
const existingData = hstStore.value?.get(parentPath)
|
|
487
|
-
if (existingData && typeof existingData === 'object') {
|
|
488
|
-
return existingData as Record<string, any>
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// TODO: Add API fetch logic here if needed
|
|
492
|
-
// For now, initialize new record
|
|
493
|
-
return initializeNewRecord(childDoctype)
|
|
494
|
-
} catch {
|
|
495
|
-
return initializeNewRecord(childDoctype)
|
|
496
|
-
}
|
|
405
|
+
throw new Error('Stonecrop instance not available')
|
|
497
406
|
}
|
|
498
|
-
|
|
499
|
-
// Initialize new record
|
|
500
|
-
return initializeNewRecord(childDoctype)
|
|
407
|
+
return stonecrop.value.loadNestedData(parentPath, childDoctype, recordId)
|
|
501
408
|
}
|
|
502
409
|
|
|
503
410
|
/**
|
|
504
|
-
*
|
|
411
|
+
* Collect a record payload with all nested doctype fields from HST
|
|
412
|
+
* Delegates to Stonecrop.collectRecordPayload method
|
|
505
413
|
* @param doctype - The doctype metadata
|
|
506
|
-
* @param recordId - The record ID to
|
|
507
|
-
* @returns The complete
|
|
414
|
+
* @param recordId - The record ID to collect
|
|
415
|
+
* @returns The complete record payload ready for API submission
|
|
508
416
|
*/
|
|
509
|
-
const
|
|
510
|
-
if (!
|
|
511
|
-
throw new Error('
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
const recordPath = `${doctype.slug}.${recordId}`
|
|
515
|
-
const recordData = hstStore.value.get(recordPath) || {}
|
|
516
|
-
|
|
517
|
-
// Build the save payload using resolved schema
|
|
518
|
-
const payload: Record<string, any> = { ...recordData }
|
|
519
|
-
|
|
520
|
-
// Use resolveSchema to get the full resolved tree, then walk Doctype fields
|
|
521
|
-
const schemaArray = doctype.schema
|
|
522
|
-
? Array.isArray(doctype.schema)
|
|
523
|
-
? doctype.schema
|
|
524
|
-
: Array.from(doctype.schema)
|
|
525
|
-
: []
|
|
526
|
-
const resolved = registry ? registry.resolveSchema(schemaArray) : schemaArray
|
|
527
|
-
const doctypeFields = resolved.filter(
|
|
528
|
-
field => 'fieldtype' in field && field.fieldtype === 'Doctype' && 'schema' in field && Array.isArray(field.schema)
|
|
529
|
-
)
|
|
530
|
-
|
|
531
|
-
// Recursively collect nested data from HST using resolved schemas
|
|
532
|
-
for (const field of doctypeFields) {
|
|
533
|
-
const doctypeField = field as DoctypeSchema
|
|
534
|
-
const fieldPath = `${recordPath}.${doctypeField.fieldname}`
|
|
535
|
-
const nestedData = collectNestedData(doctypeField.schema!, fieldPath, hstStore.value)
|
|
536
|
-
payload[doctypeField.fieldname] = nestedData
|
|
417
|
+
const collectRecordPayload = (doctype: Doctype, recordId: string): Record<string, any> => {
|
|
418
|
+
if (!stonecrop.value) {
|
|
419
|
+
throw new Error('Stonecrop instance not available')
|
|
537
420
|
}
|
|
538
|
-
|
|
539
|
-
return payload
|
|
421
|
+
return stonecrop.value.collectRecordPayload(doctype, recordId)
|
|
540
422
|
}
|
|
541
423
|
|
|
542
424
|
/**
|
|
@@ -599,7 +481,7 @@ export function useStonecrop(options?: {
|
|
|
599
481
|
formData,
|
|
600
482
|
resolvedSchema,
|
|
601
483
|
loadNestedData,
|
|
602
|
-
|
|
484
|
+
collectRecordPayload,
|
|
603
485
|
createNestedContext,
|
|
604
486
|
isLoading,
|
|
605
487
|
error,
|
|
@@ -616,7 +498,7 @@ export function useStonecrop(options?: {
|
|
|
616
498
|
formData,
|
|
617
499
|
resolvedSchema,
|
|
618
500
|
loadNestedData,
|
|
619
|
-
|
|
501
|
+
collectRecordPayload,
|
|
620
502
|
createNestedContext,
|
|
621
503
|
isLoading,
|
|
622
504
|
error,
|
|
@@ -631,45 +513,6 @@ export function useStonecrop(options?: {
|
|
|
631
513
|
} as BaseStonecropReturn
|
|
632
514
|
}
|
|
633
515
|
|
|
634
|
-
/**
|
|
635
|
-
* Initialize new record structure based on doctype schema
|
|
636
|
-
*/
|
|
637
|
-
function initializeNewRecord(doctype: Doctype): Record<string, any> {
|
|
638
|
-
const initialData: Record<string, any> = {}
|
|
639
|
-
|
|
640
|
-
if (!doctype.schema) {
|
|
641
|
-
return initialData
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
doctype.schema.forEach(field => {
|
|
645
|
-
const fieldtype = 'fieldtype' in field ? field.fieldtype : 'Data'
|
|
646
|
-
|
|
647
|
-
switch (fieldtype) {
|
|
648
|
-
case 'Data':
|
|
649
|
-
case 'Text':
|
|
650
|
-
initialData[field.fieldname] = ''
|
|
651
|
-
break
|
|
652
|
-
case 'Check':
|
|
653
|
-
initialData[field.fieldname] = false
|
|
654
|
-
break
|
|
655
|
-
case 'Int':
|
|
656
|
-
case 'Float':
|
|
657
|
-
initialData[field.fieldname] = 0
|
|
658
|
-
break
|
|
659
|
-
case 'Table':
|
|
660
|
-
initialData[field.fieldname] = []
|
|
661
|
-
break
|
|
662
|
-
case 'JSON':
|
|
663
|
-
initialData[field.fieldname] = {}
|
|
664
|
-
break
|
|
665
|
-
default:
|
|
666
|
-
initialData[field.fieldname] = null
|
|
667
|
-
}
|
|
668
|
-
})
|
|
669
|
-
|
|
670
|
-
return initialData
|
|
671
|
-
}
|
|
672
|
-
|
|
673
516
|
/**
|
|
674
517
|
* Setup deep reactivity between form data and HST store
|
|
675
518
|
*/
|
|
@@ -716,30 +559,3 @@ function updateNestedObject(obj: any, path: string[], value: any): void {
|
|
|
716
559
|
const finalKey = path[path.length - 1]
|
|
717
560
|
current[finalKey] = value
|
|
718
561
|
}
|
|
719
|
-
|
|
720
|
-
/**
|
|
721
|
-
* Recursively collect nested data from HST using pre-resolved schemas
|
|
722
|
-
* @param resolvedSchema - The already-resolved schema (with nested schemas embedded)
|
|
723
|
-
* @param basePath - The base path in HST (e.g., "customer.123.address")
|
|
724
|
-
* @param hstStore - The HST store instance
|
|
725
|
-
* @returns The collected data object
|
|
726
|
-
*/
|
|
727
|
-
function collectNestedData(resolvedSchema: SchemaTypes[], basePath: string, hstStore: HSTNode): Record<string, any> {
|
|
728
|
-
const data = hstStore.get(basePath) || {}
|
|
729
|
-
const payload: Record<string, any> = { ...data }
|
|
730
|
-
|
|
731
|
-
// Find Doctype fields that have resolved child schemas
|
|
732
|
-
const doctypeFields = resolvedSchema.filter(
|
|
733
|
-
field => 'fieldtype' in field && field.fieldtype === 'Doctype' && 'schema' in field && Array.isArray(field.schema)
|
|
734
|
-
)
|
|
735
|
-
|
|
736
|
-
// Recursively collect nested data
|
|
737
|
-
for (const field of doctypeFields) {
|
|
738
|
-
const doctypeField = field as DoctypeSchema
|
|
739
|
-
const fieldPath = `${basePath}.${doctypeField.fieldname}`
|
|
740
|
-
const nestedData = collectNestedData(doctypeField.schema!, fieldPath, hstStore)
|
|
741
|
-
payload[doctypeField.fieldname] = nestedData
|
|
742
|
-
}
|
|
743
|
-
|
|
744
|
-
return payload
|
|
745
|
-
}
|
package/src/doctype.ts
CHANGED
|
@@ -5,32 +5,7 @@ import { Component } from 'vue'
|
|
|
5
5
|
import type { UnknownMachineConfig } from 'xstate'
|
|
6
6
|
|
|
7
7
|
import type { ImmutableDoctype } from './types'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Plain object representation of doctype configuration for serialization/API responses.
|
|
11
|
-
* Compatible with the DoctypeMeta type from \@stonecrop/schema.
|
|
12
|
-
* @public
|
|
13
|
-
*/
|
|
14
|
-
export type DoctypeConfig = {
|
|
15
|
-
/** Display name of the doctype */
|
|
16
|
-
name: string
|
|
17
|
-
/** URL-friendly slug (kebab-case) */
|
|
18
|
-
slug?: string
|
|
19
|
-
/** Database table name */
|
|
20
|
-
tableName?: string
|
|
21
|
-
/** Field definitions */
|
|
22
|
-
fields?: SchemaTypes[]
|
|
23
|
-
/** Workflow configuration (XState format or simple WorkflowMeta) */
|
|
24
|
-
workflow?: UnknownMachineConfig | WorkflowMeta
|
|
25
|
-
/** Actions and their field triggers */
|
|
26
|
-
actions?: Record<string, string[]>
|
|
27
|
-
/** Parent doctype for inheritance */
|
|
28
|
-
inherits?: string
|
|
29
|
-
/** Doctype to use for list views */
|
|
30
|
-
listDoctype?: string
|
|
31
|
-
/** Parent doctype for child tables */
|
|
32
|
-
parentDoctype?: string
|
|
33
|
-
}
|
|
8
|
+
import type { DoctypeConfig } from './types/doctype'
|
|
34
9
|
|
|
35
10
|
/**
|
|
36
11
|
* Doctype runtime class with Immutable.js collections for HST change tracking.
|
|
@@ -249,9 +224,7 @@ export default class Doctype {
|
|
|
249
224
|
*
|
|
250
225
|
* @public
|
|
251
226
|
*/
|
|
252
|
-
getActionMeta(
|
|
253
|
-
actionName: string
|
|
254
|
-
):
|
|
227
|
+
getActionMeta(actionName: string):
|
|
255
228
|
| {
|
|
256
229
|
label: string
|
|
257
230
|
handler: string
|
package/src/field-triggers.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable no-new-func, no-eval */
|
|
2
1
|
import type { Map as ImmutableMap } from 'immutable'
|
|
3
2
|
import { useOperationLogStore } from './stores/operation-log'
|
|
4
3
|
import type {
|
|
@@ -101,11 +100,11 @@ export class FieldTriggerEngine {
|
|
|
101
100
|
const transitionMap = new Map<string, string[]>()
|
|
102
101
|
|
|
103
102
|
// Convert from different Map types to regular Map
|
|
104
|
-
//
|
|
105
|
-
|
|
103
|
+
// Check for Immutable.js Map first (has entrySeq method)
|
|
104
|
+
const immutableActions = actions as ImmutableMap<string, string[]>
|
|
105
|
+
if (typeof immutableActions.entrySeq === 'function') {
|
|
106
106
|
// Immutable Map
|
|
107
|
-
|
|
108
|
-
;(actions as any).entrySeq().forEach(([key, value]: [string, string[]]) => {
|
|
107
|
+
immutableActions.entrySeq().forEach(([key, value]: [string, string[]]) => {
|
|
109
108
|
this.categorizeAction(key, value, actionMap, transitionMap)
|
|
110
109
|
})
|
|
111
110
|
} else if (actions instanceof Map) {
|
|
@@ -506,7 +505,7 @@ export class FieldTriggerEngine {
|
|
|
506
505
|
})
|
|
507
506
|
.catch(error => {
|
|
508
507
|
clearTimeout(timeoutId)
|
|
509
|
-
reject(error)
|
|
508
|
+
reject(error instanceof Error ? error : new Error(String(error)))
|
|
510
509
|
})
|
|
511
510
|
})
|
|
512
511
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,8 +3,9 @@ export type * from '@stonecrop/atable/types'
|
|
|
3
3
|
|
|
4
4
|
import { useStonecrop } from './composables/stonecrop'
|
|
5
5
|
import { useOperationLog, useUndoRedoShortcuts, withBatch } from './composables/operation-log'
|
|
6
|
-
import Doctype
|
|
6
|
+
import Doctype from './doctype'
|
|
7
7
|
import {
|
|
8
|
+
FieldTriggerEngine,
|
|
8
9
|
getGlobalTriggerEngine,
|
|
9
10
|
markOperationIrreversible,
|
|
10
11
|
registerGlobalAction,
|
|
@@ -14,39 +15,29 @@ import {
|
|
|
14
15
|
} from './field-triggers'
|
|
15
16
|
import plugin from './plugins'
|
|
16
17
|
import Registry from './registry'
|
|
17
|
-
import {
|
|
18
|
+
import { Stonecrop, collectNestedData } from './stonecrop'
|
|
18
19
|
import { HST, createHST, type HSTNode } from './stores/hst'
|
|
19
20
|
import { useOperationLogStore } from './stores/operation-log'
|
|
20
|
-
// Export schema validator
|
|
21
21
|
import { SchemaValidator, createValidator, validateSchema } from './schema-validator'
|
|
22
|
+
import { ValidationSeverity } from './types/schema-validator'
|
|
23
|
+
|
|
24
|
+
// Export all types from ./types
|
|
22
25
|
export type * from './types'
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
export
|
|
26
|
-
FieldChangeContext,
|
|
27
|
-
TransitionChangeContext,
|
|
28
|
-
FieldTriggerExecutionResult,
|
|
29
|
-
ActionExecutionResult,
|
|
30
|
-
TransitionExecutionResult,
|
|
31
|
-
FieldActionFunction,
|
|
32
|
-
TransitionActionFunction,
|
|
33
|
-
} from './types/field-triggers'
|
|
34
|
-
// Export schema validator types
|
|
35
|
-
export type { ValidationIssue, ValidationResult, ValidatorOptions } from './schema-validator'
|
|
36
|
-
export { ValidationSeverity } from './schema-validator'
|
|
26
|
+
|
|
27
|
+
// Export enum as value (enums need runtime export, not just type)
|
|
28
|
+
export { ValidationSeverity }
|
|
37
29
|
|
|
38
30
|
export {
|
|
39
31
|
Doctype,
|
|
40
|
-
DoctypeConfig,
|
|
41
32
|
Registry,
|
|
42
33
|
Stonecrop,
|
|
43
|
-
StonecropOptions,
|
|
44
34
|
useStonecrop,
|
|
45
35
|
// HST exports for advanced usage
|
|
46
36
|
HST,
|
|
47
37
|
createHST,
|
|
48
38
|
HSTNode,
|
|
49
39
|
// Field trigger system exports
|
|
40
|
+
FieldTriggerEngine,
|
|
50
41
|
getGlobalTriggerEngine,
|
|
51
42
|
registerGlobalAction,
|
|
52
43
|
registerTransitionAction,
|
|
@@ -62,6 +53,8 @@ export {
|
|
|
62
53
|
useOperationLogStore,
|
|
63
54
|
useUndoRedoShortcuts,
|
|
64
55
|
withBatch,
|
|
56
|
+
// Utility functions
|
|
57
|
+
collectNestedData,
|
|
65
58
|
}
|
|
66
59
|
|
|
67
60
|
// Default export is the Vue plugin
|
package/src/plugins/index.ts
CHANGED
|
@@ -72,7 +72,10 @@ const plugin: Plugin = {
|
|
|
72
72
|
app.config.globalProperties.$registry = registry
|
|
73
73
|
|
|
74
74
|
// Create and provide a global Stonecrop instance
|
|
75
|
-
const stonecrop = new Stonecrop(registry
|
|
75
|
+
const stonecrop = new Stonecrop(registry)
|
|
76
|
+
if (options?.client) {
|
|
77
|
+
stonecrop.setClient(options.client)
|
|
78
|
+
}
|
|
76
79
|
app.provide('$stonecrop', stonecrop)
|
|
77
80
|
app.config.globalProperties.$stonecrop = stonecrop
|
|
78
81
|
|