@gjsify/cli 0.4.28 → 0.4.30

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 (82) hide show
  1. package/dist/cli.gjs.mjs +132 -132
  2. package/lib/actions/barrels-generate.js +1 -5
  3. package/lib/actions/build.d.ts +3 -3
  4. package/lib/actions/build.js +56 -64
  5. package/lib/bundler-pick.d.ts +3 -3
  6. package/lib/bundler-pick.js +5 -6
  7. package/lib/commands/build.d.ts +1 -1
  8. package/lib/commands/build.js +37 -31
  9. package/lib/commands/check.js +3 -3
  10. package/lib/commands/create.d.ts +1 -1
  11. package/lib/commands/dlx.d.ts +1 -1
  12. package/lib/commands/fix.js +33 -23
  13. package/lib/commands/flatpak/build.js +6 -2
  14. package/lib/commands/flatpak/check.js +9 -3
  15. package/lib/commands/flatpak/ci.js +1 -2
  16. package/lib/commands/flatpak/deps.js +1 -2
  17. package/lib/commands/flatpak/diff.js +2 -6
  18. package/lib/commands/flatpak/init.js +19 -19
  19. package/lib/commands/flatpak/release.js +2 -2
  20. package/lib/commands/flatpak/scaffold.js +3 -11
  21. package/lib/commands/flatpak/sync-flathub.js +5 -9
  22. package/lib/commands/flatpak/utils.js +1 -6
  23. package/lib/commands/foreach.d.ts +1 -1
  24. package/lib/commands/foreach.js +5 -14
  25. package/lib/commands/format.js +54 -41
  26. package/lib/commands/generate-installer.d.ts +1 -1
  27. package/lib/commands/gettext.d.ts +1 -1
  28. package/lib/commands/gettext.js +8 -15
  29. package/lib/commands/gresource.d.ts +1 -1
  30. package/lib/commands/gresource.js +8 -13
  31. package/lib/commands/gsettings.d.ts +1 -1
  32. package/lib/commands/gsettings.js +7 -8
  33. package/lib/commands/info.d.ts +1 -1
  34. package/lib/commands/install.d.ts +1 -1
  35. package/lib/commands/install.js +45 -13
  36. package/lib/commands/lint.d.ts +1 -1
  37. package/lib/commands/lint.js +22 -22
  38. package/lib/commands/pack.d.ts +1 -1
  39. package/lib/commands/pack.js +29 -17
  40. package/lib/commands/publish.d.ts +1 -1
  41. package/lib/commands/publish.js +17 -18
  42. package/lib/commands/run.d.ts +1 -1
  43. package/lib/commands/run.js +2 -6
  44. package/lib/commands/self-update.d.ts +1 -1
  45. package/lib/commands/self-update.js +1 -3
  46. package/lib/commands/showcase.d.ts +1 -1
  47. package/lib/commands/showcase.js +1 -1
  48. package/lib/commands/system-check.d.ts +1 -1
  49. package/lib/commands/system-check.js +8 -11
  50. package/lib/commands/test.js +12 -8
  51. package/lib/commands/uninstall.d.ts +1 -1
  52. package/lib/commands/uninstall.js +1 -3
  53. package/lib/commands/upgrade.d.ts +1 -1
  54. package/lib/commands/upgrade.js +109 -120
  55. package/lib/commands/workspace.d.ts +1 -1
  56. package/lib/commands/workspace.js +1 -3
  57. package/lib/config.js +18 -13
  58. package/lib/index.js +3 -1
  59. package/lib/templates/install.mjs.tmpl +20 -14
  60. package/lib/templates/oxfmtrc.tmpl +54 -0
  61. package/lib/templates/oxlintrc.json.tmpl +35 -0
  62. package/lib/types/command.d.ts +1 -1
  63. package/lib/types/config-data.d.ts +23 -13
  64. package/lib/types/cosmiconfig-result.d.ts +1 -1
  65. package/lib/utils/check-system-deps.js +10 -4
  66. package/lib/utils/detect-native-packages.js +1 -1
  67. package/lib/utils/dlx-cache.js +2 -7
  68. package/lib/utils/install-backend-native.d.ts +2 -2
  69. package/lib/utils/install-backend-native.js +112 -58
  70. package/lib/utils/install-backend.js +2 -1
  71. package/lib/utils/install-global.js +1 -3
  72. package/lib/utils/normalize-bundler-options.js +52 -17
  73. package/lib/utils/oxc-resolve.d.ts +63 -0
  74. package/lib/utils/oxc-resolve.js +264 -0
  75. package/lib/utils/pkg-json-edit.js +1 -6
  76. package/lib/utils/run-gjs.js +1 -4
  77. package/lib/utils/run-lifecycle-script.js +3 -7
  78. package/lib/utils/workspace-root.js +3 -1
  79. package/package.json +17 -17
  80. package/lib/templates/biome.json.tmpl +0 -79
  81. package/lib/utils/biome-resolve.d.ts +0 -47
  82. package/lib/utils/biome-resolve.js +0 -204
