Skip to content

Commit 1633789

Browse files
feat: update create-awesome-node-app to version 0.6.6 with improved scaffolding, added fs-extra dependency, and enhanced smoke tests
1 parent f629ead commit 1633789

9 files changed

Lines changed: 174 additions & 31 deletions

File tree

package-lock.json

Lines changed: 39 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/create-awesome-node-app/CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,32 @@
11
# create-awesome-node-app
22

3+
## 0.6.6
4+
5+
### Patch Changes
6+
7+
- Fix scaffolding so full template file tree is copied instead of producing an almost empty project.
8+
9+
Highlights:
10+
- Repair file discovery: removed broken readdirp negative-only filter that yielded 0 matches; now enumerate all files then apply internal skip rules.
11+
- Correct handling of special `[src]/` token directories so template source files land in the configured `srcDir`.
12+
- Add missing runtime dependency `fs-extra` (previously only implicitly relied upon) to prevent potential runtime module resolution errors.
13+
- Fix `appendTemplate` mapping so templated append operations render correctly (was incorrectly using plain append loader).
14+
- Add verbose debug logs (behind `--verbose`) for template directory resolution, first discovered file, and total operations count to ease future diagnostics.
15+
- Strengthen smoke test to assert presence of critical scaffold artifacts (e.g. `README.md`, `tsconfig.json`, `index.html`, `eslint.config.mjs`, `src/App.tsx`, `src/main.tsx`).
16+
17+
Result: Running the CLI now prepares and copies ~50 operations for the React Vite starter template (previously 0), restoring expected developer experience.
18+
19+
- Updated dependencies
20+
- @create-node-app/core@0.5.5
21+
22+
## 0.6.5
23+
24+
### Patch Changes
25+
26+
- Fix
27+
- Updated dependencies
28+
- @create-node-app/core@0.5.4
29+
330
## 0.6.2
431

532
### Patch Changes

