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
4 changes: 2 additions & 2 deletions packages/wbfy/src/generators/oxfmtConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ function getConfigContent(config: PackageConfig): string {
`// oxlint-disable unicorn/prefer-module -- Oxfmt config files are only auto-discovered as .ts, and CommonJS avoids Node typeless ESM warnings.
const oxfmtConfig = require('@willbooster/oxfmt-config');

const config = oxfmtConfig.default ?? oxfmtConfig;`
const oxfmtResolvedConfig = oxfmtConfig.default ?? oxfmtConfig;`
)}

${managedConfigBlocks.getBlock('export', 'module.exports = config;')}
${managedConfigBlocks.getBlock('export', 'module.exports = oxfmtResolvedConfig;')}
`;
}

Expand Down
24 changes: 15 additions & 9 deletions packages/wbfy/src/generators/oxlintConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ export async function generateOxlintConfig(config: PackageConfig, _rootConfig: P
const desiredContent =
shouldPreservePublishedLinterConfig && existingContent
? existingContent
: managedConfigBlocks.getConfigContent({
desiredContent: getConfigContent(config),
existingContent,
filePath,
});
: replaceLegacyConfigReferences(
managedConfigBlocks.getConfigContent({
desiredContent: getConfigContent(config),
existingContent,
filePath,
})
);

const promises: Promise<void>[] = [];
if (!shouldPreservePublishedLinterConfig) {
Expand All @@ -57,6 +59,10 @@ export async function generateOxlintConfig(config: PackageConfig, _rootConfig: P
});
}

function replaceLegacyConfigReferences(content: string): string {
return content.replaceAll('config.', 'oxlintResolvedConfig.');
}

