mirror of
https://github.com/yamadashy/repomix.git
synced 2026-06-11 15:37:16 +02:00
Merge pull request #886 from yamadashy/feat/js-config-support
feat(config): Add TypeScript/JavaScript config file support with defineConfig helper
This commit is contained in:
@@ -995,12 +995,84 @@ When running as an MCP server, Repomix provides the following tools:
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
Create a `repomix.config.json` file in your project root for custom configurations.
|
||||
Repomix supports multiple configuration file formats for flexibility and ease of use.
|
||||
|
||||
### Configuration File Formats
|
||||
|
||||
Repomix will automatically search for configuration files in the following priority order:
|
||||
|
||||
1. **TypeScript** (`repomix.config.ts`, `repomix.config.mts`, `repomix.config.cts`)
|
||||
2. **JavaScript/ES Module** (`repomix.config.js`, `repomix.config.mjs`, `repomix.config.cjs`)
|
||||
3. **JSON** (`repomix.config.json5`, `repomix.config.jsonc`, `repomix.config.json`)
|
||||
|
||||
#### JSON Configuration
|
||||
|
||||
Create a `repomix.config.json` file in your project root:
|
||||
|
||||
```bash
|
||||
repomix --init
|
||||
```
|
||||
|
||||
This will create a `repomix.config.json` file with default settings.
|
||||
|
||||
#### TypeScript Configuration
|
||||
|
||||
TypeScript configuration files provide the best developer experience with full type checking and IDE support.
|
||||
|
||||
**Installation:**
|
||||
|
||||
To use TypeScript or JavaScript configuration with `defineConfig`, you need to install Repomix as a dev dependency:
|
||||
|
||||
```bash
|
||||
npm install -D repomix
|
||||
```
|
||||
|
||||
**Example:**
|
||||
|
||||
```typescript
|
||||
// repomix.config.ts
|
||||
import { defineConfig } from 'repomix';
|
||||
|
||||
export default defineConfig({
|
||||
output: {
|
||||
filePath: 'output.xml',
|
||||
style: 'xml',
|
||||
removeComments: true,
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/node_modules/**', '**/dist/**'],
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- ✅ Full TypeScript type checking in your IDE
|
||||
- ✅ Excellent IDE autocomplete and IntelliSense
|
||||
- ✅ Use dynamic values (timestamps, environment variables, etc.)
|
||||
|
||||
**Dynamic Values Example:**
|
||||
|
||||
```typescript
|
||||
// repomix.config.ts
|
||||
import { defineConfig } from 'repomix';
|
||||
|
||||
// Generate timestamp-based filename
|
||||
const timestamp = new Date().toISOString().slice(0, 19).replace(/[:.]/g, '-');
|
||||
|
||||
export default defineConfig({
|
||||
output: {
|
||||
filePath: `output-${timestamp}.xml`,
|
||||
style: 'xml',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
#### JavaScript Configuration
|
||||
|
||||
JavaScript configuration files work the same as TypeScript, supporting `defineConfig` and dynamic values.
|
||||
|
||||
### Configuration Options
|
||||
|
||||
Here's an explanation of the configuration options:
|
||||
|
||||
| Option | Description | Default |
|
||||
@@ -1041,10 +1113,29 @@ The configuration file supports [JSON5](https://json5.org/) syntax, which allows
|
||||
- Unquoted property names
|
||||
- More relaxed string syntax
|
||||
|
||||
### Schema Validation
|
||||
|
||||
You can enable schema validation for your configuration file by adding the `$schema` property:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://repomix.com/schemas/latest/schema.json",
|
||||
"output": {
|
||||
"filePath": "repomix-output.xml",
|
||||
"style": "xml"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This provides auto-completion and validation in editors that support JSON schema.
|
||||
|
||||
### Example Configuration
|
||||
|
||||
Example configuration:
|
||||
|
||||
```json5
|
||||
{
|
||||
"$schema": "https://repomix.com/schemas/latest/schema.json",
|
||||
"input": {
|
||||
"maxFileSize": 50000000
|
||||
},
|
||||
|
||||
Generated
+10
-7
@@ -22,6 +22,7 @@
|
||||
"handlebars": "^4.7.8",
|
||||
"iconv-lite": "^0.7.0",
|
||||
"istextorbinary": "^9.5.0",
|
||||
"jiti": "^2.6.1",
|
||||
"jschardet": "^3.1.4",
|
||||
"json5": "^2.2.3",
|
||||
"log-update": "^7.0.1",
|
||||
@@ -1724,7 +1725,6 @@
|
||||
"integrity": "sha512-IbKooQVqUBrlzWTi79E8Fw78l8k1RNtlDDNWsFZs7XonuQSJ8oNYfEeclhprUldXISRMLzBpILuKgPlIxm+/Yw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~7.14.0"
|
||||
}
|
||||
@@ -3557,6 +3557,15 @@
|
||||
"@pkgjs/parseargs": "^0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jiti": {
|
||||
"version": "2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
|
||||
"integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"jiti": "lib/jiti-cli.mjs"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
|
||||
@@ -5450,7 +5459,6 @@
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -5523,7 +5531,6 @@
|
||||
"integrity": "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "~0.25.0",
|
||||
"get-tsconfig": "^4.7.5"
|
||||
@@ -5675,7 +5682,6 @@
|
||||
"integrity": "sha512-VbA8ScMvAISJNJVbRDTJdCwqQoAareR/wutevKanhR2/1EkoXVZVkkORaYm/tNVCjP/UDTKtcw3bAkwOUdedmA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.5.0",
|
||||
@@ -5792,7 +5798,6 @@
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -5806,7 +5811,6 @@
|
||||
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/chai": "^5.2.2",
|
||||
"@vitest/expect": "3.2.4",
|
||||
@@ -6062,7 +6066,6 @@
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
"handlebars": "^4.7.8",
|
||||
"iconv-lite": "^0.7.0",
|
||||
"istextorbinary": "^9.5.0",
|
||||
"jiti": "^2.6.1",
|
||||
"jschardet": "^3.1.4",
|
||||
"json5": "^2.2.3",
|
||||
"log-update": "^7.0.1",
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
{
|
||||
"$schema": "https://repomix.com/schemas/latest/schema.json",
|
||||
"input": {
|
||||
"maxFileSize": 50000000
|
||||
},
|
||||
"output": {
|
||||
"filePath": "repomix-output.xml",
|
||||
"style": "xml",
|
||||
"parsableStyle": false,
|
||||
"compress": false,
|
||||
"headerText": "This repository contains the source code for the Repomix tool.\nRepomix is designed to pack repository contents into a single file,\nmaking it easier for AI systems to analyze and process the codebase.\n\nKey Features:\n- Configurable ignore patterns\n- Custom header text support\n- Efficient file processing and packing\n\nPlease refer to the README.md file for more detailed information on usage and configuration.\n",
|
||||
"instructionFilePath": "repomix-instruction.md",
|
||||
"fileSummary": true,
|
||||
"directoryStructure": true,
|
||||
"files": true,
|
||||
"removeComments": false,
|
||||
"removeEmptyLines": false,
|
||||
"topFilesLength": 5,
|
||||
"showLineNumbers": false,
|
||||
"includeEmptyDirectories": true,
|
||||
"truncateBase64": true,
|
||||
"tokenCountTree": 50000,
|
||||
"git": {
|
||||
"sortByChanges": true,
|
||||
"sortByChangesMaxCommits": 100,
|
||||
"includeDiffs": true,
|
||||
"includeLogs": true,
|
||||
"includeLogsCount": 50
|
||||
}
|
||||
},
|
||||
"include": [],
|
||||
"ignore": {
|
||||
"useGitignore": true,
|
||||
"useDefaultPatterns": true,
|
||||
// ignore is specified in .repomixignore
|
||||
"customPatterns": []
|
||||
},
|
||||
"security": {
|
||||
"enableSecurityCheck": true
|
||||
},
|
||||
"tokenCount": {
|
||||
"encoding": "o200k_base"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Note: Normally you would import from 'repomix', but since this is the repomix project itself,
|
||||
// we import directly from the source index file.
|
||||
// For your projects, use: import { defineConfig } from 'repomix';
|
||||
import { defineConfig } from './src/index.js';
|
||||
|
||||
export default defineConfig({
|
||||
input: {
|
||||
maxFileSize: 50000000,
|
||||
},
|
||||
output: {
|
||||
filePath: 'repomix-output.xml',
|
||||
style: 'xml',
|
||||
parsableStyle: false,
|
||||
compress: false,
|
||||
headerText: `This repository contains the source code for the Repomix tool.
|
||||
Repomix is designed to pack repository contents into a single file,
|
||||
making it easier for AI systems to analyze and process the codebase.
|
||||
|
||||
Key Features:
|
||||
- Configurable ignore patterns
|
||||
- Custom header text support
|
||||
- Efficient file processing and packing
|
||||
|
||||
Please refer to the README.md file for more detailed information on usage and configuration.
|
||||
`,
|
||||
instructionFilePath: 'repomix-instruction.md',
|
||||
fileSummary: true,
|
||||
directoryStructure: true,
|
||||
files: true,
|
||||
removeComments: false,
|
||||
removeEmptyLines: false,
|
||||
topFilesLength: 5,
|
||||
showLineNumbers: false,
|
||||
includeEmptyDirectories: true,
|
||||
truncateBase64: true,
|
||||
// Display token count tree for files/directories with 50000+ tokens
|
||||
// Can be boolean (true/false) or number (minimum token threshold)
|
||||
tokenCountTree: 50000,
|
||||
git: {
|
||||
sortByChanges: true,
|
||||
sortByChangesMaxCommits: 100,
|
||||
includeDiffs: true,
|
||||
includeLogs: true,
|
||||
includeLogsCount: 50,
|
||||
},
|
||||
},
|
||||
include: [],
|
||||
ignore: {
|
||||
useGitignore: true,
|
||||
useDefaultPatterns: true,
|
||||
// ignore is specified in .repomixignore
|
||||
customPatterns: [],
|
||||
},
|
||||
security: {
|
||||
enableSecurityCheck: true,
|
||||
},
|
||||
tokenCount: {
|
||||
encoding: 'o200k_base',
|
||||
},
|
||||
});
|
||||
@@ -1,5 +1,7 @@
|
||||
import * as fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { pathToFileURL } from 'node:url';
|
||||
import { createJiti } from 'jiti';
|
||||
import JSON5 from 'json5';
|
||||
import pc from 'picocolors';
|
||||
import { RepomixError, rethrowValidationErrorIfZodError } from '../shared/errorHandle.js';
|
||||
@@ -15,7 +17,17 @@ import {
|
||||
} from './configSchema.js';
|
||||
import { getGlobalDirectory } from './globalDirectory.js';
|
||||
|
||||
const defaultConfigPaths = ['repomix.config.json5', 'repomix.config.jsonc', 'repomix.config.json'];
|
||||
const defaultConfigPaths = [
|
||||
'repomix.config.ts',
|
||||
'repomix.config.mts',
|
||||
'repomix.config.cts',
|
||||
'repomix.config.js',
|
||||
'repomix.config.mjs',
|
||||
'repomix.config.cjs',
|
||||
'repomix.config.json5',
|
||||
'repomix.config.jsonc',
|
||||
'repomix.config.json',
|
||||
];
|
||||
|
||||
const getGlobalConfigPaths = () => {
|
||||
const globalDir = getGlobalDirectory();
|
||||
@@ -83,15 +95,51 @@ export const loadFileConfig = async (rootDir: string, argConfigPath: string | nu
|
||||
return {};
|
||||
};
|
||||
|
||||
const getFileExtension = (filePath: string): string => {
|
||||
const match = filePath.match(/\.(ts|mts|cts|js|mjs|cjs|json5|jsonc|json)$/);
|
||||
return match ? match[1] : '';
|
||||
};
|
||||
|
||||
const loadAndValidateConfig = async (filePath: string): Promise<RepomixConfigFile> => {
|
||||
try {
|
||||
const fileContent = await fs.readFile(filePath, 'utf-8');
|
||||
const config = JSON5.parse(fileContent);
|
||||
let config: unknown;
|
||||
const ext = getFileExtension(filePath);
|
||||
|
||||
switch (ext) {
|
||||
case 'ts':
|
||||
case 'mts':
|
||||
case 'cts':
|
||||
case 'js':
|
||||
case 'mjs':
|
||||
case 'cjs': {
|
||||
// Use jiti for TypeScript and JavaScript files
|
||||
// This provides consistent behavior and avoids Node.js module cache issues
|
||||
const jiti = createJiti(import.meta.url, {
|
||||
moduleCache: false, // Disable cache to ensure fresh config loads
|
||||
interopDefault: true, // Automatically use default export
|
||||
});
|
||||
config = await jiti.import(pathToFileURL(filePath).href);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'json5':
|
||||
case 'jsonc':
|
||||
case 'json': {
|
||||
// Use JSON5 for JSON/JSON5/JSONC files
|
||||
const fileContent = await fs.readFile(filePath, 'utf-8');
|
||||
config = JSON5.parse(fileContent);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new RepomixError(`Unsupported config file format: ${filePath}`);
|
||||
}
|
||||
|
||||
return repomixConfigFileSchema.parse(config);
|
||||
} catch (error) {
|
||||
rethrowValidationErrorIfZodError(error, 'Invalid config schema');
|
||||
if (error instanceof SyntaxError) {
|
||||
throw new RepomixError(`Invalid JSON5 in config file ${filePath}: ${error.message}`);
|
||||
throw new RepomixError(`Invalid syntax in config file ${filePath}: ${error.message}`);
|
||||
}
|
||||
if (error instanceof Error) {
|
||||
throw new RepomixError(`Error loading config from ${filePath}: ${error.message}`);
|
||||
|
||||
@@ -165,3 +165,6 @@ export type RepomixConfigCli = z.infer<typeof repomixConfigCliSchema>;
|
||||
export type RepomixConfigMerged = z.infer<typeof repomixConfigMergedSchema>;
|
||||
|
||||
export const defaultConfig = repomixConfigDefaultSchema.parse({});
|
||||
|
||||
// Helper function for type-safe config definition
|
||||
export const defineConfig = (config: RepomixConfigFile): RepomixConfigFile => config;
|
||||
|
||||
@@ -30,6 +30,7 @@ export { parseFile } from './core/treeSitter/parseFile.js';
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
export { loadFileConfig, mergeConfigs } from './config/configLoad.js';
|
||||
export type { RepomixConfigFile as RepomixConfig } from './config/configSchema.js';
|
||||
export { defineConfig } from './config/configSchema.js';
|
||||
export { defaultIgnoreList } from './config/defaultIgnore.js';
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
import path from 'node:path';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { loadFileConfig } from '../../src/config/configLoad.js';
|
||||
|
||||
describe('configLoad Integration Tests', () => {
|
||||
const jsFixturesDir = path.join(process.cwd(), 'tests/fixtures/config-js');
|
||||
const tsFixturesDir = path.join(process.cwd(), 'tests/fixtures/config-ts');
|
||||
|
||||
describe('TypeScript Config Files', () => {
|
||||
test('should load .ts config with ESM default export', async () => {
|
||||
const config = await loadFileConfig(tsFixturesDir, 'repomix.config.ts');
|
||||
|
||||
expect(config).toEqual({
|
||||
output: {
|
||||
filePath: 'ts-output.xml',
|
||||
style: 'xml',
|
||||
removeComments: true,
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/node_modules/**', '**/dist/**'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should load .mts config', async () => {
|
||||
const config = await loadFileConfig(tsFixturesDir, 'repomix.config.mts');
|
||||
|
||||
expect(config).toEqual({
|
||||
output: {
|
||||
filePath: 'mts-output.xml',
|
||||
style: 'xml',
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/test/**'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should load .cts config', async () => {
|
||||
const config = await loadFileConfig(tsFixturesDir, 'repomix.config.cts');
|
||||
|
||||
expect(config).toEqual({
|
||||
output: {
|
||||
filePath: 'cts-output.xml',
|
||||
style: 'plain',
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/build/**'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should handle dynamic values in TypeScript config', async () => {
|
||||
const config = await loadFileConfig(tsFixturesDir, 'repomix-dynamic.config.ts');
|
||||
|
||||
// Vitest runs with NODE_ENV=test, so we need to include 'test' in the pattern
|
||||
expect(config.output?.filePath).toMatch(
|
||||
/^output-(test|development|production)-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}\.xml$/,
|
||||
);
|
||||
expect(config.output?.style).toBe('xml');
|
||||
expect(config.ignore?.customPatterns).toEqual(['**/node_modules/**']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('JavaScript Config Files', () => {
|
||||
test('should load .js config with ESM default export', async () => {
|
||||
const config = await loadFileConfig(jsFixturesDir, 'repomix.config.js');
|
||||
|
||||
expect(config).toEqual({
|
||||
output: {
|
||||
filePath: 'esm-output.xml',
|
||||
style: 'xml',
|
||||
removeComments: true,
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/node_modules/**', '**/dist/**'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should load .mjs config', async () => {
|
||||
const config = await loadFileConfig(jsFixturesDir, 'repomix.config.mjs');
|
||||
|
||||
expect(config).toEqual({
|
||||
output: {
|
||||
filePath: 'mjs-output.xml',
|
||||
style: 'xml',
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/test/**'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should load .cjs config with module.exports', async () => {
|
||||
const config = await loadFileConfig(jsFixturesDir, 'repomix.config.cjs');
|
||||
|
||||
expect(config).toEqual({
|
||||
output: {
|
||||
filePath: 'cjs-output.xml',
|
||||
style: 'plain',
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/build/**'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test('should handle dynamic values in JS config', async () => {
|
||||
const config = await loadFileConfig(jsFixturesDir, 'repomix-dynamic.config.js');
|
||||
|
||||
expect(config.output?.filePath).toMatch(/^output-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}\.xml$/);
|
||||
expect(config.output?.style).toBe('xml');
|
||||
expect(config.ignore?.customPatterns).toEqual(['**/node_modules/**']);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -58,9 +58,21 @@ describe('configLoad', () => {
|
||||
};
|
||||
vi.mocked(getGlobalDirectory).mockReturnValue('/global/repomix');
|
||||
vi.mocked(fs.stat)
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Local repomix.config.ts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Local repomix.config.mts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Local repomix.config.cts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Local repomix.config.js
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Local repomix.config.mjs
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Local repomix.config.cjs
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Local repomix.config.json5
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Local repomix.config.jsonc
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Local repomix.config.json
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Global repomix.config.ts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Global repomix.config.mts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Global repomix.config.cts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Global repomix.config.js
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Global repomix.config.mjs
|
||||
.mockRejectedValueOnce(new Error('File not found')) // Global repomix.config.cjs
|
||||
.mockResolvedValueOnce({ isFile: () => true } as Stats); // Global repomix.config.json5
|
||||
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockGlobalConfig));
|
||||
|
||||
@@ -87,7 +99,7 @@ describe('configLoad', () => {
|
||||
vi.mocked(fs.readFile).mockResolvedValue('invalid json');
|
||||
vi.mocked(fs.stat).mockResolvedValue({ isFile: () => true } as Stats);
|
||||
|
||||
await expect(loadFileConfig(process.cwd(), 'test-config.json')).rejects.toThrow('Invalid JSON');
|
||||
await expect(loadFileConfig(process.cwd(), 'test-config.json')).rejects.toThrow('Invalid syntax');
|
||||
});
|
||||
|
||||
test('should parse config file with comments', async () => {
|
||||
@@ -149,6 +161,12 @@ describe('configLoad', () => {
|
||||
ignore: { useDefaultPatterns: true },
|
||||
};
|
||||
vi.mocked(fs.stat)
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.ts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.mts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.cts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.js
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.mjs
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.cjs
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.json5
|
||||
.mockResolvedValueOnce({ isFile: () => true } as Stats); // repomix.config.jsonc
|
||||
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockConfig));
|
||||
@@ -163,14 +181,21 @@ describe('configLoad', () => {
|
||||
output: { filePath: 'json5-output.txt' },
|
||||
ignore: { useDefaultPatterns: true },
|
||||
};
|
||||
vi.mocked(fs.stat).mockResolvedValueOnce({ isFile: () => true } as Stats); // repomix.config.json5 exists
|
||||
vi.mocked(fs.stat)
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.ts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.mts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.cts
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.js
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.mjs
|
||||
.mockRejectedValueOnce(new Error('File not found')) // repomix.config.cjs
|
||||
.mockResolvedValueOnce({ isFile: () => true } as Stats); // repomix.config.json5 exists
|
||||
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockConfig));
|
||||
|
||||
const result = await loadFileConfig(process.cwd(), null);
|
||||
expect(result).toEqual(mockConfig);
|
||||
expect(fs.readFile).toHaveBeenCalledWith(path.resolve(process.cwd(), 'repomix.config.json5'), 'utf-8');
|
||||
// Should not check for .jsonc or .json since .json5 was found
|
||||
expect(fs.stat).toHaveBeenCalledTimes(1);
|
||||
expect(fs.stat).toHaveBeenCalledTimes(7);
|
||||
});
|
||||
|
||||
test('should throw RepomixError when specific config file does not exist', async () => {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { defineConfig } from '../../../src/index.js';
|
||||
|
||||
const timestamp = new Date().toISOString().slice(0, 19).replace(/[:.]/g, '-');
|
||||
|
||||
export default defineConfig({
|
||||
output: {
|
||||
filePath: `output-${timestamp}.xml`,
|
||||
style: 'xml',
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/node_modules/**'],
|
||||
},
|
||||
});
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
output: {
|
||||
filePath: 'cjs-output.xml',
|
||||
style: 'plain',
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/build/**'],
|
||||
},
|
||||
};
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { defineConfig } from '../../../src/index.js';
|
||||
|
||||
export default defineConfig({
|
||||
output: {
|
||||
filePath: 'esm-output.xml',
|
||||
style: 'xml',
|
||||
removeComments: true,
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/node_modules/**', '**/dist/**'],
|
||||
},
|
||||
});
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { defineConfig } from '../../../src/index.js';
|
||||
|
||||
export default defineConfig({
|
||||
output: {
|
||||
filePath: 'mjs-output.xml',
|
||||
style: 'xml',
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/test/**'],
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import { defineConfig } from '../../../src/index.js';
|
||||
|
||||
const timestamp = new Date().toISOString().slice(0, 19).replace(/[:.]/g, '-');
|
||||
const environment = process.env.NODE_ENV || 'development';
|
||||
|
||||
export default defineConfig({
|
||||
output: {
|
||||
filePath: `output-${environment}-${timestamp}.xml`,
|
||||
style: 'xml',
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/node_modules/**'],
|
||||
},
|
||||
});
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { defineConfig } from '../../../src/index.js';
|
||||
|
||||
export default defineConfig({
|
||||
output: {
|
||||
filePath: 'cts-output.xml',
|
||||
style: 'plain',
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/build/**'],
|
||||
},
|
||||
});
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { defineConfig } from '../../../src/index.js';
|
||||
|
||||
export default defineConfig({
|
||||
output: {
|
||||
filePath: 'mts-output.xml',
|
||||
style: 'xml',
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/test/**'],
|
||||
},
|
||||
});
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { defineConfig } from '../../../src/index.js';
|
||||
|
||||
export default defineConfig({
|
||||
output: {
|
||||
filePath: 'ts-output.xml',
|
||||
style: 'xml',
|
||||
removeComments: true,
|
||||
},
|
||||
ignore: {
|
||||
customPatterns: ['**/node_modules/**', '**/dist/**'],
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user