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.
@@ -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
- const { packages } = await readWorkspaceConfig(rootDir)
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 sites = []
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 pkgPath = join(rootDir, dir, 'package.json')
267
- if (!existsSync(pkgPath)) continue
268
- try {
269
- const pkg = JSON.parse(await readFile(pkgPath, 'utf-8'))
270
- // Site: has @uniweb/runtime in deps
271
- if (pkg.dependencies?.['@uniweb/runtime']) {
272
- sites.push({ name: pkg.name, path: dir })
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 sites
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
- return pm === 'pnpm' ? 'pnpm install' : 'npm install'
64
+ if (pm === 'pnpm') return 'pnpm install'
65
+ if (pm === 'yarn') return 'yarn install'
66
+ return 'npm install'
41
67
  }
42
68
 
43
69
  /**