frontpl 0.3.0 → 0.3.2

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
@@ -30,6 +30,7 @@ Follow the prompts to choose:
30
30
  - Optional tooling: `oxlint`, `oxfmt`, `vitest`, `tsdown`
31
31
 
32
32
  When `oxlint` is enabled, generated projects use `@kingsword/lint-config` via `oxlint.config.ts`.
33
+ Generated lint-related dependencies (`oxlint`, `oxlint-tsgolint`, `oxfmt`, `@kingsword/lint-config`) default to `latest` in scaffolded `package.json`.
33
34
 
34
35
  - Git init
35
36
  - GitHub Actions workflows:
@@ -61,10 +62,11 @@ What it does:
61
62
  - Detects Node.js major version from `.nvmrc`, `.node-version`, or `package.json#engines.node` (defaults to `22`)
62
63
  - Generates `.github/workflows/ci.yml`
63
64
  - Optionally generates `.github/workflows/release.yml` (tag/commit/both)
65
+ - Optionally generates `.github/dependabot.yml` with grouped updates (`dependencies`, `github-actions`)
64
66
 
65
67
  ## GitHub Actions (CI + Release)
66
68
 
67
- frontpl generates workflows that call reusable workflows from `kingsword09/workflows` (pinned to `@v1` by default):
69
+ frontpl generates workflows that call reusable workflows from `kingsword09/workflows` (pinned to commit SHA + `# vX.Y.Z` comment by default):
68
70
 
69
71
  - CI: `cli-ci.yml`
70
72
  - Release (tag, recommended): `cli-release-tag.yml`
@@ -81,6 +83,15 @@ frontpl generates workflows that call reusable workflows from `kingsword09/workf
81
83
  - **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.
82
84
  - **NPM token**: set `trustedPublishing: false` and provide `NPM_TOKEN` in GitHub secrets.
83
85
 
86
+ ## Dependabot (optional)
87
+
88
+ When CI workflows are enabled, frontpl can also generate `.github/dependabot.yml`:
89
+
90
+ - Keeps `github-actions` updates enabled
91
+ - Adds grouped dependencies updates (`groups.dependencies`)
92
+ - Uses the selected `workingDirectory` (`.` -> `/`, monorepo package -> `/packages/<name>`)
93
+ - Maps JavaScript package managers (`npm`/`pnpm`/`yarn`/`bun`) to Dependabot `package-ecosystem: "npm"`
94
+
84
95
  ## Development
85
96
 
86
97
  ```sh
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-CQKT_mPD.mjs";
2
+ import { n as runCi, t as runInit } from "./init-oJwslpqP.mjs";
3
3
  import bin from "tiny-bin";
4
4
 
5
5
  //#region src/cli.ts
package/dist/index.d.mts CHANGED
@@ -41,6 +41,11 @@ declare function githubCliCiWorkflowTemplate(opts: {
41
41
  formatCheckCommand?: string;
42
42
  testCommand?: string;
43
43
  workflowsRef?: string;
44
+ workflowsVersion?: string;
45
+ }): string;
46
+ declare function githubDependabotTemplate(opts: {
47
+ packageManager: "npm" | "pnpm" | "yarn" | "bun" | "deno";
48
+ workingDirectory: string;
44
49
  }): string;
45
50
  //#endregion
46
- export { githubCliCiWorkflowTemplate, oxlintConfigTemplate, packageJsonTemplate, runCi, runInit };
51
+ export { githubCliCiWorkflowTemplate, githubDependabotTemplate, oxlintConfigTemplate, packageJsonTemplate, runCi, runInit };
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { a as packageJsonTemplate, i as oxlintConfigTemplate, n as runCi, r as githubCliCiWorkflowTemplate, t as runInit } from "./init-CQKT_mPD.mjs";
1
+ import { a as oxlintConfigTemplate, i as githubDependabotTemplate, n as runCi, o as packageJsonTemplate, r as githubCliCiWorkflowTemplate, t as runInit } from "./init-oJwslpqP.mjs";
2
2
 
3
- export { githubCliCiWorkflowTemplate, oxlintConfigTemplate, packageJsonTemplate, runCi, runInit };
3
+ export { githubCliCiWorkflowTemplate, githubDependabotTemplate, oxlintConfigTemplate, packageJsonTemplate, runCi, runInit };
@@ -144,8 +144,18 @@ function packageJsonTemplate(opts) {
144
144
  packageManager: opts.packageManager
145
145
  }, null, 2) + "\n";
