@uniweb/core 0.15.0 → 0.16.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/package.json +3 -3
- package/src/index.js +0 -5
- package/src/schemas.js +22 -102
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Core classes for the Uniweb platform - Uniweb, Website, Page, Block",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"vitest": "^4.1.7"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@uniweb/
|
|
46
|
-
"@uniweb/
|
|
45
|
+
"@uniweb/theming": "^0.1.15",
|
|
46
|
+
"@uniweb/semantic-parser": "^1.4.0"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"test": "vitest run"
|
package/src/index.js
CHANGED
|
@@ -49,11 +49,6 @@ export {
|
|
|
49
49
|
} from './data-paths.js'
|
|
50
50
|
export { evaluate as evaluateWhere, match as matchWhere } from './where.js'
|
|
51
51
|
export { isRichSchema } from './schemas.js'
|
|
52
|
-
// ⛔ `normalizeSchema` MOVED to `@uniweb/schemas/editor-form` (2026-09-01) —
|
|
53
|
-
// it is editor-only and never called `isRichSchema`. Still exported here for
|
|
54
|
-
// ONE more release so `frontend` (a `workspace:*` pin, so a removal is live
|
|
55
|
-
// at commit time) can migrate its single import. Delete both lines then.
|
|
56
|
-
export { normalizeSchema } from './schemas.js'
|
|
57
52
|
// ⛔ `Tracker` is NOT on the package entry. It is a FEATURE, not part of the
|
|
58
53
|
// object graph this package exists to define, and putting it here made every
|
|
59
54
|
// consumer of core carry 1,576 gzip of it -- press, unipress, `@uniweb/api`
|
package/src/schemas.js
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Rich schemas live under `data.schemas` in a component's meta.js. They
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
2
|
+
* The rich-form-schema predicate. One function, and deliberately only one.
|
|
3
|
+
*
|
|
4
|
+
* Rich schemas live under `data.schemas` in a component's meta.js. They drive
|
|
5
|
+
* two author input paths that both land at `content.data[schema-id]`: tagged
|
|
6
|
+
* markdown blocks (``` ```yaml:<id> ``` ```) and the editor's FormBlock widget.
|
|
7
|
+
*
|
|
8
|
+
* `isRichSchema` is a **dispatch** predicate — "is this already the rich shape?"
|
|
9
|
+
* — and it is read at render by `runtime/src/prepare-props.js` (`applySchemas`)
|
|
10
|
+
* and at build by `build/src/runtime-schema.js`. Both are on the hot path of
|
|
11
|
+
* every site, which is what earns it a place in this package.
|
|
12
|
+
*
|
|
13
|
+
* ⛔ **Do not add editor-side schema code here.** `normalizeSchema` — "can this
|
|
14
|
+
* be edited, and as what?" — sat beside this function until 2026-09-01 purely
|
|
15
|
+
* because the two were adjacent; it never called `isRichSchema` and had no
|
|
16
|
+
* consumer outside the editor. `@uniweb/core` loads on every site in every lane
|
|
17
|
+
* and is not tree-shaken on the hosted one, so an editor-only function on its
|
|
18
|
+
* entry is paid for by every visitor of every site. It now lives in the
|
|
19
|
+
* zero-dependency leaf that owns what a data-schema *means*:
|
|
20
|
+
* **`@uniweb/schemas/editor-form`**.
|
|
21
|
+
*
|
|
22
|
+
* Conditional field visibility (a rich-schema feature) is likewise editor-only
|
|
23
|
+
* and is not implemented here — the editor owns its own evaluator.
|
|
16
24
|
*/
|
|
17
25
|
|
|
18
26
|
/**
|
|
@@ -35,91 +43,3 @@ export function isRichSchema(schema) {
|
|
|
35
43
|
if (schema.childSchema && typeof schema.childSchema === 'object') return true
|
|
36
44
|
return false
|
|
37
45
|
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* ⛔ **DEPRECATED — MOVED to `@uniweb/schemas/editor-form` (2026-09-01).**
|
|
41
|
-
* This copy stays only so `frontend`, which pins core as `workspace:*` and
|
|
42
|
-
* would break at commit time, can migrate its one import. Delete it once that
|
|
43
|
-
* lands; nothing else in any repo reads it.
|
|
44
|
-
*
|
|
45
|
-
* ⭐ **It never belonged here.** It does not call `isRichSchema` and never did
|
|
46
|
-
* — it re-inlines the same three checks — so nothing but adjacency held it in
|
|
47
|
-
* this file. The two answer different questions for different audiences:
|
|
48
|
-
* `isRichSchema` is a render-time dispatch predicate (`prepare-props.js`,
|
|
49
|
-
* `runtime-schema.js`) and stays; this is read only by an editor, while core
|
|
50
|
-
* ships to every site in every lane and is not tree-shaken on the hosted one.
|
|
51
|
-
*
|
|
52
|
-
* Normalize any authored `data:` schema shape to the rich form the editor
|
|
53
|
-
* renders, or null when it is not a single form at all.
|
|
54
|
-
*
|
|
55
|
-
* WHY THIS EXISTS. `isRichSchema` answers "is this already the rich shape?",
|
|
56
|
-
* which is the right question for dispatch and the wrong one for "can this be
|
|
57
|
-
* edited". There are THREE authored shapes and it accepts exactly one:
|
|
58
|
-
*
|
|
59
|
-
* { fields: [ {id, …} ] } meta.js inline rich-form → true
|
|
60
|
-
* { fields: { name: spec } } a RESOLVED NAMED REF → FALSE
|
|
61
|
-
* { name: spec } meta.js inline field map → false
|
|
62
|
-
*
|
|
63
|
-
* The middle row is the important one and the reason this helper exists at all
|
|
64
|
-
* (it once read "the reason it is in `core` rather than in the editor" — that
|
|
65
|
-
* was the wrong conclusion from a right observation: the gap is real, closing
|
|
66
|
-
* it in one shared place is right, and `@uniweb/schemas` is that place).
|
|
67
|
-
* A named ref (`'@/article'`, `'@std/person'`) is the
|
|
68
|
-
* FIRST authoring form the docs show, and `validateAndNormalizeSchema` in the
|
|
69
|
-
* build resolves it to `{ fields: <MAP> }` — a map, not an array. So filtering
|
|
70
|
-
* with `isRichSchema` discards not merely "simple" schemas but the primary
|
|
71
|
-
* documented one, and any consumer that wants to render it has to re-derive the
|
|
72
|
-
* conversion. Three consumers re-deriving it is exactly the divergence the
|
|
73
|
-
* shared predicate was introduced to prevent.
|
|
74
|
-
*
|
|
75
|
-
* A field map is an unordered `fields[]`, so the conversion is mechanical.
|
|
76
|
-
* Ordering comes from `Object.entries`, which is insertion order for string keys
|
|
77
|
-
* — i.e. the order the author wrote, which is the order a form should show.
|
|
78
|
-
*
|
|
79
|
-
* `sections` returns null on purpose: a sectioned data-schema describes a Model
|
|
80
|
-
* with several sections, which is not one form. Flattening it would invent a
|
|
81
|
-
* layout the author never expressed.
|
|
82
|
-
*
|
|
83
|
-
* @param {*} schema - any authored or resolved `data:` schema value
|
|
84
|
-
* @returns {{ fields: Array<object> } | null} the rich shape, or null
|
|
85
|
-
*/
|
|
86
|
-
export function normalizeSchema(schema) {
|
|
87
|
-
if (!schema || typeof schema !== 'object' || Array.isArray(schema))
|
|
88
|
-
return null
|
|
89
|
-
|
|
90
|
-
// Already rich — hand back untouched. Composite/childSchema variants are rich
|
|
91
|
-
// by `isRichSchema`'s definition and are not ours to reshape.
|
|
92
|
-
if (Array.isArray(schema.fields)) return schema
|
|
93
|
-
if (schema.isComposite === true || schema.childSchema) return schema
|
|
94
|
-
|
|
95
|
-
// A sectioned Model is not a single form.
|
|
96
|
-
if (schema.sections !== undefined) return null
|
|
97
|
-
|
|
98
|
-
const mapToFields = (map) =>
|
|
99
|
-
Object.entries(map).map(([id, spec]) =>
|
|
100
|
-
typeof spec === 'string' ? { id, type: spec } : { id, ...spec }
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
// A resolved named ref: `fields` present, as a map.
|
|
104
|
-
if (schema.fields && typeof schema.fields === 'object') {
|
|
105
|
-
const { fields, ...rest } = schema
|
|
106
|
-
return { ...rest, fields: mapToFields(fields) }
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// An inline field map: no `fields` key, so every value must be an OBJECT
|
|
110
|
-
// carrying `type`.
|
|
111
|
-
//
|
|
112
|
-
// The bare-type string shorthand (`{ cpu: 'string' }`) is deliberately NOT
|
|
113
|
-
// accepted here, even though schema FILES support it. Without a `fields` key
|
|
114
|
-
// there is nothing to distinguish it from ordinary data: `{ name: 'Acme' }` and
|
|
115
|
-
// `{ cpu: 'string' }` are the same shape, and an earlier cut of this function
|
|
116
|
-
// turned `{ name, description }` into a two-field form. Erring toward null
|
|
117
|
-
// costs an author the object spelling; erring the other way invents a form out
|
|
118
|
-
// of a config block.
|
|
119
|
-
const entries = Object.entries(schema)
|
|
120
|
-
if (!entries.length) return null
|
|
121
|
-
const isFieldSpec = ([, v]) =>
|
|
122
|
-
v && typeof v === 'object' && !Array.isArray(v) && v.type !== undefined
|
|
123
|
-
if (!entries.every(isFieldSpec)) return null
|
|
124
|
-
return { fields: mapToFields(schema) }
|
|
125
|
-
}
|