create-packkit 1.4.0 → 1.5.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 CHANGED
@@ -80,6 +80,13 @@ Packkit is a pure `config → { files }` **core** that runs in both Node and the
80
80
 
81
81
  Both drive from one options schema ([`src/core/options.js`](src/core/options.js)), so the CLI and the web page always stay in sync.
82
82
 
83
+ ## Staying fresh
84
+
85
+ Two GitHub Actions keep the templates honest:
86
+
87
+ - **Dependency freshness** — a weekly check flags any version Packkit writes into generated projects that's fallen a major behind (versions Dependabot can't see), and opens an issue.
88
+ - **Integration** — on any change to generation logic or a template dependency, it generates every preset, installs it, and runs its real checks (build/test/lint, and actually starts services) — so an update can't silently break the projects you'd get.
89
+
83
90
  ## License
84
91
 
85
92
  [MIT](LICENSE) © DanMat
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-packkit",
3
- "version": "1.4.0",
3
+ "version": "1.5.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": {
@@ -25,6 +25,7 @@
25
25
  "start": "node bin/cli.js",
26
26
  "test": "node --test",
27
27
  "check:deps": "node scripts/check-template-deps.mjs",
28
+ "integration": "node scripts/integration.mjs",
28
29
  "build:web": "esbuild src/core/index.js --bundle --format=esm --outfile=docs/packkit-core.js"
29
30
  },
