@oxiul/configs 0.0.0-stage → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -2
- package/dist/common-B9SE4GL9.mjs +11 -0
- package/dist/hook/install.d.mts +1 -0
- package/dist/hook/install.mjs +37 -0
- package/dist/hook/pre-commit.d.mts +1 -0
- package/dist/hook/pre-commit.mjs +57 -0
- package/dist/index.d.mts +152 -0
- package/dist/index.mjs +472 -0
- package/dist/schema-DM8wm8HH.mjs +5 -0
- package/package.json +66 -5
- package/scripts/postinstall.mjs +39 -0
package/README.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Configs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Lint config
|
|
4
|
+
|
|
5
|
+
A shared config for oxlint
|
|
6
|
+
|
|
7
|
+
## Format config
|
|
8
|
+
|
|
9
|
+
A shared config for oxfmt
|
|
10
|
+
|
|
11
|
+
## Development
|
|
12
|
+
|
|
13
|
+
### Prerequisites
|
|
14
|
+
|
|
15
|
+
- Node.js (from `engines.node` field in `package.json`)
|
|
16
|
+
- Bun (from `packageManager` field in `package.json`)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/common.ts
|
|
2
|
+
const baseIgnorePatterns = [
|
|
3
|
+
".history/",
|
|
4
|
+
"bun.lock",
|
|
5
|
+
"**/*.gen.ts"
|
|
6
|
+
];
|
|
7
|
+
const arraify = (input) => input === void 0 ? [] : Array.isArray(input) ? input : [input];
|
|
8
|
+
const moduleName = "oxiul";
|
|
9
|
+
const packageName = "@oxiul/configs";
|
|
10
|
+
//#endregion
|
|
11
|
+
export { packageName as i, baseIgnorePatterns as n, moduleName as r, arraify as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { i as packageName } from "../common-B9SE4GL9.mjs";
|
|
2
|
+
import { exec } from "node:child_process";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
//#region src/hook/install.ts
|
|
7
|
+
const promisifiedExec = promisify(exec);
|
|
8
|
+
const { stdout: rawGitRepositoryRoot } = await promisifiedExec("git rev-parse --show-toplevel");
|
|
9
|
+
const gitRepositoryRoot = rawGitRepositoryRoot.trim();
|
|
10
|
+
const { stdout: rawHooksDirectory } = await promisifiedExec("git rev-parse --path-format=absolute --git-path hooks");
|
|
11
|
+
const hooksDirectory = rawHooksDirectory.trim();
|
|
12
|
+
const packageJson = await fs.readFile(path.join(gitRepositoryRoot, "package.json"), "utf8");
|
|
13
|
+
const { name } = JSON.parse(packageJson);
|
|
14
|
+
const HOOK_CONTENT = ["#!/bin/bash", `node ${name === "@oxiul/configs" ? "." : `./node_modules/${packageName}`}/dist/hook/pre-commit.mjs`].join("\n");
|
|
15
|
+
await fs.mkdir(hooksDirectory, { recursive: true });
|
|
16
|
+
const preCommitPath = path.join(hooksDirectory, "pre-commit");
|
|
17
|
+
let oldHook = "";
|
|
18
|
+
if (await fs.stat(preCommitPath).then(() => true).catch(() => false)) {
|
|
19
|
+
if ((await fs.lstat(preCommitPath)).isSymbolicLink()) {
|
|
20
|
+
console.log("Detected an existing git pre-commit hook");
|
|
21
|
+
await fs.unlink(preCommitPath);
|
|
22
|
+
} else {
|
|
23
|
+
oldHook = await fs.readFile(preCommitPath, "utf8");
|
|
24
|
+
if (oldHook !== HOOK_CONTENT) {
|
|
25
|
+
console.log(`Found hooks path: "${hooksDirectory}"`);
|
|
26
|
+
console.log("Detected an existing git pre-commit hook");
|
|
27
|
+
await fs.writeFile(`${preCommitPath}.old`, oldHook);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (oldHook !== HOOK_CONTENT) {
|
|
32
|
+
console.log(`Found hooks path: "${hooksDirectory}"`);
|
|
33
|
+
await fs.writeFile(preCommitPath, HOOK_CONTENT, { mode: 493 });
|
|
34
|
+
console.log("Hook saved");
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { r as moduleName } from "../common-B9SE4GL9.mjs";
|
|
2
|
+
import { t as configSchema } from "../schema-DM8wm8HH.mjs";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
import { cosmiconfig } from "cosmiconfig";
|
|
6
|
+
import { Listr } from "listr2";
|
|
7
|
+
//#region src/hook/pre-commit.ts
|
|
8
|
+
const failedOutputs = /* @__PURE__ */ new Map();
|
|
9
|
+
const run = (command, task) => new Promise((resolve, reject) => {
|
|
10
|
+
const child = spawn(command, {
|
|
11
|
+
env: {
|
|
12
|
+
...process.env,
|
|
13
|
+
FORCE_COLOR: "1"
|
|
14
|
+
},
|
|
15
|
+
shell: true,
|
|
16
|
+
stdio: [
|
|
17
|
+
"ignore",
|
|
18
|
+
"pipe",
|
|
19
|
+
"pipe"
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
const window = task.stdout();
|
|
23
|
+
let output = "";
|
|
24
|
+
const onData = (chunk) => {
|
|
25
|
+
output += chunk;
|
|
26
|
+
window.write(chunk);
|
|
27
|
+
};
|
|
28
|
+
child.stdout.on("data", onData);
|
|
29
|
+
child.stderr.on("data", onData);
|
|
30
|
+
child.on("error", reject);
|
|
31
|
+
child.on("close", (code, signal) => {
|
|
32
|
+
if (code === 0) return resolve();
|
|
33
|
+
failedOutputs.set(command, output);
|
|
34
|
+
reject(/* @__PURE__ */ new Error(signal ? `killed by ${signal}` : `exited with code ${code}`));
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
const rawConfig = await cosmiconfig(moduleName).search();
|
|
38
|
+
const parsedConfig = z.safeParse(configSchema, rawConfig?.config);
|
|
39
|
+
if (!parsedConfig.success) throw new Error(`Validation error: ${parsedConfig.error.message}`);
|
|
40
|
+
try {
|
|
41
|
+
const config = parsedConfig.data;
|
|
42
|
+
if (config.preCommitCommands && config.preCommitCommands.length !== 0) await new Listr(config.preCommitCommands.map((command) => ({
|
|
43
|
+
rendererOptions: {
|
|
44
|
+
outputBar: 5,
|
|
45
|
+
persistentOutput: false
|
|
46
|
+
},
|
|
47
|
+
task: (_ctx, task) => run(command, task),
|
|
48
|
+
title: command
|
|
49
|
+
})), { concurrent: false }).run();
|
|
50
|
+
else console.log(`No commands in pre-commit list found`);
|
|
51
|
+
} catch {
|
|
52
|
+
for (const [command, output] of failedOutputs) console.error(`\n✖ Output of "${command}"\n${output}`);
|
|
53
|
+
console.error(`${failedOutputs.size} tasks failed: ${[...failedOutputs.keys()].join(", ")}`);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
//#endregion
|
|
57
|
+
export {};
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { OxlintConfig } from "oxlint";
|
|
3
|
+
import { OxfmtConfig } from "oxfmt";
|
|
4
|
+
import { KnipConfig } from "knip";
|
|
5
|
+
//#region src/oxlint.d.ts
|
|
6
|
+
export declare const disabledRules: OxlintConfig["rules"];
|
|
7
|
+
export declare const overridenRules: OxlintConfig["rules"];
|
|
8
|
+
type MergableConfig$1 = Omit<OxlintConfig, "plugins"> & {
|
|
9
|
+
plugins?: Partial<Record<NonNullable<OxlintConfig["plugins"]>[number], boolean>>;
|
|
10
|
+
};
|
|
11
|
+
type TailwindConfig = {
|
|
12
|
+
entryPoint: string;
|
|
13
|
+
};
|
|
14
|
+
type VitestConfig = {
|
|
15
|
+
files?: string[];
|
|
16
|
+
};
|
|
17
|
+
type TanstackRouterConfig = {
|
|
18
|
+
routes: string[];
|
|
19
|
+
};
|
|
20
|
+
type PackageJsonConfig = boolean;
|
|
21
|
+
type PlaywrightConfig = {
|
|
22
|
+
files: string[];
|
|
23
|
+
assertFunctionNames?: string[];
|
|
24
|
+
};
|
|
25
|
+
type ServerSideConfig = {
|
|
26
|
+
files: string[];
|
|
27
|
+
allowConsole?: string[];
|
|
28
|
+
allowProcess?: string[];
|
|
29
|
+
};
|
|
30
|
+
type RestrictedSyntaxRule = {
|
|
31
|
+
selector: string;
|
|
32
|
+
message: string;
|
|
33
|
+
};
|
|
34
|
+
type RestrictedSyntaxOverride = {
|
|
35
|
+
files: string[];
|
|
36
|
+
rules: RestrictedSyntaxRule[];
|
|
37
|
+
};
|
|
38
|
+
type RestrictedSyntaxConfig = {
|
|
39
|
+
banBarrelImport?: boolean;
|
|
40
|
+
banReactMemo?: boolean;
|
|
41
|
+
overrides?: RestrictedSyntaxOverride[];
|
|
42
|
+
rulesOverrides?: RestrictedSyntaxRule[];
|
|
43
|
+
previousRules?: RestrictedSyntaxRule[];
|
|
44
|
+
previousOverrides?: RestrictedSyntaxOverride[];
|
|
45
|
+
};
|
|
46
|
+
type RestrictedConfig = {
|
|
47
|
+
globals?: {
|
|
48
|
+
name: string;
|
|
49
|
+
message: string;
|
|
50
|
+
}[];
|
|
51
|
+
properties?: {
|
|
52
|
+
object: string;
|
|
53
|
+
property: string;
|
|
54
|
+
message: string;
|
|
55
|
+
}[];
|
|
56
|
+
syntaxOverrides?: RestrictedSyntaxConfig["overrides"];
|
|
57
|
+
syntaxRulesOverrides?: RestrictedSyntaxConfig["rulesOverrides"];
|
|
58
|
+
};
|
|
59
|
+
type ReactConfig = {
|
|
60
|
+
allowedStrings?: string[];
|
|
61
|
+
additionalHooks?: string[];
|
|
62
|
+
banMemo?: boolean;
|
|
63
|
+
};
|
|
64
|
+
type I18nConfig = {
|
|
65
|
+
ignore?: string[] | true;
|
|
66
|
+
};
|
|
67
|
+
type ImportConfig = {
|
|
68
|
+
allowDefault?: string[];
|
|
69
|
+
banBarrel?: boolean;
|
|
70
|
+
};
|
|
71
|
+
type ConfigOptions$2 = {
|
|
72
|
+
jsPlugins?: Exclude<OxlintConfig["jsPlugins"], null>;
|
|
73
|
+
plugins?: MergableConfig$1["plugins"];
|
|
74
|
+
tailwind?: TailwindConfig;
|
|
75
|
+
vitest?: VitestConfig;
|
|
76
|
+
tanstackRouter?: TanstackRouterConfig;
|
|
77
|
+
packageJson?: PackageJsonConfig;
|
|
78
|
+
playwright?: PlaywrightConfig;
|
|
79
|
+
serverSide?: ServerSideConfig;
|
|
80
|
+
restricted?: RestrictedConfig;
|
|
81
|
+
react?: ReactConfig;
|
|
82
|
+
i18n?: I18nConfig;
|
|
83
|
+
import?: ImportConfig;
|
|
84
|
+
} & Pick<OxlintConfig, "env" | "rules" | "options" | "ignorePatterns" | "categories" | "settings" | "overrides" | "globals"> & ReactConfig;
|
|
85
|
+
declare const getConfig$2: ({ tailwind, tanstackRouter, vitest, packageJson, playwright, serverSide, restricted, react, i18n, import: importOptions, ...config }?: ConfigOptions$2) => Promise<OxlintConfig>;
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/oxfmt.d.ts
|
|
88
|
+
type ConfigOptions$1 = OxfmtConfig & {
|
|
89
|
+
tailwind?: {
|
|
90
|
+
stylesheet: string;
|
|
91
|
+
functions?: string[];
|
|
92
|
+
};
|
|
93
|
+
imports?: Exclude<OxfmtConfig["sortImports"], boolean>;
|
|
94
|
+
};
|
|
95
|
+
declare const getConfig: ({ ignorePatterns, tailwind, imports, sortImports, ...rest }?: ConfigOptions$1) => Promise<{
|
|
96
|
+
readonly arrowParens?: import("oxfmt").ArrowParensConfig;
|
|
97
|
+
readonly associations?: import("oxfmt").OxfmtAssociationConfig[];
|
|
98
|
+
astro: import("oxfmt").AstroUserConfig;
|
|
99
|
+
readonly bracketSameLine?: boolean;
|
|
100
|
+
readonly bracketSpacing?: boolean;
|
|
101
|
+
readonly embeddedLanguageFormatting?: import("oxfmt").EmbeddedLanguageFormattingConfig;
|
|
102
|
+
readonly endOfLine?: import("oxfmt").EndOfLineConfig;
|
|
103
|
+
readonly experimentalOperatorPosition?: import("oxfmt").OperatorPositionConfig;
|
|
104
|
+
readonly htmlWhitespaceSensitivity?: import("oxfmt").HtmlWhitespaceSensitivityConfig;
|
|
105
|
+
readonly insertFinalNewline?: boolean;
|
|
106
|
+
readonly jsdoc?: import("oxfmt").JsdocUserConfig;
|
|
107
|
+
readonly jsxSingleQuote?: boolean;
|
|
108
|
+
readonly objectWrap?: import("oxfmt").ObjectWrapConfig;
|
|
109
|
+
readonly overrides?: import("oxfmt").OxfmtOverrideConfig[];
|
|
110
|
+
printWidth: number;
|
|
111
|
+
readonly proseWrap?: import("oxfmt").ProseWrapConfig;
|
|
112
|
+
readonly quoteProps?: import("oxfmt").QuotePropsConfig;
|
|
113
|
+
readonly semi?: boolean;
|
|
114
|
+
readonly singleAttributePerLine?: boolean;
|
|
115
|
+
readonly singleQuote?: boolean;
|
|
116
|
+
sortPackageJson: boolean | import("oxfmt").SortPackageJsonConfig | {
|
|
117
|
+
readonly sortScripts: true;
|
|
118
|
+
};
|
|
119
|
+
sortTailwindcss: import("oxfmt").SortTailwindcssUserConfig;
|
|
120
|
+
readonly svelte?: import("oxfmt").SvelteUserConfig;
|
|
121
|
+
readonly tabWidth?: number;
|
|
122
|
+
readonly trailingComma?: import("oxfmt").TrailingCommaConfig;
|
|
123
|
+
useTabs: boolean;
|
|
124
|
+
readonly vueIndentScriptAndStyle?: boolean;
|
|
125
|
+
readonly ignorePatterns: string[];
|
|
126
|
+
readonly sortImports: import("oxfmt").SortImportsUserConfig;
|
|
127
|
+
}>;
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/knip.d.ts
|
|
130
|
+
type KnipConfig$1 = Exclude<KnipConfig, Function>;
|
|
131
|
+
type MergableConfig = Omit<KnipConfig$1, "include"> & {
|
|
132
|
+
include?: Partial<Record<NonNullable<KnipConfig$1["include"]>[number], boolean>>;
|
|
133
|
+
};
|
|
134
|
+
type BaseOptions = {
|
|
135
|
+
vitest?: boolean;
|
|
136
|
+
reactNative?: boolean;
|
|
137
|
+
opencode?: boolean;
|
|
138
|
+
eslint?: boolean;
|
|
139
|
+
workspaces?: boolean;
|
|
140
|
+
};
|
|
141
|
+
type ConfigOptions = {
|
|
142
|
+
options?: BaseOptions;
|
|
143
|
+
} & MergableConfig;
|
|
144
|
+
declare const getConfig$1: ({ options, ...overrides }?: ConfigOptions) => Promise<KnipConfig$1>;
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/config/schema.d.ts
|
|
147
|
+
export declare const configSchema: z.ZodObject<{
|
|
148
|
+
preCommitCommands: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
149
|
+
}, z.core.$strip>;
|
|
150
|
+
type Config = z.infer<typeof configSchema>;
|
|
151
|
+
//#endregion
|
|
152
|
+
export { type Config, getConfig as getFormatConfig, getConfig$1 as getKnipConfig, getConfig$2 as getLintConfig };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
import { n as baseIgnorePatterns, t as arraify } from "./common-B9SE4GL9.mjs";
|
|
2
|
+
import { t as configSchema } from "./schema-DM8wm8HH.mjs";
|
|
3
|
+
import { isNonNullish, mapValues, omitBy } from "remeda";
|
|
4
|
+
//#region src/oxlint.ts
|
|
5
|
+
const disabledRules = {
|
|
6
|
+
"eslint/capitalized-comments": "off",
|
|
7
|
+
"eslint/default-case": "off",
|
|
8
|
+
"eslint/id-length": "off",
|
|
9
|
+
"eslint/max-lines": "off",
|
|
10
|
+
"eslint/max-lines-per-function": "off",
|
|
11
|
+
"eslint/max-params": "off",
|
|
12
|
+
"eslint/max-statements": "off",
|
|
13
|
+
"eslint/no-await-in-loop": "off",
|
|
14
|
+
"eslint/no-continue": "off",
|
|
15
|
+
"eslint/no-duplicate-imports": "off",
|
|
16
|
+
"eslint/no-inline-comments": "off",
|
|
17
|
+
"eslint/no-nested-ternary": "off",
|
|
18
|
+
"eslint/no-ternary": "off",
|
|
19
|
+
"eslint/no-undefined": "off",
|
|
20
|
+
"eslint/no-warning-comments": "off",
|
|
21
|
+
"eslint/one-var": "off",
|
|
22
|
+
"eslint/require-await": "off",
|
|
23
|
+
"import/exports-last": "off",
|
|
24
|
+
"import/group-exports": "off",
|
|
25
|
+
"import/max-dependencies": "off",
|
|
26
|
+
"import/no-named-export": "off",
|
|
27
|
+
"import/no-namespace": "off",
|
|
28
|
+
"import/no-unassigned-import": "off",
|
|
29
|
+
"import/prefer-default-export": "off",
|
|
30
|
+
"import/unambiguous": "off",
|
|
31
|
+
"oxc/no-accumulating-spread": "off",
|
|
32
|
+
"oxc/no-async-await": "off",
|
|
33
|
+
"oxc/no-map-spread": "off",
|
|
34
|
+
"oxc/no-optional-chaining": "off",
|
|
35
|
+
"oxc/no-rest-spread-properties": "off",
|
|
36
|
+
"promise/avoid-new": "off",
|
|
37
|
+
"promise/prefer-await-to-callbacks": "off",
|
|
38
|
+
"promise/prefer-await-to-then": "off",
|
|
39
|
+
"react-perf/jsx-no-jsx-as-prop": "off",
|
|
40
|
+
"react-perf/jsx-no-new-array-as-prop": "off",
|
|
41
|
+
"react-perf/jsx-no-new-function-as-prop": "off",
|
|
42
|
+
"react-perf/jsx-no-new-object-as-prop": "off",
|
|
43
|
+
"react/display-name": "off",
|
|
44
|
+
"react/forbid-component-props": "off",
|
|
45
|
+
"react/jsx-filename-extension": "off",
|
|
46
|
+
"react/jsx-handler-names": "off",
|
|
47
|
+
"react/jsx-max-depth": "off",
|
|
48
|
+
"react/jsx-props-no-spreading": "off",
|
|
49
|
+
"react/no-multi-comp": "off",
|
|
50
|
+
"react/only-export-components": "off",
|
|
51
|
+
"react/react-in-jsx-scope": "off",
|
|
52
|
+
"react/rule-suppression": "off",
|
|
53
|
+
"typescript/consistent-return": "off",
|
|
54
|
+
"typescript/explicit-function-return-type": "off",
|
|
55
|
+
"typescript/explicit-module-boundary-types": "off",
|
|
56
|
+
"typescript/no-confusing-void-expression": "off",
|
|
57
|
+
"typescript/no-dynamic-delete": "off",
|
|
58
|
+
"typescript/no-invalid-void-type": "off",
|
|
59
|
+
"typescript/no-unnecessary-type-parameters": "off",
|
|
60
|
+
"typescript/no-unsafe-type-assertion": "off",
|
|
61
|
+
"typescript/prefer-nullish-coalescing": "off",
|
|
62
|
+
"typescript/prefer-readonly-parameter-types": "off",
|
|
63
|
+
"typescript/promise-function-async": "off",
|
|
64
|
+
"unicorn/no-array-callback-reference": "off",
|
|
65
|
+
"unicorn/no-array-reduce": "off",
|
|
66
|
+
"unicorn/no-nested-ternary": "off",
|
|
67
|
+
"unicorn/no-null": "off",
|
|
68
|
+
"unicorn/no-useless-undefined": "off",
|
|
69
|
+
"unicorn/number-literal-case": "off",
|
|
70
|
+
"unicorn/prefer-global-this": "off",
|
|
71
|
+
"unicorn/prefer-spread": "off",
|
|
72
|
+
"vitest/max-expects": "off",
|
|
73
|
+
"vitest/no-conditional-in-test": "off",
|
|
74
|
+
"vitest/no-hooks": "off",
|
|
75
|
+
"vitest/no-importing-vitest-globals": "off",
|
|
76
|
+
"vitest/no-standalone-expect": "off",
|
|
77
|
+
"vitest/prefer-called-once": "off",
|
|
78
|
+
"vitest/prefer-expect-assertions": "off",
|
|
79
|
+
"vitest/prefer-importing-vitest-globals": "off",
|
|
80
|
+
"vitest/prefer-lowercase-title": "off",
|
|
81
|
+
"vitest/prefer-to-be": "off",
|
|
82
|
+
"vitest/prefer-to-be-falsy": "off",
|
|
83
|
+
"vitest/prefer-to-be-truthy": "off",
|
|
84
|
+
"vitest/require-hook": "off",
|
|
85
|
+
"vitest/require-test-timeout": "off"
|
|
86
|
+
};
|
|
87
|
+
const disabledTailwindRules = {
|
|
88
|
+
"better-tailwindcss/enforce-consistent-class-order": "off",
|
|
89
|
+
"better-tailwindcss/enforce-consistent-line-wrapping": "off"
|
|
90
|
+
};
|
|
91
|
+
const overridenRules = {
|
|
92
|
+
"eslint/no-magic-numbers": ["error", { ignore: [
|
|
93
|
+
0,
|
|
94
|
+
1,
|
|
95
|
+
-1
|
|
96
|
+
] }],
|
|
97
|
+
"eslint/no-void": ["error", { allowAsStatement: true }],
|
|
98
|
+
"eslint/sort-imports": ["error", { ignoreDeclarationSort: true }],
|
|
99
|
+
"react/function-component-definition": ["error", {
|
|
100
|
+
namedComponents: "arrow-function",
|
|
101
|
+
unnamedComponents: "arrow-function"
|
|
102
|
+
}],
|
|
103
|
+
"react/jsx-no-useless-fragment": ["error", { allowExpressions: true }],
|
|
104
|
+
"typescript/consistent-type-definitions": ["error", "type"],
|
|
105
|
+
"typescript/no-misused-promises": ["error", { checksVoidReturn: {
|
|
106
|
+
arguments: false,
|
|
107
|
+
attributes: false
|
|
108
|
+
} }],
|
|
109
|
+
"typescript/no-unnecessary-condition": ["error", { allowConstantLoopConditions: true }],
|
|
110
|
+
"typescript/restrict-template-expressions": ["error", { allowNumber: true }],
|
|
111
|
+
"typescript/strict-boolean-expressions": ["error", {
|
|
112
|
+
allowNullableBoolean: true,
|
|
113
|
+
allowNullableNumber: true,
|
|
114
|
+
allowNullableString: true,
|
|
115
|
+
allowNumber: true,
|
|
116
|
+
allowString: true
|
|
117
|
+
}],
|
|
118
|
+
"typescript/switch-exhaustiveness-check": ["error", { considerDefaultExhaustiveForUnions: true }],
|
|
119
|
+
"unicorn/explicit-length-check": ["error", { "non-zero": "not-equal" }],
|
|
120
|
+
"unicorn/max-nested-calls": ["error", { max: 5 }],
|
|
121
|
+
"unicorn/switch-case-braces": ["error", "avoid"],
|
|
122
|
+
"vitest/consistent-test-it": ["error", { fn: "test" }]
|
|
123
|
+
};
|
|
124
|
+
const mergeConfigs$1 = (...configs) => configs.reduce(({ categories, env, globals, ignorePatterns, jsPlugins, options, overrides, plugins, rules, settings, ...rest }, { categories: configCategories, env: configEnv, globals: configGlobals, ignorePatterns: configIgnorePatterns, jsPlugins: configJsPlugins, options: configOptions, overrides: configOverrides, plugins: configPlugins, rules: configRules, settings: configSettings, ...configRest }) => ({
|
|
125
|
+
categories: {
|
|
126
|
+
...categories,
|
|
127
|
+
...configCategories
|
|
128
|
+
},
|
|
129
|
+
env: {
|
|
130
|
+
...env,
|
|
131
|
+
...configEnv
|
|
132
|
+
},
|
|
133
|
+
globals: {
|
|
134
|
+
...globals,
|
|
135
|
+
...configGlobals
|
|
136
|
+
},
|
|
137
|
+
ignorePatterns: [...ignorePatterns ?? [], ...configIgnorePatterns ?? []],
|
|
138
|
+
jsPlugins: [...jsPlugins ?? [], ...configJsPlugins ?? []],
|
|
139
|
+
options: {
|
|
140
|
+
...options,
|
|
141
|
+
...configOptions
|
|
142
|
+
},
|
|
143
|
+
overrides: [...overrides ?? [], ...configOverrides ?? []],
|
|
144
|
+
plugins: {
|
|
145
|
+
...plugins,
|
|
146
|
+
...configPlugins
|
|
147
|
+
},
|
|
148
|
+
rules: {
|
|
149
|
+
...rules,
|
|
150
|
+
...configRules
|
|
151
|
+
},
|
|
152
|
+
settings: {
|
|
153
|
+
...settings,
|
|
154
|
+
...configSettings
|
|
155
|
+
},
|
|
156
|
+
...rest,
|
|
157
|
+
...configRest
|
|
158
|
+
}), {});
|
|
159
|
+
const getTailwindConfig = async (config) => {
|
|
160
|
+
if (!config) return {};
|
|
161
|
+
const tailwindPlugin = await import("eslint-plugin-better-tailwindcss");
|
|
162
|
+
return {
|
|
163
|
+
jsPlugins: [{
|
|
164
|
+
name: "better-tailwindcss",
|
|
165
|
+
specifier: "eslint-plugin-better-tailwindcss"
|
|
166
|
+
}],
|
|
167
|
+
rules: {
|
|
168
|
+
...Object.fromEntries(Object.keys(tailwindPlugin.default.rules).map((key) => [`better-tailwindcss/${key}`, "error"])),
|
|
169
|
+
...disabledTailwindRules
|
|
170
|
+
},
|
|
171
|
+
settings: { "better-tailwindcss": { entryPoint: config.entryPoint } }
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
const getVitestConfig = (config) => {
|
|
175
|
+
if (!config) return {};
|
|
176
|
+
return {
|
|
177
|
+
overrides: config.files ? [{
|
|
178
|
+
files: config.files,
|
|
179
|
+
rules: { "react/rules-of-hooks": "off" }
|
|
180
|
+
}] : [],
|
|
181
|
+
plugins: { vitest: true }
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
const getTanstackRouterConfig = async (config) => {
|
|
185
|
+
if (!config) return {};
|
|
186
|
+
const plugin = await import("@tanstack/eslint-plugin-router");
|
|
187
|
+
return {
|
|
188
|
+
jsPlugins: [{
|
|
189
|
+
name: "@tanstack/router",
|
|
190
|
+
specifier: "@tanstack/eslint-plugin-router"
|
|
191
|
+
}],
|
|
192
|
+
overrides: [{
|
|
193
|
+
files: config.routes,
|
|
194
|
+
rules: { "no-use-before-define": "off" }
|
|
195
|
+
}],
|
|
196
|
+
rules: plugin.default.configs["flat/recommended"][0].rules
|
|
197
|
+
};
|
|
198
|
+
};
|
|
199
|
+
const getPackageJsonConfig = async (config) => {
|
|
200
|
+
if (!config) return {};
|
|
201
|
+
return {
|
|
202
|
+
jsPlugins: [{
|
|
203
|
+
name: "package-json",
|
|
204
|
+
specifier: "eslint-plugin-package-json"
|
|
205
|
+
}],
|
|
206
|
+
rules: (await import("eslint-plugin-package-json")).configs.recommended.rules
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
const getPlaywrightConfig = async (config) => {
|
|
210
|
+
if (!config) return {};
|
|
211
|
+
const plugin = await import("eslint-plugin-playwright");
|
|
212
|
+
return {
|
|
213
|
+
jsPlugins: [{
|
|
214
|
+
name: "playwright",
|
|
215
|
+
specifier: "eslint-plugin-playwright"
|
|
216
|
+
}],
|
|
217
|
+
overrides: [{
|
|
218
|
+
files: config.files,
|
|
219
|
+
rules: {
|
|
220
|
+
...plugin.default.configs["flat/recommended"].rules,
|
|
221
|
+
...config.assertFunctionNames ? { "playwright/expect-expect": ["error", { assertFunctionNames: config.assertFunctionNames }] } : {},
|
|
222
|
+
"react/rules-of-hooks": "off",
|
|
223
|
+
"vitest/consistent-test-filename": "off",
|
|
224
|
+
"vitest/prefer-each": "off",
|
|
225
|
+
"vitest/valid-expect": "off"
|
|
226
|
+
}
|
|
227
|
+
}]
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
const getServerSideConfig = (config) => {
|
|
231
|
+
if (!config) return {};
|
|
232
|
+
return { overrides: [
|
|
233
|
+
{
|
|
234
|
+
files: config.files,
|
|
235
|
+
rules: { "import/no-nodejs-modules": "off" }
|
|
236
|
+
},
|
|
237
|
+
config.allowConsole ? {
|
|
238
|
+
files: config.allowConsole,
|
|
239
|
+
rules: { "no-console": "off" }
|
|
240
|
+
} : null,
|
|
241
|
+
config.allowProcess ? {
|
|
242
|
+
files: config.allowProcess,
|
|
243
|
+
rules: { "node/no-process-env": "off" }
|
|
244
|
+
} : null
|
|
245
|
+
].filter(isNonNullish) };
|
|
246
|
+
};
|
|
247
|
+
const getRestrictedSyntaxConfig = (config) => {
|
|
248
|
+
if (!config) return {};
|
|
249
|
+
const overrides = config.overrides ?? [];
|
|
250
|
+
const rawRules = [config.banBarrelImport ? {
|
|
251
|
+
message: "Do not use barrel export, prefer named export",
|
|
252
|
+
selector: "ExportAllDeclaration"
|
|
253
|
+
} : null, config.banReactMemo ? {
|
|
254
|
+
message: "No need to use `React.memo`, we have a react compiler turned on",
|
|
255
|
+
selector: "MemberExpression[object.name='React'][property.name='memo']"
|
|
256
|
+
} : null].filter(isNonNullish);
|
|
257
|
+
return {
|
|
258
|
+
overrides: overrides.map(({ files, rules }) => ({
|
|
259
|
+
files,
|
|
260
|
+
rules: { "eslint-js/no-restricted-syntax": ["error", [
|
|
261
|
+
...rawRules,
|
|
262
|
+
...rules,
|
|
263
|
+
...config.rulesOverrides ?? []
|
|
264
|
+
]] }
|
|
265
|
+
})),
|
|
266
|
+
rules: { "eslint-js/no-restricted-syntax": [
|
|
267
|
+
"error",
|
|
268
|
+
...rawRules,
|
|
269
|
+
...config.rulesOverrides ?? []
|
|
270
|
+
] }
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
const getRestrictedConfig = (config) => {
|
|
274
|
+
if (!config) return {};
|
|
275
|
+
return { rules: {
|
|
276
|
+
"eslint/no-restricted-globals": config.globals ? ["error", ...config.globals] : "error",
|
|
277
|
+
"eslint/no-restricted-properties": config.properties ? ["error", ...config.properties] : "error"
|
|
278
|
+
} };
|
|
279
|
+
};
|
|
280
|
+
const getReactConfig = (config) => {
|
|
281
|
+
if (!config) return {};
|
|
282
|
+
return { rules: {
|
|
283
|
+
"react/exhaustive-deps": config.additionalHooks ? ["error", { additionalHooks: `(${config.additionalHooks.join(",")})` }] : "error",
|
|
284
|
+
"react/jsx-no-literals": ["error", {
|
|
285
|
+
allowedStrings: config.allowedStrings,
|
|
286
|
+
ignoreProps: true,
|
|
287
|
+
noAttributeStrings: true,
|
|
288
|
+
noStrings: true
|
|
289
|
+
}]
|
|
290
|
+
} };
|
|
291
|
+
};
|
|
292
|
+
const getI18nConfig = (config) => {
|
|
293
|
+
if (!config) return {};
|
|
294
|
+
return {
|
|
295
|
+
overrides: Array.isArray(config.ignore) ? [{
|
|
296
|
+
files: config.ignore,
|
|
297
|
+
rules: { "react/jsx-no-literals": "off" }
|
|
298
|
+
}] : [],
|
|
299
|
+
rules: config.ignore === true ? { "react/jsx-no-literals": "off" } : {}
|
|
300
|
+
};
|
|
301
|
+
};
|
|
302
|
+
const getImportConfig = (config) => {
|
|
303
|
+
if (!config) return {};
|
|
304
|
+
return { overrides: [config.allowDefault ? {
|
|
305
|
+
files: config.allowDefault,
|
|
306
|
+
rules: { "import/no-default-export": "off" }
|
|
307
|
+
} : null].filter(isNonNullish) };
|
|
308
|
+
};
|
|
309
|
+
const getBaseConfig$1 = () => ({
|
|
310
|
+
categories: {
|
|
311
|
+
correctness: "error",
|
|
312
|
+
nursery: "error",
|
|
313
|
+
pedantic: "error",
|
|
314
|
+
perf: "error",
|
|
315
|
+
restriction: "error",
|
|
316
|
+
style: "error",
|
|
317
|
+
suspicious: "error"
|
|
318
|
+
},
|
|
319
|
+
env: {
|
|
320
|
+
browser: true,
|
|
321
|
+
es2026: true
|
|
322
|
+
},
|
|
323
|
+
ignorePatterns: baseIgnorePatterns,
|
|
324
|
+
jsPlugins: [{
|
|
325
|
+
name: "eslint-js",
|
|
326
|
+
specifier: "oxlint-plugin-eslint"
|
|
327
|
+
}],
|
|
328
|
+
options: {
|
|
329
|
+
denyWarnings: true,
|
|
330
|
+
reportUnusedDisableDirectives: "error",
|
|
331
|
+
typeAware: true
|
|
332
|
+
},
|
|
333
|
+
overrides: [{
|
|
334
|
+
files: ["**/*.config.{j,t}s"],
|
|
335
|
+
rules: {
|
|
336
|
+
"import/no-default-export": "off",
|
|
337
|
+
"import/no-nodejs-modules": "off",
|
|
338
|
+
"node/no-top-level-await": "off"
|
|
339
|
+
}
|
|
340
|
+
}, {
|
|
341
|
+
files: ["**/*.d.ts"],
|
|
342
|
+
rules: { "typescript/triple-slash-reference": "off" }
|
|
343
|
+
}],
|
|
344
|
+
plugins: {
|
|
345
|
+
eslint: true,
|
|
346
|
+
import: true,
|
|
347
|
+
"jsx-a11y": true,
|
|
348
|
+
node: true,
|
|
349
|
+
oxc: true,
|
|
350
|
+
promise: true,
|
|
351
|
+
react: true,
|
|
352
|
+
"react-perf": true,
|
|
353
|
+
typescript: true,
|
|
354
|
+
unicorn: true
|
|
355
|
+
},
|
|
356
|
+
rules: {
|
|
357
|
+
...disabledRules,
|
|
358
|
+
...overridenRules
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
const getConfig$2 = async ({ tailwind, tanstackRouter, vitest, packageJson = true, playwright, serverSide, restricted, react, i18n, import: importOptions, ...config } = {}) => {
|
|
362
|
+
const baseConfig = getBaseConfig$1();
|
|
363
|
+
const tailwindConfig = await getTailwindConfig(tailwind);
|
|
364
|
+
const tanstackRouterConfig = await getTanstackRouterConfig(tanstackRouter);
|
|
365
|
+
const vitestConfig = getVitestConfig(vitest);
|
|
366
|
+
const packageJsonConfig = await getPackageJsonConfig(packageJson);
|
|
367
|
+
const playwrightConfig = await getPlaywrightConfig(playwright);
|
|
368
|
+
const serverSideConfig = getServerSideConfig(serverSide);
|
|
369
|
+
const reactConfig = getReactConfig(react);
|
|
370
|
+
const i18nConfig = getI18nConfig(i18n);
|
|
371
|
+
const importConfig = getImportConfig(importOptions);
|
|
372
|
+
const restrictedConfig = getRestrictedConfig(restricted);
|
|
373
|
+
const rawMergedConfig = mergeConfigs$1(baseConfig, vitestConfig, tanstackRouterConfig, packageJsonConfig, playwrightConfig, tailwindConfig, serverSideConfig, restrictedConfig, reactConfig, i18nConfig, importConfig, config);
|
|
374
|
+
const restrictedSyntaxConfig = getRestrictedSyntaxConfig({
|
|
375
|
+
banBarrelImport: importOptions?.banBarrel,
|
|
376
|
+
banReactMemo: react?.banMemo,
|
|
377
|
+
overrides: restricted?.syntaxOverrides,
|
|
378
|
+
previousOverrides: rawMergedConfig.overrides?.map((override) => override.rules?.["eslint-js/no-restricted-syntax"] === void 0 ? void 0 : {
|
|
379
|
+
files: override.files,
|
|
380
|
+
rules: override.rules["eslint-js/no-restricted-syntax"].slice(1)
|
|
381
|
+
}).filter(isNonNullish),
|
|
382
|
+
previousRules: (rawMergedConfig.rules?.["eslint-js/no-restricted-syntax"])?.slice(1),
|
|
383
|
+
rulesOverrides: restricted?.syntaxRulesOverrides
|
|
384
|
+
});
|
|
385
|
+
const { plugins: pluginsRecord = {}, ...mergedConfig } = mergeConfigs$1(rawMergedConfig, restrictedSyntaxConfig);
|
|
386
|
+
return {
|
|
387
|
+
...mergedConfig,
|
|
388
|
+
plugins: Object.entries(pluginsRecord).filter(([, value]) => value).map(([key]) => key)
|
|
389
|
+
};
|
|
390
|
+
};
|
|
391
|
+
//#endregion
|
|
392
|
+
//#region src/oxfmt.ts
|
|
393
|
+
const getConfig = async ({ ignorePatterns = [], tailwind, imports, sortImports, ...rest } = {}) => ({
|
|
394
|
+
astro: true,
|
|
395
|
+
ignorePatterns: [...baseIgnorePatterns, ...ignorePatterns],
|
|
396
|
+
printWidth: 80,
|
|
397
|
+
sortImports: sortImports ?? (imports ? {
|
|
398
|
+
newlinesBetween: false,
|
|
399
|
+
order: "asc",
|
|
400
|
+
...imports
|
|
401
|
+
} : true),
|
|
402
|
+
sortPackageJson: { sortScripts: true },
|
|
403
|
+
sortTailwindcss: tailwind ? {
|
|
404
|
+
functions: tailwind.functions,
|
|
405
|
+
stylesheet: tailwind.stylesheet
|
|
406
|
+
} : void 0,
|
|
407
|
+
useTabs: true,
|
|
408
|
+
...rest
|
|
409
|
+
});
|
|
410
|
+
//#endregion
|
|
411
|
+
//#region src/knip.ts
|
|
412
|
+
const mergeConfigs = (...configs) => configs.reduce(({ include, ignore, ignoreDependencies, entry, ignoreIssues, workspaces = {}, ...rest }, { include: configInclude, ignore: configIgnore, ignoreDependencies: configIgnoreDependencies, entry: configEntry, ignoreIssues: configIgnoreIssues, workspaces: configWorkspaces = {}, ...configRest }) => ({
|
|
413
|
+
entry: [...arraify(entry), ...arraify(configEntry)],
|
|
414
|
+
ignore: [...arraify(ignore), ...arraify(configIgnore)],
|
|
415
|
+
ignoreDependencies: [...arraify(ignoreDependencies), ...arraify(configIgnoreDependencies)],
|
|
416
|
+
ignoreIssues: {
|
|
417
|
+
...ignoreIssues,
|
|
418
|
+
...configIgnoreIssues
|
|
419
|
+
},
|
|
420
|
+
include: {
|
|
421
|
+
...include,
|
|
422
|
+
...configInclude
|
|
423
|
+
},
|
|
424
|
+
workspaces: {
|
|
425
|
+
...mapValues(workspaces, (workspace, key) => ({
|
|
426
|
+
...workspace,
|
|
427
|
+
...configWorkspaces[key]
|
|
428
|
+
})),
|
|
429
|
+
...omitBy(configWorkspaces, (_value, key) => Boolean(workspaces[key]))
|
|
430
|
+
},
|
|
431
|
+
...rest,
|
|
432
|
+
...configRest
|
|
433
|
+
}), {});
|
|
434
|
+
const getBaseConfig = ({ opencode = false, reactNative = false, eslint = true, vitest = true, workspaces = false } = {}) => ({
|
|
435
|
+
entry: workspaces ? [] : ["**/*.config.ts"],
|
|
436
|
+
ignore: [process.env.CI ? void 0 : ".history/**", opencode ? ".opencode/**" : void 0].filter(isNonNullish),
|
|
437
|
+
ignoreDependencies: [
|
|
438
|
+
reactNative ? "expo-doctor" : void 0,
|
|
439
|
+
vitest ? "@vitest/coverage-v8" : void 0,
|
|
440
|
+
eslint ? "oxlint-plugin-eslint" : void 0
|
|
441
|
+
].filter(isNonNullish),
|
|
442
|
+
ignoreIssues: { "**/*.gen.ts": ["types"] },
|
|
443
|
+
include: {
|
|
444
|
+
catalog: true,
|
|
445
|
+
catalogReferences: true,
|
|
446
|
+
cycles: true,
|
|
447
|
+
dependencies: true,
|
|
448
|
+
duplicates: true,
|
|
449
|
+
enumMembers: true,
|
|
450
|
+
exports: true,
|
|
451
|
+
files: true,
|
|
452
|
+
namespaceMembers: true,
|
|
453
|
+
nsExports: true,
|
|
454
|
+
nsTypes: true,
|
|
455
|
+
types: true,
|
|
456
|
+
unlisted: true,
|
|
457
|
+
unresolved: true
|
|
458
|
+
},
|
|
459
|
+
treatConfigHintsAsErrors: true,
|
|
460
|
+
treatTagHintsAsErrors: true,
|
|
461
|
+
workspaces: workspaces ? { ".": { entry: ["**/*.config.ts"] } } : {}
|
|
462
|
+
});
|
|
463
|
+
const getConfig$1 = async ({ options, ...overrides } = {}) => {
|
|
464
|
+
const baseConfig = getBaseConfig(options);
|
|
465
|
+
const { include: includeRecord = {}, ...mergedConfig } = mergeConfigs(baseConfig, overrides);
|
|
466
|
+
return {
|
|
467
|
+
...mergedConfig,
|
|
468
|
+
include: Object.entries(includeRecord).filter(([, value]) => value).map(([key]) => key)
|
|
469
|
+
};
|
|
470
|
+
};
|
|
471
|
+
//#endregion
|
|
472
|
+
export { configSchema, disabledRules, getConfig as getFormatConfig, getConfig$1 as getKnipConfig, getConfig$2 as getLintConfig, overridenRules };
|
package/package.json
CHANGED
|
@@ -1,6 +1,67 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@oxiul/configs",
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/oxiul/configs.git"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist/**",
|
|
11
|
+
"scripts/postinstall.mjs"
|
|
12
|
+
],
|
|
13
|
+
"type": "module",
|
|
14
|
+
"sideEffects": false,
|
|
15
|
+
"main": "./dist/index.mjs",
|
|
16
|
+
"module": "./dist/index.mjs",
|
|
17
|
+
"exports": {
|
|
18
|
+
"types": "./dist/index.d.mts",
|
|
19
|
+
"default": "./dist/index.mjs"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsdown",
|
|
26
|
+
"changeset": "changeset add",
|
|
27
|
+
"deps": "knip",
|
|
28
|
+
"format": "oxfmt --write",
|
|
29
|
+
"format:verify": "oxfmt --check",
|
|
30
|
+
"lint": "oxlint",
|
|
31
|
+
"lint:fix": "oxlint --fix",
|
|
32
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
33
|
+
"typecheck": "bun check"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"cosmiconfig": "^10.0.1",
|
|
37
|
+
"listr2": "^11.4.0",
|
|
38
|
+
"oxlint-plugin-eslint": "^1.88.0",
|
|
39
|
+
"zod": "^4.6.7"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@arethetypeswrong/core": "^0.18.5",
|
|
43
|
+
"@changesets/changelog-github": "^1.0.1",
|
|
44
|
+
"@changesets/cli": "^3.0.3",
|
|
45
|
+
"@tanstack/eslint-plugin-router": "^1.162.0",
|
|
46
|
+
"@types/bun": "1.4.3",
|
|
47
|
+
"eslint-plugin-better-tailwindcss": "^4.9.1",
|
|
48
|
+
"eslint-plugin-package-json": "^1.10.1",
|
|
49
|
+
"eslint-plugin-playwright": "^2.12.1",
|
|
50
|
+
"knip": "^6.42.0",
|
|
51
|
+
"oxfmt": "^0.73.0",
|
|
52
|
+
"oxlint": "^1.88.0",
|
|
53
|
+
"oxlint-tsgolint": "^7.0.2004",
|
|
54
|
+
"publint": "^0.3.25",
|
|
55
|
+
"remeda": "^2.52.0",
|
|
56
|
+
"tsdown": "^0.23.1"
|
|
57
|
+
},
|
|
58
|
+
"peerDependencies": {
|
|
59
|
+
"knip": "^6.42.0",
|
|
60
|
+
"oxfmt": "^0.73.0",
|
|
61
|
+
"oxlint": "^1.88.0"
|
|
62
|
+
},
|
|
63
|
+
"engines": {
|
|
64
|
+
"node": "26"
|
|
65
|
+
},
|
|
66
|
+
"packageManager": "bun@1.4.3"
|
|
67
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { execFileSync, spawnSync } from "node:child_process";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
if (process.env.CI) {
|
|
6
|
+
process.exit(0);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const readName = (dir) => {
|
|
10
|
+
try {
|
|
11
|
+
// oxlint-disable-next-line typescript/no-unsafe-argument
|
|
12
|
+
const fileContent = readFileSync(path.join(dir, "package.json"), "utf8");
|
|
13
|
+
// oxlint-disable-next-line typescript/no-unsafe-return typescript/no-unsafe-member-access
|
|
14
|
+
return JSON.parse(fileContent).name;
|
|
15
|
+
} catch {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// oxlint-disable-next-line typescript/no-unsafe-assignment
|
|
21
|
+
const ownName = readName(process.cwd());
|
|
22
|
+
|
|
23
|
+
let gitRoot = "";
|
|
24
|
+
try {
|
|
25
|
+
gitRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
|
26
|
+
encoding: "utf8",
|
|
27
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
28
|
+
}).trim();
|
|
29
|
+
} catch {
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const [cmd, ...args] =
|
|
34
|
+
readName(gitRoot) === ownName
|
|
35
|
+
? ["bun", "src/hook/install.ts"]
|
|
36
|
+
: ["node", "dist/hook/install.mjs"];
|
|
37
|
+
|
|
38
|
+
const result = spawnSync(cmd, args, { stdio: "inherit" });
|
|
39
|
+
process.exit(result.status ?? 1);
|