@gjsify/cli 0.4.27 → 0.4.29

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 (64) hide show
  1. package/dist/cli.gjs.mjs +34 -32
  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.js +37 -31
  8. package/lib/commands/check.js +3 -3
  9. package/lib/commands/fix.js +33 -23
  10. package/lib/commands/flatpak/build.js +6 -2
  11. package/lib/commands/flatpak/check.js +9 -3
  12. package/lib/commands/flatpak/ci.js +1 -2
  13. package/lib/commands/flatpak/deps.js +1 -2
  14. package/lib/commands/flatpak/diff.js +2 -6
  15. package/lib/commands/flatpak/init.js +19 -19
  16. package/lib/commands/flatpak/release.js +2 -2
  17. package/lib/commands/flatpak/scaffold.js +3 -11
  18. package/lib/commands/flatpak/sync-flathub.js +4 -8
  19. package/lib/commands/flatpak/utils.js +1 -6
  20. package/lib/commands/foreach.js +5 -14
  21. package/lib/commands/format.js +54 -41
  22. package/lib/commands/gettext.js +2 -10
  23. package/lib/commands/gresource.js +2 -8
  24. package/lib/commands/gsettings.js +1 -3
  25. package/lib/commands/install.js +13 -6
  26. package/lib/commands/lint.d.ts +1 -1
  27. package/lib/commands/lint.js +22 -22
  28. package/lib/commands/pack.js +29 -17
  29. package/lib/commands/publish.d.ts +1 -0
  30. package/lib/commands/publish.js +113 -21
  31. package/lib/commands/run.js +2 -6
  32. package/lib/commands/self-update.js +36 -8
  33. package/lib/commands/showcase.js +1 -1
  34. package/lib/commands/system-check.js +8 -11
  35. package/lib/commands/test.js +12 -8
  36. package/lib/commands/uninstall.js +1 -3
  37. package/lib/commands/upgrade.d.ts +1 -1
  38. package/lib/commands/upgrade.js +109 -120
  39. package/lib/commands/workspace.js +1 -3
  40. package/lib/config.js +18 -13
  41. package/lib/index.js +21 -0
  42. package/lib/templates/install.mjs.tmpl +20 -14
  43. package/lib/templates/oxfmtrc.tmpl +54 -0
  44. package/lib/templates/oxlintrc.json.tmpl +35 -0
  45. package/lib/types/config-data.d.ts +23 -13
  46. package/lib/utils/check-system-deps.js +10 -4
  47. package/lib/utils/detect-native-packages.js +1 -1
  48. package/lib/utils/dlx-cache.js +2 -7
  49. package/lib/utils/install-backend-native.d.ts +2 -2
  50. package/lib/utils/install-backend-native.js +72 -63
  51. package/lib/utils/install-backend.d.ts +13 -0
  52. package/lib/utils/install-backend.js +2 -1
  53. package/lib/utils/install-global.js +1 -3
  54. package/lib/utils/normalize-bundler-options.js +52 -17
  55. package/lib/utils/oxc-resolve.d.ts +63 -0
  56. package/lib/utils/oxc-resolve.js +264 -0
  57. package/lib/utils/pkg-json-edit.js +1 -6
  58. package/lib/utils/run-gjs.js +1 -4
  59. package/lib/utils/run-lifecycle-script.js +3 -7
  60. package/lib/utils/workspace-root.js +3 -1
  61. package/package.json +17 -17
  62. package/lib/templates/biome.json.tmpl +0 -79
  63. package/lib/utils/biome-resolve.d.ts +0 -47
  64. package/lib/utils/biome-resolve.js +0 -204
