@stonecrop/stonecrop 0.10.16 → 0.11.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.
- package/README.md +72 -29
- package/dist/composable.js +1 -0
- package/dist/composables/lazy-link.js +125 -0
- package/dist/composables/stonecrop.js +123 -68
- package/dist/composables/use-lazy-link-state.js +125 -0
- package/dist/composables/use-stonecrop.js +476 -0
- package/dist/doctype.js +10 -2
- package/dist/field-triggers.js +15 -3
- package/dist/index.js +4 -3
- package/dist/operation-log-DB-dGNT9.js +593 -0
- package/dist/operation-log-DB-dGNT9.js.map +1 -0
- package/dist/registry.js +261 -101
- package/dist/schema-validator.js +105 -1
- package/dist/src/composable.d.ts +11 -0
- package/dist/src/composable.d.ts.map +1 -0
- package/dist/src/composable.js +477 -0
- package/dist/src/composables/lazy-link.d.ts +25 -0
- package/dist/src/composables/lazy-link.d.ts.map +1 -0
- package/dist/src/composables/operation-log.d.ts +5 -5
- package/dist/src/composables/operation-log.d.ts.map +1 -1
- package/dist/src/composables/operation-log.js +224 -0
- package/dist/src/composables/stonecrop.d.ts +11 -1
- package/dist/src/composables/stonecrop.d.ts.map +1 -1
- package/dist/src/composables/stonecrop.js +574 -0
- package/dist/src/composables/use-lazy-link-state.d.ts +25 -0
- package/dist/src/composables/use-lazy-link-state.d.ts.map +1 -0
- package/dist/src/composables/use-stonecrop.d.ts +93 -0
- package/dist/src/composables/use-stonecrop.d.ts.map +1 -0
- package/dist/src/composables/useNestedSchema.d.ts +110 -0
- package/dist/src/composables/useNestedSchema.d.ts.map +1 -0
- package/dist/src/composables/useNestedSchema.js +155 -0
- package/dist/src/doctype.d.ts +9 -1
- package/dist/src/doctype.d.ts.map +1 -1
- package/dist/src/doctype.js +234 -0
- package/dist/src/exceptions.js +16 -0
- package/dist/src/field-triggers.d.ts +6 -0
- package/dist/src/field-triggers.d.ts.map +1 -1
- package/dist/src/field-triggers.js +567 -0
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +23 -0
- package/dist/src/plugins/index.js +96 -0
- package/dist/src/registry.d.ts +102 -23
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +246 -0
- package/dist/src/schema-validator.d.ts +8 -1
- package/dist/src/schema-validator.d.ts.map +1 -1
- package/dist/src/schema-validator.js +315 -0
- package/dist/src/stonecrop.d.ts +73 -28
- package/dist/src/stonecrop.d.ts.map +1 -1
- package/dist/src/stonecrop.js +339 -0
- package/dist/src/stores/data.d.ts +11 -0
- package/dist/src/stores/data.d.ts.map +1 -0
- package/dist/src/stores/hst.d.ts +5 -75
- package/dist/src/stores/hst.d.ts.map +1 -1
- package/dist/src/stores/hst.js +495 -0
- package/dist/src/stores/index.js +12 -0
- package/dist/src/stores/operation-log.d.ts +14 -14
- package/dist/src/stores/operation-log.d.ts.map +1 -1
- package/dist/src/stores/operation-log.js +568 -0
- package/dist/src/stores/xstate.d.ts +31 -0
- package/dist/src/stores/xstate.d.ts.map +1 -0
- package/dist/src/tsdoc-metadata.json +11 -0
- package/dist/src/types/composable.d.ts +50 -12
- package/dist/src/types/composable.d.ts.map +1 -1
- package/dist/src/types/doctype.d.ts +6 -7
- package/dist/src/types/doctype.d.ts.map +1 -1
- package/dist/src/types/field-triggers.d.ts +1 -1
- package/dist/src/types/field-triggers.d.ts.map +1 -1
- package/dist/src/types/field-triggers.js +4 -0
- package/dist/src/types/hst.d.ts +70 -0
- package/dist/src/types/hst.d.ts.map +1 -0
- package/dist/src/types/index.d.ts +1 -0
- package/dist/src/types/index.d.ts.map +1 -1
- package/dist/src/types/index.js +4 -0
- package/dist/src/types/operation-log.d.ts +4 -4
- package/dist/src/types/operation-log.d.ts.map +1 -1
- package/dist/src/types/operation-log.js +0 -0
- package/dist/src/types/registry.js +0 -0
- package/dist/src/types/schema-validator.d.ts +2 -0
- package/dist/src/types/schema-validator.d.ts.map +1 -1
- package/dist/src/utils.d.ts +24 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/stonecrop.d.ts +317 -99
- package/dist/stonecrop.js +2191 -1897
- package/dist/stonecrop.js.map +1 -1
- package/dist/stonecrop.umd.cjs +6 -0
- package/dist/stonecrop.umd.cjs.map +1 -0
- package/dist/stores/data.js +7 -0
- package/dist/stores/hst.js +27 -25
- package/dist/stores/operation-log.js +59 -47
- package/dist/stores/xstate.js +29 -0
- package/dist/tests/setup.d.ts +5 -0
- package/dist/tests/setup.d.ts.map +1 -0
- package/dist/tests/setup.js +15 -0
- package/dist/types/hst.js +0 -0
- package/dist/types/index.js +1 -0
- package/dist/utils.js +46 -0
- package/package.json +5 -5
- package/src/composables/lazy-link.ts +146 -0
- package/src/composables/operation-log.ts +1 -1
- package/src/composables/stonecrop.ts +142 -73
- package/src/doctype.ts +13 -4
- package/src/field-triggers.ts +18 -4
- package/src/index.ts +4 -2
- package/src/registry.ts +289 -111
- package/src/schema-validator.ts +120 -1
- package/src/stonecrop.ts +230 -106
- package/src/stores/hst.ts +29 -104
- package/src/stores/operation-log.ts +64 -50
- package/src/types/composable.ts +55 -12
- package/src/types/doctype.ts +6 -7
- package/src/types/field-triggers.ts +1 -1
- package/src/types/hst.ts +77 -0
- package/src/types/index.ts +1 -0
- package/src/types/operation-log.ts +4 -4
- package/src/types/schema-validator.ts +2 -0
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { defineStore } from 'pinia'
|
|
2
2
|
import { ref, computed, watch } from 'vue'
|
|
3
3
|
import { useLocalStorage } from '@vueuse/core'
|
|
4
|
+
|
|
5
|
+
import type { HSTNode } from './hst'
|
|
4
6
|
import type {
|
|
7
|
+
CrossTabMessage,
|
|
5
8
|
HSTOperation,
|
|
6
9
|
HSTOperationInput,
|
|
7
10
|
OperationLogConfig,
|
|
8
|
-
UndoRedoState,
|
|
9
11
|
OperationLogSnapshot,
|
|
10
|
-
CrossTabMessage,
|
|
11
12
|
OperationSource,
|
|
13
|
+
UndoRedoState,
|
|
12
14
|
} from '../types/operation-log'
|
|
13
|
-
import type { HSTNode } from './hst'
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Generate a UUID using crypto API or fallback
|
|
@@ -107,8 +108,7 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
107
108
|
const currentIndex = ref(-1) // Points to the last applied operation
|
|
108
109
|
const clientId = ref(generateId())
|
|
109
110
|
const batchMode = ref(false)
|
|
110
|
-
const
|
|
111
|
-
const currentBatchId = ref<string | null>(null)
|
|
111
|
+
const batchStack = ref<{ id: string; operations: HSTOperation[] }[]>([])
|
|
112
112
|
|
|
113
113
|
// Computed
|
|
114
114
|
const canUndo = computed(() => {
|
|
@@ -183,9 +183,9 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
183
183
|
return fullOperation.id
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
// If in batch mode, collect operations
|
|
187
|
-
if (batchMode.value) {
|
|
188
|
-
|
|
186
|
+
// If in batch mode, collect operations in current batch
|
|
187
|
+
if (batchMode.value && batchStack.value.length > 0) {
|
|
188
|
+
batchStack.value[batchStack.value.length - 1].operations.push(fullOperation)
|
|
189
189
|
return fullOperation.id
|
|
190
190
|
}
|
|
191
191
|
|
|
@@ -218,25 +218,35 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
218
218
|
*/
|
|
219
219
|
function startBatch() {
|
|
220
220
|
batchMode.value = true
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
batchStack.value.push({
|
|
222
|
+
id: generateId(),
|
|
223
|
+
operations: [],
|
|
224
|
+
})
|
|
223
225
|
}
|
|
224
226
|
|
|
225
227
|
/**
|
|
226
228
|
* Commit batch - create a single batch operation
|
|
227
229
|
*/
|
|
228
230
|
function commitBatch(description?: string): string | null {
|
|
229
|
-
if (!batchMode.value ||
|
|
230
|
-
batchMode.value = false
|
|
231
|
-
currentBatch.value = []
|
|
232
|
-
currentBatchId.value = null
|
|
231
|
+
if (!batchMode.value || batchStack.value.length === 0) {
|
|
233
232
|
return null
|
|
234
233
|
}
|
|
235
234
|
|
|
236
|
-
const
|
|
237
|
-
const
|
|
235
|
+
const currentBatchData = batchStack.value.pop()!
|
|
236
|
+
const batchOperations = currentBatchData.operations
|
|
238
237
|
|
|
239
|
-
|
|
238
|
+
if (batchOperations.length === 0) {
|
|
239
|
+
// Empty batch - just pop and continue if there are outer batches
|
|
240
|
+
if (batchStack.value.length === 0) {
|
|
241
|
+
batchMode.value = false
|
|
242
|
+
}
|
|
243
|
+
return null
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const batchId = currentBatchData.id
|
|
247
|
+
const allReversible = batchOperations.every(op => op.reversible)
|
|
248
|
+
|
|
249
|
+
// Create ancestor batch operation
|
|
240
250
|
const batchOperation: HSTOperation = {
|
|
241
251
|
id: batchId,
|
|
242
252
|
type: 'batch',
|
|
@@ -244,45 +254,49 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
244
254
|
fieldname: '',
|
|
245
255
|
beforeValue: null,
|
|
246
256
|
afterValue: null,
|
|
247
|
-
doctype:
|
|
257
|
+
doctype: batchOperations[0]?.doctype || '',
|
|
248
258
|
timestamp: new Date(),
|
|
249
259
|
source: 'user',
|
|
250
260
|
reversible: allReversible,
|
|
251
261
|
irreversibleReason: allReversible ? undefined : 'Contains irreversible operations',
|
|
252
|
-
|
|
262
|
+
descendantOperationIds: batchOperations.map(op => op.id),
|
|
253
263
|
metadata: { description },
|
|
254
264
|
}
|
|
255
265
|
|
|
256
|
-
// Add
|
|
257
|
-
|
|
258
|
-
op.
|
|
266
|
+
// Add ancestor operation ID to all descendants
|
|
267
|
+
batchOperations.forEach(op => {
|
|
268
|
+
op.ancestorOperationId = batchId
|
|
259
269
|
})
|
|
260
270
|
|
|
261
|
-
//
|
|
262
|
-
|
|
263
|
-
|
|
271
|
+
// If we're inside a ancestor batch, add this batch as a descendant of the ancestor
|
|
272
|
+
if (batchStack.value.length > 0) {
|
|
273
|
+
// Nested batch - add the batch operation to the ancestor batch
|
|
274
|
+
batchStack.value[batchStack.value.length - 1].operations.push(batchOperation)
|
|
275
|
+
} else {
|
|
276
|
+
// Top-level batch - add to the operations log
|
|
277
|
+
operations.value.push(...batchOperations, batchOperation)
|
|
278
|
+
currentIndex.value = operations.value.length - 1
|
|
279
|
+
}
|
|
264
280
|
|
|
265
281
|
// Broadcast batch
|
|
266
282
|
if (config.value.enableCrossTabSync) {
|
|
267
|
-
broadcastBatch(
|
|
283
|
+
broadcastBatch(batchOperations, batchOperation)
|
|
268
284
|
}
|
|
269
285
|
|
|
270
|
-
//
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
currentBatchId.value = null
|
|
286
|
+
// If no more batches on stack, exit batch mode
|
|
287
|
+
if (batchStack.value.length === 0) {
|
|
288
|
+
batchMode.value = false
|
|
289
|
+
}
|
|
275
290
|
|
|
276
|
-
return
|
|
291
|
+
return batchId
|
|
277
292
|
}
|
|
278
293
|
|
|
279
294
|
/**
|
|
280
295
|
* Cancel batch mode without committing
|
|
281
296
|
*/
|
|
282
297
|
function cancelBatch() {
|
|
298
|
+
batchStack.value = []
|
|
283
299
|
batchMode.value = false
|
|
284
|
-
currentBatch.value = []
|
|
285
|
-
currentBatchId.value = null
|
|
286
300
|
}
|
|
287
301
|
|
|
288
302
|
/**
|
|
@@ -304,13 +318,13 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
304
318
|
|
|
305
319
|
try {
|
|
306
320
|
// Handle batch operations
|
|
307
|
-
if (operation.type === 'batch' && operation.
|
|
308
|
-
// Undo all
|
|
309
|
-
for (let i = operation.
|
|
310
|
-
const
|
|
311
|
-
const
|
|
312
|
-
if (
|
|
313
|
-
revertOperation(
|
|
321
|
+
if (operation.type === 'batch' && operation.descendantOperationIds) {
|
|
322
|
+
// Undo all descendant operations in reverse order
|
|
323
|
+
for (let i = operation.descendantOperationIds.length - 1; i >= 0; i--) {
|
|
324
|
+
const descendantId = operation.descendantOperationIds[i]
|
|
325
|
+
const descendantOp = operations.value.find(op => op.id === descendantId)
|
|
326
|
+
if (descendantOp) {
|
|
327
|
+
revertOperation(descendantOp, store)
|
|
314
328
|
}
|
|
315
329
|
}
|
|
316
330
|
} else {
|
|
@@ -346,12 +360,12 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
346
360
|
|
|
347
361
|
try {
|
|
348
362
|
// Handle batch operations
|
|
349
|
-
if (operation.type === 'batch' && operation.
|
|
350
|
-
// Redo all
|
|
351
|
-
for (const
|
|
352
|
-
const
|
|
353
|
-
if (
|
|
354
|
-
applyOperation(
|
|
363
|
+
if (operation.type === 'batch' && operation.descendantOperationIds) {
|
|
364
|
+
// Redo all descendant operations in order
|
|
365
|
+
for (const descendantId of operation.descendantOperationIds) {
|
|
366
|
+
const descendantOp = operations.value.find(op => op.id === descendantId)
|
|
367
|
+
if (descendantOp) {
|
|
368
|
+
applyOperation(descendantOp, store)
|
|
355
369
|
}
|
|
356
370
|
}
|
|
357
371
|
} else {
|
|
@@ -525,12 +539,12 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
525
539
|
broadcastChannel.postMessage(serializeForBroadcast(message))
|
|
526
540
|
}
|
|
527
541
|
|
|
528
|
-
function broadcastBatch(
|
|
542
|
+
function broadcastBatch(descendantOps: HSTOperation[], batchOp: HSTOperation) {
|
|
529
543
|
if (!broadcastChannel) return
|
|
530
544
|
|
|
531
545
|
const message: CrossTabMessage = {
|
|
532
546
|
type: 'operation',
|
|
533
|
-
operations: [...
|
|
547
|
+
operations: [...descendantOps, batchOp],
|
|
534
548
|
clientId: clientId.value,
|
|
535
549
|
timestamp: new Date(),
|
|
536
550
|
}
|
|
@@ -567,7 +581,7 @@ export const useOperationLogStore = defineStore('hst-operation-log', () => {
|
|
|
567
581
|
currentIndex: number
|
|
568
582
|
}
|
|
569
583
|
|
|
570
|
-
const persistedData = useLocalStorage<PersistedData | null>('stonecrop-
|
|
584
|
+
const persistedData = useLocalStorage<PersistedData | null>('stonecrop-operations', null, {
|
|
571
585
|
serializer: {
|
|
572
586
|
read: (v: string) => {
|
|
573
587
|
try {
|
package/src/types/composable.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { SchemaTypes } from '@stonecrop/aform'
|
|
1
|
+
import type { SchemaTypes } from '@stonecrop/aform'
|
|
2
2
|
import type { Ref, ComputedRef } from 'vue'
|
|
3
3
|
|
|
4
4
|
import type Doctype from '../doctype'
|
|
5
|
-
import type { HSTNode } from '
|
|
5
|
+
import type { HSTNode } from './hst'
|
|
6
6
|
import type { HSTOperation, OperationLogConfig, OperationLogSnapshot } from './operation-log'
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -179,14 +179,28 @@ export type HSTStonecropReturn = BaseStonecropReturn & {
|
|
|
179
179
|
*/
|
|
180
180
|
resolvedSchema: Ref<SchemaTypes[]>
|
|
181
181
|
/**
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
* @param
|
|
185
|
-
* @param childDoctype - The nested doctype metadata
|
|
186
|
-
* @param recordId - Optional record ID (reserved for future API fetch)
|
|
187
|
-
* @returns The loaded or initialized data object
|
|
182
|
+
* Scaffold empty descendant records from defaults for all descendant links.
|
|
183
|
+
* @param path - The HST path where initialized data should be stored
|
|
184
|
+
* @param doctype - The doctype to initialize
|
|
188
185
|
*/
|
|
189
|
-
|
|
186
|
+
initializeNestedData: (path: string, doctype: Doctype) => void
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Fetch a record and its nested data from the server.
|
|
190
|
+
* Stores each field at its own HST path per the field-level convention.
|
|
191
|
+
* @param path - The HST path (e.g., "recipe.r1")
|
|
192
|
+
* @param doctype - The doctype to fetch
|
|
193
|
+
* @param recordId - Record ID to fetch
|
|
194
|
+
* @param options - Query options (includeNested to control which links are fetched)
|
|
195
|
+
* @throws Error with code "CLIENT_REQUIRED" if no data client is configured
|
|
196
|
+
* @throws Error with code "RECORD_NOT_FOUND" if the server returns null
|
|
197
|
+
*/
|
|
198
|
+
fetchNestedData: (
|
|
199
|
+
path: string,
|
|
200
|
+
doctype: Doctype,
|
|
201
|
+
recordId: string,
|
|
202
|
+
options?: { includeNested?: boolean | string[] }
|
|
203
|
+
) => Promise<void>
|
|
190
204
|
/**
|
|
191
205
|
* Collects a complete record payload with all nested data from HST.
|
|
192
206
|
* Use this before submitting to an API. Recursively includes 1:1 and 1:many nested records.
|
|
@@ -196,15 +210,15 @@ export type HSTStonecropReturn = BaseStonecropReturn & {
|
|
|
196
210
|
*/
|
|
197
211
|
collectRecordPayload: (doctype: Doctype, recordId: string) => Record<string, any>
|
|
198
212
|
/**
|
|
199
|
-
* Creates a nested context for a
|
|
213
|
+
* Creates a nested context for a descendant doctype component.
|
|
200
214
|
* Use this in parent components to pass scoped handlers to child components.
|
|
201
215
|
* @param basePath - The parent HST path prefix
|
|
202
|
-
* @param
|
|
216
|
+
* @param descendantDoctype - The descendant doctype metadata
|
|
203
217
|
* @returns Scoped provideHSTPath and handleHSTChange functions
|
|
204
218
|
*/
|
|
205
219
|
createNestedContext: (
|
|
206
220
|
basePath: string,
|
|
207
|
-
|
|
221
|
+
descendantDoctype: Doctype
|
|
208
222
|
) => {
|
|
209
223
|
provideHSTPath: (fieldname: string) => string
|
|
210
224
|
handleHSTChange: (changeData: HSTChangeData) => void
|
|
@@ -224,6 +238,17 @@ export type HSTStonecropReturn = BaseStonecropReturn & {
|
|
|
224
238
|
* Available immediately if Doctype instance passed, after async resolution if slug string passed.
|
|
225
239
|
*/
|
|
226
240
|
resolvedDoctype: Ref<Doctype | undefined>
|
|
241
|
+
/**
|
|
242
|
+
* Computed ref indicating whether workflow actions are ready to run.
|
|
243
|
+
* True when all links with blockWorkflows are loaded in HST.
|
|
244
|
+
* Use with v-bind:disabled="!isWorkflowReady" on action buttons.
|
|
245
|
+
*/
|
|
246
|
+
isWorkflowReady: ComputedRef<boolean>
|
|
247
|
+
/**
|
|
248
|
+
* List of link fieldnames that are blocking workflow execution.
|
|
249
|
+
* Empty array when isWorkflowReady is true.
|
|
250
|
+
*/
|
|
251
|
+
blockedLinks: ComputedRef<string[]>
|
|
227
252
|
}
|
|
228
253
|
|
|
229
254
|
// Import Stonecrop class for the BaseStonecropReturn type (circular reference handled via import)
|
|
@@ -243,3 +268,21 @@ export type HSTChangeData = {
|
|
|
243
268
|
/** Optional record ID */
|
|
244
269
|
recordId?: string
|
|
245
270
|
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Lazy link state for a single link field.
|
|
274
|
+
* Provides reactive state and reload capability for lazy-loaded links.
|
|
275
|
+
* @public
|
|
276
|
+
*/
|
|
277
|
+
export type LazyLink = {
|
|
278
|
+
/** True while fetching data */
|
|
279
|
+
loading: Ref<boolean>
|
|
280
|
+
/** True after successful fetch (permanent until reload) */
|
|
281
|
+
loaded: Ref<boolean>
|
|
282
|
+
/** Error state, if any */
|
|
283
|
+
error: Ref<Error | null>
|
|
284
|
+
/** Explicitly trigger a fetch for this link */
|
|
285
|
+
reload: () => Promise<void>
|
|
286
|
+
/** The loaded data from HST, or undefined if not loaded */
|
|
287
|
+
data: ComputedRef<any>
|
|
288
|
+
}
|
package/src/types/doctype.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SchemaTypes } from '@stonecrop/aform'
|
|
2
|
-
import type { WorkflowMeta } from '@stonecrop/schema'
|
|
2
|
+
import type { LinkDeclaration, WorkflowMeta } from '@stonecrop/schema'
|
|
3
3
|
import { List, Map } from 'immutable'
|
|
4
4
|
import type { AnyStateNodeConfig, UnknownMachineConfig } from 'xstate'
|
|
5
5
|
|
|
@@ -11,6 +11,7 @@ export type ImmutableDoctype = {
|
|
|
11
11
|
readonly schema?: List<SchemaTypes>
|
|
12
12
|
readonly workflow?: UnknownMachineConfig | AnyStateNodeConfig | WorkflowMeta
|
|
13
13
|
readonly actions?: Map<string, string[]>
|
|
14
|
+
readonly links?: Record<string, LinkDeclaration>
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
/**
|
|
@@ -45,16 +46,14 @@ export type DoctypeConfig = {
|
|
|
45
46
|
slug?: string
|
|
46
47
|
/** Database table name */
|
|
47
48
|
tableName?: string
|
|
48
|
-
/** Field definitions */
|
|
49
|
+
/** Field definitions (including link fields with fieldtype: 'Link') */
|
|
49
50
|
fields?: SchemaTypes[]
|
|
51
|
+
/** Relationship links to other doctypes */
|
|
52
|
+
links?: Record<string, LinkDeclaration>
|
|
50
53
|
/** Workflow configuration (XState format or simple WorkflowMeta) */
|
|
51
54
|
workflow?: UnknownMachineConfig | WorkflowMeta
|
|
52
55
|
/** Actions and their field triggers */
|
|
53
56
|
actions?: Record<string, string[]>
|
|
54
|
-
/**
|
|
57
|
+
/** Ancestor doctype for inheritance */
|
|
55
58
|
inherits?: string
|
|
56
|
-
/** Doctype to use for list views */
|
|
57
|
-
listDoctype?: string
|
|
58
|
-
/** Parent doctype for child tables */
|
|
59
|
-
parentDoctype?: string
|
|
60
59
|
}
|
package/src/types/hst.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core HST Interface - enhanced with tree navigation
|
|
3
|
+
* Provides a hierarchical state tree interface for navigating and manipulating nested data structures.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export interface HSTNode {
|
|
8
|
+
/**
|
|
9
|
+
* Gets a value at the specified path
|
|
10
|
+
* @param path - The dot-separated path to the value
|
|
11
|
+
* @returns The value at the specified path
|
|
12
|
+
*/
|
|
13
|
+
get(path: string): any
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Sets a value at the specified path
|
|
17
|
+
* @param path - The dot-separated path where to set the value
|
|
18
|
+
* @param value - The value to set
|
|
19
|
+
* @param source - Optional source of the operation (user, system, sync, undo, redo)
|
|
20
|
+
*/
|
|
21
|
+
set(path: string, value: any, source?: 'user' | 'system' | 'sync' | 'undo' | 'redo'): void
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Checks if a value exists at the specified path
|
|
25
|
+
* @param path - The dot-separated path to check
|
|
26
|
+
* @returns True if the path exists, false otherwise
|
|
27
|
+
*/
|
|
28
|
+
has(path: string): boolean
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Gets the ancestor node in the tree hierarchy (immediate predecessor)
|
|
32
|
+
* @returns The ancestor HSTNode or null if this is the root
|
|
33
|
+
*/
|
|
34
|
+
getAncestor(): HSTNode | null
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Gets the root node of the tree
|
|
38
|
+
* @returns The root HSTNode
|
|
39
|
+
*/
|
|
40
|
+
getRoot(): HSTNode
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Gets the full path from root to this node
|
|
44
|
+
* @returns The dot-separated path string
|
|
45
|
+
*/
|
|
46
|
+
getPath(): string
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Gets the depth level of this node in the tree
|
|
50
|
+
* @returns The depth as a number (0 for root)
|
|
51
|
+
*/
|
|
52
|
+
getDepth(): number
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Gets an array of path segments from root to this node
|
|
56
|
+
* @returns Array of path segments representing breadcrumbs
|
|
57
|
+
*/
|
|
58
|
+
getBreadcrumbs(): string[]
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Gets a child node at the specified relative path
|
|
62
|
+
* @param path - The relative path to the child node
|
|
63
|
+
* @returns The child HSTNode
|
|
64
|
+
*/
|
|
65
|
+
getNode(path: string): HSTNode
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Trigger an XState transition with optional context data
|
|
69
|
+
* @param transition - The transition name (should be uppercase per convention)
|
|
70
|
+
* @param context - Optional additional FSM context data
|
|
71
|
+
* @returns Promise resolving to the transition execution results
|
|
72
|
+
*/
|
|
73
|
+
triggerTransition(
|
|
74
|
+
transition: string,
|
|
75
|
+
context?: { currentState?: string; targetState?: string; fsmContext?: Record<string, any> }
|
|
76
|
+
): Promise<any>
|
|
77
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -79,11 +79,11 @@ export interface HSTOperation {
|
|
|
79
79
|
/** Additional metadata for custom use cases */
|
|
80
80
|
metadata?: Record<string, any>
|
|
81
81
|
|
|
82
|
-
/**
|
|
83
|
-
|
|
82
|
+
/** Ancestor operation ID for batch operations */
|
|
83
|
+
ancestorOperationId?: string
|
|
84
84
|
|
|
85
|
-
/**
|
|
86
|
-
|
|
85
|
+
/** Descendant operation IDs for batch operations */
|
|
86
|
+
descendantOperationIds?: string[]
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
/**
|
|
@@ -58,6 +58,8 @@ export interface ValidatorOptions {
|
|
|
58
58
|
registry?: Registry
|
|
59
59
|
/** Whether to validate Link field targets */
|
|
60
60
|
validateLinkTargets?: boolean
|
|
61
|
+
/** Whether to validate links object (target resolution, backlink consistency, Link field correspondence) */
|
|
62
|
+
validateLinks?: boolean
|
|
61
63
|
/** Whether to validate workflow reachability */
|
|
62
64
|
validateWorkflows?: boolean
|
|
63
65
|
/** Whether to validate action registration */
|