create-packkit 1.2.0 → 1.4.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.
- package/README.md +2 -1
- package/package.json +2 -1
- package/src/cli/args.js +9 -1
- package/src/cli/index.js +6 -2
- package/src/core/features/frameworks.js +5 -5
- package/src/core/index.js +3 -0
- package/src/core/monorepo.js +236 -0
- package/src/core/options.js +6 -0
- package/src/core/presets.js +2 -0
package/README.md
CHANGED
|
@@ -45,11 +45,12 @@ No install needed: **[danmat.github.io/create-packkit](https://danmat.github.io/
|
|
|
45
45
|
| **GitHub Actions** | CI · npm publish (provenance) · Pages · CodeQL · Codecov · stale bot |
|
|
46
46
|
| **Deps** | Renovate · Dependabot · none |
|
|
47
47
|
| **Repo** | LICENSE · community files · **AGENTS.md + CLAUDE.md** · VS Code · `.editorconfig` |
|
|
48
|
+
| **Monorepo** | optional pnpm/npm/yarn workspace with **Turborepo** + Changesets + example packages |
|
|
48
49
|
| **Package manager** | npm · pnpm · yarn · bun |
|
|
49
50
|
|
|
50
51
|
## Presets
|
|
51
52
|
|
|
52
|
-
`ts-lib` · `js-lib` · `ts-cli` / `cli` · `react-lib` · `react-lib-js` · `react-app` · `vue-lib` · `vue-app` · `svelte-lib` · `svelte-app` · `node-service` · `oss` · `minimal` · `full` — named bundles of the options above. See the [roadmap](ROADMAP.md) for what's next.
|
|
53
|
+
`ts-lib` · `js-lib` · `ts-cli` / `cli` · `react-lib` · `react-lib-js` · `react-app` · `vue-lib` · `vue-app` · `svelte-lib` · `svelte-app` · `node-service` · `monorepo` · `oss` · `minimal` · `full` — named bundles of the options above. See the [roadmap](ROADMAP.md) for what's next.
|
|
53
54
|
|
|
54
55
|
**Team profiles:** save a partial config as `packkit.config.json` (or any file) and reuse it with `npx create-packkit my-lib --from ./packkit.config.json` — flags still override the file.
|
|
55
56
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-packkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Highly configurable scaffolder for modern npm packages and CLIs — pick your stack (TS/JS, bundler, tests, linter, CI, releases) from a CLI or a web configurator.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"scripts": {
|
|
25
25
|
"start": "node bin/cli.js",
|
|
26
26
|
"test": "node --test",
|
|
27
|
+
"check:deps": "node scripts/check-template-deps.mjs",
|
|
27
28
|
"build:web": "esbuild src/core/index.js --bundle --format=esm --outfile=docs/packkit-core.js"
|
|
28
29
|
},
|
|
29
30
|
"repository": {
|
package/src/cli/args.js
CHANGED
|
@@ -38,6 +38,7 @@ export function parseCliArgs(argv) {
|
|
|
38
38
|
from: { type: 'string' },
|
|
39
39
|
name: { type: 'string' },
|
|
40
40
|
yes: { type: 'boolean', short: 'y' },
|
|
41
|
+
recommended: { type: 'boolean' },
|
|
41
42
|
here: { type: 'boolean' },
|
|
42
43
|
'no-install': { type: 'boolean' },
|
|
43
44
|
'no-git': { type: 'boolean' },
|
|
@@ -45,6 +46,7 @@ export function parseCliArgs(argv) {
|
|
|
45
46
|
target: { type: 'string', multiple: true },
|
|
46
47
|
workflows: { type: 'string', multiple: true },
|
|
47
48
|
minify: { type: 'boolean' },
|
|
49
|
+
monorepo: { type: 'boolean' },
|
|
48
50
|
storybook: { type: 'boolean' },
|
|
49
51
|
'pkg-checks': { type: 'boolean' },
|
|
50
52
|
knip: { type: 'boolean' },
|
|
@@ -70,6 +72,7 @@ export function parseCliArgs(argv) {
|
|
|
70
72
|
if (values.target) overrides.target = values.target;
|
|
71
73
|
if (values.workflows) overrides.workflows = values.workflows;
|
|
72
74
|
if (values.minify) overrides.minify = true;
|
|
75
|
+
if (values.monorepo) overrides.monorepo = true;
|
|
73
76
|
if (values.storybook) overrides.storybook = true;
|
|
74
77
|
if (values['pkg-checks']) overrides.pkgChecks = true;
|
|
75
78
|
if (values.knip) overrides.knip = true;
|
|
@@ -79,12 +82,17 @@ export function parseCliArgs(argv) {
|
|
|
79
82
|
}
|
|
80
83
|
if (name) overrides.name = name;
|
|
81
84
|
|
|
85
|
+
// Config flags provided (anything beyond the name) → the user knows what they
|
|
86
|
+
// want, so we can skip the wizard.
|
|
87
|
+
const hasConfigFlags = Object.keys(overrides).some((k) => k !== 'name');
|
|
88
|
+
|
|
82
89
|
return {
|
|
83
90
|
preset,
|
|
84
91
|
from: values.from,
|
|
85
92
|
name,
|
|
86
93
|
here: !!values.here,
|
|
87
|
-
yes: !!values.yes,
|
|
94
|
+
yes: !!values.yes || !!values.recommended,
|
|
95
|
+
hasConfigFlags,
|
|
88
96
|
install: !values['no-install'],
|
|
89
97
|
git: !values['no-git'],
|
|
90
98
|
help: !!values.help,
|
package/src/cli/index.js
CHANGED
|
@@ -30,7 +30,9 @@ Options:
|
|
|
30
30
|
--from <file> Load defaults from a JSON profile (or packkit.config.json)
|
|
31
31
|
--name <name> Package name
|
|
32
32
|
--here Scaffold into the current directory
|
|
33
|
-
-y, --yes Accept defaults / preset, no prompts
|
|
33
|
+
-y, --yes Accept defaults / preset, no prompts (one-shot)
|
|
34
|
+
--recommended Alias for --yes — recommended defaults in one command
|
|
35
|
+
--monorepo Generate a pnpm/Turborepo workspace
|
|
34
36
|
--no-install Skip dependency install
|
|
35
37
|
--no-git Skip git init
|
|
36
38
|
--pm <manager> npm | pnpm | yarn | bun
|
|
@@ -64,7 +66,9 @@ export async function run(argv = process.argv.slice(2)) {
|
|
|
64
66
|
return void console.log(JSON.stringify({ version: pkgVersion(), options: OPTIONS, presets: PRESET_INFO, aliases: PRESET_ALIASES }, null, 2));
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
|
|
69
|
+
// Only prompt when the user gave nothing to go on — a preset, --yes, a
|
|
70
|
+
// profile, or any config flag makes it a one-shot.
|
|
71
|
+
const interactive = !args.preset && !args.yes && !args.from && !args.hasConfigFlags && process.stdout.isTTY;
|
|
68
72
|
|
|
69
73
|
// Precedence: preset < profile file < CLI flags.
|
|
70
74
|
const profile = loadProfile(args);
|
|
@@ -40,7 +40,7 @@ function react(cfg, files, pkg, forApp) {
|
|
|
40
40
|
`}`,
|
|
41
41
|
``,
|
|
42
42
|
].join('\n');
|
|
43
|
-
pkg.dependencies = { react: '^
|
|
43
|
+
pkg.dependencies = { react: '^19.0.0', 'react-dom': '^19.0.0' };
|
|
44
44
|
} else {
|
|
45
45
|
files[`src/index.${x}`] = cfg.isTs
|
|
46
46
|
? [
|
|
@@ -56,12 +56,12 @@ function react(cfg, files, pkg, forApp) {
|
|
|
56
56
|
].join('\n')
|
|
57
57
|
: [`export function Button({ label, onClick }) {`, `\treturn <button onClick={onClick}>{label}</button>;`, `}`, ``].join('\n');
|
|
58
58
|
pkg.peerDependencies = { react: '>=18', 'react-dom': '>=18' };
|
|
59
|
-
pkg.devDependencies.react = '^
|
|
60
|
-
pkg.devDependencies['react-dom'] = '^
|
|
59
|
+
pkg.devDependencies.react = '^19.0.0';
|
|
60
|
+
pkg.devDependencies['react-dom'] = '^19.0.0';
|
|
61
61
|
}
|
|
62
62
|
if (cfg.isTs) {
|
|
63
|
-
pkg.devDependencies['@types/react'] = '^
|
|
64
|
-
pkg.devDependencies['@types/react-dom'] = '^
|
|
63
|
+
pkg.devDependencies['@types/react'] = '^19.0.0';
|
|
64
|
+
pkg.devDependencies['@types/react-dom'] = '^19.0.0';
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
package/src/core/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { normalizeConfig, OPTIONS, GROUPS, defaultConfig } from './options.js';
|
|
|
6
6
|
import { deepMerge, toJson } from './render.js';
|
|
7
7
|
import { finalizePackageJson } from './pkg.js';
|
|
8
8
|
import features from './features/index.js';
|
|
9
|
+
import { buildMonorepo } from './monorepo.js';
|
|
9
10
|
import { PRESETS, PRESET_NAMES, PRESET_INFO, PRESET_ALIASES, resolvePreset } from './presets.js';
|
|
10
11
|
|
|
11
12
|
export { OPTIONS, GROUPS, defaultConfig, normalizeConfig, PRESETS, PRESET_NAMES, PRESET_INFO, PRESET_ALIASES, resolvePreset };
|
|
@@ -20,6 +21,8 @@ export function fromPreset(name, overrides = {}) {
|
|
|
20
21
|
/** Turn a config into a complete set of files. */
|
|
21
22
|
export function generate(input) {
|
|
22
23
|
const cfg = normalizeConfig(input);
|
|
24
|
+
if (cfg.monorepo) return buildMonorepo(cfg);
|
|
25
|
+
|
|
23
26
|
const files = {};
|
|
24
27
|
let pkg = {};
|
|
25
28
|
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
// Monorepo generation — a pnpm/Turborepo (or npm/yarn workspaces) workspace
|
|
2
|
+
// with Changesets and two example packages (one depending on the other).
|
|
3
|
+
// This is a distinct shape from a single package, so generate() delegates here.
|
|
4
|
+
|
|
5
|
+
import { toJson } from './render.js';
|
|
6
|
+
import community from './features/community.js';
|
|
7
|
+
import agents from './features/agents.js';
|
|
8
|
+
import gitfiles from './features/gitfiles.js';
|
|
9
|
+
|
|
10
|
+
export function buildMonorepo(cfg) {
|
|
11
|
+
const files = {};
|
|
12
|
+
const pm = cfg.packageManager;
|
|
13
|
+
const scope = cfg.name.replace(/^@/, '').split('/')[0];
|
|
14
|
+
const core = `@${scope}/core`;
|
|
15
|
+
const utils = `@${scope}/utils`;
|
|
16
|
+
const wsProto = pm === 'pnpm' ? 'workspace:*' : '*';
|
|
17
|
+
|
|
18
|
+
// Reuse the package-agnostic root files (LICENSE, community, AGENTS.md, gitignore).
|
|
19
|
+
for (const feat of [community, agents, gitfiles]) {
|
|
20
|
+
if (feat.active(cfg)) Object.assign(files, feat.apply(cfg).files);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ---- root ----
|
|
24
|
+
const rootPkg = {
|
|
25
|
+
name: cfg.name,
|
|
26
|
+
version: '0.0.0',
|
|
27
|
+
private: true,
|
|
28
|
+
type: 'module',
|
|
29
|
+
...(cfg.license !== 'none' ? { license: cfg.license } : {}),
|
|
30
|
+
...(pm === 'pnpm' ? { packageManager: 'pnpm@9.10.0' } : { workspaces: ['packages/*'] }),
|
|
31
|
+
scripts: {
|
|
32
|
+
build: 'turbo build',
|
|
33
|
+
test: 'turbo test',
|
|
34
|
+
lint: 'turbo lint',
|
|
35
|
+
typecheck: 'turbo typecheck',
|
|
36
|
+
dev: 'turbo dev',
|
|
37
|
+
changeset: 'changeset',
|
|
38
|
+
version: 'changeset version',
|
|
39
|
+
release: 'turbo build && changeset publish',
|
|
40
|
+
},
|
|
41
|
+
devDependencies: {
|
|
42
|
+
turbo: '^2.0.0',
|
|
43
|
+
typescript: '^5.5.0',
|
|
44
|
+
tsup: '^8.0.0',
|
|
45
|
+
vitest: '^2.0.0',
|
|
46
|
+
eslint: '^9.0.0',
|
|
47
|
+
'@eslint/js': '^9.0.0',
|
|
48
|
+
'typescript-eslint': '^8.0.0',
|
|
49
|
+
prettier: '^3.3.0',
|
|
50
|
+
'@changesets/cli': '^2.27.0',
|
|
51
|
+
'@types/node': `^${cfg.nodeVersion}.0.0`,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
files['package.json'] = toJson(rootPkg);
|
|
55
|
+
|
|
56
|
+
if (pm === 'pnpm') files['pnpm-workspace.yaml'] = 'packages:\n - "packages/*"\n';
|
|
57
|
+
|
|
58
|
+
files['turbo.json'] = toJson({
|
|
59
|
+
$schema: 'https://turbo.build/schema.json',
|
|
60
|
+
tasks: {
|
|
61
|
+
build: { dependsOn: ['^build'], outputs: ['dist/**'] },
|
|
62
|
+
test: { dependsOn: ['^build'] },
|
|
63
|
+
typecheck: { dependsOn: ['^build'] },
|
|
64
|
+
lint: {},
|
|
65
|
+
dev: { cache: false, persistent: true },
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
files['tsconfig.base.json'] = toJson({
|
|
70
|
+
$schema: 'https://json.schemastore.org/tsconfig',
|
|
71
|
+
compilerOptions: {
|
|
72
|
+
target: 'ES2022',
|
|
73
|
+
module: 'ESNext',
|
|
74
|
+
moduleResolution: 'Bundler',
|
|
75
|
+
lib: ['ES2022'],
|
|
76
|
+
strict: true,
|
|
77
|
+
esModuleInterop: true,
|
|
78
|
+
skipLibCheck: true,
|
|
79
|
+
declaration: true,
|
|
80
|
+
noEmit: true,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
files['.changeset/config.json'] = toJson({
|
|
85
|
+
$schema: 'https://unpkg.com/@changesets/config@3.0.0/schema.json',
|
|
86
|
+
changelog: '@changesets/cli/changelog',
|
|
87
|
+
commit: false,
|
|
88
|
+
access: 'public',
|
|
89
|
+
baseBranch: 'main',
|
|
90
|
+
});
|
|
91
|
+
files['.changeset/README.md'] = '# Changesets\n\nRun `npx changeset` to record a version bump for your next release.\n';
|
|
92
|
+
|
|
93
|
+
files['eslint.config.js'] = [
|
|
94
|
+
`import js from '@eslint/js';`,
|
|
95
|
+
`import tseslint from 'typescript-eslint';`,
|
|
96
|
+
``,
|
|
97
|
+
`export default tseslint.config(`,
|
|
98
|
+
`\tjs.configs.recommended,`,
|
|
99
|
+
`\t...tseslint.configs.recommended,`,
|
|
100
|
+
`\t{ ignores: ['**/dist'] },`,
|
|
101
|
+
`);`,
|
|
102
|
+
``,
|
|
103
|
+
].join('\n');
|
|
104
|
+
files['.prettierrc.json'] = toJson({ useTabs: true, singleQuote: true, semi: true, printWidth: 100, trailingComma: 'all' });
|
|
105
|
+
|
|
106
|
+
files['README.md'] = rootReadme(cfg, pm, core, utils);
|
|
107
|
+
files['.github/workflows/ci.yml'] = ciWorkflow(cfg, pm);
|
|
108
|
+
|
|
109
|
+
// ---- packages ----
|
|
110
|
+
addPackage(files, {
|
|
111
|
+
name: core,
|
|
112
|
+
dir: 'packages/core',
|
|
113
|
+
src: [
|
|
114
|
+
`/** Greet someone by name. */`,
|
|
115
|
+
`export function greet(name: string): string {`,
|
|
116
|
+
`\treturn \`Hello, \${name}!\`;`,
|
|
117
|
+
`}`,
|
|
118
|
+
``,
|
|
119
|
+
].join('\n'),
|
|
120
|
+
test: exampleTest(`import { greet } from './index.js';`, `expect(greet('world')).toBe('Hello, world!')`),
|
|
121
|
+
deps: {},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
addPackage(files, {
|
|
125
|
+
name: utils,
|
|
126
|
+
dir: 'packages/utils',
|
|
127
|
+
src: [
|
|
128
|
+
`import { greet } from '${core}';`,
|
|
129
|
+
``,
|
|
130
|
+
`/** Greet someone, loudly. */`,
|
|
131
|
+
`export function shout(name: string): string {`,
|
|
132
|
+
`\treturn greet(name).toUpperCase();`,
|
|
133
|
+
`}`,
|
|
134
|
+
``,
|
|
135
|
+
].join('\n'),
|
|
136
|
+
test: exampleTest(`import { shout } from './index.js';`, `expect(shout('world')).toBe('HELLO, WORLD!')`),
|
|
137
|
+
deps: { [core]: wsProto },
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
const install = pm === 'npm' ? 'npm install' : `${pm} install`;
|
|
141
|
+
return {
|
|
142
|
+
config: cfg,
|
|
143
|
+
files,
|
|
144
|
+
postCommands: cfg.gitInit ? ['git init', 'git add -A', 'git commit -m "Initial commit from Packkit"'] : [],
|
|
145
|
+
summary: {
|
|
146
|
+
name: cfg.name,
|
|
147
|
+
fileCount: Object.keys(files).length,
|
|
148
|
+
stack: ['monorepo', `${pm}+turbo`, 'TypeScript', 'tsup', 'vitest', 'changesets'],
|
|
149
|
+
workflows: ['ci'],
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function addPackage(files, { name, dir, src, test, deps }) {
|
|
155
|
+
const pkg = {
|
|
156
|
+
name,
|
|
157
|
+
version: '0.0.0',
|
|
158
|
+
type: 'module',
|
|
159
|
+
main: './dist/index.js',
|
|
160
|
+
types: './dist/index.d.ts',
|
|
161
|
+
exports: { '.': { types: './dist/index.d.ts', default: './dist/index.js' } },
|
|
162
|
+
files: ['dist'],
|
|
163
|
+
scripts: {
|
|
164
|
+
build: 'tsup src/index.ts --format esm --dts --clean',
|
|
165
|
+
dev: 'tsup src/index.ts --format esm --dts --watch',
|
|
166
|
+
test: 'vitest run',
|
|
167
|
+
typecheck: 'tsc --noEmit',
|
|
168
|
+
lint: 'eslint .',
|
|
169
|
+
},
|
|
170
|
+
...(Object.keys(deps).length ? { dependencies: deps } : {}),
|
|
171
|
+
};
|
|
172
|
+
files[`${dir}/package.json`] = toJson(pkg);
|
|
173
|
+
files[`${dir}/tsconfig.json`] = toJson({ extends: '../../tsconfig.base.json', include: ['src'] });
|
|
174
|
+
files[`${dir}/src/index.ts`] = src;
|
|
175
|
+
files[`${dir}/src/index.test.ts`] = test;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function exampleTest(importLine, assertion) {
|
|
179
|
+
return [`import { describe, it, expect } from 'vitest';`, importLine, ``, `describe('example', () => {`, `\tit('works', () => {`, `\t\t${assertion};`, `\t});`, `});`, ``].join('\n');
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function ciWorkflow(cfg, pm) {
|
|
183
|
+
const setup = [' - uses: actions/checkout@v4'];
|
|
184
|
+
if (pm === 'pnpm') setup.push(' - uses: pnpm/action-setup@v4');
|
|
185
|
+
setup.push(
|
|
186
|
+
' - uses: actions/setup-node@v4',
|
|
187
|
+
' with:',
|
|
188
|
+
` node-version: '${cfg.nodeVersion}'`,
|
|
189
|
+
` cache: '${pm === 'yarn' ? 'yarn' : pm === 'pnpm' ? 'pnpm' : 'npm'}'`,
|
|
190
|
+
);
|
|
191
|
+
const install = pm === 'npm' ? 'npm ci' : pm === 'pnpm' ? 'pnpm install --frozen-lockfile' : `${pm} install --frozen-lockfile`;
|
|
192
|
+
const run = (s) => (pm === 'npm' ? `npm run ${s}` : `${pm} ${s}`);
|
|
193
|
+
return [
|
|
194
|
+
'name: CI',
|
|
195
|
+
'on:',
|
|
196
|
+
' push:',
|
|
197
|
+
' branches: [main]',
|
|
198
|
+
' pull_request:',
|
|
199
|
+
'jobs:',
|
|
200
|
+
' ci:',
|
|
201
|
+
' runs-on: ubuntu-latest',
|
|
202
|
+
' steps:',
|
|
203
|
+
setup.join('\n'),
|
|
204
|
+
` - run: ${install}`,
|
|
205
|
+
` - run: ${run('typecheck')}`,
|
|
206
|
+
` - run: ${run('lint')}`,
|
|
207
|
+
` - run: ${run('test')}`,
|
|
208
|
+
` - run: ${run('build')}`,
|
|
209
|
+
'',
|
|
210
|
+
].join('\n');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function rootReadme(cfg, pm, core, utils) {
|
|
214
|
+
const install = pm === 'npm' ? 'npm install' : `${pm} install`;
|
|
215
|
+
const run = (s) => (pm === 'npm' ? `npm run ${s}` : `${pm} ${s}`);
|
|
216
|
+
return [
|
|
217
|
+
`# ${cfg.name}`,
|
|
218
|
+
'',
|
|
219
|
+
cfg.description || '_A monorepo scaffolded with [Packkit](https://danmat.github.io/create-packkit/)._',
|
|
220
|
+
'',
|
|
221
|
+
'## Packages',
|
|
222
|
+
'',
|
|
223
|
+
`- \`${core}\` — the core library`,
|
|
224
|
+
`- \`${utils}\` — utilities built on \`${core}\``,
|
|
225
|
+
'',
|
|
226
|
+
'## Develop',
|
|
227
|
+
'',
|
|
228
|
+
'```sh',
|
|
229
|
+
install,
|
|
230
|
+
run('build') + ' # build all packages (Turborepo)',
|
|
231
|
+
run('test'),
|
|
232
|
+
'```',
|
|
233
|
+
'',
|
|
234
|
+
cfg.license !== 'none' ? `## License\n\n${cfg.license}${cfg.author ? ' © ' + cfg.author : ''}\n` : '',
|
|
235
|
+
].join('\n');
|
|
236
|
+
}
|
package/src/core/options.js
CHANGED
|
@@ -37,6 +37,9 @@ export const OPTIONS = {
|
|
|
37
37
|
{ value: 'app', label: 'App (Vite SPA)' },
|
|
38
38
|
],
|
|
39
39
|
},
|
|
40
|
+
monorepo: {
|
|
41
|
+
group: 'core', type: 'boolean', label: 'Monorepo (pnpm/Turborepo workspace)', default: false,
|
|
42
|
+
},
|
|
40
43
|
framework: {
|
|
41
44
|
group: 'core', type: 'select', label: 'Framework', default: 'none',
|
|
42
45
|
choices: [
|
|
@@ -240,6 +243,9 @@ export function normalizeConfig(input = {}) {
|
|
|
240
243
|
// Storybook only applies to component libraries.
|
|
241
244
|
if (!cfg.hasFramework || cfg.hasApp || !cfg.hasLibrary) cfg.storybook = false;
|
|
242
245
|
|
|
246
|
+
// A monorepo is its own generation path (see buildMonorepo); it has a build.
|
|
247
|
+
if (cfg.monorepo) cfg.hasBuild = true;
|
|
248
|
+
|
|
243
249
|
cfg.publishable = (cfg.hasLibrary || cfg.hasCli) && !cfg.hasApp && !cfg.hasService;
|
|
244
250
|
// Package-correctness checks only make sense for a publishable package.
|
|
245
251
|
if (!cfg.publishable) cfg.pkgChecks = false;
|
package/src/core/presets.js
CHANGED
|
@@ -18,6 +18,7 @@ export const PRESETS = {
|
|
|
18
18
|
test: 'vitest', lint: 'eslint-prettier', gitHooks: 'simple-git-hooks',
|
|
19
19
|
release: 'none', workflows: ['ci'], deps: 'renovate', agents: true, vscode: true,
|
|
20
20
|
},
|
|
21
|
+
monorepo: { monorepo: true, language: 'ts', packageManager: 'pnpm' },
|
|
21
22
|
oss: {
|
|
22
23
|
language: 'ts', target: ['library'], moduleFormat: 'dual', bundler: 'tsup',
|
|
23
24
|
test: 'vitest', coverage: true, lint: 'eslint-prettier', gitHooks: 'simple-git-hooks',
|
|
@@ -76,6 +77,7 @@ export const PRESET_INFO = {
|
|
|
76
77
|
'svelte-lib': 'Svelte component library — ships source, peer svelte, jsdom tests.',
|
|
77
78
|
'svelte-app': 'Svelte SPA — Vite dev server, build, Testing Library.',
|
|
78
79
|
'node-service': 'Node HTTP service (Hono) — tsx dev, tsup build, Dockerfile.',
|
|
80
|
+
monorepo: 'pnpm + Turborepo workspace — two example packages, Changesets, CI.',
|
|
79
81
|
oss: 'Full open-source library — coverage, CodeQL, Codecov, Renovate, Changesets.',
|
|
80
82
|
minimal: 'Bare TS library — tsup only, no tests/lint/CI.',
|
|
81
83
|
full: 'Everything on — library + CLI, all workflows and extras.',
|