uniweb 0.89.1 → 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 -10
- package/partials/agents.md +29 -2
- 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 +51 -43
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,17 +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/
|
|
48
|
-
"@uniweb/content-writer": "^0.3.4",
|
|
49
|
-
"@uniweb/schemas": "^0.13.0"
|
|
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"
|
|
50
48
|
},
|
|
51
49
|
"peerDependencies": {
|
|
52
|
-
"@uniweb/
|
|
53
|
-
"@uniweb/build": "
|
|
54
|
-
"@uniweb/
|
|
50
|
+
"@uniweb/content-reader": "~1.2.8",
|
|
51
|
+
"@uniweb/build": "~0.80.4",
|
|
52
|
+
"@uniweb/semantic-parser": "~1.5.1"
|
|
55
53
|
},
|
|
56
54
|
"peerDependenciesMeta": {
|
|
57
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
|
|
|
@@ -2580,6 +2582,29 @@ takes them there already signed in. ⛔ **Navigate to it, never `fetch` it**: th
|
|
|
2580
2582
|
a redirect carrying a one-time credential no script on the site is to hold. It decides
|
|
2581
2583
|
what to offer, not what is allowed — on the site the operator acts as a member.
|
|
2582
2584
|
|
|
2585
|
+
### The links the backend mails
|
|
2586
|
+
|
|
2587
|
+
A sign-up's confirmation, a password reset and an invitation to an address with no
|
|
2588
|
+
account all arrive as a link to the site's root, a token in the query — `?verify=`,
|
|
2589
|
+
`?reset=`, `?offer=` — and the page it lands on finishes the step:
|
|
2590
|
+
|
|
2591
|
+
```jsx
|
|
2592
|
+
const { step, status, result, error, confirm } = useMailedLink()
|
|
2593
|
+
// step: null | 'verify' | 'reset' | 'offer' status: 'idle' | 'working' | 'done' | 'error'
|
|
2594
|
+
```
|
|
2595
|
+
|
|
2596
|
+
- `verify` finishes by itself; then the member signs in.
|
|
2597
|
+
- `reset` waits for `confirm({ new_password })`, and the hook supplies the token. A
|
|
2598
|
+
password the rule refuses is `error.extensions.reason === 'password_too_short'`, and
|
|
2599
|
+
the same link works again.
|
|
2600
|
+
- `offer` waits for a sign-in, then claims by itself. `result` is counts,
|
|
2601
|
+
`{ invitations, grants }`, never names. ⛔ `error.kind === 'absent'` means unknown,
|
|
2602
|
+
revoked or already used, alike: one sentence, no cause.
|
|
2603
|
+
|
|
2604
|
+
Render it where the root renders it — a header or a layout is on every page. ⛔ Never
|
|
2605
|
+
copy the token anywhere: it is a credential, it stays in the URL until the backend has
|
|
2606
|
+
judged it, and then the hook takes it off.
|
|
2607
|
+
|
|
2583
2608
|
### A backend on your machine
|
|
2584
2609
|
|
|
2585
2610
|
You do not need a live backend to build against one. In `site.yml`:
|
|
@@ -2601,7 +2626,9 @@ supplies on its own origin, so cookies behave exactly as they will in production
|
|
|
2601
2626
|
no address of your own for it: under `services:` an address means a backend you run, and
|
|
2602
2627
|
asks your host to leave its own off. It **enforces** who
|
|
2603
2628
|
may edit an entry and `append_only`, so a permission you are relying on fails on your
|
|
2604
|
-
machine rather than in front of a user.
|
|
2629
|
+
machine rather than in front of a user. The mail it would send is printed in the dev
|
|
2630
|
+
server's terminal, its link on your site's root — follow it to try your page; seed
|
|
2631
|
+
`offers: [{ email }]` to try an invitation. State is in memory; restart to reset.
|
|
2605
2632
|
|
|
2606
2633
|
`uniweb create my-event --template conference` is a worked example of all of this.
|
|
2607
2634
|
|
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.
|
|
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
|
@@ -9,26 +9,33 @@
|
|
|
9
9
|
*
|
|
10
10
|
* ## How versions are resolved
|
|
11
11
|
*
|
|
12
|
-
* 1. Start from the CLI's own `package.json` dependencies.
|
|
13
|
-
*
|
|
14
|
-
* spec
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* `
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
12
|
+
* 1. Start from the CLI's own `package.json` dependencies. A published CLI
|
|
13
|
+
* carries concrete ranges like `~0.9.1` there — pnpm rewrites each
|
|
14
|
+
* `workspace:~` spec at publish.
|
|
15
|
+
* 2. For any dep that is still a `workspace:` spec (the CLI is running
|
|
16
|
+
* *from* a workspace checkout — local dev, sandboxes, tests), read the
|
|
17
|
+
* `package.json` of the sibling package under `framework/<name>/` and
|
|
18
|
+
* use `~<that version>`: the range a published CLI would carry.
|
|
19
|
+
* 3. Scan `framework/*` for every other `@uniweb/*` package (press, loom,
|
|
20
|
+
* scholar, etc.), so a new package reaches the scaffolder automatically.
|
|
21
|
+
* 4. A published CLI has no `framework/` beside it: it reads every other
|
|
22
|
+
* package's version from its bundled `framework-index.json`, refreshed
|
|
23
|
+
* when the CLI is published.
|
|
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
|
+
*
|
|
31
|
+
* ⭐ A version is not a reason to depend on a package. Steps 3 and 4 name
|
|
32
|
+
* every `@uniweb/*` package, so the CLI's `dependencies` list only what its
|
|
33
|
+
* code loads — each one is installed with every `npx uniweb`.
|
|
34
|
+
*
|
|
35
|
+
* The previous implementation shipped a hardcoded fallback table that
|
|
36
|
+
* nothing kept in sync, so every scaffold silently pinned years-old
|
|
37
|
+
* versions. That table is gone. A package none of these steps resolves gets
|
|
38
|
+
* the `{{version}}` helper's `^0.1.0` (templates/processor.js).
|
|
32
39
|
*/
|
|
33
40
|
|
|
34
41
|
import { readFileSync, readdirSync, statSync } from 'node:fs'
|
|
@@ -198,16 +205,17 @@ function getFrameworkRoot() {
|
|
|
198
205
|
|
|
199
206
|
/**
|
|
200
207
|
* Read the current on-disk version of a specific `@uniweb/*` package by
|
|
201
|
-
* looking up `framework/<last-segment>/package.json
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
*
|
|
206
|
-
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
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
|
|
210
|
+
* running from npm, not from a workspace checkout).
|
|
211
|
+
*
|
|
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
|
|
214
|
+
* the scaffolder write the same `package.json` whether the CLI ran from npm
|
|
215
|
+
* or from a workspace. ⛔ This returned the version exact until 2026-10-11:
|
|
216
|
+
* right while the deps were `workspace:*`, which pnpm publishes exact, and
|
|
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`.
|
|
211
219
|
*/
|
|
212
220
|
function readWorkspaceVersion(packageName) {
|
|
213
221
|
const root = getFrameworkRoot()
|
|
@@ -219,7 +227,7 @@ function readWorkspaceVersion(packageName) {
|
|
|
219
227
|
try {
|
|
220
228
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
|
|
221
229
|
if (pkg.name === packageName && pkg.version) {
|
|
222
|
-
return pkg.version
|
|
230
|
+
return `~${pkg.version}`
|
|
223
231
|
}
|
|
224
232
|
} catch {}
|
|
225
233
|
return null
|
|
@@ -258,7 +266,7 @@ export function loadFrameworkIndex() {
|
|
|
258
266
|
|
|
259
267
|
/**
|
|
260
268
|
* Pull `@uniweb/*` package versions out of the framework index's
|
|
261
|
-
* `packages` field and format them as
|
|
269
|
+
* `packages` field and format them as tilde ranges. Used as the
|
|
262
270
|
* published-CLI fallback source after the CLI's own deps and the live
|
|
263
271
|
* workspace walk both come up empty.
|
|
264
272
|
*/
|
|
@@ -268,7 +276,7 @@ function readIndexPackages() {
|
|
|
268
276
|
const result = {}
|
|
269
277
|
for (const [name, entry] of Object.entries(index.packages)) {
|
|
270
278
|
if (entry && entry.version) {
|
|
271
|
-
result[name] =
|
|
279
|
+
result[name] = `~${entry.version}`
|
|
272
280
|
}
|
|
273
281
|
}
|
|
274
282
|
return result
|
|
@@ -301,7 +309,7 @@ function discoverWorkspacePackages() {
|
|
|
301
309
|
try {
|
|
302
310
|
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'))
|
|
303
311
|
if (pkg.name && pkg.version && pkg.name.startsWith('@uniweb/')) {
|
|
304
|
-
found[pkg.name] =
|
|
312
|
+
found[pkg.name] = `~${pkg.version}`
|
|
305
313
|
}
|
|
306
314
|
} catch {}
|
|
307
315
|
}
|
|
@@ -310,8 +318,8 @@ function discoverWorkspacePackages() {
|
|
|
310
318
|
|
|
311
319
|
/**
|
|
312
320
|
* Resolve a single version spec to something npm can install. A concrete
|
|
313
|
-
* spec like
|
|
314
|
-
*
|
|
321
|
+
* spec like `~0.9.0` passes through untouched; a `workspace:` spec becomes
|
|
322
|
+
* `~<on-disk version>` of the named package; anything still unresolved
|
|
315
323
|
* returns null so the caller can fall back.
|
|
316
324
|
*/
|
|
317
325
|
function resolveVersionSpec(spec, packageName) {
|
|
@@ -328,8 +336,8 @@ function resolveVersionSpec(spec, packageName) {
|
|
|
328
336
|
* Priority (highest first):
|
|
329
337
|
*
|
|
330
338
|
* 1. A concrete version spec already in the CLI's own `package.json`
|
|
331
|
-
* (the state after an npm publish: `workspace
|
|
332
|
-
*
|
|
339
|
+
* (the state after an npm publish: pnpm rewrites `workspace:~` to
|
|
340
|
+
* `~<version>`), or a `workspace:` spec read as `~<on-disk version>`.
|
|
333
341
|
* 2. Live workspace walk — every `@uniweb/*` package found under
|
|
334
342
|
* `framework/*` at CLI invocation time. This is the path that
|
|
335
343
|
* matters for local dev: a freshly-added package becomes
|
|
@@ -382,10 +390,10 @@ export function getResolvedVersions() {
|
|
|
382
390
|
if (!result[name]) result[name] = version
|
|
383
391
|
}
|
|
384
392
|
|
|
385
|
-
// CLI itself.
|
|
386
|
-
//
|
|
387
|
-
//
|
|
388
|
-
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}`
|
|
389
397
|
|
|
390
398
|
resolvedVersions = result
|
|
391
399
|
return resolvedVersions
|
|
@@ -395,7 +403,7 @@ export function getResolvedVersions() {
|
|
|
395
403
|
* Get a specific package version
|
|
396
404
|
*
|
|
397
405
|
* @param {string} packageName - Package name (e.g., "@uniweb/build")
|
|
398
|
-
* @returns {string} Version spec (e.g., "
|
|
406
|
+
* @returns {string} Version spec (e.g., "~0.1.4")
|
|
399
407
|
*/
|
|
400
408
|
export function getVersion(packageName) {
|
|
401
409
|
const versions = getResolvedVersions()
|