@stonecrop/stonecrop 0.10.12 → 0.10.14

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 (50) hide show
  1. package/dist/composables/stonecrop.js +19 -144
  2. package/dist/index.js +9 -6
  3. package/dist/plugins/index.js +4 -1
  4. package/dist/schema-validator.js +1 -13
  5. package/dist/src/composables/stonecrop.d.ts +2 -74
  6. package/dist/src/composables/stonecrop.d.ts.map +1 -1
  7. package/dist/src/doctype.d.ts +1 -27
  8. package/dist/src/doctype.d.ts.map +1 -1
  9. package/dist/src/index.d.ts +6 -9
  10. package/dist/src/index.d.ts.map +1 -1
  11. package/dist/src/plugins/index.d.ts.map +1 -1
  12. package/dist/src/schema-validator.d.ts +1 -62
  13. package/dist/src/schema-validator.d.ts.map +1 -1
  14. package/dist/src/stonecrop.d.ts +38 -17
  15. package/dist/src/stonecrop.d.ts.map +1 -1
  16. package/dist/src/stores/operation-log.d.ts +1 -1
  17. package/dist/src/types/composable.d.ts +230 -0
  18. package/dist/src/types/composable.d.ts.map +1 -0
  19. package/dist/src/types/doctype.d.ts +57 -0
  20. package/dist/src/types/doctype.d.ts.map +1 -0
  21. package/dist/src/types/index.d.ts +6 -67
  22. package/dist/src/types/index.d.ts.map +1 -1
  23. package/dist/src/types/plugin.d.ts +37 -0
  24. package/dist/src/types/plugin.d.ts.map +1 -0
  25. package/dist/src/types/schema-validator.d.ts +64 -0
  26. package/dist/src/types/schema-validator.d.ts.map +1 -0
  27. package/dist/src/types/stonecrop.d.ts +17 -0
  28. package/dist/src/types/stonecrop.d.ts.map +1 -0
  29. package/dist/stonecrop.d.ts +192 -3
  30. package/dist/stonecrop.js +1509 -1517
  31. package/dist/stonecrop.js.map +1 -1
  32. package/dist/types/composable.js +0 -0
  33. package/dist/types/doctype.js +0 -0
  34. package/dist/types/index.js +7 -2
  35. package/dist/types/plugin.js +0 -0
  36. package/dist/types/schema-validator.js +13 -0
  37. package/dist/types/stonecrop.js +0 -0
  38. package/package.json +5 -5
  39. package/src/composables/stonecrop.ts +26 -266
  40. package/src/doctype.ts +2 -29
  41. package/src/index.ts +12 -19
  42. package/src/plugins/index.ts +4 -1
  43. package/src/schema-validator.ts +3 -66
  44. package/src/stonecrop.ts +147 -16
  45. package/src/types/composable.ts +245 -0
  46. package/src/types/doctype.ts +60 -0
  47. package/src/types/index.ts +7 -74
  48. package/src/types/plugin.ts +38 -0
  49. package/src/types/schema-validator.ts +67 -0
  50. package/src/types/stonecrop.ts +17 -0
package/src/stonecrop.ts CHANGED
@@ -1,3 +1,10 @@
1
+ import {
2
+ type DoctypeManySchema,
3
+ type DoctypeOneSchema,
4
+ type DoctypeSchema,
5
+ type SchemaTypes,
6
+ isDoctypeMany,
7
+ } from '@stonecrop/aform'
1
8
  import type { DataClient } from '@stonecrop/schema'
2
9
  import { reactive } from 'vue'
3
10
 
@@ -7,28 +14,21 @@ import { createHST, type HSTNode } from './stores/hst'
7
14
  import { useOperationLogStore } from './stores/operation-log'
8
15
  import type { OperationLogConfig } from './types/operation-log'
9
16
  import type { RouteContext } from './types/registry'
17
+ import type { StonecropOptions } from './types/stonecrop'
10
18
 
11
19
  /**
12
- * Options for constructing a Stonecrop instance directly.
13
- * When using the Vue plugin, pass these via `InstallOptions` instead.
20
+ * Main Stonecrop class with HST integration and built-in Operation Log
14
21
  * @public
15
22
  */
