frontpl 0.2.0 → 0.3.1

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
@@ -28,6 +28,9 @@ Follow the prompts to choose:
28
28
 
29
29
  - Package manager (`npm`/`pnpm`/`yarn`/`bun`/`deno`)
30
30
  - Optional tooling: `oxlint`, `oxfmt`, `vitest`, `tsdown`
31
+
32
+ When `oxlint` is enabled, generated projects use `@kingsword/lint-config` via `oxlint.config.ts`.
33
+
31
34
  - Git init
32
35
  - GitHub Actions workflows:
33
36
  - CI only
@@ -42,9 +45,9 @@ Scaffold a new project into `./<name>` (or prompt for a name when omitted).
42
45
  Generated output includes (based on options):
43
46
 
44
47
  - `.editorconfig`, `.gitignore`, `.gitattributes`
45
- - `package.json` (+ scripts like `typecheck`, optional `lint`, `format:check`, `test`, `build`)
48
+ - `package.json` (+ scripts like optional `lint`, `format:check`, `test`, `build`)
46
49
  - `tsconfig.json`, `src/index.ts`
47
- - Optional configs: `.oxlintrc.json`, `.oxfmtrc.json`, `tsdown.config.ts`
50
+ - Optional configs: `oxlint.config.ts`, `.oxfmtrc.json`, `tsdown.config.ts`
48
51
  - Optional GitHub Actions workflows in `.github/workflows/`
49
52
 
50
53
  ### `frontpl ci`
@@ -58,10 +61,11 @@ What it does:
58
61
  - Detects Node.js major version from `.nvmrc`, `.node-version`, or `package.json#engines.node` (defaults to `22`)
59
62
  - Generates `.github/workflows/ci.yml`
60
63
  - Optionally generates `.github/workflows/release.yml` (tag/commit/both)
64
+ - Optionally generates `.github/dependabot.yml` with grouped updates (`dependencies`, `github-actions`)
61
65
 
62
66
  ## GitHub Actions (CI + Release)
63
67
 
64
- frontpl generates workflows that call reusable workflows from `kingsword09/workflows` (pinned to `@v1` by default):
68
+ frontpl generates workflows that call reusable workflows from `kingsword09/workflows` (pinned to commit SHA + `# vX.Y.Z` comment by default):
65
69
 
66
70
  - CI: `cli-ci.yml`
67
71
  - Release (tag, recommended): `cli-release-tag.yml`
@@ -78,12 +82,25 @@ frontpl generates workflows that call reusable workflows from `kingsword09/workf
78
82
  - **Trusted publishing (OIDC)**: enable `trustedPublishing: true` (no `NPM_TOKEN` required). Your repo must be configured on npm as a trusted publisher for the calling workflow.
79
83
  - **NPM token**: set `trustedPublishing: false` and provide `NPM_TOKEN` in GitHub secrets.
80
84
 
85
+ ## Dependabot (optional)
86
+
87
+ When CI workflows are enabled, frontpl can also generate `.github/dependabot.yml`:
88
+
89
+ - Keeps `github-actions` updates enabled
90
+ - Adds grouped dependencies updates (`groups.dependencies`)
91
+ - Uses the selected `workingDirectory` (`.` -> `/`, monorepo package -> `/packages/<name>`)
92
+ - Maps JavaScript package managers (`npm`/`pnpm`/`yarn`/`bun`) to Dependabot `package-ecosystem: "npm"`
93
+
81
94
  ## Development
82
95
 
83
96
  ```sh
84
97
  pnpm install
85
- pnpm run typecheck
98
+ pnpm run lint
86
99
  pnpm run build
87
100
  node dist/cli.mjs --help
88
101
  node dist/cli.mjs ci
