spinup-ts 0.1.0

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.
Files changed (138) hide show
  1. package/README.md +82 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +96 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/prompts.d.ts +17 -0
  7. package/dist/prompts.d.ts.map +1 -0
  8. package/dist/prompts.js +264 -0
  9. package/dist/prompts.js.map +1 -0
  10. package/dist/scaffold.d.ts +5 -0
  11. package/dist/scaffold.d.ts.map +1 -0
  12. package/dist/scaffold.js +128 -0
  13. package/dist/scaffold.js.map +1 -0
  14. package/dist/transforms/devcontainer.d.ts +3 -0
  15. package/dist/transforms/devcontainer.d.ts.map +1 -0
  16. package/dist/transforms/devcontainer.js +8 -0
  17. package/dist/transforms/devcontainer.js.map +1 -0
  18. package/dist/transforms/docker.d.ts +3 -0
  19. package/dist/transforms/docker.d.ts.map +1 -0
  20. package/dist/transforms/docker.js +11 -0
  21. package/dist/transforms/docker.js.map +1 -0
  22. package/dist/transforms/docs.d.ts +3 -0
  23. package/dist/transforms/docs.d.ts.map +1 -0
  24. package/dist/transforms/docs.js +22 -0
  25. package/dist/transforms/docs.js.map +1 -0
  26. package/dist/transforms/documentation.d.ts +3 -0
  27. package/dist/transforms/documentation.d.ts.map +1 -0
  28. package/dist/transforms/documentation.js +37 -0
  29. package/dist/transforms/documentation.js.map +1 -0
  30. package/dist/transforms/github-actions.d.ts +3 -0
  31. package/dist/transforms/github-actions.d.ts.map +1 -0
  32. package/dist/transforms/github-actions.js +48 -0
  33. package/dist/transforms/github-actions.js.map +1 -0
  34. package/dist/transforms/index.d.ts +3 -0
  35. package/dist/transforms/index.d.ts.map +1 -0
  36. package/dist/transforms/index.js +24 -0
  37. package/dist/transforms/index.js.map +1 -0
  38. package/dist/transforms/license.d.ts +3 -0
  39. package/dist/transforms/license.d.ts.map +1 -0
  40. package/dist/transforms/license.js +19 -0
  41. package/dist/transforms/license.js.map +1 -0
  42. package/dist/transforms/npm-publish.d.ts +3 -0
  43. package/dist/transforms/npm-publish.d.ts.map +1 -0
  44. package/dist/transforms/npm-publish.js +15 -0
  45. package/dist/transforms/npm-publish.js.map +1 -0
  46. package/dist/transforms/package-manager.d.ts +3 -0
  47. package/dist/transforms/package-manager.d.ts.map +1 -0
  48. package/dist/transforms/package-manager.js +31 -0
  49. package/dist/transforms/package-manager.js.map +1 -0
  50. package/dist/types.d.ts +116 -0
  51. package/dist/types.d.ts.map +1 -0
  52. package/dist/types.js +52 -0
  53. package/dist/types.js.map +1 -0
  54. package/dist/update.d.ts +2 -0
  55. package/dist/update.d.ts.map +1 -0
  56. package/dist/update.js +207 -0
  57. package/dist/update.js.map +1 -0
  58. package/package.json +94 -0
  59. package/template/.commitlintrc.json +3 -0
  60. package/template/.devcontainer/.zshrc +159 -0
  61. package/template/.devcontainer/DISCOVER-DEPS.md +109 -0
  62. package/template/.devcontainer/README.md +223 -0
  63. package/template/.devcontainer/SETUP.md +191 -0
  64. package/template/.devcontainer/TOOLS.md +215 -0
  65. package/template/.devcontainer/devcontainer.json +106 -0
  66. package/template/.devcontainer/scripts/init-project.sh +167 -0
  67. package/template/.editorconfig +12 -0
  68. package/template/.github/.release-please-manifest.json +3 -0
  69. package/template/.github/ISSUE_TEMPLATE/bug_report.md +21 -0
  70. package/template/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
  71. package/template/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  72. package/template/.github/actions/setup-node-env/action.yml +20 -0
  73. package/template/.github/dependabot.yml +17 -0
  74. package/template/.github/labeler.yml +17 -0
  75. package/template/.github/release-please-config.json +7 -0
  76. package/template/.github/workflows/ci.yml +95 -0
  77. package/template/.github/workflows/codeql.yml +31 -0
  78. package/template/.github/workflows/labeler.yml +18 -0
  79. package/template/.github/workflows/release-please.yml +72 -0
  80. package/template/.github/workflows/stale.yml +32 -0
  81. package/template/.husky/commit-msg +1 -0
  82. package/template/.husky/pre-commit +1 -0
  83. package/template/.nvmrc +1 -0
  84. package/template/.vscode/extensions.json +11 -0
  85. package/template/.vscode/settings.json +12 -0
  86. package/template/AGENTS.md +1 -0
  87. package/template/CHANGELOG.md +11 -0
  88. package/template/CLAUDE.md +0 -0
  89. package/template/CONTRIBUTING.md +22 -0
  90. package/template/Dockerfile +21 -0
  91. package/template/LICENSE.Apache-2.0 +17 -0
  92. package/template/LICENSE.BSD-3-Clause +28 -0
  93. package/template/LICENSE.GPL-3.0 +17 -0
  94. package/template/LICENSE.ISC +15 -0
  95. package/template/LICENSE.MIT +21 -0
  96. package/template/README.md +62 -0
  97. package/template/biome.json +49 -0
  98. package/template/docker-compose.yml +7 -0
  99. package/template/docs/architecture/api-layer.md +44 -0
  100. package/template/docs/architecture/constitution.md +24 -0
  101. package/template/docs/architecture/data-model.md +24 -0
  102. package/template/docs/architecture/index.md +15 -0
  103. package/template/docs/architecture/project.md +24 -0
  104. package/template/docs/architecture/quality-checks.md +28 -0
  105. package/template/docs/architecture/testing-plan.md +35 -0
  106. package/template/docs/architecture/ui.md +37 -0
  107. package/template/docs/changelog.md +9 -0
  108. package/template/docs/contributing.md +46 -0
  109. package/template/docs/developer-guide/architecture.md +22 -0
  110. package/template/docs/developer-guide/contributing.md +30 -0
  111. package/template/docs/developer-guide/data-model.md +25 -0
  112. package/template/docs/developer-guide/index.md +12 -0
  113. package/template/docs/developer-guide/testing.md +40 -0
  114. package/template/docs/examples.md +37 -0
  115. package/template/docs/getting-started.md +42 -0
  116. package/template/docs/installation.md +45 -0
  117. package/template/docs/intro.md +60 -0
  118. package/template/docs/post-mortems/.gitkeep +0 -0
  119. package/template/docs/reference/cli.md +32 -0
  120. package/template/docs/reference/configuration.md +33 -0
  121. package/template/docs/reference/hooks.md +27 -0
  122. package/template/docs/research/competitor-analysis.md +21 -0
  123. package/template/docs/research/real-world-demand.md +21 -0
  124. package/template/docs/user-guide/configuration.md +32 -0
  125. package/template/docs/user-guide/features.md +21 -0
  126. package/template/docs/user-guide/how-it-works.md +29 -0
  127. package/template/docs/user-guide/index.md +11 -0
  128. package/template/docusaurus.config.ts +93 -0
  129. package/template/eslint.config.mjs +66 -0
  130. package/template/justfile +51 -0
  131. package/template/package.json +88 -0
  132. package/template/pnpm-workspace.yaml +8 -0
  133. package/template/sidebars.ts +72 -0
  134. package/template/src/index.ts +3 -0
  135. package/template/static/img/logo.svg +4 -0
  136. package/template/tests/index.test.ts +8 -0
  137. package/template/tsconfig.json +23 -0
  138. package/template/vitest.config.ts +19 -0