30
31
  "repository": {
@@ -46,19 +46,23 @@ export default {
46
46
  pkg.scripts.build = tool;
47
47
  pkg.scripts.dev = `${tool} --watch`;
48
48
  pkg.devDependencies = { [tool]: tool === 'tsup' ? '^8.0.0' : '^0.6.0' };
49
+ // tsup/tsdown resolve `typescript` even for plain-JS builds; TS projects
50
+ // already get it from the typescript feature.
51
+ if (!cfg.isTs) pkg.devDependencies.typescript = '^5.9.3';
49
52
  } else if (cfg.bundler === 'unbuild') {
50
53
  files['build.config.ts'] = unbuildConfig(cfg);
51
54
  pkg.scripts.build = 'unbuild';
52
55
  pkg.scripts.dev = 'unbuild --stub';
53
- pkg.devDependencies = { unbuild: '^2.0.0' };
56
+ pkg.devDependencies = { unbuild: '^3.0.0' };
54
57
  } else if (cfg.bundler === 'rollup') {
55
- files[`rollup.config.${cfg.ext === 'ts' ? 'ts' : 'js'}`] = rollupConfig(cfg, formats);
58
+ // Always a .js config rollup can't load a .ts config without a loader.
59
+ files['rollup.config.js'] = rollupConfig(cfg, formats);
56
60
  pkg.scripts.build = 'rollup -c';
57
61
  pkg.scripts.dev = 'rollup -c -w';
58
62
  pkg.devDependencies = {
59
63
  rollup: '^4.0.0',
60
- ...(cfg.isTs ? { '@rollup/plugin-typescript': '^11.0.0', tslib: '^2.6.0' } : {}),
61
- ...(cfg.minify ? { '@rollup/plugin-terser': '^0.4.0' } : {}),
64
+ ...(cfg.isTs ? { '@rollup/plugin-typescript': '^12.0.0', tslib: '^2.6.0' } : {}),
65
+ ...(cfg.minify ? { '@rollup/plugin-terser': '^1.0.0' } : {}),
62
66
  };
63
67
  } else if (cfg.bundler === 'none' && cfg.isTs) {
64
68
  // tsc-only build for TypeScript.
@@ -99,6 +103,7 @@ function unbuildConfig(cfg) {
99
103
  `\tentries: ['src/index'],`,
100
104
  `\tdeclaration: ${cfg.isTs},`,
101
105
  `\tclean: true,`,
106
+ `\tfailOnWarn: false,`,
102
107
  `\trollup: { emitCJS: ${cfg.hasCjs}${cfg.minify ? ', esbuild: { minify: true }' : ''} },`,
103
108
  `});`,
104
109
  ``,
@@ -113,7 +118,8 @@ function rollupConfig(cfg, formats) {
113
118
  cfg.isTs ? `import typescript from '@rollup/plugin-typescript';` : null,
114
119
  cfg.minify ? `import terser from '@rollup/plugin-terser';` : null,
115
120
  ].filter(Boolean);
116
- const plugins = [cfg.isTs ? 'typescript()' : null, cfg.minify ? 'terser()' : null].filter(Boolean);
121
+ // plugin-typescript needs a declarationDir when the tsconfig enables declarations.
122
+ const plugins = [cfg.isTs ? `typescript({ declarationDir: 'dist', rootDir: 'src', exclude: ['**/*.test.ts'] })` : null, cfg.minify ? 'terser()' : null].filter(Boolean);
117
123
  const pluginLine = plugins.length ? `\n\tplugins: [${plugins.join(', ')}],` : '';
118
124
  return [
119
125
  (imports.length ? imports.join('\n') + '\n' : '') + `export default {`,
@@ -101,7 +101,7 @@ function svelte(cfg, files, pkg, forApp) {
101
101
  const script = cfg.isTs ? `<script lang="ts">` : `<script>`;
102
102
  // Shared by the Vite app build and the Vitest (test) config; enables TS in SFCs.
103
103
  files['svelte.config.js'] = `import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';\n\nexport default { preprocess: vitePreprocess() };\n`;
104
- pkg.devDependencies['@sveltejs/vite-plugin-svelte'] = '^4.0.0';
104
+ pkg.devDependencies['@sveltejs/vite-plugin-svelte'] = '^7.0.0';
105
105
  if (cfg.isTs) pkg.devDependencies['svelte-check'] = '^4.0.0';
106
106
  if (forApp) {
107
107
  files['index.html'] = htmlShell(cfg, `/src/main.${cfg.ext}`);
@@ -29,12 +29,12 @@ export default {
29
29
  } else if (cfg.gitHooks === 'lefthook') {
30
30
  files['lefthook.yml'] = lefthookYml(cfg, staged);
31
31
  pkg.scripts.prepare = 'lefthook install';
32
- pkg.devDependencies.lefthook = '^1.7.0';
32
+ pkg.devDependencies.lefthook = '^2.0.0';
33
33
  }
34
34
 
35
35
  if (needsLintStaged) {
36
36
  pkg['lint-staged'] = staged;
37
- pkg.devDependencies['lint-staged'] = '^15.2.0';
37
+ pkg.devDependencies['lint-staged'] = '^17.0.0';
38
38
  }
39
39
 
40
40
  return { files, pkg };
@@ -26,23 +26,23 @@ export default {
26
26
  files['eslint.config.js'] = eslintFlatConfig(cfg);
27
27
  pkg.scripts.lint = 'eslint .';
28
28
  pkg.scripts['lint:fix'] = 'eslint . --fix';
29
- pkg.devDependencies.eslint = '^9.0.0';
30
- pkg.devDependencies['@eslint/js'] = '^9.0.0';
29
+ pkg.devDependencies.eslint = '^10.0.0';
30
+ pkg.devDependencies['@eslint/js'] = '^10.0.0';
31
31
  if (cfg.isTs) pkg.devDependencies['typescript-eslint'] = '^8.0.0';
32
32
  } else if (cfg.lint === 'oxlint') {
33
33
  pkg.scripts.lint = 'oxlint';
34
- pkg.devDependencies.oxlint = '^0.9.0';
34
+ pkg.devDependencies.oxlint = '^1.0.0';
35
35
  } else if (cfg.lint === 'biome') {
36
36
  files['biome.json'] = toJson({
37
- $schema: 'https://biomejs.dev/schemas/1.8.0/schema.json',
37
+ $schema: 'https://biomejs.dev/schemas/2.1.2/schema.json',
38
38
  formatter: { enabled: true, indentStyle: 'tab', lineWidth: 100 },
39
- linter: { enabled: true, rules: { recommended: true } },
39
+ linter: { enabled: true },
40
40
  javascript: { formatter: { quoteStyle: 'single', trailingCommas: 'all' } },
41
41
  });
42
- pkg.scripts.lint = 'biome check .';
43
- pkg.scripts['lint:fix'] = 'biome check --write .';
42
+ pkg.scripts.lint = 'biome lint .';
43
+ pkg.scripts['lint:fix'] = 'biome lint --write .';
44
44
  pkg.scripts.format = 'biome format --write .';
45
- pkg.devDependencies['@biomejs/biome'] = '^1.8.0';
45
+ pkg.devDependencies['@biomejs/biome'] = '^2.0.0';
46
46
  }
47
47
 
48
48
  return { files, pkg };
@@ -29,10 +29,10 @@ export default {
29
29
  npm: { publish: true },
30
30
  });
31
31
  pkg.scripts.release = 'release-it';
32
- pkg.devDependencies['release-it'] = '^17.0.0';
32
+ pkg.devDependencies['release-it'] = '^20.0.0';
33
33
  } else if (cfg.release === 'np') {
34
34
  pkg.scripts.release = 'np';
35
- pkg.devDependencies.np = '^10.0.0';
35
+ pkg.devDependencies.np = '^11.0.0';
36
36
  }
37
37
 
38
38
  return { files, pkg };
@@ -20,7 +20,7 @@ export default {
20
20
  start: 'node dist/index.js',
21
21
  dev: cfg.isTs ? 'tsx watch src/index.ts' : 'node --watch src/index.js',
22
22
  },
23
- dependencies: { hono: '^4.5.0', '@hono/node-server': '^1.12.0' },
23
+ dependencies: { hono: '^4.5.0', '@hono/node-server': '^2.0.0' },
24
24
  ...(cfg.isTs ? { devDependencies: { tsx: '^4.0.0' } } : {}),
25
25
  },
26
26
  };
@@ -18,7 +18,7 @@ export default {
18
18
  ``,
19
19
  `const config: StorybookConfig = {`,
20
20
  `\tstories: ['../src/**/*.stories.@(ts|tsx|svelte)'],`,
21
- `\taddons: ['@storybook/addon-essentials'],`,
21
+ `\taddons: [],`,
22
22
  `\tframework: '${fw.builder}',`,
23
23
  `};`,
24
24
  `export default config;`,
@@ -37,11 +37,10 @@ export default {
37
37
  'build-storybook': 'storybook build',
38
38
  },
39
39
  devDependencies: {
40
- storybook: '^8.2.0',
41
- [fw.builder]: '^8.2.0',
42
- [fw.renderer]: '^8.2.0',
43
- '@storybook/addon-essentials': '^8.2.0',
44
- vite: '^5.4.0',
40
+ storybook: '^10.0.0',
41
+ [fw.builder]: '^10.0.0',
42
+ [fw.renderer]: '^10.0.0',
43
+ vite: '^8.0.0',
45
44
  },
46
45
  },
47
46
  };
@@ -35,9 +35,9 @@ export default {
35
35
  ].filter((l) => l !== null).join('\n');
36
36
  pkg.scripts.test = 'vitest run';
37
37
  pkg.scripts['test:watch'] = 'vitest';
38
- pkg.devDependencies.vitest = '^2.0.0';
38
+ pkg.devDependencies.vitest = '^4.0.0';
39
39
  if (cfg.hasFramework) {
40
- pkg.devDependencies.jsdom = '^25.0.0';
40
+ pkg.devDependencies.jsdom = '^29.0.0';
41
41
  pkg.devDependencies['@testing-library/dom'] = '^10.0.0';
42
42
  if (cfg.isReact) pkg.devDependencies['@testing-library/react'] = '^16.0.0';
43
43
  if (cfg.isVue) pkg.devDependencies['@testing-library/vue'] = '^8.1.0';
@@ -45,17 +45,17 @@ export default {
45
45
  }
46
46
  if (cfg.coverage) {
47
47
  pkg.scripts.coverage = 'vitest run --coverage';
48
- pkg.devDependencies['@vitest/coverage-v8'] = '^2.0.0';
48
+ pkg.devDependencies['@vitest/coverage-v8'] = '^4.0.0';
49
49
  }
50
50
  files[`src/index.test.${testExt}`] = exampleTest('vitest', cfg);
51
51
  } else if (cfg.test === 'jest') {
52
52
  files['jest.config.js'] = jestConfig(cfg);
53
53
  pkg.scripts.test = 'jest';
54
54
  pkg.scripts['test:watch'] = 'jest --watch';
55
- pkg.devDependencies.jest = '^29.0.0';
55
+ pkg.devDependencies.jest = '^30.0.0';
56
56
  if (cfg.isTs) {
57
57
  pkg.devDependencies['ts-jest'] = '^29.0.0';
58
- pkg.devDependencies['@types/jest'] = '^29.0.0';
58
+ pkg.devDependencies['@types/jest'] = '^30.0.0';
59
59
  }
60
60
  if (cfg.coverage) pkg.scripts.coverage = 'jest --coverage';
61
61
  files[`src/index.test.${testExt}`] = exampleTest('jest', cfg);
@@ -156,6 +156,11 @@ function jestConfig(cfg) {
156
156
  `\tpreset: 'ts-jest/presets/default-esm',`,
157
157
  `\ttestEnvironment: 'node',`,
158
158
  `\textensionsToTreatAsEsm: ['.ts'],`,
159
+ `\ttransform: {`,
160
+ `\t\t'^.+\\\\.ts$': ['ts-jest', { useESM: true, tsconfig: { verbatimModuleSyntax: false } }],`,
161
+ `\t},`,
162
+ `\t// let \`./x.js\` imports resolve to the .ts source under ESM`,
163
+ `\tmoduleNameMapper: { '^(\\\\.{1,2}/.*)\\\\.js$': '$1' },`,
159
164
  `};`,
160
165
  ``,
161
166
  ].join('\n');
@@ -41,7 +41,7 @@ export default {
41
41
  },
42
42
  pkg: {
43
43
  devDependencies: {
44
- typescript: '^5.5.0',
44
+ typescript: '^5.9.3',
45
45
  '@types/node': `^${cfg.nodeVersion}.0.0`,
46
46
  },
47
47
  },
@@ -4,9 +4,9 @@
4
4
  // from frameworks.js. Svelte libraries ship source and don't come through here.
5
5
 
6
6
  const PLUGIN = {
7
- react: { import: `import react from '@vitejs/plugin-react';`, call: 'react()', dep: { '@vitejs/plugin-react': '^4.3.0' } },
8
- vue: { import: `import vue from '@vitejs/plugin-vue';`, call: 'vue()', dep: { '@vitejs/plugin-vue': '^5.1.0' } },
9
- svelte: { import: `import { svelte } from '@sveltejs/vite-plugin-svelte';`, call: 'svelte()', dep: { '@sveltejs/vite-plugin-svelte': '^4.0.0' } },
7
+ react: { import: `import react from '@vitejs/plugin-react';`, call: 'react()', dep: { '@vitejs/plugin-react': '^6.0.0' } },
8
+ vue: { import: `import vue from '@vitejs/plugin-vue';`, call: 'vue()', dep: { '@vitejs/plugin-vue': '^6.0.0' } },
9
+ svelte: { import: `import { svelte } from '@sveltejs/vite-plugin-svelte';`, call: 'svelte()', dep: { '@sveltejs/vite-plugin-svelte': '^7.0.0' } },
10
10
  };
11
11
 
12
12
  export default {
@@ -14,10 +14,10 @@ export default {
14
14
  active: (cfg) => cfg.viteBuild,
15
15
  apply(cfg) {
16
16
  const files = {};
17
- const pkg = { scripts: {}, devDependencies: { vite: '^5.4.0' } };
17
+ const pkg = { scripts: {}, devDependencies: { vite: '^8.0.0' } };
18
18
  const p = PLUGIN[cfg.framework];
19
19
  Object.assign(pkg.devDependencies, p.dep);
20
- if (cfg.isVue && cfg.isTs) pkg.devDependencies['vue-tsc'] = '^2.0.0';
20
+ if (cfg.isVue && cfg.isTs) pkg.devDependencies['vue-tsc'] = '^3.0.0';
21
21
 
22
22
  if (cfg.hasApp) {
23
23
  // Front-end SPA — not a published package.
@@ -48,8 +48,8 @@ export default {
48
48
  ].join('\n');
49
49
  pkg.scripts.build = 'vite build';
50
50
  pkg.scripts.dev = 'vite build --watch';
51
- pkg.devDependencies['vite-plugin-dts'] = '^4.0.0';
52
- if (cfg.isVue) pkg.devDependencies['vue-tsc'] = '^2.0.0';
51
+ pkg.devDependencies['vite-plugin-dts'] = '^5.0.0';
52
+ if (cfg.isVue) pkg.devDependencies['vue-tsc'] = '^3.0.0';
53
53
  // entry points
54
54
  pkg.files = ['dist'];
55
55
  pkg.type = 'module';
@@ -40,11 +40,11 @@ export function buildMonorepo(cfg) {
40
40
  },
41
41
  devDependencies: {
42
42
  turbo: '^2.0.0',
43
- typescript: '^5.5.0',
43
+ typescript: '^5.9.3',
44
44
  tsup: '^8.0.0',
45
- vitest: '^2.0.0',
46
- eslint: '^9.0.0',
47
- '@eslint/js': '^9.0.0',
45
+ vitest: '^4.0.0',
46
+ eslint: '^10.0.0',
47
+ '@eslint/js': '^10.0.0',
48
48
  'typescript-eslint': '^8.0.0',
49
49
  prettier: '^3.3.0',
50
50
  '@changesets/cli': '^2.27.0',