@stonecrop/stonecrop 0.13.8 → 0.13.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/doctype.d.ts +9 -11
- package/dist/src/doctype.d.ts.map +1 -1
- package/dist/src/doctype.js +6 -6
- package/dist/src/registry.d.ts +23 -43
- package/dist/src/registry.d.ts.map +1 -1
- package/dist/src/registry.js +124 -167
- package/dist/src/schema-validator.d.ts +3 -3
- package/dist/src/schema-validator.d.ts.map +1 -1
- package/dist/src/schema-validator.js +13 -29
- package/dist/src/stonecrop.d.ts +1 -1
- package/dist/src/stonecrop.d.ts.map +1 -1
- package/dist/src/stonecrop.js +0 -1
- package/dist/src/stores/operation-log.d.ts +1 -1
- package/dist/src/types/composable.d.ts +2 -2
- package/dist/src/types/composable.d.ts.map +1 -1
- package/dist/src/types/doctype.d.ts +6 -25
- package/dist/src/types/doctype.d.ts.map +1 -1
- package/dist/stonecrop.d.ts +41 -81
- package/dist/stonecrop.js +458 -508
- package/dist/stonecrop.js.map +1 -1
- package/package.json +4 -4
- package/src/composables/stonecrop.ts +2 -2
- package/src/doctype.ts +10 -12
- package/src/registry.ts +137 -217
- package/src/schema-validator.ts +20 -41
- package/src/stonecrop.ts +0 -1
- package/src/types/composable.ts +2 -2
- package/src/types/doctype.ts +6 -27
package/src/schema-validator.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @packageDocumentation
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import type {
|
|
7
|
+
import type { DoctypeField } from '@stonecrop/schema'
|
|
8
8
|
import type { LinkDeclaration } from '@stonecrop/schema'
|
|
9
9
|
import type { List, Map as ImmutableMap } from 'immutable'
|
|
10
10
|
import type { AnyStateNodeConfig } from 'xstate'
|
|
@@ -47,7 +47,7 @@ export class SchemaValidator {
|
|
|
47
47
|
*/
|
|
48
48
|
validate(
|
|
49
49
|
doctype: string,
|
|
50
|
-
schema: List<
|
|
50
|
+
schema: List<DoctypeField> | DoctypeField[] | undefined,
|
|
51
51
|
workflow?: AnyStateNodeConfig,
|
|
52
52
|
actions?: ImmutableMap<string, string[]> | Map<string, string[]>,
|
|
53
53
|
links?: Record<string, LinkDeclaration>
|
|
@@ -102,7 +102,7 @@ export class SchemaValidator {
|
|
|
102
102
|
* Validates that required schema properties are present
|
|
103
103
|
* @internal
|
|
104
104
|
*/
|
|
105
|
-
private validateRequiredProperties(doctype: string, schema:
|
|
105
|
+
private validateRequiredProperties(doctype: string, schema: DoctypeField[]): ValidationIssue[] {
|
|
106
106
|
const issues: ValidationIssue[] = []
|
|
107
107
|
|
|
108
108
|
for (const field of schema) {
|
|
@@ -118,8 +118,8 @@ export class SchemaValidator {
|
|
|
118
118
|
continue
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
//
|
|
122
|
-
if (!field.component && !
|
|
121
|
+
// ValueField requires fieldtype; fieldset/table have their own structural requirements
|
|
122
|
+
if (field.kind === 'field' && !field.component && !field.fieldtype) {
|
|
123
123
|
issues.push({
|
|
124
124
|
severity: ValidationSeverity.ERROR,
|
|
125
125
|
rule: 'required-component-or-fieldtype',
|
|
@@ -129,16 +129,9 @@ export class SchemaValidator {
|
|
|
129
129
|
})
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
// Validate nested schemas (
|
|
133
|
-
if ('
|
|
134
|
-
|
|
135
|
-
const nestedSchema = (field as { schema: unknown }).schema
|
|
136
|
-
// oxlint-disable typescript/no-unsafe-type-assertion -- Immutable List or plain array; toArray() returns SchemaTypes elements
|
|
137
|
-
const nestedArray = (
|
|
138
|
-
Array.isArray(nestedSchema) ? nestedSchema : (nestedSchema as { toArray?: () => unknown[] }).toArray?.() || []
|
|
139
|
-
) as SchemaTypes[]
|
|
140
|
-
// oxlint-enable typescript/no-unsafe-type-assertion
|
|
141
|
-
issues.push(...this.validateRequiredProperties(doctype, nestedArray))
|
|
132
|
+
// Validate nested schemas recursively (fieldset only; table columns are ColumnSchema not DoctypeField)
|
|
133
|
+
if (field.kind === 'fieldset') {
|
|
134
|
+
issues.push(...this.validateRequiredProperties(doctype, field.schema))
|
|
142
135
|
}
|
|
143
136
|
}
|
|
144
137
|
|
|
@@ -149,16 +142,12 @@ export class SchemaValidator {
|
|
|
149
142
|
* Validates Link field targets exist in registry
|
|
150
143
|
* @internal
|
|
151
144
|
*/
|
|
152
|
-
private validateLinkFields(doctype: string, schema:
|
|
145
|
+
private validateLinkFields(doctype: string, schema: DoctypeField[], registry: Registry): ValidationIssue[] {
|
|
153
146
|
const issues: ValidationIssue[] = []
|
|
154
147
|
|
|
155
148
|
for (const field of schema) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
// Check Link fields
|
|
160
|
-
if (fieldtype === 'Link') {
|
|
161
|
-
const options = 'options' in field ? (field as { options: unknown }).options : undefined
|
|
149
|
+
if (field.kind === 'field' && field.fieldtype === 'Link') {
|
|
150
|
+
const options = field.options
|
|
162
151
|
if (!options) {
|
|
163
152
|
issues.push({
|
|
164
153
|
severity: ValidationSeverity.ERROR,
|
|
@@ -170,8 +159,6 @@ export class SchemaValidator {
|
|
|
170
159
|
continue
|
|
171
160
|
}
|
|
172
161
|
|
|
173
|
-
// Check if target doctype exists in registry
|
|
174
|
-
// Options should be a string representing the target doctype name
|
|
175
162
|
const targetDoctype = typeof options === 'string' ? options : ''
|
|
176
163
|
if (!targetDoctype) {
|
|
177
164
|
issues.push({
|
|
@@ -197,16 +184,9 @@ export class SchemaValidator {
|
|
|
197
184
|
}
|
|
198
185
|
}
|
|
199
186
|
|
|
200
|
-
// Recursively check nested schemas
|
|
201
|
-
if ('
|
|
202
|
-
|
|
203
|
-
const nestedSchema = (field as { schema: unknown }).schema
|
|
204
|
-
// oxlint-disable typescript/no-unsafe-type-assertion -- Immutable List or plain array; toArray() returns SchemaTypes elements
|
|
205
|
-
const nestedArray = (
|
|
206
|
-
Array.isArray(nestedSchema) ? nestedSchema : (nestedSchema as { toArray?: () => unknown[] }).toArray?.() || []
|
|
207
|
-
) as SchemaTypes[]
|
|
208
|
-
// oxlint-enable typescript/no-unsafe-type-assertion
|
|
209
|
-
issues.push(...this.validateLinkFields(doctype, nestedArray, registry))
|
|
187
|
+
// Recursively check nested fieldset schemas
|
|
188
|
+
if (field.kind === 'fieldset') {
|
|
189
|
+
issues.push(...this.validateLinkFields(doctype, field.schema, registry))
|
|
210
190
|
}
|
|
211
191
|
}
|
|
212
192
|
|
|
@@ -220,15 +200,15 @@ export class SchemaValidator {
|
|
|
220
200
|
private validateLinkDeclarations(
|
|
221
201
|
doctype: string,
|
|
222
202
|
links: Record<string, LinkDeclaration>,
|
|
223
|
-
schema:
|
|
203
|
+
schema: DoctypeField[],
|
|
224
204
|
registry: Registry
|
|
225
205
|
): ValidationIssue[] {
|
|
226
206
|
const issues: ValidationIssue[] = []
|
|
227
207
|
|
|
228
208
|
// Build a map of Link fields by fieldname for quick lookup
|
|
229
|
-
const linkFieldsByFieldname = new Map<string,
|
|
209
|
+
const linkFieldsByFieldname = new Map<string, DoctypeField>()
|
|
230
210
|
for (const field of schema) {
|
|
231
|
-
if (
|
|
211
|
+
if (field.kind === 'field' && field.fieldtype === 'Link') {
|
|
232
212
|
linkFieldsByFieldname.set(field.fieldname, field)
|
|
233
213
|
}
|
|
234
214
|
}
|
|
@@ -288,9 +268,8 @@ export class SchemaValidator {
|
|
|
288
268
|
// Only check if link has fieldname set (otherwise it's a standalone link without a field)
|
|
289
269
|
if (link.fieldname) {
|
|
290
270
|
const linkField = linkFieldsByFieldname.get(link.fieldname)
|
|
291
|
-
if (linkField) {
|
|
292
|
-
const
|
|
293
|
-
const linkFieldTarget = typeof linkFieldOptions === 'string' ? linkFieldOptions : undefined
|
|
271
|
+
if (linkField && linkField.kind === 'field') {
|
|
272
|
+
const linkFieldTarget = typeof linkField.options === 'string' ? linkField.options : undefined
|
|
294
273
|
if (linkFieldTarget && linkFieldTarget !== link.target) {
|
|
295
274
|
issues.push({
|
|
296
275
|
severity: ValidationSeverity.ERROR,
|
|
@@ -483,7 +462,7 @@ export function createValidator(registry: Registry, options?: Partial<ValidatorO
|
|
|
483
462
|
*/
|
|
484
463
|
export function validateSchema(
|
|
485
464
|
doctype: string,
|
|
486
|
-
schema: List<
|
|
465
|
+
schema: List<DoctypeField> | DoctypeField[] | undefined,
|
|
487
466
|
registry: Registry,
|
|
488
467
|
workflow?: AnyStateNodeConfig,
|
|
489
468
|
actions?: ImmutableMap<string, string[]> | Map<string, string[]>
|
package/src/stonecrop.ts
CHANGED
|
@@ -319,7 +319,6 @@ export class Stonecrop {
|
|
|
319
319
|
// TODO: For custom fetch handlers, this returns false (not blocking), but the custom handler
|
|
320
320
|
// may still be invoked by useLazyLink. Future: custom handlers should be able to declare they
|
|
321
321
|
// satisfy blockWorkflows, or validation should reject custom + blockWorkflows: true.
|
|
322
|
-
// See: relationships.md Phase 6 "Open Question: blockWorkflows + custom fetch"
|
|
323
322
|
return link.fetch?.method === 'sync'
|
|
324
323
|
}
|
|
325
324
|
|
package/src/types/composable.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ResolvedField } from '@stonecrop/aform'
|
|
2
2
|
import type { Ref, ComputedRef } from 'vue'
|
|
3
3
|
|
|
4
4
|
import type Doctype from '../doctype'
|
|
@@ -177,7 +177,7 @@ export type HSTStonecropReturn = BaseStonecropReturn & {
|
|
|
177
177
|
* Resolved schema with nested Doctype fields expanded.
|
|
178
178
|
* Use this to iterate over fields for rendering, excluding nested doctypes handled separately.
|
|
179
179
|
*/
|
|
180
|
-
resolvedSchema: Ref<
|
|
180
|
+
resolvedSchema: Ref<ResolvedField[]>
|
|
181
181
|
/**
|
|
182
182
|
* Scaffold empty descendant records from defaults for all descendant links.
|
|
183
183
|
* @param path - The HST path where initialized data should be stored
|
package/src/types/doctype.ts
CHANGED
|
@@ -1,42 +1,21 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { FieldMeta, LinkDeclaration, WorkflowMeta } from '@stonecrop/schema'
|
|
1
|
+
import type { DoctypeField, LinkDeclaration, WorkflowMeta } from '@stonecrop/schema'
|
|
3
2
|
import { List, Map } from 'immutable'
|
|
4
3
|
import type { AnyStateNodeConfig, UnknownMachineConfig } from 'xstate'
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
|
-
* Immutable Doctype type for Stonecrop instances
|
|
6
|
+
* Immutable Doctype type for Stonecrop instances. App authors should use
|
|
7
|
+
* `Doctype.fromObject()` rather than constructing this shape manually.
|
|
8
8
|
* @public
|
|
9
9
|
*/
|
|
10
10
|
export type ImmutableDoctype = {
|
|
11
|
-
readonly schema?: List<
|
|
11
|
+
readonly schema?: List<DoctypeField>
|
|
12
12
|
readonly workflow?: UnknownMachineConfig | AnyStateNodeConfig | WorkflowMeta
|
|
13
13
|
readonly actions?: Map<string, string[]>
|
|
14
|
-
readonly links?: Record<string, LinkDeclaration>
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Mutable Doctype type for Stonecrop instances
|
|
19
|
-
* @public
|
|
20
|
-
*/
|
|
21
|
-
export type MutableDoctype = {
|
|
22
|
-
doctype?: string
|
|
23
|
-
schema?: SchemaTypes[]
|
|
24
|
-
workflow?: UnknownMachineConfig | AnyStateNodeConfig | WorkflowMeta
|
|
25
|
-
actions?: Record<string, string[]>
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Schema type for Stonecrop instances
|
|
30
|
-
* @public
|
|
31
|
-
*/
|
|
32
|
-
export type Schema = {
|
|
33
|
-
doctype: string
|
|
34
|
-
schema: List<SchemaTypes>
|
|
35
14
|
}
|
|
36
15
|
|
|
37
16
|
/**
|
|
38
17
|
* Plain object representation of doctype configuration for serialization/API responses.
|
|
39
|
-
*
|
|
18
|
+
* Extends DoctypeMeta with Stonecrop-specific properties: actions, slug, inherits.
|
|
40
19
|
* @public
|
|
41
20
|
*/
|
|
42
21
|
export type DoctypeConfig = {
|
|
@@ -45,7 +24,7 @@ export type DoctypeConfig = {
|
|
|
45
24
|
/** URL-friendly slug (kebab-case) */
|
|
46
25
|
slug?: string
|
|
47
26
|
/** Field definitions (including link fields with fieldtype: 'Link') */
|
|
48
|
-
fields?:
|
|
27
|
+
fields?: DoctypeField[]
|
|
49
28
|
/** Relationship links to other doctypes */
|
|
50
29
|
links?: Record<string, LinkDeclaration>
|
|
51
30
|
/** Workflow configuration (XState format or simple WorkflowMeta) */
|