packages/create-awesome-node-app/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "create-awesome-node-app",
3-
"version": "0.6.2",
3+
"version": "0.6.6",
44
"type": "module",
55
"description": "Command line tool to create Node apps with a lot of different templates and extensions.",
66
"license": "MIT",
@@ -28,7 +28,8 @@
2828
"exports": {
2929
".": {
3030
"types": "./dist/index.d.ts",
31-
"import": "./index.js"
31+
"import": "./index.js",
32+
"require": "./dist/index.cjs"
3233
}
3334
},
3435
"files": [
@@ -52,7 +53,7 @@
5253
"test": "node --test tests/**/*.test.mjs"
5354
},
5455
"dependencies": {
55-
"@create-node-app/core": "*",
56+
"@create-node-app/core": "^0.5.5",
5657
"axios": "^1.12.2",
5758
"ci-info": "^4.3.0",
5859
"commander": "^14.0.1",

packages/create-awesome-node-app/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ const main = async () => {
8080
const packageManager = useYarn ? "yarn" : usePnpm ? "pnpm" : "npm";
8181

8282
const templatesOrExtensions: TemplateOrExtension[] = [restOpts.template]
83+
.concat(Array.isArray(restOpts.extend) ? restOpts.extend : [])
8384
.filter(Boolean)
8485
.reduce((acc, templateOrExtension) => {
8586
if (!templateOrExtension) return acc;

packages/create-awesome-node-app/tests/smoke.test.mjs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ try {
3535
if (!existsSync(projectDir)) {
3636
throw new Error('Project directory was not created');
3737
}
38+
// Assert key scaffolded files exist
39+
const expectedFiles = [
40+
'README.md',
41+
'tsconfig.json',
42+
'index.html',
43+
'eslint.config.mjs',
44+
'src/App.tsx',
45+
'src/main.tsx'
46+
];
47+
const missing = expectedFiles.filter(f => !existsSync(join(projectDir, f)));
48+
if (missing.length) {
49+
throw new Error('Missing expected scaffold files: ' + missing.join(', '));
50+
}
3851
console.log('Smoke test passed');
3952
} catch (err) {
4053
console.error('Smoke test failed:', err.message);

packages/create-node-app-core/CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
# @create-node-app/core
22

3+
## 0.5.5
4+
5+
### Patch Changes
6+
7+
- Fix scaffolding so full template file tree is copied instead of producing an almost empty project.
8+
9+
Highlights:
10+
- Repair file discovery: removed broken readdirp negative-only filter that yielded 0 matches; now enumerate all files then apply internal skip rules.
11+
- Correct handling of special `[src]/` token directories so template source files land in the configured `srcDir`.
12+
- Add missing runtime dependency `fs-extra` (previously only implicitly relied upon) to prevent potential runtime module resolution errors.
13+
- Fix `appendTemplate` mapping so templated append operations render correctly (was incorrectly using plain append loader).
14+
- Add verbose debug logs (behind `--verbose`) for template directory resolution, first discovered file, and total operations count to ease future diagnostics.
15+
- Strengthen smoke test to assert presence of critical scaffold artifacts (e.g. `README.md`, `tsconfig.json`, `index.html`, `eslint.config.mjs`, `src/App.tsx`, `src/main.tsx`).
16+
17+
Result: Running the CLI now prepares and copies ~50 operations for the React Vite starter template (previously 0), restoring expected developer experience.
18+
19+
## 0.5.4
20+
21+
### Patch Changes
22+
23+
- Fix
24+
325
## 0.5.2
426

527
### Patch Changes

packages/create-node-app-core/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { execSync } from "child_process";
55
import type { TemplateOrExtension } from "./loaders.js";
66
export type { TemplateOrExtension } from "./loaders.js";
77
import { createApp } from "./installer.js";
8+
export { downloadRepository } from "./git.js";
89

910
export const checkNodeVersion = (
1011
requiredVersion: string,

packages/create-node-app-core/loaders.ts

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import { promisify } from "util";
99
const writeFileAsync = promisify(fs.writeFile);
1010
const copyFileAsync = promisify(fs.copyFile);
1111

12+
// Token used inside templates to denote the source directory.
13+
// Templates name a directory literally `[src]` and files inside like `[src]/App.tsx.template`.
14+
// We map the prefix `[src]/` to the selected srcDir (e.g. `src/`).
1215
const SRC_PATH_PATTERN = "[src]/";
1316
const DEFAULT_SRC_PATH = "src/";
1417

@@ -149,8 +152,6 @@ const batchedAppendFiles = async (
149152
await Promise.all(batchedPromises);
150153
};
151154

152-
// AI tool specific filters removed (cursor/copilot). All files now processed uniformly.
153-
154155
const copyLoader: FileLoader =
155156
({ root, templateDir, verbose, srcDir }) =>
156157
async ({ path }) => {
@@ -271,8 +272,9 @@ const fileLoader: FileLoader =
271272
copy: copyLoader,
272273
append: appendLoader,
273274
copyTemplate: templateLoader,
274-
appendTemplate: appendLoader,
275-
};
275+
// appendTemplate means treat as a template (interpolate) but append instead of overwrite
276+
appendTemplate: templateLoader,
277+
} as const;
276278

277279
await loaders[mode]({
278280
root,
@@ -332,31 +334,55 @@ export const loadFiles = async ({
332334
const operations = [];
333335
for await (const { url: templateOrExtensionUrl } of templatesOrExtensions) {
334336
const templateDir = await getTemplateDirPath(templateOrExtensionUrl);
337+
if (verbose) {
338+
try {
339+
const stat = fs.existsSync(templateDir)
340+
? fs.statSync(templateDir)
341+
: undefined;
342+
console.log(
343+
pc.dim(
344+
`[cna] Template dir resolved: ${templateDir} exists=${!!stat} isDir=$${stat?.isDirectory?.()}`,
345+
),
346+
);
347+
} catch {
348+
// ignore
349+
}
350+
}
335351

336352
if (
337353
fs.existsSync(templateDir) &&
338354
fs.statSync(templateDir).isDirectory()
339355
) {
356+
// readdirp requires at least one positive pattern when using negations; we'll include '**/*'
357+
// and then filter out undesired files. This ensures templates are actually discovered.
358+
let debugFirst = true;
359+
// Collect all file entries without filters then skip undesired patterns manually
360+
const skipGlobs = [
361+
/\bpackage\.js$/,
362+
/\bpackage\.json$/,
363+
/\bpackage-lock\.json$/,
364+
/\btemplate\.json$/,
365+
/\byarn\.lock$/,
366+
/\bpnpm-lock\.yaml$/,
367+
];
368+
const skipManager = usePnpm
369+
? [/\.if-npm\./, /\.if-yarn\./]
370+
: useYarn
371+
? [/\.if-npm\./, /\.if-pnpm\./]
372+
: [/\.if-yarn\./, /\.if-pnpm\./];
373+
const shouldSkip = (p: string) =>
374+
[...skipGlobs, ...skipManager].some((rgx) => rgx.test(p));
375+
340376
for await (const entry of readdirp(templateDir, {
341-
fileFilter: [
342-
"!package.js",
343-
"!package.json",
344-
"!package-lock.json",
345-
"!template.json",
346-
"!yarn.lock",
347-
"!pnpm-lock.yaml",
348-
// based on the package manager we want to ignore files containing
349-
// the other package as condition.
350-
// For example, if `usePnpm` is true, the we need to ignore
351-
// all files with `.if-npm` or `.if-yarn` somewhere in the name.
352-
...(usePnpm
353-
? ["!*.if-npm.*", "!*.if-yarn.*"]
354-
: useYarn
355-
? ["!*.if-npm.*", "!*.if-pnpm.*"]
356-
: ["!*.if-yarn.*", "!*.if-pnpm.*"]),
357-
],
358-
directoryFilter: ["!package"],
377+
type: "files",
378+
alwaysStat: false,
359379
})) {
380+
if (shouldSkip(entry.path)) continue;
381+
if (entry.path.startsWith("package/")) continue; // skip helper package dir
382+
if (verbose && debugFirst) {
383+
console.log(pc.dim(`[cna] First discovered file: ${entry.path}`));
384+
debugFirst = false;
385+
}
360386
operations.push({
361387
root,
362388
templateDir,
@@ -375,6 +401,21 @@ export const loadFiles = async ({
375401
}
376402
}
377403

404+
if (verbose) {
405+
console.log(
406+
pc.dim(
407+
`[cna] Prepared ${operations.length} file operations from ${templatesOrExtensions.length} template(s)`,
408+
),
409+
);
410+
if (operations.length === 0) {
411+
console.log(
412+
pc.yellow(
413+
"[cna] No files discovered. Check that the template repository was cloned and fileFilter patterns are correct.",
414+
),
415+
);
416+
}
417+
}
418+
378419
await Promise.all(
379420
operations.map((operation) => fileLoader(operation)(operation.entry)),
380421
);

packages/create-node-app-core/package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@create-node-app/core",
3-
"version": "0.5.2",
3+
"version": "0.5.5",
44
"type": "module",
55
"main": "./dist/index.cjs",
66
"types": "./dist/index.d.ts",
@@ -27,8 +27,8 @@
2727
"lint": "eslint '**/*.{ts,tsx,js}'",
2828
"lint:fix": "eslint '**/*.{ts,tsx,js}' --fix",
2929
"type-check": "tsc --noEmit",
30-
"build": "tsup ./index.ts --format esm,cjs --dts --external simple-git,fs,path,child_process --no-splitting",
31-
"dev": "tsup ./index.ts --format esm,cjs --watch --dts --external simple-git,fs,path,child_process --no-splitting"
30+
"build": "tsup ./index.ts --format esm,cjs --dts --no-splitting",
31+
"dev": "tsup ./index.ts --format esm,cjs --watch --dts --no-splitting"
3232
},
3333
"devDependencies": {
3434
"@create-node-app/eslint-config-ts": "*",
@@ -52,6 +52,7 @@
5252
"cross-spawn": "^7.0.6",
5353
"debug": "^4.4.3",
5454
"envinfo": "^7.14.0",
55+
"fs-extra": "^11.2.0",
5556
"simple-git": "^3.28.0",
5657
"lodash.merge": "^4.6.2",
5758
"readdirp": "^4.1.2",

0 commit comments

Comments
 (0)