@gjsify/cli 0.3.13 → 0.3.15

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.
Files changed (48) hide show
  1. package/lib/actions/build.d.ts +14 -93
  2. package/lib/actions/build.js +182 -154
  3. package/lib/commands/flatpak/build.d.ts +16 -0
  4. package/lib/commands/flatpak/build.js +187 -0
  5. package/lib/commands/flatpak/ci.d.ts +13 -0
  6. package/lib/commands/flatpak/ci.js +133 -0
  7. package/lib/commands/flatpak/deps.d.ts +12 -0
  8. package/lib/commands/flatpak/deps.js +96 -0
  9. package/lib/commands/flatpak/index.d.ts +7 -0
  10. package/lib/commands/flatpak/index.js +23 -0
  11. package/lib/commands/flatpak/init.d.ts +15 -0
  12. package/lib/commands/flatpak/init.js +154 -0
  13. package/lib/commands/flatpak/utils.d.ts +32 -0
  14. package/lib/commands/flatpak/utils.js +63 -0
  15. package/lib/commands/gsettings.d.ts +9 -0
  16. package/lib/commands/gsettings.js +72 -0
  17. package/lib/commands/index.d.ts +2 -0
  18. package/lib/commands/index.js +2 -0
  19. package/lib/commands/install.d.ts +1 -0
  20. package/lib/commands/install.js +66 -11
  21. package/lib/config.js +103 -11
  22. package/lib/index.js +3 -1
  23. package/lib/types/cli-build-options.d.ts +1 -1
  24. package/lib/types/config-data.d.ts +194 -4
  25. package/lib/utils/install-global.d.ts +54 -0
  26. package/lib/utils/install-global.js +153 -0
  27. package/lib/utils/normalize-bundler-options.d.ts +17 -0
  28. package/lib/utils/normalize-bundler-options.js +123 -0
  29. package/lib/utils/resolve-plugin-by-name.d.ts +21 -0
  30. package/lib/utils/resolve-plugin-by-name.js +75 -0
  31. package/package.json +11 -11
  32. package/src/actions/build.ts +406 -352
  33. package/src/commands/flatpak/build.ts +225 -0
  34. package/src/commands/flatpak/ci.ts +173 -0
  35. package/src/commands/flatpak/deps.ts +120 -0
  36. package/src/commands/flatpak/index.ts +53 -0
  37. package/src/commands/flatpak/init.ts +191 -0
  38. package/src/commands/flatpak/utils.ts +76 -0
  39. package/src/commands/gsettings.ts +87 -0
  40. package/src/commands/index.ts +2 -0
  41. package/src/commands/install.ts +90 -11
  42. package/src/config.ts +103 -11
  43. package/src/index.ts +4 -0
  44. package/src/types/cli-build-options.ts +1 -1
  45. package/src/types/config-data.ts +191 -4
  46. package/src/utils/install-global.ts +182 -0
  47. package/src/utils/normalize-bundler-options.ts +129 -0
  48. package/src/utils/resolve-plugin-by-name.ts +106 -0
@@ -1,12 +1,11 @@
1
1
  import type { ConfigData } from "../types/index.js";
2
- import type { App } from "@gjsify/esbuild-plugin-gjsify";
3
- import { BuildOptions, BuildResult, Plugin } from "esbuild";
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<BuildResult<BuildOptions>[]>;
8
+ buildLibrary(): Promise<RolldownOutput[]>;
10
9
  /**
11
10
  * Parse the `--globals` value into { autoMode, extras }.
12
11
  * - `auto` → { autoMode: true, extras: '' }
@@ -19,104 +18,26 @@ 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 esbuild plugin will append to its `inject` list. Only runs
23
- * for `--app gjs` — Node and browser builds rely on native globals.
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 two-pass build.
25
+ * The auto path is handled in `buildApp` via the iterative multi-pass build.
27
26
  */
28
27
  private resolveGlobalsInject;
29
28
  /**
30
- * Post-processing: prepend GJS shebang and mark the output file executable.
31
- * Only runs for GJS app builds with a resolvable single outfile.
29
+ * Post-processing: prepend the resolved shebang line and mark the
30
+ * output executable. Only runs for GJS app builds with a single outfile.
31
+ * The shebang plugin in `@gjsify/rolldown-plugin-gjsify` already injects
32
+ * during bundling — this hook is the safety net for anything that
33
+ * bypassed the plugin (e.g. user-supplied banners that out-ordered it),
34
+ * plus the chmod.
32
35
  */
