uniweb 0.12.14 → 0.12.16
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/README.md +46 -19
- package/package.json +3 -3
- package/partials/agents.md +5 -0
- package/src/commands/add.js +224 -7
- package/src/commands/build.js +2 -2
- package/src/commands/doctor.js +155 -1
- package/src/commands/update.js +352 -54
- package/src/framework-index.json +3 -3
- package/src/index.js +25 -14
- package/src/utils/config.js +32 -32
- package/src/utils/pm.js +28 -2
package/src/utils/config.js
CHANGED
|
@@ -10,6 +10,7 @@ import { readFile, writeFile } from 'node:fs/promises'
|
|
|
10
10
|
import { join } from 'node:path'
|
|
11
11
|
import { homedir } from 'node:os'
|
|
12
12
|
import yaml from 'js-yaml'
|
|
13
|
+
import { classifyPackage } from '@uniweb/build'
|
|
13
14
|
import { filterCmd } from './pm.js'
|
|
14
15
|
|
|
15
16
|
// ── Platform URLs ──────────────────────────────────────────────
|
|
@@ -228,27 +229,7 @@ export async function updateRootScripts(rootDir, sites, pm = 'pnpm') {
|
|
|
228
229
|
* @returns {Promise<Array<{name: string, path: string}>>}
|
|
229
230
|
*/
|
|
230
231
|
export async function discoverFoundations(rootDir) {
|
|
231
|
-
|
|
232
|
-
const foundations = []
|
|
233
|
-
|
|
234
|
-
for (const pattern of packages) {
|
|
235
|
-
const dirs = await resolveGlob(rootDir, pattern)
|
|
236
|
-
for (const dir of dirs) {
|
|
237
|
-
const pkgPath = join(rootDir, dir, 'package.json')
|
|
238
|
-
if (!existsSync(pkgPath)) continue
|
|
239
|
-
try {
|
|
240
|
-
const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'))
|
|
241
|
-
// Foundation: has @uniweb/build in devDeps but NOT @uniweb/runtime in deps
|
|
242
|
-
if (pkg.devDependencies?.['@uniweb/build'] && !pkg.dependencies?.['@uniweb/runtime']) {
|
|
243
|
-
foundations.push({ name: pkg.name, path: dir })
|
|
244
|
-
}
|
|
245
|
-
} catch {
|
|
246
|
-
// skip
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return foundations
|
|
232
|
+
return discoverByKind(rootDir, 'foundation')
|
|
252
233
|
}
|
|
253
234
|
|
|
254
235
|
/**
|
|
@@ -257,27 +238,46 @@ export async function discoverFoundations(rootDir) {
|
|
|
257
238
|
* @returns {Promise<Array<{name: string, path: string}>>}
|
|
258
239
|
*/
|
|
259
240
|
export async function discoverSites(rootDir) {
|
|
241
|
+
return discoverByKind(rootDir, 'site')
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Walk the workspace globs and return packages of the requested kind.
|
|
246
|
+
* Uses `classifyPackage` from @uniweb/build — the canonical classifier
|
|
247
|
+
* shared with the build pipeline, which keys on real signals (site.yml
|
|
248
|
+
* for sites, generated entry for foundations) rather than which
|
|
249
|
+
* `@uniweb/*` packages happen to be in dependencies. Templates whose
|
|
250
|
+
* sites pull runtime transitively through the foundation (e.g.,
|
|
251
|
+
* marketing) used to be invisible to the older dependency-based check.
|
|
252
|
+
*/
|
|
253
|
+
async function discoverByKind(rootDir, kind) {
|
|
260
254
|
const { packages } = await readWorkspaceConfig(rootDir)
|
|
261
|
-
const
|
|
255
|
+
const out = []
|
|
262
256
|
|
|
263
257
|
for (const pattern of packages) {
|
|
264
258
|
const dirs = await resolveGlob(rootDir, pattern)
|
|
265
259
|
for (const dir of dirs) {
|
|
266
|
-
const
|
|
267
|
-
if (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
260
|
+
const fullPath = join(rootDir, dir)
|
|
261
|
+
if (classifyPackage(fullPath) !== kind) continue
|
|
262
|
+
|
|
263
|
+
// Read package.json for the package name. Synthesize one from
|
|
264
|
+
// the directory if it's missing or malformed — we still want
|
|
265
|
+
// the package to surface in pickers.
|
|
266
|
+
const pkgPath = join(fullPath, 'package.json')
|
|
267
|
+
let name = dir.split('/').pop()
|
|
268
|
+
if (existsSync(pkgPath)) {
|
|
269
|
+
try {
|
|
270
|
+
const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'))
|
|
271
|
+
if (pkg.name) name = pkg.name
|
|
272
|
+
} catch {
|
|
273
|
+
// keep directory-derived name
|
|
273
274
|
}
|
|
274
|
-
} catch {
|
|
275
|
-
// skip
|
|
276
275
|
}
|
|
276
|
+
out.push({ name, path: dir })
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
return
|
|
280
|
+
return out
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
// Resolve a workspace glob pattern to actual directories
|
package/src/utils/pm.js
CHANGED
|
@@ -5,9 +5,17 @@
|
|
|
5
5
|
* and generate PM-appropriate commands for output messages.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { existsSync } from 'node:fs'
|
|
9
|
+
import { join } from 'node:path'
|
|
10
|
+
|
|
8
11
|
/**
|
|
9
12
|
* Detect which package manager invoked the CLI.
|
|
10
13
|
* Uses the standard npm_config_user_agent env var (same technique as create-vite, create-next-app).
|
|
14
|
+
*
|
|
15
|
+
* Note: this returns the *invoker* PM, which is empty when the user runs
|
|
16
|
+
* a global CLI binary directly from a shell. For the workspace's own PM
|
|
17
|
+
* (driven by lockfile presence), use `detectWorkspacePm`.
|
|
18
|
+
*
|
|
11
19
|
* @returns {'pnpm' | 'npm'}
|
|
12
20
|
*/
|
|
13
21
|
export function detectPackageManager() {
|
|
@@ -16,6 +24,22 @@ export function detectPackageManager() {
|
|
|
16
24
|
return 'npm'
|
|
17
25
|
}
|
|
18
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Detect the workspace's package manager by inspecting lockfiles at the
|
|
29
|
+
* workspace root. This is the right signal for "what PM should I use to
|
|
30
|
+
* install in this workspace" — independent of how the CLI was invoked.
|
|
31
|
+
*
|
|
32
|
+
* @param {string} workspaceRoot - Absolute path to workspace root
|
|
33
|
+
* @returns {'pnpm' | 'yarn' | 'npm' | null} - null when no lockfile is present
|
|
34
|
+
*/
|
|
35
|
+
export function detectWorkspacePm(workspaceRoot) {
|
|
36
|
+
if (!workspaceRoot) return null
|
|
37
|
+
if (existsSync(join(workspaceRoot, 'pnpm-lock.yaml'))) return 'pnpm'
|
|
38
|
+
if (existsSync(join(workspaceRoot, 'yarn.lock'))) return 'yarn'
|
|
39
|
+
if (existsSync(join(workspaceRoot, 'package-lock.json'))) return 'npm'
|
|
40
|
+
return null
|
|
41
|
+
}
|
|
42
|
+
|
|
19
43
|
/**
|
|
20
44
|
* Generate a workspace-filtered command.
|
|
21
45
|
* pnpm: "pnpm --filter site dev"
|
|
@@ -33,11 +57,13 @@ export function filterCmd(pm, pkg, cmd) {
|
|
|
33
57
|
|
|
34
58
|
/**
|
|
35
59
|
* Generate an install command.
|
|
36
|
-
* @param {'pnpm' | 'npm'} pm
|
|
60
|
+
* @param {'pnpm' | 'yarn' | 'npm'} pm
|
|
37
61
|
* @returns {string}
|
|
38
62
|
*/
|
|
39
63
|
export function installCmd(pm) {
|
|
40
|
-
|
|
64
|
+
if (pm === 'pnpm') return 'pnpm install'
|
|
65
|
+
if (pm === 'yarn') return 'yarn install'
|
|
66
|
+
return 'npm install'
|
|
41
67
|
}
|
|
42
68
|
|
|
43
69
|
/**
|