function getConfigContent(config: PackageConfig): string {
// Do not collapse this to a static import for every package. CommonJS packages
// type-check auto-discovered oxlint.config.ts as CommonJS, so importing the ESM
Expand All @@ -68,15 +74,15 @@ function getConfigContent(config: PackageConfig): string {
`// oxlint-disable unicorn/prefer-module -- Oxlint only auto-discovers .ts config files, and CommonJS avoids Node typeless ESM warnings.
const oxlintBaseConfig = require('@willbooster/oxlint-config');

const config = oxlintBaseConfig.default ?? oxlintBaseConfig;`
const oxlintResolvedConfig = oxlintBaseConfig.default ?? oxlintBaseConfig;`
)}

${managedConfigBlocks.getBlock('export', 'module.exports = config;')}
${managedConfigBlocks.getBlock('export', 'module.exports = oxlintResolvedConfig;')}
`;
}

return `${managedConfigBlocks.getBlock('base', "import config from '@willbooster/oxlint-config';")}
return `${managedConfigBlocks.getBlock('base', "import oxlintResolvedConfig from '@willbooster/oxlint-config';")}

${managedConfigBlocks.getBlock('export', 'export default config;')}
${managedConfigBlocks.getBlock('export', 'export default oxlintResolvedConfig;')}
`;
}
11 changes: 11 additions & 0 deletions packages/wbfy/src/generators/tsconfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,24 @@ async function cleanupLegacyTsconfigModuleSettings(config: PackageConfig): Promi
const settings = JSON.parse(await fs.promises.readFile(filePath, 'utf8')) as TsConfigJson;
normalizeNextTsconfigModuleSettings(settings.compilerOptions);
normalizeNextTsconfigPathAliases(settings.compilerOptions);
addScriptsIncludeForFrameworkProject(settings);
await promisePool.run(() => fsUtil.generateFile(filePath, JSON.stringify(settings, undefined, 2)));
} catch {
// Next/Blitz own their tsconfig shape, but TypeScript 6 no longer accepts
// node10 resolver spellings that older projects commonly inherited.
}
}

function addScriptsIncludeForFrameworkProject(settings: TsConfigJson): void {
// Omitting include lets framework tsconfigs keep TypeScript's default
// "all TS/TSX files" behavior, which already covers scripts.
if (!settings.include) return;
if (settings.include.includes('scripts/**/*')) return;

settings.include.push('scripts/**/*');
settings.include.sort();
}

function normalizeNextTsconfigModuleSettings(compilerOptions: TsConfigJson.CompilerOptions | undefined): void {
if (!compilerOptions) return;
if (
Expand Down
12 changes: 6 additions & 6 deletions packages/wbfy/test/oxlintConfigGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export default config;
expect(content).toContain('// wbfy:start oxlint-base');
expect(content).toContain('// wbfy:start oxlint-export');
expect(content).toContain("const oxlintBaseConfig = require('@willbooster/oxlint-config');");
expect(content).toContain('const config = oxlintBaseConfig.default ?? oxlintBaseConfig;');
expect(content).toContain('module.exports = config;');
expect(content).toContain('const oxlintResolvedConfig = oxlintBaseConfig.default ?? oxlintBaseConfig;');
expect(content).toContain('module.exports = oxlintResolvedConfig;');
expect(content).not.toContain("config.ignorePatterns?.push('generated/**');");
});

Expand All @@ -61,8 +61,8 @@ module.exports = staleConfig;

const content = await readOxlintConfig(dirPath);
expect(content).toContain("const oxlintBaseConfig = require('@willbooster/oxlint-config');");
expect(content).toContain("config.ignorePatterns?.push('generated/**');");
expect(content).toContain('module.exports = config;');
expect(content).toContain("oxlintResolvedConfig.ignorePatterns?.push('generated/**');");
expect(content).toContain('module.exports = oxlintResolvedConfig;');
expect(content).not.toContain('staleConfig');
});

Expand All @@ -73,8 +73,8 @@ test('generates esm oxlint config for esm packages', async () => {
await promisePool.promiseAll();

const content = await readOxlintConfig(dirPath);
expect(content).toContain("import config from '@willbooster/oxlint-config';");
expect(content).toContain('export default config;');
expect(content).toContain("import oxlintResolvedConfig from '@willbooster/oxlint-config';");
expect(content).toContain('export default oxlintResolvedConfig;');
});

function createTempDir(): string {
Expand Down
54 changes: 54 additions & 0 deletions packages/wbfy/test/tsconfigGenerator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,60 @@ test('normalizes Next.js aliases for TypeScript 6 linting', async () => {
expect(tsconfig.compilerOptions.paths).toEqual({ '@/*': ['./src/*'] });
});

test('adds scripts include for Next.js projects', async () => {
const dirPath = createTempDir();
await fs.promises.writeFile(
path.join(dirPath, 'tsconfig.json'),
JSON.stringify({
compilerOptions: {
moduleResolution: 'bundler',
},
include: ['src/**/*'],
})
);

await generateTsconfig(
createConfig({
dirPath,
depending: {
...createConfig().depending,
next: true,
},
})
);
await promisePool.promiseAll();

const tsconfig = await readTsconfig(dirPath);
expect(tsconfig.include).toEqual(['scripts/**/*', 'src/**/*']);
});

test('does not duplicate scripts include for Next.js projects', async () => {
const dirPath = createTempDir();
await fs.promises.writeFile(
path.join(dirPath, 'tsconfig.json'),
JSON.stringify({
compilerOptions: {
moduleResolution: 'bundler',
},
include: ['scripts/**/*', 'src/**/*'],
})
);

await generateTsconfig(
createConfig({
dirPath,
depending: {
...createConfig().depending,
next: true,
},
})
);
await promisePool.promiseAll();

const tsconfig = await readTsconfig(dirPath);
expect(tsconfig.include).toEqual(['scripts/**/*', 'src/**/*']);
});

function createTempDir(): string {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'wbfy-tsconfig-'));
tempDirs.push(tempDir);
Expand Down
Loading