create-packkit 1.0.0 → 1.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.
- package/README.md +11 -0
- package/llms.txt +43 -0
- package/package.json +3 -2
- package/src/cli/args.js +11 -2
- package/src/cli/index.js +9 -1
- package/src/core/features/bundler.js +10 -7
- package/src/core/features/checks.js +24 -0
- package/src/core/features/index.js +4 -0
- package/src/core/features/jsr.js +42 -0
- package/src/core/features/meta.js +1 -0
- package/src/core/features/workflows.js +5 -0
- package/src/core/index.js +6 -6
- package/src/core/options.js +9 -0
- package/src/core/presets.js +22 -0
package/README.md
CHANGED
|
@@ -53,6 +53,17 @@ No install needed: **[danmat.github.io/create-packkit](https://danmat.github.io/
|
|
|
53
53
|
|
|
54
54
|
**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
55
|
|
|
56
|
+
## For AI agents & automation
|
|
57
|
+
|
|
58
|
+
Packkit is safe to drive non-interactively — every option is a flag, so no prompts are needed. Agents can introspect the whole interface as JSON:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
npx create-packkit --schema # all options, presets, and aliases as JSON
|
|
62
|
+
npx create-packkit my-lib ts-lib --no-install --no-git # deterministic scaffold
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
There's also an [`llms.txt`](llms.txt) (served at [danmat.github.io/create-packkit/llms.txt](https://danmat.github.io/create-packkit/llms.txt)) describing the commands for LLMs.
|
|
66
|
+
|
|
56
67
|
## How it works
|
|
57
68
|
|
|
58
69
|
Packkit is a pure `config → { files }` **core** that runs in both Node and the browser:
|
package/llms.txt
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Packkit (create-packkit)
|
|
2
|
+
|
|
3
|
+
> A highly configurable, non-interactive scaffolder for modern npm packages, CLIs, HTTP services, and front-end apps (React/Vue/Svelte). Designed to be driven by humans OR automation/agents.
|
|
4
|
+
|
|
5
|
+
Packkit generates a complete, ready-to-ship project from a single deterministic command. It is safe for agents to call because every option is a flag — no prompts are required when a name and flags (or a preset) are given.
|
|
6
|
+
|
|
7
|
+
## For agents: how to use it
|
|
8
|
+
|
|
9
|
+
Introspect the full interface (all options, presets, aliases) as JSON:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npx create-packkit --schema
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Generate non-interactively (no prompts; `--no-install`/`--no-git` for a pure file scaffold):
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
npx create-packkit <name> [preset] [--flags...]
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
npx create-packkit my-lib ts-lib
|
|
25
|
+
npx create-packkit my-cli cli --pm pnpm
|
|
26
|
+
npx create-packkit ui react-lib --storybook
|
|
27
|
+
npx create-packkit api node-service
|
|
28
|
+
npx create-packkit web react-app
|
|
29
|
+
npx create-packkit lib my-lib --no-install --no-git
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Presets (and short aliases)
|
|
33
|
+
|
|
34
|
+
`ts-lib` (`lib`) · `js-lib` (`jslib`) · `ts-cli` / `cli` · `react-lib` (`rlib`) · `react-app` (`rapp`) · `vue-lib` (`vlib`) · `vue-app` (`vapp`) · `svelte-lib` (`slib`) · `svelte-app` (`sapp`) · `node-service` (`svc`) · `oss` · `minimal` · `full`
|
|
35
|
+
|
|
36
|
+
## Key flags
|
|
37
|
+
|
|
38
|
+
`--language ts|js` · `--framework none|react|vue|svelte` · `--target library|cli|service|app` (repeatable) · `--module esm|cjs|dual` · `--bundler tsup|tsdown|unbuild|rollup|none` · `--minify` · `--test vitest|jest|node|none` · `--lint eslint-prettier|biome|oxlint|none` · `--hooks ...` · `--release changesets|release-it|np|none` · `--workflows ci|npm-publish|pages|codeql|codecov|stale` (repeatable) · `--pkg-checks` (publint + are-the-types-wrong) · `--knip` · `--jsr` · `--deps renovate|dependabot|none` · `--license MIT|Apache-2.0|ISC|none` · `--pm npm|pnpm|yarn|bun` · `--from <file>` (load a JSON profile) · `--no-install` · `--no-git`
|
|
39
|
+
|
|
40
|
+
## Links
|
|
41
|
+
- Web configurator: https://danmat.github.io/create-packkit/
|
|
42
|
+
- Repo: https://github.com/DanMat/create-packkit
|
|
43
|
+
- npm: https://www.npmjs.com/package/create-packkit
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-packkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.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": {
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"bin",
|
|
16
16
|
"src",
|
|
17
17
|
"README.md",
|
|
18
|
-
"LICENSE"
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"llms.txt"
|
|
19
20
|
],
|
|
20
21
|
"engines": {
|
|
21
22
|
"node": ">=18"
|
package/src/cli/args.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseArgs } from 'node:util';
|
|
2
|
-
import {
|
|
2
|
+
import { resolvePreset } from '../core/presets.js';
|
|
3
3
|
|
|
4
4
|
// Map friendly flag names to config keys for non-interactive use.
|
|
5
5
|
const OVERRIDE_FLAGS = {
|
|
@@ -17,6 +17,7 @@ const OVERRIDE_FLAGS = {
|
|
|
17
17
|
node: 'nodeVersion',
|
|
18
18
|
author: 'author',
|
|
19
19
|
description: 'description',
|
|
20
|
+
repo: 'repo',
|
|
20
21
|
};
|
|
21
22
|
|
|
22
23
|
// Boolean options that default ON — a --no-<flag> turns them off.
|
|
@@ -45,8 +46,12 @@ export function parseCliArgs(argv) {
|
|
|
45
46
|
workflows: { type: 'string', multiple: true },
|
|
46
47
|
minify: { type: 'boolean' },
|
|
47
48
|
storybook: { type: 'boolean' },
|
|
49
|
+
'pkg-checks': { type: 'boolean' },
|
|
50
|
+
knip: { type: 'boolean' },
|
|
51
|
+
jsr: { type: 'boolean' },
|
|
48
52
|
help: { type: 'boolean', short: 'h' },
|
|
49
53
|
version: { type: 'boolean', short: 'v' },
|
|
54
|
+
schema: { type: 'boolean' },
|
|
50
55
|
...Object.fromEntries(Object.keys(OVERRIDE_FLAGS).map((k) => [k, { type: 'string' }])),
|
|
51
56
|
...Object.fromEntries(Object.keys(NEGATABLE).map((k) => [k, { type: 'boolean' }])),
|
|
52
57
|
},
|
|
@@ -55,7 +60,7 @@ export function parseCliArgs(argv) {
|
|
|
55
60
|
// First positional may be a known preset; otherwise it's the project name.
|
|
56
61
|
let preset = values.preset;
|
|
57
62
|
const pos = [...positionals];
|
|
58
|
-
if (!preset && pos.length &&
|
|
63
|
+
if (!preset && pos.length && resolvePreset(pos[0])) preset = pos.shift();
|
|
59
64
|
const name = values.name || pos[0];
|
|
60
65
|
|
|
61
66
|
const overrides = {};
|
|
@@ -66,6 +71,9 @@ export function parseCliArgs(argv) {
|
|
|
66
71
|
if (values.workflows) overrides.workflows = values.workflows;
|
|
67
72
|
if (values.minify) overrides.minify = true;
|
|
68
73
|
if (values.storybook) overrides.storybook = true;
|
|
74
|
+
if (values['pkg-checks']) overrides.pkgChecks = true;
|
|
75
|
+
if (values.knip) overrides.knip = true;
|
|
76
|
+
if (values.jsr) overrides.jsr = true;
|
|
69
77
|
for (const [flag, key] of Object.entries(NEGATABLE)) {
|
|
70
78
|
if (values[flag]) overrides[key] = false;
|
|
71
79
|
}
|
|
@@ -81,6 +89,7 @@ export function parseCliArgs(argv) {
|
|
|
81
89
|
git: !values['no-git'],
|
|
82
90
|
help: !!values.help,
|
|
83
91
|
version: !!values.version,
|
|
92
|
+
schema: !!values.schema,
|
|
84
93
|
overrides,
|
|
85
94
|
};
|
|
86
95
|
}
|
package/src/cli/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { resolve, basename } from 'node:path';
|
|
|
2
2
|
import { readFileSync, existsSync } from 'node:fs';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import * as p from '@clack/prompts';
|
|
5
|
-
import { generate, fromPreset, normalizeConfig, PRESET_NAMES } from '../core/index.js';
|
|
5
|
+
import { generate, fromPreset, normalizeConfig, PRESET_NAMES, OPTIONS, PRESET_INFO, PRESET_ALIASES } from '../core/index.js';
|
|
6
6
|
import { parseCliArgs } from './args.js';
|
|
7
7
|
import { runWizard } from './wizard.js';
|
|
8
8
|
import { writeProject, dirIsEmptyOrMissing, gitInit, installDeps } from './write.js';
|
|
@@ -41,10 +41,14 @@ Options:
|
|
|
41
41
|
--hooks <simple-git-hooks|husky|lefthook|none> --release <changesets|release-it|np|none>
|
|
42
42
|
--workflows <ci|npm-publish|pages|codeql|codecov|stale> (repeatable)
|
|
43
43
|
--deps <renovate|dependabot|none> --license <MIT|Apache-2.0|ISC|none>
|
|
44
|
+
--pkg-checks (publint + are-the-types-wrong) --knip --jsr
|
|
44
45
|
--no-coverage --no-community --no-agents --no-vscode --no-editorconfig
|
|
46
|
+
--schema Print the full option/preset schema as JSON (for tools/agents)
|
|
45
47
|
-h, --help Show this help
|
|
46
48
|
-v, --version Show version
|
|
47
49
|
|
|
50
|
+
Preset shortcuts: lib, jslib, rlib, rapp, vlib, vapp, slib, sapp, svc
|
|
51
|
+
|
|
48
52
|
Examples:
|
|
49
53
|
npx packkit ts-lib my-lib
|
|
50
54
|
npm create packkit@latest my-cli -- --preset cli
|
|
@@ -55,6 +59,10 @@ export async function run(argv = process.argv.slice(2)) {
|
|
|
55
59
|
const args = parseCliArgs(argv);
|
|
56
60
|
if (args.help) return void console.log(HELP);
|
|
57
61
|
if (args.version) return void console.log(pkgVersion());
|
|
62
|
+
if (args.schema) {
|
|
63
|
+
// Machine-readable interface for tools/agents: every option, preset, and alias.
|
|
64
|
+
return void console.log(JSON.stringify({ version: pkgVersion(), options: OPTIONS, presets: PRESET_INFO, aliases: PRESET_ALIASES }, null, 2));
|
|
65
|
+
}
|
|
58
66
|
|
|
59
67
|
const interactive = !args.preset && !args.yes && !args.from && process.stdout.isTTY;
|
|
60
68
|
|
|
@@ -20,16 +20,19 @@ export default {
|
|
|
20
20
|
pkg.files = ['dist'];
|
|
21
21
|
const esm = './dist/index.js';
|
|
22
22
|
const cjs = './dist/index.cjs';
|
|
23
|
-
const
|
|
23
|
+
const dtsEsm = './dist/index.d.ts';
|
|
24
|
+
// Dual builds emit a separate .d.cts so CJS consumers resolve the right
|
|
25
|
+
// types under the "require" condition (publint / are-the-types-wrong).
|
|
26
|
+
const dtsCjs = cfg.moduleFormat === 'dual' ? './dist/index.d.cts' : dtsEsm;
|
|
27
|
+
|
|
24
28
|
const exp = {};
|
|
25
|
-
if (cfg.
|
|
26
|
-
if (cfg.
|
|
27
|
-
if (cfg.hasCjs) exp.require = build ? cjs : './dist/index.cjs';
|
|
29
|
+
if (cfg.hasEsm) exp.import = cfg.isTs ? { types: dtsEsm, default: esm } : esm;
|
|
30
|
+
if (cfg.hasCjs) exp.require = cfg.isTs ? { types: dtsCjs, default: cjs } : cjs;
|
|
28
31
|
pkg.exports = { '.': exp };
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
|
|
33
|
+
pkg.main = cfg.hasCjs ? cjs : esm;
|
|
31
34
|
if (cfg.hasEsm) pkg.module = esm;
|
|
32
|
-
if (cfg.isTs) pkg.types =
|
|
35
|
+
if (cfg.isTs) pkg.types = cfg.hasEsm ? dtsEsm : dtsCjs;
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
// ---- build tooling ----
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Package-correctness + hygiene checks (opt-in):
|
|
2
|
+
// - publint validates package.json shape (exports/main/module)
|
|
3
|
+
// - are-the-types-wrong verifies TS consumers resolve your .d.ts correctly
|
|
4
|
+
// - knip finds unused files, dependencies, and exports
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
id: 'checks',
|
|
8
|
+
active: (cfg) => cfg.pkgChecks || cfg.knip,
|
|
9
|
+
apply(cfg) {
|
|
10
|
+
const pkg = { scripts: {}, devDependencies: {} };
|
|
11
|
+
|
|
12
|
+
if (cfg.pkgChecks) {
|
|
13
|
+
pkg.scripts['check:pkg'] = 'publint && attw --pack';
|
|
14
|
+
pkg.devDependencies.publint = '^0.3.0';
|
|
15
|
+
pkg.devDependencies['@arethetypeswrong/cli'] = '^0.18.0';
|
|
16
|
+
}
|
|
17
|
+
if (cfg.knip) {
|
|
18
|
+
pkg.scripts.knip = 'knip';
|
|
19
|
+
pkg.devDependencies.knip = '^5.0.0';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return { files: {}, pkg };
|
|
23
|
+
},
|
|
24
|
+
};
|
|
@@ -12,6 +12,8 @@ import lint from './lint.js';
|
|
|
12
12
|
import githooks from './githooks.js';
|
|
13
13
|
import release from './release.js';
|
|
14
14
|
import cli from './cli.js';
|
|
15
|
+
import checks from './checks.js';
|
|
16
|
+
import jsr from './jsr.js';
|
|
15
17
|
import workflows from './workflows.js';
|
|
16
18
|
import storybook from './storybook.js';
|
|
17
19
|
import community from './community.js';
|
|
@@ -31,6 +33,8 @@ export default [
|
|
|
31
33
|
githooks,
|
|
32
34
|
release,
|
|
33
35
|
cli,
|
|
36
|
+
checks,
|
|
37
|
+
jsr,
|
|
34
38
|
workflows,
|
|
35
39
|
storybook,
|
|
36
40
|
community,
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { toJson } from '../render.js';
|
|
2
|
+
|
|
3
|
+
// JSR publishing (TypeScript-first, ESM-only registry with automatic provenance).
|
|
4
|
+
// Publishes source directly — no build step required. JSR names are scoped, so
|
|
5
|
+
// a non-scoped package gets an @scope placeholder to fill in.
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
id: 'jsr',
|
|
9
|
+
active: (cfg) => cfg.jsr,
|
|
10
|
+
apply(cfg) {
|
|
11
|
+
const name = cfg.name.startsWith('@') ? cfg.name : `@scope/${cfg.name}`;
|
|
12
|
+
return {
|
|
13
|
+
files: {
|
|
14
|
+
'jsr.json': toJson({
|
|
15
|
+
name,
|
|
16
|
+
version: '0.0.0',
|
|
17
|
+
exports: `./src/index.${cfg.ext}`,
|
|
18
|
+
}),
|
|
19
|
+
'.github/workflows/jsr.yml': [
|
|
20
|
+
'name: Publish to JSR',
|
|
21
|
+
'on:',
|
|
22
|
+
' push:',
|
|
23
|
+
' tags: ["v*"]',
|
|
24
|
+
'permissions:',
|
|
25
|
+
' contents: read',
|
|
26
|
+
' id-token: write',
|
|
27
|
+
'jobs:',
|
|
28
|
+
' publish:',
|
|
29
|
+
' runs-on: ubuntu-latest',
|
|
30
|
+
' steps:',
|
|
31
|
+
' - uses: actions/checkout@v4',
|
|
32
|
+
' - uses: actions/setup-node@v4',
|
|
33
|
+
" with:",
|
|
34
|
+
" node-version: '20'",
|
|
35
|
+
' - run: npx jsr publish',
|
|
36
|
+
'',
|
|
37
|
+
].join('\n'),
|
|
38
|
+
},
|
|
39
|
+
pkg: {},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -16,6 +16,7 @@ export default {
|
|
|
16
16
|
|
|
17
17
|
const kw = String(cfg.keywords || '').split(',').map((s) => s.trim()).filter(Boolean);
|
|
18
18
|
if (kw.length) pkg.keywords = kw;
|
|
19
|
+
if (cfg.license !== 'none') pkg.license = cfg.license;
|
|
19
20
|
if (cfg.author) pkg.author = cfg.author;
|
|
20
21
|
if (cfg.repo) {
|
|
21
22
|
pkg.repository = { type: 'git', url: `git+${cfg.repo.replace(/\.git$/, '')}.git` };
|
|
@@ -72,7 +72,9 @@ function ciWorkflow(cfg, codecov) {
|
|
|
72
72
|
if (cfg.isTs) jobs.push(` - run: ${pmRun(cfg, 'typecheck')}`);
|
|
73
73
|
if (cfg.lint !== 'none') jobs.push(` - run: ${pmRun(cfg, 'lint')}`);
|
|
74
74
|
if (cfg.test !== 'none') jobs.push(` - run: ${pmRun(cfg, codecov ? 'coverage' : 'test')}`);
|
|
75
|
+
if (cfg.knip) jobs.push(` - run: ${pmRun(cfg, 'knip')}`);
|
|
75
76
|
if (cfg.hasBuild) jobs.push(` - run: ${pmRun(cfg, 'build')}`);
|
|
77
|
+
if (cfg.pkgChecks) jobs.push(` - run: ${pmRun(cfg, 'check:pkg')}`); // after build (attw packs dist)
|
|
76
78
|
const cov = codecov
|
|
77
79
|
? '\n - uses: codecov/codecov-action@v4\n with:\n token: ${{ secrets.CODECOV_TOKEN }}'
|
|
78
80
|
: '';
|
|
@@ -85,6 +87,7 @@ function ciWorkflow(cfg, codecov) {
|
|
|
85
87
|
'jobs:',
|
|
86
88
|
' ci:',
|
|
87
89
|
' runs-on: ubuntu-latest',
|
|
90
|
+
' steps:',
|
|
88
91
|
setupSteps(cfg),
|
|
89
92
|
jobs.join('\n') + cov,
|
|
90
93
|
'',
|
|
@@ -106,6 +109,7 @@ function releaseWorkflow(cfg) {
|
|
|
106
109
|
'jobs:',
|
|
107
110
|
' release:',
|
|
108
111
|
' runs-on: ubuntu-latest',
|
|
112
|
+
' steps:',
|
|
109
113
|
setupSteps(cfg),
|
|
110
114
|
' - uses: changesets/action@v1',
|
|
111
115
|
' with:',
|
|
@@ -130,6 +134,7 @@ function releaseWorkflow(cfg) {
|
|
|
130
134
|
'jobs:',
|
|
131
135
|
' publish:',
|
|
132
136
|
' runs-on: ubuntu-latest',
|
|
137
|
+
' steps:',
|
|
133
138
|
setupSteps(cfg),
|
|
134
139
|
cfg.hasBuild ? ` - run: ${pmRun(cfg, 'build')}` : null,
|
|
135
140
|
' - run: npm publish --provenance --access public',
|
package/src/core/index.js
CHANGED
|
@@ -6,15 +6,15 @@ 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 { PRESETS, PRESET_NAMES, PRESET_INFO } from './presets.js';
|
|
9
|
+
import { PRESETS, PRESET_NAMES, PRESET_INFO, PRESET_ALIASES, resolvePreset } from './presets.js';
|
|
10
10
|
|
|
11
|
-
export { OPTIONS, GROUPS, defaultConfig, normalizeConfig, PRESETS, PRESET_NAMES, PRESET_INFO };
|
|
11
|
+
export { OPTIONS, GROUPS, defaultConfig, normalizeConfig, PRESETS, PRESET_NAMES, PRESET_INFO, PRESET_ALIASES, resolvePreset };
|
|
12
12
|
|
|
13
|
-
/** Apply a named preset over the defaults, returning a full config. */
|
|
13
|
+
/** Apply a named preset (or alias) over the defaults, returning a full config. */
|
|
14
14
|
export function fromPreset(name, overrides = {}) {
|
|
15
|
-
const
|
|
16
|
-
if (!
|
|
17
|
-
return normalizeConfig({ ...
|
|
15
|
+
const canonical = resolvePreset(name);
|
|
16
|
+
if (!canonical) throw new Error(`Unknown preset "${name}". Known: ${PRESET_NAMES.join(', ')}`);
|
|
17
|
+
return normalizeConfig({ ...PRESETS[canonical], ...overrides });
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/** Turn a config into a complete set of files. */
|
package/src/core/options.js
CHANGED
|
@@ -91,6 +91,8 @@ export const OPTIONS = {
|
|
|
91
91
|
},
|
|
92
92
|
coverage: { group: 'quality', type: 'boolean', label: 'Coverage reporting', default: true },
|
|
93
93
|
storybook: { group: 'quality', type: 'boolean', label: 'Storybook (component libraries)', default: false },
|
|
94
|
+
pkgChecks: { group: 'quality', type: 'boolean', label: 'Package checks (publint + are-the-types-wrong)', default: false },
|
|
95
|
+
knip: { group: 'quality', type: 'boolean', label: 'Knip (unused files / deps / exports)', default: false },
|
|
94
96
|
|
|
95
97
|
// ---- lint / format ----
|
|
96
98
|
lint: {
|
|
@@ -124,6 +126,7 @@ export const OPTIONS = {
|
|
|
124
126
|
{ value: 'none', label: 'None' },
|
|
125
127
|
],
|
|
126
128
|
},
|
|
129
|
+
jsr: { group: 'release', type: 'boolean', label: 'Publish to JSR (TS-first registry)', default: false },
|
|
127
130
|
|
|
128
131
|
// ---- github actions (configurable workflows) ----
|
|
129
132
|
workflows: {
|
|
@@ -236,5 +239,11 @@ export function normalizeConfig(input = {}) {
|
|
|
236
239
|
|
|
237
240
|
// Storybook only applies to component libraries.
|
|
238
241
|
if (!cfg.hasFramework || cfg.hasApp || !cfg.hasLibrary) cfg.storybook = false;
|
|
242
|
+
|
|
243
|
+
cfg.publishable = (cfg.hasLibrary || cfg.hasCli) && !cfg.hasApp && !cfg.hasService;
|
|
244
|
+
// Package-correctness checks only make sense for a publishable package.
|
|
245
|
+
if (!cfg.publishable) cfg.pkgChecks = false;
|
|
246
|
+
// JSR is TypeScript-first, ESM, and for plain (non-framework) libraries.
|
|
247
|
+
if (!(cfg.isTs && cfg.hasLibrary && !cfg.hasFramework && !cfg.hasApp)) cfg.jsr = false;
|
|
239
248
|
return cfg;
|
|
240
249
|
}
|
package/src/core/presets.js
CHANGED
|
@@ -23,6 +23,7 @@ export const PRESETS = {
|
|
|
23
23
|
test: 'vitest', coverage: true, lint: 'eslint-prettier', gitHooks: 'simple-git-hooks',
|
|
24
24
|
release: 'changesets', workflows: ['ci', 'npm-publish', 'codeql', 'codecov'],
|
|
25
25
|
deps: 'renovate', community: true, agents: true, vscode: true,
|
|
26
|
+
pkgChecks: true, knip: true,
|
|
26
27
|
},
|
|
27
28
|
minimal: {
|
|
28
29
|
language: 'ts', target: ['library'], moduleFormat: 'dual', bundler: 'tsup',
|
|
@@ -40,6 +41,27 @@ export const PRESETS = {
|
|
|
40
41
|
|
|
41
42
|
export const PRESET_NAMES = Object.keys(PRESETS);
|
|
42
43
|
|
|
44
|
+
// Short shortcuts, e.g. `npx create-packkit lib my-lib`.
|
|
45
|
+
export const PRESET_ALIASES = {
|
|
46
|
+
lib: 'ts-lib',
|
|
47
|
+
jslib: 'js-lib',
|
|
48
|
+
rlib: 'react-lib',
|
|
49
|
+
rapp: 'react-app',
|
|
50
|
+
vlib: 'vue-lib',
|
|
51
|
+
vapp: 'vue-app',
|
|
52
|
+
slib: 'svelte-lib',
|
|
53
|
+
sapp: 'svelte-app',
|
|
54
|
+
svc: 'node-service',
|
|
55
|
+
service: 'node-service',
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/** Resolve a preset name or alias to its canonical preset id (or undefined). */
|
|
59
|
+
export function resolvePreset(name) {
|
|
60
|
+
if (PRESETS[name]) return name;
|
|
61
|
+
if (PRESET_ALIASES[name]) return PRESET_ALIASES[name];
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
43
65
|
// Short gists for the CLI help and the web configurator (tooltips + description).
|
|
44
66
|
export const PRESET_INFO = {
|
|
45
67
|
'ts-lib': 'TypeScript library — dual ESM/CJS, tsup, Vitest, ESLint.',
|