@gjsify/cli 0.10.0 → 0.12.0
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/dist/cli.gjs.mjs +95 -69
- package/lib/cli-app.js +3 -1
- package/lib/commands/browse.d.ts +16 -0
- package/lib/commands/browse.js +117 -0
- package/lib/commands/build.js +6 -1
- package/lib/commands/debug.d.ts +10 -0
- package/lib/commands/debug.js +148 -0
- package/lib/commands/index.d.ts +2 -0
- package/lib/commands/index.js +2 -0
- package/lib/commands/install.js +17 -2
- package/lib/commands/self-update.js +29 -2
- package/lib/commands/tsc.js +11 -0
- package/lib/config.js +6 -0
- package/lib/index.js +20 -1
- package/lib/utils/install-backend-native.js +96 -5
- package/lib/utils/install-global.d.ts +41 -0
- package/lib/utils/install-global.js +74 -0
- package/lib/utils/install-progress.js +27 -3
- package/package.json +17 -17
- package/showcases.json +7 -0
|
@@ -10,6 +10,47 @@ export interface GlobalLayout {
|
|
|
10
10
|
* `GJSIFY_GLOBAL_PREFIX` and `GJSIFY_GLOBAL_BIN_DIR` escape hatches for tests.
|
|
11
11
|
*/
|
|
12
12
|
export declare function defaultGlobalLayout(): GlobalLayout;
|
|
13
|
+
/**
|
|
14
|
+
* The GJS-native tooling bridges the global CLI needs to run a build under GJS.
|
|
15
|
+
*
|
|
16
|
+
* These are declared OPTIONAL peer dependencies of `@gjsify/cli` (so a plain
|
|
17
|
+
* `npm install @gjsify/cli` on Node — where the npm `rolldown` / `lightningcss`
|
|
18
|
+
* / `oxfmt` crates work — does not force a linux prebuild fetch). But a *global
|
|
19
|
+
* GJS install* exists precisely to run the GJS CLI, where there is NO npm
|
|
20
|
+
* fallback: `@gjsify/rolldown-native` is the only bundler engine (`gjsify build`
|
|
21
|
+
* hard-fails without it), `@gjsify/lightningcss-native` backs CSS lowering, and
|
|
22
|
+
* `@gjsify/oxfmt-native` backs `gjsify format`/`fix`. So the global installer
|
|
23
|
+
* lays them down explicitly, on top of the cli's resolved runtime deps.
|
|
24
|
+
*
|
|
25
|
+
* `@gjsify/rolldown-native` is the load-bearing one (build is dead without it);
|
|
26
|
+
* the other two degrade gracefully at runtime (CSS / format fall back), so all
|
|
27
|
+
* three are installed best-effort: a platform with no published prebuild for
|
|
28
|
+
* the engine just gets a warning + continue, mirroring how the optional-peer
|
|
29
|
+
* story already degrades on Node.
|
|
30
|
+
*/
|
|
31
|
+
export declare const GJS_ENGINE_PACKAGES: readonly ["@gjsify/rolldown-native", "@gjsify/lightningcss-native", "@gjsify/oxfmt-native"];
|
|
32
|
+
/** True when `<prefix>/node_modules/@gjsify/rolldown-native` is laid down. */
|
|
33
|
+
export declare function hasBundlerEngineInstalled(prefix: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Best-effort install of the GJS-native engine packages into a global prefix.
|
|
36
|
+
*
|
|
37
|
+
* Each engine is installed in its own `installPackages` call so one engine that
|
|
38
|
+
* has no published prebuild for the current platform (the resolver throws "No
|
|
39
|
+
* version of … satisfies …", or the registry 404s) does NOT abort the others —
|
|
40
|
+
* it warns and continues. The bundler engine (`@gjsify/rolldown-native`) is the
|
|
41
|
+
* one a build truly needs; the failure surfaces a clear, actionable message.
|
|
42
|
+
*
|
|
43
|
+
* `version` is the dist-tag / version the top-level `@gjsify/cli` resolved to,
|
|
44
|
+
* so the engines move in lockstep with the bundle. It may be a concrete version
|
|
45
|
+
* (`0.11.0`) or a dist-tag (`latest`, `next`); both are valid spec suffixes.
|
|
46
|
+
*
|
|
47
|
+
* @param installFn Injected to keep this unit-testable without a real registry —
|
|
48
|
+
* defaults to the production `installPackages` backend.
|
|
49
|
+
*/
|
|
50
|
+
export declare function installGjsEnginePackages(prefix: string, version: string, opts?: {
|
|
51
|
+
verbose?: boolean;
|
|
52
|
+
installFn?: (spec: string) => Promise<void>;
|
|
53
|
+
}): Promise<void>;
|
|
13
54
|
export interface LinkedBin {
|
|
14
55
|
/** The bin-name (key from `bin` / `gjsify.bin`). */
|
|
15
56
|
name: string;
|
|
@@ -39,6 +39,80 @@ export function defaultGlobalLayout() {
|
|
|
39
39
|
binDir: binOverride ?? path.join(home, '.local', 'bin'),
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* The GJS-native tooling bridges the global CLI needs to run a build under GJS.
|
|
44
|
+
*
|
|
45
|
+
* These are declared OPTIONAL peer dependencies of `@gjsify/cli` (so a plain
|
|
46
|
+
* `npm install @gjsify/cli` on Node — where the npm `rolldown` / `lightningcss`
|
|
47
|
+
* / `oxfmt` crates work — does not force a linux prebuild fetch). But a *global
|
|
48
|
+
* GJS install* exists precisely to run the GJS CLI, where there is NO npm
|
|
49
|
+
* fallback: `@gjsify/rolldown-native` is the only bundler engine (`gjsify build`
|
|
50
|
+
* hard-fails without it), `@gjsify/lightningcss-native` backs CSS lowering, and
|
|
51
|
+
* `@gjsify/oxfmt-native` backs `gjsify format`/`fix`. So the global installer
|
|
52
|
+
* lays them down explicitly, on top of the cli's resolved runtime deps.
|
|
53
|
+
*
|
|
54
|
+
* `@gjsify/rolldown-native` is the load-bearing one (build is dead without it);
|
|
55
|
+
* the other two degrade gracefully at runtime (CSS / format fall back), so all
|
|
56
|
+
* three are installed best-effort: a platform with no published prebuild for
|
|
57
|
+
* the engine just gets a warning + continue, mirroring how the optional-peer
|
|
58
|
+
* story already degrades on Node.
|
|
59
|
+
*/
|
|
60
|
+
export const GJS_ENGINE_PACKAGES = [
|
|
61
|
+
'@gjsify/rolldown-native',
|
|
62
|
+
'@gjsify/lightningcss-native',
|
|
63
|
+
'@gjsify/oxfmt-native',
|
|
64
|
+
];
|
|
65
|
+
/** True when `<prefix>/node_modules/@gjsify/rolldown-native` is laid down. */
|
|
66
|
+
export function hasBundlerEngineInstalled(prefix) {
|
|
67
|
+
return fs.existsSync(path.join(prefix, 'node_modules', '@gjsify/rolldown-native', 'package.json'));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Best-effort install of the GJS-native engine packages into a global prefix.
|
|
71
|
+
*
|
|
72
|
+
* Each engine is installed in its own `installPackages` call so one engine that
|
|
73
|
+
* has no published prebuild for the current platform (the resolver throws "No
|
|
74
|
+
* version of … satisfies …", or the registry 404s) does NOT abort the others —
|
|
75
|
+
* it warns and continues. The bundler engine (`@gjsify/rolldown-native`) is the
|
|
76
|
+
* one a build truly needs; the failure surfaces a clear, actionable message.
|
|
77
|
+
*
|
|
78
|
+
* `version` is the dist-tag / version the top-level `@gjsify/cli` resolved to,
|
|
79
|
+
* so the engines move in lockstep with the bundle. It may be a concrete version
|
|
80
|
+
* (`0.11.0`) or a dist-tag (`latest`, `next`); both are valid spec suffixes.
|
|
81
|
+
*
|
|
82
|
+
* @param installFn Injected to keep this unit-testable without a real registry —
|
|
83
|
+
* defaults to the production `installPackages` backend.
|
|
84
|
+
*/
|
|
85
|
+
export async function installGjsEnginePackages(prefix, version, opts = {}) {
|
|
86
|
+
const verbose = opts.verbose ?? false;
|
|
87
|
+
const installOne = opts.installFn ??
|
|
88
|
+
(async (spec) => {
|
|
89
|
+
// Lazy import to avoid a static cycle (install-backend → … → here)
|
|
90
|
+
// and to keep this module importable from the lighter unit tests.
|
|
91
|
+
const { installPackages } = await import('./install-backend.js');
|
|
92
|
+
await installPackages({ prefix, specs: [spec], verbose });
|
|
93
|
+
});
|
|
94
|
+
for (const name of GJS_ENGINE_PACKAGES) {
|
|
95
|
+
const spec = version ? `${name}@${version}` : name;
|
|
96
|
+
try {
|
|
97
|
+
await installOne(spec);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
101
|
+
// `@gjsify/rolldown-native` is the bundler engine — its absence
|
|
102
|
+
// means `gjsify build` (and storybook / anything that builds) will
|
|
103
|
+
// hard-fail under GJS. Make that one loud; the other two degrade
|
|
104
|
+
// gracefully so a plain note suffices.
|
|
105
|
+
if (name === '@gjsify/rolldown-native') {
|
|
106
|
+
console.warn(`\nWarning: could not install the GJS bundler engine ${name}@${version} — ${msg}\n` +
|
|
107
|
+
` \`gjsify build\` (and storybook / flatpak) will fail under GJS until it is present.\n` +
|
|
108
|
+
` This usually means no prebuild is published for this platform (${process.platform}/${process.arch}).`);
|
|
109
|
+
}
|
|
110
|
+
else if (verbose) {
|
|
111
|
+
console.warn(`gjsify install: optional GJS engine ${name}@${version} not installed — ${msg}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
42
116
|
/**
|
|
43
117
|
* Install each top-level package's bin entries into `binDir` as small POSIX
|
|
44
118
|
* `sh` launchers that exec the real bin. Reads each package's installed
|
|
@@ -73,14 +73,38 @@ function makeTtyReporter(stream) {
|
|
|
73
73
|
},
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
|
-
// ──── Plain reporter —
|
|
76
|
+
// ──── Plain reporter — phase begin/end + periodic heartbeat (non-TTY) ──────
|
|
77
|
+
//
|
|
78
|
+
// On a non-TTY (piped to a log file, CI, or captured output) the bar can't
|
|
79
|
+
// `\r`-overwrite, so per-package lines are suppressed to avoid flooding the
|
|
80
|
+
// log. But emitting NOTHING between `beginPhase` and `endPhase` makes a long
|
|
81
|
+
// download/extract phase look frozen — the exact "no further output for 25+
|
|
82
|
+
// minutes" symptom of a slow install. So we emit a low-frequency heartbeat:
|
|
83
|
+
// at most one line per HEARTBEAT_MS, AND only after at least a few packages of
|
|
84
|
+
// real progress, so a fast warm install (most nodes skipped) stays quiet while
|
|
85
|
+
// a genuinely long phase reports `… N/M (X%)` every few seconds. This mirrors
|
|
86
|
+
// what npm (`--loglevel http`) and pnpm log on non-TTY: progress you can watch
|
|
87
|
+
// without it being one line per file.
|
|
88
|
+
const HEARTBEAT_MS = 5_000;
|
|
77
89
|
function makePlainReporter(stream) {
|
|
90
|
+
let lastHeartbeat = 0;
|
|
91
|
+
let lastReported = 0;
|
|
78
92
|
return {
|
|
79
93
|
beginPhase(phase, total) {
|
|
94
|
+
lastHeartbeat = Date.now();
|
|
95
|
+
lastReported = 0;
|
|
80
96
|
stream.write(`gjsify install: ${PHASE_LABEL[phase]} ${total} package(s)\n`);
|
|
81
97
|
},
|
|
82
|
-
update() {
|
|
83
|
-
|
|
98
|
+
update(ev) {
|
|
99
|
+
const now = Date.now();
|
|
100
|
+
if (now - lastHeartbeat < HEARTBEAT_MS)
|
|
101
|
+
return;
|
|
102
|
+
if (ev.current <= lastReported)
|
|
103
|
+
return;
|
|
104
|
+
lastHeartbeat = now;
|
|
105
|
+
lastReported = ev.current;
|
|
106
|
+
const pct = ev.total > 0 ? Math.round((ev.current / ev.total) * 100) : 0;
|
|
107
|
+
stream.write(`gjsify install: ${PHASE_LABEL[ev.phase]} ${ev.current}/${ev.total} (${pct}%)\n`);
|
|
84
108
|
},
|
|
85
109
|
endPhase(phase) {
|
|
86
110
|
stream.write(`gjsify install: ${PHASE_LABEL[phase]} done\n`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjsify/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "CLI for Gjsify",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -120,19 +120,19 @@
|
|
|
120
120
|
"cli"
|
|
121
121
|
],
|
|
122
122
|
"dependencies": {
|
|
123
|
-
"@gjsify/buffer": "^0.
|
|
124
|
-
"@gjsify/create-app": "^0.
|
|
125
|
-
"@gjsify/node-globals": "^0.
|
|
126
|
-
"@gjsify/node-polyfills": "^0.
|
|
127
|
-
"@gjsify/npm-registry": "^0.
|
|
128
|
-
"@gjsify/resolve-npm": "^0.
|
|
129
|
-
"@gjsify/rolldown-plugin-gjsify": "^0.
|
|
130
|
-
"@gjsify/rolldown-plugin-pnp": "^0.
|
|
131
|
-
"@gjsify/semver": "^0.
|
|
132
|
-
"@gjsify/tar": "^0.
|
|
133
|
-
"@gjsify/tsc": "^0.
|
|
134
|
-
"@gjsify/web-polyfills": "^0.
|
|
135
|
-
"@gjsify/workspace": "^0.
|
|
123
|
+
"@gjsify/buffer": "^0.12.0",
|
|
124
|
+
"@gjsify/create-app": "^0.12.0",
|
|
125
|
+
"@gjsify/node-globals": "^0.12.0",
|
|
126
|
+
"@gjsify/node-polyfills": "^0.12.0",
|
|
127
|
+
"@gjsify/npm-registry": "^0.12.0",
|
|
128
|
+
"@gjsify/resolve-npm": "^0.12.0",
|
|
129
|
+
"@gjsify/rolldown-plugin-gjsify": "^0.12.0",
|
|
130
|
+
"@gjsify/rolldown-plugin-pnp": "^0.12.0",
|
|
131
|
+
"@gjsify/semver": "^0.12.0",
|
|
132
|
+
"@gjsify/tar": "^0.12.0",
|
|
133
|
+
"@gjsify/tsc": "^0.12.0",
|
|
134
|
+
"@gjsify/web-polyfills": "^0.12.0",
|
|
135
|
+
"@gjsify/workspace": "^0.12.0",
|
|
136
136
|
"cosmiconfig": "^9.0.2",
|
|
137
137
|
"get-tsconfig": "^4.14.0",
|
|
138
138
|
"pkg-types": "^2.3.1",
|
|
@@ -140,13 +140,13 @@
|
|
|
140
140
|
"yargs": "^18.0.0"
|
|
141
141
|
},
|
|
142
142
|
"devDependencies": {
|
|
143
|
-
"@gjsify/unit": "^0.
|
|
143
|
+
"@gjsify/unit": "^0.12.0",
|
|
144
144
|
"@types/yargs": "^17.0.35",
|
|
145
145
|
"typescript": "^6.0.3"
|
|
146
146
|
},
|
|
147
147
|
"peerDependencies": {
|
|
148
|
-
"@gjsify/oxfmt-native": "^0.
|
|
149
|
-
"@gjsify/rolldown-native": "^0.
|
|
148
|
+
"@gjsify/oxfmt-native": "^0.12.0",
|
|
149
|
+
"@gjsify/rolldown-native": "^0.12.0"
|
|
150
150
|
},
|
|
151
151
|
"peerDependenciesMeta": {
|
|
152
152
|
"@gjsify/oxfmt-native": {
|
package/showcases.json
CHANGED
|
@@ -49,6 +49,13 @@
|
|
|
49
49
|
"package": "@gjsify/example-node-express-webserver",
|
|
50
50
|
"description": "Express web server on GJS via @gjsify/http",
|
|
51
51
|
"needsWebgl": false
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"name": "adwaita-storybook",
|
|
55
|
+
"category": "gtk",
|
|
56
|
+
"package": "@gjsify/example-gtk-adwaita-storybook",
|
|
57
|
+
"description": "Interactive Libadwaita component browser — author one story per widget, rendered natively (GTK) and in the browser",
|
|
58
|
+
"needsWebgl": false
|
|
52
59
|
}
|
|
53
60
|
]
|
|
54
61
|
}
|