33
36
  private applyShebang;
34
37
  /** Application mode */
35
- buildApp(app?: App): Promise<BuildResult<{
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
- }>[]>;
38
+ buildApp(app?: App): Promise<RolldownOutput[]>;
118
39
  start(buildType?: {
119
40
  library?: boolean;
120
41
  app?: App;
121
- }): Promise<BuildResult<BuildOptions>[]>;
42
+ }): Promise<RolldownOutput[]>;
122
43
  }
@@ -1,11 +1,12 @@
1
- import { build } from "esbuild";
2
- import { gjsifyPlugin } from "@gjsify/esbuild-plugin-gjsify";
3
- import { resolveGlobalsList, writeRegisterInjectFile, detectAutoGlobals, } from "@gjsify/esbuild-plugin-gjsify/globals";
4
- import { getBundleDir, rewriteContents } from "@gjsify/esbuild-plugin-gjsify";
5
- import { getPnpPlugin } from "@gjsify/resolve-npm/pnp-relay";
1
+ import { rolldown } from "rolldown";
2
+ import { gjsifyPlugin, textLoaderPlugin, resolveShebangLine } from "@gjsify/rolldown-plugin-gjsify";
3
+ import { resolveUserPlugins } from "../utils/resolve-plugin-by-name.js";
4
+ import { resolveGlobalsList, writeRegisterInjectFile, detectAutoGlobals, } from "@gjsify/rolldown-plugin-gjsify/globals";
5
+ import { pnpPlugin } from "@gjsify/rolldown-plugin-pnp";
6
6
  import { dirname, extname } from "node:path";
7
7
  import { chmod, readFile, writeFile } from "node:fs/promises";
8
- const GJS_SHEBANG = "#!/usr/bin/env -S gjs -m\n";
8
+ import { normalizeBundlerOptions, mergeBundlerOptions } from "../utils/normalize-bundler-options.js";
9
+ const DEFAULT_GJS_SHEBANG = "#!/usr/bin/env -S gjs -m";
9
10
  /**
10
11
  * `true` when `path` points at a location that's unsafe to use as a build
11
12
  * outfile (would overwrite source). Currently catches:
@@ -26,104 +27,81 @@ function isUnsafeDefaultOutput(path) {
26
27
  * @gjsify/{node,web}-polyfills) are resolvable for external consumers without
27
28
  * each one having to be a direct devDep.
28
29
  *
29
- * Wires the @gjsify/esbuild-plugin-gjsify rewriter (`__filename`/`__dirname`
30
- * injection for CJS code in node_modules) into the pnp plugin's onLoad
31
- * esbuild stops at the first matching onLoad, so the rewriter MUST run from
32
- * inside the pnp plugin's onLoad rather than as a separate registration.
30
+ * The path rewriter (`__filename`/`__dirname` + `import.meta.url` injection
31
+ * for node_modules code) is registered separately by the orchestrator
32
+ * Rolldown's transform hooks all run sequentially, no shared `onLoad` race.
33
33
  */
34
34
  async function buildPnpPlugin() {
35
- return getPnpPlugin({
36
- issuerUrl: import.meta.url,
37
- transformContentsFactory: (build) => {
38
- const bundleDir = getBundleDir(build);
39
- return (args, contents) => rewriteContents(args, contents, bundleDir);
40
- },
41
- });
35
+ return pnpPlugin({ issuerUrl: import.meta.url });
42
36
  }
