@gjsify/cli 0.3.13 → 0.3.14
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/lib/actions/build.d.ts +8 -91
- package/lib/actions/build.js +147 -148
- package/lib/config.js +51 -11
- package/lib/types/cli-build-options.d.ts +1 -1
- package/lib/types/config-data.d.ts +51 -2
- package/lib/utils/normalize-bundler-options.d.ts +17 -0
- package/lib/utils/normalize-bundler-options.js +123 -0
- package/package.json +11 -11
- package/src/actions/build.ts +372 -351
- package/src/config.ts +47 -11
- package/src/types/cli-build-options.ts +1 -1
- package/src/types/config-data.ts +51 -2
- package/src/utils/normalize-bundler-options.ts +129 -0
package/lib/actions/build.d.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { ConfigData } from "../types/index.js";
|
|
2
|
-
import type { App } from "@gjsify/
|
|
3
|
-
import {
|
|
2
|
+
import type { App } from "@gjsify/rolldown-plugin-gjsify";
|
|
3
|
+
import type { RolldownOutput } from "rolldown";
|
|
4
4
|
export declare class BuildAction {
|
|
5
5
|
readonly configData: ConfigData;
|
|
6
6
|
constructor(configData?: ConfigData);
|
|
7
|
-
getEsBuildDefaults(): BuildOptions;
|
|
8
7
|
/** Library mode */
|
|
9
|
-
buildLibrary(): Promise<
|
|
8
|
+
buildLibrary(): Promise<RolldownOutput[]>;
|
|
10
9
|
/**
|
|
11
10
|
* Parse the `--globals` value into { autoMode, extras }.
|
|
12
11
|
* - `auto` → { autoMode: true, extras: '' }
|
|
@@ -19,11 +18,11 @@ export declare class BuildAction {
|
|
|
19
18
|
private parseGlobalsValue;
|
|
20
19
|
/**
|
|
21
20
|
* Resolve the `--globals` CLI list into a pre-computed inject stub path
|
|
22
|
-
* that the
|
|
23
|
-
*
|
|
21
|
+
* that the orchestrator appends to its input list. Only runs for
|
|
22
|
+
* `--app gjs` — Node and browser builds rely on native globals.
|
|
24
23
|
*
|
|
25
24
|
* Used only for the explicit-only path (no `auto` token in the value).
|
|
26
|
-
* The auto path is handled in `buildApp` via the
|
|
25
|
+
* The auto path is handled in `buildApp` via the iterative multi-pass build.
|
|
27
26
|
*/
|
|
28
27
|
private resolveGlobalsInject;
|
|
29
28
|
/**
|
|
@@ -32,91 +31,9 @@ export declare class BuildAction {
|
|
|
32
31
|
*/
|
|
33
32
|
private applyShebang;
|
|
34
33
|
/** Application mode */
|
|
35
|
-
buildApp(app?: App): Promise<
|
|
36
|
-
format: "esm" | "cjs";
|
|
37
|
-
plugins: Plugin[];
|
|
38
|
-
bundle?: boolean;
|
|
39
|
-
splitting?: boolean;
|
|
40
|
-
preserveSymlinks?: boolean;
|
|
41
|
-
outfile?: string;
|
|
42
|
-
metafile?: boolean;
|
|
43
|
-
outdir?: string;
|
|
44
|
-
outbase?: string;
|
|
45
|
-
external?: string[];
|
|
46
|
-
packages?: "bundle" | "external";
|
|
47
|
-
alias?: Record<string, string>;
|
|
48
|
-
loader?: {
|
|
49
|
-
[ext: string]: import("esbuild").Loader;
|
|
50
|
-
};
|
|
51
|
-
resolveExtensions?: string[];
|
|
52
|
-
mainFields?: string[];
|
|
53
|
-
conditions?: string[];
|
|
54
|
-
write?: boolean;
|
|
55
|
-
allowOverwrite?: boolean;
|
|
56
|
-
tsconfig?: string;
|
|
57
|
-
outExtension?: {
|
|
58
|
-
[ext: string]: string;
|
|
59
|
-
};
|
|
60
|
-
publicPath?: string;
|
|
61
|
-
entryNames?: string;
|
|
62
|
-
chunkNames?: string;
|
|
63
|
-
assetNames?: string;
|
|
64
|
-
inject?: string[];
|
|
65
|
-
banner?: {
|
|
66
|
-
[type: string]: string;
|
|
67
|
-
};
|
|
68
|
-
footer?: {
|
|
69
|
-
[type: string]: string;
|
|
70
|
-
};
|
|
71
|
-
entryPoints?: (string | {
|
|
72
|
-
in: string;
|
|
73
|
-
out: string;
|
|
74
|
-
})[] | Record<string, string>;
|
|
75
|
-
stdin?: import("esbuild").StdinOptions;
|
|
76
|
-
absWorkingDir?: string;
|
|
77
|
-
nodePaths?: string[];
|
|
78
|
-
sourcemap?: boolean | "linked" | "inline" | "external" | "both";
|
|
79
|
-
legalComments?: "none" | "inline" | "eof" | "linked" | "external";
|
|
80
|
-
sourceRoot?: string;
|
|
81
|
-
sourcesContent?: boolean;
|
|
82
|
-
globalName?: string;
|
|
83
|
-
target?: string | string[];
|
|
84
|
-
supported?: Record<string, boolean>;
|
|
85
|
-
platform?: import("esbuild").Platform;
|
|
86
|
-
mangleProps?: RegExp;
|
|
87
|
-
reserveProps?: RegExp;
|
|
88
|
-
mangleQuoted?: boolean;
|
|
89
|
-
mangleCache?: Record<string, string | false>;
|
|
90
|
-
drop?: import("esbuild").Drop[];
|
|
91
|
-
dropLabels?: string[];
|
|
92
|
-
minify?: boolean;
|
|
93
|
-
minifyWhitespace?: boolean;
|
|
94
|
-
minifyIdentifiers?: boolean;
|
|
95
|
-
minifySyntax?: boolean;
|
|
96
|
-
lineLimit?: number;
|
|
97
|
-
charset?: import("esbuild").Charset;
|
|
98
|
-
treeShaking?: boolean;
|
|
99
|
-
ignoreAnnotations?: boolean;
|
|
100
|
-
jsx?: "transform" | "preserve" | "automatic";
|
|
101
|
-
jsxFactory?: string;
|
|
102
|
-
jsxFragment?: string;
|
|
103
|
-
jsxImportSource?: string;
|
|
104
|
-
jsxDev?: boolean;
|
|
105
|
-
jsxSideEffects?: boolean;
|
|
106
|
-
define?: {
|
|
107
|
-
[key: string]: string;
|
|
108
|
-
};
|
|
109
|
-
pure?: string[];
|
|
110
|
-
keepNames?: boolean;
|
|
111
|
-
absPaths?: import("esbuild").AbsPaths[];
|
|
112
|
-
color?: boolean;
|
|
113
|
-
logLevel?: import("esbuild").LogLevel;
|
|
114
|
-
logLimit?: number;
|
|
115
|
-
logOverride?: Record<string, import("esbuild").LogLevel>;
|
|
116
|
-
tsconfigRaw?: string | import("esbuild").TsconfigRaw;
|
|
117
|
-
}>[]>;
|
|
34
|
+
buildApp(app?: App): Promise<RolldownOutput[]>;
|
|
118
35
|
start(buildType?: {
|
|
119
36
|
library?: boolean;
|
|
120
37
|
app?: App;
|
|
121
|
-
}): Promise<
|
|
38
|
+
}): Promise<RolldownOutput[]>;
|
|
122
39
|
}
|
package/lib/actions/build.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { gjsifyPlugin } from "@gjsify/
|
|
3
|
-
import { resolveGlobalsList, writeRegisterInjectFile, detectAutoGlobals, } from "@gjsify/
|
|
4
|
-
import {
|
|
5
|
-
import { getPnpPlugin } from "@gjsify/resolve-npm/pnp-relay";
|
|
1
|
+
import { rolldown } from "rolldown";
|
|
2
|
+
import { gjsifyPlugin } from "@gjsify/rolldown-plugin-gjsify";
|
|
3
|
+
import { resolveGlobalsList, writeRegisterInjectFile, detectAutoGlobals, } from "@gjsify/rolldown-plugin-gjsify/globals";
|
|
4
|
+
import { pnpPlugin } from "@gjsify/rolldown-plugin-pnp";
|
|
6
5
|
import { dirname, extname } from "node:path";
|
|
7
6
|
import { chmod, readFile, writeFile } from "node:fs/promises";
|
|
7
|
+
import { normalizeBundlerOptions, mergeBundlerOptions } from "../utils/normalize-bundler-options.js";
|
|
8
8
|
const GJS_SHEBANG = "#!/usr/bin/env -S gjs -m\n";
|
|
9
9
|
/**
|
|
10
10
|
* `true` when `path` points at a location that's unsafe to use as a build
|
|
@@ -26,104 +26,81 @@ function isUnsafeDefaultOutput(path) {
|
|
|
26
26
|
* @gjsify/{node,web}-polyfills) are resolvable for external consumers without
|
|
27
27
|
* each one having to be a direct devDep.
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* inside the pnp plugin's onLoad rather than as a separate registration.
|
|
29
|
+
* The path rewriter (`__filename`/`__dirname` + `import.meta.url` injection
|
|
30
|
+
* for node_modules code) is registered separately by the orchestrator —
|
|
31
|
+
* Rolldown's transform hooks all run sequentially, no shared `onLoad` race.
|
|
33
32
|
*/
|
|
34
33
|
async function buildPnpPlugin() {
|
|
35
|
-
return
|
|
36
|
-
issuerUrl: import.meta.url,
|
|
37
|
-
transformContentsFactory: (build) => {
|
|
38
|
-
const bundleDir = getBundleDir(build);
|
|
39
|
-
return (args, contents) => rewriteContents(args, contents, bundleDir);
|
|
40
|
-
},
|
|
41
|
-
});
|
|
34
|
+
return pnpPlugin({ issuerUrl: import.meta.url });
|
|
42
35
|
}
|
|
43
36
|
export class BuildAction {
|
|
44
37
|
configData;
|
|
45
38
|
constructor(configData = {}) {
|
|
46
39
|
this.configData = configData;
|
|
47
40
|
}
|
|
48
|
-
getEsBuildDefaults() {
|
|
49
|
-
const defaults = {
|
|
50
|
-
allowOverwrite: true,
|
|
51
|
-
};
|
|
52
|
-
return defaults;
|
|
53
|
-
}
|
|
54
41
|
/** Library mode */
|
|
55
42
|
async buildLibrary() {
|
|
56
|
-
|
|
57
|
-
library
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
const mainOutExt = library.main ? extname(library.main) : ".js";
|
|
43
|
+
const { verbose, library, typescript, exclude, aliases } = this.configData;
|
|
44
|
+
const lib = library ?? {};
|
|
45
|
+
const userBundler = normalizeBundlerOptions(this.configData);
|
|
46
|
+
const moduleOutdir = lib.module ? dirname(lib.module) : undefined;
|
|
47
|
+
const mainOutdir = lib.main ? dirname(lib.main) : undefined;
|
|
48
|
+
const moduleOutExt = lib.module ? extname(lib.module) : ".js";
|
|
49
|
+
const mainOutExt = lib.main ? extname(lib.main) : ".js";
|
|
64
50
|
const multipleBuilds = moduleOutdir && mainOutdir && moduleOutdir !== mainOutdir;
|
|
65
|
-
const
|
|
66
|
-
const pnpPlugins =
|
|
51
|
+
const pnp = await buildPnpPlugin();
|
|
52
|
+
const pnpPlugins = pnp ? [pnp] : [];
|
|
67
53
|
const results = [];
|
|
68
54
|
if (multipleBuilds) {
|
|
69
55
|
const moduleFormat = moduleOutdir.includes("/cjs") || moduleOutExt === ".cjs"
|
|
70
56
|
? "cjs"
|
|
71
57
|
: "esm";
|
|
72
|
-
results.push(await
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
jsExtension: moduleOutExt,
|
|
85
|
-
}),
|
|
86
|
-
],
|
|
58
|
+
results.push(await runOneLibraryBuild({
|
|
59
|
+
pluginOpts: {
|
|
60
|
+
debug: verbose,
|
|
61
|
+
library: moduleFormat,
|
|
62
|
+
exclude,
|
|
63
|
+
reflection: typescript?.reflection,
|
|
64
|
+
jsExtension: moduleOutExt,
|
|
65
|
+
},
|
|
66
|
+
userBundler,
|
|
67
|
+
output: { dir: moduleOutdir },
|
|
68
|
+
userAliases: aliases,
|
|
69
|
+
pnpPlugins,
|
|
87
70
|
}));
|
|
88
71
|
const mainFormat = mainOutdir.includes("/cjs") || mainOutExt === ".cjs" ? "cjs" : "esm";
|
|
89
|
-
results.push(await
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
jsExtension: mainOutExt,
|
|
102
|
-
}),
|
|
103
|
-
],
|
|
72
|
+
results.push(await runOneLibraryBuild({
|
|
73
|
+
pluginOpts: {
|
|
74
|
+
debug: verbose,
|
|
75
|
+
library: mainFormat,
|
|
76
|
+
exclude,
|
|
77
|
+
reflection: typescript?.reflection,
|
|
78
|
+
jsExtension: mainOutExt,
|
|
79
|
+
},
|
|
80
|
+
userBundler,
|
|
81
|
+
output: { dir: mainOutdir },
|
|
82
|
+
userAliases: aliases,
|
|
83
|
+
pnpPlugins,
|
|
104
84
|
}));
|
|
105
85
|
}
|
|
106
86
|
else {
|
|
107
|
-
const outfilePath =
|
|
87
|
+
const outfilePath = userBundler.output?.file ?? lib.module ?? lib.main;
|
|
108
88
|
const outExt = outfilePath ? extname(outfilePath) : ".js";
|
|
109
|
-
const outdir =
|
|
110
|
-
const format =
|
|
89
|
+
const outdir = userBundler.output?.dir ?? (outfilePath ? dirname(outfilePath) : undefined);
|
|
90
|
+
const format = userBundler.output?.format ??
|
|
111
91
|
(outdir?.includes("/cjs") || outExt === ".cjs" ? "cjs" : "esm");
|
|
112
|
-
results.push(await
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
jsExtension: outExt,
|
|
125
|
-
}),
|
|
126
|
-
],
|
|
92
|
+
results.push(await runOneLibraryBuild({
|
|
93
|
+
pluginOpts: {
|
|
94
|
+
debug: verbose,
|
|
95
|
+
library: format,
|
|
96
|
+
exclude,
|
|
97
|
+
reflection: typescript?.reflection,
|
|
98
|
+
jsExtension: outExt,
|
|
99
|
+
},
|
|
100
|
+
userBundler,
|
|
101
|
+
output: { dir: outdir },
|
|
102
|
+
userAliases: aliases,
|
|
103
|
+
pnpPlugins,
|
|
127
104
|
}));
|
|
128
105
|
}
|
|
129
106
|
return results;
|
|
@@ -152,11 +129,11 @@ export class BuildAction {
|
|
|
152
129
|
}
|
|
153
130
|
/**
|
|
154
131
|
* Resolve the `--globals` CLI list into a pre-computed inject stub path
|
|
155
|
-
* that the
|
|
156
|
-
*
|
|
132
|
+
* that the orchestrator appends to its input list. Only runs for
|
|
133
|
+
* `--app gjs` — Node and browser builds rely on native globals.
|
|
157
134
|
*
|
|
158
135
|
* Used only for the explicit-only path (no `auto` token in the value).
|
|
159
|
-
* The auto path is handled in `buildApp` via the
|
|
136
|
+
* The auto path is handled in `buildApp` via the iterative multi-pass build.
|
|
160
137
|
*/
|
|
161
138
|
async resolveGlobalsInject(app, globals, verbose) {
|
|
162
139
|
if (app !== "gjs")
|
|
@@ -196,30 +173,34 @@ export class BuildAction {
|
|
|
196
173
|
}
|
|
197
174
|
/** Application mode */
|
|
198
175
|
async buildApp(app = "gjs") {
|
|
199
|
-
const { verbose,
|
|
200
|
-
const
|
|
201
|
-
|
|
176
|
+
const { verbose, typescript, exclude, library: pkg, aliases, excludeGlobals, } = this.configData;
|
|
177
|
+
const userBundler = normalizeBundlerOptions(this.configData);
|
|
178
|
+
const formatRaw = userBundler.output?.format ??
|
|
179
|
+
(userBundler.output?.file?.endsWith(".cjs") ? "cjs" : "esm");
|
|
180
|
+
// The orchestrator only handles esm/cjs (iife is not a GJS / Node /
|
|
181
|
+
// browser-bundle target we support). Coerce.
|
|
182
|
+
const format = formatRaw === "iife" ? "esm" : formatRaw;
|
|
202
183
|
// Set default outfile if no outdir is set
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
: pgk.module || pgk.main;
|
|
184
|
+
let outfile = userBundler.output?.file;
|
|
185
|
+
let outdir = userBundler.output?.dir;
|
|
186
|
+
if (!outfile && !outdir && (pkg?.main || pkg?.module)) {
|
|
187
|
+
const candidate = format === "cjs"
|
|
188
|
+
? pkg.main ?? pkg.module
|
|
189
|
+
: pkg.module ?? pkg.main;
|
|
210
190
|
if (candidate && isUnsafeDefaultOutput(candidate)) {
|
|
211
|
-
// `package.json#main`/`module` commonly points at a TypeScript
|
|
212
|
-
// source (e.g. `src/index.ts` for TS-direct workflows). Falling
|
|
213
|
-
// back to that value would have esbuild OVERWRITE the source.
|
|
214
|
-
// Surface a clear error and require an explicit outfile/outdir
|
|
215
|
-
// instead of silently destroying the user's code.
|
|
216
191
|
throw new Error(`gjsify build: refusing to default --outfile to ${candidate} ` +
|
|
217
192
|
`(would overwrite a TypeScript source file). Pass --outfile/--outdir ` +
|
|
218
|
-
`explicitly, or set "gjsify.
|
|
193
|
+
`explicitly, or set "gjsify.bundler.output.file" in package.json.`);
|
|
219
194
|
}
|
|
220
|
-
|
|
195
|
+
outfile = candidate;
|
|
221
196
|
}
|
|
222
197
|
const { consoleShim, globals } = this.configData;
|
|
198
|
+
const userExternal = Array.isArray(userBundler.external)
|
|
199
|
+
? userBundler.external
|
|
200
|
+
: undefined;
|
|
201
|
+
const userBanner = typeof userBundler.output?.banner === "string"
|
|
202
|
+
? userBundler.output.banner
|
|
203
|
+
: undefined;
|
|
223
204
|
const pluginOpts = {
|
|
224
205
|
debug: verbose,
|
|
225
206
|
app,
|
|
@@ -230,65 +211,83 @@ export class BuildAction {
|
|
|
230
211
|
...(aliases ? { aliases } : {}),
|
|
231
212
|
};
|
|
232
213
|
const { autoMode, extras } = this.parseGlobalsValue(globals);
|
|
233
|
-
const
|
|
234
|
-
const pnpPlugins =
|
|
214
|
+
const pnp = await buildPnpPlugin();
|
|
215
|
+
const pnpPlugins = pnp ? [pnp] : [];
|
|
235
216
|
// --- Auto mode (with optional extras): iterative multi-pass build ---
|
|
236
|
-
// The extras token is used for cases where the detector cannot
|
|
237
|
-
// statically see a global (e.g. Excalibur indirects globalThis via
|
|
238
|
-
// BrowserComponent.nativeComponent). Common pattern: --globals auto,dom
|
|
239
217
|
if (app === "gjs" && autoMode) {
|
|
218
|
+
const gjsifyPluginFactory = async (opts) => {
|
|
219
|
+
const cfg = await gjsifyPlugin({
|
|
220
|
+
input: userBundler.input,
|
|
221
|
+
output: { file: outfile, dir: outdir },
|
|
222
|
+
userExternal,
|
|
223
|
+
userBanner,
|
|
224
|
+
userAliases: aliases,
|
|
225
|
+
shebang: this.configData.shebang,
|
|
226
|
+
}, opts);
|
|
227
|
+
return cfg.plugins;
|
|
228
|
+
};
|
|
240
229
|
const { injectPath } = await detectAutoGlobals({
|
|
241
|
-
|
|
242
|
-
...esbuild,
|
|
243
|
-
format,
|
|
230
|
+
input: userBundler.input,
|
|
244
231
|
plugins: pnpPlugins,
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
...this.getEsBuildDefaults(),
|
|
248
|
-
...esbuild,
|
|
232
|
+
external: userBundler.external,
|
|
233
|
+
transform: userBundler.transform,
|
|
249
234
|
format,
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
235
|
+
}, pluginOpts, gjsifyPluginFactory, verbose, { extraGlobalsList: extras, excludeGlobals });
|
|
236
|
+
pluginOpts.autoGlobalsInject = injectPath;
|
|
237
|
+
}
|
|
238
|
+
else if (extras) {
|
|
239
|
+
pluginOpts.autoGlobalsInject = await this.resolveGlobalsInject(app, extras, verbose);
|
|
240
|
+
}
|
|
241
|
+
// Final build: orchestrator → rolldown → write
|
|
242
|
+
const cfg = await gjsifyPlugin({
|
|
243
|
+
input: userBundler.input,
|
|
244
|
+
output: { file: outfile, dir: outdir },
|
|
245
|
+
userExternal,
|
|
246
|
+
userBanner,
|
|
247
|
+
userAliases: aliases,
|
|
248
|
+
shebang: this.configData.shebang,
|
|
249
|
+
}, pluginOpts);
|
|
250
|
+
const merged = mergeBundlerOptions(cfg.options, userBundler);
|
|
251
|
+
const finalOpts = {
|
|
252
|
+
...merged,
|
|
253
|
+
plugins: [...pnpPlugins, ...cfg.plugins],
|
|
254
|
+
};
|
|
255
|
+
const build = await rolldown(finalOpts);
|
|
256
|
+
let writeResult;
|
|
257
|
+
try {
|
|
258
|
+
writeResult = await build.write(finalOpts.output ?? {});
|
|
259
|
+
}
|
|
260
|
+
finally {
|
|
261
|
+
await build.close();
|
|
262
262
|
}
|
|
263
|
-
// --- Explicit list (no `auto` token) or none mode ---
|
|
264
|
-
const autoGlobalsInject = extras
|
|
265
|
-
? await this.resolveGlobalsInject(app, extras, verbose)
|
|
266
|
-
: undefined;
|
|
267
|
-
const result = await build({
|
|
268
|
-
...this.getEsBuildDefaults(),
|
|
269
|
-
...esbuild,
|
|
270
|
-
format,
|
|
271
|
-
plugins: [
|
|
272
|
-
...pnpPlugins,
|
|
273
|
-
gjsifyPlugin({
|
|
274
|
-
...pluginOpts,
|
|
275
|
-
autoGlobalsInject,
|
|
276
|
-
}),
|
|
277
|
-
],
|
|
278
|
-
});
|
|
279
263
|
if (app === "gjs" && this.configData.shebang) {
|
|
280
|
-
await this.applyShebang(
|
|
264
|
+
await this.applyShebang(outfile, verbose);
|
|
281
265
|
}
|
|
282
|
-
return [
|
|
266
|
+
return [writeResult];
|
|
283
267
|
}
|
|
284
268
|
async start(buildType = { app: "gjs" }) {
|
|
285
|
-
const results = [];
|
|
286
269
|
if (buildType.library) {
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
else {
|
|
290
|
-
results.push(...(await this.buildApp(buildType.app)));
|
|
270
|
+
return await this.buildLibrary();
|
|
291
271
|
}
|
|
292
|
-
return
|
|
272
|
+
return await this.buildApp(buildType.app);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
async function runOneLibraryBuild(args) {
|
|
276
|
+
const cfg = await gjsifyPlugin({
|
|
277
|
+
input: args.userBundler.input,
|
|
278
|
+
output: args.output,
|
|
279
|
+
userAliases: args.userAliases,
|
|
280
|
+
}, args.pluginOpts);
|
|
281
|
+
const merged = mergeBundlerOptions(cfg.options, args.userBundler);
|
|
282
|
+
const finalOpts = {
|
|
283
|
+
...merged,
|
|
284
|
+
plugins: [...args.pnpPlugins, ...cfg.plugins],
|
|
285
|
+
};
|
|
286
|
+
const build = await rolldown(finalOpts);
|
|
287
|
+
try {
|
|
288
|
+
return await build.write(finalOpts.output ?? {});
|
|
289
|
+
}
|
|
290
|
+
finally {
|
|
291
|
+
await build.close();
|
|
293
292
|
}
|
|
294
293
|
}
|
package/lib/config.js
CHANGED
|
@@ -84,7 +84,7 @@ export class Config {
|
|
|
84
84
|
if (fileResult?.config && isPlainObject(fileResult.config)) {
|
|
85
85
|
merge(merged, fileResult.config);
|
|
86
86
|
}
|
|
87
|
-
merged.
|
|
87
|
+
merged.bundler ||= {};
|
|
88
88
|
merged.library ||= {};
|
|
89
89
|
merged.typescript ||= {};
|
|
90
90
|
return {
|
|
@@ -155,16 +155,56 @@ export class Config {
|
|
|
155
155
|
if (Object.keys(aliasMap).length) {
|
|
156
156
|
configData.aliases = { ...(configData.aliases ?? {}), ...aliasMap };
|
|
157
157
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
});
|
|
158
|
+
// Merge CLI flags into the Rolldown-shape `bundler` field. Mappings:
|
|
159
|
+
// --entry-points → bundler.input
|
|
160
|
+
// --outfile → bundler.output.file
|
|
161
|
+
// --outdir → bundler.output.dir
|
|
162
|
+
// --format → bundler.output.format
|
|
163
|
+
// --minify → bundler.output.minify
|
|
164
|
+
// --log-level → bundler.logLevel
|
|
165
|
+
// --external → bundler.external
|
|
166
|
+
// --define → bundler.transform.define
|
|
167
|
+
const bundler = (configData.bundler ??= {});
|
|
168
|
+
const output = (bundler.output ??= {});
|
|
169
|
+
const transform = (bundler.transform ??= {});
|
|
170
|
+
if (cliArgs.entryPoints?.length)
|
|
171
|
+
bundler.input = cliArgs.entryPoints;
|
|
172
|
+
if (cliArgs.outfile !== undefined)
|
|
173
|
+
output.file = cliArgs.outfile;
|
|
174
|
+
if (cliArgs.outdir !== undefined)
|
|
175
|
+
output.dir = cliArgs.outdir;
|
|
176
|
+
if (cliArgs.format !== undefined)
|
|
177
|
+
output.format = cliArgs.format;
|
|
178
|
+
if (cliArgs.minify !== undefined)
|
|
179
|
+
output.minify = cliArgs.minify;
|
|
180
|
+
if (cliArgs.logLevel) {
|
|
181
|
+
// Map esbuild log levels to Rolldown's narrower set:
|
|
182
|
+
// esbuild → rolldown
|
|
183
|
+
// silent → silent
|
|
184
|
+
// error → warn (rolldown has no error-only)
|
|
185
|
+
// warning → warn
|
|
186
|
+
// info → info
|
|
187
|
+
// debug → debug
|
|
188
|
+
// verbose → debug (rolldown has no verbose)
|
|
189
|
+
const map = {
|
|
190
|
+
silent: 'silent',
|
|
191
|
+
error: 'warn',
|
|
192
|
+
warning: 'warn',
|
|
193
|
+
warn: 'warn',
|
|
194
|
+
info: 'info',
|
|
195
|
+
debug: 'debug',
|
|
196
|
+
verbose: 'debug',
|
|
197
|
+
};
|
|
198
|
+
const level = map[cliArgs.logLevel] ?? 'warn';
|
|
199
|
+
bundler.logLevel = level;
|
|
200
|
+
}
|
|
201
|
+
if (cliArgs.external?.length) {
|
|
202
|
+
const userExternal = Array.isArray(bundler.external) ? bundler.external : [];
|
|
203
|
+
bundler.external = [...userExternal, ...cliArgs.external];
|
|
204
|
+
}
|
|
205
|
+
if (Object.keys(defineMap).length) {
|
|
206
|
+
transform.define = { ...(transform.define ?? {}), ...defineMap };
|
|
207
|
+
}
|
|
168
208
|
if (configData.verbose)
|
|
169
209
|
console.debug("configData", configData);
|
|
170
210
|
return configData;
|
|
@@ -1,9 +1,58 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RolldownOptions, OutputOptions } from 'rolldown';
|
|
2
2
|
import type { ConfigDataLibrary, ConfigDataTypescript } from './index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Subset of `RolldownOptions` accepted in `.gjsifyrc.js`. Mirrors the legacy
|
|
5
|
+
* `esbuild?: BuildOptions` field — a thin pass-through. The orchestrator
|
|
6
|
+
* applies platform defaults on top of these, so most projects only need
|
|
7
|
+
* `output.file` / `output.dir` here.
|
|
8
|
+
*
|
|
9
|
+
* `output` is constrained to a single `OutputOptions` object (Rolldown also
|
|
10
|
+
* accepts an array for multi-output builds, but the CLI surface targets the
|
|
11
|
+
* single-output use case).
|
|
12
|
+
*/
|
|
13
|
+
export type BundlerOptions = Omit<RolldownOptions, 'output'> & {
|
|
14
|
+
output?: OutputOptions;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Legacy `esbuild?: BuildOptions` shape — kept as a compatibility shim for
|
|
18
|
+
* one minor release. Setting it logs a deprecation warning; the supported
|
|
19
|
+
* subset of fields is mapped into `bundler` at config-load time.
|
|
20
|
+
*
|
|
21
|
+
* Drop in 0.5.0.
|
|
22
|
+
*/
|
|
23
|
+
export interface LegacyEsbuildOptions {
|
|
24
|
+
outfile?: string;
|
|
25
|
+
outdir?: string;
|
|
26
|
+
format?: 'esm' | 'cjs' | 'iife';
|
|
27
|
+
external?: string[];
|
|
28
|
+
define?: Record<string, string>;
|
|
29
|
+
inject?: string[];
|
|
30
|
+
banner?: {
|
|
31
|
+
js?: string;
|
|
32
|
+
};
|
|
33
|
+
target?: string | string[];
|
|
34
|
+
minify?: boolean;
|
|
35
|
+
sourcemap?: boolean | 'inline' | 'external' | 'both';
|
|
36
|
+
mainFields?: string[];
|
|
37
|
+
conditions?: string[];
|
|
38
|
+
platform?: 'browser' | 'node' | 'neutral';
|
|
39
|
+
loader?: Record<string, string>;
|
|
40
|
+
}
|
|
3
41
|
export interface ConfigData {
|
|
4
42
|
/** Switch on the verbose mode */
|
|
5
43
|
verbose?: boolean;
|
|
6
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Bundler-level options forwarded to Rolldown. Replaces the legacy
|
|
46
|
+
* `esbuild` field. The orchestrator applies platform-specific defaults
|
|
47
|
+
* on top — most projects only need to set `output.file` / `output.dir`.
|
|
48
|
+
*/
|
|
49
|
+
bundler?: BundlerOptions;
|
|
50
|
+
/**
|
|
51
|
+
* @deprecated Use `bundler` instead. Will be removed in 0.5.0. The shim
|
|
52
|
+
* maps the supported subset of esbuild fields into the equivalent
|
|
53
|
+
* Rolldown shape and logs a deprecation warning.
|
|
54
|
+
*/
|
|
55
|
+
esbuild?: LegacyEsbuildOptions;
|
|
7
56
|
library?: ConfigDataLibrary;
|
|
8
57
|
typescript?: ConfigDataTypescript;
|
|
9
58
|
/** An array of glob patterns to exclude matches and aliases */
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ConfigData, BundlerOptions } from '../types/config-data.js';
|
|
2
|
+
export declare function normalizeBundlerOptions(configData: ConfigData): BundlerOptions;
|
|
3
|
+
/**
|
|
4
|
+
* Shallow merge with deep-merge of `output`, `transform`, and `resolve`. The
|
|
5
|
+
* second argument wins on conflicts, matching `merge(target, ...sources)`
|
|
6
|
+
* semantics from `@gjsify/rolldown-plugin-gjsify/utils/merge`.
|
|
7
|
+
*
|
|
8
|
+
* `base` is typically the Rolldown-generic shape returned by the orchestrator;
|
|
9
|
+
* `overrides` is the user's `BundlerOptions` from `.gjsifyrc.js` plus CLI
|
|
10
|
+
* flag merges. Single-output assumption matches `BundlerOptions['output']`.
|
|
11
|
+
*
|
|
12
|
+
* The orchestrator-side `input` is authoritative — it's the post-glob-expansion
|
|
13
|
+
* value. Overriding it with the user's raw glob string would re-introduce
|
|
14
|
+
* unresolved glob patterns into the final Rolldown call. Same for `external`,
|
|
15
|
+
* which the orchestrator concatenates with platform defaults already.
|
|
16
|
+
*/
|
|
17
|
+
export declare function mergeBundlerOptions(base: BundlerOptions, overrides: BundlerOptions): BundlerOptions;
|