frontpl 0.6.3 → 0.6.4

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/README.md CHANGED
@@ -147,7 +147,8 @@ Add/migrate linting in the current project to `oxlint`.
147
147
 
148
148
  What it does:
149
149
 
150
- - Asks strategy interactively:
150
+ - Asks mode interactively:
151
+ - Initialize `oxlint.config.ts` only
151
152
  - Migrate gradually (keep existing ESLint assets)
152
153
  - Replace ESLint directly (current mode)
153
154
  - Ensures `package.json` scripts use:
@@ -164,6 +165,8 @@ What it does:
164
165
 
165
166
  Use `--yes` (or `-y`) to skip confirmations and apply default choices.
166
167
  With `--yes`, strategy defaults to `replace`.
168
+ When selecting initialize mode, only `oxlint.config.ts` is created/updated; `package.json`, scripts, and dependencies stay unchanged.
169
+ That means existing `lint` scripts are kept as-is in initialize mode; only migrate/replace mode may update them.
167
170
 
168
171
  ### `frontpl oxfmt`
169
172
 
@@ -171,7 +174,8 @@ Add/migrate formatting in the current project to `oxfmt`.
171
174
 
172
175
  What it does:
173
176
 
174
- - Asks config strategy interactively:
177
+ - Asks mode interactively:
178
+ - Initialize `.oxfmtrc.json` only
175
179
  - Migrate from Prettier (`oxfmt --migrate=prettier`)
176
180
  - Rebuild `.oxfmtrc.json` (current mode)
177
181
  - Ensures `package.json` scripts use:
@@ -188,6 +192,8 @@ What it does:
188
192
 
189
193
  Use `--yes` (or `-y`) to skip confirmations and apply default choices.
190
194
  With `--yes`, config strategy defaults to rebuild `.oxfmtrc.json`.
195
+ When selecting initialize mode, only `.oxfmtrc.json` is created/updated; `package.json`, scripts, and dependencies stay unchanged.
196
+ That means existing `fmt` / `format` scripts are kept as-is in initialize mode; only migrate/rebuild mode may update standard scripts.
191
197
 
192
198
  ## GitHub Actions (CI + Release)
193
199
 
package/dist/cli.mjs CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { a as runBump, i as runCi, n as runOxfmt, o as runAdd, r as runOxlint, s as runInit, t as runPackage } from "./package-ChZ_08zS.mjs";
2
+ import { a as runBump, i as runCi, n as runOxfmt, o as runAdd, r as runOxlint, s as runInit, t as runPackage } from "./package-DmtImzoP.mjs";
3
3
  import bin from "tiny-bin";
4
-
5
4
  //#region src/cli.ts
