-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy patheslint.ts
120 lines (98 loc) · 3.27 KB
/
eslint.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import path from "path";
import fs from "fs-extra";
import { format } from "prettier";
import { _eslintTypes } from "~/../template/extras/config/_eslint-types.js";
import { _initialConfig } from "~/../template/extras/config/_eslint.js";
import { type Installer } from "~/installers/index.js";
export const dynamicEslintInstaller: Installer = ({ projectDir, packages }) => {
const usingDrizzle = !!packages?.drizzle?.inUse;
const configFileContents = createEslintConfig(usingDrizzle);
const configDest = path.join(projectDir, "eslint.config.js");
const configTypesFileContents = createEslintConfigTypes(usingDrizzle);
const configTypesDest = path.join(projectDir, "eslint-types.d.ts");
void formatAndWriteFile(configDest, configFileContents);
void formatAndWriteFile(configTypesDest, configTypesFileContents);
};
function createEslintConfig(usingDrizzle: boolean): string {
const rawConfig = getRawEslintConfig(usingDrizzle);
const stringConfig = JSON.stringify(rawConfig);
const configBody = stringConfig
.replace(/"%%|%%"/g, "")
// Add Next.js core web vitals rules
.replace(
'"rules":{',
'"rules":{ ...nextPlugin.configs["core-web-vitals"].rules,'
);
const imports = getImports(usingDrizzle);
// Convert config from _eslint.js to eslint.config.js
const configFileContents = [
'/// <reference types="./eslint-types.d.ts" />',
"",
...imports,
"",
"export default tseslint.config(",
configBody,
");",
].join("\n");
return configFileContents;
}
function getRawEslintConfig(usingDrizzle: boolean) {
const eslintConfig = _initialConfig;
if (usingDrizzle) {
Object.assign(eslintConfig.plugins, {
drizzle: "%%drizzlePlugin%%",
});
Object.assign(eslintConfig.rules, {
"drizzle/enforce-delete-with-where": [
"error",
{ drizzleObjectName: ["db", "ctx.db"] },
],
"drizzle/enforce-update-with-where": [
"error",
{ drizzleObjectName: ["db", "ctx.db"] },
],
});
}
return eslintConfig;
}
function getImports(usingDrizzle: boolean): string[] {
const imports = [
createImport("nextPlugin", "@next/eslint-plugin-next"),
createImport("tseslint", "typescript-eslint"),
];
if (usingDrizzle) {
imports.unshift(createImport("drizzlePlugin", "eslint-plugin-drizzle"));
}
return imports;
}
function createImport(defaultImportName: string, packageName: string): string {
return `import ${defaultImportName} from "${packageName}";`;
}
function createEslintConfigTypes(usingDrizzle: boolean): string {
let eslintConfigTypes = _eslintTypes;
if (usingDrizzle) {
eslintConfigTypes = eslintConfigTypes.concat(
`\n
declare module "eslint-plugin-drizzle" {
import type { Rule } from "eslint";
export const rules: Record<string, Rule.RuleModule>;
}`
);
}
return eslintConfigTypes;
}
async function formatAndWriteFile(
filePath: string,
fileContents: string
): Promise<void> {
try {
const formattedFileContents = await format(fileContents, {
parser: "typescript",
});
await fs.writeFile(filePath, formattedFileContents, "utf-8");
} catch (e) {
console.error("Unable to format ESLint config file.", e);
// Write to fs anyway.
fs.writeFileSync(filePath, fileContents, "utf-8");
}
}