uniweb 0.12.52 → 0.12.54
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/commands/add.js +33 -16
- package/src/framework-index.json +8 -8
- package/src/utils/pm.js +43 -1
- package/src/versions.js +24 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniweb",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.54",
|
|
4
4
|
"description": "Create structured Vite + React sites with content/code separation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"js-yaml": "^4.1.0",
|
|
42
42
|
"prompts": "^2.4.2",
|
|
43
43
|
"tar": "^7.0.0",
|
|
44
|
-
"@uniweb/core": "0.7.
|
|
45
|
-
"@uniweb/
|
|
46
|
-
"@uniweb/
|
|
44
|
+
"@uniweb/core": "0.7.22",
|
|
45
|
+
"@uniweb/kit": "0.9.28",
|
|
46
|
+
"@uniweb/runtime": "0.8.28"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@uniweb/build": "0.14.
|
|
50
|
-
"@uniweb/content-reader": "1.1.
|
|
51
|
-
"@uniweb/semantic-parser": "1.1.
|
|
49
|
+
"@uniweb/build": "0.14.35",
|
|
50
|
+
"@uniweb/content-reader": "1.1.13",
|
|
51
|
+
"@uniweb/semantic-parser": "1.1.18"
|
|
52
52
|
},
|
|
53
53
|
"peerDependenciesMeta": {
|
|
54
54
|
"@uniweb/build": {
|
package/src/commands/add.js
CHANGED
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
import { discoverFoundations, discoverSites } from '../utils/discover.js'
|
|
28
28
|
import { validatePackageName, getExistingPackageNames, resolveUniqueName } from '../utils/names.js'
|
|
29
29
|
import { findWorkspaceRoot } from '../utils/workspace.js'
|
|
30
|
-
import { detectPackageManager, detectWorkspacePm, filterCmd, installCmd } from '../utils/pm.js'
|
|
30
|
+
import { detectPackageManager, detectWorkspacePm, detectInstalledPnpmVersion, filterCmd, installCmd } from '../utils/pm.js'
|
|
31
31
|
import { isNonInteractive, getCliPrefix, stripNonInteractiveFlag, formatOptions } from '../utils/interactive.js'
|
|
32
32
|
import { resolveTemplate } from '../templates/index.js'
|
|
33
33
|
import { validateTemplate } from '../templates/validator.js'
|
|
@@ -1156,9 +1156,13 @@ async function addCi(rootDir, opts, pm = 'pnpm') {
|
|
|
1156
1156
|
// CI must run the project's own toolchain. The pnpm major comes from
|
|
1157
1157
|
// its `packageManager` field when declared; the node major is the
|
|
1158
1158
|
// project's floor, raised if that pnpm needs more.
|
|
1159
|
-
const
|
|
1159
|
+
const installedPnpm = detectInstalledPnpmVersion(rootDir)
|
|
1160
|
+
const pnpmVersion = resolveCiPnpmVersion(rootPkg, installedPnpm)
|
|
1160
1161
|
const nodeVersion = resolveCiNodeVersion(rootPkg.engines?.node, pm, pnpmVersion)
|
|
1161
|
-
reportCiToolchain({
|
|
1162
|
+
reportCiToolchain({
|
|
1163
|
+
pm, pnpmVersion, nodeVersion,
|
|
1164
|
+
source: rootPkg?.packageManager ? 'declared' : installedPnpm ? 'installed' : 'fallback',
|
|
1165
|
+
})
|
|
1162
1166
|
|
|
1163
1167
|
const siteDir = join(rootDir, site.path)
|
|
1164
1168
|
if (!resolvedDomain) {
|
|
@@ -1284,19 +1288,28 @@ function stripScope(name) {
|
|
|
1284
1288
|
}
|
|
1285
1289
|
|
|
1286
1290
|
/**
|
|
1287
|
-
* Print the toolchain the generated workflow will install
|
|
1291
|
+
* Print the toolchain the generated workflow will install, and where each
|
|
1292
|
+
* part came from.
|
|
1288
1293
|
*
|
|
1289
|
-
* These
|
|
1290
|
-
* silent
|
|
1291
|
-
* unnoticed.
|
|
1292
|
-
*
|
|
1294
|
+
* These values are resolved rather than stated whenever the project is
|
|
1295
|
+
* silent, and a silent resolution is what let a broken pnpm/Node pairing
|
|
1296
|
+
* ship unnoticed. Naming the source matters too: "we read this from your
|
|
1297
|
+
* install" invites a different reaction than "we guessed", and only the
|
|
1298
|
+
* latter needs an override hint.
|
|
1293
1299
|
*/
|
|
1294
|
-
function reportCiToolchain({ pm, pnpmVersion, nodeVersion,
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
+
function reportCiToolchain({ pm, pnpmVersion, nodeVersion, source }) {
|
|
1301
|
+
if (pm !== 'pnpm') {
|
|
1302
|
+
info(`CI will use ${pm} + Node ${nodeVersion}`)
|
|
1303
|
+
return
|
|
1304
|
+
}
|
|
1305
|
+
const origin = {
|
|
1306
|
+
declared: '',
|
|
1307
|
+
installed: ' (matching your install)',
|
|
1308
|
+
fallback: ' (no pnpm detected — using the default)',
|
|
1309
|
+
}[source] ?? ''
|
|
1310
|
+
info(`CI will use pnpm ${pnpmVersion} + Node ${nodeVersion}${origin}`)
|
|
1311
|
+
if (source === 'fallback') {
|
|
1312
|
+
info(`Pin with "packageManager": "pnpm@<version>" in package.json to choose a major.`)
|
|
1300
1313
|
}
|
|
1301
1314
|
}
|
|
1302
1315
|
|
|
@@ -1358,9 +1371,13 @@ async function addFoundationCi(rootDir, opts, adapter, pm) {
|
|
|
1358
1371
|
// CI must run the project's own toolchain. The pnpm major comes from
|
|
1359
1372
|
// its `packageManager` field when declared; the node major is the
|
|
1360
1373
|
// project's floor, raised if that pnpm needs more.
|
|
1361
|
-
const
|
|
1374
|
+
const installedPnpm = detectInstalledPnpmVersion(rootDir)
|
|
1375
|
+
const pnpmVersion = resolveCiPnpmVersion(rootPkg, installedPnpm)
|
|
1362
1376
|
const nodeVersion = resolveCiNodeVersion(rootPkg.engines?.node, pm, pnpmVersion)
|
|
1363
|
-
reportCiToolchain({
|
|
1377
|
+
reportCiToolchain({
|
|
1378
|
+
pm, pnpmVersion, nodeVersion,
|
|
1379
|
+
source: rootPkg?.packageManager ? 'declared' : installedPnpm ? 'installed' : 'fallback',
|
|
1380
|
+
})
|
|
1364
1381
|
|
|
1365
1382
|
let result
|
|
1366
1383
|
try {
|
package/src/framework-index.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-07-
|
|
3
|
+
"generatedAt": "2026-07-22T09:39:33.879Z",
|
|
4
4
|
"packages": {
|
|
5
5
|
"@uniweb/build": {
|
|
6
|
-
"version": "0.14.
|
|
6
|
+
"version": "0.14.35",
|
|
7
7
|
"path": "framework/build",
|
|
8
8
|
"deps": [
|
|
9
9
|
"@uniweb/content-reader",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
]
|
|
16
16
|
},
|
|
17
17
|
"@uniweb/content-reader": {
|
|
18
|
-
"version": "1.1.
|
|
18
|
+
"version": "1.1.13",
|
|
19
19
|
"path": "framework/content-reader",
|
|
20
20
|
"deps": []
|
|
21
21
|
},
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"deps": []
|
|
26
26
|
},
|
|
27
27
|
"@uniweb/core": {
|
|
28
|
-
"version": "0.7.
|
|
28
|
+
"version": "0.7.22",
|
|
29
29
|
"path": "framework/core",
|
|
30
30
|
"deps": [
|
|
31
31
|
"@uniweb/semantic-parser",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"deps": []
|
|
44
44
|
},
|
|
45
45
|
"@uniweb/kit": {
|
|
46
|
-
"version": "0.9.
|
|
46
|
+
"version": "0.9.28",
|
|
47
47
|
"path": "framework/kit",
|
|
48
48
|
"deps": [
|
|
49
49
|
"@uniweb/core",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"deps": []
|
|
62
62
|
},
|
|
63
63
|
"@uniweb/runtime": {
|
|
64
|
-
"version": "0.8.
|
|
64
|
+
"version": "0.8.28",
|
|
65
65
|
"path": "framework/runtime",
|
|
66
66
|
"deps": [
|
|
67
67
|
"@uniweb/core",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"deps": []
|
|
85
85
|
},
|
|
86
86
|
"@uniweb/semantic-parser": {
|
|
87
|
-
"version": "1.1.
|
|
87
|
+
"version": "1.1.18",
|
|
88
88
|
"path": "framework/semantic-parser",
|
|
89
89
|
"deps": []
|
|
90
90
|
},
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"deps": []
|
|
100
100
|
},
|
|
101
101
|
"@uniweb/unipress": {
|
|
102
|
-
"version": "0.4.
|
|
102
|
+
"version": "0.4.42",
|
|
103
103
|
"path": "framework/unipress",
|
|
104
104
|
"deps": [
|
|
105
105
|
"@uniweb/build",
|
package/src/utils/pm.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* and generate PM-appropriate commands for output messages.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { existsSync } from 'node:fs'
|
|
8
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
9
9
|
import { join } from 'node:path'
|
|
10
10
|
import { execSync } from 'node:child_process'
|
|
11
11
|
|
|
@@ -41,6 +41,48 @@ export function detectWorkspacePm(workspaceRoot) {
|
|
|
41
41
|
return null
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* The pnpm major that actually installed this workspace.
|
|
46
|
+
*
|
|
47
|
+
* pnpm records the version it ran as in `node_modules/.modules.yaml`:
|
|
48
|
+
*
|
|
49
|
+
* "packageManager": "pnpm@10.30.0"
|
|
50
|
+
*
|
|
51
|
+
* This is a *record of what happened*, not a guess about intent — which
|
|
52
|
+
* matters, because intent cannot be inferred. The documented way to
|
|
53
|
+
* scaffold is `npm create uniweb`, and plenty of people follow it with
|
|
54
|
+
* `pnpm install`; the invoking package manager therefore says nothing
|
|
55
|
+
* about the one the project uses. The lockfile says WHICH manager
|
|
56
|
+
* (`detectWorkspacePm`); this says which pnpm MAJOR, which the lockfile
|
|
57
|
+
* cannot — pnpm 10 and 11 both write `lockfileVersion: 9.0`.
|
|
58
|
+
*
|
|
59
|
+
* Despite the extension the file is JSON in current pnpm; `js-yaml`
|
|
60
|
+
* parses both, since YAML is a superset. Older pnpm wrote real YAML.
|
|
61
|
+
*
|
|
62
|
+
* @param {string} workspaceRoot
|
|
63
|
+
* @returns {string|null} pnpm major (e.g. '10'), or null when the file is
|
|
64
|
+
* absent or unreadable — callers fall back to their own default.
|
|
65
|
+
*/
|
|
66
|
+
export function detectInstalledPnpmVersion(workspaceRoot) {
|
|
67
|
+
if (!workspaceRoot) return null
|
|
68
|
+
const path = join(workspaceRoot, 'node_modules', '.modules.yaml')
|
|
69
|
+
if (!existsSync(path)) return null
|
|
70
|
+
try {
|
|
71
|
+
// Cheap targeted read: the file is large (hoisted-dependency maps run
|
|
72
|
+
// to hundreds of KB) and we want exactly one field, so match it
|
|
73
|
+
// directly rather than parsing the whole document.
|
|
74
|
+
const text = readFileSync(path, 'utf8')
|
|
75
|
+
// Quotes optional on both key and value: current pnpm writes JSON
|
|
76
|
+
// (`"packageManager": "pnpm@10.30.0"`), but the file is named .yaml and
|
|
77
|
+
// YAML permits the bare form, so accept either rather than depending on
|
|
78
|
+
// which serializer the installing pnpm happened to use.
|
|
79
|
+
const match = text.match(/["']?packageManager["']?\s*:\s*["']?pnpm@(\d+)/)
|
|
80
|
+
return match ? match[1] : null
|
|
81
|
+
} catch {
|
|
82
|
+
return null
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
44
86
|
/**
|
|
45
87
|
* Detect which package manager owns a *globally installed* `uniweb` CLI
|
|
46
88
|
* binary, by inspecting its install path (`process.argv[1]`). pnpm and
|
package/src/versions.js
CHANGED
|
@@ -100,20 +100,37 @@ export const PNPM_MIN_NODE = { '10': 18, '11': 22 }
|
|
|
100
100
|
/**
|
|
101
101
|
* Resolve the pnpm major a generated CI workflow should install.
|
|
102
102
|
*
|
|
103
|
-
*
|
|
104
|
-
* the project stating which pnpm it is developed and locked against, so CI
|
|
105
|
-
* should honour it rather than impose a different major.
|
|
103
|
+
* Observed, not assumed, in this order:
|
|
106
104
|
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
105
|
+
* 1. `packageManager` in package.json — the project stating explicitly
|
|
106
|
+
* which pnpm it is developed and locked against. Honour it.
|
|
107
|
+
* 2. What actually installed the project, from
|
|
108
|
+
* `node_modules/.modules.yaml` (`detectInstalledPnpmVersion`). A record
|
|
109
|
+
* of fact: the developer running `add ci` is the developer who ran
|
|
110
|
+
* `pnpm install`, and `add ci` refuses to run before install, so this
|
|
111
|
+
* is normally present.
|
|
112
|
+
* 3. `PNPM_VERSION` — a last resort that should rarely apply.
|
|
113
|
+
*
|
|
114
|
+
* There is deliberately no inference from *how the CLI was invoked*. The
|
|
115
|
+
* documented way to scaffold is `npm create uniweb`, commonly followed by
|
|
116
|
+
* `pnpm install`, so the invoking manager says nothing about the project's.
|
|
117
|
+
* Writing a `packageManager` field at scaffold time was considered and
|
|
118
|
+
* rejected for the same reason — it would guess intent and, being enforced
|
|
119
|
+
* by corepack, would be a hard pin rather than a hint.
|
|
120
|
+
*
|
|
121
|
+
* `pnpm-lock.yaml`'s `lockfileVersion` is NOT usable here: pnpm 10 and 11
|
|
122
|
+
* both write `9.0`, so it cannot distinguish them. Checked, not assumed.
|
|
109
123
|
*
|
|
110
124
|
* @param {object|null} rootPkg — the workspace root's parsed package.json.
|
|
125
|
+
* @param {string|null} [installedMajor] — from `detectInstalledPnpmVersion`.
|
|
111
126
|
* @returns {string} pnpm major, as a string for YAML interpolation.
|
|
112
127
|
*/
|
|
113
|
-
export function resolveCiPnpmVersion(rootPkg) {
|
|
128
|
+
export function resolveCiPnpmVersion(rootPkg, installedMajor = null) {
|
|
114
129
|
const declared = rootPkg?.packageManager
|
|
115
130
|
const match = typeof declared === 'string' ? declared.match(/^pnpm@(\d+)/) : null
|
|
116
|
-
|
|
131
|
+
if (match) return match[1]
|
|
132
|
+
if (installedMajor) return String(installedMajor)
|
|
133
|
+
return PNPM_VERSION
|
|
117
134
|
}
|
|
118
135
|
|
|
119
136
|
/**
|