@@ -28,13 +28,7 @@ async function fileExists(path) {
28
28
  async function compileBulkXml(opts) {
29
29
  const outputFile = join(opts.outDir, opts.filename);
30
30
  await ensureDir(opts.outDir);
31
- const args = [
32
- `--output-file=${outputFile}`,
33
- '--xml',
34
- `--template=${opts.template}`,
35
- '-d',
36
- opts.poDir,
37
- ];
31
+ const args = [`--output-file=${outputFile}`, '--xml', `--template=${opts.template}`, '-d', opts.poDir];
38
32
  if (opts.verbose) {
39
33
  console.log(`[gjsify gettext] msgfmt ${args.join(' ')}`);
40
34
  }
@@ -55,9 +49,7 @@ async function compilePerLanguage(opts) {
55
49
  }
56
50
  for (const lang of languages) {
57
51
  const poFile = join(opts.poDir, `${lang}.po`);
58
- const langDir = opts.format === 'mo'
59
- ? join(opts.outDir, lang, 'LC_MESSAGES')
60
- : join(opts.outDir, lang);
52
+ const langDir = opts.format === 'mo' ? join(opts.outDir, lang, 'LC_MESSAGES') : join(opts.outDir, lang);
61
53
  await ensureDir(langDir);
62
54
  const outputFile = join(langDir, opts.filename);
63
55
  // msgfmt produces the binary .mo format by default — there is no
@@ -187,15 +179,16 @@ export const gettextCommand = {
187
179
  }
188
180
  }
189
181
  catch (err) {
190
- if (err?.code === 'ENOENT') {
182
+ const e = err;
183
+ if (e?.code === 'ENOENT') {
191
184
  console.error('[gjsify gettext] msgfmt not found. Install it via your distro (package: gettext).');
192
185
  }
193
186
  else {
194
- if (err?.stderr)
195
- process.stderr.write(err.stderr);
196
- console.error(`[gjsify gettext] msgfmt failed${err?.code !== undefined ? ` (exit ${err.code})` : ''}`);
187
+ if (e?.stderr)
188
+ process.stderr.write(e.stderr);
189
+ console.error(`[gjsify gettext] msgfmt failed${e?.code !== undefined ? ` (exit ${e.code})` : ''}`);
197
190
  }
198
- process.exitCode = typeof err?.code === 'number' ? err.code : 1;
191
+ process.exitCode = typeof e?.code === 'number' ? e.code : 1;
199
192
  }
200
193
  },
201
194
  };
@@ -5,5 +5,5 @@ interface GResourceOptions {
5
5
  target?: string;
6
6
  verbose?: boolean;
7
7
  }
8
- export declare const gresourceCommand: Command<any, GResourceOptions>;
8
+ export declare const gresourceCommand: Command<unknown, GResourceOptions>;
9
9
  export {};
@@ -43,14 +43,8 @@ export const gresourceCommand = {
43
43
  handler: async (args) => {
44
44
  const xmlPath = resolve(args.xml);
45
45
  const target = args.target ? resolve(args.target) : defaultTargetFor(xmlPath);
46
- const sourcedir = args.sourcedir
47
- ? resolve(args.sourcedir)
48
- : dirname(xmlPath);
49
- const cmdArgs = [
50
- `--sourcedir=${sourcedir}`,
51
- `--target=${target}`,
52
- xmlPath,
53
- ];
46
+ const sourcedir = args.sourcedir ? resolve(args.sourcedir) : dirname(xmlPath);
47
+ const cmdArgs = [`--sourcedir=${sourcedir}`, `--target=${target}`, xmlPath];
54
48
  if (args.verbose) {
55
49
  console.log(`[gjsify gresource] glib-compile-resources ${cmdArgs.join(' ')}`);
56
50
  }
@@ -68,15 +62,16 @@ export const gresourceCommand = {
68
62
  }
69
63
  }
70
64
  catch (err) {
71
- if (err?.code === 'ENOENT') {
65
+ const e = err;
66
+ if (e?.code === 'ENOENT') {
72
67
  console.error('[gjsify gresource] glib-compile-resources not found. Install it via your distro (package: glib2-devel / libglib2.0-dev).');
73
68
  }
74
69
  else {
75
- if (err?.stderr)
76
- process.stderr.write(err.stderr);
77
- console.error(`[gjsify gresource] glib-compile-resources failed${err?.code !== undefined ? ` (exit ${err.code})` : ''}`);
70
+ if (e?.stderr)
71
+ process.stderr.write(e.stderr);
72
+ console.error(`[gjsify gresource] glib-compile-resources failed${e?.code !== undefined ? ` (exit ${e.code})` : ''}`);
78
73
  }
79
- process.exitCode = typeof err?.code === 'number' ? err.code : 1;
74
+ process.exitCode = typeof e?.code === 'number' ? e.code : 1;
80
75
  }
81
76
  },
82
77
  };
@@ -5,5 +5,5 @@ interface GSettingsOptions {
5
5
  strict?: boolean;
6
6
  verbose?: boolean;
7
7
  }
8
- export declare const gsettingsCommand: Command<any, GSettingsOptions>;
8
+ export declare const gsettingsCommand: Command<unknown, GSettingsOptions>;
9
9
  export {};
@@ -33,9 +33,7 @@ export const gsettingsCommand = {
33
33
  },
34
34
  handler: async (args) => {
35
35
  const schemadir = resolve(args.schemadir);
36
- const targetdir = args.targetdir
37
- ? resolve(args.targetdir)
38
- : schemadir;
36
+ const targetdir = args.targetdir ? resolve(args.targetdir) : schemadir;
39
37
  const cmdArgs = [];
40
38
  if (args.strict)
41
39
  cmdArgs.push('--strict');
@@ -58,15 +56,16 @@ export const gsettingsCommand = {
58
56
  }
59
57
  }
60
58
  catch (err) {
61
- if (err?.code === 'ENOENT') {
59
+ const e = err;
60
+ if (e?.code === 'ENOENT') {
62
61
  console.error('[gjsify gsettings] glib-compile-schemas not found. Install it via your distro (package: glib2-devel / libglib2.0-dev).');
63
62
  }
64
63
  else {
65
- if (err?.stderr)
66
- process.stderr.write(err.stderr);
67
- console.error(`[gjsify gsettings] glib-compile-schemas failed${err?.code !== undefined ? ` (exit ${err.code})` : ''}`);
64
+ if (e?.stderr)
65
+ process.stderr.write(e.stderr);
66
+ console.error(`[gjsify gsettings] glib-compile-schemas failed${e?.code !== undefined ? ` (exit ${e.code})` : ''}`);
68
67
  }
69
- process.exitCode = typeof err?.code === 'number' ? err.code : 1;
68
+ process.exitCode = typeof e?.code === 'number' ? e.code : 1;
70
69
  }
71
70
  },
72
71
  };
