mirror of
https://github.com/affaan-m/ECC.git
synced 2026-09-29 04:55:12 +02:00
fix(install): accept UTF-8 BOM in install configs
This commit is contained in:
@@ -10,7 +10,9 @@ let cachedValidator = null;
|
||||
|
||||
function readJson(filePath, label) {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
||||
// Windows PowerShell 5.1 writes a BOM with Set-Content -Encoding UTF8.
|
||||
const content = fs.readFileSync(filePath, 'utf8').replace(/^\uFEFF/, '');
|
||||
return JSON.parse(content);
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid JSON in ${label}: ${error.message}`);
|
||||
}
|
||||
|
||||
@@ -106,6 +106,63 @@ function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('loads a UTF-8 BOM config without changing its values or source bytes', () => {
|
||||
const cwd = createTempDir('install-config-');
|
||||
|
||||
try {
|
||||
const configPath = path.join(cwd, 'ecc-install.json');
|
||||
const value = { version: 1, target: 'cursor', modules: ['rules-core'] };
|
||||
writeJson(configPath, value);
|
||||
const expected = loadInstallConfig(configPath);
|
||||
const content = `\uFEFF${JSON.stringify(value, null, 2).replace(/\n/g, '\r\n')}\r\n`;
|
||||
fs.writeFileSync(configPath, content, 'utf8');
|
||||
|
||||
assert.deepStrictEqual(loadInstallConfig(configPath), expected);
|
||||
assert.strictEqual(fs.readFileSync(configPath, 'utf8'), content);
|
||||
} finally {
|
||||
cleanup(cwd);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('preserves BOM characters inside JSON string values', () => {
|
||||
const cwd = createTempDir('install-config-');
|
||||
|
||||
try {
|
||||
const configPath = path.join(cwd, 'ecc-install.json');
|
||||
const options = { note: 'custom\uFEFFvalue' };
|
||||
fs.writeFileSync(configPath, `\uFEFF${JSON.stringify({ version: 1, options })}`, 'utf8');
|
||||
assert.deepStrictEqual(loadInstallConfig(configPath).options, options);
|
||||
} finally {
|
||||
cleanup(cwd);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('still rejects malformed JSON and misplaced BOM characters', () => {
|
||||
const cwd = createTempDir('install-config-');
|
||||
|
||||
try {
|
||||
const configPath = path.join(cwd, 'ecc-install.json');
|
||||
for (const content of ['\uFEFF{', ' \uFEFF{"version":1}', '\uFEFF\uFEFF{"version":1}']) {
|
||||
fs.writeFileSync(configPath, content, 'utf8');
|
||||
assert.throws(() => loadInstallConfig(configPath), /Invalid JSON in ecc-install.json/);
|
||||
}
|
||||
} finally {
|
||||
cleanup(cwd);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('validates the schema after reading a UTF-8 BOM config', () => {
|
||||
const cwd = createTempDir('install-config-');
|
||||
|
||||
try {
|
||||
const configPath = path.join(cwd, 'ecc-install.json');
|
||||
fs.writeFileSync(configPath, '\uFEFF{"version":2,"target":"ghost-target"}', 'utf8');
|
||||
assert.throws(() => loadInstallConfig(configPath), /Invalid install config/);
|
||||
} finally {
|
||||
cleanup(cwd);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
if (test('rejects invalid config schema values', () => {
|
||||
const cwd = createTempDir('install-config-');
|
||||
|
||||
|
||||
@@ -1487,6 +1487,29 @@ function runTests() {
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
|
||||
for (const explicitConfig of [true, false]) {
|
||||
if (test(`installs from a UTF-8 BOM config (${explicitConfig ? '--config' : 'auto-detected'})`, () => {
|
||||
const homeDir = createTempDir('install-apply-bom-home-');
|
||||
const projectDir = createTempDir('install-apply-bom-project-');
|
||||
const configPath = path.join(projectDir, 'ecc-install.json');
|
||||
const content = '\uFEFF{\r\n "version": 1,\r\n "target": "cursor",\r\n "modules": ["rules-core"]\r\n}\r\n';
|
||||
|
||||
try {
|
||||
fs.writeFileSync(configPath, content, 'utf8');
|
||||
const args = explicitConfig ? ['--config', configPath] : [];
|
||||
const result = run(args, { cwd: projectDir, homeDir });
|
||||
assert.strictEqual(result.code, 0, result.stderr);
|
||||
assert.ok(fs.existsSync(path.join(projectDir, '.cursor', 'rules', 'common-coding-style.mdc')));
|
||||
const state = readJson(path.join(projectDir, '.cursor', 'ecc-install-state.json'));
|
||||
assert.deepStrictEqual(state.request.modules, ['rules-core']);
|
||||
assert.strictEqual(fs.readFileSync(configPath, 'utf8'), content);
|
||||
} finally {
|
||||
cleanup(homeDir);
|
||||
cleanup(projectDir);
|
||||
}
|
||||
})) passed++; else failed++;
|
||||
}
|
||||
|
||||
if (test('preserves legacy language installs when a project config is present', () => {
|
||||
const homeDir = createTempDir('install-apply-home-');
|
||||
const projectDir = createTempDir('install-apply-project-');
|
||||
|
||||
Reference in New Issue
Block a user