From a76699925efe7c4e9e8333587a0fea2aff400634 Mon Sep 17 00:00:00 2001 From: daichenwei Date: Fri, 4 Sep 2026 11:43:51 +0800 Subject: [PATCH 1/2] feat: expose resolved skip files to extra tool actions --- README.md | 27 +++++++++ src/index.ts | 2 + .../template-storybook/pnpm-workspace.yaml | 2 + test/package-manager-files.test.ts | 60 ++++++++++++++++++- 4 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/package-manager-files/template-storybook/pnpm-workspace.yaml diff --git a/README.md b/README.md index 31d24db..72147f2 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,33 @@ When a local template contains `pnpm-workspace.yaml`, the file is only copied if the project is created with pnpm. Templates loaded from third-party npm packages are copied without this filtering. +The toolkit automatically passes the resolved `skipFiles` list to custom +`extraTools` actions. When an action uses `copyFolder` to copy a local tool +template, forward the received list so the same package-manager filtering is +applied: + +```ts +import { copyFolder, create } from '@rstackjs/create-toolkit'; + +create({ + extraTools: [ + { + value: 'storybook', + label: 'Storybook', + action: ({ distFolder, skipFiles }) => { + copyFolder({ + from: storybookTemplate, + to: distFolder, + skipFiles, + isMergePackageJson: true, + }); + }, + }, + ], + // ...other options +}); +``` + ### Git Initialization By default, the toolkit initializes a Git repository after creating the diff --git a/src/index.ts b/src/index.ts index 4aee23b..de745b0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -464,6 +464,7 @@ type ExtraTool = { action?: (context: { templateName: string; distFolder: string; + skipFiles: string[]; addAgentsMdSearchDirs: (dir: string) => void; }) => unknown; /** @@ -932,6 +933,7 @@ export async function create({ await matchedTool.action({ templateName, distFolder, + skipFiles: localSkipFiles, addAgentsMdSearchDirs: (dir: string) => agentsMdSearchDirs.push(dir), }); diff --git a/test/fixtures/package-manager-files/template-storybook/pnpm-workspace.yaml b/test/fixtures/package-manager-files/template-storybook/pnpm-workspace.yaml new file mode 100644 index 0000000..5ed0b5a --- /dev/null +++ b/test/fixtures/package-manager-files/template-storybook/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +allowBuilds: + esbuild: true diff --git a/test/package-manager-files.test.ts b/test/package-manager-files.test.ts index f2e6632..63dc3f7 100644 --- a/test/package-manager-files.test.ts +++ b/test/package-manager-files.test.ts @@ -2,11 +2,12 @@ import fs from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { beforeEach, expect, rs, test } from 'rstack/test'; -import { create } from '../src'; +import { copyFolder, create } from '../src'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const fixturesDir = path.join(__dirname, 'fixtures', 'package-manager-files'); const testDir = path.join(fixturesDir, 'test-temp-output'); +const extraToolDir = path.join(fixturesDir, 'template-storybook'); beforeEach(() => { rs.unstubAllEnvs(); @@ -36,6 +37,41 @@ async function createProject(projectDir: string) { }); } +async function createProjectWithExtraTool(projectDir: string) { + await create({ + name: 'test', + root: fixturesDir, + templates: ['vanilla'], + getTemplateName: async () => 'vanilla', + git: false, + builtinTools: [], + extraTools: [ + { + value: 'storybook', + label: 'Storybook', + action: ({ distFolder, skipFiles }) => { + copyFolder({ + from: extraToolDir, + to: distFolder, + skipFiles, + isMergePackageJson: true, + }); + }, + }, + ], + argv: [ + 'node', + 'test', + '--dir', + projectDir, + '--template', + 'vanilla', + '--tools', + 'storybook', + ], + }); +} + test('should copy pnpm-workspace.yaml for pnpm', async () => { const projectDir = path.join(testDir, 'pnpm'); rs.stubEnv('npm_config_user_agent', 'pnpm/11.20.0'); @@ -57,3 +93,25 @@ test('should skip pnpm-workspace.yaml for other package managers', async () => { false, ); }); + +test('should copy pnpm-workspace.yaml from an extra tool for pnpm', async () => { + const projectDir = path.join(testDir, 'extra-tool-pnpm'); + rs.stubEnv('npm_config_user_agent', 'pnpm/11.20.0'); + + await createProjectWithExtraTool(projectDir); + + expect( + fs.readFileSync(path.join(projectDir, 'pnpm-workspace.yaml'), 'utf8'), + ).toBe('allowBuilds:\n esbuild: true\n'); +}); + +test('should skip pnpm-workspace.yaml from an extra tool for npm', async () => { + const projectDir = path.join(testDir, 'extra-tool-npm'); + rs.stubEnv('npm_config_user_agent', 'npm/11.0.0'); + + await createProjectWithExtraTool(projectDir); + + expect(fs.existsSync(path.join(projectDir, 'pnpm-workspace.yaml'))).toBe( + false, + ); +}); From 8dbc07a748d6c02f15961cf68a8fef1097723d74 Mon Sep 17 00:00:00 2001 From: daichenwei Date: Fri, 4 Sep 2026 11:49:06 +0800 Subject: [PATCH 2/2] fix: isolate skip files for extra tool actions --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index de745b0..15f009c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -933,7 +933,7 @@ export async function create({ await matchedTool.action({ templateName, distFolder, - skipFiles: localSkipFiles, + skipFiles: [...localSkipFiles], addAgentsMdSearchDirs: (dir: string) => agentsMdSearchDirs.push(dir), });