uniweb 0.89.2 → 0.89.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 +8 -8
- package/partials/agents.md +3 -1
- package/src/commands/update.js +4 -4
- package/src/framework-index.json +9 -9
- package/src/utils/dep-survey.js +8 -9
- package/src/versions.js +28 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniweb",
|
|
3
|
-
"version": "0.89.
|
|
3
|
+
"version": "0.89.3",
|
|
4
4
|
"description": "Create structured Vite + React sites with content/code separation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,15 +41,15 @@
|
|
|
41
41
|
"js-yaml": "^4.1.0",
|
|
42
42
|
"prompts": "^2.4.2",
|
|
43
43
|
"tar": "^7.0.0",
|
|
44
|
-
"@uniweb/
|
|
45
|
-
"@uniweb/
|
|
46
|
-
"@uniweb/
|
|
47
|
-
"@uniweb/
|
|
44
|
+
"@uniweb/content-writer": "~0.3.4",
|
|
45
|
+
"@uniweb/semantic-parser": "~1.5.1",
|
|
46
|
+
"@uniweb/schemas": "~0.13.0",
|
|
47
|
+
"@uniweb/core": "~0.38.2"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@uniweb/
|
|
51
|
-
"@uniweb/
|
|
52
|
-
"@uniweb/
|
|
50
|
+
"@uniweb/content-reader": "~1.2.8",
|
|
51
|
+
"@uniweb/build": "~0.80.4",
|
|
52
|
+
"@uniweb/semantic-parser": "~1.5.1"
|
|
53
53
|
},
|
|
54
54
|
"peerDependenciesMeta": {
|
|
55
55
|
"@uniweb/build": {
|
package/partials/agents.md
CHANGED
|
@@ -1016,6 +1016,8 @@ src/ # the foundation package (folder name is `src`)
|
|
|
1016
1016
|
|
|
1017
1017
|
**Discovery:** PascalCase files and folders at the root of `sections/` are auto-discovered. Nested levels require a `meta.js`. Lowercase directories are organizational only. `hidden: true` excludes a component entirely. Everything outside `sections/` and `layouts/` is ordinary React.
|
|
1018
1018
|
|
|
1019
|
+
**JSX goes in `.jsx` files** (or `.tsx`). Discovery also accepts a `.js` component, but only one without JSX: JSX compiles in no `.js` file, and the build stops on one, naming the file to rename.
|
|
1020
|
+
|
|
1019
1021
|
**Source root.** The foundation package's source lives at the package root — the `src/` folder *is* the foundation. The build reads `package.json::main` (for new scaffolds, `main: "./_entry.generated.js"`). Older foundations nest source in `foundation/src/` with `main` pointing at `./src/_entry.generated.js`; both work through the same code path.
|
|
1020
1022
|
|
|
1021
1023
|
**Import aliases.** Foundations include subpath imports for shared internals — use them instead of brittle relative paths:
|
|
@@ -1032,7 +1034,7 @@ import LessonHeader from '../../components/LessonHeader' // ❌ breaks if you re
|
|
|
1032
1034
|
|
|
1033
1035
|
Within the same directory, use normal relative imports (`./AIFeedbackCard`).
|
|
1034
1036
|
|
|
1035
|
-
**Foundation entry (`main.js`).** A single `export default { … }` whose top-level keys are the foundation's identity — `name` (what it registers as, `@org/<name>`) and `description` — and the capabilities it provides — `defaultLayout`, `defaultSection`, `viewTransitions`, `defaultInsets`, `xref`, `outputs`, `handlers` — plus an optional named `vars` export. The capabilities are read at render; the one thing a foundation declares that *isn't* — which host services it supports — lives in `package.json` instead (see [Declaring what your foundation supports](#declaring-what-your-foundation-supports)). Section types and layouts are auto-discovered and merged in by `@uniweb/build`. The build carries into `default.capabilities` in `dist/entry.js` only what a published page reads of your default export — the code it calls (`handlers`, `defaultInsets`, `xref`, `transports`, `outputs`) and its data, lean (`defaultLayout`, `defaultSection`, `viewTransitions`, `scroll`, each var's `default`, `type` and `applyTo`, each `data:` key's schema ref). `name`, `description`, a var's label or description and any key the framework does not read stay out of the published bundle: they are for the editor, which reads them from the foundation's schema. You never write that wrapper. The file is `main.js` — never `main.jsx`, which the build refuses
|
|
1037
|
+
**Foundation entry (`main.js`).** A single `export default { … }` whose top-level keys are the foundation's identity — `name` (what it registers as, `@org/<name>`) and `description` — and the capabilities it provides — `defaultLayout`, `defaultSection`, `viewTransitions`, `defaultInsets`, `xref`, `outputs`, `handlers` — plus an optional named `vars` export. The capabilities are read at render; the one thing a foundation declares that *isn't* — which host services it supports — lives in `package.json` instead (see [Declaring what your foundation supports](#declaring-what-your-foundation-supports)). Section types and layouts are auto-discovered and merged in by `@uniweb/build`. The build carries into `default.capabilities` in `dist/entry.js` only what a published page reads of your default export — the code it calls (`handlers`, `defaultInsets`, `xref`, `transports`, `outputs`) and its data, lean (`defaultLayout`, `defaultSection`, `viewTransitions`, `scroll`, each var's `default`, `type` and `applyTo`, each `data:` key's schema ref). `name`, `description`, a var's label or description and any key the framework does not read stay out of the published bundle: they are for the editor, which reads them from the foundation's schema. You never write that wrapper. The file is `main.js` — never `main.jsx`, which the build refuses — and it is plain JavaScript: a component it declares (in `defaultInsets`, `xref`) lives in a `.jsx` file it imports. The one place it matters: when you import your **own** `main.js` from a component (e.g. a download button calling `compileDocument(website, { foundation })`), you get the bare default object — pass it through directly, Press handles both shapes.
|
|
1036
1038
|
|
|
1037
1039
|
### Props interface
|
|
1038
1040
|
|
package/src/commands/update.js
CHANGED
|
@@ -260,8 +260,8 @@ export function printSurvey(
|
|
|
260
260
|
} else if (row.status === 'behind') {
|
|
261
261
|
icon = `${colors.yellow}✗${colors.reset}`
|
|
262
262
|
// ⛔ `behind` alone was the whole message, in one colour, for every
|
|
263
|
-
// distance.
|
|
264
|
-
// (`publish.js` derives it from a breaking marker and nothing else), so
|
|
263
|
+
// distance. The minor slot is where our breaking changes live, in 1.x as in
|
|
264
|
+
// 0.x (`publish.js` derives it from a breaking marker and nothing else), so
|
|
265
265
|
// `^0.14.1 → ^0.16.0` is two releases a consumer must act on and
|
|
266
266
|
// `^0.15.0 → ^0.15.2` is not — and the table said the same thing about
|
|
267
267
|
// both. Naming the class is the difference between a list and a signal.
|
|
@@ -289,7 +289,7 @@ export function printSurvey(
|
|
|
289
289
|
// artifact is a log. This block names the packages, so "what did that
|
|
290
290
|
// upgrade cross?" is answerable afterwards from the log alone.
|
|
291
291
|
//
|
|
292
|
-
// ⚖️ It reports; it does not gate. Crossing a
|
|
292
|
+
// ⚖️ It reports; it does not gate. Crossing a minor IS the ordinary way
|
|
293
293
|
// to take a Uniweb update — gating it would gate nearly every real upgrade
|
|
294
294
|
// and make the verb useless. The decision stays the operator's; what changed
|
|
295
295
|
// is that they can now make it knowingly.
|
|
@@ -305,7 +305,7 @@ export function printSurvey(
|
|
|
305
305
|
log(` ${colors.red}${name}${colors.reset} ${r.current} → ${r.target} ${colors.dim}(${r.bump})${colors.reset}`)
|
|
306
306
|
}
|
|
307
307
|
log(
|
|
308
|
-
` ${colors.dim}
|
|
308
|
+
` ${colors.dim}A minor version is where Uniweb's breaking changes go, so these are releases${colors.reset}`
|
|
309
309
|
)
|
|
310
310
|
log(
|
|
311
311
|
` ${colors.dim}you may need to act on. Read their changelogs before shipping.${colors.reset}`
|
package/src/framework-index.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-11T19:38:43.125Z",
|
|
4
4
|
"packages": {
|
|
5
5
|
"@uniweb/api": {
|
|
6
|
-
"version": "0.9.
|
|
6
|
+
"version": "0.9.1"
|
|
7
7
|
},
|
|
8
8
|
"@uniweb/build": {
|
|
9
|
-
"version": "0.80.
|
|
9
|
+
"version": "0.80.4"
|
|
10
10
|
},
|
|
11
11
|
"@uniweb/content-reader": {
|
|
12
12
|
"version": "1.2.8"
|
|
@@ -15,16 +15,16 @@
|
|
|
15
15
|
"version": "0.3.4"
|
|
16
16
|
},
|
|
17
17
|
"@uniweb/core": {
|
|
18
|
-
"version": "0.38.
|
|
18
|
+
"version": "0.38.2"
|
|
19
19
|
},
|
|
20
20
|
"@uniweb/frame-bridge": {
|
|
21
21
|
"version": "0.3.2"
|
|
22
22
|
},
|
|
23
23
|
"@uniweb/icons": {
|
|
24
|
-
"version": "0.4.
|
|
24
|
+
"version": "0.4.30"
|
|
25
25
|
},
|
|
26
26
|
"@uniweb/kit": {
|
|
27
|
-
"version": "0.20.
|
|
27
|
+
"version": "0.20.1"
|
|
28
28
|
},
|
|
29
29
|
"@uniweb/loom": {
|
|
30
30
|
"version": "0.2.5"
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"version": "0.4.18"
|
|
34
34
|
},
|
|
35
35
|
"@uniweb/projections": {
|
|
36
|
-
"version": "0.7.
|
|
36
|
+
"version": "0.7.16"
|
|
37
37
|
},
|
|
38
38
|
"@uniweb/runtime": {
|
|
39
|
-
"version": "0.29.
|
|
39
|
+
"version": "0.29.7"
|
|
40
40
|
},
|
|
41
41
|
"@uniweb/scene": {
|
|
42
42
|
"version": "0.1.3"
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"version": "0.2.0"
|
|
61
61
|
},
|
|
62
62
|
"@uniweb/unipress": {
|
|
63
|
-
"version": "0.10.
|
|
63
|
+
"version": "0.10.25"
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
"templates": {
|
package/src/utils/dep-survey.js
CHANGED
|
@@ -36,8 +36,8 @@ export function stripVersionRange(spec) {
|
|
|
36
36
|
/**
|
|
37
37
|
* How far a bump moves, in the terms our versioning actually uses.
|
|
38
38
|
*
|
|
39
|
-
* ⭐ **
|
|
40
|
-
*
|
|
39
|
+
* ⭐ **The MINOR slot is the breaking one — in 1.x as in 0.x** *[ruled
|
|
40
|
+
* 2026-10-11]*. `scripts/framework/publish.js` derives a package's bump from its own
|
|
41
41
|
* commits: a breaking marker means minor, everything else patch. So
|
|
42
42
|
* `^0.14.1 → ^0.16.0` is two breaking releases and `^0.15.0 → ^0.15.2` is not —
|
|
43
43
|
* and until 2026-09-02 `update` printed both as `behind`, in the same colour,
|
|
@@ -64,10 +64,11 @@ export function bumpClass(from, to) {
|
|
|
64
64
|
/**
|
|
65
65
|
* Is this crossing one a consumer must act on?
|
|
66
66
|
*
|
|
67
|
-
* A major
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* refuses
|
|
67
|
+
* A major, or a minor — at every major. Our scheme ships a breaking change as a minor
|
|
68
|
+
* bump, in 1.x as in 0.x *[ruled 2026-10-11]*, and the ranges a project carries (`~`)
|
|
69
|
+
* treat the minor slot as the wall: `~1.4.0` admits 1.4.x and refuses 1.5.0, as
|
|
70
|
+
* `^0.14.1` refuses 0.15.0. ⛔ Until then a minor counted only below 1.0, where a caret
|
|
71
|
+
* refuses it — so this would have stopped warning at the first 1.x minor.
|
|
71
72
|
*
|
|
72
73
|
* @param {string} from
|
|
73
74
|
* @param {string} to
|
|
@@ -75,9 +76,7 @@ export function bumpClass(from, to) {
|
|
|
75
76
|
*/
|
|
76
77
|
export function isBreakingBump(from, to) {
|
|
77
78
|
const cls = bumpClass(from, to)
|
|
78
|
-
|
|
79
|
-
if (cls !== 'minor') return false
|
|
80
|
-
return Number(stripVersionRange(to).split('.')[0]) === 0
|
|
79
|
+
return cls === 'major' || cls === 'minor'
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
/**
|
package/src/versions.js
CHANGED
|
@@ -10,18 +10,24 @@
|
|
|
10
10
|
* ## How versions are resolved
|
|
11
11
|
*
|
|
12
12
|
* 1. Start from the CLI's own `package.json` dependencies. A published CLI
|
|
13
|
-
* carries concrete ranges like
|
|
14
|
-
* `workspace
|
|
13
|
+
* carries concrete ranges like `~0.9.1` there — pnpm rewrites each
|
|
14
|
+
* `workspace:~` spec at publish.
|
|
15
15
|
* 2. For any dep that is still a `workspace:` spec (the CLI is running
|
|
16
16
|
* *from* a workspace checkout — local dev, sandboxes, tests), read the
|
|
17
17
|
* `package.json` of the sibling package under `framework/<name>/` and
|
|
18
|
-
* use
|
|
18
|
+
* use `~<that version>`: the range a published CLI would carry.
|
|
19
19
|
* 3. Scan `framework/*` for every other `@uniweb/*` package (press, loom,
|
|
20
20
|
* scholar, etc.), so a new package reaches the scaffolder automatically.
|
|
21
21
|
* 4. A published CLI has no `framework/` beside it: it reads every other
|
|
22
22
|
* package's version from its bundled `framework-index.json`, refreshed
|
|
23
23
|
* when the CLI is published.
|
|
24
24
|
*
|
|
25
|
+
* ⭐ EVERY RANGE IS A TILDE. A breaking change ships as a minor bump, in 1.x as in
|
|
26
|
+
* 0.x *[ruled 2026-10-11]*, and `~1.4.0` admits 1.4.x alone, where `^1.4.0` would
|
|
27
|
+
* admit 1.5.0. So a project receives fixes and features (patches) by itself, and a
|
|
28
|
+
* breaking release through `uniweb update`, which says so. Below 1.0 a caret meant
|
|
29
|
+
* the same, which is why the table wrote one until then.
|
|
30
|
+
*
|
|
25
31
|
* ⭐ A version is not a reason to depend on a package. Steps 3 and 4 name
|
|
26
32
|
* every `@uniweb/*` package, so the CLI's `dependencies` list only what its
|
|
27
33
|
* code loads — each one is installed with every `npx uniweb`.
|
|
@@ -199,17 +205,17 @@ function getFrameworkRoot() {
|
|
|
199
205
|
|
|
200
206
|
/**
|
|
201
207
|
* Read the current on-disk version of a specific `@uniweb/*` package by
|
|
202
|
-
* looking up `framework/<last-segment>/package.json`, as a
|
|
203
|
-
* (e.g.
|
|
208
|
+
* looking up `framework/<last-segment>/package.json`, as a tilde range
|
|
209
|
+
* (e.g. `~0.7.11`) — or null if the package isn't on disk (the CLI is
|
|
204
210
|
* running from npm, not from a workspace checkout).
|
|
205
211
|
*
|
|
206
|
-
* ⭐ A
|
|
207
|
-
* its `workspace
|
|
212
|
+
* ⭐ A tilde, because that is what a published CLI carries: pnpm rewrites
|
|
213
|
+
* its `workspace:~` deps to `~<version>` at publish. So `uniweb update` and
|
|
208
214
|
* the scaffolder write the same `package.json` whether the CLI ran from npm
|
|
209
215
|
* or from a workspace. ⛔ This returned the version exact until 2026-10-11:
|
|
210
216
|
* right while the deps were `workspace:*`, which pnpm publishes exact, and
|
|
211
|
-
* wrong once they became
|
|
212
|
-
*
|
|
217
|
+
* wrong once they became a range — a scaffold from a workspace checkout
|
|
218
|
+
* pinned `0.20.0` where a user's got `^0.20.0`.
|
|
213
219
|
*/
|
|
214
220
|
function readWorkspaceVersion(packageName) {
|
|
215
221
|
const root = getFrameworkRoot()
|
|
@@ -221,7 +227,7 @@ function readWorkspaceVersion(packageName) {
|
|
|
221
227
|
try {
|
|
222
228
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
|
|
223
229
|
if (pkg.name === packageName && pkg.version) {
|
|
224
|
-
return
|
|
230
|
+
return `~${pkg.version}`
|
|
225
231
|
}
|
|
226
232
|
} catch {}
|
|
227
233
|
return null
|
|
@@ -260,7 +266,7 @@ export function loadFrameworkIndex() {
|
|
|
260
266
|
|
|
261
267
|
/**
|
|
262
268
|
* Pull `@uniweb/*` package versions out of the framework index's
|
|
263
|
-
* `packages` field and format them as
|
|
269
|
+
* `packages` field and format them as tilde ranges. Used as the
|
|
264
270
|
* published-CLI fallback source after the CLI's own deps and the live
|
|
265
271
|
* workspace walk both come up empty.
|
|
266
272
|
*/
|
|
@@ -270,7 +276,7 @@ function readIndexPackages() {
|
|
|
270
276
|
const result = {}
|
|
271
277
|
for (const [name, entry] of Object.entries(index.packages)) {
|
|
272
278
|
if (entry && entry.version) {
|
|
273
|
-
result[name] =
|
|
279
|
+
result[name] = `~${entry.version}`
|
|
274
280
|
}
|
|
275
281
|
}
|
|
276
282
|
return result
|
|
@@ -303,7 +309,7 @@ function discoverWorkspacePackages() {
|
|
|
303
309
|
try {
|
|
304
310
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
|
|
305
311
|
if (pkg.name && pkg.version && pkg.name.startsWith('@uniweb/')) {
|
|
306
|
-
found[pkg.name] =
|
|
312
|
+
found[pkg.name] = `~${pkg.version}`
|
|
307
313
|
}
|
|
308
314
|
} catch {}
|
|
309
315
|
}
|
|
@@ -312,8 +318,8 @@ function discoverWorkspacePackages() {
|
|
|
312
318
|
|
|
313
319
|
/**
|
|
314
320
|
* Resolve a single version spec to something npm can install. A concrete
|
|
315
|
-
* spec like
|
|
316
|
-
*
|
|
321
|
+
* spec like `~0.9.0` passes through untouched; a `workspace:` spec becomes
|
|
322
|
+
* `~<on-disk version>` of the named package; anything still unresolved
|
|
317
323
|
* returns null so the caller can fall back.
|
|
318
324
|
*/
|
|
319
325
|
function resolveVersionSpec(spec, packageName) {
|
|
@@ -330,8 +336,8 @@ function resolveVersionSpec(spec, packageName) {
|
|
|
330
336
|
* Priority (highest first):
|
|
331
337
|
*
|
|
332
338
|
* 1. A concrete version spec already in the CLI's own `package.json`
|
|
333
|
-
* (the state after an npm publish: pnpm rewrites `workspace
|
|
334
|
-
*
|
|
339
|
+
* (the state after an npm publish: pnpm rewrites `workspace:~` to
|
|
340
|
+
* `~<version>`), or a `workspace:` spec read as `~<on-disk version>`.
|
|
335
341
|
* 2. Live workspace walk — every `@uniweb/*` package found under
|
|
336
342
|
* `framework/*` at CLI invocation time. This is the path that
|
|
337
343
|
* matters for local dev: a freshly-added package becomes
|
|
@@ -384,10 +390,10 @@ export function getResolvedVersions() {
|
|
|
384
390
|
if (!result[name]) result[name] = version
|
|
385
391
|
}
|
|
386
392
|
|
|
387
|
-
// CLI itself.
|
|
388
|
-
//
|
|
389
|
-
//
|
|
390
|
-
result['uniweb'] =
|
|
393
|
+
// CLI itself. Tilde on the current version, like every other entry: a
|
|
394
|
+
// project takes the CLI's patches by itself, and a minor — breaking —
|
|
395
|
+
// through `uniweb update`.
|
|
396
|
+
result['uniweb'] = `~${pkg.version}`
|
|
391
397
|
|
|
392
398
|
resolvedVersions = result
|
|
393
399
|
return resolvedVersions
|
|
@@ -397,7 +403,7 @@ export function getResolvedVersions() {
|
|
|
397
403
|
* Get a specific package version
|
|
398
404
|
*
|
|
399
405
|
* @param {string} packageName - Package name (e.g., "@uniweb/build")
|
|
400
|
-
* @returns {string} Version spec (e.g., "
|
|
406
|
+
* @returns {string} Version spec (e.g., "~0.1.4")
|
|
401
407
|
*/
|
|
402
408
|
export function getVersion(packageName) {
|
|
403
409
|
const versions = getResolvedVersions()
|