@uniweb/build 0.75.0 → 0.76.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 +8 -8
- package/src/dev/plugin.js +3 -3
- package/src/generate-entry.js +15 -28
- package/src/i18n/data-models.js +77 -0
- package/src/i18n/data-strings.js +27 -0
- package/src/i18n/extract.js +15 -11
- package/src/i18n/index.js +9 -4
- package/src/i18n/merge.js +39 -22
- package/src/i18n/model-fields.js +97 -0
- package/src/i18n/records.js +3 -59
- package/src/resolve-data-schema.js +66 -13
- package/src/runtime-schema.js +54 -218
- package/src/site/plugin.js +8 -1
- package/src/uwx/data-schema.js +4 -2
- package/src/uwx/index.js +2 -0
- package/src/uwx/locale-sync.js +17 -11
- package/src/uwx/site-project.js +7 -4
- package/src/uwx/site.js +4 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ⭐ A RECORD'S FIELDS, WALKED BY ITS MODEL — the shape a push sends it in, lowered by the push's
|
|
3
|
+
* own rule (`uwx/data-schema.js::toDataSchemaDeclaration`), which marks `localized` exactly the
|
|
4
|
+
* fields that travel per locale: text — never an enum, a value format (a URL, an email), a
|
|
5
|
+
* `translatable: false` field, a number, a date, a file or a reference.
|
|
6
|
+
*
|
|
7
|
+
* One walk for two things a model describes: a record (`records.js`), and a tagged data block whose
|
|
8
|
+
* key a section type declares the shape of (`data-strings.js::visitDataBlockStrings`).
|
|
9
|
+
*/
|
|
10
|
+
import { isOpenMapSection } from '../uwx/data-schema.js'
|
|
11
|
+
|
|
12
|
+
export function isPlainObject(value) {
|
|
13
|
+
return !!value && typeof value === 'object' && !Array.isArray(value)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* ⛔ A RECORD'S SYSTEM FIELDS ARE NEVER PROSE — never extracted, never translated, by
|
|
18
|
+
* either path. A `$`-prefixed key at any depth is the system's (`$name`, the handle a
|
|
19
|
+
* parametric page's URL names; `$uuid`; `$branch`, the folder a compiled list holds a
|
|
20
|
+
* record under), and a top-level `slug` is how a record's reader hands the file's name
|
|
21
|
+
* on. Until 2026-09-14 they became translation units, and a translation whose source
|
|
22
|
+
* happened to equal one rewrote it, so a record's page stopped matching its URL.
|
|
23
|
+
* ⛔ A top-level `path` was one too until 2026-09-27, when the placement it named moved to
|
|
24
|
+
* `$branch` [Diego]: a field an author names `path` is theirs, and translated as its schema says.
|
|
25
|
+
*
|
|
26
|
+
* @param {string|number} key - a field name (an array index is never one)
|
|
27
|
+
* @param {boolean} topLevel - whether the key sits at the record's own level
|
|
28
|
+
* @returns {boolean}
|
|
29
|
+
*/
|
|
30
|
+
export function isRecordSystemField(key, topLevel) {
|
|
31
|
+
if (typeof key !== 'string') return false
|
|
32
|
+
return key.startsWith('$') || (topLevel && key === 'slug')
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Each field of a model that a record holds a value for, in the shape the record is DELIVERED in
|
|
37
|
+
* (`toDeliveredRecord`): the brief's fields at the top — every field, for a model of one single
|
|
38
|
+
* section — and each other section under its name, a list of them for a `multiple` one, a nested
|
|
39
|
+
* section the same way. Calls `visit(holder, name, field, path)` for each.
|
|
40
|
+
*/
|
|
41
|
+
export function eachModelField(record, model, visit) {
|
|
42
|
+
const sections = Object.entries(model?.sections || {})
|
|
43
|
+
const flat = sections.length === 1 && !sections[0][1]?.multiple
|
|
44
|
+
for (const [name, section] of sections) {
|
|
45
|
+
if (flat || section?.brief) eachSectionField(record, section?.fields, '', visit)
|
|
46
|
+
else eachSectionValue(record?.[name], section, name, visit)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function eachSectionValue(value, section, path, visit) {
|
|
51
|
+
if (!section?.multiple) return eachSectionField(value, section?.fields, path, visit)
|
|
52
|
+
if (Array.isArray(value)) value.forEach((item, i) => eachSectionField(item, section.fields, `${path}[${i}]`, visit))
|
|
53
|
+
// An open map as its file holds it: each entry is one of the rows a push sends (`isOpenMapSection`).
|
|
54
|
+
else if (isOpenMapSection(section) && isPlainObject(value)) {
|
|
55
|
+
for (const [key, item] of Object.entries(value)) eachSectionField(item, section.fields, `${path}.${key}`, visit)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function eachSectionField(holder, fields, path, visit) {
|
|
60
|
+
if (!isPlainObject(holder)) return
|
|
61
|
+
for (const [name, field] of Object.entries(fields || {})) {
|
|
62
|
+
if (holder[name] == null || isRecordSystemField(name, !path)) continue
|
|
63
|
+
const at = path ? `${path}.${name}` : name
|
|
64
|
+
if (field?.type === 'section') eachSectionValue(holder[name], field, at, visit)
|
|
65
|
+
else visit(holder, name, field || {}, at)
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Each string a record's model marks `localized` — a text field's value, or each string of a list
|
|
71
|
+
* of them — handed to `visit(value, path)`; a different string returned replaces it, in place, as
|
|
72
|
+
* `data-strings.js::visitDataStrings` does. A rich field is one string here: a data block holds its
|
|
73
|
+
* markdown as written.
|
|
74
|
+
*
|
|
75
|
+
* @param {object} record
|
|
76
|
+
* @param {object} model - a lowered data schema (`toDataSchemaDeclaration`)
|
|
77
|
+
* @param {(value: string, path: string) => string|void} visit
|
|
78
|
+
* @param {string} [prefix] - prepended to each path (`[0]` for a list's first item)
|
|
79
|
+
*/
|
|
80
|
+
export function visitModelStrings(record, model, visit, prefix = '') {
|
|
81
|
+
const pathOf = (path) => (prefix ? (path.startsWith('[') ? `${prefix}${path}` : `${prefix}.${path}`) : path)
|
|
82
|
+
eachModelField(record, model, (holder, name, field, path) => {
|
|
83
|
+
if (!field.localized) return
|
|
84
|
+
const value = holder[name]
|
|
85
|
+
if (typeof value === 'string') {
|
|
86
|
+
if (!value.trim()) return
|
|
87
|
+
const next = visit(value, pathOf(path))
|
|
88
|
+
if (typeof next === 'string' && next !== value) holder[name] = next
|
|
89
|
+
} else if (Array.isArray(value)) {
|
|
90
|
+
value.forEach((item, i) => {
|
|
91
|
+
if (typeof item !== 'string' || !item.trim()) return
|
|
92
|
+
const next = visit(item, pathOf(`${path}[${i}]`))
|
|
93
|
+
if (typeof next === 'string' && next !== item) value[i] = next
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
}
|
package/src/i18n/records.js
CHANGED
|
@@ -23,7 +23,8 @@ import { computeHash } from './hash.js'
|
|
|
23
23
|
import { loadFreeformRecord } from './freeform.js'
|
|
24
24
|
import { resolveQueriesConfig, resolveRecordSchemas, foundationSchemaJson } from '../site/queries-config.js'
|
|
25
25
|
import { dataKeyTypes, keyOfDefaultRef } from '../uwx/data-key-types.js'
|
|
26
|
-
import { toDataSchemaDeclaration, isProseMirrorField
|
|
26
|
+
import { toDataSchemaDeclaration, isProseMirrorField } from '../uwx/data-schema.js'
|
|
27
|
+
import { eachModelField, eachSectionField, isRecordSystemField, isPlainObject } from './model-fields.js'
|
|
27
28
|
import { toDeliveredRecord, contentBodyField, misplacedFields, mergedFromStored, storedFromMerged } from '@uniweb/schemas/conform'
|
|
28
29
|
import { resolveDocForLocale } from './merge.js'
|
|
29
30
|
import { extractUnitsFromDoc } from './extract.js'
|
|
@@ -186,7 +187,7 @@ function isFieldTranslatable(fieldDef) {
|
|
|
186
187
|
* @param {string} ref - the ref it was resolved from
|
|
187
188
|
* @returns {Object|null} the lowered declaration, or null when there is none
|
|
188
189
|
*/
|
|
189
|
-
function modelOf(schema, ref) {
|
|
190
|
+
export function modelOf(schema, ref) {
|
|
190
191
|
if (!schema) return null
|
|
191
192
|
try {
|
|
192
193
|
return toDataSchemaDeclaration(schema, { name: ref || '@/record', resolveName: (r) => r })
|
|
@@ -208,40 +209,6 @@ function referencedModels(model) {
|
|
|
208
209
|
return out
|
|
209
210
|
}
|
|
210
211
|
|
|
211
|
-
/**
|
|
212
|
-
* Each field of a model that a record holds a value for, in the shape the record is DELIVERED in
|
|
213
|
-
* (`toDeliveredRecord`): the brief's fields at the top — every field, for a model of one single
|
|
214
|
-
* section — and each other section under its name, a list of them for a `multiple` one, a nested
|
|
215
|
-
* section the same way. Calls `visit(holder, name, field, path)` for each.
|
|
216
|
-
*/
|
|
217
|
-
function eachModelField(record, model, visit) {
|
|
218
|
-
const sections = Object.entries(model?.sections || {})
|
|
219
|
-
const flat = sections.length === 1 && !sections[0][1]?.multiple
|
|
220
|
-
for (const [name, section] of sections) {
|
|
221
|
-
if (flat || section?.brief) eachSectionField(record, section?.fields, '', visit)
|
|
222
|
-
else eachSectionValue(record?.[name], section, name, visit)
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
function eachSectionValue(value, section, path, visit) {
|
|
227
|
-
if (!section?.multiple) return eachSectionField(value, section?.fields, path, visit)
|
|
228
|
-
if (Array.isArray(value)) value.forEach((item, i) => eachSectionField(item, section.fields, `${path}[${i}]`, visit))
|
|
229
|
-
// An open map as its file holds it: each entry is one of the rows a push sends (`isOpenMapSection`).
|
|
230
|
-
else if (isOpenMapSection(section) && isPlainObject(value)) {
|
|
231
|
-
for (const [key, item] of Object.entries(value)) eachSectionField(item, section.fields, `${path}.${key}`, visit)
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function eachSectionField(holder, fields, path, visit) {
|
|
236
|
-
if (!isPlainObject(holder)) return
|
|
237
|
-
for (const [name, field] of Object.entries(fields || {})) {
|
|
238
|
-
if (holder[name] == null || isRecordSystemField(name, !path)) continue
|
|
239
|
-
const at = path ? `${path}.${name}` : name
|
|
240
|
-
if (field?.type === 'section') eachSectionValue(holder[name], field, at, visit)
|
|
241
|
-
else visit(holder, name, field || {}, at)
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
212
|
/** The fields of a model's brief — what a reference to one of its records is delivered as. */
|
|
246
213
|
function briefFields(model) {
|
|
247
214
|
const sections = Object.values(model?.sections || {})
|
|
@@ -360,25 +327,6 @@ function derivesExcerpt(record, whole, dataSchema, config) {
|
|
|
360
327
|
return derivedExcerptOf(whole ?? record, dataSchema, config) === record.excerpt
|
|
361
328
|
}
|
|
362
329
|
|
|
363
|
-
/**
|
|
364
|
-
* ⛔ A RECORD'S SYSTEM FIELDS ARE NEVER PROSE — never extracted, never translated, by
|
|
365
|
-
* either path. A `$`-prefixed key at any depth is the system's (`$name`, the handle a
|
|
366
|
-
* parametric page's URL names; `$uuid`; `$branch`, the folder a compiled list holds a
|
|
367
|
-
* record under), and a top-level `slug` is how a record's reader hands the file's name
|
|
368
|
-
* on. Until 2026-09-14 they became translation units, and a translation whose source
|
|
369
|
-
* happened to equal one rewrote it, so a record's page stopped matching its URL.
|
|
370
|
-
* ⛔ A top-level `path` was one too until 2026-09-27, when the placement it named moved to
|
|
371
|
-
* `$branch` [Diego]: a field an author names `path` is theirs, and translated as its schema says.
|
|
372
|
-
*
|
|
373
|
-
* @param {string|number} key - a field name (an array index is never one)
|
|
374
|
-
* @param {boolean} topLevel - whether the key sits at the record's own level
|
|
375
|
-
* @returns {boolean}
|
|
376
|
-
*/
|
|
377
|
-
function isRecordSystemField(key, topLevel) {
|
|
378
|
-
if (typeof key !== 'string') return false
|
|
379
|
-
return key.startsWith('$') || (topLevel && key === 'slug')
|
|
380
|
-
}
|
|
381
|
-
|
|
382
330
|
/**
|
|
383
331
|
* A record's handle — `$name`, which the build sets from the record's file (`slug:` or
|
|
384
332
|
* its name). ⭐ Not `slug` alone: a record of a schema whose brief declares a `slug`
|
|
@@ -1208,10 +1156,6 @@ function applyFreeform(record, freeform, dataSchema, schemaRef) {
|
|
|
1208
1156
|
return out
|
|
1209
1157
|
}
|
|
1210
1158
|
|
|
1211
|
-
function isPlainObject(value) {
|
|
1212
|
-
return !!value && typeof value === 'object' && !Array.isArray(value)
|
|
1213
|
-
}
|
|
1214
|
-
|
|
1215
1159
|
/**
|
|
1216
1160
|
* Apply translations to a collection item (sync, hash-based only) — by the model it is pushed as
|
|
1217
1161
|
* when it has one (`translateByModel`), else a companion schema's fields, else the heuristic.
|
|
@@ -84,6 +84,60 @@ export const SCHEMA_NOT_FOUND = 'SCHEMA_NOT_FOUND'
|
|
|
84
84
|
const RESERVED_SYSTEM_SCOPE = 'uniweb'
|
|
85
85
|
const packageForScope = (scope) => SCOPE_PACKAGE[scope] ?? `@${scope}/schemas`
|
|
86
86
|
|
|
87
|
+
/**
|
|
88
|
+
* A NAMED data schema — a `schemas/` file, `@std/<name>`, `@org/<name>` — validated and
|
|
89
|
+
* normalized, and refused when a field declares a `default`.
|
|
90
|
+
*
|
|
91
|
+
* ⛔ A named schema declares no default — ruled 2026-10-05 [Diego], when the runtime stopped
|
|
92
|
+
* filling fields: nothing would read one. The runtime fills no field, the declaration a
|
|
93
|
+
* registry stores carries none (`uwx/data-schema.js`), and the foundation schema an editor
|
|
94
|
+
* reads leaves `dataSchemas` out (`uwx/registry-package.js`) — so a `default:` here would be a
|
|
95
|
+
* promise kept nowhere. What an absent field renders as is the component's choice. A default
|
|
96
|
+
* stays where an editor reads it: a component's own inline field map or form in `data:`.
|
|
97
|
+
*
|
|
98
|
+
* @param {object} schema - the schema as authored
|
|
99
|
+
* @param {string} ref - its ref, for the message
|
|
100
|
+
* @returns {object} the normalized schema
|
|
101
|
+
*/
|
|
102
|
+
function normalizeNamedSchema(schema, ref) {
|
|
103
|
+
const normalized = validateAndNormalizeSchema(schema, ref)
|
|
104
|
+
const paths = fieldsWithDefaults(normalized)
|
|
105
|
+
if (paths.length > 0) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`Data schema '${ref}': a named data schema declares no default — remove \`default:\` from ` +
|
|
108
|
+
`${paths.map((p) => `'${p}'`).join(', ')}. A component decides what an absent field ` +
|
|
109
|
+
`renders as; an editor pre-fills from a component's own inline field map or form in \`data:\`.`
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
return normalized
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** The dotted paths of every field in a normalized schema that declares a `default`. */
|
|
116
|
+
function fieldsWithDefaults(schema) {
|
|
117
|
+
const found = []
|
|
118
|
+
const walkFields = (fields, prefix) => {
|
|
119
|
+
if (!fields || typeof fields !== 'object') return
|
|
120
|
+
for (const [name, spec] of Object.entries(fields)) walkSpec(spec, `${prefix}${name}`)
|
|
121
|
+
}
|
|
122
|
+
const walkSpec = (spec, path) => {
|
|
123
|
+
if (!spec || typeof spec !== 'object') return
|
|
124
|
+
if (spec.default !== undefined) found.push(path)
|
|
125
|
+
walkFields(spec.fields, `${path}.`)
|
|
126
|
+
if (spec.items) walkSpec(spec.items, `${path}[]`)
|
|
127
|
+
if (spec.values) walkSpec(spec.values, `${path}{}`)
|
|
128
|
+
}
|
|
129
|
+
const walkSections = (sections, prefix) => {
|
|
130
|
+
if (!sections || typeof sections !== 'object') return
|
|
131
|
+
for (const [name, section] of Object.entries(sections)) {
|
|
132
|
+
walkFields(section?.fields, `${prefix}${name}.`)
|
|
133
|
+
walkSections(section?.sections, `${prefix}${name}.`)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
walkFields(schema?.fields, '')
|
|
137
|
+
walkSections(schema?.sections, '')
|
|
138
|
+
return found
|
|
139
|
+
}
|
|
140
|
+
|
|
87
141
|
/**
|
|
88
142
|
* Collect every distinct schema ref used by a foundation's section bindings.
|
|
89
143
|
* Reads `data: { key: '<ref>' }` (short) and `data: { key: { schema: '<ref>' } }`
|
|
@@ -94,9 +148,9 @@ const packageForScope = (scope) => SCOPE_PACKAGE[scope] ?? `@${scope}/schemas`
|
|
|
94
148
|
* (`declaredKeys`, `@uniweb/core/data-keys`) — but only components were scanned
|
|
95
149
|
* here, so a ref at that tier was neither resolved into `dataSchemas` nor
|
|
96
150
|
* rejected when dangling, while the key was still delivered at runtime. The
|
|
97
|
-
* symptom would have been no schema for the editor
|
|
98
|
-
*
|
|
99
|
-
*
|
|
151
|
+
* symptom would have been no schema for the editor, with no build error. It bit
|
|
152
|
+
* nobody only because every foundation-tier declaration in the templates is
|
|
153
|
+
* ref-less.
|
|
100
154
|
*
|
|
101
155
|
* @param {Object} components - Map of componentName → full meta (with `data`)
|
|
102
156
|
* @param {Object|false|null} [foundationData] - the foundation's `main.js` `data:`
|
|
@@ -136,7 +190,7 @@ export async function resolveSchemaRef(ref, { srcDir, aliases }) {
|
|
|
136
190
|
{ code: SCHEMA_NOT_FOUND }
|
|
137
191
|
)
|
|
138
192
|
}
|
|
139
|
-
return
|
|
193
|
+
return normalizeNamedSchema(await loadSchemaFile(file), ref)
|
|
140
194
|
}
|
|
141
195
|
|
|
142
196
|
// ⭐ THE SYSTEM MODELS A SITE'S RECORDS MAY NAME — `@uniweb/link` — resolve from the build's own
|
|
@@ -145,7 +199,7 @@ export async function resolveSchemaRef(ref, { srcDir, aliases }) {
|
|
|
145
199
|
// never a data-schema source. (The whole scope was refused until 2026-09-28.)
|
|
146
200
|
if (scope === RESERVED_SYSTEM_SCOPE) {
|
|
147
201
|
const system = SYSTEM_RECORD_SCHEMAS[name]
|
|
148
|
-
if (system) return
|
|
202
|
+
if (system) return normalizeNamedSchema(system, ref)
|
|
149
203
|
const allowed = Object.keys(SYSTEM_RECORD_SCHEMAS).map((n) => `'@${scope}/${n}'`).join(', ')
|
|
150
204
|
throw new Error(
|
|
151
205
|
`'@${scope}' is the reserved platform system namespace: the only data schemas a site's records ` +
|
|
@@ -170,7 +224,7 @@ export async function resolveSchemaRef(ref, { srcDir, aliases }) {
|
|
|
170
224
|
`exists there. Point it at a ${SCHEMA_EXTENSIONS.join(' / ')} file.`
|
|
171
225
|
)
|
|
172
226
|
}
|
|
173
|
-
return
|
|
227
|
+
return normalizeNamedSchema(await loadSchemaFile(file), ref)
|
|
174
228
|
}
|
|
175
229
|
|
|
176
230
|
// A scope alias ('@org' → a DIR) resolves 'name' to a bare schema FILE in that
|
|
@@ -195,7 +249,7 @@ export async function resolveSchemaRef(ref, { srcDir, aliases }) {
|
|
|
195
249
|
}
|
|
196
250
|
throw new Error(msg)
|
|
197
251
|
}
|
|
198
|
-
return
|
|
252
|
+
return normalizeNamedSchema(await loadSchemaFile(file), ref)
|
|
199
253
|
}
|
|
200
254
|
|
|
201
255
|
// Every other scope is an org namespace: '@org/name' resolves `name` from that
|
|
@@ -207,7 +261,7 @@ export async function resolveSchemaRef(ref, { srcDir, aliases }) {
|
|
|
207
261
|
if (!schema) {
|
|
208
262
|
throw new Error(`Unknown data schema '${ref}': '${pkg}' exports no schema named '${name}'.`)
|
|
209
263
|
}
|
|
210
|
-
return
|
|
264
|
+
return normalizeNamedSchema(schema, ref)
|
|
211
265
|
}
|
|
212
266
|
|
|
213
267
|
/**
|
|
@@ -224,9 +278,8 @@ export async function resolveSchemaRef(ref, { srcDir, aliases }) {
|
|
|
224
278
|
export async function buildDataSchemaMap(refs, { srcDir }) {
|
|
225
279
|
// Load the foundation's optional schemas.config.js once; every ref (and every
|
|
226
280
|
// transitively-discovered ref) resolves against the same alias map. This is
|
|
227
|
-
// the single entry
|
|
228
|
-
//
|
|
229
|
-
// resolve refs identically.
|
|
281
|
+
// the single entry schema discovery and `uniweb validate` go through, so the
|
|
282
|
+
// editor's schema.json and the check of a site's data resolve refs identically.
|
|
230
283
|
const aliases = await loadSchemaAliases(srcDir)
|
|
231
284
|
const map = {}
|
|
232
285
|
const queue = Array.from(refs)
|
|
@@ -299,7 +352,7 @@ async function collectSchemasFromExports(packageDir) {
|
|
|
299
352
|
for (const name of names) {
|
|
300
353
|
const schema = get(name)
|
|
301
354
|
if (!schema || typeof schema !== 'object') continue
|
|
302
|
-
out[`@/${name}`] =
|
|
355
|
+
out[`@/${name}`] = normalizeNamedSchema(schema, `@/${name}`)
|
|
303
356
|
}
|
|
304
357
|
return out
|
|
305
358
|
}
|
|
@@ -309,7 +362,7 @@ async function collectSchemasFromExports(packageDir) {
|
|
|
309
362
|
async function collectSchemasFromDir(dir) {
|
|
310
363
|
const out = {}
|
|
311
364
|
for (const { file, name } of schemaFilesIn(dir)) {
|
|
312
|
-
out[`@/${name}`] =
|
|
365
|
+
out[`@/${name}`] = normalizeNamedSchema(await loadSchemaFile(join(dir, file)), `@/${name}`)
|
|
313
366
|
}
|
|
314
367
|
return out
|
|
315
368
|
}
|