create-chanom-app 0.4.1 → 0.4.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/dist/index.js +29 -52
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import * as clack from "@clack/prompts";
|
|
|
5
5
|
import pc from "picocolors";
|
|
6
6
|
import { NodeContext, NodeRuntime } from "@effect/platform-node";
|
|
7
7
|
import { join } from "node:path";
|
|
8
|
-
|
|
8
|
+
// ../internal/src/domain/package-manager.ts
|
|
9
9
|
/** How to run a locally installed binary with each package manager. */
|
|
10
10
|
const PM_EXEC = {
|
|
11
11
|
pnpm: ["pnpm", "exec"],
|
|
@@ -38,8 +38,7 @@ function parsePmUserAgent(agent) {
|
|
|
38
38
|
function resolvePm(hints) {
|
|
39
39
|
return parsePmField(hints.packageManagerField) ?? parsePmUserAgent(hints.userAgent) ?? hints.fallback ?? "pnpm";
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
//#region ../internal/src/domain/vscode.ts
|
|
41
|
+
// ../internal/src/domain/vscode.ts
|
|
43
42
|
/** Keys VS Code reads as a per-language override, e.g. `[typescript]`. */
|
|
44
43
|
const LANGUAGES = [
|
|
45
44
|
"markdown",
|
|
@@ -75,8 +74,7 @@ function chanomSettings(oxfmtConfigPath) {
|
|
|
75
74
|
...Object.fromEntries(LANGUAGES.map((language) => [`[${language}]`, { "editor.defaultFormatter": OXC_FORMATTER }]))
|
|
76
75
|
};
|
|
77
76
|
}
|
|
78
|
-
|
|
79
|
-
//#region ../internal/src/services/command-runner.ts
|
|
77
|
+
// ../internal/src/services/command-runner.ts
|
|
80
78
|
const collectText = (stream) => stream.pipe(Stream.decodeText(), Stream.mkString);
|
|
81
79
|
/**
|
|
82
80
|
* Low-level process execution. Everything that shells out (git, package
|
|
@@ -112,8 +110,7 @@ var CommandRunner = class extends Effect.Service()("internal/CommandRunner", { e
|
|
|
112
110
|
execInherit
|
|
113
111
|
};
|
|
114
112
|
}) }) {};
|
|
115
|
-
|
|
116
|
-
//#region ../internal/src/services/git.ts
|
|
113
|
+
// ../internal/src/services/git.ts
|
|
117
114
|
/** Git operations, built on top of {@link CommandRunner}. */
|
|
118
115
|
var Git = class extends Effect.Service()("internal/Git", { effect: Effect.gen(function* () {
|
|
119
116
|
const runner = yield* CommandRunner;
|
|
@@ -162,8 +159,7 @@ var Git = class extends Effect.Service()("internal/Git", { effect: Effect.gen(fu
|
|
|
162
159
|
readGitignore: (cwd) => fs.readFileString(path.join(cwd, ".gitignore"))
|
|
163
160
|
};
|
|
164
161
|
}) }) {};
|
|
165
|
-
|
|
166
|
-
//#region ../internal/src/services/prompter.ts
|
|
162
|
+
// ../internal/src/services/prompter.ts
|
|
167
163
|
var Cancelled = class extends Data.TaggedError("Cancelled") {};
|
|
168
164
|
const guardCancel = (make) => Effect.promise(make).pipe(Effect.filterOrFail((result) => typeof result !== "symbol", () => new Cancelled()));
|
|
169
165
|
/**
|
|
@@ -205,8 +201,7 @@ var Prompter = class extends Effect.Service()("internal/Prompter", { succeed: {
|
|
|
205
201
|
return { stop: (stopMessage) => Effect.sync(() => s.stop(stopMessage)) };
|
|
206
202
|
})
|
|
207
203
|
} }) {};
|
|
208
|
-
|
|
209
|
-
//#region ../internal/src/skills/index.ts
|
|
204
|
+
// ../internal/src/skills/index.ts
|
|
210
205
|
/**
|
|
211
206
|
* The coding-standards skill, targeting the stack `create-chanom-app` scaffolds
|
|
212
207
|
* (Vite + React + TypeScript, oxlint, oxfmt, vitest). Its markdown is authored
|
|
@@ -257,8 +252,7 @@ function skillLink(skill) {
|
|
|
257
252
|
target: `../../${SKILLS_ROOT}/${skill.name}`
|
|
258
253
|
};
|
|
259
254
|
}
|
|
260
|
-
|
|
261
|
-
//#region src/bundled-versions.ts
|
|
255
|
+
// src/bundled-versions.ts
|
|
262
256
|
const depVersions = {
|
|
263
257
|
"react": "19.2.8",
|
|
264
258
|
"react-dom": "19.2.8",
|
|
@@ -266,27 +260,26 @@ const depVersions = {
|
|
|
266
260
|
"@tsconfig/vite-react": "8.1.1",
|
|
267
261
|
"@types/react": "19.2.17",
|
|
268
262
|
"@types/react-dom": "19.2.3",
|
|
269
|
-
"typescript": "
|
|
263
|
+
"typescript": "7.0.2",
|
|
270
264
|
"vite": "8.1.0",
|
|
271
265
|
"vitest": "3.2.6",
|
|
272
266
|
"@vitest/coverage-v8": "3.2.6",
|
|
273
267
|
"jsdom": "30.0.0",
|
|
274
268
|
"@testing-library/react": "16.3.2",
|
|
275
269
|
"@testing-library/jest-dom": "7.0.0",
|
|
276
|
-
"oxlint": "1.
|
|
277
|
-
"oxlint-tsgolint": "0.
|
|
278
|
-
"oxfmt": "0.
|
|
270
|
+
"oxlint": "1.89.0",
|
|
271
|
+
"oxlint-tsgolint": "7.0.2005",
|
|
272
|
+
"oxfmt": "0.74.0",
|
|
279
273
|
"husky": "9.1.7",
|
|
280
274
|
"lint-staged": "17.0.8",
|
|
281
275
|
"@commitlint/cli": "21.2.0",
|
|
282
276
|
"@commitlint/config-conventional": "21.2.0",
|
|
283
|
-
"@chanom/dev-config": "0.0.
|
|
277
|
+
"@chanom/dev-config": "0.0.5",
|
|
284
278
|
"@chanom/vite-config": "0.1.1"
|
|
285
279
|
};
|
|
286
280
|
/** This package's own version, for `--version`. */
|
|
287
|
-
const pkgVersion = "0.4.
|
|
288
|
-
|
|
289
|
-
//#region src/domain/args.ts
|
|
281
|
+
const pkgVersion = "0.4.2";
|
|
282
|
+
// src/domain/args.ts
|
|
290
283
|
const PACKAGE_MANAGERS = [
|
|
291
284
|
"pnpm",
|
|
292
285
|
"npm",
|
|
@@ -390,8 +383,7 @@ function validateProjectName(name) {
|
|
|
390
383
|
if (!/^[a-z0-9._-]+$/i.test(name)) return "Use letters, numbers, dots, dashes, and underscores only.";
|
|
391
384
|
if (name.startsWith(".")) return "Name cannot start with a dot.";
|
|
392
385
|
}
|
|
393
|
-
|
|
394
|
-
//#region src/domain/project-name.ts
|
|
386
|
+
// src/domain/project-name.ts
|
|
395
387
|
/**
|
|
396
388
|
* Converts a project name to the lowercase kebab-case format expected for an
|
|
397
389
|
* unscoped npm package name.
|
|
@@ -399,8 +391,7 @@ function validateProjectName(name) {
|
|
|
399
391
|
function toKebabCase(name) {
|
|
400
392
|
return name.replace(/([A-Z]+)([A-Z][a-z])/g, "$1-$2").replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[._\s-]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
|
|
401
393
|
}
|
|
402
|
-
|
|
403
|
-
//#region src/domain/contribution.ts
|
|
394
|
+
// src/domain/contribution.ts
|
|
404
395
|
const emptyContribution = {
|
|
405
396
|
dependencies: [],
|
|
406
397
|
devDependencies: [],
|
|
@@ -435,8 +426,7 @@ function mergeContributions(contributions) {
|
|
|
435
426
|
links: [...linksByPath.values()]
|
|
436
427
|
};
|
|
437
428
|
}
|
|
438
|
-
|
|
439
|
-
//#region src/generate/app-template.ts
|
|
429
|
+
// src/generate/app-template.ts
|
|
440
430
|
/**
|
|
441
431
|
* Replaces the placeholder app name in the generated component and its test.
|
|
442
432
|
* The app name is normalized before it reaches this renderer.
|
|
@@ -444,8 +434,7 @@ function mergeContributions(contributions) {
|
|
|
444
434
|
function renderAppTemplate(template, appName) {
|
|
445
435
|
return template.replaceAll("my-app", appName);
|
|
446
436
|
}
|
|
447
|
-
|
|
448
|
-
//#region src/generate/index-html.ts
|
|
437
|
+
// src/generate/index-html.ts
|
|
449
438
|
/**
|
|
450
439
|
* Renders `index.html` with the app name as its `<title>`. This is the one file
|
|
451
440
|
* whose content varies by project name, so it is generated rather than copied;
|
|
@@ -466,8 +455,7 @@ function renderIndexHtml(appName) {
|
|
|
466
455
|
</html>
|
|
467
456
|
`;
|
|
468
457
|
}
|
|
469
|
-
|
|
470
|
-
//#region src/domain/versions.ts
|
|
458
|
+
// src/domain/versions.ts
|
|
471
459
|
/**
|
|
472
460
|
* Pinned version for `name`, throwing when it is absent. Missing keys are a
|
|
473
461
|
* build/catalog bug (the strict build-time reader should have already caught
|
|
@@ -478,8 +466,7 @@ function resolveVersion(versions, name) {
|
|
|
478
466
|
if (version === void 0) throw new Error(`No pinned version for "${name}". The dependency version map is incomplete.`);
|
|
479
467
|
return version;
|
|
480
468
|
}
|
|
481
|
-
|
|
482
|
-
//#region src/generate/package-json.ts
|
|
469
|
+
// src/generate/package-json.ts
|
|
483
470
|
/** Resolves each name to its exact pinned version, sorted for deterministic output. */
|
|
484
471
|
function toDependencyMap(names, versions) {
|
|
485
472
|
const map = {};
|
|
@@ -508,8 +495,7 @@ function buildPackageJson(input) {
|
|
|
508
495
|
};
|
|
509
496
|
return JSON.stringify(pkg, null, 2) + "\n";
|
|
510
497
|
}
|
|
511
|
-
|
|
512
|
-
//#region src/generate/pnpm-workspace.ts
|
|
498
|
+
// src/generate/pnpm-workspace.ts
|
|
513
499
|
/**
|
|
514
500
|
* Build scripts pnpm must be told to run for the generated app. pnpm v10 blocks
|
|
515
501
|
* every dependency lifecycle script unless it is allow-listed; esbuild (pulled
|
|
@@ -532,8 +518,7 @@ function buildPnpmWorkspace() {
|
|
|
532
518
|
...allowBuilds.map((name) => ` ${name}: true`)
|
|
533
519
|
].join("\n") + "\n";
|
|
534
520
|
}
|
|
535
|
-
|
|
536
|
-
//#region src/generate/readme.ts
|
|
521
|
+
// src/generate/readme.ts
|
|
537
522
|
/**
|
|
538
523
|
* Replaces the template's project heading with the generated package name.
|
|
539
524
|
* Keeping the rest of the template untouched makes README updates independent
|
|
@@ -542,8 +527,7 @@ function buildPnpmWorkspace() {
|
|
|
542
527
|
function renderReadme(template, appName) {
|
|
543
528
|
return template.replace(/^# my-app$/m, `# ${appName}`);
|
|
544
529
|
}
|
|
545
|
-
|
|
546
|
-
//#region src/generate/tsconfig.ts
|
|
530
|
+
// src/generate/tsconfig.ts
|
|
547
531
|
const TSCONFIG = {
|
|
548
532
|
extends: "@tsconfig/vite-react/tsconfig.json",
|
|
549
533
|
compilerOptions: { types: ["vite/client", "vitest/globals"] },
|
|
@@ -553,8 +537,7 @@ const TSCONFIG = {
|
|
|
553
537
|
function buildTsconfig() {
|
|
554
538
|
return JSON.stringify(TSCONFIG, null, 2) + "\n";
|
|
555
539
|
}
|
|
556
|
-
|
|
557
|
-
//#region src/generate/vite-config.ts
|
|
540
|
+
// src/generate/vite-config.ts
|
|
558
541
|
/**
|
|
559
542
|
* Renders `vite.config.ts` from the folded contribution's Vite imports and
|
|
560
543
|
* plugin list. Generated (not a static template) so a future topping can add
|
|
@@ -564,8 +547,7 @@ function buildTsconfig() {
|
|
|
564
547
|
function renderViteConfig(contribution) {
|
|
565
548
|
return `${["import { createViteConfig } from '@chanom/vite-config';", ...contribution.viteImports].join("\n")}\n\nexport default createViteConfig({ plugins: [${contribution.vitePlugins.join(", ")}] });\n`;
|
|
566
549
|
}
|
|
567
|
-
|
|
568
|
-
//#region src/templates.ts
|
|
550
|
+
// src/templates.ts
|
|
569
551
|
/**
|
|
570
552
|
* Template files copied into every generated app. Source files use
|
|
571
553
|
* a `.template` suffix so repository tooling does not lint, format, or type-check
|
|
@@ -621,8 +603,7 @@ const TEMPLATE_FILES = [
|
|
|
621
603
|
dest: "src/vite-env.d.ts"
|
|
622
604
|
}
|
|
623
605
|
];
|
|
624
|
-
|
|
625
|
-
//#region src/toppings.ts
|
|
606
|
+
// src/toppings.ts
|
|
626
607
|
const asJson = (value) => JSON.stringify(value, null, 2) + "\n";
|
|
627
608
|
/**
|
|
628
609
|
* The always-present baseline: a minimal Vite + React + TS app wired to the
|
|
@@ -739,8 +720,7 @@ function selectContributions(selection) {
|
|
|
739
720
|
if (selection.agentSkills) contributions.push(agentSkills);
|
|
740
721
|
return contributions;
|
|
741
722
|
}
|
|
742
|
-
|
|
743
|
-
//#region src/scaffold.ts
|
|
723
|
+
// src/scaffold.ts
|
|
744
724
|
var InstallFailed = class extends Data.TaggedError("InstallFailed") {};
|
|
745
725
|
const writeFile = Effect.fn("scaffold.writeFile")(function* (targetDir, relPath, contents) {
|
|
746
726
|
const fs = yield* FileSystem.FileSystem;
|
|
@@ -830,8 +810,7 @@ const scaffold = Effect.fn("scaffold")(function* (plan) {
|
|
|
830
810
|
if (plan.git) yield* initGit(plan);
|
|
831
811
|
if (plan.install) yield* installDependencies(plan);
|
|
832
812
|
});
|
|
833
|
-
|
|
834
|
-
//#region src/cli.ts
|
|
813
|
+
// src/cli.ts
|
|
835
814
|
const DEFAULT_NAME = "my-chanom-app";
|
|
836
815
|
const HELP = `${pc.bold("create-chanom-app")} ${pc.dim("- scaffold a Vite + React + TS app")}
|
|
837
816
|
|
|
@@ -969,8 +948,7 @@ const run = (argv, cwd, options) => {
|
|
|
969
948
|
InstallFailed: (e) => reportError([`Dependency installation with ${e.pm} failed.`, e.output].filter(Boolean).join("\n"))
|
|
970
949
|
}), Effect.catchAll((e) => reportError(`Unexpected error: ${e.message}`)), Logger.withMinimumLogLevel(debug ? LogLevel.Debug : LogLevel.Info));
|
|
971
950
|
};
|
|
972
|
-
|
|
973
|
-
//#region src/index.ts
|
|
951
|
+
// src/index.ts
|
|
974
952
|
const debug = process.argv.includes("--debug");
|
|
975
953
|
const argv = process.argv.slice(2).filter((arg) => arg !== "--debug");
|
|
976
954
|
const templatesRoot = join(import.meta.dirname, "templates");
|
|
@@ -988,5 +966,4 @@ NodeRuntime.runMain(program, {
|
|
|
988
966
|
disableErrorReporting: true,
|
|
989
967
|
disablePrettyLogger: true
|
|
990
968
|
});
|
|
991
|
-
//#endregion
|
|
992
969
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-chanom-app",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Scaffold a Vite + React + TypeScript app, wired to the chanom shared configs.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"create",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"@tsconfig/node-ts": "23.6.4",
|
|
40
40
|
"@types/node": "26.0.1",
|
|
41
41
|
"@vitest/coverage-v8": "3.2.6",
|
|
42
|
-
"tsdown": "0.
|
|
43
|
-
"typescript": "
|
|
42
|
+
"tsdown": "0.23.1",
|
|
43
|
+
"typescript": "7.0.2",
|
|
44
44
|
"vitest": "3.2.6",
|
|
45
|
-
"@chanom/dev-config": "0.0.
|
|
45
|
+
"@chanom/dev-config": "0.0.5",
|
|
46
46
|
"@chanom/internal": "0.0.0"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|