@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.
@@ -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 { ENTITIES_DIR } from './entity-pool.js'
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 entities are records, as an entity change decides what one says.
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 resolvedEntitiesDir = null // site.yml `paths.entities`, site-root-relative
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, resolvedEntitiesDir, basePath, {
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
- resolvedEntitiesDir = paths.entities || null
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
- resolvedEntitiesDir = paths.entities || null
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, resolvedEntitiesDir, basePath)
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. `entities/` is one
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, resolvedEntitiesDir || ENTITIES_DIR)
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
- // `entities/{schema}/` is the pool, `records.yml` is the folder (what makes an
20
- // entity a record), and a query asks the folder for a set. This file resolves the
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 — `entities/{schema}/` supplies the records, so there is
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 \`entities/{schema}/\` supplies its records — there is no directory ` +
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']) {