@uniweb/build 0.56.0 → 0.57.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 +7 -7
- package/src/content/index.js +3 -0
- package/src/i18n/data-strings.js +1 -1
- package/src/i18n/freeform.js +20 -19
- package/src/i18n/index.js +4 -4
- package/src/i18n/records.js +9 -5
- package/src/site/build-site-data.js +4 -3
- package/src/site/config.js +1 -1
- package/src/site/content-collector.js +4 -3
- package/src/site/entity-pool.js +136 -42
- package/src/site/plugin.js +12 -9
- package/src/site/queries-config.js +15 -5
- package/src/site/query-processor.js +126 -112
- package/src/site/record-draft.js +40 -0
- package/src/site/records-config.js +101 -93
- package/src/uwx/asset-map.js +2 -1
- package/src/uwx/backfill.js +2 -2
- package/src/uwx/entity-source.js +3 -3
- package/src/uwx/folder.js +89 -49
- package/src/uwx/index.js +9 -9
- package/src/uwx/records-project.js +95 -64
- package/src/uwx/records.js +310 -214
- package/src/uwx/self-scope.js +5 -5
- package/src/uwx/site-project.js +3 -3
- package/src/uwx/site.js +45 -39
- package/src/uwx/sync-package.js +19 -15
- package/src/validate-data.js +3 -1
package/src/site/plugin.js
CHANGED
|
@@ -50,7 +50,7 @@ import { collectSiteContent, mountEntriesOf } from './content-collector.js'
|
|
|
50
50
|
import { processAssets, rewriteSiteContentPaths } from './asset-processor.js'
|
|
51
51
|
import { processAdvancedAssets } from './advanced-processors.js'
|
|
52
52
|
import { processQueries, writeQueryFiles } from './query-processor.js'
|
|
53
|
-
import {
|
|
53
|
+
import { RECORDS_DIR, resolveRecordsDir } from './entity-pool.js'
|
|
54
54
|
import { executeFetch, mergeDataIntoContent, toFetchList } from './data-fetcher.js'
|
|
55
55
|
import { shouldSplitContent } from './split-content.js'
|
|
56
56
|
import { FONT_LINKS_MARKER } from './head-markers.js'
|
|
@@ -133,7 +133,7 @@ export function shouldPrefetchInDev(cfg) {
|
|
|
133
133
|
* query list just collected, reload. `queries.yml` declares queries, and so does
|
|
134
134
|
* `site.yml` (`queries:`), beside the rest of the site's configuration.
|
|
135
135
|
* - `'records'` — re-materialize the query files, reload: `records.yml` decides
|
|
136
|
-
* which
|
|
136
|
+
* which folder each record sits in, which a query's `scope:` reads.
|
|
137
137
|
* - `'content'` — re-collect the site, reload.
|
|
138
138
|
*
|
|
139
139
|
* ⛔ Until 2026-09-14 nothing watched `records.yml` or `queries.yml`, a `site.yml`
|
|
@@ -665,7 +665,7 @@ export function siteContentPlugin(options = {}) {
|
|
|
665
665
|
let resolvedPagesPath = null // Resolved from site.yml pagesDir or default
|
|
666
666
|
let resolvedMountPaths = [] // Absolute dirs mounted under pages/ via site.yml paths:
|
|
667
667
|
let resolvedLayoutPath = null // Resolved from site.yml layoutDir or default
|
|
668
|
-
let
|
|
668
|
+
let resolvedRecordsDir = null // site.yml `paths.records` as written, via `resolveRecordsDir`
|
|
669
669
|
let headHtml = '' // Contents of site/head.html for injection
|
|
670
670
|
let basePath = '/' // Vite's config.base, always has trailing slash
|
|
671
671
|
|
|
@@ -725,8 +725,11 @@ export function siteContentPlugin(options = {}) {
|
|
|
725
725
|
*/
|
|
726
726
|
async function materializeQueries(queries, config) {
|
|
727
727
|
if (!queries) return
|
|
728
|
-
const byQuery = await processQueries(resolvedSitePath, queries,
|
|
728
|
+
const byQuery = await processQueries(resolvedSitePath, queries, resolvedRecordsDir, basePath, {
|
|
729
729
|
locale: resolveDefaultLocale(config ?? {}) ?? null,
|
|
730
|
+
// ⭐ A draft is previewable here, as a hidden page is — `pnpm dev` is where the
|
|
731
|
+
// author looks at it. A production build leaves it out (`buildStart`).
|
|
732
|
+
includeDrafts: !isProduction,
|
|
730
733
|
})
|
|
731
734
|
await writeQueryFiles(resolvedSitePath, byQuery, queries)
|
|
732
735
|
}
|
|
@@ -911,7 +914,7 @@ export function siteContentPlugin(options = {}) {
|
|
|
911
914
|
resolvedLayoutPath = paths.layout
|
|
912
915
|
? resolve(resolvedSitePath, paths.layout)
|
|
913
916
|
: resolve(resolvedSitePath, 'layout')
|
|
914
|
-
|
|
917
|
+
resolvedRecordsDir = resolveRecordsDir(resolvedSitePath, paths).rel
|
|
915
918
|
resolvedMountPaths = mountEntriesOf(paths).map(([, rel]) => resolve(resolvedSitePath, rel))
|
|
916
919
|
|
|
917
920
|
if (queriesConfig) {
|
|
@@ -934,7 +937,7 @@ export function siteContentPlugin(options = {}) {
|
|
|
934
937
|
resolvedLayoutPath = paths.layout
|
|
935
938
|
? resolve(resolvedSitePath, paths.layout)
|
|
936
939
|
: resolve(resolvedSitePath, 'layout')
|
|
937
|
-
|
|
940
|
+
resolvedRecordsDir = resolveRecordsDir(resolvedSitePath, paths).rel
|
|
938
941
|
}
|
|
939
942
|
},
|
|
940
943
|
|
|
@@ -954,7 +957,7 @@ export function siteContentPlugin(options = {}) {
|
|
|
954
957
|
// In production, do it here
|
|
955
958
|
if (isProduction && siteContent.config?.queries) {
|
|
956
959
|
console.log('[site-content] Materializing queries...')
|
|
957
|
-
const byQuery = await processQueries(resolvedSitePath, siteContent.config.queries,
|
|
960
|
+
const byQuery = await processQueries(resolvedSitePath, siteContent.config.queries, resolvedRecordsDir, basePath)
|
|
958
961
|
await writeQueryFiles(resolvedSitePath, byQuery, siteContent.config.queries)
|
|
959
962
|
}
|
|
960
963
|
|
|
@@ -1113,11 +1116,11 @@ export function siteContentPlugin(options = {}) {
|
|
|
1113
1116
|
// ⭐ WATCH THE POOL, NOT A DIRECTORY PER QUERY. This used to resolve
|
|
1114
1117
|
// `config.path` for each declaration and watch each one, so a schema
|
|
1115
1118
|
// folder no query had mentioned yet — a new one, mid-session — was
|
|
1116
|
-
// watched by nothing and its records never rebuilt. `
|
|
1119
|
+
// watched by nothing and its records never rebuilt. `records/` is one
|
|
1117
1120
|
// recursive root and covers every schema, present and future.
|
|
1118
1121
|
{
|
|
1119
1122
|
const contentPaths = new Set([
|
|
1120
|
-
resolve(resolvedSitePath,
|
|
1123
|
+
resolve(resolvedSitePath, resolvedRecordsDir || RECORDS_DIR)
|
|
1121
1124
|
])
|
|
1122
1125
|
|
|
1123
1126
|
for (const contentPath of contentPaths) {
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
// rather keep one file. Precedence (per-query, per-key): queries.yml > site.yml.
|
|
17
17
|
//
|
|
18
18
|
// ⛔ THE THREE JOBS `collections/<name>/` USED TO FUSE ARE NOW THREE THINGS.
|
|
19
|
-
// `
|
|
20
|
-
//
|
|
21
|
-
// LAST of those only.
|
|
19
|
+
// `records/{schema}/` holds the site's records (placing a file there is what makes
|
|
20
|
+
// it one), `records.yml` sorts them into folders, and a query asks for a set. This
|
|
21
|
+
// file resolves the LAST of those only.
|
|
22
22
|
//
|
|
23
23
|
// ⚠️ `collections.yml` and `site.yml::collections` are GONE, with no alias and no
|
|
24
24
|
// deprecation path — the model's §5 ruling, and there is nothing outside this
|
|
@@ -85,7 +85,7 @@ export function defaultSchema(name) {
|
|
|
85
85
|
// address nothing local can derive.
|
|
86
86
|
function normalizeQueryDecl(name, decl) {
|
|
87
87
|
// ⭐ THE STRING SHORTHAND NAMES THE SCHEMA, because that is what a file-based
|
|
88
|
-
// query actually needs — `
|
|
88
|
+
// query actually needs — `records/{schema}/` supplies the records, so there is
|
|
89
89
|
// no directory left to name. (It named a PATH while the pool was
|
|
90
90
|
// `collections/<name>/` and the same directory answered both questions.)
|
|
91
91
|
if (typeof decl === 'string') return { name, schema: decl }
|
|
@@ -165,7 +165,7 @@ export async function resolveQueriesConfig(siteRoot, opts = {}) {
|
|
|
165
165
|
if (decl.path && decl.url === undefined) {
|
|
166
166
|
console.warn(
|
|
167
167
|
`[uniweb] query "${decl.name}": \`path: ${decl.path}\` is ignored. A query names a ` +
|
|
168
|
-
`\`schema:\` and \`
|
|
168
|
+
`\`schema:\` and \`records/{schema}/\` supplies its records — there is no directory ` +
|
|
169
169
|
`for it to name. Move the files under the schema folder instead.`
|
|
170
170
|
)
|
|
171
171
|
}
|
|
@@ -234,6 +234,16 @@ export function refuseQueryDeclaration(decl) {
|
|
|
234
234
|
}
|
|
235
235
|
refuseQueryRoute(decl, where)
|
|
236
236
|
refuseLimit(decl.limit, where)
|
|
237
|
+
// ⛔ `sync:` IS RETIRED (2026-09-21). `sync: false` kept a query's records off a
|
|
238
|
+
// backend while a query owned its records; every record in `records/` is pushed
|
|
239
|
+
// now, whatever reads it, so an ignored `sync: false` would push exactly what the
|
|
240
|
+
// author meant to hold back. Refused, naming what does that now.
|
|
241
|
+
if (decl.sync !== undefined) {
|
|
242
|
+
throw new Error(
|
|
243
|
+
`[uniweb] ${where}: \`sync:\` is retired — a query does not own its records. Every file in ` +
|
|
244
|
+
`\`records/\` is a record and is pushed; a file whose name starts with \`_\` is not a record.`
|
|
245
|
+
)
|
|
246
|
+
}
|
|
237
247
|
const external = decl.url !== undefined
|
|
238
248
|
if (!external) {
|
|
239
249
|
for (const key of ['method', 'body', 'transform', 'record']) {
|