@@ -88,12 +88,16 @@ export const flatpakBuildCommand = {
88
88
  rmSync(buildDir, { recursive: true, force: true });
89
89
  await runFlatpakBuilder([...sharedFlags, buildDir, manifest], { verbose: args.verbose });
90
90
  if (args.install) {
91
- await runFlatpakBuilder(['--user', '--install', '--force-clean', buildDir, manifest], { verbose: args.verbose });
91
+ await runFlatpakBuilder(['--user', '--install', '--force-clean', buildDir, manifest], {
92
+ verbose: args.verbose,
93
+ });
92
94
  }
93
95
  if (args.repo) {
94
96
  const repoPath = resolve(cwd, args.repo);
95
97
  mkdirSync(dirname(repoPath), { recursive: true });
96
- await runFlatpakBuilder([`--repo=${repoPath}`, '--force-clean', buildDir, manifest], { verbose: args.verbose });
98
+ await runFlatpakBuilder([`--repo=${repoPath}`, '--force-clean', buildDir, manifest], {
99
+ verbose: args.verbose,
100
+ });
97
101
  }
98
102
  if (args.bundle) {
99
103
  if (!args.repo) {
@@ -101,7 +101,9 @@ function resolveAppId(explicit, flatpak, cwd) {
101
101
  if (looksLikeAppId(pkg.name))
102
102
  return pkg.name;
103
103
  }
104
- catch { /* no pkg.json */ }
104
+ catch {
105
+ /* no pkg.json */
106
+ }
105
107
  if (explicit) {
106
108
  // strip `.json` extension if present
107
109
  return explicit.replace(/\.json$/, '');
@@ -130,8 +132,12 @@ function runLinter(bin, args, verbose) {
130
132
  if (!verbose) {
131
133
  child.stdout?.setEncoding('utf-8');
132
134
  child.stderr?.setEncoding('utf-8');
133
- child.stdout?.on('data', (c) => { stdout += c; });
134
- child.stderr?.on('data', (c) => { stderr += c; });
135
+ child.stdout?.on('data', (c) => {
136
+ stdout += c;
137
+ });
138
+ child.stderr?.on('data', (c) => {
139
+ stderr += c;
140
+ });
135
141
  }
136
142
  child.on('error', (err) => {
137
143
  const e = err;
@@ -61,8 +61,7 @@ export const flatpakCiCommand = {
61
61
  const configData = await cfg.forBuild({}).catch(() => ({}));
62
62
  const flatpak = configData.flatpak ?? {};
63
63
  const pkg = readPackageJson(cwd);
64
- const appId = flatpak.appId ??
65
- (looksLikeAppId(pkg.name) ? pkg.name : undefined);
64
+ const appId = flatpak.appId ?? (looksLikeAppId(pkg.name) ? pkg.name : undefined);
66
65
  if (!appId) {
67
66
  throw new Error('gjsify flatpak ci: no app id available. Set gjsify.flatpak.appId in package.json ' +
68
67
  'or rename the package to a reverse-DNS id.');
@@ -53,8 +53,7 @@ export const flatpakDepsCommand = {
53
53
  if (!existsSync(lockfile)) {
54
54
  throw new Error(`gjsify flatpak deps: lockfile ${lockfile} not found (use --lockfile to override)`);
55
55
  }
56
- const type = args.type ??
57
- (lockfile.endsWith('package-lock.json') ? 'npm' : 'yarn');
56
+ const type = args.type ?? (lockfile.endsWith('package-lock.json') ? 'npm' : 'yarn');
58
57
  const out = resolve(cwd, args.out ?? 'flatpak-node-sources.json');
59
58
  mkdirSync(dirname(out), { recursive: true });
60
59
  const cmdArgs = [type, lockfile, '-o', out];
@@ -62,15 +62,11 @@ export const flatpakDiffCommand = {
62
62
  const cfg = new Config();
63
63
  const configData = await cfg.forBuild({}).catch(() => ({}));
64
64
  const flatpak = configData.flatpak ?? {};
65
- const appId = args.appId ??
66
- flatpak.appId ??
67
- readPackageJson(cwd).name;
65
+ const appId = args.appId ?? flatpak.appId ?? readPackageJson(cwd).name;
68
66
  if (!appId) {
69
67
  throw new Error('[gjsify flatpak diff] no app id available — pass --app-id or set gjsify.flatpak.appId.');
70
68
  }
71
- const flathubRepo = args.flathubRepo ??
72
- flatpak.flathubRepo ??
73
- `flathub/${appId}`;
69
+ const flathubRepo = args.flathubRepo ?? flatpak.flathubRepo ?? `flathub/${appId}`;
74
70
  const localVersion = args.version ?? (await resolveLatestTag(cwd, args.verbose));
75
71
  const remoteSource = await loadFlathubSource({ appId, flathubRepo, against: args.against, verbose: args.verbose }, args.sourceIndex);
76
72
  const remoteTag = remoteSource?.tag;
@@ -16,7 +16,7 @@ import { dirname, resolve } from 'node:path';
16
16
  import { DEFAULT_CLI_FINISH_ARGS, DEFAULT_GUI_FINISH_ARGS, looksLikeAppId, readPackageJson, resolveRuntime, } from './utils.js';
17
17
  import { renderDesktop, renderFlathubJson, renderMetainfoApp, renderMetainfoCli, validateScaffoldInputs, } from './scaffold.js';
18
18
  import { Config } from '../../config.js';
19
- import { BiomeNotFoundError, hasBiomeDevDep, runBiome, } from '../../utils/biome-resolve.js';
19
+ import { OxcNotFoundError, hasOxcDevDep, runOxfmt } from '../../utils/oxc-resolve.js';
20
20
  export const flatpakInitCommand = {
21
21
  command: 'init',
22
22
  description: 'Generate Flatpak manifest + MetaInfo XML + .desktop + flathub.json from `gjsify.flatpak` config.',
@@ -88,8 +88,9 @@ export const flatpakInitCommand = {
88
88
  default: false,
89
89
  })
90
90
  .option('format', {
91
- description: 'Run `gjsify format --write` on the generated files when `@biomejs/biome` is detected in the project. ' +
92
- 'Default: true. Pass --no-format to skip.',
91
+ description: 'Run `oxfmt --write` on the generated JS/TS files when `oxfmt` is detected in the project. ' +
92
+ 'Default: true. Pass --no-format to skip. Note: oxfmt formats JS/TS only — the JSON/XML/.desktop ' +
93
+ 'manifests generated here are not reformatted (CSS/JSON formatting was dropped in the oxc migration).',
93
94
  type: 'boolean',
94
95
  default: true,
95
96
  });
@@ -107,9 +108,7 @@ export const flatpakInitCommand = {
107
108
  throw new Error('gjsify flatpak init: no app id available. Pass --app-id, set gjsify.flatpak.appId in package.json, ' +
108
109
  'or rename the package to a reverse-DNS id like org.example.MyApp.');
109
110
  }
110
- const kind = args.kind ??
111
- flatpak.kind ??
112
- (args.cliOnly ? 'cli' : 'app');
111
+ const kind = args.kind ?? flatpak.kind ?? (args.cliOnly ? 'cli' : 'app');
113
112
  const { runtime, runtimeId, sdk, runtimeVersion } = resolveRuntime(flatpak, {
114
113
  runtime: args.runtime,
115
114
  runtimeVersion: args.runtimeVersion,
@@ -120,8 +119,7 @@ export const flatpakInitCommand = {
120
119
  const explicitFinishArgs = args.finishArg;
121
120
  const finishArgs = explicitFinishArgs !== undefined
122
121
  ? explicitFinishArgs
123
- : flatpak.finishArgs ??
124
- (kind === 'cli' ? DEFAULT_CLI_FINISH_ARGS : DEFAULT_GUI_FINISH_ARGS);
122
+ : (flatpak.finishArgs ?? (kind === 'cli' ? DEFAULT_CLI_FINISH_ARGS : DEFAULT_GUI_FINISH_ARGS));
125
123
  const manifest = {
126
124
  id: appId,
127
125
  runtime: runtimeId,
@@ -199,20 +197,22 @@ export const flatpakInitCommand = {
199
197
  const flathubOut = args.flathubJson ?? 'flathub.json';
200
198
  trackWrite(writeIfFresh(resolve(cwd, flathubOut), renderFlathubJson(kind), args.force ?? false, 'flathub.json'));
201
199
  }
202
- // Optional post-format: when biome is configured in the project,
203
- // run `biome format --write` on the generated files so they match
204
- // the project's prettier/biome style. Default behaviour (2-space
205
- // JSON) already matches biome/prettier/Flathub defaults; this
206
- // step harmonises edge-case fields (line endings, trailing commas
207
- // in JSONC, key sort order if biome's organize-imports has rules).
208
- if (writtenFiles.length > 0 && args.format !== false && hasBiomeDevDep(cwd)) {
200
+ // Optional post-format: when oxfmt is configured in the project, run
201
+ // `oxfmt --write` on any generated JS/TS files. oxfmt formats JS/TS
202
+ // (+TOML) only the manifest/MetaInfo/.desktop/flathub outputs are
203
+ // JSON/XML/INI and are therefore left untouched (CSS/JSON formatting
204
+ // was dropped in the Biome oxc migration). In practice flatpak init
205
+ // emits no JS/TS, so this is usually a no-op; it remains as a hook for
206
+ // any future JS/TS scaffold output.
207
+ const jsLikeFiles = writtenFiles.filter((p) => /\.(ts|tsx|mts|cts|js|jsx|mjs|cjs)$/.test(p));
208
+ if (jsLikeFiles.length > 0 && args.format !== false && hasOxcDevDep(cwd)) {
209
209
  try {
210
- await runBiome(['format', '--write', ...writtenFiles], { cwd });
210
+ await runOxfmt(['--write', ...jsLikeFiles], { cwd });
211
211
  }
212
212
  catch (err) {
213
- if (err instanceof BiomeNotFoundError) {
214
- // Biome configured but binary missing — non-fatal warning.
215
- console.warn(`[gjsify flatpak init] post-format skipped: @biomejs/biome declared but binary not installed. ` +
213
+ if (err instanceof OxcNotFoundError) {
214
+ // oxfmt configured but binding missing — non-fatal warning.
215
+ console.warn(`[gjsify flatpak init] post-format skipped: oxfmt declared but binding not installed. ` +
216
216
  `Run \`gjsify install\` then re-run with --force, or pass --no-format.`);
217
217
  }
218
218
  else {
@@ -22,7 +22,7 @@ export const flatpakReleaseCommand = {
22
22
  command: 'release <version>',
23
23
  description: 'Cut a release end-to-end: regenerate Flathub assets, run linters, create + push the git tag, then open the Flathub PR. Each step delegates to the equivalent `gjsify flatpak <sub>` command.',
24
24
  builder: (yargs) => {
25
- return yargs
25
+ return (yargs
26
26
  // yargs' built-in `--version` flag would otherwise consume the
27
27
  // positional value.
28
28
  .version(false)
@@ -64,7 +64,7 @@ export const flatpakReleaseCommand = {
64
64
  description: 'Echo every sub-command invocation.',
65
65
  type: 'boolean',
66
66
  default: false,
67
- });
67
+ }));
68
68
  },
69
69
  handler: async (args) => {
70
70
  const version = typeof args.version === 'string' ? args.version.trim() : '';
@@ -75,9 +75,7 @@ export function renderMetainfoCli(inputs) {
75
75
  export function renderDesktop(inputs) {
76
76
  const f = inputs.flatpak;
77
77
  const categoriesLine = (f.categories ?? ['Utility']).join(';') + ';';
78
- const keywordsLine = f.keywords?.length
79
- ? `Keywords=${f.keywords.join(';')};\n`
80
- : '';
78
+ const keywordsLine = f.keywords?.length ? `Keywords=${f.keywords.join(';')};\n` : '';
81
79
  return substitute(loadDesktopTemplate(), {
82
80
  NAME: inputs.name,
83
81
  SUMMARY: f.summary ?? inputs.name,
@@ -265,9 +263,7 @@ function renderMetainfo(inputs, kind) {
265
263
  }
266
264
  // ─── Description block renderer ──────────────────────────────────────────
267
265
  function renderDescriptionBlocks(description, indent) {
268
- const blocks = typeof description === 'string'
269
- ? stringToBlocks(description)
270
- : description;
266
+ const blocks = typeof description === 'string' ? stringToBlocks(description) : description;
271
267
  const out = [];
272
268
  for (const block of blocks) {
273
269
  if ('p' in block) {
@@ -319,9 +315,5 @@ function substitute(template, tokens) {
319
315
  return out;
320
316
  }
321
317
  function escapeXml(value) {
322
- return value
323
- .replace(/&/g, '&amp;')
324
- .replace(/</g, '&lt;')
325
- .replace(/>/g, '&gt;')
326
- .replace(/"/g, '&quot;');
318
+ return value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
327
319
  }
@@ -26,7 +26,7 @@ export const flatpakSyncFlathubCommand = {
26
26
  command: 'sync-flathub',
27
27
  description: 'Update the per-app Flathub tracking-repo manifest to a new git tag + commit. Clones, edits, commits, optionally opens a PR.',
28
28
  builder: (yargs) => {
29
- return yargs
29
+ return (yargs
30
30
  // Disable yargs' built-in `--version` (which would otherwise
31
31
  // print the package version) so this command's `--version
32
32
  // <tag>` flag works.
@@ -69,22 +69,18 @@ export const flatpakSyncFlathubCommand = {
69
69
  description: 'Echo every git / gh invocation before running.',
70
70
  type: 'boolean',
71
71
  default: false,
72
- });
72
+ }));
73
73
  },
74
74
  handler: async (args) => {
75
75
  const cwd = process.cwd();
76
76
  const cfg = new Config();
77
77
  const configData = await cfg.forBuild({}).catch(() => ({}));
78
78
  const flatpak = configData.flatpak ?? {};
79
- const appId = args.appId ??
80
- flatpak.appId ??
81
- readPackageJson(cwd).name;
79
+ const appId = args.appId ?? flatpak.appId ?? readPackageJson(cwd).name;
82
80
  if (!appId) {
83
81
  throw new Error('[gjsify flatpak sync-flathub] no app id available — pass --app-id or set gjsify.flatpak.appId.');
84
82
  }
85
- const flathubRepo = args.flathubRepo ??
86
- flatpak.flathubRepo ??
87
- `flathub/${appId}`;
83
+ const flathubRepo = args.flathubRepo ?? flatpak.flathubRepo ?? `flathub/${appId}`;
88
84
  const version = args.version ?? (await resolveLatestTag(cwd, args.verbose));
89
85
  if (!version) {
90
86
  throw new Error('[gjsify flatpak sync-flathub] no version resolved — pass --version vX.Y.Z or create a git tag locally.');
@@ -10,12 +10,7 @@ export const DEFAULT_GNOME_RUNTIME_VERSION = '50';
10
10
  /** Default Freedesktop-Platform runtime version (LTS-ish). */
11
11
  export const DEFAULT_FREEDESKTOP_RUNTIME_VERSION = '24.08';
12
12
  /** Permissive GUI defaults for GTK4 + Adwaita apps. */
13
- export const DEFAULT_GUI_FINISH_ARGS = [
14
- '--device=dri',
15
- '--share=ipc',
16
- '--socket=fallback-x11',
17
- '--socket=wayland',
18
- ];
13
+ export const DEFAULT_GUI_FINISH_ARGS = ['--device=dri', '--share=ipc', '--socket=fallback-x11', '--socket=wayland'];
19
14
  /** Lean defaults for headless CLI tools — no display, no GPU. */
20
15
  export const DEFAULT_CLI_FINISH_ARGS = [];
21
16
  /** Read package.json from a directory. Throws a helpful error if missing/invalid. */
@@ -38,7 +38,7 @@ export const foreachCommand = {
38
38
  default: false,
39
39
  })
40
40
  .option('topological', {
41
- description: 'Wait for each workspace\'s deps to finish before starting it (production deps only).',
41
+ description: "Wait for each workspace's deps to finish before starting it (production deps only).",
42
42
  type: 'boolean',
43
43
  alias: 't',
44
44
  default: false,
@@ -105,8 +105,7 @@ export const foreachCommand = {
105
105
  // With populate--:true, anything after the literal `--`
106
106
  // separator lands in top-level args['--']. yargs DOES NOT
107
107
  // attach it to args._ — it's a sibling array.
108
- const fromDoubleDash = (args['--'] ?? [])
109
- .filter((v) => typeof v === 'string');
108
+ const fromDoubleDash = (args['--'] ?? []).filter((v) => typeof v === 'string');
110
109
  if (fromDoubleDash.length > 0) {
111
110
  if (!cmd) {
112
111
  cmd = fromDoubleDash[0];
@@ -206,11 +205,7 @@ async function runTopologicalParallel(workspaces, script, args, concurrency, ver
206
205
  for (const ws of workspaces) {
207
206
  const wsDeps = new Set();
208
207
  const m = ws.manifest;
209
- for (const block of [
210
- m.dependencies,
211
- includeDev ? m.devDependencies : undefined,
212
- m.optionalDependencies,
213
- ]) {
208
+ for (const block of [m.dependencies, includeDev ? m.devDependencies : undefined, m.optionalDependencies]) {
214
209
  if (!block)
215
210
  continue;
216
211
  for (const [name, spec] of Object.entries(block)) {
@@ -284,9 +279,7 @@ async function runOne(ws, script, args, prefixOutput, verbose, exec) {
284
279
  // when nothing is detectable; the script-runner (D.5) will replace
285
280
  // this once `gjsify run` ships.
286
281
  const runner = detectPackageManager();
287
- const argv = runner === 'gjsify'
288
- ? ['run', script, ...args]
289
- : ['run', script, ...(args.length > 0 ? ['--', ...args] : [])];
282
+ const argv = runner === 'gjsify' ? ['run', script, ...args] : ['run', script, ...(args.length > 0 ? ['--', ...args] : [])];
290
283
  if (verbose) {
291
284
  console.error(`[${ws.name}] $ ${runner} ${argv.join(' ')}`);
292
285
  }
@@ -307,9 +300,7 @@ function spawnPrefixed(cmd, args, cwd, prefix) {
307
300
  // Default FORCE_COLOR=1 unless the user explicitly opted out, so tools
308
301
  // that key on `process.stdout.isTTY` (chalk, picocolors, …) still emit
309
302
  // ANSI colors when run under gjsify foreach. Mirrors yarn / npm.
310
- const colorEnv = process.env.FORCE_COLOR !== undefined || process.env.NO_COLOR !== undefined
311
- ? {}
312
- : { FORCE_COLOR: '1' };
303
+ const colorEnv = process.env.FORCE_COLOR !== undefined || process.env.NO_COLOR !== undefined ? {} : { FORCE_COLOR: '1' };
313
304
  return new Promise((resolve, reject) => {
314
305
  const child = spawn(cmd, args, {
315
306
  cwd,
@@ -1,19 +1,25 @@
1
- // `gjsify format` — wraps biome's `format` mode.
1
+ // `gjsify format` — wraps oxfmt.
2
2
  //
3
- // Resolves biome's native binary from node_modules (skipping the Node
4
- // launcher in @biomejs/biome/bin/biome) and spawns it directly. This
5
- // keeps the Node-free promise intact: biome's per-platform package
6
- // (e.g. @biomejs/cli-linux-x64) carries a self-contained Rust binary.
3
+ // Resolves oxfmt's Node launcher from node_modules
4
+ // (`node_modules/oxfmt/bin/oxfmt` → `dist/cli.js`) and spawns it with the
5
+ // current Node executable. oxfmt is a napi-rs hybrid CLI; the launcher carries
6
+ // the per-platform `@oxfmt/binding-<target>` native code as an
7
+ // optionalDependency, keeping the Node-free runtime promise for the bundled
8
+ // CLI intact (the formatter runs in dev/CI, not in shipped GJS apps).
7
9
  //
8
- // `--init` writes a recommended biome.json template tuned for GJS/GNOME
9
- // projects (4-space JS/TS, 2-space JSON+CSS, single-quotes, lineWidth
10
- // 120, biome's recommended linter + a few GJS-specific opt-outs).
10
+ // oxfmt formats JS/TS (+TOML) only. CSS/JSON formatting that the old Biome
11
+ // toolchain handled is intentionally DROPPED in the oxc migration — no other
12
+ // formatter is wired up for those file types.
13
+ //
14
+ // `--init` writes recommended `.oxlintrc.json` + `.oxfmtrc.json` templates
15
+ // tuned for GJS/GNOME projects (4-space, single-quote, printWidth 120,
16
+ // trailing-comma all, semicolons always, arrow parens always).
11
17
  import { existsSync, writeFileSync } from 'node:fs';
12
18
  import { resolve } from 'node:path';
13
- import { BiomeNotFoundError, findBiomeConfig, loadBiomeTemplate, printBiomeNotFound, runBiome, } from '../utils/biome-resolve.js';
19
+ import { OxcNotFoundError, findOxfmtConfig, loadOxfmtTemplate, loadOxlintTemplate, printOxcNotFound, runOxfmt, } from '../utils/oxc-resolve.js';
14
20
  export const formatCommand = {
15
21
  command: 'format [paths..]',
16
- description: 'Format source files via Biome (native binary spawn no Node launcher).',
22
+ description: 'Format JS/TS source files via oxfmt (CSS/JSON formatting is not supported).',
17
23
  builder: (yargs) => {
18
24
  return yargs
19
25
  .positional('paths', {
@@ -22,7 +28,7 @@ export const formatCommand = {
22
28
  array: true,
23
29
  })
24
30
  .option('write', {
25
- description: 'Modify files in place (default: stdout / report).',
31
+ description: 'Modify files in place (default: report drift without writing).',
26
32
  type: 'boolean',
27
33
  default: false,
28
34
  })
@@ -32,22 +38,22 @@ export const formatCommand = {
32
38
  default: false,
33
39
  })
34
40
  .option('config-path', {
35
- description: 'Path to a biome.json. Default: walks up from cwd to find one.',
41
+ description: 'Path to an .oxfmtrc.json. Default: walks up from cwd to find one.',
36
42
  type: 'string',
37
43
  normalize: true,
38
44
  })
39
45
  .option('init', {
40
- description: 'Write a recommended biome.json into cwd (skips if one exists; --force to overwrite).',
46
+ description: 'Write recommended .oxlintrc.json + .oxfmtrc.json into cwd (skips existing files unless --force).',
41
47
  type: 'boolean',
42
48
  default: false,
43
49
  })
44
50
  .option('force', {
45
- description: 'Overwrite an existing biome.json with --init.',
51
+ description: 'Overwrite existing .oxlintrc.json / .oxfmtrc.json with --init.',
46
52
  type: 'boolean',
47
53
  default: false,
48
54
  })
49
55
  .option('verbose', {
50
- description: 'Echo the resolved biome binary + args before spawning.',
56
+ description: 'Echo the resolved oxfmt launcher + args before spawning.',
51
57
  type: 'boolean',
52
58
  default: false,
53
59
  });
@@ -55,29 +61,33 @@ export const formatCommand = {
55
61
  handler: async (args) => {
56
62
  const cwd = process.cwd();
57
63
  if (args.init) {
58
- await handleInit({ cwd, force: args.force ?? false });
64
+ handleInit({ cwd, force: args.force ?? false });
59
65
  return;
60
66
  }
61
- const paths = args.paths?.length
62
- ? args.paths
63
- : ['.'];
64
- const biomeArgs = ['format'];
65
- if (args.write && !args.check)
66
- biomeArgs.push('--write');
67
- // --check is the CI semantic: don't write, exit non-zero on drift.
68
- // Biome's default mode (no --write) already reports drift + exits
69
- // non-zero. We forward neither flag and let biome's defaults apply.
70
- const configPath = args.configPath ?? findBiomeConfig(cwd) ?? undefined;
67
+ const paths = args.paths?.length ? args.paths : ['.'];
68
+ const oxfmtArgs = [];
69
+ if (args.check) {
70
+ oxfmtArgs.push('--check');
71
+ }
72
+ else if (args.write) {
73
+ oxfmtArgs.push('--write');
74
+ }
75
+ else {
76
+ // No flag: report drift without modifying files. oxfmt's bare
77
+ // default is `--write`, so be explicit with `--list-different`.
78
+ oxfmtArgs.push('--list-different');
79
+ }
80
+ const configPath = args.configPath ?? findOxfmtConfig(cwd) ?? undefined;
71
81
  if (configPath)
72
- biomeArgs.push(`--config-path=${resolve(configPath, '..')}`);
73
- biomeArgs.push(...paths);
82
+ oxfmtArgs.push('--config', resolve(configPath));
83
+ oxfmtArgs.push(...paths);
74
84
  try {
75
- const code = await runBiome(biomeArgs, { cwd, verbose: args.verbose });
85
+ const code = await runOxfmt(oxfmtArgs, { cwd, verbose: args.verbose });
76
86
  process.exitCode = code;
77
87
  }
78
88
  catch (err) {
79
- if (err instanceof BiomeNotFoundError) {
80
- printBiomeNotFound(err);
89
+ if (err instanceof OxcNotFoundError) {
90
+ printOxcNotFound(err);
81
91
  process.exitCode = 1;
82
92
  return;
83
93
  }
@@ -85,14 +95,17 @@ export const formatCommand = {
85
95
  }
86
96
  },
87
97
  };
88
- async function handleInit({ cwd, force }) {
89
- const target = resolve(cwd, 'biome.json');
90
- if (existsSync(target) && !force) {
91
- console.log(`[gjsify format] biome.json exists at ${target} pass --force to overwrite.`);
92
- process.exitCode = 0;
93
- return;
94
- }
95
- writeFileSync(target, loadBiomeTemplate(), 'utf-8');
96
- console.log(`[gjsify format] wrote ${target}`);
97
- console.log(`[gjsify format] Run \`gjsify format --write .\` to apply the formatter to the project.`);
98
+ function handleInit({ cwd, force }) {
99
+ const writeOne = (name, contents) => {
100
+ const target = resolve(cwd, name);
101
+ if (existsSync(target) && !force) {
102
+ console.log(`[gjsify format] ${name} exists at ${target} — pass --force to overwrite.`);
103
+ return;
104
+ }
105
+ writeFileSync(target, contents, 'utf-8');
106
+ console.log(`[gjsify format] wrote ${target}`);
107
+ };
108
+ writeOne('.oxlintrc.json', loadOxlintTemplate());
109
+ writeOne('.oxfmtrc.json', loadOxfmtTemplate());
110
+ console.log('[gjsify format] Run `gjsify format --write .` to apply the formatter to the project.');
98
111
  }
@@ -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
@@ -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
  }
@@ -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');
@@ -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..]',
@@ -320,7 +320,8 @@ async function workspaceInstall(cwd, args) {
320
320
  try {
321
321
  rmSync(linkPath, { recursive: true, force: true });
322
322
  }
323
- catch { /* unexpected — Gio failure on a path we just lstat'd to
323
+ catch {
324
+ /* unexpected — Gio failure on a path we just lstat'd to
324
325
  decide we wanted to remove. The subsequent symlinkSync
325
326
  will surface the real reason if there is one. */
326
327
  }
@@ -367,7 +368,9 @@ async function workspaceInstall(cwd, args) {
367
368
  lstatSync(linkPath);
368
369
  existsHere = true;
369
370
  }
370
- catch { /* ENOENT */ }
371
+ catch {
372
+ /* ENOENT */
373
+ }
371
374
  if (existsHere)
372
375
  continue;
373
376
  mkdirSync(dirname(linkPath), { recursive: true });
@@ -419,8 +422,12 @@ async function workspaceInstall(cwd, args) {
419
422
  try {
420
423
  rmSync(linkPath, { force: true });
421
424
  }
422
- catch { /* fine */ }
423
- writeFileSync(linkPath, buildBinShim(ws.location, nodeTarget, gjsTarget, nativePrebuildDirs), { mode: 0o755 });
425
+ catch {
426
+ /* fine */
427
+ }
428
+ writeFileSync(linkPath, buildBinShim(ws.location, nodeTarget, gjsTarget, nativePrebuildDirs), {
429
+ mode: 0o755,
430
+ });
424
431
  chmodSync(linkPath, 0o755);
425
432
  wsBinsCreated++;
426
433
  }
@@ -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
  }