43
37
  export class BuildAction {
44
38
  configData;
45
39
  constructor(configData = {}) {
46
40
  this.configData = configData;
47
41
  }
48
- getEsBuildDefaults() {
49
- const defaults = {
50
- allowOverwrite: true,
51
- };
52
- return defaults;
53
- }
54
42
  /** Library mode */
55
43
  async buildLibrary() {
56
- let { verbose, library, esbuild, typescript, exclude } = this.configData;
57
- library ||= {};
58
- esbuild ||= {};
59
- typescript ||= {};
60
- const moduleOutdir = library?.module ? dirname(library.module) : undefined;
61
- const mainOutdir = library?.main ? dirname(library.main) : undefined;
62
- const moduleOutExt = library.module ? extname(library.module) : ".js";
63
- const mainOutExt = library.main ? extname(library.main) : ".js";
44
+ const { verbose, library, typescript, exclude, aliases } = this.configData;
45
+ const lib = library ?? {};
46
+ const userBundler = normalizeBundlerOptions(this.configData);
47
+ const moduleOutdir = lib.module ? dirname(lib.module) : undefined;
48
+ const mainOutdir = lib.main ? dirname(lib.main) : undefined;
49
+ const moduleOutExt = lib.module ? extname(lib.module) : ".js";
50
+ const mainOutExt = lib.main ? extname(lib.main) : ".js";
64
51
  const multipleBuilds = moduleOutdir && mainOutdir && moduleOutdir !== mainOutdir;
65
- const pnpPlugin = await buildPnpPlugin();
66
- const pnpPlugins = pnpPlugin ? [pnpPlugin] : [];
52
+ const pnp = await buildPnpPlugin();
53
+ const pnpPlugins = pnp ? [pnp] : [];
67
54
  const results = [];
68
55
  if (multipleBuilds) {
69
56
  const moduleFormat = moduleOutdir.includes("/cjs") || moduleOutExt === ".cjs"
70
57
  ? "cjs"
71
58
  : "esm";
72
- results.push(await build({
73
- ...this.getEsBuildDefaults(),
74
- ...esbuild,
75
- format: moduleFormat,
76
- outdir: moduleOutdir,
77
- plugins: [
78
- ...pnpPlugins,
79
- gjsifyPlugin({
80
- debug: verbose,
81
- library: moduleFormat,
82
- exclude,
83
- reflection: typescript?.reflection,
84
- jsExtension: moduleOutExt,
85
- }),
86
- ],
59
+ results.push(await runOneLibraryBuild({
60
+ pluginOpts: {
61
+ debug: verbose,
62
+ library: moduleFormat,
63
+ exclude,
64
+ reflection: typescript?.reflection,
65
+ jsExtension: moduleOutExt,
66
+ },
67
+ userBundler,
68
+ output: { dir: moduleOutdir },
69
+ userAliases: aliases,
70
+ pnpPlugins,
87
71
  }));
88
72
  const mainFormat = mainOutdir.includes("/cjs") || mainOutExt === ".cjs" ? "cjs" : "esm";
89
- results.push(await build({
90
- ...this.getEsBuildDefaults(),
91
- ...esbuild,
92
- format: mainFormat,
93
- outdir: mainOutdir,
94
- plugins: [
95
- ...pnpPlugins,
96
- gjsifyPlugin({
97
- debug: verbose,
98
- library: mainFormat,
99
- exclude,
100
- reflection: typescript?.reflection,
101
- jsExtension: mainOutExt,
102
- }),
103
- ],
73
+ results.push(await runOneLibraryBuild({
74
+ pluginOpts: {
75
+ debug: verbose,
76
+ library: mainFormat,
77
+ exclude,
78
+ reflection: typescript?.reflection,
79
+ jsExtension: mainOutExt,
80
+ },
81
+ userBundler,
82
+ output: { dir: mainOutdir },
83
+ userAliases: aliases,
84
+ pnpPlugins,
104
85
  }));
105
86
  }
106
87
  else {
107
- const outfilePath = esbuild?.outfile || library?.module || library?.main;
88
+ const outfilePath = userBundler.output?.file ?? lib.module ?? lib.main;
108
89
  const outExt = outfilePath ? extname(outfilePath) : ".js";
109
- const outdir = esbuild?.outdir || (outfilePath ? dirname(outfilePath) : undefined);
110
- const format = esbuild?.format ??
90
+ const outdir = userBundler.output?.dir ?? (outfilePath ? dirname(outfilePath) : undefined);
91
+ const format = userBundler.output?.format ??
111
92
  (outdir?.includes("/cjs") || outExt === ".cjs" ? "cjs" : "esm");
112
- results.push(await build({
113
- ...this.getEsBuildDefaults(),
114
- ...esbuild,
115
- format,
116
- outdir,
117
- plugins: [
118
- ...pnpPlugins,
119
- gjsifyPlugin({
120
- debug: verbose,
121
- library: format,
122
- exclude,
123
- reflection: typescript?.reflection,
124
- jsExtension: outExt,
125
- }),
126
- ],
93
+ results.push(await runOneLibraryBuild({
94
+ pluginOpts: {
95
+ debug: verbose,
96
+ library: format,
97
+ exclude,
98
+ reflection: typescript?.reflection,
99
+ jsExtension: outExt,
100
+ },
101
+ userBundler,
102
+ output: { dir: outdir },
103
+ userAliases: aliases,
104
+ pnpPlugins,
127
105
  }));
128
106
  }
129
107
  return results;
@@ -152,11 +130,11 @@ export class BuildAction {
152
130
  }
153
131
  /**
154
132
  * Resolve the `--globals` CLI list into a pre-computed inject stub path
155
- * that the esbuild plugin will append to its `inject` list. Only runs
156
- * for `--app gjs` — Node and browser builds rely on native globals.
133
+ * that the orchestrator appends to its input list. Only runs for
134
+ * `--app gjs` — Node and browser builds rely on native globals.
157
135
  *
158
136
  * Used only for the explicit-only path (no `auto` token in the value).
159
- * The auto path is handled in `buildApp` via the two-pass build.
137
+ * The auto path is handled in `buildApp` via the iterative multi-pass build.
160
138
  */
161
139
  async resolveGlobalsInject(app, globals, verbose) {
162
140
  if (app !== "gjs")
@@ -173,8 +151,12 @@ export class BuildAction {
173
151
  return injectPath ?? undefined;
174
152
  }
175
153
  /**
176
- * Post-processing: prepend GJS shebang and mark the output file executable.
177
- * Only runs for GJS app builds with a resolvable single outfile.
154
+ * Post-processing: prepend the resolved shebang line and mark the
155
+ * output executable. Only runs for GJS app builds with a single outfile.
156
+ * The shebang plugin in `@gjsify/rolldown-plugin-gjsify` already injects
157
+ * during bundling — this hook is the safety net for anything that
158
+ * bypassed the plugin (e.g. user-supplied banners that out-ordered it),
159
+ * plus the chmod.
178
160
  */
179
161
  async applyShebang(outfile, verbose) {
180
162
  if (!outfile) {
@@ -182,44 +164,49 @@ export class BuildAction {
182
164
  console.warn("[gjsify] --shebang skipped: no single outfile (use --outfile for GJS executables)");
183
165
  return;
184
166
  }
167
+ const line = resolveShebangLine(this.configData.shebang) ?? DEFAULT_GJS_SHEBANG;
185
168
  const content = await readFile(outfile, "utf-8");
186
169
  if (content.startsWith("#!")) {
187
170
  if (verbose)
188
171
  console.debug(`[gjsify] --shebang skipped: ${outfile} already starts with a shebang`);
189
172
  }
190
173
  else {
191
- await writeFile(outfile, GJS_SHEBANG + content);
174
+ await writeFile(outfile, line + "\n" + content);
192
175
  }
193
176
  await chmod(outfile, 0o755);
194
177
  if (verbose)
195
- console.debug(`[gjsify] --shebang: wrote shebang + chmod 0o755 to ${outfile}`);
178
+ console.debug(`[gjsify] --shebang: wrote ${line} + chmod 0o755 to ${outfile}`);
196
179
  }
197
180
  /** Application mode */
198
181
  async buildApp(app = "gjs") {
199
- const { verbose, esbuild, typescript, exclude, library: pgk, aliases, excludeGlobals, } = this.configData;
200
- const format = esbuild?.format ??
201
- (esbuild?.outfile?.endsWith(".cjs") ? "cjs" : "esm");
182
+ const { verbose, typescript, exclude, library: pkg, aliases, excludeGlobals, } = this.configData;
183
+ const userBundler = normalizeBundlerOptions(this.configData);
184
+ const formatRaw = userBundler.output?.format ??
185
+ (userBundler.output?.file?.endsWith(".cjs") ? "cjs" : "esm");
186
+ // The orchestrator only handles esm/cjs (iife is not a GJS / Node /
187
+ // browser-bundle target we support). Coerce.
188
+ const format = formatRaw === "iife" ? "esm" : formatRaw;
202
189
  // Set default outfile if no outdir is set
203
- if (esbuild &&
204
- !esbuild?.outfile &&
205
- !esbuild?.outdir &&
206
- (pgk?.main || pgk?.module)) {
207
- const candidate = esbuild?.format === "cjs"
208
- ? pgk.main || pgk.module
209
- : pgk.module || pgk.main;
190
+ let outfile = userBundler.output?.file;
191
+ let outdir = userBundler.output?.dir;
192
+ if (!outfile && !outdir && (pkg?.main || pkg?.module)) {
193
+ const candidate = format === "cjs"
194
+ ? pkg.main ?? pkg.module
195
+ : pkg.module ?? pkg.main;
210
196
  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
197
  throw new Error(`gjsify build: refusing to default --outfile to ${candidate} ` +
217
198
  `(would overwrite a TypeScript source file). Pass --outfile/--outdir ` +
218
- `explicitly, or set "gjsify.esbuild.outfile" in package.json.`);
199
+ `explicitly, or set "gjsify.bundler.output.file" in package.json.`);
219
200
  }
220
- esbuild.outfile = candidate;
201
+ outfile = candidate;
221
202
  }
222
203
  const { consoleShim, globals } = this.configData;
204
+ const userExternal = Array.isArray(userBundler.external)
205
+ ? userBundler.external
206
+ : undefined;
207
+ const userBanner = typeof userBundler.output?.banner === "string"
208
+ ? userBundler.output.banner
209
+ : undefined;
223
210
  const pluginOpts = {
224
211
  debug: verbose,
225
212
  app,
@@ -230,65 +217,106 @@ export class BuildAction {
230
217
  ...(aliases ? { aliases } : {}),
231
218
  };
232
219
  const { autoMode, extras } = this.parseGlobalsValue(globals);
233
- const pnpPlugin = await buildPnpPlugin();
234
- const pnpPlugins = pnpPlugin ? [pnpPlugin] : [];
220
+ const pnp = await buildPnpPlugin();
221
+ const pnpPlugins = pnp ? [pnp] : [];
222
+ // User-supplied text loaders need to be available during BOTH the
223
+ // auto-globals pre-build (`detectAutoGlobals`) and the final build —
224
+ // otherwise Rolldown's parser hits unknown extensions like `.ui` /
225
+ // `.asm` during the pre-build, fails to parse them as JS/JSX, and
226
+ // the auto-globals iteration aborts before the final plugin chain is
227
+ // ever assembled. Build the user-plugin chain once, up front, and
228
+ // pass it into both passes.
229
+ const userTextLoader = textLoaderPlugin({ loaders: this.configData.loaders });
230
+ const userPlugins = userTextLoader ? [userTextLoader] : [];
231
+ // User-supplied bundler.plugins (mix of plugin objects + by-name
232
+ // entries) — resolved from the project's node_modules. Same
233
+ // ordering rationale as the text loader: must be present during
234
+ // auto-globals pre-build to avoid claiming the same files via
235
+ // Rolldown's default classifier.
236
+ if (userBundler.plugins?.length) {
237
+ const resolved = await resolveUserPlugins(userBundler.plugins, process.cwd());
238
+ userPlugins.push(...resolved);
239
+ }
235
240
  // --- 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
241
  if (app === "gjs" && autoMode) {
242
+ const gjsifyPluginFactory = async (opts) => {
243
+ const cfg = await gjsifyPlugin({
244
+ input: userBundler.input,
245
+ output: { file: outfile, dir: outdir },
246
+ userExternal,
247
+ userBanner,
248
+ userAliases: aliases,
249
+ shebang: this.configData.shebang,
250
+ }, opts);
251
+ return cfg.plugins;
252
+ };
240
253
  const { injectPath } = await detectAutoGlobals({
241
- ...this.getEsBuildDefaults(),
242
- ...esbuild,
254
+ input: userBundler.input,
255
+ plugins: [...pnpPlugins, ...userPlugins],
256
+ external: userBundler.external,
257
+ transform: userBundler.transform,
243
258
  format,
244
- plugins: pnpPlugins,
245
- }, pluginOpts, verbose, { extraGlobalsList: extras, excludeGlobals });
246
- const result = await build({
247
- ...this.getEsBuildDefaults(),
248
- ...esbuild,
249
- format,
250
- plugins: [
251
- ...pnpPlugins,
252
- gjsifyPlugin({
253
- ...pluginOpts,
254
- autoGlobalsInject: injectPath,
255
- }),
256
- ],
257
- });
258
- if (app === "gjs" && this.configData.shebang) {
259
- await this.applyShebang(esbuild?.outfile, verbose);
260
- }
261
- return [result];
259
+ }, pluginOpts, gjsifyPluginFactory, verbose, { extraGlobalsList: extras, excludeGlobals });
260
+ pluginOpts.autoGlobalsInject = injectPath;
261
+ }
262
+ else if (extras) {
263
+ pluginOpts.autoGlobalsInject = await this.resolveGlobalsInject(app, extras, verbose);
264
+ }
265
+ // Final build: orchestrator → rolldown → write
266
+ const cfg = await gjsifyPlugin({
267
+ input: userBundler.input,
268
+ output: { file: outfile, dir: outdir },
269
+ userExternal,
270
+ userBanner,
271
+ userAliases: aliases,
272
+ shebang: this.configData.shebang,
273
+ }, pluginOpts);
274
+ const merged = mergeBundlerOptions(cfg.options, userBundler);
275
+ const finalOpts = {
276
+ ...merged,
277
+ // Drop user-config plugins from `merged` — they survived
278
+ // mergeBundlerOptions via spread but have already been resolved
279
+ // and appended into `userPlugins` above. Re-emitting the raw
280
+ // entries (which may include `BundlerPluginByName` shapes
281
+ // Rolldown doesn't understand) would crash the build.
282
+ plugins: [...pnpPlugins, ...userPlugins, ...cfg.plugins],
283
+ };
284
+ const build = await rolldown(finalOpts);
285
+ let writeResult;
286
+ try {
287
+ writeResult = await build.write(finalOpts.output ?? {});
288
+ }
289
+ finally {
290
+ await build.close();
262
291
  }
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
292
  if (app === "gjs" && this.configData.shebang) {
280
- await this.applyShebang(esbuild?.outfile, verbose);
293
+ await this.applyShebang(outfile, verbose);
281
294
  }
282
- return [result];
295
+ return [writeResult];
283
296
  }
284
297
  async start(buildType = { app: "gjs" }) {
285
- const results = [];
286
298
  if (buildType.library) {
287
- results.push(...(await this.buildLibrary()));
288
- }
289
- else {
290
- results.push(...(await this.buildApp(buildType.app)));
299
+ return await this.buildLibrary();
291
300
  }
292
- return results;
301
+ return await this.buildApp(buildType.app);
302
+ }
303
+ }
304
+ async function runOneLibraryBuild(args) {
305
+ const cfg = await gjsifyPlugin({
306
+ input: args.userBundler.input,
307
+ output: args.output,
308
+ userAliases: args.userAliases,
309
+ }, args.pluginOpts);
310
+ const merged = mergeBundlerOptions(cfg.options, args.userBundler);
311
+ const finalOpts = {
312
+ ...merged,
313
+ plugins: [...args.pnpPlugins, ...cfg.plugins],
314
+ };
315
+ const build = await rolldown(finalOpts);
316
+ try {
317
+ return await build.write(finalOpts.output ?? {});
318
+ }
319
+ finally {
320
+ await build.close();
293
321
  }
294
322
  }
@@ -0,0 +1,16 @@
1
+ import type { Command } from '../../types/index.js';
2
+ interface FlatpakBuildOptions {
3
+ manifest?: string;
4
+ buildDir?: string;
5
+ install?: boolean;
6
+ repo?: string;
7
+ bundle?: string;
8
+ tarball?: string;
9
+ forceClean?: boolean;
10
+ sandbox?: boolean;
11
+ deleteBuildDirs?: boolean;
12
+ installDepsFrom?: string;
13
+ verbose?: boolean;
14
+ }
15
+ export declare const flatpakBuildCommand: Command<unknown, FlatpakBuildOptions>;
16
+ export {};