@webjsdev/ui 0.3.15 → 0.3.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 +7 -0
- package/package.json +1 -1
- package/src/commands/add.js +19 -6
- package/src/utils/package-manager.js +92 -0
package/README.md
CHANGED
|
@@ -111,6 +111,13 @@ it on demand with `npx @webjsdev/ui view <name>`, which is what the pointer it
|
|
|
111
111
|
leaves behind says too). It also self-heals the theme tokens if
|
|
112
112
|
they are missing.
|
|
113
113
|
|
|
114
|
+
The install runs with your project's package manager. `add` looks for a
|
|
115
|
+
lockfile in the current directory and then each parent, stopping at the
|
|
116
|
+
workspace root, so an app inside a monorepo uses the root's lockfile:
|
|
117
|
+
`pnpm-lock.yaml` means pnpm, `yarn.lock` yarn, `bun.lock` or `bun.lockb` bun,
|
|
118
|
+
`package-lock.json` npm. With no lockfile it reads `npm_config_user_agent`
|
|
119
|
+
(set by `bunx`, `pnpm dlx` and friends), and falls back to npm.
|
|
120
|
+
|
|
114
121
|
Resolution is LOCAL-FIRST: `init` / `add` / `list` / `view` read the registry
|
|
115
122
|
that ships inside the installed `@webjsdev/ui` package, so they work with no
|
|
116
123
|
network. Point at a custom registry with `--registry <url>`; `webjsui diff`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webjsdev/ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The AI-first component library for WebJs, a full-stack JavaScript framework built on web components with server-side rendering and no build step. Class-helper functions for visuals, custom elements only where state matters, source-copied into your repo so you own it.",
|
|
6
6
|
"bin": {
|
package/src/commands/add.js
CHANGED
|
@@ -10,6 +10,7 @@ import { DEFAULT_REGISTRY_URL } from '../registry/fetcher.js';
|
|
|
10
10
|
import { isCustomElementSource } from '../registry/local.js';
|
|
11
11
|
import { stripExample } from '../registry/example.js';
|
|
12
12
|
import { ensureTheme } from '../utils/theme.js';
|
|
13
|
+
import { detectPackageManager } from '../utils/package-manager.js';
|
|
13
14
|
|
|
14
15
|
export const add = new Command()
|
|
15
16
|
.name('add')
|
|
@@ -247,7 +248,7 @@ function ensureDir(d) {
|
|
|
247
248
|
}
|
|
248
249
|
|
|
249
250
|
async function installDeps(cwd, deps, dev) {
|
|
250
|
-
const manager =
|
|
251
|
+
const manager = detectAddCommand(cwd);
|
|
251
252
|
const flag = dev ? '-D' : '';
|
|
252
253
|
const cmd = `${manager.exec} ${manager.add} ${flag} ${deps.join(' ')}`.replace(/\s+/g, ' ').trim();
|
|
253
254
|
logger.info(`${logger.dim('$')} ${cmd}`);
|
|
@@ -258,9 +259,21 @@ async function installDeps(cwd, deps, dev) {
|
|
|
258
259
|
}
|
|
259
260
|
}
|
|
260
261
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
262
|
+
/** Install command per manager (`-D` marks a dev dependency for all four). */
|
|
263
|
+
const ADD_COMMANDS = {
|
|
264
|
+
npm: { exec: 'npm', add: 'install' },
|
|
265
|
+
pnpm: { exec: 'pnpm', add: 'add' },
|
|
266
|
+
yarn: { exec: 'yarn', add: 'add' },
|
|
267
|
+
bun: { exec: 'bun', add: 'add' },
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Resolve the install command for the project at `cwd` (#1494): the lockfile
|
|
272
|
+
* walk-up (so `bun.lock` and a workspace-root lockfile both count), then the
|
|
273
|
+
* invoking tool's user agent, then npm.
|
|
274
|
+
* @param {string} cwd
|
|
275
|
+
* @param {Record<string, string | undefined>} [env]
|
|
276
|
+
*/
|
|
277
|
+
export function detectAddCommand(cwd, env = process.env) {
|
|
278
|
+
return ADD_COMMANDS[detectPackageManager({ cwd, env })];
|
|
266
279
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package-manager detection for `webjs ui add` (#1494).
|
|
3
|
+
*
|
|
4
|
+
* KEEP IN SYNC with `packages/cli/lib/package-manager.js`. The two published
|
|
5
|
+
* packages carry the same small module rather than one importing the other,
|
|
6
|
+
* so a `@webjsdev/cli` release can never fail at import time against an older
|
|
7
|
+
* `@webjsdev/ui` that lacks the export. `packages/cli/test/package-manager.test.mjs`
|
|
8
|
+
* asserts both copies agree on every fixture.
|
|
9
|
+
*
|
|
10
|
+
* Detection order (with `prefer: 'lockfile'`, the default):
|
|
11
|
+
* 1. A lockfile in `cwd` or any ancestor. The walk stops at the first
|
|
12
|
+
* workspace root (a package.json declaring `workspaces`, or a
|
|
13
|
+
* `pnpm-workspace.yaml`) or at the filesystem root, so an app nested in a
|
|
14
|
+
* workspace finds the root's lockfile. Within one directory the order is
|
|
15
|
+
* pnpm, yarn, bun (`bun.lock`, the text lockfile Bun writes since 1.2,
|
|
16
|
+
* and the older binary `bun.lockb`), then npm.
|
|
17
|
+
* 2. `npm_config_user_agent`, which npm, pnpm, yarn and bun set when they
|
|
18
|
+
* run a script or a `dlx` / `bunx` / `npx` binary.
|
|
19
|
+
* 3. `npm`.
|
|
20
|
+
* With `prefer: 'agent'` steps 1 and 2 swap, which suits `webjs create`: the
|
|
21
|
+
* tool that invoked it is the strongest signal for a directory that has no
|
|
22
|
+
* lockfile yet.
|
|
23
|
+
*/
|
|
24
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
25
|
+
import { dirname, join, resolve } from 'node:path';
|
|
26
|
+
|
|
27
|
+
/** @typedef {'npm'|'pnpm'|'yarn'|'bun'} PackageManager */
|
|
28
|
+
|
|
29
|
+
/** Lockfile name to manager, in per-directory precedence order. */
|
|
30
|
+
const LOCKFILES = /** @type {const} */ ([
|
|
31
|
+
['pnpm-lock.yaml', 'pnpm'],
|
|
32
|
+
['yarn.lock', 'yarn'],
|
|
33
|
+
['bun.lock', 'bun'],
|
|
34
|
+
['bun.lockb', 'bun'],
|
|
35
|
+
['package-lock.json', 'npm'],
|
|
36
|
+
['npm-shrinkwrap.json', 'npm'],
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Whether `dir` is a workspace root, where the lockfile walk stops.
|
|
41
|
+
* @param {string} dir
|
|
42
|
+
* @returns {boolean}
|
|
43
|
+
*/
|
|
44
|
+
function isWorkspaceRoot(dir) {
|
|
45
|
+
if (existsSync(join(dir, 'pnpm-workspace.yaml'))) return true;
|
|
46
|
+
const pkgPath = join(dir, 'package.json');
|
|
47
|
+
if (!existsSync(pkgPath)) return false;
|
|
48
|
+
try {
|
|
49
|
+
return Boolean(JSON.parse(readFileSync(pkgPath, 'utf8')).workspaces);
|
|
50
|
+
} catch {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Walk up from `cwd` looking for a lockfile.
|
|
57
|
+
* @param {string} cwd
|
|
58
|
+
* @returns {PackageManager | null}
|
|
59
|
+
*/
|
|
60
|
+
export function managerFromLockfile(cwd) {
|
|
61
|
+
let dir = resolve(cwd);
|
|
62
|
+
for (;;) {
|
|
63
|
+
for (const [file, manager] of LOCKFILES) {
|
|
64
|
+
if (existsSync(join(dir, file))) return manager;
|
|
65
|
+
}
|
|
66
|
+
if (isWorkspaceRoot(dir)) return null;
|
|
67
|
+
const parent = dirname(dir);
|
|
68
|
+
if (parent === dir) return null;
|
|
69
|
+
dir = parent;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Read the manager from an `npm_config_user_agent` value such as
|
|
75
|
+
* `bun/1.3.14 npm/? node/v24.0.0 linux x64`.
|
|
76
|
+
* @param {string | undefined} ua
|
|
77
|
+
* @returns {PackageManager | null}
|
|
78
|
+
*/
|
|
79
|
+
export function managerFromUserAgent(ua) {
|
|
80
|
+
const name = String(ua || '').split('/')[0];
|
|
81
|
+
return name === 'pnpm' || name === 'yarn' || name === 'bun' || name === 'npm' ? name : null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @param {{ cwd?: string | null, env?: Record<string, string | undefined>, prefer?: 'lockfile' | 'agent' }} [opts]
|
|
86
|
+
* @returns {PackageManager}
|
|
87
|
+
*/
|
|
88
|
+
export function detectPackageManager({ cwd = null, env = process.env, prefer = 'lockfile' } = {}) {
|
|
89
|
+
const fromLock = () => (cwd ? managerFromLockfile(cwd) : null);
|
|
90
|
+
const fromAgent = () => managerFromUserAgent(env.npm_config_user_agent);
|
|
91
|
+
return (prefer === 'agent' ? fromAgent() ?? fromLock() : fromLock() ?? fromAgent()) ?? 'npm';
|
|
92
|
+
}
|