@@ -3,5 +3,5 @@ interface InfoOptions {
3
3
  export: boolean;
4
4
  file?: string;
5
5
  }
6
- export declare const infoCommand: Command<any, InfoOptions>;
6
+ export declare const infoCommand: Command<unknown, InfoOptions>;
7
7
  export {};
@@ -9,5 +9,5 @@ interface InstallOptions {
9
9
  verbose: boolean;
10
10
  backend?: 'native' | 'npm';
11
11
  }
12
- export declare const installCommand: Command<any, InstallOptions>;
12
+ export declare const installCommand: Command<unknown, InstallOptions>;
13
13
  export {};
@@ -22,10 +22,10 @@ import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, rmSync, syml
22
22
  import { dirname, join, relative } from 'node:path';
23
23
  import { spawn } from 'node:child_process';
24
24
  import { discoverWorkspaces } from '@gjsify/workspace';
25
- import { buildInstallCommand, detectPackageManager, runMinimalChecks, } from '../utils/check-system-deps.js';
25
+ import { buildInstallCommand, detectPackageManager, runMinimalChecks } from '../utils/check-system-deps.js';
26
26
  import { detectNativePackages } from '../utils/detect-native-packages.js';
27
27
  import { installPackages } from '../utils/install-backend.js';
28
- import { binDirOnPath, defaultGlobalLayout, linkGlobalBins, specToPackageName, } from '../utils/install-global.js';
28
+ import { binDirOnPath, defaultGlobalLayout, linkGlobalBins, specToPackageName } from '../utils/install-global.js';
29
29
  import { addDependencyEntry, defaultRangeFromVersion, parseSpec, projectSpecsFromPackageJson, readPackageJson, writePackageJson, } from '../utils/pkg-json-edit.js';
