@localess/schema 4.0.3-dev.20261004111503 → 4.0.3-dev.20261004121049
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/SKILL.md +7 -6
- package/dist/define.d.ts +3 -3
- package/dist/index.js +10 -6
- package/dist/index.mjs +10 -6
- package/dist/infer.d.ts +4 -11
- package/package.json +2 -2
package/SKILL.md
CHANGED
|
@@ -111,16 +111,15 @@ in `schemas`. Both are normalized to string ids at runtime by `defineSchema`,
|
|
|
111
111
|
matching the wire format exactly — but the *type* keeps the literal id, so
|
|
112
112
|
`InferContent` resolves `OPTION` fields to the referenced enum's literal
|
|
113
113
|
value union instead of plain `string`, and `SCHEMA`/`SCHEMAS` fields to the
|
|
114
|
-
allowed schemas' content types
|
|
115
|
-
`schemas` list is omitted).
|
|
114
|
+
allowed schemas' content types.
|
|
116
115
|
|
|
117
116
|
Fallbacks when a reference can't be resolved against the config:
|
|
118
117
|
|
|
119
118
|
- `OPTION`/`OPTIONS` whose `source` id is not in the config → `string` (or
|
|
120
119
|
`string[]`), mirroring the CLI's `type generate` behavior.
|
|
121
120
|
- `InferEnum` of an enum with no `values` → `string`.
|
|
122
|
-
-
|
|
123
|
-
`
|
|
121
|
+
- `SCHEMA`/`SCHEMAS` with an empty `schemas` list (a `validate()` error) →
|
|
122
|
+
`{ _id: string; _schema: string }` (or an array of it).
|
|
124
123
|
- `InferContentData` of a config with no `ROOT` schema → `never`.
|
|
125
124
|
|
|
126
125
|
## Field kinds
|
|
@@ -142,7 +141,7 @@ everything else is optional.
|
|
|
142
141
|
| `LINK` | — | `ContentLink` |
|
|
143
142
|
| `REFERENCE` / `REFERENCES` | `path?` | `ContentReference` / `ContentReference[]` |
|
|
144
143
|
| `ASSET` / `ASSETS` | `fileTypes?: AssetFileType[]`, `fileType?: AssetFileType` | `ContentAsset` / `ContentAsset[]` |
|
|
145
|
-
| `SCHEMA` / `SCHEMAS` | `schemas
|
|
144
|
+
| `SCHEMA` / `SCHEMAS` | `schemas` (required: allowed `NODE` ids or `defineSchema` results — the editor offers exactly these) | allowed schemas' content type / array of it |
|
|
146
145
|
|
|
147
146
|
`AssetFileType` is `'ANY' | 'IMAGE' | 'VIDEO' | 'TEXT' | 'AUDIO' | 'APPLICATION'`.
|
|
148
147
|
|
|
@@ -175,7 +174,9 @@ schema in the config is checked, not just the first. Rules and their `code`:
|
|
|
175
174
|
| `field/unresolved-source` | `OPTION`/`OPTIONS` `source` must be the id of a schema in the config. |
|
|
176
175
|
| `field/source-not-enum` | ...and that schema must be an `ENUM`. |
|
|
177
176
|
| `field/unresolved-schema-ref` | Every `SCHEMA`/`SCHEMAS` `schemas` entry must be the id of a schema in the config. |
|
|
178
|
-
| `field/schema-ref-is-enum` | ...and that schema must be `
|
|
177
|
+
| `field/schema-ref-is-enum` | ...and that schema must be `NODE`, not `ENUM`. |
|
|
178
|
+
| `field/schema-ref-is-root` | ...nor `ROOT` — the Studio editor only offers `NODE` schemas. |
|
|
179
|
+
| `field/missing-schemas` | A `SCHEMA`/`SCHEMAS` field must list at least one schema in `schemas`; with none the editor can add no block. |
|
|
179
180
|
|
|
180
181
|
`validate` does not check for stray properties from the wrong field kind —
|
|
181
182
|
use `defineField` for that (above). Duplicate field names and duplicate
|
package/dist/define.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ type FieldInputOf<F> = F extends {
|
|
|
27
27
|
} : F extends {
|
|
28
28
|
kind: 'SCHEMA' | 'SCHEMAS';
|
|
29
29
|
} ? Omit<DeepReadonly<F>, 'schemas'> & {
|
|
30
|
-
readonly schemas
|
|
30
|
+
readonly schemas: readonly (string | ComponentDefinition)[];
|
|
31
31
|
} : DeepReadonly<F>;
|
|
32
32
|
/**
|
|
33
33
|
* A field as authored: OPTION/OPTIONS source and SCHEMA/SCHEMAS schemas accept by-value refs.
|
|
@@ -141,8 +141,8 @@ export declare function defineEnum<const TId extends string, const TValues exten
|
|
|
141
141
|
* - `OPTIONS` — `source` (required, same as `OPTION`), `minValues?`, `maxValues?`
|
|
142
142
|
* - `REFERENCE` / `REFERENCES` — `path?`
|
|
143
143
|
* - `ASSET` / `ASSETS` — `fileTypes?`, `fileType?`
|
|
144
|
-
* - `SCHEMA` / `SCHEMAS` — `schemas
|
|
145
|
-
*
|
|
144
|
+
* - `SCHEMA` / `SCHEMAS` — `schemas` (required: the allowed `NODE` definitions from `defineSchema`,
|
|
145
|
+
* or their ids — the Studio editor offers exactly these, so an empty list leaves the field unusable)
|
|
146
146
|
*
|
|
147
147
|
* Full field-kind reference, including the type each kind infers to: `docs/schema.md`.
|
|
148
148
|
*
|
package/dist/index.js
CHANGED
|
@@ -44,8 +44,8 @@ function defineEnum(definition) {
|
|
|
44
44
|
* - `OPTIONS` — `source` (required, same as `OPTION`), `minValues?`, `maxValues?`
|
|
45
45
|
* - `REFERENCE` / `REFERENCES` — `path?`
|
|
46
46
|
* - `ASSET` / `ASSETS` — `fileTypes?`, `fileType?`
|
|
47
|
-
* - `SCHEMA` / `SCHEMAS` — `schemas
|
|
48
|
-
*
|
|
47
|
+
* - `SCHEMA` / `SCHEMAS` — `schemas` (required: the allowed `NODE` definitions from `defineSchema`,
|
|
48
|
+
* or their ids — the Studio editor offers exactly these, so an empty list leaves the field unusable)
|
|
49
49
|
*
|
|
50
50
|
* Full field-kind reference, including the type each kind infers to: `docs/schema.md`.
|
|
51
51
|
*
|
|
@@ -193,10 +193,14 @@ function validate(config) {
|
|
|
193
193
|
if (!source) error("field/unresolved-source", fieldPath, `source '${field.source}' does not resolve to a schema in the config`);
|
|
194
194
|
else if (source.type !== "ENUM") error("field/source-not-enum", fieldPath, `source '${field.source}' must be an ENUM schema`);
|
|
195
195
|
}
|
|
196
|
-
if (field.kind === "SCHEMA" || field.kind === "SCHEMAS")
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
196
|
+
if (field.kind === "SCHEMA" || field.kind === "SCHEMAS") {
|
|
197
|
+
if (!field.schemas || field.schemas.length === 0) error("field/missing-schemas", fieldPath, `${field.kind} field must list at least one NODE schema in 'schemas'`);
|
|
198
|
+
for (const ref of field.schemas ?? []) {
|
|
199
|
+
const target = byId.get(ref);
|
|
200
|
+
if (!target) error("field/unresolved-schema-ref", fieldPath, `schemas ref '${ref}' does not resolve to a schema in the config`);
|
|
201
|
+
else if (target.type === "ENUM") error("field/schema-ref-is-enum", fieldPath, `schemas ref '${ref}' must be a NODE schema, not an ENUM`);
|
|
202
|
+
else if (target.type === "ROOT") error("field/schema-ref-is-root", fieldPath, `schemas ref '${ref}' must be a NODE schema; the editor never offers a ROOT schema`);
|
|
203
|
+
}
|
|
200
204
|
}
|
|
201
205
|
}
|
|
202
206
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -43,8 +43,8 @@ function defineEnum(definition) {
|
|
|
43
43
|
* - `OPTIONS` — `source` (required, same as `OPTION`), `minValues?`, `maxValues?`
|
|
44
44
|
* - `REFERENCE` / `REFERENCES` — `path?`
|
|
45
45
|
* - `ASSET` / `ASSETS` — `fileTypes?`, `fileType?`
|
|
46
|
-
* - `SCHEMA` / `SCHEMAS` — `schemas
|
|
47
|
-
*
|
|
46
|
+
* - `SCHEMA` / `SCHEMAS` — `schemas` (required: the allowed `NODE` definitions from `defineSchema`,
|
|
47
|
+
* or their ids — the Studio editor offers exactly these, so an empty list leaves the field unusable)
|
|
48
48
|
*
|
|
49
49
|
* Full field-kind reference, including the type each kind infers to: `docs/schema.md`.
|
|
50
50
|
*
|
|
@@ -192,10 +192,14 @@ function validate(config) {
|
|
|
192
192
|
if (!source) error("field/unresolved-source", fieldPath, `source '${field.source}' does not resolve to a schema in the config`);
|
|
193
193
|
else if (source.type !== "ENUM") error("field/source-not-enum", fieldPath, `source '${field.source}' must be an ENUM schema`);
|
|
194
194
|
}
|
|
195
|
-
if (field.kind === "SCHEMA" || field.kind === "SCHEMAS")
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
195
|
+
if (field.kind === "SCHEMA" || field.kind === "SCHEMAS") {
|
|
196
|
+
if (!field.schemas || field.schemas.length === 0) error("field/missing-schemas", fieldPath, `${field.kind} field must list at least one NODE schema in 'schemas'`);
|
|
197
|
+
for (const ref of field.schemas ?? []) {
|
|
198
|
+
const target = byId.get(ref);
|
|
199
|
+
if (!target) error("field/unresolved-schema-ref", fieldPath, `schemas ref '${ref}' does not resolve to a schema in the config`);
|
|
200
|
+
else if (target.type === "ENUM") error("field/schema-ref-is-enum", fieldPath, `schemas ref '${ref}' must be a NODE schema, not an ENUM`);
|
|
201
|
+
else if (target.type === "ROOT") error("field/schema-ref-is-root", fieldPath, `schemas ref '${ref}' must be a NODE schema; the editor never offers a ROOT schema`);
|
|
202
|
+
}
|
|
199
203
|
}
|
|
200
204
|
}
|
|
201
205
|
}
|
package/dist/infer.d.ts
CHANGED
|
@@ -9,13 +9,6 @@ type SchemasOf<C> = C extends {
|
|
|
9
9
|
type FindById<C, Id> = Extract<SchemasOf<C>, {
|
|
10
10
|
id: Id;
|
|
11
11
|
}>;
|
|
12
|
-
type NodeIds<C> = [Extract<SchemasOf<C>, {
|
|
13
|
-
type: 'NODE';
|
|
14
|
-
}>] extends [never] ? never : Extract<SchemasOf<C>, {
|
|
15
|
-
type: 'NODE';
|
|
16
|
-
}> extends {
|
|
17
|
-
id: infer Id extends string;
|
|
18
|
-
} ? Id : never;
|
|
19
12
|
type EnumValuesUnion<E> = E extends {
|
|
20
13
|
values: readonly SchemaEnumValue[];
|
|
21
14
|
} ? E extends {
|
|
@@ -26,13 +19,13 @@ type EnumValuesUnion<E> = E extends {
|
|
|
26
19
|
/** Literal union of an ENUM definition's values (falls back to `string` when values are absent). */
|
|
27
20
|
export type InferEnum<E> = EnumValuesUnion<E>;
|
|
28
21
|
type ResolveEnum<Id extends string, C> = [FindById<C, Id>] extends [never] ? string : EnumValuesUnion<FindById<C, Id>>;
|
|
29
|
-
type AllowedIds<F
|
|
22
|
+
type AllowedIds<F> = F extends {
|
|
30
23
|
schemas: readonly (infer Id extends string)[];
|
|
31
|
-
} ? Id :
|
|
32
|
-
type ResolveSchemaContent<F, C> = [AllowedIds<F
|
|
24
|
+
} ? Id : never;
|
|
25
|
+
type ResolveSchemaContent<F, C> = [AllowedIds<F>] extends [never] ? {
|
|
33
26
|
_id: string;
|
|
34
27
|
_schema: string;
|
|
35
|
-
} : ContentByIds<AllowedIds<F
|
|
28
|
+
} : ContentByIds<AllowedIds<F>, C>;
|
|
36
29
|
type ContentByIds<Id extends string, C> = Id extends unknown ? InferContent<FindById<C, Id>, C> : never;
|
|
37
30
|
type FieldValue<F, C> = F extends {
|
|
38
31
|
kind: 'TEXT' | 'TEXTAREA' | 'MARKDOWN' | 'COLOR' | 'DATE' | 'DATETIME';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@localess/schema",
|
|
3
|
-
"version": "4.0.3-dev.
|
|
3
|
+
"version": "4.0.3-dev.20261004121049",
|
|
4
4
|
"description": "Programmatic schema definitions for Localess with TypeScript content type inference.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"localess",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
},
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@localess/model": "4.0.3-dev.
|
|
46
|
+
"@localess/model": "4.0.3-dev.20261004121049"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/node": "^24",
|