89
102
  ```
103
+
104
+ ## Lint preset
105
+
106
+ This repository itself uses `@kingsword/lint-config` (see `oxlint.config.ts`).
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { n as runCi, t as runInit } from "./init-DXlH6jJs.mjs";
2
+ import { n as runCi, t as runInit } from "./init-BGuupDrG.mjs";
3
3
  import bin from "tiny-bin";
4
4
 
5
5
  //#region src/cli.ts
package/dist/index.d.mts CHANGED
@@ -8,4 +8,44 @@ declare function runInit({
8
8
  nameArg?: string;
9
9
  }): Promise<void>;
10
10
  //#endregion
11
- export { runCi, runInit };
11
+ //#region src/lib/templates.d.ts
12
+ declare function oxlintConfigTemplate({
13
+ useVitest
14
+ }: {
15
+ useVitest: boolean;
16
+ }): string;
17
+ declare function packageJsonTemplate(opts: {
18
+ name: string;
19
+ packageManager: string;
20
+ typescriptVersion: string;
21
+ useOxlint: boolean;
22
+ oxlintVersion?: string;
23
+ oxlintTsgolintVersion?: string;
24
+ kingswordLintConfigVersion?: string;
25
+ useOxfmt: boolean;
26
+ oxfmtVersion?: string;
27
+ useVitest: boolean;
28
+ vitestVersion?: string;
29
+ useTsdown: boolean;
30
+ tsdownVersion?: string;
31
+ }): string;
32
+ declare function githubCliCiWorkflowTemplate(opts: {
33
+ packageManager: "npm" | "pnpm" | "yarn" | "bun" | "deno";
34
+ nodeVersion: number;
35
+ workingDirectory: string;
36
+ runLint: boolean;
37
+ runFormatCheck: boolean;
38
+ runTests: boolean;
39
+ installCommand?: string;
40
+ lintCommand?: string;
41
+ formatCheckCommand?: string;
42
+ testCommand?: string;
43
+ workflowsRef?: string;
44
+ workflowsVersion?: string;
45
+ }): string;
46
+ declare function githubDependabotTemplate(opts: {
47
+ packageManager: "npm" | "pnpm" | "yarn" | "bun" | "deno";
48
+ workingDirectory: string;
49
+ }): string;
50
+ //#endregion
51
+ export { githubCliCiWorkflowTemplate, githubDependabotTemplate, oxlintConfigTemplate, packageJsonTemplate, runCi, runInit };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { n as runCi, t as runInit } from "./init-DXlH6jJs.mjs";
1
+ import { a as oxlintConfigTemplate, i as githubDependabotTemplate, n as runCi, o as packageJsonTemplate, r as githubCliCiWorkflowTemplate, t as runInit } from "./init-BGuupDrG.mjs";
2
2
 
3
- export { runCi, runInit };
3
+ export { githubCliCiWorkflowTemplate, githubDependabotTemplate, oxlintConfigTemplate, packageJsonTemplate, runCi, runInit };
@@ -88,13 +88,13 @@ function readmeTemplate(projectName) {
88
88
  ].join("\n");
89
89
  }
90
90
  function oxlintConfigTemplate({ useVitest }) {
91
- return JSON.stringify({
92
- $schema: "https://json.schemastore.org/oxlintrc.json",
93
- env: {
94
- browser: true,
95
- es2022: true
96
- }
97
- }, null, 2) + "\n";
91
+ return [
92
+ "import { defineConfig } from \"oxlint\";",
93
+ "import { oxlint } from \"@kingsword/lint-config/config\";",
94
+ "",
95
+ `export default defineConfig(oxlint({ profile: "lib", test: "${useVitest ? "vitest" : "none"}", level: "recommended" }));`,
96
+ ""
97
+ ].join("\n");
98
98
  }
99
99
  function oxfmtConfigTemplate() {
100
100
  return JSON.stringify({ $schema: "https://json.schemastore.org/oxfmtrc.json" }, null, 2) + "\n";
@@ -111,17 +111,12 @@ function tsdownConfigTemplate() {
111
111
  ].join("\n");
112
112
  }
113
113
  function packageJsonTemplate(opts) {
114
- const scripts = { typecheck: "tsc --noEmit" };
114
+ const scripts = {};
115
115
  if (opts.useOxlint) {
116
- const oxlintCmd = [
117
- "oxlint",
118
- opts.useVitest ? "--vitest-plugin" : void 0,
119
- "--type-aware",
120
- "--type-check"
121
- ].filter(Boolean).join(" ");
116
+ const oxlintCmd = "oxlint --type-aware --type-check";
122
117
  scripts.lint = oxlintCmd;
123
118
  scripts["lint:fix"] = `${oxlintCmd} --fix`;
124
- }
119
+ } else scripts.typecheck = "tsc --noEmit";
125
120
  if (opts.useOxfmt) {
126
121
  scripts.format = "oxfmt";
127
122
  scripts["format:check"] = "oxfmt --check";
@@ -134,6 +129,7 @@ function packageJsonTemplate(opts) {
134
129
  if (opts.useOxlint) {
135
130
  if (opts.oxlintVersion) devDependencies.oxlint = opts.oxlintVersion;
136
131
  if (opts.oxlintTsgolintVersion) devDependencies["oxlint-tsgolint"] = opts.oxlintTsgolintVersion;
132
+ if (opts.kingswordLintConfigVersion) devDependencies["@kingsword/lint-config"] = opts.kingswordLintConfigVersion;
137
133
  }
138
134
  if (opts.useOxfmt && opts.oxfmtVersion) devDependencies.oxfmt = opts.oxfmtVersion;
139
135
  if (opts.useVitest && opts.vitestVersion) devDependencies.vitest = opts.vitestVersion;
@@ -148,8 +144,18 @@ function packageJsonTemplate(opts) {
148
144
  packageManager: opts.packageManager
149
145
  }, null, 2) + "\n";
150
146
  }
147
+ const DEFAULT_WORKFLOWS_REF = "7320d30bcd47cee17cc2d8d28250ba1ab1f742b8";
148
+ const DEFAULT_WORKFLOWS_VERSION = "v1.0.3";
149
+ function resolveWorkflowsPin(opts) {
150
+ const ref = opts.workflowsRef?.trim() || DEFAULT_WORKFLOWS_REF;
151
+ const version = opts.workflowsVersion?.trim() || (opts.workflowsRef ? void 0 : DEFAULT_WORKFLOWS_VERSION);
152
+ return {
153
+ ref,
154
+ versionComment: version ? ` # ${version}` : ""
155
+ };
156
+ }
151
157
  function githubCliCiWorkflowTemplate(opts) {
152
- const ref = opts.workflowsRef ?? "v1";
158
+ const { ref, versionComment } = resolveWorkflowsPin(opts);
153
159
  const installCommand = opts.installCommand?.trim();
154
160
  const lintCommand = opts.lintCommand?.trim();
155
161
  const formatCheckCommand = opts.formatCheckCommand?.trim();
@@ -165,7 +171,7 @@ function githubCliCiWorkflowTemplate(opts) {
165
171
  "",
166
172
  "jobs:",
167
173
  " ci:",
168
- ` uses: kingsword09/workflows/.github/workflows/cli-ci.yml@${ref}`,
174
+ ` uses: kingsword09/workflows/.github/workflows/cli-ci.yml@${ref}${versionComment}`,
169
175
  " with:",
170
176
  ` packageManager: ${opts.packageManager}`,
171
177
  ` nodeVersion: ${opts.nodeVersion}`,
@@ -181,7 +187,7 @@ function githubCliCiWorkflowTemplate(opts) {
181
187
  ].join("\n");
182
188
  }
183
189
  function githubCliReleaseWorkflowTemplate(opts) {
184
- const ref = opts.workflowsRef ?? "v1";
190
+ const { ref, versionComment } = resolveWorkflowsPin(opts);
185
191
  const trustedPublishing = opts.trustedPublishing;
186
192
  const needsNpmToken = opts.packageManager !== "deno" && trustedPublishing === false;
187
193
  return [
@@ -196,7 +202,7 @@ function githubCliReleaseWorkflowTemplate(opts) {
196
202
  " permissions:",
197
203
  " contents: write",
198
204
  " id-token: write",
199
- ` uses: kingsword09/workflows/.github/workflows/cli-release.yml@${ref}`,
205
+ ` uses: kingsword09/workflows/.github/workflows/cli-release.yml@${ref}${versionComment}`,
200
206
  " with:",
201
207
  ` packageManager: ${opts.packageManager}`,
202
208
  ` nodeVersion: ${opts.nodeVersion}`,
@@ -207,7 +213,7 @@ function githubCliReleaseWorkflowTemplate(opts) {
207
213
  ].join("\n");
208
214
  }
209
215
  function githubCliReleaseTagWorkflowTemplate(opts) {
210
- const ref = opts.workflowsRef ?? "v1";
216
+ const { ref, versionComment } = resolveWorkflowsPin(opts);
211
217
  const trustedPublishing = opts.trustedPublishing;
212
218
  const needsNpmToken = opts.packageManager !== "deno" && trustedPublishing === false;
213
219
  return [
@@ -222,7 +228,7 @@ function githubCliReleaseTagWorkflowTemplate(opts) {
222
228
  " permissions:",
223
229
  " contents: write",
224
230
  " id-token: write",
225
- ` uses: kingsword09/workflows/.github/workflows/cli-release-tag.yml@${ref}`,
231
+ ` uses: kingsword09/workflows/.github/workflows/cli-release-tag.yml@${ref}${versionComment}`,
226
232
  " with:",
227
233
  ` packageManager: ${opts.packageManager}`,
228
234
  ` nodeVersion: ${opts.nodeVersion}`,
@@ -233,7 +239,7 @@ function githubCliReleaseTagWorkflowTemplate(opts) {
233
239
  ].join("\n");
234
240
  }
235
241
  function githubCliReleaseBothWorkflowTemplate(opts) {
236
- const ref = opts.workflowsRef ?? "v1";
242
+ const { ref, versionComment } = resolveWorkflowsPin(opts);
237
243
  const trustedPublishing = opts.trustedPublishing;
238
244
  const needsNpmToken = opts.packageManager !== "deno" && trustedPublishing === false;
239
245
  return [
@@ -250,7 +256,7 @@ function githubCliReleaseBothWorkflowTemplate(opts) {
250
256
  " permissions:",
251
257
  " contents: write",
252
258
  " id-token: write",
253
- ` uses: kingsword09/workflows/.github/workflows/cli-release-tag.yml@${ref}`,
259
+ ` uses: kingsword09/workflows/.github/workflows/cli-release-tag.yml@${ref}${versionComment}`,
254
260
  " with:",
255
261
  ` packageManager: ${opts.packageManager}`,
256
262
  ` nodeVersion: ${opts.nodeVersion}`,
@@ -263,7 +269,7 @@ function githubCliReleaseBothWorkflowTemplate(opts) {
263
269
  " permissions:",
264
270
  " contents: write",
265
271
  " id-token: write",
266
- ` uses: kingsword09/workflows/.github/workflows/cli-release.yml@${ref}`,
272
+ ` uses: kingsword09/workflows/.github/workflows/cli-release.yml@${ref}${versionComment}`,
267
273
  " with:",
268
274
  ` packageManager: ${opts.packageManager}`,
269
275
  ` nodeVersion: ${opts.nodeVersion}`,
@@ -273,6 +279,56 @@ function githubCliReleaseBothWorkflowTemplate(opts) {
273
279
  ""
274
280
  ].join("\n");
275
281
  }
282
+ function toDependabotDirectory(workingDirectory) {
283
+ const normalized = workingDirectory.trim();
284
+ if (!normalized || normalized === ".") return "/";
285
+ return normalized.startsWith("/") ? normalized : `/${normalized}`;
286
+ }
287
+ function resolveDependabotPackageEcosystem(packageManager) {
288
+ if (packageManager === "deno") return;
289
+ return "npm";
290
+ }
291
+ function githubDependabotTemplate(opts) {
292
+ const packageEcosystem = resolveDependabotPackageEcosystem(opts.packageManager);
293
+ const directory = toDependabotDirectory(opts.workingDirectory);
294
+ return [
295
+ "version: 2",
296
+ "updates:",
297
+ ...packageEcosystem ? [
298
+ ` - package-ecosystem: "${packageEcosystem}"`,
299
+ ` directory: "${directory}"`,
300
+ " schedule:",
301
+ " interval: \"weekly\"",
302
+ " day: \"monday\"",
303
+ " time: \"03:00\"",
304
+ " timezone: \"America/Los_Angeles\"",
305
+ " open-pull-requests-limit: 10",
306
+ " groups:",
307
+ " dependencies:",
308
+ " patterns:",
309
+ " - \"*\"",
310
+ " labels:",
311
+ " - \"dependencies\"",
312
+ ""
313
+ ] : [],
314
+ " - package-ecosystem: \"github-actions\"",
315
+ " directory: \"/\"",
316
+ " schedule:",
317
+ " interval: \"weekly\"",
318
+ " day: \"monday\"",
319
+ " time: \"03:00\"",
320
+ " timezone: \"America/Los_Angeles\"",
321
+ " open-pull-requests-limit: 10",
322
+ " groups:",
323
+ " github-actions:",
324
+ " patterns:",
325
+ " - \"*\"",
326
+ " labels:",
327
+ " - \"dependencies\"",
328
+ " - \"github-actions\"",
329
+ ""
330
+ ].join("\n");
331
+ }
276
332
  function yamlString(value) {
277
333
  return JSON.stringify(value);
278
334
  }
@@ -342,7 +398,7 @@ async function runCi() {
342
398
  const nodeVersionText = await text({
343
399
  message: "Node.js major version (for GitHub Actions)",
344
400
  initialValue: String(nodeVersionDefault),
345
- validate: (value) => {
401
+ validate: (value = "") => {
346
402
  const major = Number.parseInt(value.trim(), 10);
347
403
  if (!Number.isFinite(major) || major <= 0) return "Enter a valid major version (e.g. 22)";
348
404
  }
@@ -379,8 +435,14 @@ async function runCi() {
379
435
  initialValue: true
380
436
  }) : void 0;
381
437
  if (isCancel(trustedPublishing)) return abort();
438
+ const addDependabot = await pathExists(path.join(rootDir, ".git")) ? await confirm({
439
+ message: "Add/update Dependabot config (.github/dependabot.yml)?",
440
+ initialValue: true
441
+ }) : false;
442
+ if (isCancel(addDependabot)) return abort();
382
443
  const ciWorkflowPath = path.join(rootDir, ".github/workflows/ci.yml");
383
444
  const releaseWorkflowPath = path.join(rootDir, ".github/workflows/release.yml");
445
+ const dependabotPath = path.join(rootDir, ".github/dependabot.yml");
384
446
  if (!await confirmOverwriteIfExists(ciWorkflowPath, ".github/workflows/ci.yml")) {
385
447
  cancel("Skipped CI workflow");
386
448
  process.exitCode = 0;
@@ -405,7 +467,13 @@ async function runCi() {
405
467
  trustedPublishing
406
468
  }));
407
469
  }
408
- outro(addRelease ? "Done. Generated CI + release workflows in .github/workflows/." : "Done. Generated CI workflow in .github/workflows/.");
470
+ if (addDependabot) {
471
+ if (await confirmOverwriteIfExists(dependabotPath, ".github/dependabot.yml")) await writeText(dependabotPath, githubDependabotTemplate({
472
+ packageManager,
473
+ workingDirectory
474
+ }));
475
+ }
476
+ outro(addRelease ? "Done. Generated CI + release workflows (and optional Dependabot)." : "Done. Generated CI workflow (and optional Dependabot).");
409
477
  } catch (err) {
410
478
  if (err instanceof CancelledError) return;
411
479
  throw err;
@@ -527,21 +595,21 @@ async function resolveCiCommands(rootDir, workingDirectory, packageManager) {
527
595
  runLint,
528
596
  runFormatCheck,
529
597
  runTests,
530
- lintCommand: runLint && !hasLint ? await promptCommand("Lint command", pmRun(packageManager, "lint")) : void 0,
531
- formatCheckCommand: runFormatCheck && !hasFormatCheck ? hasFmtCheck ? pmRun(packageManager, "fmt:check") : await promptCommand("Format check command", pmRun(packageManager, "format:check")) : void 0,
532
- testCommand: runTests && !hasTest ? await promptCommand("Test command", pmRun(packageManager, "test")) : void 0
598
+ lintCommand: runLint && hasLint ? pmRun$1(packageManager, "lint") : runLint ? await promptCommand("Lint command", pmRun$1(packageManager, "lint")) : void 0,
599
+ formatCheckCommand: runFormatCheck && hasFormatCheck ? pmRun$1(packageManager, "format:check") : runFormatCheck && hasFmtCheck ? pmRun$1(packageManager, "fmt:check") : runFormatCheck ? await promptCommand("Format check command", pmRun$1(packageManager, "format:check")) : void 0,
600
+ testCommand: runTests && hasTest ? pmRun$1(packageManager, "test") : runTests ? await promptCommand("Test command", pmRun$1(packageManager, "test")) : void 0
533
601
  };
534
602
  }
535
603
  async function promptCommand(message, initialValue) {
536
604
  const value = await text({
537
605
  message,
538
606
  initialValue,
539
- validate: (v) => !v.trim() ? "Command is required" : void 0
607
+ validate: (v = "") => !v.trim() ? "Command is required" : void 0
540
608
  });
541
609
  if (isCancel(value)) return abort();
542
610
  return String(value).trim();
543
611
  }
544
- function pmRun(pm, script) {
612
+ function pmRun$1(pm, script) {
545
613
  switch (pm) {
546
614
  case "npm": return `npm run ${script}`;
547
615
  case "pnpm": return `pnpm run ${script}`;
@@ -629,6 +697,15 @@ function resolveCommand(command) {
629
697
 
630
698
  //#endregion
631
699
  //#region src/commands/init.ts
700
+ function pmRun(pm, script) {
701
+ switch (pm) {
702
+ case "npm": return `npm run ${script}`;
703
+ case "pnpm": return `pnpm run ${script}`;
704
+ case "yarn": return `yarn ${script}`;
705
+ case "bun": return `bun run ${script}`;
706
+ case "deno": return script;
707
+ }
708
+ }
632
709
  async function runInit({ nameArg }) {
633
710
  intro("frontpl");
634
711
  const projectName = await text({
@@ -670,7 +747,7 @@ async function runInit({ nameArg }) {
670
747
  }) : false;
671
748
  if (isCancel(pnpmWorkspace)) return onCancel();
672
749
  const useOxlint = await confirm({
673
- message: "Enable oxlint (type-aware + type-check via tsgolint)?",
750
+ message: "Enable oxlint (@kingsword/lint-config preset)?",
674
751
  initialValue: true
675
752
  });
676
753
  if (isCancel(useOxlint)) return onCancel();
@@ -732,6 +809,11 @@ async function runInit({ nameArg }) {
732
809
  ]
733
810
  }) : void 0;
734
811
  if (isCancel(releaseMode)) return onCancel();
812
+ const addDependabot = initGit && githubActions !== "none" ? await confirm({
813
+ message: "Add Dependabot config (.github/dependabot.yml)?",
814
+ initialValue: true
815
+ }) : false;
816
+ if (isCancel(addDependabot)) return onCancel();
735
817
  const trustedPublishing = githubActions === "ci+release" && packageManager !== "deno" ? await confirm({
736
818
  message: "Release: npm trusted publishing (OIDC)?",
737
819
  initialValue: true
@@ -775,6 +857,7 @@ async function runInit({ nameArg }) {
775
857
  useOxlint,
776
858
  oxlintVersion: "latest",
777
859
  oxlintTsgolintVersion: "latest",
860
+ kingswordLintConfigVersion: "^0.1.1",
778
861
  useOxfmt,
779
862
  oxfmtVersion: "latest",
780
863
  useVitest,
@@ -783,20 +866,30 @@ async function runInit({ nameArg }) {
783
866
  tsdownVersion: "latest"
784
867
  }))
785
868
  ]);
786
- if (useOxlint) await writeText(path.join(pkgDir, ".oxlintrc.json"), oxlintConfigTemplate({ useVitest }));
869
+ if (useOxlint) await writeText(path.join(pkgDir, "oxlint.config.ts"), oxlintConfigTemplate({ useVitest }));
787
870
  if (useOxfmt) await writeText(path.join(pkgDir, ".oxfmtrc.json"), oxfmtConfigTemplate());
788
871
  if (useVitest) await writeText(path.join(pkgDir, "src/index.test.ts"), srcVitestTemplate());
789
872
  if (useTsdown) await writeText(path.join(pkgDir, "tsdown.config.ts"), tsdownConfigTemplate());
790
873
  if (packageManager === "deno") await writeText(path.join(rootDir, "deno.json"), JSON.stringify({ nodeModulesDir: "auto" }, null, 2) + "\n");
791
874
  if (githubActions !== "none") {
792
875
  const workingDirectory = pnpmWorkspace ? path.posix.join("packages", projectName) : ".";
876
+ const lintCommand = useOxlint && packageManager !== "deno" ? pmRun(packageManager, "lint") : void 0;
877
+ const formatCheckCommand = useOxfmt && packageManager !== "deno" ? pmRun(packageManager, "format:check") : void 0;
878
+ const testCommand = useVitest && packageManager !== "deno" ? pmRun(packageManager, "test") : void 0;
793
879
  await writeText(path.join(rootDir, ".github/workflows/ci.yml"), githubCliCiWorkflowTemplate({
794
880
  packageManager,
795
881
  nodeVersion: 22,
796
882
  workingDirectory,
797
883
  runLint: useOxlint,
798
884
  runFormatCheck: useOxfmt,
799
- runTests: useVitest
885
+ runTests: useVitest,
886
+ lintCommand,
887
+ formatCheckCommand,
888
+ testCommand
889
+ }));
890
+ if (addDependabot) await writeText(path.join(rootDir, ".github/dependabot.yml"), githubDependabotTemplate({
891
+ packageManager,
892
+ workingDirectory
800
893
  }));
801
894
  }
802
895
  if (githubActions === "ci+release") {
@@ -820,7 +913,7 @@ async function runInit({ nameArg }) {
820
913
  outro(`Done. Next:\n cd ${projectName}${!canInstall ? `\n (${packageManager} not found, run install manually)` : !installOk ? `\n (${packageManager} install failed, run install manually)` : ""}\n ${nextStepHint(packageManager)}`);
821
914
  }
822
915
  function validateProjectName(value) {
823
- const name = value.trim();
916
+ const name = (value ?? "").trim();
824
917
  if (!name) return "Project name is required";
825
918
  if (name.length > 214) return "Project name is too long";
826
919
  if (name.startsWith(".")) return "Project name cannot start with '.'";
@@ -834,13 +927,13 @@ function onCancel() {
834
927
  }
835
928
  function nextStepHint(pm) {
836
929
  switch (pm) {
837
- case "npm": return "npm run typecheck";
838
- case "pnpm": return "pnpm run typecheck";
839
- case "yarn": return "yarn typecheck";
840
- case "bun": return "bun run typecheck";
841
- case "deno": return "deno task typecheck # (or run the package.json scripts with your preferred runner)";
930
+ case "npm": return "npm run lint";
931
+ case "pnpm": return "pnpm run lint";
932
+ case "yarn": return "yarn lint";
933
+ case "bun": return "bun run lint";
934
+ case "deno": return "deno task lint # (or run the package.json scripts with your preferred runner)";
842
935
  }
843
936
  }
844
937
 
845
938
  //#endregion
846
- export { runCi as n, runInit as t };
939
+ export { oxlintConfigTemplate as a, githubDependabotTemplate as i, runCi as n, packageJsonTemplate as o, githubCliCiWorkflowTemplate as r, runInit as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontpl",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Interactive CLI to scaffold standardized frontend project templates.",
5
5
  "keywords": [
6
6
  "cli",
@@ -49,13 +49,14 @@
49
49
  "prepublishOnly": "pnpm run build"
50
50
  },
51
51
  "dependencies": {
52
- "@clack/prompts": "^0.11.0",
53
- "tiny-bin": "^1.11.3"
52
+ "@clack/prompts": "^1.0.0",
53
+ "tiny-bin": "^2.0.0"
54
54
  },
55
55
  "devDependencies": {
56
+ "@kingsword/lint-config": "^0.1.1",
56
57
  "@types/node": "^25.0.10",
57
- "oxfmt": "^0.26.0",
58
- "oxlint": "^1.41.0",
58
+ "oxfmt": "^0.28.0",
59
+ "oxlint": "^1.43.0",
59
60
  "oxlint-tsgolint": "^0.11.1",
60
61
  "tsdown": "^0.20.1",
61
62
  "typescript": "^5.9.3"