Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
node_modules
dist/
test-results
test-temp-*

# IDE
.vscode/*
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"fs-extra": "^11.3.2",
"minimist": "^1.2.8",
"picocolors": "^1.1.1",
"rimraf": "^6.1.2",
"rslog": "^1.3.2",
"simple-git-hooks": "^2.13.1",
"typescript": "^5.9.3"
Expand Down
57 changes: 57 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 10 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ const readJSON = async (path: string) =>
const readPackageJson = async (filePath: string) =>
readJSON(path.join(filePath, 'package.json'));

const parseArgv = () => {
const argv = minimist<Argv>(process.argv.slice(2), {
const parseArgv = (processArgv: string[]) => {
const argv = minimist<Argv>(processArgv.slice(2), {
alias: { h: 'help', d: 'dir', t: 'template' },
});

Expand Down Expand Up @@ -210,7 +210,7 @@ type ExtraTool = {
command?: string;
};

async function runCommand(command: string, cwd: string) {
function runCommand(command: string, cwd: string) {
const [bin, ...args] = command.split(' ');
spawn.sync(bin, args, {
stdio: 'inherit',
Expand All @@ -228,6 +228,7 @@ export async function create({
version,
noteInformation,
extraTools,
argv: processArgv = process.argv,
}: {
name: string;
root: string;
Expand All @@ -248,11 +249,15 @@ export async function create({
* Specify additional tools.
*/
extraTools?: ExtraTool[];
/**
* For test purpose, override the default argv (process.argv).
*/
argv?: string[];
}) {
console.log('');
logger.greet(`◆ Create ${upperFirst(name)} Project`);

const argv = parseArgv();
const argv = parseArgv(processArgv);

if (argv.help) {
logHelpMessage(name, templates);
Expand Down Expand Up @@ -346,7 +351,7 @@ export async function create({
await matchedTool.action();
}
if (matchedTool?.command) {
await runCommand(matchedTool.command, distFolder);
runCommand(matchedTool.command, distFolder);
}
continue;
}
Expand Down
53 changes: 24 additions & 29 deletions test/agents.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { assert, beforeEach, expect, test } from '@rstest/core';
import { create } from '../dist/index.js';
import { create } from '../src';
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test imports from ../src instead of ../dist/index.js, which is inconsistent with test/index.test.ts that imports from ../dist/index.js. Consider using the same import path across test files for consistency, especially since the built distribution is what will be published.

Suggested change
import { create } from '../src';
import { create } from '../dist/index.js';

Copilot uses AI. Check for mistakes.

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const testDir = path.join(__dirname, 'temp');
const fixturesDir = path.join(__dirname, 'fixtures', 'agents-md');
const testDir = path.join(fixturesDir, 'test-temp-output');
Copy link

Copilot AI Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test output directory test-temp-output is now placed inside fixturesDir (fixtures/agents-md), which means test outputs will be created within the fixtures directory. This could lead to:

  1. Test artifacts polluting the fixtures directory
  2. Potential conflicts if fixtures are version-controlled
  3. Issues if fixtures directory is read-only

Consider placing the test output directory at the test root level instead:

const testDir = path.join(__dirname, 'test-temp-output');
Suggested change
const testDir = path.join(fixturesDir, 'test-temp-output');
const testDir = path.join(__dirname, 'test-temp-output');

Copilot uses AI. Check for mistakes.

beforeEach(() => {
// Clean up test directory before each test
Expand All @@ -15,13 +15,8 @@ beforeEach(() => {
}
fs.mkdirSync(testDir, { recursive: true });

// Store original argv
const originalArgv = process.argv;

// Return cleanup function
return () => {
// Restore original argv and clean up
process.argv = originalArgv;
if (fs.existsSync(testDir)) {
fs.rmSync(testDir, { recursive: true });
}
Expand All @@ -30,13 +25,13 @@ beforeEach(() => {

test('should generate AGENTS.md with no tools selected', async () => {
const projectDir = path.join(testDir, 'no-tools');
process.argv = ['node', 'test', '--dir', projectDir, '--template', 'vanilla'];

await create({
name: 'test',
root: fixturesDir,
templates: ['vanilla'],
getTemplateName: async () => 'vanilla',
argv: ['node', 'test', '--dir', projectDir, '--template', 'vanilla'],
});

const agentsPath = path.join(projectDir, 'AGENTS.md');
Expand Down Expand Up @@ -75,22 +70,22 @@ test('should generate AGENTS.md with no tools selected', async () => {

test('should generate AGENTS.md with single tool selected', async () => {
const projectDir = path.join(testDir, 'single-tool');
process.argv = [
'node',
'test',
'--dir',
projectDir,
'--template',
'vanilla',
'--tools',
'biome',
];

await create({
name: 'test',
root: fixturesDir,
templates: ['vanilla'],
getTemplateName: async () => 'vanilla',
argv: [
'node',
'test',
'--dir',
projectDir,
'--template',
'vanilla',
'--tools',
'biome',
],
});

const agentsPath = path.join(projectDir, 'AGENTS.md');
Expand Down Expand Up @@ -134,16 +129,6 @@ test('should generate AGENTS.md with single tool selected', async () => {

test('should generate AGENTS.md with eslint tool and template mapping', async () => {
const projectDir = path.join(testDir, 'eslint-tool');
process.argv = [
'node',
'test',
'--dir',
projectDir,
'--template',
'vanilla',
'--tools',
'eslint',
];

await create({
name: 'test',
Expand All @@ -154,6 +139,16 @@ test('should generate AGENTS.md with eslint tool and template mapping', async ()
if (templateName === 'vanilla') return 'vanilla-ts';
return null;
},
argv: [
'node',
'test',
'--dir',
projectDir,
'--template',
'vanilla',
'--tools',
'eslint',
],
});

const agentsPath = path.join(projectDir, 'AGENTS.md');
Expand Down Expand Up @@ -196,13 +191,13 @@ test('should generate AGENTS.md with eslint tool and template mapping', async ()

test('should merge top-level sections from AGENTS.md files', async () => {
const projectDir = path.join(testDir, 'h1-support');
process.argv = ['node', 'test', '--dir', projectDir, '--template', 'vanilla'];

await create({
name: 'test',
root: fixturesDir,
templates: ['vanilla'],
getTemplateName: async () => 'vanilla',
argv: ['node', 'test', '--dir', projectDir, '--template', 'vanilla'],
});

const agentsPath = path.join(projectDir, 'AGENTS.md');
Expand Down
Loading