package/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # spinup-ts
2
+
3
+ Scaffold a production-ready TypeScript project with opinionated tooling — the TypeScript sibling of [spinup-py](https://github.com/joeblackwaslike/spinup-py) and the TypeScript equivalent of [cookiecutter-uv](https://github.com/joeblackwaslike/cookiecutter-uv).
4
+
5
+ `spinup-ts` ⇄ `spinup-py` share the same CLI schema, so remembering one gives you the other.
6
+
7
+ ## Usage
8
+
9
+ ```bash
10
+ # New project (interactive)
11
+ npx spinup-ts my-project
12
+ # or: pnpm dlx spinup-ts my-project
13
+ # or: bunx spinup-ts my-project
14
+
15
+ # New project (defaults only, no prompts)
16
+ npx spinup-ts my-project --non-interactive
17
+
18
+ # Retrofit an existing repo with template tooling
19
+ npx spinup-ts update .
20
+ ```
21
+
22
+ Install globally if you scaffold often:
23
+
24
+ ```bash
25
+ npm i -g spinup-ts
26
+ spinup-ts my-project
27
+ ```
28
+
29
+ ## CLI
30
+
31
+ ```text
32
+ spinup-ts [new] <project-name> Scaffold a new TypeScript project
33
+ spinup-ts update [dir] Retrofit an existing repo with template tooling
34
+ spinup-ts --update [dir] Alias for `update`
35
+
36
+ -y, --yes, --non-interactive Scaffold with defaults only, no prompts (needs <project-name>)
37
+ -v, --version Print version
38
+ -h, --help Show this help
39
+ ```
40
+
41
+ Non-interactive defaults resolve from `~/.spinup-tsrc.json`, then local `git config`
42
+ (author name/email), then built-in fallbacks.
43
+
44
+ ## What's Included
45
+
46
+ | Python (cookiecutter-uv) | TypeScript equivalent |
47
+ |---|---|
48
+ | `uv` | `pnpm` |
49
+ | `ruff` | `Biome` |
50
+ | `wemake-python-styleguide` | ESLint strict (unicorn + sonarjs + import-x) |
51
+ | `mypy --strict` | `tsc --noEmit` + `@typescript-eslint/strictTypeChecked` |
52
+ | `pytest` + `coverage` | `Vitest` + `@vitest/coverage-v8` |
53
+ | `mkdocs-material` | `Docusaurus` |
54
+ | `deptry` | `depcheck` |
55
+ | `pre-commit` | `Husky` + `lint-staged` + `commitlint` |
56
+ | `Makefile` | `justfile` |
57
+ | `tox` (multi-version) | CI matrix over Node 20/22 |
58
+ | `release-please` | `release-please` (`release-type: node`) |
59
+
60
+ ## Prompt Options
61
+
62
+ - **Project name** — kebab-case slug
63
+ - **Description** — one-liner
64
+ - **Author / Email / GitHub handle**
65
+ - **Node version** — 20, 22, 23
66
+ - **Package manager** — pnpm (default), bun, npm
67
+ - **Project type** — library, cli, server, mcp-server
68
+ - **GitHub Actions** — CI + release workflows
69
+ - **Publish to npm** — with provenance
70
+ - **Docusaurus docs** — deployed to GitHub Pages on release
71
+ - **Codecov** — coverage reporting
72
+ - **Dockerfile** — multi-stage Node build
73
+ - **Devcontainer** — full Claude Code-optimized environment
74
+ - **License** — MIT, Apache 2.0, BSD, ISC, GPL-3, None
75
+
76
+ ## Development
77
+
78
+ ```bash
79
+ pnpm install
80
+ pnpm build
81
+ pnpm test
82
+ ```
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire } from 'node:module';
3
+ import path from 'node:path';
4
+ import * as clack from '@clack/prompts';
5
+ // eslint-disable-next-line import-x/no-unresolved
6
+ import { buildDefaultConfig, runPrompts } from './prompts.js';
7
+ // eslint-disable-next-line import-x/no-unresolved
8
+ import { checkDestinationDir, scaffold } from './scaffold.js';
9
+ // eslint-disable-next-line import-x/no-unresolved
10
+ import { updateProject } from './update.js';
11
+ const require = createRequire(import.meta.url);
12
+ const packageJson = require('../package.json');
13
+ const HELP_TEXT = `spinup-ts — scaffold a production-ready TypeScript project (sibling of spinup-py)
14
+
15
+ Usage:
16
+ spinup-ts [new] <project-name> Scaffold a new TypeScript project
17
+ spinup-ts update [dir] Retrofit an existing repo with template tooling
18
+ spinup-ts --update [dir] Alias for \`update\`
19
+
20
+ Options:
21
+ -y, --yes, --non-interactive Scaffold with defaults only, no prompts (needs <project-name>)
22
+ -v, --version Print version
23
+ -h, --help Show this help
24
+
25
+ Examples:
26
+ spinup-ts my-lib
27
+ spinup-ts new my-lib
28
+ spinup-ts my-lib --non-interactive
29
+ spinup-ts update .
30
+ spinup-ts --update /path/to/repo
31
+ `;
32
+ function parseArgs(argv) {
33
+ const help = argv.includes('--help') || argv.includes('-h');
34
+ const version = argv.includes('--version') || argv.includes('-v');
35
+ const nonInteractive = argv.includes('--non-interactive') || argv.includes('--yes') || argv.includes('-y');
36
+ const updateFlag = argv.includes('--update') || argv.includes('-u');
37
+ const positionals = argv.filter((a) => !a.startsWith('-'));
38
+ // Subcommand form: `new <name>` / `update [dir]`
39
+ if (positionals[0] === 'new') {
40
+ return { command: 'new', name: positionals[1], nonInteractive, help, version };
41
+ }
42
+ if (positionals[0] === 'update') {
43
+ return { command: 'update', dir: positionals[1], nonInteractive, help, version };
44
+ }
45
+ // Flag form: `--update [dir]`
46
+ if (updateFlag) {
47
+ return { command: 'update', dir: positionals[0], nonInteractive, help, version };
48
+ }
49
+ // Bare form: `spinup-ts <name>`
50
+ return { command: 'new', name: positionals[0], nonInteractive, help, version };
51
+ }
52
+ async function runCreate(projectName, nonInteractive) {
53
+ const destDir = path.resolve(projectName ?? '.');
54
+ await checkDestinationDir(destDir);
55
+ let config;
56
+ if (nonInteractive) {
57
+ if (!projectName) {
58
+ throw new Error('A project name is required in non-interactive mode: spinup-ts <name> --yes');
59
+ }
60
+ config = await buildDefaultConfig(projectName);
61
+ }
62
+ else {
63
+ config = await runPrompts(projectName);
64
+ }
65
+ await scaffold(destDir, config);
66
+ clack.outro(`Project created at ${destDir}`);
67
+ }
68
+ async function runUpdate(targetDir) {
69
+ await updateProject(path.resolve(targetDir));
70
+ }
71
+ async function main() {
72
+ const args = parseArgs(process.argv.slice(2));
73
+ if (args.help) {
74
+ process.stdout.write(HELP_TEXT);
75
+ return;
76
+ }
77
+ if (args.version) {
78
+ process.stdout.write(`${packageJson.version}\n`);
79
+ return;
80
+ }
81
+ if (args.command === 'update') {
82
+ await runUpdate(args.dir ?? '.');
83
+ return;
84
+ }
85
+ await runCreate(args.name, args.nonInteractive);
86
+ }
87
+ await main().catch((error) => {
88
+ if (error instanceof Error) {
89
+ clack.log.error(error.message);
90
+ }
91
+ else {
92
+ clack.log.error(String(error));
93
+ }
94
+ process.exit(1);
95
+ });
96
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type ProjectConfig } from './types.js';
2
+ /**
3
+ * Run the full interactive prompt flow and return a validated {@link ProjectConfig}.
4
+ *
5
+ * @param projectName - Optional name from CLI args; when provided, the name prompt is skipped.
6
+ */
7
+ export declare function runPrompts(projectName?: string): Promise<ProjectConfig>;
8
+ /**
9
+ * Build a {@link ProjectConfig} from defaults only, with no interactive prompts.
10
+ *
11
+ * Resolution order for each field: `~/.spinup-tsrc.json` → local `git config` (author
12
+ * name/email) → built-in fallback. Mirrors spinup-py's `--non-interactive` / `--yes` mode.
13
+ *
14
+ * @param projectName - kebab-case project name (required; validated here).
15
+ */
16
+ export declare function buildDefaultConfig(projectName: string): Promise<ProjectConfig>;
17
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,YAAY,CAAC;AA4FpB;;;;GAIG;AAEH,wBAAsB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA8K7E;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CA8BpF"}
@@ -0,0 +1,264 @@
1
+ import { exec } from 'node:child_process';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { homedir } from 'node:os';
4
+ import path from 'node:path';
5
+ import { promisify } from 'node:util';
6
+ import * as clack from '@clack/prompts';
7
+ /* eslint-disable import-x/no-unresolved */
8
+ import { deriveSlug, projectConfigSchema, userDefaultsSchema, } from './types.js';
9
+ /* eslint-enable import-x/no-unresolved */
10
+ const execAsync = promisify(exec);
11
+ const RC_PATH = path.join(homedir(), '.spinup-tsrc.json');
12
+ async function loadUserDefaults() {
13
+ try {
14
+ const raw = await readFile(RC_PATH, 'utf8');
15
+ const result = userDefaultsSchema.safeParse(JSON.parse(raw));
16
+ return result.success ? result.data : {};
17
+ }
18
+ catch {
19
+ return {};
20
+ }
21
+ }
22
+ /** Read a single `git config` value, returning undefined if unset or git is unavailable. */
23
+ async function gitConfigValue(key) {
24
+ try {
25
+ const { stdout } = await execAsync(`git config --get ${key}`);
26
+ return stdout.trim() || undefined;
27
+ }
28
+ catch {
29
+ return undefined;
30
+ }
31
+ }
32
+ /** kebab-case identifier: starts with a letter, then letters/digits/hyphens. */
33
+ const KEBAB_CASE = /^[a-z][a-z0-9-]*$/;
34
+ /** Lightweight RFC 5322-ish email check; full validation happens in Zod. */
35
+ // eslint-disable-next-line sonarjs/slow-regex
36
+ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
37
+ /**
38
+ * Narrow a clack prompt result, exiting cleanly if the user cancelled.
39
+ * Returns the value typed as `T` on success.
40
+ */
41
+ function unwrap(value) {
42
+ if (clack.isCancel(value)) {
43
+ clack.cancel('Operation cancelled.');
44
+ process.exit(0);
45
+ }
46
+ return value;
47
+ }
48
+ /** Validator for the project name text prompt. */
49
+ function validateProjectName(value) {
50
+ if (!value)
51
+ return 'Project name is required';
52
+ if (!KEBAB_CASE.test(value)) {
53
+ return 'Use kebab-case: lowercase letters, numbers, hyphens; start with a letter';
54
+ }
55
+ return undefined;
56
+ }
57
+ /** Validator for the author email text prompt. */
58
+ function validateEmail(value) {
59
+ if (!value)
60
+ return 'Email is required';
61
+ if (!EMAIL_RE.test(value))
62
+ return 'Enter a valid email address';
63
+ return undefined;
64
+ }
65
+ /** Prompt for the project name, or return the provided CLI arg if valid. */
66
+ async function promptProjectName(provided) {
67
+ if (provided !== undefined) {
68
+ const err = validateProjectName(provided);
69
+ if (err) {
70
+ clack.cancel(`Invalid project name "${provided}": ${err}`);
71
+ process.exit(1);
72
+ }
73
+ return provided;
74
+ }
75
+ const value = await clack.text({
76
+ message: 'Project name?',
77
+ placeholder: 'my-awesome-lib',
78
+ validate: validateProjectName,
79
+ });
80
+ return unwrap(value);
81
+ }
82
+ /** Build the human-readable feature summary line. */
83
+ function summarizeFeatures(config) {
84
+ const features = [];
85
+ if (config.includeGithubActions)
86
+ features.push('GitHub Actions');
87
+ if (config.publishToNpm)
88
+ features.push('npm publish');
89
+ if (config.includeDocs)
90
+ features.push('Docusaurus docs');
91
+ if (config.includeCodecov)
92
+ features.push('Codecov');
93
+ if (config.includeDockerfile)
94
+ features.push('Dockerfile');
95
+ if (config.includeDevcontainer)
96
+ features.push('devcontainer');
97
+ features.push(`${config.license} license`);
98
+ return features.join(', ');
99
+ }
100
+ /**
101
+ * Run the full interactive prompt flow and return a validated {@link ProjectConfig}.
102
+ *
103
+ * @param projectName - Optional name from CLI args; when provided, the name prompt is skipped.
104
+ */
105
+ // eslint-disable-next-line max-lines-per-function, max-statements
106
+ export async function runPrompts(projectName) {
107
+ clack.intro('spinup-ts');
108
+ const d = await loadUserDefaults();
109
+ const name = await promptProjectName(projectName);
110
+ const description = unwrap(await clack.text({
111
+ message: 'Short description?',
112
+ placeholder: 'A delightful TypeScript project',
113
+ }));
114
+ const author = unwrap(await clack.text({
115
+ message: 'Author name?',
116
+ ...(d.author !== undefined && { initialValue: d.author }),
117
+ validate: (v) => (v ? undefined : 'Author name is required'),
118
+ }));
119
+ const email = unwrap(await clack.text({
120
+ message: 'Author email?',
121
+ ...(d.email !== undefined && { initialValue: d.email }),
122
+ validate: validateEmail,
123
+ }));
124
+ const githubHandle = unwrap(await clack.text({
125
+ message: 'GitHub handle?',
126
+ placeholder: 'octocat',
127
+ ...(d.githubHandle !== undefined && { initialValue: d.githubHandle }),
128
+ validate: (v) => (v ? undefined : 'GitHub handle is required'),
129
+ }));
130
+ const nodeVersion = unwrap(await clack.select({
131
+ message: 'Node version?',
132
+ initialValue: d.nodeVersion ?? '22',
133
+ options: [
134
+ { value: '20', label: '20' },
135
+ { value: '22', label: '22', hint: 'LTS ✓' },
136
+ { value: '23', label: '23' },
137
+ ],
138
+ }));
139
+ const packageManager = unwrap(await clack.select({
140
+ message: 'Package manager?',
141
+ initialValue: d.packageManager ?? 'pnpm',
142
+ options: [
143
+ { value: 'pnpm', label: 'pnpm', hint: 'recommended' },
144
+ { value: 'bun', label: 'bun' },
145
+ { value: 'npm', label: 'npm' },
146
+ ],
147
+ }));
148
+ const projectType = unwrap(await clack.select({
149
+ message: 'Project type?',
150
+ initialValue: d.projectType ?? 'library',
151
+ options: [
152
+ { value: 'library', label: 'library' },
153
+ { value: 'cli', label: 'cli' },
154
+ { value: 'server', label: 'server' },
155
+ { value: 'mcp-server', label: 'mcp-server' },
156
+ ],
157
+ }));
158
+ const includeGithubActions = unwrap(await clack.confirm({
159
+ message: 'Include GitHub Actions?',
160
+ initialValue: d.includeGithubActions ?? true,
161
+ }));
162
+ const publishToNpm = unwrap(await clack.confirm({
163
+ message: 'Publish to npm?',
164
+ initialValue: d.publishToNpm ?? false,
165
+ }));
166
+ const includeDocumentation = unwrap(await clack.confirm({
167
+ message: 'Include Docusaurus docs?',
168
+ initialValue: d.includeDocs ?? false,
169
+ }));
170
+ const includeCodecov = unwrap(await clack.confirm({
171
+ message: 'Include Codecov?',
172
+ initialValue: d.includeCodecov ?? false,
173
+ }));
174
+ const includeDockerfile = unwrap(await clack.confirm({
175
+ message: 'Include Dockerfile?',
176
+ initialValue: d.includeDockerfile ?? false,
177
+ }));
178
+ const includeDevcontainer = unwrap(await clack.confirm({
179
+ message: 'Include devcontainer?',
180
+ initialValue: d.includeDevcontainer ?? true,
181
+ }));
182
+ const license = unwrap(await clack.select({
183
+ message: 'License?',
184
+ initialValue: d.license ?? 'MIT',
185
+ options: [
186
+ { value: 'MIT', label: 'MIT' },
187
+ { value: 'Apache-2.0', label: 'Apache-2.0' },
188
+ { value: 'BSD-3-Clause', label: 'BSD-3-Clause' },
189
+ { value: 'ISC', label: 'ISC' },
190
+ { value: 'GPL-3.0', label: 'GPL-3.0' },
191
+ { value: 'UNLICENSED', label: 'Unlicensed' },
192
+ ],
193
+ }));
194
+ const config = projectConfigSchema.parse({
195
+ projectName: name,
196
+ projectSlug: deriveSlug(name),
197
+ description,
198
+ author,
199
+ email,
200
+ githubHandle,
201
+ nodeVersion,
202
+ packageManager,
203
+ projectType,
204
+ includeGithubActions,
205
+ publishToNpm,
206
+ includeDocs: includeDocumentation,
207
+ includeCodecov,
208
+ includeDockerfile,
209
+ includeDevcontainer,
210
+ license,
211
+ });
212
+ clack.note([
213
+ `Project: ${config.projectName}`,
214
+ `Type: ${config.projectType} · Node: ${config.nodeVersion} · PM: ${config.packageManager}`,
215
+ `Features: ${summarizeFeatures(config)}`,
216
+ ].join('\n'), 'Summary');
217
+ const proceed = unwrap(await clack.confirm({
218
+ message: 'Create project with these settings?',
219
+ initialValue: true,
220
+ }));
221
+ if (!proceed) {
222
+ clack.cancel('Operation cancelled.');
223
+ process.exit(0);
224
+ }
225
+ return config;
226
+ }
227
+ /**
228
+ * Build a {@link ProjectConfig} from defaults only, with no interactive prompts.
229
+ *
230
+ * Resolution order for each field: `~/.spinup-tsrc.json` → local `git config` (author
231
+ * name/email) → built-in fallback. Mirrors spinup-py's `--non-interactive` / `--yes` mode.
232
+ *
233
+ * @param projectName - kebab-case project name (required; validated here).
234
+ */
235
+ export async function buildDefaultConfig(projectName) {
236
+ const nameError = validateProjectName(projectName);
237
+ if (nameError) {
238
+ throw new Error(`Invalid project name "${projectName}": ${nameError}`);
239
+ }
240
+ const d = await loadUserDefaults();
241
+ const [gitName, gitEmail] = await Promise.all([
242
+ gitConfigValue('user.name'),
243
+ gitConfigValue('user.email'),
244
+ ]);
245
+ return projectConfigSchema.parse({
246
+ projectName,
247
+ projectSlug: deriveSlug(projectName),
248
+ description: '',
249
+ author: d.author ?? gitName ?? 'Your Name',
250
+ email: d.email ?? gitEmail ?? 'you@example.com',
251
+ githubHandle: d.githubHandle ?? 'your-handle',
252
+ nodeVersion: d.nodeVersion ?? '22',
253
+ packageManager: d.packageManager ?? 'pnpm',
254
+ projectType: d.projectType ?? 'library',
255
+ includeGithubActions: d.includeGithubActions ?? true,
256
+ publishToNpm: d.publishToNpm ?? false,
257
+ includeDocs: d.includeDocs ?? false,
258
+ includeCodecov: d.includeCodecov ?? false,
259
+ includeDockerfile: d.includeDockerfile ?? false,
260
+ includeDevcontainer: d.includeDevcontainer ?? true,
261
+ license: d.license ?? 'MIT',
262
+ });
263
+ }
264
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type ProjectConfig, type TokenMap } from './types.js';
2
+ export declare function checkDestinationDir(destDir: string): Promise<void>;
3
+ export declare function replaceTokensInTree(destDir: string, tokens: TokenMap): Promise<void>;
4
+ export declare function scaffold(destDir: string, config: ProjectConfig): Promise<void>;
5
+ //# sourceMappingURL=scaffold.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAc,MAAM,YAAY,CAAC;AAoB3E,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUxE;AA+BD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB1F;AAsCD,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBpF"}
@@ -0,0 +1,128 @@
1
+ import { exec } from 'node:child_process';
2
+ import { mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { promisify } from 'node:util';
6
+ import degit from 'degit';
7
+ import fse from 'fs-extra';
8
+ import { globby } from 'globby';
9
+ import pc from 'picocolors';
10
+ // eslint-disable-next-line import-x/no-unresolved
11
+ import { applyTransforms } from './transforms/index.js';
12
+ // eslint-disable-next-line import-x/no-unresolved
13
+ import { toTokenMap } from './types.js';
14
+ const execAsync = promisify(exec);
15
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
+ const DEGIT_SOURCE = 'joeblackwaslike/spinup-ts/template';
17
+ const INSTALL_COMMANDS = {
18
+ pnpm: 'pnpm install',
19
+ bun: 'bun install',
20
+ npm: 'npm install',
21
+ };
22
+ const logStep = (message) => {
23
+ // biome-ignore lint/suspicious/noConsole: intentional CLI output
24
+ console.log(` ${pc.green('✓')} ${message}`);
25
+ };
26
+ const isDevelopmentMode = () => process.env.NODE_ENV === 'development' || process.env.__DEV_TEMPLATE_PATH__ !== undefined;
27
+ export async function checkDestinationDir(destDir) {
28
+ try {
29
+ const entries = await readdir(destDir);
30
+ if (entries.length > 0) {
31
+ throw new Error(`Directory ${destDir} already exists and is not empty.`);
32
+ }
33
+ }
34
+ catch (error) {
35
+ if (error.code === 'ENOENT')
36
+ return;
37
+ throw error;
38
+ }
39
+ }
40
+ async function cloneTemplate(destDir) {
41
+ if (isDevelopmentMode()) {
42
+ const override = process.env.__DEV_TEMPLATE_PATH__;
43
+ const localPath = override ?? path.resolve(__dirname, '..', 'template');
44
+ await fse.copy(localPath, destDir);
45
+ return;
46
+ }
47
+ const emitter = degit(DEGIT_SOURCE, { cache: false, force: true, verbose: false });
48
+ await emitter.clone(destDir);
49
+ }
50
+ const BINARY_SAMPLE_SIZE = 8000;
51
+ function isBinaryBuffer(buffer) {
52
+ const sampleSize = Math.min(buffer.length, BINARY_SAMPLE_SIZE);
53
+ for (let index = 0; index < sampleSize; index++) {
54
+ if (buffer[index] === 0)
55
+ return true;
56
+ }
57
+ return false;
58
+ }
59
+ function replaceTokens(content, tokens) {
60
+ let result = content;
61
+ for (const [token, value] of Object.entries(tokens)) {
62
+ result = result.replaceAll(token, value);
63
+ }
64
+ return result;
65
+ }
66
+ export async function replaceTokensInTree(destDir, tokens) {
67
+ const files = await globby('**/*', {
68
+ cwd: destDir,
69
+ dot: true,
70
+ gitignore: false,
71
+ onlyFiles: true,
72
+ ignore: ['node_modules/**', '.git/**'],
73
+ });
74
+ await Promise.all(files.map(async (relativePath) => {
75
+ const filePath = path.join(destDir, relativePath);
76
+ const buffer = await readFile(filePath);
77
+ if (isBinaryBuffer(buffer))
78
+ return;
79
+ const original = buffer.toString('utf8');
80
+ const replaced = replaceTokens(original, tokens);
81
+ if (replaced !== original)
82
+ await writeFile(filePath, replaced, 'utf8');
83
+ }));
84
+ }
85
+ async function initGit(destDir) {
86
+ await execAsync('git init', { cwd: destDir });
87
+ await execAsync('git add -A', { cwd: destDir });
88
+ // Inline identity so the initial commit never depends on the user's global
89
+ // git config (keeps scaffolding deterministic in CI and fresh environments).
90
+ await execAsync('git -c user.name="spinup-ts" -c user.email="spinup-ts@users.noreply.github.com" commit -m "chore: initial scaffold from spinup-ts"', { cwd: destDir });
91
+ }
92
+ async function installDependencies(destDir, packageManager) {
93
+ await execAsync(INSTALL_COMMANDS[packageManager], { cwd: destDir });
94
+ }
95
+ async function initializeProjectTools(destDir, config) {
96
+ try {
97
+ await execAsync('bd init --skip-agents --non-interactive', { cwd: destDir });
98
+ logStep('Initialized Beads task manager');
99
+ }
100
+ catch {
101
+ // bd not installed; skip silently
102
+ }
103
+ const serenaDir = path.join(destDir, '.serena');
104
+ await mkdir(serenaDir, { recursive: true });
105
+ await writeFile(path.join(serenaDir, 'project.yml'), `project_name: ${config.projectSlug}\nlanguages:\n - typescript\n`, 'utf8');
106
+ logStep('Initialized Serena project config');
107
+ }
108
+ export async function scaffold(destDir, config) {
109
+ await cloneTemplate(destDir);
110
+ logStep('Cloning template...');
111
+ await replaceTokensInTree(destDir, toTokenMap(config));
112
+ logStep('Replacing tokens...');
113
+ await applyTransforms(destDir, config);
114
+ logStep('Applying transforms...');
115
+ await initGit(destDir);
116
+ logStep('Initializing git...');
117
+ // SPINUP_TS_SKIP_INSTALL=1 skips the (heavy, network-bound) dependency install
118
+ // for the generated project — used by the packaged-binary smoke test in CI.
119
+ if (process.env.SPINUP_TS_SKIP_INSTALL === '1') {
120
+ logStep('Skipping dependency install (SPINUP_TS_SKIP_INSTALL=1)');
121
+ }
122
+ else {
123
+ await installDependencies(destDir, config.packageManager);
124
+ logStep('Installing dependencies...');
125
+ }
126
+ await initializeProjectTools(destDir, config);
127
+ }
128
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ProjectConfig } from '../types.js';
2
+ export declare function transformDevcontainer(destDir: string, config: ProjectConfig): Promise<void>;
3
+ //# sourceMappingURL=devcontainer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devcontainer.d.ts","sourceRoot":"","sources":["../../src/transforms/devcontainer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAIjG"}
@@ -0,0 +1,8 @@
1
+ import path from 'node:path';
2
+ import fse from 'fs-extra';
3
+ export async function transformDevcontainer(destDir, config) {
4
+ if (config.includeDevcontainer)
5
+ return;
6
+ await fse.remove(path.join(destDir, '.devcontainer'));
7
+ }
8
+ //# sourceMappingURL=devcontainer.js.map