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 +21 -4
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +41 -1
- package/dist/index.mjs +2 -2
- package/dist/{init-DXlH6jJs.mjs → init-BGuupDrG.mjs} +134 -41
- package/package.json +6 -5
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
|
|
48
|
+
- `package.json` (+ scripts like optional `lint`, `format:check`, `test`, `build`)
|
|
46
49
|
- `tsconfig.json`, `src/index.ts`
|
|
47
|
-
- Optional configs:
|
|
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
|
|
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
|
|
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
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
|
-
|
|
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-
|
|
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
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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 = {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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 &&
|
|
531
|
-
formatCheckCommand: runFormatCheck &&
|
|
532
|
-
testCommand: runTests &&
|
|
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 (
|
|
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, ".
|
|
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
|
|
838
|
-
case "pnpm": return "pnpm run
|
|
839
|
-
case "yarn": return "yarn
|
|
840
|
-
case "bun": return "bun run
|
|
841
|
-
case "deno": return "deno task
|
|
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.
|
|
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.
|
|
53
|
-
"tiny-bin": "^
|
|
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.
|
|
58
|
-
"oxlint": "^1.
|
|
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"
|