16
- export interface StonecropOptions {
23
+ export class Stonecrop {
17
24
  /**
18
- * Data client for fetching doctype metadata and records.
19
- * Use \@stonecrop/graphql-client's StonecropClient for GraphQL backends,
20
- * or implement DataClient for custom data sources.
21
- *
22
- * Can be set later via `setClient()` for deferred configuration.
25
+ * Singleton instance of Stonecrop. Only one Stonecrop instance can exist
26
+ * per application, ensuring consistent HST state and registry access.
27
+ * Subsequent constructor calls return this instance instead of creating new ones.
28
+ * @internal
23
29
  */
24
- client?: DataClient
25
- }
30
+ static _root: Stonecrop
26
31
 
27
- /**
28
- * Main Stonecrop class with HST integration and built-in Operation Log
29
- * @public
30
- */
31
- export class Stonecrop {
32
32
  private hstStore: HSTNode
33
33
  private _operationLogStore?: ReturnType<typeof useOperationLogStore>
34
34
  private _operationLogConfig?: Partial<OperationLogConfig>
@@ -38,12 +38,17 @@ export class Stonecrop {
38
38
  readonly registry: Registry
39
39
 
40
40
  /**
41
- * Creates a new Stonecrop instance with HST integration
41
+ * Creates a new Stonecrop instance with HST integration (singleton pattern)
42
42
  * @param registry - The Registry instance containing doctype definitions
43
43
  * @param operationLogConfig - Optional configuration for the operation log
44
44
  * @param options - Options including the data client (can be set later via setClient)
45
45
  */
46
46
  constructor(registry: Registry, operationLogConfig?: Partial<OperationLogConfig>, options?: StonecropOptions) {
47
+ if (Stonecrop._root) {
48
+ return Stonecrop._root
49
+ }
50
+ Stonecrop._root = this
51
+
47
52
  this.registry = registry
48
53
 
49
54
  // Store config for lazy initialization
@@ -417,4 +422,130 @@ export class Stonecrop {
417
422
 
418
423
  return status || initialState
419
424
  }
425
+
426
+ /**
427
+ * Collect a record payload with all nested doctype fields from HST
428
+ * @param doctype - The doctype metadata
429
+ * @param recordId - The record ID to collect
430
+ * @returns The complete record payload ready for API submission
431
+ * @public
432
+ */
433
+ collectRecordPayload(doctype: Doctype, recordId: string): Record<string, any> {
434
+ const recordPath = `${doctype.slug}.${recordId}`
435
+ const recordData = this.hstStore.get(recordPath) || {}
436
+
437
+ const payload: Record<string, any> = { ...recordData }
438
+
439
+ const schemaArray = doctype.schema
440
+ ? Array.isArray(doctype.schema)
441
+ ? doctype.schema
442
+ : Array.from(doctype.schema)
443
+ : []
444
+ const resolved = this.registry.resolveSchema(schemaArray)
445
+
446
+ const doctypeFields = resolved.filter(
447
+ field =>
448
+ 'fieldtype' in field &&
449
+ field.fieldtype === 'Doctype' &&
450
+ !isDoctypeMany(field as DoctypeSchema) &&
451
+ 'schema' in field &&
452
+ Array.isArray(field.schema)
453
+ )
454
+
455
+ for (const field of doctypeFields) {
456
+ const doctypeField = field as DoctypeOneSchema
457
+ const fieldPath = `${recordPath}.${doctypeField.fieldname}`
458
+ const nestedData = collectNestedData(doctypeField.schema!, fieldPath, this.hstStore)
459
+ payload[doctypeField.fieldname] = nestedData
460
+ }
461
+
462
+ const doctypeManyFields = resolved.filter(
463
+ field => 'fieldtype' in field && field.fieldtype === 'Doctype' && isDoctypeMany(field as DoctypeSchema)
464
+ )
465
+
466
+ for (const field of doctypeManyFields) {
467
+ const doctypeField = field as DoctypeManySchema
468
+ const fieldPath = `${recordPath}.${doctypeField.fieldname}`
469
+ const arrayData = this.hstStore.get(fieldPath)
470
+ if (Array.isArray(arrayData)) {
471
+ payload[doctypeField.fieldname] = arrayData
472
+ }
473
+ }
474
+
475
+ return payload
476
+ }
477
+
478
+ /**
479
+ * Load nested data from HST or initialize with defaults
480
+ * @param parentPath - The HST path to check for existing data
481
+ * @param childDoctype - The child doctype metadata
482
+ * @param _recordId - Optional record ID to load
483
+ * @returns The loaded or initialized data
484
+ * @public
485
+ */
486
+ loadNestedData(parentPath: string, childDoctype: Doctype, _recordId?: string): Record<string, any> {
487
+ // Check if data already exists in HST
488
+ const existingData = this.hstStore.get(parentPath)
489
+ if (existingData && typeof existingData === 'object') {
490
+ return existingData as Record<string, any>
491
+ }
492
+
493
+ // TODO: If recordId provided and no HST data, fetch from API using this._client
494
+ // For now, always fall through to initialize new record
495
+
496
+ // Resolve schema and initialize with defaults
497
+ const schemaArray = childDoctype.schema
498
+ ? Array.isArray(childDoctype.schema)
499
+ ? childDoctype.schema
500
+ : Array.from(childDoctype.schema)
501
+ : []
502
+ const resolvedSchema = this.registry.resolveSchema(schemaArray)
503
+ return this.registry.initializeRecord(resolvedSchema)
504
+ }
420
505
  }
506
+
507
+ /**
508
+ * Recursively collect nested data from HST using pre-resolved schemas
509
+ * @param resolvedSchema - The already-resolved schema (with nested schemas embedded)
510
+ * @param basePath - The base path in HST (e.g., "customer.123.address")
511
+ * @param hstStore - The HST store instance
512
+ * @returns The collected data object
513
+ * @public
514
+ */
515
+ function collectNestedData(resolvedSchema: SchemaTypes[], basePath: string, hstStore: HSTNode): Record<string, any> {
516
+ const data = hstStore.get(basePath) || {}
517
+ const payload: Record<string, any> = { ...data }
518
+
519
+ const doctypeFields = resolvedSchema.filter(
520
+ field =>
521
+ 'fieldtype' in field &&
522
+ field.fieldtype === 'Doctype' &&
523
+ !isDoctypeMany(field as DoctypeSchema) &&
524
+ 'schema' in field &&
525
+ Array.isArray(field.schema)
526
+ )
527
+
528
+ for (const field of doctypeFields) {
529
+ const doctypeField = field as DoctypeOneSchema
530
+ const fieldPath = `${basePath}.${doctypeField.fieldname}`
531
+ const nestedData = collectNestedData(doctypeField.schema!, fieldPath, hstStore)
532
+ payload[doctypeField.fieldname] = nestedData
533
+ }
534
+
535
+ const doctypeManyFields = resolvedSchema.filter(
536
+ field => 'fieldtype' in field && field.fieldtype === 'Doctype' && isDoctypeMany(field as DoctypeSchema)
537
+ )
538
+
539
+ for (const field of doctypeManyFields) {
540
+ const doctypeField = field as DoctypeManySchema
541
+ const fieldPath = `${basePath}.${doctypeField.fieldname}`
542
+ const arrayData = hstStore.get(fieldPath)
543
+ if (Array.isArray(arrayData)) {
544
+ payload[doctypeField.fieldname] = arrayData
545
+ }
546
+ }
547
+
548
+ return payload
549
+ }
550
+
551
+ export { collectNestedData }
@@ -0,0 +1,245 @@
1
+ import { SchemaTypes } from '@stonecrop/aform'
2
+ import type { Ref, ComputedRef } from 'vue'
3
+
4
+ import type Doctype from '../doctype'
5
+ import type { HSTNode } from '../stores/hst'
6
+ import type { HSTOperation, OperationLogConfig, OperationLogSnapshot } from './operation-log'
7
+
8
+ /**
9
+ * Operation Log API - nested object containing all operation log functionality
10
+ * @public
11
+ */
12
+ export type OperationLogAPI = {
13
+ /**
14
+ * List of all recorded operations in the log.
15
+ * Each operation represents a state change that can be undone/redone.
16
+ */
17
+ operations: Ref<HSTOperation[]>
18
+ /**
19
+ * Current position in the operation log.
20
+ * -1 means no operations, 0 means at first operation, etc.
21
+ */
22
+ currentIndex: Ref<number>
23
+ /**
24
+ * Computed snapshot of undo/redo state.
25
+ * Use this for UI indicators (buttons, menu state).
26
+ */
27
+ undoRedoState: ComputedRef<{
28
+ canUndo: boolean
29
+ canRedo: boolean
30
+ undoCount: number
31
+ redoCount: number
32
+ currentIndex: number
33
+ }>
34
+ /**
35
+ * Whether undo is currently available.
36
+ * True when there are operations that can be undone.
37
+ */
38
+ canUndo: ComputedRef<boolean>
39
+ /**
40
+ * Whether redo is currently available.
41
+ * True when there are undone operations that can be redone.
42
+ */
43
+ canRedo: ComputedRef<boolean>
44
+ /**
45
+ * Number of operations available to undo.
46
+ */
47
+ undoCount: ComputedRef<number>
48
+ /**
49
+ * Number of operations available to redo.
50
+ */
51
+ redoCount: ComputedRef<number>
52
+ /**
53
+ * Undo the last operation.
54
+ * @param hstStore - The HST node to apply the inverse operation to
55
+ * @returns True if undo succeeded, false if nothing to undo
56
+ */
57
+ undo: (hstStore: HSTNode) => boolean
58
+ /**
59
+ * Redo the last undone operation.
60
+ * @param hstStore - The HST node to apply the operation to
61
+ * @returns True if redo succeeded, false if nothing to redo
62
+ */
63
+ redo: (hstStore: HSTNode) => boolean
64
+ /**
65
+ * Start batching multiple operations together.
66
+ * Call before a series of changes that should be undone/redone as a unit.
67
+ */
68
+ startBatch: () => void
69
+ /**
70
+ * Commit the current batch of operations.
71
+ * @param description - Optional description for the batch
72
+ * @returns The batch operation ID, or null if no batch in progress
73
+ */
74
+ commitBatch: (description?: string) => string | null
75
+ /**
76
+ * Cancel the current batch without committing.
77
+ * Discards all operations added since startBatch().
78
+ */
79
+ cancelBatch: () => void
80
+ /**
81
+ * Clear all operations from the log.
82
+ * Resets the log to its initial empty state.
83
+ */
84
+ clear: () => void
85
+ /**
86
+ * Get all operations for a specific doctype.
87
+ * @param doctype - The doctype name to filter by
88
+ * @param recordId - Optional record ID to further filter
89
+ * @returns Array of matching operations
90
+ */
91
+ getOperationsFor: (doctype: string, recordId?: string) => HSTOperation[]
92
+ /**
93
+ * Get a serializable snapshot of the operation log.
94
+ * Use for debugging, logging, or state persistence.
95
+ * @returns Snapshot containing operations and current index
96
+ */
97
+ getSnapshot: () => OperationLogSnapshot
98
+ /**
99
+ * Mark an operation as irreversible.
100
+ * Irreversible operations cannot be undone.
101
+ * @param operationId - The operation ID to mark
102
+ * @param reason - Human-readable reason why it cannot be undone
103
+ */
104
+ markIrreversible: (operationId: string, reason: string) => void
105
+ /**
106
+ * Log a custom action (non-HST operation).
107
+ * Use for tracking server calls, external side effects, etc.
108
+ * @param doctype - The doctype this action relates to
109
+ * @param actionName - Name of the action (e.g., 'save', 'submit')
110
+ * @param recordIds - Optional array of affected record IDs
111
+ * @param result - Optional result status
112
+ * @param error - Optional error message if result is 'failure'
113
+ * @returns The logged operation ID
114
+ */
115
+ logAction: (
116
+ doctype: string,
117
+ actionName: string,
118
+ recordIds?: string[],
119
+ result?: 'success' | 'failure' | 'pending',
120
+ error?: string
121
+ ) => string
122
+ /**
123
+ * Configure operation log options.
124
+ * @param options - Partial configuration to merge with existing settings
125
+ */
126
+ configure: (options: Partial<OperationLogConfig>) => void
127
+ }
128
+
129
+ /**
130
+ * Base Stonecrop composable return type - includes operation log functionality
131
+ * @public
132
+ */
133
+ export type BaseStonecropReturn = {
134
+ /**
135
+ * Reactive reference to the Stonecrop singleton instance.
136
+ * Use this to access class methods like `getRecord()`, `addRecord()`, `runAction()`.
137
+ */
138
+ stonecrop: Ref<Stonecrop | undefined>
139
+ /**
140
+ * Operation log API for undo/redo functionality.
141
+ * Use `operationLog.undo()` and `operationLog.redo()` for user-triggered operations.
142
+ * Use `operationLog.startBatch()` / `operationLog.commitBatch()` for grouping operations.
143
+ */
144
+ operationLog: OperationLogAPI
145
+ }
146
+
147
+ /**
148
+ * HST-enabled Stonecrop composable return type
149
+ * @public
150
+ */
151
+ export type HSTStonecropReturn = BaseStonecropReturn & {
152
+ /**
153
+ * Generates a fully-qualified HST path for a field.
154
+ * Use this in nested components to create paths like "customer.123.address".
155
+ * @param fieldname - The field name to append to the path
156
+ * @param recordId - Optional record ID (defaults to current record)
157
+ * @returns The full HST path string
158
+ */
159
+ provideHSTPath: (fieldname: string, recordId?: string) => string
160
+ /**
161
+ * Handles a field value change and updates HST.
162
+ * Call this from form input handlers to persist changes to the store.
163
+ * @param changeData - Object containing path, value, fieldname, and optional recordId
164
+ */
165
+ handleHSTChange: (changeData: HSTChangeData) => void
166
+ /**
167
+ * Reactive reference to the HST node for this doctype/record.
168
+ * Use this to read current form state or subscribe to changes.
169
+ */
170
+ hstStore: Ref<HSTNode | undefined>
171
+ /**
172
+ * Reactive form data bound to HST.
173
+ * Use this as the v-model target for form inputs. Changes sync to hstStore.
174
+ */
175
+ formData: Ref<Record<string, any>>
176
+ /**
177
+ * Resolved schema with nested Doctype fields expanded.
178
+ * Use this to iterate over fields for rendering, excluding nested doctypes handled separately.
179
+ */
180
+ resolvedSchema: Ref<SchemaTypes[]>
181
+ /**
182
+ * Loads or initializes nested doctype data.
183
+ * Use this when rendering a nested form component. Checks HST first, then initializes defaults.
184
+ * @param parentPath - The HST path to check for existing data
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
188
+ */
189
+ loadNestedData: (parentPath: string, childDoctype: Doctype, recordId?: string) => Record<string, any>
190
+ /**
191
+ * Collects a complete record payload with all nested data from HST.
192
+ * Use this before submitting to an API. Recursively includes 1:1 and 1:many nested records.
193
+ * @param doctype - The doctype metadata
194
+ * @param recordId - The record ID to collect
195
+ * @returns The complete record payload ready for API submission
196
+ */
197
+ collectRecordPayload: (doctype: Doctype, recordId: string) => Record<string, any>
198
+ /**
199
+ * Creates a nested context for a child doctype component.
200
+ * Use this in parent components to pass scoped handlers to child components.
201
+ * @param basePath - The parent HST path prefix
202
+ * @param childDoctype - The child doctype metadata
203
+ * @returns Scoped provideHSTPath and handleHSTChange functions
204
+ */
205
+ createNestedContext: (
206
+ basePath: string,
207
+ childDoctype: Doctype
208
+ ) => {
209
+ provideHSTPath: (fieldname: string) => string
210
+ handleHSTChange: (changeData: HSTChangeData) => void
211
+ }
212
+ /**
213
+ * Loading state for async doctype resolution.
214
+ * True while fetching doctype by slug string from registry.
215
+ */
216
+ isLoading: Ref<boolean>
217
+ /**
218
+ * Error state for doctype resolution failures.
219
+ * Set when doctype slug lookup fails.
220
+ */
221
+ error: Ref<Error | null>
222
+ /**
223
+ * Resolved doctype instance.
224
+ * Available immediately if Doctype instance passed, after async resolution if slug string passed.
225
+ */
226
+ resolvedDoctype: Ref<Doctype | undefined>
227
+ }
228
+
229
+ // Import Stonecrop class for the BaseStonecropReturn type (circular reference handled via import)
230
+ import type { Stonecrop } from '../stonecrop'
231
+
232
+ /**
233
+ * HST Change data structure
234
+ * @public
235
+ */
236
+ export type HSTChangeData = {
237
+ /** Full HST path to the changed field */
238
+ path: string
239
+ /** New value for the field */
240
+ value: any
241
+ /** Field name that changed */
242
+ fieldname: string
243
+ /** Optional record ID */
244
+ recordId?: string
245
+ }
@@ -0,0 +1,60 @@
1
+ import type { SchemaTypes } from '@stonecrop/aform'
2
+ import type { WorkflowMeta } from '@stonecrop/schema'
3
+ import { List, Map } from 'immutable'
4
+ import type { AnyStateNodeConfig, UnknownMachineConfig } from 'xstate'
5
+
6
+ /**
7
+ * Immutable Doctype type for Stonecrop instances
8
+ * @public
9
+ */
10
+ export type ImmutableDoctype = {
11
+ readonly schema?: List<SchemaTypes>
12
+ readonly workflow?: UnknownMachineConfig | AnyStateNodeConfig | WorkflowMeta
13
+ readonly actions?: Map<string, string[]>
14
+ }
15
+
16
+ /**
17
+ * Mutable Doctype type for Stonecrop instances
18
+ * @public
19
+ */
20
+ export type MutableDoctype = {
21
+ doctype?: string
22
+ schema?: SchemaTypes[]
23
+ workflow?: UnknownMachineConfig | AnyStateNodeConfig | WorkflowMeta
24
+ actions?: Record<string, string[]>
25
+ }
26
+
27
+ /**
28
+ * Schema type for Stonecrop instances
29
+ * @public
30
+ */
31
+ export type Schema = {
32
+ doctype: string
33
+ schema: List<SchemaTypes>
34
+ }
35
+
36
+ /**
37
+ * Plain object representation of doctype configuration for serialization/API responses.
38
+ * Compatible with the DoctypeMeta type from \@stonecrop/schema.
39
+ * @public
40
+ */
41
+ export type DoctypeConfig = {
42
+ /** Display name of the doctype */
43
+ name: string
44
+ /** URL-friendly slug (kebab-case) */
45
+ slug?: string
46
+ /** Database table name */
47
+ tableName?: string
48
+ /** Field definitions */
49
+ fields?: SchemaTypes[]
50
+ /** Workflow configuration (XState format or simple WorkflowMeta) */
51
+ workflow?: UnknownMachineConfig | WorkflowMeta
52
+ /** Actions and their field triggers */
53
+ actions?: Record<string, string[]>
54
+ /** Parent doctype for inheritance */
55
+ inherits?: string
56
+ /** Doctype to use for list views */
57
+ listDoctype?: string
58
+ /** Parent doctype for child tables */
59
+ parentDoctype?: string
60
+ }
@@ -1,76 +1,9 @@
1
- import type { DataClient, WorkflowMeta } from '@stonecrop/schema'
2
- import type { SchemaTypes } from '@stonecrop/aform'
3
- import { List, Map } from 'immutable'
4
- import type { Component } from 'vue'
5
- import type { Router } from 'vue-router'
6
- import type { AnyStateNodeConfig, UnknownMachineConfig } from 'xstate'
7
-
8
- import type Doctype from '../doctype'
9
- import Registry from '../registry'
10
- import { Stonecrop } from '../stonecrop'
11
- import type { RouteContext } from './registry'
12
-
13
- /**
14
- * Immutable Doctype type for Stonecrop instances
15
- * @public
16
- */
17
- export type ImmutableDoctype = {
18
- readonly schema?: List<SchemaTypes> // TODO: allow schema to be a function
19
- readonly workflow?: UnknownMachineConfig | AnyStateNodeConfig | WorkflowMeta
20
- readonly actions?: Map<string, string[]>
21
- }
22
-
23
- /**
24
- * Mutable Doctype type for Stonecrop instances
25
- * @public
26
- */
27
- export type MutableDoctype = {
28
- doctype?: string
29
- schema?: SchemaTypes[] // TODO: allow schema to be a function
30
- workflow?: UnknownMachineConfig | AnyStateNodeConfig | WorkflowMeta
31
- actions?: Record<string, string[]>
32
- }
33
-
34
- /**
35
- * Schema type for Stonecrop instances
36
- * @public
37
- */
38
- export type Schema = {
39
- doctype: string
40
- schema: List<SchemaTypes>
41
- }
42
-
43
- /**
44
- * Install options for Stonecrop Vue plugin
45
- * @public
46
- */
47
- export type InstallOptions = {
48
- router?: Router
49
- components?: Record<string, Component>
50
- getMeta?: (routeContext: RouteContext) => Doctype | Promise<Doctype>
51
- /**
52
- * Data client for fetching doctype metadata and records.
53
- * Use \@stonecrop/graphql-client's StonecropClient for GraphQL backends,
54
- * or implement DataClient for custom data sources.
55
- *
56
- * Can be set later via `useStonecropRegistry().setClient()` for deferred configuration.
57
- *
58
- * @example
59
- * ```ts
60
- * import { StonecropClient } from '@stonecrop/graphql-client'
61
- *
62
- * const client = new StonecropClient({ endpoint: '/graphql' })
63
- * app.use(StonecropPlugin, { client })
64
- * ```
65
- */
66
- client?: DataClient
67
- /** Automatically run initialization callback after app mounting (default: false) */
68
- autoInitializeRouter?: boolean
69
- /** Callback function called after plugin is ready and mounted */
70
- onRouterInitialized?: (registry: Registry, stonecrop: Stonecrop) => void | Promise<void>
71
- }
72
-
73
- // Re-export types
1
+ // Re-export all type files
2
+ export * from './composable'
3
+ export * from './doctype'
74
4
  export * from './field-triggers'
75
- export * from './registry'
76
5
  export * from './operation-log'
6
+ export * from './plugin'
7
+ export * from './registry'
8
+ export * from './schema-validator'
9
+ export * from './stonecrop'
@@ -0,0 +1,38 @@
1
+ import type { DataClient } from '@stonecrop/schema'
2
+ import type { Component } from 'vue'
3
+ import type { Router } from 'vue-router'
4
+
5
+ import type Doctype from '../doctype'
6
+ import type Registry from '../registry'
7
+ import type { Stonecrop } from '../stonecrop'
8
+ import type { RouteContext } from './registry'
9
+
10
+ /**
11
+ * Install options for Stonecrop Vue plugin
12
+ * @public
13
+ */
14
+ export type InstallOptions = {
15
+ router?: Router
16
+ components?: Record<string, Component>
17
+ getMeta?: (routeContext: RouteContext) => Doctype | Promise<Doctype>
18
+ /**
19
+ * Data client for fetching doctype metadata and records.
20
+ * Use \@stonecrop/graphql-client's StonecropClient for GraphQL backends,
21
+ * or implement DataClient for custom data sources.
22
+ *
23
+ * Can be set later via `useStonecropRegistry().setClient()` for deferred configuration.
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { StonecropClient } from '@stonecrop/graphql-client'
28
+ *
29
+ * const client = new StonecropClient({ endpoint: '/graphql' })
30
+ * app.use(StonecropPlugin, { client })
31
+ * ```
32
+ */
33
+ client?: DataClient
34
+ /** Automatically run initialization callback after app mounting (default: false) */
35
+ autoInitializeRouter?: boolean
36
+ /** Callback function called after plugin is ready and mounted */
37
+ onRouterInitialized?: (registry: Registry, stonecrop: Stonecrop) => void | Promise<void>
38
+ }
@@ -0,0 +1,67 @@
1
+ import type Registry from '../registry'
2
+
3
+ /**
4
+ * Validation severity levels
5
+ * @public
6
+ */
7
+ export enum ValidationSeverity {
8
+ /** Blocking error that prevents save */
9
+ ERROR = 'error',
10
+ /** Advisory warning that allows save */
11
+ WARNING = 'warning',
12
+ /** Informational message */
13
+ INFO = 'info',
14
+ }
15
+
16
+ /**
17
+ * Validation issue
18
+ * @public
19
+ */
20
+ export interface ValidationIssue {
21
+ /** Severity level */
22
+ severity: ValidationSeverity
23
+ /** Validation rule that failed */
24
+ rule: string
25
+ /** Human-readable message */
26
+ message: string
27
+ /** Doctype name */
28
+ doctype?: string
29
+ /** Field name if applicable */
30
+ fieldname?: string
31
+ /** Additional context */
32
+ context?: Record<string, unknown>
33
+ }
34
+
35
+ /**
36
+ * Validation result
37
+ * @public
38
+ */
39
+ export interface ValidationResult {
40
+ /** Whether validation passed (no blocking errors) */
41
+ valid: boolean
42
+ /** List of validation issues */
43
+ issues: ValidationIssue[]
44
+ /** Count of errors */
45
+ errorCount: number
46
+ /** Count of warnings */
47
+ warningCount: number
48
+ /** Count of info messages */
49
+ infoCount: number
50
+ }
51
+
52
+ /**
53
+ * Schema validator options
54
+ * @public
55
+ */
56
+ export interface ValidatorOptions {
57
+ /** Registry instance for doctype lookups */
58
+ registry?: Registry
59
+ /** Whether to validate Link field targets */
60
+ validateLinkTargets?: boolean
61
+ /** Whether to validate workflow reachability */
62
+ validateWorkflows?: boolean
63
+ /** Whether to validate action registration */
64
+ validateActions?: boolean
65
+ /** Whether to validate required schema properties */
66
+ validateRequiredProperties?: boolean
67
+ }