@uniweb/build 0.64.0 → 0.64.2
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/i18n/extract.js +19 -0
- package/src/i18n/merge.js +15 -1
- package/src/i18n/records.js +5 -1
- package/src/import-map-plugin.js +13 -0
- package/src/runtime-schema.js +3 -1
- package/src/site/config.js +59 -5
- package/src/site/foundation-ref.js +21 -2
- package/src/site/index.js +2 -0
- package/src/site/preview-media.js +90 -0
- package/src/site/preview.js +84 -0
- package/src/site/queries-config.js +8 -1
- package/src/site/query-processor.js +6 -4
- package/src/site/registered-foundation.js +48 -0
- package/src/uwx/backfill.js +17 -6
- package/src/uwx/data-schema.js +34 -0
- package/src/uwx/emit-surface.json +6 -0
- package/src/uwx/index.js +9 -0
- package/src/uwx/open-graph.js +69 -0
- package/src/uwx/project-writer.js +6 -3
- package/src/uwx/records-project.js +50 -9
- package/src/uwx/records.js +48 -2
- package/src/uwx/site-project.js +13 -2
- package/src/uwx/site.js +36 -13
- package/src/uwx/sync-package.js +24 -1
- package/src/validate-data.js +15 -5
package/src/uwx/sync-package.js
CHANGED
|
@@ -359,6 +359,11 @@ export async function emitSyncPackages(siteRoot, opts = {}) {
|
|
|
359
359
|
// …and the same data schema, where a name stands for the type of its data key
|
|
360
360
|
// (`@/team` → `@/member`, `data-key-types.js`): decided once, by the records.
|
|
361
361
|
keyTyped: col.keyTyped,
|
|
362
|
+
// …and whether this deployment takes the key that says so (`siteContent.queryFields`) —
|
|
363
|
+
// and the page and `settings` keys that carry Open Graph texts per language.
|
|
364
|
+
...(Array.isArray(opts.queryFields) ? { queryFields: opts.queryFields } : {}),
|
|
365
|
+
...(Array.isArray(opts.pageFields) ? { pageFields: opts.pageFields } : {}),
|
|
366
|
+
...(Array.isArray(opts.settingsFields) ? { settingsFields: opts.settingsFields } : {}),
|
|
362
367
|
// Withhold the `$services`/`$secrets` Sections when the caller has
|
|
363
368
|
// determined the file is not asking for anything new by them. Passed
|
|
364
369
|
// through rather than decided here: the last-agreed state is project
|
|
@@ -517,6 +522,21 @@ export async function emitSyncPackages(siteRoot, opts = {}) {
|
|
|
517
522
|
}))
|
|
518
523
|
const changedRecords = recordChanged.filter((r) => r.changed)
|
|
519
524
|
|
|
525
|
+
// ⛔ A RECORD THAT LOST ITS IDENTITY IS NOT UNCHANGED. Its hash was banked for this backend,
|
|
526
|
+
// so a push to it succeeded — and wrote the record's `$uuid` into its file — yet it goes with no
|
|
527
|
+
// `$uuid` now: the line is gone from the file. Skipped as unchanged, the folder still named it,
|
|
528
|
+
// by `$ref`, and the backend refused a reference to a record the package does not carry
|
|
529
|
+
// (measured 2026-09-26); sent, it would be a second record. A pull writes it back.
|
|
530
|
+
const refusals = [...(col.refusals || [])]
|
|
531
|
+
for (const r of recordChanged) {
|
|
532
|
+
if (r.changed || r.entity.document.$uuid) continue
|
|
533
|
+
refusals.push(
|
|
534
|
+
`${r.entity.id}: its \`$uuid\` is gone from its file, though it was pushed to this backend ` +
|
|
535
|
+
'before — sent as it is, it would be a second record. Run `uniweb pull`, which writes it ' +
|
|
536
|
+
'back, then push.'
|
|
537
|
+
)
|
|
538
|
+
}
|
|
539
|
+
|
|
520
540
|
let records = null
|
|
521
541
|
// ⭐ A RECORD THAT NAMES A RECORD THIS PUSH CREATES names it by `$ref`
|
|
522
542
|
// (`records.js::encodeReference`), and the backend stores the uuid it mints for it. The
|
|
@@ -572,6 +592,9 @@ export async function emitSyncPackages(siteRoot, opts = {}) {
|
|
|
572
592
|
// banked is then, by construction, what was hashed. A future injection is covered
|
|
573
593
|
// by adding one line here — not by finding every reader.
|
|
574
594
|
const applied = {
|
|
595
|
+
...(Array.isArray(opts.queryFields) ? { queryFields: opts.queryFields } : {}),
|
|
596
|
+
...(Array.isArray(opts.pageFields) ? { pageFields: opts.pageFields } : {}),
|
|
597
|
+
...(Array.isArray(opts.settingsFields) ? { settingsFields: opts.settingsFields } : {}),
|
|
575
598
|
...(assetRewrite ? { assetRewrite } : {}),
|
|
576
599
|
...(assetIds ? { assetIds } : {}),
|
|
577
600
|
...(injectInfo ? { injectInfo } : {}),
|
|
@@ -582,7 +605,7 @@ export async function emitSyncPackages(siteRoot, opts = {}) {
|
|
|
582
605
|
siteContent, records, siteContentUuid, hashes, warnings, skipped,
|
|
583
606
|
// Records that name a record this push creates — see `namesNew` above.
|
|
584
607
|
namesNew,
|
|
585
|
-
refusals
|
|
608
|
+
refusals,
|
|
586
609
|
schemaless: col.schemaless, localAssets, applied,
|
|
587
610
|
// { stamped, unknown } when identity was applied; null when the caller passed
|
|
588
611
|
// no map. `unknown > 0` with `stamped === 0` on a site that has been pushed
|
package/src/validate-data.js
CHANGED
|
@@ -206,10 +206,19 @@ export async function validateDataInputs({ siteRoot, foundationPath }) {
|
|
|
206
206
|
// (pass 2). A list root was deferred here until then, though the query's records
|
|
207
207
|
// are exactly that list.
|
|
208
208
|
|
|
209
|
+
// ⭐ WHAT THE QUERY'S RECORDS ARE, for a key typed by a schema whose root is a list: the
|
|
210
|
+
// list's ITEMS when the query selects other records (`@/link` records feeding `@/menu`), but
|
|
211
|
+
// ENTITIES of the list schema — each holding a whole list — when the query names that schema
|
|
212
|
+
// itself (`menus: { schema: '@/menu' }`). ⛔ Until 2026-09-26 both were checked as items, so
|
|
213
|
+
// every query over a list schema failed ("missing required field '[0].label'") and a push,
|
|
214
|
+
// which gates on this check, stopped.
|
|
215
|
+
const decl = typeof input.query === 'string' ? config.queries?.[input.query] : null
|
|
216
|
+
const querySchema = decl ? decl.schema ?? keyTypes.get(input.query) ?? `@/${input.query}` : undefined
|
|
217
|
+
|
|
209
218
|
const pairKey = `${input.path} ${ref}`
|
|
210
219
|
let entry = work.get(pairKey)
|
|
211
220
|
if (!entry) {
|
|
212
|
-
entry = { path: input.path, ref, schema, users: [] }
|
|
221
|
+
entry = { path: input.path, ref, schema, users: [], entities: querySchema === ref }
|
|
213
222
|
work.set(pairKey, entry)
|
|
214
223
|
}
|
|
215
224
|
entry.users.push({ route: page.route, section: type, key })
|
|
@@ -234,10 +243,11 @@ export async function validateDataInputs({ siteRoot, foundationPath }) {
|
|
|
234
243
|
schemasSeen.add(entry.ref)
|
|
235
244
|
const items = Array.isArray(records) ? records : [records]
|
|
236
245
|
|
|
237
|
-
// A schema whose ROOT IS A LIST describes the whole value the key receives, and
|
|
238
|
-
//
|
|
239
|
-
// schema describes one record, checked per record
|
|
240
|
-
|
|
246
|
+
// A schema whose ROOT IS A LIST describes the whole value the key receives, and a query of
|
|
247
|
+
// other records delivers that list — so they are checked once, as the list. Any other
|
|
248
|
+
// schema describes one record, checked per record — and so are the entities of a list
|
|
249
|
+
// schema a query of that schema delivers, each holding its list (`validateItem`).
|
|
250
|
+
if (rootListSection(entry.schema) && !entry.entities) {
|
|
241
251
|
recordCount += items.length
|
|
242
252
|
const base = { file: entry.path, schema: entry.ref, users: entry.users }
|
|
243
253
|
for (const finding of validateBound(entry.schema, items)) {
|