6
5
  async function main() {
7
6
  await bin("frontpl", "Scaffold standardized frontend templates").argument("[name]", "Project name (directory name)").action(async (_options, args) => {
@@ -29,6 +28,5 @@ async function main() {
29
28
  }).run();
30
29
  }
31
30
  main();
32
-
33
31
  //#endregion
34
- export { };
32
+ export {};
package/dist/index.d.mts CHANGED
@@ -32,17 +32,21 @@ declare function validateProjectName(value: string | undefined): "Project name i
32
32
  //#region src/commands/oxlint.d.ts
33
33
  type CommandOptions$2 = {
34
34
  yes?: boolean;
35
+ init?: boolean;
35
36
  };
36
37
  declare function runOxlint({
37
- yes
38
+ yes,
39
+ init
38
40
  }?: CommandOptions$2): Promise<void>;
39
41
  //#endregion
40
42
  //#region src/commands/oxfmt.d.ts
41
43
  type CommandOptions$1 = {
42
44
  yes?: boolean;
45
+ init?: boolean;
43
46
  };
44
47
  declare function runOxfmt({
45
- yes
48
+ yes,
49
+ init
46
50
  }?: CommandOptions$1): Promise<void>;
47
51
  //#endregion
48
52
  //#region src/commands/package.d.ts
package/dist/index.mjs CHANGED
@@ -1,3 +1,2 @@
1
- import { a as runBump, c as validateProjectName, d as oxlintConfigTemplate, f as packageJsonTemplate, i as runCi, l as githubCliCiWorkflowTemplate, n as runOxfmt, o as runAdd, p as workspaceRootPackageJsonTemplate, r as runOxlint, s as runInit, t as runPackage, u as githubDependabotTemplate } from "./package-ChZ_08zS.mjs";
2
-
3
- export { githubCliCiWorkflowTemplate, githubDependabotTemplate, oxlintConfigTemplate, packageJsonTemplate, runAdd, runBump, runCi, runInit, runOxfmt, runOxlint, runPackage, validateProjectName, workspaceRootPackageJsonTemplate };
1
+ import { a as runBump, c as validateProjectName, d as oxlintConfigTemplate, f as packageJsonTemplate, i as runCi, l as githubCliCiWorkflowTemplate, n as runOxfmt, o as runAdd, p as workspaceRootPackageJsonTemplate, r as runOxlint, s as runInit, t as runPackage, u as githubDependabotTemplate } from "./package-DmtImzoP.mjs";
2
+ export { githubCliCiWorkflowTemplate, githubDependabotTemplate, oxlintConfigTemplate, packageJsonTemplate, runAdd, runBump, runCi, runInit, runOxfmt, runOxlint, runPackage, validateProjectName, workspaceRootPackageJsonTemplate };
@@ -4,7 +4,6 @@ import path from "node:path";
4
4
  import process from "node:process";
5
5
  import { spawn, spawnSync } from "node:child_process";
6
6
  import os from "node:os";
7
-
8
7
  //#region src/lib/versions.ts
9
8
  async function detectPackageManagerVersion(pm) {
10
9
  switch (pm) {
@@ -49,7 +48,6 @@ function resolveCommand$1(command) {
49
48
  if (command === "yarn") return "yarn.cmd";
50
49
  return command;
51
50
  }
52
-
53
51
  //#endregion
54
52
  //#region src/lib/templates.ts
55
53
  function editorconfigTemplate() {
@@ -403,14 +401,12 @@ function githubDependabotTemplate(opts) {
403
401
  function yamlString(value) {
404
402
  return JSON.stringify(value);
405
403
  }
406
-
407
404
  //#endregion
408
405
  //#region src/lib/fs.ts
409
406
  async function writeText(filePath, contents) {
410
407
  await mkdir(path.dirname(filePath), { recursive: true });
411
408
  await writeFile(filePath, contents, "utf8");
412
409
  }
413
-
414
410
  //#endregion
415
411
  //#region src/lib/utils.ts
416
412
  async function pathExists(pathname) {
@@ -421,7 +417,6 @@ async function pathExists(pathname) {
421
417
  return false;
422
418
  }
423
419
  }
424
-
425
420
  //#endregion
426
421
  //#region src/lib/project.ts
427
422
  async function readPackageJson(filePath) {
@@ -452,7 +447,6 @@ async function detectPackageManager(rootDir) {
452
447
  function isPackageManager$1(value) {
453
448
  return value === "npm" || value === "pnpm" || value === "yarn" || value === "bun" || value === "deno";
454
449
  }
455
-
456
450
  //#endregion
457
451
  //#region src/lib/exec.ts
458
452
  async function exec(command, args, opts = {}) {
@@ -475,7 +469,6 @@ function resolveCommand(command) {
475
469
  if (command === "yarn") return "yarn.cmd";
476
470
  return command;
477
471
  }
478
-
479
472
  //#endregion
480
473
  //#region src/commands/init.ts
481
474
  function pmRun$2(pm, script) {
@@ -726,7 +719,6 @@ function nextStepHint(pm) {
726
719
  case "deno": return "deno task lint # (or run the package.json scripts with your preferred runner)";
727
720
  }
728
721
  }
729
-
730
722
  //#endregion
731
723
  //#region src/commands/add.ts
732
724
  async function runAdd({ nameArg, yes = false } = {}) {
@@ -821,7 +813,6 @@ function onCancel$2() {
821
813
  cancel("Cancelled");
822
814
  process.exitCode = 0;
823
815
  }
824
-
825
816
  //#endregion
826
817
  //#region src/commands/bump.ts
827
818
  const SEMVER_PATTERN = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
@@ -971,7 +962,6 @@ function onCancel$1() {
971
962
  cancel("Cancelled");
972
963
  process.exitCode = 0;
973
964
  }
974
-
975
965
  //#endregion
976
966
  //#region src/commands/ci.ts
977
967
  async function runCi() {
@@ -1228,7 +1218,6 @@ function pmRun$1(pm, script) {
1228
1218
  case "deno": return script;
1229
1219
  }
1230
1220
  }
1231
-
1232
1221
  //#endregion
1233
1222
  //#region src/commands/oxlint.ts
1234
1223
  const OXLINT_COMMAND = "oxlint --type-aware --type-check";
@@ -1260,7 +1249,7 @@ const OXLINT_DEPENDENCIES = [
1260
1249
  "oxlint-tsgolint",
1261
1250
  "@kingsword/lint-config"
1262
1251
  ];
1263
- async function runOxlint({ yes = false } = {}) {
1252
+ async function runOxlint({ yes = false, init = false } = {}) {
1264
1253
  try {
1265
1254
  intro("frontpl (oxlint)");
1266
1255
  const rootDir = process.cwd();
@@ -1273,14 +1262,27 @@ async function runOxlint({ yes = false } = {}) {
1273
1262
  return;
1274
1263
  }
1275
1264
  const packageManager = await detectPackageManager(rootDir) ?? "pnpm";
1265
+ const mode = init ? "init" : yes ? "replace" : await askOxlintMode({
1266
+ rootDir,
1267
+ pkg
1268
+ });
1269
+ if (mode === "init") {
1270
+ outro([
1271
+ "Done. Initialized oxlint config.",
1272
+ `- ${await applyOxlintConfig({
1273
+ pkg,
1274
+ oxlintConfigPath,
1275
+ yes
1276
+ }) === "written" ? "wrote oxlint.config.ts" : "kept existing oxlint.config.ts"}`,
1277
+ "- package.json and dependencies left unchanged"
1278
+ ].join("\n"));
1279
+ return;
1280
+ }
1276
1281
  const stats = await migrateToOxlint({
1277
1282
  pkg,
1278
1283
  rootDir,
1279
1284
  oxlintConfigPath,
1280
- strategy: yes ? "replace" : await askMigrationStrategy({
1281
- rootDir,
1282
- pkg
1283
- }),
1285
+ strategy: mode,
1284
1286
  yes
1285
1287
  });
1286
1288
  await writePackageJson(packageJsonPath, pkg);
@@ -1405,20 +1407,28 @@ async function askConfirm$1(opts) {
1405
1407
  if (isCancel(answer)) return abort$1();
1406
1408
  return answer;
1407
1409
  }
1408
- async function askMigrationStrategy(opts) {
1409
- const strategy = await select({
1410
- message: "ESLint strategy",
1411
- initialValue: await detectEslintAssets(opts.rootDir, opts.pkg) ? "migrate" : "replace",
1412
- options: [{
1413
- value: "migrate",
1414
- label: "Migrate gradually (keep ESLint assets)"
1415
- }, {
1416
- value: "replace",
1417
- label: "Replace ESLint directly (current mode)"
1418
- }]
1410
+ async function askOxlintMode(opts) {
1411
+ const hasEslintAssets = await detectEslintAssets(opts.rootDir, opts.pkg);
1412
+ const mode = await select({
1413
+ message: "oxlint mode",
1414
+ initialValue: !await pathExists(path.join(opts.rootDir, "oxlint.config.ts")) && detectExistingOxlintSetup(opts.pkg) ? "init" : hasEslintAssets ? "migrate" : "replace",
1415
+ options: [
1416
+ {
1417
+ value: "init",
1418
+ label: "Initialize oxlint.config.ts only"
1419
+ },
1420
+ {
1421
+ value: "migrate",
1422
+ label: "Migrate gradually (keep ESLint assets)"
1423
+ },
1424
+ {
1425
+ value: "replace",
1426
+ label: "Replace ESLint directly (current mode)"
1427
+ }
1428
+ ]
1419
1429
  });
1420
- if (isCancel(strategy)) return abort$1();
1421
- return strategy;
1430
+ if (isCancel(mode)) return abort$1();
1431
+ return mode;
1422
1432
  }
1423
1433
  async function detectEslintAssets(rootDir, pkg) {
1424
1434
  if (Object.prototype.hasOwnProperty.call(pkg, "eslintConfig")) return true;
@@ -1440,6 +1450,9 @@ async function applyOxlintConfig(opts) {
1440
1450
  function detectUseVitest(scripts) {
1441
1451
  return typeof scripts?.test === "string" && scripts.test.includes("vitest");
1442
1452
  }
1453
+ function detectExistingOxlintSetup(pkg) {
1454
+ return pkg.scripts?.lint === OXLINT_COMMAND || pkg.scripts?.["lint:fix"] === OXLINT_FIX_COMMAND || Boolean(pkg.dependencies?.oxlint || pkg.devDependencies?.oxlint || pkg.devDependencies?.["oxlint-tsgolint"] || pkg.devDependencies?.["@kingsword/lint-config"]);
1455
+ }
1443
1456
  function removeEslintDependencies(pkg, key) {
1444
1457
  const bucket = pkg[key];
1445
1458
  if (!bucket) return [];
@@ -1473,7 +1486,6 @@ function abort$1(opts = {}) {
1473
1486
  process.exitCode = opts.exitCode ?? 0;
1474
1487
  throw new CancelledError$1();
1475
1488
  }
1476
-
1477
1489
  //#endregion
1478
1490
  //#region src/commands/oxfmt.ts
1479
1491
  const OXFMT_SCRIPTS = {
@@ -1504,7 +1516,7 @@ const PRETTIER_CONFIG_FILES = [
1504
1516
  "prettier.config.cts",
1505
1517
  "prettier.config.mts"
1506
1518
  ];
1507
- async function runOxfmt({ yes = false } = {}) {
1519
+ async function runOxfmt({ yes = false, init = false } = {}) {
1508
1520
  try {
1509
1521
  intro("frontpl (oxfmt)");
1510
1522
  const rootDir = process.cwd();
@@ -1517,15 +1529,30 @@ async function runOxfmt({ yes = false } = {}) {
1517
1529
  return;
1518
1530
  }
1519
1531
  const packageManager = await detectPackageManager(rootDir) ?? "pnpm";
1532
+ const mode = init ? "init" : yes ? "rebuild" : await askOxfmtMode({
1533
+ rootDir,
1534
+ pkg
1535
+ });
1536
+ if (mode === "init") {
1537
+ outro([
1538
+ "Done. Initialized oxfmt config.",
1539
+ `- ${await applyOxfmtConfig({
1540
+ rootDir,
1541
+ oxfmtConfigPath,
1542
+ packageManager,
1543
+ configMode: "rebuild",
1544
+ yes
1545
+ }) === "rebuilt" ? "wrote .oxfmtrc.json" : "kept existing .oxfmtrc.json"}`,
1546
+ "- package.json and dependencies left unchanged"
1547
+ ].join("\n"));
1548
+ return;
1549
+ }
1520
1550
  const stats = await migrateToOxfmt({
1521
1551
  pkg,
1522
1552
  rootDir,
1523
1553
  oxfmtConfigPath,
1524
1554
  packageManager,
1525
- configMode: yes ? "rebuild" : await askConfigMode({
1526
- rootDir,
1527
- pkg
1528
- }),
1555
+ configMode: mode,
1529
1556
  yes
1530
1557
  });
1531
1558
  await writePackageJson(packageJsonPath, pkg);
@@ -1650,17 +1677,25 @@ async function askConfirm(opts) {
1650
1677
  if (isCancel(answer)) return abort();
1651
1678
  return answer;
1652
1679
  }
1653
- async function askConfigMode(opts) {
1680
+ async function askOxfmtMode(opts) {
1681
+ const hasPrettierConfig = await detectPrettierConfig(opts.rootDir, opts.pkg);
1654
1682
  const mode = await select({
1655
- message: "Prettier config strategy",
1656
- initialValue: await detectPrettierConfig(opts.rootDir, opts.pkg) ? "migrate" : "rebuild",
1657
- options: [{
1658
- value: "migrate",
1659
- label: "Migrate from Prettier (oxfmt --migrate=prettier)"
1660
- }, {
1661
- value: "rebuild",
1662
- label: "Rebuild .oxfmtrc.json (current mode)"
1663
- }]
1683
+ message: "oxfmt mode",
1684
+ initialValue: !await pathExists(path.join(opts.rootDir, ".oxfmtrc.json")) && detectExistingOxfmtSetup(opts.pkg) ? "init" : hasPrettierConfig ? "migrate" : "rebuild",
1685
+ options: [
1686
+ {
1687
+ value: "init",
1688
+ label: "Initialize .oxfmtrc.json only"
1689
+ },
1690
+ {
1691
+ value: "migrate",
1692
+ label: "Migrate from Prettier (oxfmt --migrate=prettier)"
1693
+ },
1694
+ {
1695
+ value: "rebuild",
1696
+ label: "Rebuild .oxfmtrc.json (current mode)"
1697
+ }
1698
+ ]
1664
1699
  });
1665
1700
  if (isCancel(mode)) return abort();
1666
1701
  return mode;
@@ -1741,6 +1776,9 @@ function removePrettierConfigFromPackageJson(pkg) {
1741
1776
  function isPrettierDependency(name) {
1742
1777
  return name === "prettier" || /(^|\/)prettier-plugin-/.test(name) || name.startsWith("@prettier/plugin-");
1743
1778
  }
1779
+ function detectExistingOxfmtSetup(pkg) {
1780
+ return pkg.scripts?.format === OXFMT_SCRIPTS.format || pkg.scripts?.["format:check"] === OXFMT_SCRIPTS["format:check"] || pkg.scripts?.fmt === OXFMT_LEGACY_SCRIPTS.fmt || pkg.scripts?.["fmt:check"] === OXFMT_LEGACY_SCRIPTS["fmt:check"] || Boolean(pkg.dependencies?.oxfmt || pkg.devDependencies?.oxfmt);
1781
+ }
1744
1782
  var CancelledError = class extends Error {
1745
1783
  constructor() {
1746
1784
  super("Cancelled");
@@ -1751,7 +1789,6 @@ function abort(opts = {}) {
1751
1789
  process.exitCode = opts.exitCode ?? 0;
1752
1790
  throw new CancelledError();
1753
1791
  }
1754
-
1755
1792
  //#endregion
1756
1793
  //#region src/commands/package.ts
1757
1794
  async function runPackage({ yes = false } = {}) {
@@ -1940,6 +1977,5 @@ function onCancel() {
1940
1977
  cancel("Cancelled");
1941
1978
  process.exitCode = 0;
1942
1979
  }
1943
-
1944
1980
  //#endregion
1945
- export { runBump as a, validateProjectName as c, oxlintConfigTemplate as d, packageJsonTemplate as f, runCi as i, githubCliCiWorkflowTemplate as l, runOxfmt as n, runAdd as o, workspaceRootPackageJsonTemplate as p, runOxlint as r, runInit as s, runPackage as t, githubDependabotTemplate as u };
1981
+ export { runBump as a, validateProjectName as c, oxlintConfigTemplate as d, packageJsonTemplate as f, runCi as i, githubCliCiWorkflowTemplate as l, runOxfmt as n, runAdd as o, workspaceRootPackageJsonTemplate as p, runOxlint as r, runInit as s, runPackage as t, githubDependabotTemplate as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontpl",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
4
4
  "description": "Interactive CLI to scaffold standardized frontend project templates.",
5
5
  "keywords": [
6
6
  "cli",
@@ -55,8 +55,8 @@
55
55
  "@types/node": "^25.0.10",
56
56
  "oxfmt": "^0.36.0",
57
57
  "oxlint": "^1.46.0",
58
- "oxlint-tsgolint": "^0.15.0",
59
- "tsdown": "^0.20.1",
58
+ "oxlint-tsgolint": "^0.16.0",
59
+ "tsdown": "^0.21.1",
60
60
  "typescript": "^5.9.3"
61
61
  },
62
62
  "engines": {