30
30
  export const installCommand = {
31
31
  command: 'install [packages..]',
@@ -265,14 +265,39 @@ async function workspaceInstall(cwd, args) {
265
265
  for (const [depName, spec] of Object.entries(block)) {
266
266
  if (typeof spec !== 'string')
267
267
  continue;
268
- if (spec.startsWith('workspace:')) {
269
- const target = byName.get(depName);
270
- if (!target) {
271
- throw new Error(`gjsify install: ${ws.name} declares "${depName}: ${spec}" but ` +
272
- `no workspace with that name exists`);
268
+ // A dependency whose NAME matches a local workspace is always
269
+ // satisfied by that workspace — never by a same-named package on
270
+ // npm. This holds regardless of the spec form: an explicit
271
+ // `workspace:` protocol, a plain semver range (`^1.2.3`), or even
272
+ // a dist-tag. Yarn/npm resolve a workspace-named dep to the local
273
+ // package first; we MUST do the same. Routing such a dep into the
274
+ // native fetch/extract queue is the data-loss bug this guards
275
+ // against — `extractOne` would `rmSync` + drop the published
276
+ // tarball over the workspace's OWN source tree (the published
277
+ // tarball ships only `files`, so `src/**` gets wiped). Symlink
278
+ // it instead, exactly like a `workspace:` ref.
279
+ const localWorkspace = byName.get(depName);
280
+ if (localWorkspace) {
281
+ // Only an EXPLICIT out-of-workspace protocol (link:/file:/
282
+ // portal:/git+/http(s):) opts out of the local workspace. Any
283
+ // other shape — `workspace:` or a plain semver range/dist-tag
284
+ // (`^1.2.3`, `*`, `latest`) — resolves to the local package.
285
+ const explicitOverride = /^(link|file|portal|git\+|https?):/.test(spec);
286
+ if (!explicitOverride) {
287
+ symlinks.push({
288
+ fromWorkspaceName: ws.name,
289
+ depName,
290
+ targetLocation: localWorkspace.location,
291
+ });
292
+ continue;
273
293
  }
274
- symlinks.push({ fromWorkspaceName: ws.name, depName, targetLocation: target.location });
275
- continue;
294
+ // explicit override fall through to the existing handling.
295
+ }
296
+ if (spec.startsWith('workspace:')) {
297
+ // `workspace:` against a name that is NOT a discovered
298
+ // workspace is a hard error (typo / missing package).
299
+ throw new Error(`gjsify install: ${ws.name} declares "${depName}: ${spec}" but ` +
300
+ `no workspace with that name exists`);
276
301
  }
277
302
  if (/^(link|file|portal|git\+|https?):/.test(spec))
278
303
  continue;
@@ -320,7 +345,8 @@ async function workspaceInstall(cwd, args) {
320
345
  try {
321
346
  rmSync(linkPath, { recursive: true, force: true });
322
347
  }
323
- catch { /* unexpected — Gio failure on a path we just lstat'd to
348
+ catch {
349
+ /* unexpected — Gio failure on a path we just lstat'd to
324
350
  decide we wanted to remove. The subsequent symlinkSync
325
351
  will surface the real reason if there is one. */
326
352
  }
@@ -367,7 +393,9 @@ async function workspaceInstall(cwd, args) {
367
393
  lstatSync(linkPath);
368
394
  existsHere = true;
369
395
  }
370
- catch { /* ENOENT */ }
396
+ catch {
397
+ /* ENOENT */
398
+ }
371
399
  if (existsHere)
372
400
  continue;
373
401
  mkdirSync(dirname(linkPath), { recursive: true });
@@ -419,8 +447,12 @@ async function workspaceInstall(cwd, args) {
419
447
  try {
420
448
  rmSync(linkPath, { force: true });
421
449
  }
422
- catch { /* fine */ }
423
- writeFileSync(linkPath, buildBinShim(ws.location, nodeTarget, gjsTarget, nativePrebuildDirs), { mode: 0o755 });
450
+ catch {
451
+ /* fine */
452
+ }
453
+ writeFileSync(linkPath, buildBinShim(ws.location, nodeTarget, gjsTarget, nativePrebuildDirs), {
454
+ mode: 0o755,
455
+ });
424
456
  chmodSync(linkPath, 0o755);
425
457
  wsBinsCreated++;
426
458
  }
@@ -1,7 +1,7 @@
1
1
  import type { Command } from '../types/index.js';
2
2
  interface LintOptions {
3
3
  paths?: string[];
4
- write?: boolean;
4
+ fix?: boolean;
5
5
  configPath?: string;
6
6
  verbose?: boolean;
7
7
  }
@@ -1,14 +1,16 @@
1
- // `gjsify lint` — wraps biome's `lint` mode.
1
+ // `gjsify lint` — wraps oxlint.
2
2
  //
3
- // Sibling of `gjsify format`. Spawns biome from node_modules directly
4
- // (no Node launcher). Default behaviour: report-only. Pass `--write`
5
- // for biome's safe-fix mode, or use `gjsify fix` for the combined
6
- // format + safe-lint-fix + organize-imports surface.
3
+ // Sibling of `gjsify format`. Spawns oxlint via its Node launcher
4
+ // (`node_modules/oxlint/bin/oxlint` `dist/cli.js`) NOT a bare binary —
5
+ // because oxlint's JS-plugin host (used by the internal
6
+ // `oxlint-plugin-gjsify` rule) lives in the JS launcher. Default behaviour:
7
+ // report-only. Pass `--fix` for oxlint's safe-fix mode, or use `gjsify fix`
8
+ // for the combined oxfmt + oxlint --fix surface.
7
9
  import { resolve } from 'node:path';
8
- import { BiomeNotFoundError, findBiomeConfig, printBiomeNotFound, runBiome, } from '../utils/biome-resolve.js';
10
+ import { OxcNotFoundError, findOxlintConfig, printOxcNotFound, runOxlint } from '../utils/oxc-resolve.js';
9
11
  export const lintCommand = {
10
12
  command: 'lint [paths..]',
11
- description: 'Run Biome lint diagnostics (native binary spawn no Node launcher).',
13
+ description: 'Run oxlint diagnostics (spawned via its Node launcher to support JS plugins).',
12
14
  builder: (yargs) => {
13
15
  return yargs
14
16
  .positional('paths', {
@@ -16,41 +18,39 @@ export const lintCommand = {
16
18
  type: 'string',
17
19
  array: true,
18
20
  })
19
- .option('write', {
21
+ .option('fix', {
20
22
  description: 'Apply safe lint fixes in place.',
21
23
  type: 'boolean',
22
24
  default: false,
23
25
  })
24
26
  .option('config-path', {
25
- description: 'Path to a biome.json. Default: walks up from cwd to find one.',
27
+ description: 'Path to an .oxlintrc.json. Default: walks up from cwd to find one.',
26
28
  type: 'string',
27
29
  normalize: true,
28
30
  })
29
31
  .option('verbose', {
30
- description: 'Echo the resolved biome binary + args before spawning.',
32
+ description: 'Echo the resolved oxlint launcher + args before spawning.',
31
33
  type: 'boolean',
32
34
  default: false,
33
35
  });
34
36
  },
35
37
  handler: async (args) => {
36
38
  const cwd = process.cwd();
37
- const paths = args.paths?.length
38
- ? args.paths
39
- : ['.'];
40
- const biomeArgs = ['lint'];
41
- if (args.write)
42
- biomeArgs.push('--write');
43
- const configPath = args.configPath ?? findBiomeConfig(cwd) ?? undefined;
39
+ const paths = args.paths?.length ? args.paths : ['.'];
40
+ const oxlintArgs = [];
41
+ if (args.fix)
42
+ oxlintArgs.push('--fix');
43
+ const configPath = args.configPath ?? findOxlintConfig(cwd) ?? undefined;
44
44
  if (configPath)
45
- biomeArgs.push(`--config-path=${resolve(configPath, '..')}`);
46
- biomeArgs.push(...paths);
45
+ oxlintArgs.push('--config', resolve(configPath));
46
+ oxlintArgs.push(...paths);
47
47
  try {
48
- const code = await runBiome(biomeArgs, { cwd, verbose: args.verbose });
48
+ const code = await runOxlint(oxlintArgs, { cwd, verbose: args.verbose });
49
49
  process.exitCode = code;
50
50
  }
51
51
  catch (err) {
52
- if (err instanceof BiomeNotFoundError) {
53
- printBiomeNotFound(err);
52
+ if (err instanceof OxcNotFoundError) {
53
+ printOxcNotFound(err);
54
54
  process.exitCode = 1;
55
55
  return;
56
56
  }
@@ -23,7 +23,7 @@ interface PackResult {
23
23
  /** Absolute path of the written .tgz, or null on --dry-run. */
24
24
  absolutePath: string | null;
25
25
  }
26
- export declare const packCommand: Command<any, PackOptions>;
26
+ export declare const packCommand: Command<unknown, PackOptions>;
27
27
  export interface PackWorkspaceOptions {
28
28
  /** Directory to write the .tgz into. Defaults to the workspace itself. */
29
29
  destination?: string;
@@ -113,15 +113,11 @@ export async function packWorkspace(wsDir, opts = {}) {
113
113
  // mutated it (e.g. a `prepack` that injects build metadata into
114
114
  // package.json fields). Rare but legal — npm pack does the same.
115
115
  const sourceAfterScripts = readFileSync(pkgPath, 'utf-8');
116
- const pkgAfterScripts = sourceAfterScripts === originalSource
117
- ? pkg
118
- : JSON.parse(sourceAfterScripts);
116
+ const pkgAfterScripts = sourceAfterScripts === originalSource ? pkg : JSON.parse(sourceAfterScripts);
119
117
  // Rewrite workspace:^/~/* deps to resolved npm version ranges, mirroring
120
118
  // yarn's auto-rewrite at publish time. Done in-memory only — the source
121
119
  // package.json on disk is never mutated by `gjsify pack`.
122
- const rewrittenPkg = opts.skipWorkspaceRewrite
123
- ? pkgAfterScripts
124
- : rewriteWorkspaceDeps(pkgAfterScripts, wsDir);
120
+ const rewrittenPkg = opts.skipWorkspaceRewrite ? pkgAfterScripts : rewriteWorkspaceDeps(pkgAfterScripts, wsDir);
125
121
  const rewrittenSource = JSON.stringify(rewrittenPkg, null, indentOf(sourceAfterScripts)) + '\n';
126
122
  // Collect files according to the package.json `files` field (or npm's
127
123
  // default set). The package.json itself is always included with the
@@ -148,9 +144,7 @@ export async function packWorkspace(wsDir, opts = {}) {
148
144
  const tarBytes = createTarball(entries);
149
145
  const gzipBytes = await gzip(tarBytes);
150
146
  // npm filename: scope replaced with leading dash. "@gjsify/foo" → "gjsify-foo".
151
- const filenameBase = name.startsWith('@')
152
- ? name.slice(1).replace('/', '-')
153
- : name;
147
+ const filenameBase = name.startsWith('@') ? name.slice(1).replace('/', '-') : name;
154
148
  const filename = `${filenameBase}-${version}.tgz`;
155
149
  const sha1 = createHash('sha1').update(gzipBytes).digest('hex');
156
150
  const sha512 = createHash('sha512').update(gzipBytes).digest('base64');
@@ -188,7 +182,9 @@ export async function packWorkspace(wsDir, opts = {}) {
188
182
  */
189
183
  function collectFiles(wsDir, pkg) {
190
184
  const always = forceIncluded(pkg);
191
- const filesField = Array.isArray(pkg.files) ? pkg.files.filter((f) => typeof f === 'string') : null;
185
+ const filesField = Array.isArray(pkg.files)
186
+ ? pkg.files.filter((f) => typeof f === 'string')
187
+ : null;
192
188
  let candidates;
193
189
  if (filesField) {
194
190
  candidates = expandFilesPatterns(wsDir, filesField);
@@ -208,12 +204,25 @@ function collectFiles(wsDir, pkg) {
208
204
  }
209
205
  return [...out].sort();
210
206
  }
211
- const ALWAYS_INCLUDED_BASENAMES = new Set(['package.json', 'README', 'README.md', 'LICENSE', 'LICENSE.md', 'NOTICE', 'NOTICE.md']);
212
207
  const NEVER_INCLUDED_BASENAMES = new Set([
213
- '.git', '.svn', '.hg', '.gitignore', '.gitattributes', '.npmrc',
214
- 'CVS', '.DS_Store', 'node_modules', '.npmignore', 'package-lock.json',
215
- 'gjsify-lock.json', 'yarn.lock', 'yarn-error.log', '.yarn',
216
- '.pnp.cjs', '.pnp.loader.mjs', 'tsconfig.tsbuildinfo',
208
+ '.git',
209
+ '.svn',
210
+ '.hg',
211
+ '.gitignore',
212
+ '.gitattributes',
213
+ '.npmrc',
214
+ 'CVS',
215
+ '.DS_Store',
216
+ 'node_modules',
217
+ '.npmignore',
218
+ 'package-lock.json',
219
+ 'gjsify-lock.json',
220
+ 'yarn.lock',
221
+ 'yarn-error.log',
222
+ '.yarn',
223
+ '.pnp.cjs',
224
+ '.pnp.loader.mjs',
225
+ 'tsconfig.tsbuildinfo',
217
226
  ]);
218
227
  function forceIncluded(pkg) {
219
228
  const out = new Set();
@@ -292,7 +301,7 @@ function loadIgnore(wsDir) {
292
301
  const npmIgnorePath = join(wsDir, '.npmignore');
293
302
  const gitIgnorePath = join(wsDir, '.gitignore');
294
303
  const patterns = [];
295
- const sourcePath = existsSync(npmIgnorePath) ? npmIgnorePath : (existsSync(gitIgnorePath) ? gitIgnorePath : null);
304
+ const sourcePath = existsSync(npmIgnorePath) ? npmIgnorePath : existsSync(gitIgnorePath) ? gitIgnorePath : null;
296
305
  if (sourcePath) {
297
306
  const lines = readFileSync(sourcePath, 'utf-8').split('\n');
298
307
  for (const raw of lines) {
@@ -319,7 +328,10 @@ function globToRegex(glob) {
319
328
  // Escape regex metachars except *,?,/
320
329
  pat = pat.replace(/[.+^${}()|[\]\\]/g, '\\$&');
321
330
  // ** → .* * → [^/]* ? → [^/]
322
- pat = pat.replace(/\*\*/g, '__DOUBLESTAR__').replace(/\*/g, '[^/]*').replace(/__DOUBLESTAR__/g, '.*');
331
+ pat = pat
332
+ .replace(/\*\*/g, '__DOUBLESTAR__')
333
+ .replace(/\*/g, '[^/]*')
334
+ .replace(/__DOUBLESTAR__/g, '.*');
323
335
  pat = pat.replace(/\?/g, '[^/]');
324
336
  return new RegExp(`^${pat}($|/)`);
325
337
  }
@@ -12,5 +12,5 @@ interface PublishOptions {
12
12
  trusted?: boolean | 'auto';
13
13
  'check-trusted'?: boolean;
14
14
  }
15
- export declare const publishCommand: Command<any, PublishOptions>;
15
+ export declare const publishCommand: Command<unknown, PublishOptions>;
16
16
  export {};
@@ -36,9 +36,9 @@
36
36
  import { existsSync, readFileSync } from 'node:fs';
37
37
  import { homedir } from 'node:os';
38
38
  import { join, resolve } from 'node:path';
39
- import { DEFAULT_REGISTRY, parseNpmrc, registryFor, buildHeaders, } from '@gjsify/npm-registry';
39
+ import { DEFAULT_REGISTRY, parseNpmrc, registryFor, buildHeaders } from '@gjsify/npm-registry';
40
40
  import { packWorkspace } from './pack.js';
41
- import { getNpmTrustedToken, hasGithubOidcEnv, OidcExchangeError, OidcUnavailableError, } from '../utils/npm-oidc.js';
41
+ import { getNpmTrustedToken, hasGithubOidcEnv, OidcExchangeError, OidcUnavailableError } from '../utils/npm-oidc.js';
42
42
  export const publishCommand = {
43
43
  command: 'publish [path]',
44
44
  description: 'Pack + upload the workspace at <path> (default: cwd) to its npm registry. Drop-in for `npm publish` with workspace:^ rewrite handled automatically.',
@@ -68,7 +68,7 @@ export const publishCommand = {
68
68
  default: false,
69
69
  })
70
70
  .option('provenance', {
71
- description: 'Pass-through flag — recorded in the payload but no signing happens (gjsify doesn\'t ship a sigstore signer yet).',
71
+ description: "Pass-through flag — recorded in the payload but no signing happens (gjsify doesn't ship a sigstore signer yet).",
72
72
  type: 'boolean',
73
73
  default: false,
74
74
  })
@@ -227,9 +227,7 @@ export const publishCommand = {
227
227
  // libnpmpublish/lib/publish.js). The full scoped filename is what
228
228
  // `npm pack` writes to disk, but the registry stores tarballs at
229
229
  // the unscoped path.
230
- const unscopedName = packed.name.includes('/')
231
- ? packed.name.slice(packed.name.indexOf('/') + 1)
232
- : packed.name;
230
+ const unscopedName = packed.name.includes('/') ? packed.name.slice(packed.name.indexOf('/') + 1) : packed.name;
233
231
  const wireFilename = `${unscopedName}-${packed.version}.tgz`;
234
232
  const tarballUrl = `${registryClean}/${packed.name}/-/${wireFilename}`;
235
233
  // 4. Build payload + PUT
@@ -255,8 +253,7 @@ export const publishCommand = {
255
253
  // OIDC is used iff GitHub OIDC env vars are present AND no
256
254
  // `NODE_AUTH_TOKEN` is set. With `NODE_AUTH_TOKEN` set the user has
257
255
  // explicitly opted into token auth, so we don't shadow their choice.
258
- const wantTrusted = trustedFlag === true ||
259
- (trustedFlag === undefined && hasGithubOidcEnv() && !process.env.NODE_AUTH_TOKEN);
256
+ const wantTrusted = trustedFlag === true || (trustedFlag === undefined && hasGithubOidcEnv() && !process.env.NODE_AUTH_TOKEN);
260
257
  let authMode = 'token';
261
258
  if (wantTrusted) {
262
259
  try {
@@ -281,9 +278,7 @@ export const publishCommand = {
281
278
  // Trusted Publisher bootstrap"). Skip such a package when
282
279
  // --tolerate-untrusted-new is set so one un-bootstrapped
283
280
  // package doesn't break the entire serialized publish loop.
284
- const isUntrustedNewPackage = err instanceof OidcExchangeError &&
285
- err.status === 404 &&
286
- /package not found/i.test(err.body);
281
+ const isUntrustedNewPackage = err instanceof OidcExchangeError && err.status === 404 && /package not found/i.test(err.body);
287
282
  if (isUntrustedNewPackage && tolerateUntrustedNew) {
288
283
  const headerMsg = `${packed.name}@${packed.version} (skipped — no Trusted Publisher on npm, see AGENTS.md "New @gjsify/* package: first-publish + Trusted Publisher bootstrap")`;
289
284
  if (args.json) {
@@ -343,8 +338,7 @@ export const publishCommand = {
343
338
  if (!otp && res.status === 401) {
344
339
  const wwwAuth = res.headers.get('www-authenticate') ?? '';
345
340
  const body401 = await res.text().catch(() => '');
346
- const needsOtp = wwwAuth.toLowerCase().split(/,\s*/).includes('otp') ||
347
- /one-time pass/i.test(body401);
341
+ const needsOtp = wwwAuth.toLowerCase().split(/,\s*/).includes('otp') || /one-time pass/i.test(body401);
348
342
  if (needsOtp) {
349
343
  // Interactive path: if stdin is a TTY, prompt and retry once.
350
344
  if (process.stdin.isTTY && process.stdout.isTTY) {
@@ -394,8 +388,7 @@ export const publishCommand = {
394
388
  // Both are intentionally tolerated under --tolerate-republish so
395
389
  // that re-running a release workflow after a partial failure does
396
390
  // not error on the already-published packages.
397
- const isRepublishConflict = res.status === 409 ||
398
- (res.status === 403 && /previously published/i.test(text));
391
+ const isRepublishConflict = res.status === 409 || (res.status === 403 && /previously published/i.test(text));
399
392
  if (isRepublishConflict && tolerate) {
400
393
  const out = {
401
394
  ok: true,
@@ -433,11 +426,15 @@ async function packWorkspaceToBytes(wsDir) {
433
426
  try {
434
427
  (await import('node:fs')).rmSync(res.absolutePath);
435
428
  }
436
- catch { /* best effort */ }
429
+ catch {
430
+ /* best effort */
431
+ }
437
432
  try {
438
433
  (await import('node:fs')).rmdirSync(tmp);
439
434
  }
440
- catch { /* best effort */ }
435
+ catch {
436
+ /* best effort */
437
+ }
441
438
  return bytes;
442
439
  }
443
440
  async function loadRewrittenManifest(wsDir, pkg) {
@@ -490,7 +487,9 @@ async function loadNpmrc(cwd) {
490
487
  // The auth-token npmrc from actions/setup-node ships
491
488
  // `_authToken=${NODE_AUTH_TOKEN}` as a literal placeholder; the env var
492
489
  // is set on the publish step.
493
- const merged = sources.join('\n').replace(/\$\{([A-Z_][A-Z0-9_]*)\}/gi, (_, name) => process.env[name] ?? '');
490
+ const merged = sources
491
+ .join('\n')
492
+ .replace(/\$\{([A-Z_][A-Z0-9_]*)\}/gi, (_, name) => process.env[name] ?? '');
494
493
  return parseNpmrc(merged);
495
494
  }
496
495
  function buildPublishPayload(opts) {
@@ -3,5 +3,5 @@ interface RunOptions {
3
3
  target: string;
4
4
  args: string[];
5
5
  }
6
- export declare const runCommand: Command<any, RunOptions>;
6
+ export declare const runCommand: Command<unknown, RunOptions>;
7
7
  export {};
@@ -108,9 +108,7 @@ async function runScript(script, extraArgs) {
108
108
  // (stdout is always a pipe there, but the GHA log viewer renders ANSI
109
109
  // fine). Respect user overrides: FORCE_COLOR=0 or NO_COLOR keeps
110
110
  // colors off.
111
- const colorEnv = process.env.FORCE_COLOR !== undefined || process.env.NO_COLOR !== undefined
112
- ? {}
113
- : { FORCE_COLOR: '1' };
111
+ const colorEnv = process.env.FORCE_COLOR !== undefined || process.env.NO_COLOR !== undefined ? {} : { FORCE_COLOR: '1' };
114
112
  const env = {
115
113
  ...process.env,
116
114
  ...colorEnv,
@@ -119,9 +117,7 @@ async function runScript(script, extraArgs) {
119
117
  npm_package_name: pkg.name ?? '',
120
118
  npm_package_version: pkg.version ?? '',
121
119
  };
122
- const fullCmd = extraArgs.length > 0
123
- ? `${literal} ${extraArgs.map(shellEscape).join(' ')}`
124
- : literal;
120
+ const fullCmd = extraArgs.length > 0 ? `${literal} ${extraArgs.map(shellEscape).join(' ')}` : literal;
125
121
  // ensureMainLoop() (called inside spawn) keeps GJS alive after the
126
122
  // child exits — without an explicit process.exit() the success path
127
123
  // would park the loop forever. The error path already exits.
@@ -4,5 +4,5 @@ interface SelfUpdateOptions {
4
4
  force?: boolean;
5
5
  tag: string;
6
6
  }
7
- export declare const selfUpdateCommand: Command<any, SelfUpdateOptions>;
7
+ export declare const selfUpdateCommand: Command<unknown, SelfUpdateOptions>;
8
8
  export {};
@@ -76,9 +76,7 @@ export const selfUpdateCommand = {
76
76
  return;
77
77
  }
78
78
  if (args.check) {
79
- console.log(currentVersion
80
- ? `Update available: v${currentVersion} → v${target}`
81
- : `Install required: → v${target}`);
79
+ console.log(currentVersion ? `Update available: v${currentVersion} → v${target}` : `Install required: → v${target}`);
82
80
  process.exit(1);
83
81
  return;
84
82
  }
@@ -4,5 +4,5 @@ interface ShowcaseOptions {
4
4
  json: boolean;
5
5
  list: boolean;
6
6
  }
7
- export declare const showcaseCommand: Command<any, ShowcaseOptions>;
7
+ export declare const showcaseCommand: Command<unknown, ShowcaseOptions>;
8
8
  export {};
@@ -1,5 +1,5 @@
1
1
  import { discoverShowcases, findShowcase } from '../utils/discover-showcases.js';
2
- import { runMinimalChecks, detectPackageManager, buildInstallCommand, } from '../utils/check-system-deps.js';
2
+ import { runMinimalChecks, detectPackageManager, buildInstallCommand } from '../utils/check-system-deps.js';
3
3
  import { spawn } from 'node:child_process';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { readFileSync } from 'node:fs';
@@ -2,5 +2,5 @@ import type { Command } from '../types/index.js';
2
2
  interface CheckOptions {
3
3
  json: boolean;
4
4
  }
5
- export declare const systemCheckCommand: Command<any, CheckOptions>;
5
+ export declare const systemCheckCommand: Command<unknown, CheckOptions>;
6
6
  export {};