@uniweb/build 0.24.1 → 0.24.3
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/build",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.3",
|
|
4
4
|
"description": "Build tooling for the Uniweb Component Web Platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -59,17 +59,17 @@
|
|
|
59
59
|
"js-yaml": "^4.1.0",
|
|
60
60
|
"sharp": "^0.35.3",
|
|
61
61
|
"yaml": "^2.5.0",
|
|
62
|
-
"@uniweb/theming": "^0.1.15",
|
|
63
|
-
"@uniweb/projections": "^0.3.3",
|
|
64
|
-
"@uniweb/semantic-parser": "^1.2.3",
|
|
65
62
|
"@uniweb/schemas": "^0.2.10",
|
|
66
|
-
"@uniweb/
|
|
63
|
+
"@uniweb/semantic-parser": "^1.2.3",
|
|
64
|
+
"@uniweb/theming": "^0.1.15",
|
|
65
|
+
"@uniweb/content-writer": "^0.3.3",
|
|
66
|
+
"@uniweb/projections": "^0.3.3"
|
|
67
67
|
},
|
|
68
68
|
"optionalDependencies": {
|
|
69
|
-
"@uniweb/
|
|
70
|
-
"@uniweb/runtime": "^0.12.1",
|
|
69
|
+
"@uniweb/schemas": "^0.2.10",
|
|
71
70
|
"@uniweb/semantic-parser": "^1.2.3",
|
|
72
|
-
"@uniweb/
|
|
71
|
+
"@uniweb/runtime": "^0.12.2",
|
|
72
|
+
"@uniweb/content-reader": "^1.2.3"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
75
|
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0",
|
|
@@ -126,8 +126,9 @@ export async function buildSiteData({
|
|
|
126
126
|
// in the vite plugin path that's fine because vite copies
|
|
127
127
|
// `public/` into `dist/` at build time. The link-mode pipeline
|
|
128
128
|
// has no vite, so we mirror that copy ourselves into
|
|
129
|
-
// `<distDir>/data/` — the
|
|
130
|
-
//
|
|
129
|
+
// `<distDir>/data/` — the set the CLI's `site-data-upload` lane walks at
|
|
130
|
+
// publish time. (This named `uniweb deploy::collectDataFiles` until
|
|
131
|
+
// 2026-08-18; no such function has existed for some time.) Same output bytes, same paths, just
|
|
131
132
|
// without the vite intermediary.
|
|
132
133
|
if (siteContent.config?.collections) {
|
|
133
134
|
const collectionsBase = siteContent.config?.paths?.collections
|
package/src/site/index.js
CHANGED
|
@@ -42,7 +42,7 @@ export {
|
|
|
42
42
|
writeCollectionFiles,
|
|
43
43
|
getCollectionLastModified
|
|
44
44
|
} from './collection-processor.js'
|
|
45
|
-
export {
|
|
45
|
+
export { collectSchemalessData, collectSchemalessDataAssets, rewriteSchemalessDataAssets } from './schemaless-data.js'
|
|
46
46
|
export {
|
|
47
47
|
parseFetchConfig,
|
|
48
48
|
executeFetch,
|
|
@@ -1,19 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* collections partition by schema presence: a collection that resolves a data schema
|
|
4
|
-
* syncs as folder entities; a SCHEMA-LESS collection has no entity model, so its built
|
|
5
|
-
* `dist/data/<name>.json` (cascade + any `deferred:` per-record files) is delivered
|
|
6
|
-
* statically. This bundles that schema-less subset of `dist/data/**` into one JSON doc
|
|
7
|
-
* the deploy uploads as a single content-addressed asset; the backend unwraps it into
|
|
8
|
-
* the `/data/*` bytes the gateway serves.
|
|
2
|
+
* Schema-less collection data — the set, and its local media.
|
|
9
3
|
*
|
|
10
|
-
*
|
|
4
|
+
* ⭐ **The name carries the scope on purpose.** This is NOT "the site's static
|
|
5
|
+
* data" in general. A site's collections partition by **schema presence**: one
|
|
6
|
+
* that resolves a data schema syncs as folder entities — content a backend
|
|
7
|
+
* genuinely consumes, queryable, editable, with a `brief:` for its lean shape.
|
|
8
|
+
* A **schema-less** collection has no entity model, so its compiled
|
|
9
|
+
* `dist/data/<name>.json` (plus any `deferred:` per-record files) is delivered
|
|
10
|
+
* as files instead. That fallback tier is all this module is about.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* { data: { "<relpath under dist/data>": <json> } } // schema-less only
|
|
13
|
+
*
|
|
14
|
+
* ⇒ It is an **in-memory enumeration**, not an artifact. `collectSchemalessData`
|
|
15
|
+
* gathers the set; the CLI's `site-data-upload` lane PUTs each file to the
|
|
16
|
+
* target the backend returns, landing at its serving tail.
|
|
17
|
+
*
|
|
18
|
+
* ## ⛔ It used to be a "data ball", and that is retired (2026-08-18)
|
|
19
|
+
*
|
|
20
|
+
* This merged the whole set into ONE uploaded asset that the backend then had
|
|
21
|
+
* to fetch, parse and fan out. It was the **only aggregate the CLI produced** —
|
|
22
|
+
* media, foundation code and the runtime all upload one object per file — and
|
|
23
|
+
* the only place these bytes ever transited the backend. Nothing in the code or
|
|
24
|
+
* the docs ever justified the bundling.
|
|
25
|
+
*
|
|
26
|
+
* ⇒ **Do not reintroduce a bundle here.** One object per file is what the
|
|
27
|
+
* reader's static arm already assumes: a plain object GET on the verbatim tail,
|
|
28
|
+
* with nothing anywhere that unbundles. Full account, including the endpoint
|
|
29
|
+
* contract: `kb/framework/build/data-ball-retirement.md`.
|
|
30
|
+
*
|
|
31
|
+
* **A search index used to ride here too, and deliberately no longer does**
|
|
32
|
+
* (2026-08-01). Only a CLI deploy produced one — a CMS publish produced none —
|
|
33
|
+
* so a site's search existed or vanished depending on who published it, which
|
|
34
|
+
* is the artifact-flicker rule exactly. A host that wants search derives it from
|
|
35
|
+
* the content it already stores. See the note at the removal point below and
|
|
36
|
+
* `collab/context/site-derived-artifacts.md`.
|
|
17
37
|
*/
|
|
18
38
|
|
|
19
39
|
import { existsSync } from 'node:fs'
|
|
@@ -56,7 +76,7 @@ function collectionOf(relPath) {
|
|
|
56
76
|
* `emitSyncPackages(...).schemaless`); only these contribute `data`.
|
|
57
77
|
* @returns {Promise<{ data: Object }|null>} null when there is nothing to deliver.
|
|
58
78
|
*/
|
|
59
|
-
export async function
|
|
79
|
+
export async function collectSchemalessData(distDir, schemalessNames = []) {
|
|
60
80
|
const schemaless = new Set(schemalessNames)
|
|
61
81
|
const allData = await readJsonTree(join(distDir, DATA_DIR))
|
|
62
82
|
const data = {}
|
|
@@ -128,7 +148,7 @@ export async function assembleDataBall(distDir, schemalessNames = []) {
|
|
|
128
148
|
* @param {{data:object}|null} ball
|
|
129
149
|
* @returns {string[]} deduped refs to upload
|
|
130
150
|
*/
|
|
131
|
-
export function
|
|
151
|
+
export function collectSchemalessDataAssets(ball) {
|
|
132
152
|
const refs = new Set()
|
|
133
153
|
const walk = (n) => {
|
|
134
154
|
if (typeof n === 'string') {
|
|
@@ -150,7 +170,7 @@ export function collectBallAssets(ball) {
|
|
|
150
170
|
* @param {Record<string,string>} map - ref → serve URL
|
|
151
171
|
* @returns {{data:object}|null} a new ball, or the input when there's nothing to do
|
|
152
172
|
*/
|
|
153
|
-
export function
|
|
173
|
+
export function rewriteSchemalessDataAssets(ball, map) {
|
|
154
174
|
if (!ball || !map || Object.keys(map).length === 0) return ball
|
|
155
175
|
const walk = (n) => {
|
|
156
176
|
if (typeof n === 'string') return map[n] || n
|
package/src/uwx/collections.js
CHANGED
|
@@ -493,10 +493,16 @@ export async function buildCollectionEntities(siteRoot, opts = {}) {
|
|
|
493
493
|
// soft skip — the collection is delivery-only, not a sync target. Only an
|
|
494
494
|
// EXPLICIT schema/model the author asked for is a hard error.
|
|
495
495
|
if (!decl.schemaExplicit) {
|
|
496
|
-
warnings.
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
496
|
+
// ⛔ Deliberately NOT a `warnings` string. This is a product decision the
|
|
497
|
+
// author is making — entities or static files — and it needs to be
|
|
498
|
+
// reported at a prominence a prose warning cannot carry. Callers get the
|
|
499
|
+
// structured entry and say it themselves (`cli/src/commands/{publish,push}.js`).
|
|
500
|
+
//
|
|
501
|
+
// It used to push `"… — not synced"`, printed dim among everything else.
|
|
502
|
+
// That was misleading in the expensive direction: the data IS delivered,
|
|
503
|
+
// as static files. An author read "not synced" as "my data did not
|
|
504
|
+
// upload" — or skimmed it — and either way could not act on it.
|
|
505
|
+
schemaless.push({ name, model: modelName })
|
|
500
506
|
continue
|
|
501
507
|
}
|
|
502
508
|
throw new Error(
|
package/src/uwx/sync-package.js
CHANGED
|
@@ -121,9 +121,33 @@ function walkEntityAssets(node, visitor) {
|
|
|
121
121
|
// - **the id is what survives.** A URL is a host's route layout frozen into
|
|
122
122
|
// content that outlives it; an id is re-resolved on every render, so a host
|
|
123
123
|
// that moves its assets costs a config edit rather than a migration.
|
|
124
|
-
// - **the URL is what RENDERS today.**
|
|
125
|
-
//
|
|
126
|
-
//
|
|
124
|
+
// - **the URL is what RENDERS today.** With the URL still there, a resolver
|
|
125
|
+
// that cannot resolve the id falls through and renders exactly as before.
|
|
126
|
+
//
|
|
127
|
+
// ⚠️ **This bullet used to justify itself with "no deployment emits
|
|
128
|
+
// `config.assets.url` yet". FALSIFIED 2026-08-18** by the backend lane:
|
|
129
|
+
// `serve` publishes the pattern **unconditionally**, falling back to the
|
|
130
|
+
// direct form, so a deployment with no asset storage emits the honest
|
|
131
|
+
// `/gateway/asset/dist/{id}/base.{ext}` rather than nothing (measured by
|
|
132
|
+
// them on a running daemon, not read off a type). ⛔ Scoped to deployments
|
|
133
|
+
// running code from 2026-08-17 or later; an older one emits nothing, and
|
|
134
|
+
// absent stays absent. A present-tense negative about someone else's
|
|
135
|
+
// deployments is the claim nothing in this repo can ever contradict — it
|
|
136
|
+
// was true when written, and nothing here changed when it stopped being.
|
|
137
|
+
//
|
|
138
|
+
// ⛔ **That does NOT license dropping the URL, and the reason is not
|
|
139
|
+
// coverage.** An earlier version of this note named coverage as the
|
|
140
|
+
// governor; it was only ever a gate. Dropping the `src` companion was
|
|
141
|
+
// **withdrawn as a goal** on 2026-08-17 on CONSUMER grounds: the editor
|
|
142
|
+
// canvas renders `attrs.url || attrs.src` and reads `assetId` nowhere, so
|
|
143
|
+
// an id-only node shows an `<img>` with no source *(measured by the
|
|
144
|
+
// frontend lane — their surface, their finding)*. Durability comes from
|
|
145
|
+
// every consumer PREFERRING the id, which each can do on its own schedule;
|
|
146
|
+
// dropping `src` only forces that at the cost of a migration window across
|
|
147
|
+
// two consumer chains where images blank.
|
|
148
|
+
//
|
|
149
|
+
// ⇒ **Keep writing both.** See `kb/framework/content/asset-url-resolution.md`
|
|
150
|
+
// item 13 — and re-read it there rather than re-deriving the answer here.
|
|
127
151
|
//
|
|
128
152
|
// ⇒ Writing both means content authored now stays correct whichever order the
|
|
129
153
|
// halves arrive in — the same reason the app writes both. The URL is dropped
|
|
@@ -213,7 +237,7 @@ function rewriteEntityAssets(node, map, ids) {
|
|
|
213
237
|
* siteContent: { buffer, entityCount, index, models }|null,
|
|
214
238
|
* collections: { buffer, entityCount, index, models }|null,
|
|
215
239
|
* hashes: Object<string,string>, warnings: string[], skipped: number,
|
|
216
|
-
* schemaless: Array<{name: string}>, localAssets: string[] }>}
|
|
240
|
+
* schemaless: Array<{name: string, model: string}>, localAssets: string[] }>}
|
|
217
241
|
* `schemaless` lists collections that resolved no data schema (soft-skipped from
|
|
218
242
|
* the sync) — the composite deploy delivers these statically via the data ball.
|
|
219
243
|
* `localAssets` lists the site-root local media refs (`/images/x.png`) the deploy
|