146
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
+ }
147
157
  function githubCliCiWorkflowTemplate(opts) {
148
- const ref = opts.workflowsRef ?? "v1";
158
+ const { ref, versionComment } = resolveWorkflowsPin(opts);
149
159
  const installCommand = opts.installCommand?.trim();
150
160
  const lintCommand = opts.lintCommand?.trim();
151
161
  const formatCheckCommand = opts.formatCheckCommand?.trim();
@@ -161,7 +171,7 @@ function githubCliCiWorkflowTemplate(opts) {
161
171
  "",
162
172
  "jobs:",
163
173
  " ci:",
164
- ` uses: kingsword09/workflows/.github/workflows/cli-ci.yml@${ref}`,
174
+ ` uses: kingsword09/workflows/.github/workflows/cli-ci.yml@${ref}${versionComment}`,
165
175
  " with:",
166
176
  ` packageManager: ${opts.packageManager}`,
167
177
  ` nodeVersion: ${opts.nodeVersion}`,
@@ -177,7 +187,7 @@ function githubCliCiWorkflowTemplate(opts) {
177
187
  ].join("\n");
178
188
  }
179
189
  function githubCliReleaseWorkflowTemplate(opts) {
180
- const ref = opts.workflowsRef ?? "v1";
190
+ const { ref, versionComment } = resolveWorkflowsPin(opts);
181
191
  const trustedPublishing = opts.trustedPublishing;
182
192
  const needsNpmToken = opts.packageManager !== "deno" && trustedPublishing === false;
183
193
  return [
@@ -192,7 +202,7 @@ function githubCliReleaseWorkflowTemplate(opts) {
192
202
  " permissions:",
193
203
  " contents: write",
194
204
  " id-token: write",
195
- ` uses: kingsword09/workflows/.github/workflows/cli-release.yml@${ref}`,
205
+ ` uses: kingsword09/workflows/.github/workflows/cli-release.yml@${ref}${versionComment}`,
196
206
  " with:",
197
207
  ` packageManager: ${opts.packageManager}`,
198
208
  ` nodeVersion: ${opts.nodeVersion}`,
@@ -203,7 +213,7 @@ function githubCliReleaseWorkflowTemplate(opts) {
203
213
  ].join("\n");
204
214
  }
205
215
  function githubCliReleaseTagWorkflowTemplate(opts) {
206
- const ref = opts.workflowsRef ?? "v1";
216
+ const { ref, versionComment } = resolveWorkflowsPin(opts);
207
217
  const trustedPublishing = opts.trustedPublishing;
208
218
  const needsNpmToken = opts.packageManager !== "deno" && trustedPublishing === false;
209
219
  return [
@@ -218,7 +228,7 @@ function githubCliReleaseTagWorkflowTemplate(opts) {
218
228
  " permissions:",
219
229
  " contents: write",
220
230
  " id-token: write",
221
- ` uses: kingsword09/workflows/.github/workflows/cli-release-tag.yml@${ref}`,
231
+ ` uses: kingsword09/workflows/.github/workflows/cli-release-tag.yml@${ref}${versionComment}`,
222
232
  " with:",
223
233
  ` packageManager: ${opts.packageManager}`,
224
234
  ` nodeVersion: ${opts.nodeVersion}`,
@@ -229,7 +239,7 @@ function githubCliReleaseTagWorkflowTemplate(opts) {
229
239
  ].join("\n");
230
240
  }
231
241
  function githubCliReleaseBothWorkflowTemplate(opts) {
232
- const ref = opts.workflowsRef ?? "v1";
242
+ const { ref, versionComment } = resolveWorkflowsPin(opts);
233
243
  const trustedPublishing = opts.trustedPublishing;
234
244
  const needsNpmToken = opts.packageManager !== "deno" && trustedPublishing === false;
235
245
  return [
@@ -246,7 +256,7 @@ function githubCliReleaseBothWorkflowTemplate(opts) {
246
256
  " permissions:",
247
257
  " contents: write",
248
258
  " id-token: write",
249
- ` uses: kingsword09/workflows/.github/workflows/cli-release-tag.yml@${ref}`,
259
+ ` uses: kingsword09/workflows/.github/workflows/cli-release-tag.yml@${ref}${versionComment}`,
250
260
  " with:",
251
261
  ` packageManager: ${opts.packageManager}`,
252
262
  ` nodeVersion: ${opts.nodeVersion}`,
@@ -259,7 +269,7 @@ function githubCliReleaseBothWorkflowTemplate(opts) {
259
269
  " permissions:",
260
270
  " contents: write",
261
271
  " id-token: write",
262
- ` uses: kingsword09/workflows/.github/workflows/cli-release.yml@${ref}`,
272
+ ` uses: kingsword09/workflows/.github/workflows/cli-release.yml@${ref}${versionComment}`,
263
273
  " with:",
264
274
  ` packageManager: ${opts.packageManager}`,
265
275
  ` nodeVersion: ${opts.nodeVersion}`,
@@ -269,6 +279,56 @@ function githubCliReleaseBothWorkflowTemplate(opts) {
269
279
  ""
270
280
  ].join("\n");
271
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
+ }
272
332
  function yamlString(value) {
273
333
  return JSON.stringify(value);
274
334
  }
@@ -338,7 +398,7 @@ async function runCi() {
338
398
  const nodeVersionText = await text({
339
399
  message: "Node.js major version (for GitHub Actions)",
340
400
  initialValue: String(nodeVersionDefault),
341
- validate: (value) => {
401
+ validate: (value = "") => {
342
402
  const major = Number.parseInt(value.trim(), 10);
343
403
  if (!Number.isFinite(major) || major <= 0) return "Enter a valid major version (e.g. 22)";
344
404
  }
@@ -375,8 +435,14 @@ async function runCi() {
375
435
  initialValue: true
376
436
  }) : void 0;
377
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();
378
443
  const ciWorkflowPath = path.join(rootDir, ".github/workflows/ci.yml");
379
444
  const releaseWorkflowPath = path.join(rootDir, ".github/workflows/release.yml");
445
+ const dependabotPath = path.join(rootDir, ".github/dependabot.yml");
380
446
  if (!await confirmOverwriteIfExists(ciWorkflowPath, ".github/workflows/ci.yml")) {
381
447
  cancel("Skipped CI workflow");
382
448
  process.exitCode = 0;
@@ -401,7 +467,13 @@ async function runCi() {
401
467
  trustedPublishing
402
468
  }));
403
469
  }
404
- 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).");
405
477
  } catch (err) {
406
478
  if (err instanceof CancelledError) return;
407
479
  throw err;
@@ -532,7 +604,7 @@ async function promptCommand(message, initialValue) {
532
604
  const value = await text({
533
605
  message,
534
606
  initialValue,
535
- validate: (v) => !v.trim() ? "Command is required" : void 0
607
+ validate: (v = "") => !v.trim() ? "Command is required" : void 0
536
608
  });
537
609
  if (isCancel(value)) return abort();
538
610
  return String(value).trim();
@@ -737,6 +809,11 @@ async function runInit({ nameArg }) {
737
809
  ]
738
810
  }) : void 0;
739
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();
740
817
  const trustedPublishing = githubActions === "ci+release" && packageManager !== "deno" ? await confirm({
741
818
  message: "Release: npm trusted publishing (OIDC)?",
742
819
  initialValue: true
@@ -780,7 +857,7 @@ async function runInit({ nameArg }) {
780
857
  useOxlint,
781
858
  oxlintVersion: "latest",
782
859
  oxlintTsgolintVersion: "latest",
783
- kingswordLintConfigVersion: "^0.1.1",
860
+ kingswordLintConfigVersion: "latest",
784
861
  useOxfmt,
785
862
  oxfmtVersion: "latest",
786
863
  useVitest,
@@ -810,6 +887,10 @@ async function runInit({ nameArg }) {
810
887
  formatCheckCommand,
811
888
  testCommand
812
889
  }));
890
+ if (addDependabot) await writeText(path.join(rootDir, ".github/dependabot.yml"), githubDependabotTemplate({
891
+ packageManager,
892
+ workingDirectory
893
+ }));
813
894
  }
814
895
  if (githubActions === "ci+release") {
815
896
  const workingDirectory = pnpmWorkspace ? path.posix.join("packages", projectName) : ".";
@@ -832,7 +913,7 @@ async function runInit({ nameArg }) {
832
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)}`);
833
914
  }
834
915
  function validateProjectName(value) {
835
- const name = value.trim();
916
+ const name = (value ?? "").trim();
836
917
  if (!name) return "Project name is required";
837
918
  if (name.length > 214) return "Project name is too long";
838
919
  if (name.startsWith(".")) return "Project name cannot start with '.'";
@@ -855,4 +936,4 @@ function nextStepHint(pm) {
855
936
  }
856
937
 
857
938
  //#endregion
858
- export { packageJsonTemplate as a, oxlintConfigTemplate as i, runCi as n, githubCliCiWorkflowTemplate as r, 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.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Interactive CLI to scaffold standardized frontend project templates.",
5
5
  "keywords": [
6
6
  "cli",
@@ -49,15 +49,15 @@
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
56
  "@kingsword/lint-config": "^0.1.1",
57
57
  "@types/node": "^25.0.10",
58
- "oxfmt": "^0.28.0",
59
- "oxlint": "^1.43.0",
60
- "oxlint-tsgolint": "^0.11.1",
58
+ "oxfmt": "^0.31.0",
59
+ "oxlint": "^1.46.0",
60
+ "oxlint-tsgolint": "^0.11.5",
61
61
  "tsdown": "^0.20.1",
62
62
  "typescript": "^5.9.3"
63
63
  },