@oxiul/configs 0.0.0-stage → 0.4.0

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 CHANGED
@@ -1,3 +1,67 @@
1
- # Temporary Holding Version
1
+ # Configs
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ ## Lint config
4
+
5
+ A shared config for oxlint
6
+
7
+ ## Format config
8
+
9
+ A shared config for oxfmt
10
+
11
+ ## GitHub Actions
12
+
13
+ Configure generation in `oxiul.config.ts`:
14
+
15
+ ```ts
16
+ import type { Config } from "@oxiul/configs";
17
+
18
+ export default {
19
+ workflows: {
20
+ workflows: [], // Optional { name, workflow } objects for project workflows.
21
+ jobs: {}, // Optional { jobName: <job> } object with CI jobs descriptions.
22
+ },
23
+ } satisfies Config;
24
+ ```
25
+
26
+ ## Package.json verification
27
+
28
+ Run `oxiul verify` to require a pinned Bun version of at least 1.4.4,
29
+ a Node.js engine range starting at 26 or higher, and these exact scripts:
30
+
31
+ ```json
32
+ {
33
+ "lint": "oxlint",
34
+ "lint:fix": "oxlint --fix",
35
+ "format": "oxfmt --write",
36
+ "format:verify": "oxfmt --check",
37
+ "workflows": "oxiul workflows --verify",
38
+ "workflows:generate": "oxiul workflows --generate",
39
+ "typecheck": "bun check",
40
+ "deps": "knip",
41
+ "oxiul:verify": "oxiul verify"
42
+ }
43
+ ```
44
+
45
+ Add requirements or override commands in `oxiul.config.ts`:
46
+
47
+ ```ts
48
+ export default {
49
+ verify: {
50
+ scripts: {
51
+ build: "bun build src/index.ts",
52
+ test: "*", // Required script, any command.
53
+ lint: "oxlint --deny-warnings",
54
+ },
55
+ },
56
+ } satisfies Config;
57
+ ```
58
+
59
+ Other scripts are allowed and left unchecked. Verification reads `package.json`
60
+ from the current directory and never modifies it.
61
+
62
+ ## Development
63
+
64
+ ### Prerequisites
65
+
66
+ - Node.js (from `engines.node` field in `package.json`)
67
+ - Bun (from `packageManager` field in `package.json`)
package/dist/bin.d.mts ADDED
@@ -0,0 +1 @@
1
+ export {}
package/dist/bin.mjs ADDED
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env bun
2
+ import { t as parse } from "./parse-DnOcFJT0.mjs";
3
+ import { a as getDepsJob, c as getPackageJsonVerifyJob, d as getWorkflowsVerifyJob, i as getDefaultWorkflow, l as getSetupAction, o as getFormatVerifyJob, s as getLintJob, t as generateWorkflows, u as getTypecheckJob } from "./generate-BGCgStVl.mjs";
4
+ import { gte, subset, valid, validRange } from "semver";
5
+ import { z } from "zod";
6
+ import { Crust, defineCommand } from "@crustjs/core";
7
+ import { help } from "@crustjs/extensions";
8
+ import { readFile } from "node:fs/promises";
9
+ //#region src/schemas.ts
10
+ const packageJsonSchema = z.object({
11
+ engines: z.object({ node: z.string() }),
12
+ packageManager: z.string(),
13
+ scripts: z.record(z.string(), z.string())
14
+ }).partial();
15
+ //#endregion
16
+ //#region src/verify/package-json.ts
17
+ const defaultScripts = {
18
+ deps: "knip",
19
+ format: "oxfmt --write",
20
+ "format:verify": "oxfmt --check",
21
+ lint: "oxlint",
22
+ "lint:fix": "oxlint --fix",
23
+ "oxiul:verify": "oxiul verify",
24
+ typecheck: "bun check",
25
+ workflows: "oxiul workflows --verify",
26
+ "workflows:generate": "oxiul workflows --generate"
27
+ };
28
+ const verifyPackageJson = (packageJson, { scripts: extraScripts, minBunVersion, minNodeVersion }) => {
29
+ const { scripts = {}, packageManager = "", engines: { node: nodeVersionRaw = "" } = { node: "" } } = packageJson;
30
+ const errors = [];
31
+ const bunVersion = /^bun@(?<version>[^+]+)(?:\+sha\d+\.[a-f\d]+)?$/u.exec(packageManager)?.groups?.version;
32
+ if (!bunVersion || !valid(bunVersion) || !gte(bunVersion, minBunVersion)) errors.push(`packageManager must pin bun@${minBunVersion} or higher`);
33
+ const nodeRange = validRange(nodeVersionRaw);
34
+ if (!nodeRange || !subset(nodeRange, `>=${minNodeVersion}`)) errors.push(`engines.node must require Node.js ${minNodeVersion} or higher`);
35
+ for (const [name, command] of Object.entries({
36
+ ...defaultScripts,
37
+ ...extraScripts
38
+ })) if (!scripts[name]) errors.push(`Missing script: ${name}`);
39
+ else if (command !== "*" && scripts[name] !== command) errors.push(`scripts[${name}] must be ${JSON.stringify(command)}`);
40
+ if (errors.length !== 0) throw new Error(`Package.json verification failed:\n${errors.join("\n")}`);
41
+ };
42
+ //#endregion
43
+ //#region src/verify/bin.ts
44
+ const command$1 = defineCommand("verify", { description: "Verify package.json" }, (def) => def.action(async ({ stdout }) => {
45
+ stdout("Verifying package.json...");
46
+ const config = await parse();
47
+ const parseResult = packageJsonSchema.safeParse(JSON.parse(await readFile("package.json", "utf8")));
48
+ if (!parseResult.success) throw new Error(`Invalid package.json: ${parseResult.error.message}`);
49
+ verifyPackageJson(parseResult.data, config.verify);
50
+ stdout("package.json verified successfully!");
51
+ }));
52
+ //#endregion
53
+ //#region src/workflows/bin.ts
54
+ const command = defineCommand("workflows", { description: "Workflows" }, (def) => def.flags({
55
+ name: "verify",
56
+ short: "r",
57
+ type: "boolean"
58
+ }).flags({
59
+ name: "generate",
60
+ short: "g",
61
+ type: "boolean"
62
+ }).action(async ({ flags, stdout }) => {
63
+ const config = await parse();
64
+ const options = {
65
+ actions: { "setup-env": getSetupAction() },
66
+ workflows: [getDefaultWorkflow({
67
+ jobs: {
68
+ deps: getDepsJob(),
69
+ format: getFormatVerifyJob(),
70
+ lint: getLintJob(),
71
+ typecheck: getTypecheckJob(),
72
+ verify: getPackageJsonVerifyJob(),
73
+ workflows: getWorkflowsVerifyJob(),
74
+ ...config.workflows?.jobs
75
+ },
76
+ name: "CI"
77
+ }), ...config.workflows?.workflows ?? []]
78
+ };
79
+ if (flags.generate) {
80
+ stdout(`Generating the workflows..`);
81
+ await generateWorkflows({
82
+ ...options,
83
+ check: false
84
+ });
85
+ stdout(`Workflows generated successfully!`);
86
+ } else {
87
+ stdout(`Verifying the workflows..`);
88
+ await generateWorkflows({
89
+ ...options,
90
+ check: true
91
+ });
92
+ stdout(`Workflows verified successfully!`);
93
+ }
94
+ }));
95
+ //#endregion
96
+ //#region src/bin.ts
97
+ await new Crust("oxiul", { description: "Oxiul runner" }).add(command$1).add(command).extend(help()).execute();
98
+ //#endregion
99
+ export {};
@@ -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,103 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { stringify } from "yaml";
4
+ //#region src/workflows/default.ts
5
+ const DEFAULT_MACHINE = "ubuntu-26.04";
6
+ const getSetupAction = () => ({
7
+ description: "Setup runtime",
8
+ name: "Runtime setup",
9
+ runs: {
10
+ steps: [
11
+ {
12
+ name: "Setup Node.js",
13
+ uses: "actions/setup-node@v7",
14
+ with: { "node-version-file": "package.json" }
15
+ },
16
+ {
17
+ name: "Setup Bun",
18
+ uses: "oven-sh/setup-bun@v2",
19
+ with: { "bun-version-file": "package.json" }
20
+ },
21
+ {
22
+ name: "Install dependencies",
23
+ run: "bun install --frozen-lockfile",
24
+ shell: "bash"
25
+ }
26
+ ],
27
+ using: "composite"
28
+ }
29
+ });
30
+ const getDefaultWorkflow = ({ concurrency, on, name = "Default workflow", ...rest }) => ({
31
+ concurrency: {
32
+ "cancel-in-progress": true,
33
+ group: "${{ github.workflow }}-${{ github.ref }}",
34
+ ...concurrency
35
+ },
36
+ name,
37
+ on: {
38
+ pull_request: {},
39
+ push: { branches: ["main"] },
40
+ workflow_dispatch: {},
41
+ ...on
42
+ },
43
+ ...rest
44
+ });
45
+ const getCheckJob = ({ "runs-on": runsOn = DEFAULT_MACHINE, steps, overrideSteps = false, ...rest }) => ({
46
+ "runs-on": runsOn,
47
+ steps: overrideSteps ? steps : [
48
+ { uses: "actions/checkout@v7" },
49
+ { uses: "./.github/actions/setup-env" },
50
+ ...steps
51
+ ],
52
+ ...rest
53
+ });
54
+ const getFormatVerifyJob = () => getCheckJob({
55
+ name: "Format verification",
56
+ steps: [{ run: "bun run format:verify" }]
57
+ });
58
+ const getDepsJob = () => getCheckJob({
59
+ name: "Dependencies check",
60
+ steps: [{ run: "bun run deps" }]
61
+ });
62
+ const getTypecheckJob = () => getCheckJob({
63
+ name: "Typecheck",
64
+ steps: [{ run: "bun run typecheck" }]
65
+ });
66
+ const getLintJob = () => getCheckJob({
67
+ name: "Lint",
68
+ steps: [{ run: "bun run lint" }]
69
+ });
70
+ const getWorkflowsVerifyJob = () => getCheckJob({
71
+ name: "Workflows verification",
72
+ steps: [{ run: "bun run workflows" }]
73
+ });
74
+ const getPackageJsonVerifyJob = () => getCheckJob({
75
+ name: "Package.json verification",
76
+ steps: [{ run: "bun run oxiul:verify" }]
77
+ });
78
+ //#endregion
79
+ //#region src/workflows/generate.ts
80
+ const generateWorkflows = async ({ workflows = [], actions = {}, directory = ".", check = false }) => {
81
+ const files = /* @__PURE__ */ new Map();
82
+ const addFile = (name, filePath, value) => {
83
+ if (!name || !/^[\w-]+$/u.test(name)) throw new Error(`Invalid generated file name: ${name}`);
84
+ if (files.has(filePath)) throw new Error(`Duplicate generated file: ${filePath}`);
85
+ files.set(filePath, `# Generated by @oxiul/configs/workflows. Do not edit.\n${stringify(value, { lineWidth: 0 })}`);
86
+ };
87
+ for (const workflow of workflows) addFile(workflow.name, `.github/workflows/${workflow.name.toLowerCase()}.yml`, workflow);
88
+ for (const [name, action] of Object.entries(actions)) addFile(name, `.github/actions/${name}/action.yml`, action);
89
+ for (const [filePath, content] of files) {
90
+ const target = path.resolve(directory, filePath);
91
+ if (check) {
92
+ if (await readFile(target, "utf8").catch((error) => {
93
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") return;
94
+ throw error;
95
+ }) !== content) throw new Error(`Generated file is out of date: ${filePath}`);
96
+ } else {
97
+ await mkdir(path.dirname(target), { recursive: true });
98
+ await writeFile(target, content);
99
+ }
100
+ }
101
+ };
102
+ //#endregion
103
+ export { getDepsJob as a, getPackageJsonVerifyJob as c, getWorkflowsVerifyJob as d, getDefaultWorkflow as i, getSetupAction as l, DEFAULT_MACHINE as n, getFormatVerifyJob as o, getCheckJob as r, getLintJob as s, generateWorkflows as t, getTypecheckJob as u };
@@ -0,0 +1 @@
1
+ export {}
@@ -0,0 +1,37 @@
1
+ import { i as packageName } from "../common-B9SE4GL9.mjs";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { exec } from "node:child_process";
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,51 @@
1
+ import { t as parse } from "../parse-DnOcFJT0.mjs";
2
+ import { spawn } from "node:child_process";
3
+ import { Listr } from "listr2";
4
+ //#region src/hook/pre-commit.ts
5
+ const failedOutputs = /* @__PURE__ */ new Map();
6
+ const run = (command, task) => new Promise((resolve, reject) => {
7
+ const child = spawn(command, {
8
+ env: {
9
+ ...process.env,
10
+ FORCE_COLOR: "1"
11
+ },
12
+ shell: true,
13
+ stdio: [
14
+ "ignore",
15
+ "pipe",
16
+ "pipe"
17
+ ]
18
+ });
19
+ const window = task.stdout();
20
+ let output = "";
21
+ const onData = (chunk) => {
22
+ output += chunk;
23
+ window.write(chunk);
24
+ };
25
+ child.stdout.on("data", onData);
26
+ child.stderr.on("data", onData);
27
+ child.on("error", reject);
28
+ child.on("close", (code, signal) => {
29
+ if (code === 0) return resolve();
30
+ failedOutputs.set(command, output);
31
+ reject(/* @__PURE__ */ new Error(signal ? `killed by ${signal}` : `exited with code ${code}`));
32
+ });
33
+ });
34
+ try {
35
+ const config = await parse();
36
+ if (config.preCommitCommands && config.preCommitCommands.length !== 0) await new Listr(config.preCommitCommands.map((command) => ({
37
+ rendererOptions: {
38
+ outputBar: 5,
39
+ persistentOutput: false
40
+ },
41
+ task: (_ctx, task) => run(command, task),
42
+ title: command
43
+ })), { concurrent: false }).run();
44
+ else console.log(`No commands in pre-commit list found`);
45
+ } catch {
46
+ for (const [command, output] of failedOutputs) console.error(`\n✖ Output of "${command}"\n${output}`);
47
+ console.error(`${failedOutputs.size} tasks failed: ${[...failedOutputs.keys()].join(", ")}`);
48
+ process.exit(1);
49
+ }
50
+ //#endregion
51
+ export {};
@@ -0,0 +1,44 @@
1
+ import { GeneratedWorkflowTypes, GeneratedWorkflowTypes as GeneratedWorkflowTypes$1 } from "@github-actions-workflow-ts/lib";
2
+ //#region src/workflows/types.d.ts
3
+ type CompositeAction = {
4
+ name: string;
5
+ description: string;
6
+ runs: {
7
+ using: "composite";
8
+ steps: GeneratedWorkflowTypes.Step[];
9
+ };
10
+ };
11
+ type Workflow = GeneratedWorkflowTypes.Workflow;
12
+ //#endregion
13
+ //#region src/workflows/default.d.ts
14
+ declare const DEFAULT_MACHINE = "ubuntu-26.04";
15
+ declare const getSetupAction: () => CompositeAction;
16
+ declare const getDefaultWorkflow: ({ concurrency, on, name, ...rest }: Omit<GeneratedWorkflowTypes.Workflow, "on" | "concurrency"> & {
17
+ on?: Exclude<GeneratedWorkflowTypes.Workflow["on"], GeneratedWorkflowTypes.Event | GeneratedWorkflowTypes.Event[]>;
18
+ concurrency?: Exclude<GeneratedWorkflowTypes.Workflow["concurrency"], string>;
19
+ }) => Omit<GeneratedWorkflowTypes.Workflow, "name"> & {
20
+ name: string;
21
+ };
22
+ declare const getCheckJob: ({ "runs-on": runsOn, steps, overrideSteps, ...rest }: Omit<GeneratedWorkflowTypes.NormalJob, "runs-on"> & {
23
+ overrideSteps?: boolean;
24
+ "runs-on"?: GeneratedWorkflowTypes.NormalJob["runs-on"];
25
+ steps: Exclude<GeneratedWorkflowTypes.NormalJob["steps"], undefined>;
26
+ }) => GeneratedWorkflowTypes.NormalJob;
27
+ declare const getFormatVerifyJob: () => GeneratedWorkflowTypes.NormalJob;
28
+ declare const getDepsJob: () => GeneratedWorkflowTypes.NormalJob;
29
+ declare const getTypecheckJob: () => GeneratedWorkflowTypes.NormalJob;
30
+ declare const getLintJob: () => GeneratedWorkflowTypes.NormalJob;
31
+ declare const getWorkflowsVerifyJob: () => GeneratedWorkflowTypes.NormalJob;
32
+ declare const getPackageJsonVerifyJob: () => GeneratedWorkflowTypes.NormalJob;
33
+ //#endregion
34
+ //#region src/workflows/generate.d.ts
35
+ declare const generateWorkflows: ({ workflows, actions, directory, check }: {
36
+ workflows?: (Omit<GeneratedWorkflowTypes.Workflow, "name"> & {
37
+ name: string;
38
+ })[];
39
+ actions?: Record<string, CompositeAction>;
40
+ directory?: string;
41
+ check?: boolean;
42
+ }) => Promise<void>;
43
+ //#endregion
44
+ export { getDefaultWorkflow as a, getLintJob as c, getTypecheckJob as d, getWorkflowsVerifyJob as f, getCheckJob as i, getPackageJsonVerifyJob as l, Workflow as m, generateWorkflows as n, getDepsJob as o, CompositeAction as p, DEFAULT_MACHINE as r, getFormatVerifyJob as s, GeneratedWorkflowTypes$1 as t, getSetupAction as u };
@@ -0,0 +1,168 @@
1
+ import { t as GeneratedWorkflowTypes } from "./index-DqMadVlO.mjs";
2
+ import { z } from "zod";
3
+ import { OxlintConfig } from "oxlint";
4
+ import { OxfmtConfig } from "oxfmt";
5
+ import { KnipConfig } from "knip";
6
+ //#region src/oxlint.d.ts
7
+ export declare const disabledRules: OxlintConfig["rules"];
8
+ export declare const overridenRules: OxlintConfig["rules"];
9
+ type MergableConfig$1 = Omit<OxlintConfig, "plugins"> & {
10
+ plugins?: Partial<Record<NonNullable<OxlintConfig["plugins"]>[number], boolean>>;
11
+ };
12
+ type TailwindConfig = {
13
+ entryPoint: string;
14
+ };
15
+ type VitestConfig = {
16
+ files?: string[];
17
+ };
18
+ type TanstackRouterConfig = {
19
+ routes: string[];
20
+ };
21
+ type PackageJsonConfig = boolean;
22
+ type PlaywrightConfig = {
23
+ files: string[];
24
+ assertFunctionNames?: string[];
25
+ };
26
+ type ServerSideConfig = {
27
+ files: string[];
28
+ allowConsole?: string[];
29
+ allowProcess?: string[];
30
+ };
31
+ type RestrictedSyntaxRule = {
32
+ selector: string;
33
+ message: string;
34
+ };
35
+ type RestrictedSyntaxOverride = {
36
+ files: string[];
37
+ rules: RestrictedSyntaxRule[];
38
+ };
39
+ type RestrictedSyntaxConfig = {
40
+ banBarrelImport?: boolean;
41
+ banReactMemo?: boolean;
42
+ overrides?: RestrictedSyntaxOverride[];
43
+ rulesOverrides?: RestrictedSyntaxRule[];
44
+ previousRules?: RestrictedSyntaxRule[];
45
+ previousOverrides?: RestrictedSyntaxOverride[];
46
+ };
47
+ type RestrictedConfig = {
48
+ globals?: {
49
+ name: string;
50
+ message: string;
51
+ }[];
52
+ properties?: {
53
+ object: string;
54
+ property: string;
55
+ message: string;
56
+ }[];
57
+ syntaxOverrides?: RestrictedSyntaxConfig["overrides"];
58
+ syntaxRulesOverrides?: RestrictedSyntaxConfig["rulesOverrides"];
59
+ };
60
+ type ReactConfig = {
61
+ allowedStrings?: string[];
62
+ additionalHooks?: string[];
63
+ banMemo?: boolean;
64
+ };
65
+ type I18nConfig = {
66
+ ignore?: string[] | true;
67
+ };
68
+ type ImportConfig = {
69
+ allowDefault?: string[];
70
+ banBarrel?: boolean;
71
+ };
72
+ type ConfigOptions$2 = {
73
+ jsPlugins?: Exclude<OxlintConfig["jsPlugins"], null>;
74
+ plugins?: MergableConfig$1["plugins"];
75
+ tailwind?: TailwindConfig;
76
+ vitest?: VitestConfig;
77
+ tanstackRouter?: TanstackRouterConfig;
78
+ packageJson?: PackageJsonConfig;
79
+ playwright?: PlaywrightConfig;
80
+ serverSide?: ServerSideConfig;
81
+ restricted?: RestrictedConfig;
82
+ react?: ReactConfig;
83
+ i18n?: I18nConfig;
84
+ import?: ImportConfig;
85
+ } & Pick<OxlintConfig, "env" | "rules" | "options" | "ignorePatterns" | "categories" | "settings" | "overrides" | "globals"> & ReactConfig;
86
+ declare const getConfig$2: ({ tailwind, tanstackRouter, vitest, packageJson, playwright, serverSide, restricted, react, i18n, import: importOptions, ...config }?: ConfigOptions$2) => Promise<OxlintConfig>;
87
+ //#endregion
88
+ //#region src/oxfmt.d.ts
89
+ type ConfigOptions$1 = OxfmtConfig & {
90
+ tailwind?: {
91
+ stylesheet: string;
92
+ functions?: string[];
93
+ };
94
+ imports?: Exclude<OxfmtConfig["sortImports"], boolean>;
95
+ };
96
+ declare const getConfig: ({ ignorePatterns, tailwind, imports, sortImports, ...rest }?: ConfigOptions$1) => Promise<{
97
+ readonly arrowParens?: import("oxfmt").ArrowParensConfig;
98
+ readonly associations?: import("oxfmt").OxfmtAssociationConfig[];
99
+ astro: import("oxfmt").AstroUserConfig;
100
+ readonly bracketSameLine?: boolean;
101
+ readonly bracketSpacing?: boolean;
102
+ readonly embeddedLanguageFormatting?: import("oxfmt").EmbeddedLanguageFormattingConfig;
103
+ readonly endOfLine?: import("oxfmt").EndOfLineConfig;
104
+ readonly experimentalOperatorPosition?: import("oxfmt").OperatorPositionConfig;
105
+ readonly htmlWhitespaceSensitivity?: import("oxfmt").HtmlWhitespaceSensitivityConfig;
106
+ readonly insertFinalNewline?: boolean;
107
+ readonly jsdoc?: import("oxfmt").JsdocUserConfig;
108
+ readonly jsxSingleQuote?: boolean;
109
+ readonly objectWrap?: import("oxfmt").ObjectWrapConfig;
110
+ readonly overrides?: import("oxfmt").OxfmtOverrideConfig[];
111
+ printWidth: number;
112
+ readonly proseWrap?: import("oxfmt").ProseWrapConfig;
113
+ readonly quoteProps?: import("oxfmt").QuotePropsConfig;
114
+ readonly semi?: boolean;
115
+ readonly singleAttributePerLine?: boolean;
116
+ readonly singleQuote?: boolean;
117
+ sortPackageJson: boolean | import("oxfmt").SortPackageJsonConfig | {
118
+ readonly sortScripts: true;
119
+ };
120
+ sortTailwindcss: import("oxfmt").SortTailwindcssUserConfig;
121
+ readonly svelte?: import("oxfmt").SvelteUserConfig;
122
+ readonly tabWidth?: number;
123
+ readonly trailingComma?: import("oxfmt").TrailingCommaConfig;
124
+ useTabs: boolean;
125
+ readonly vueIndentScriptAndStyle?: boolean;
126
+ readonly ignorePatterns: string[];
127
+ readonly sortImports: import("oxfmt").SortImportsUserConfig;
128
+ }>;
129
+ //#endregion
130
+ //#region src/knip.d.ts
131
+ type KnipConfig$1 = Exclude<KnipConfig, Function>;
132
+ type MergableConfig = Omit<KnipConfig$1, "include"> & {
133
+ include?: Partial<Record<NonNullable<KnipConfig$1["include"]>[number], boolean>>;
134
+ };
135
+ type BaseOptions = {
136
+ vitest?: boolean;
137
+ reactNative?: boolean;
138
+ opencode?: boolean;
139
+ eslint?: boolean;
140
+ workspaces?: boolean;
141
+ };
142
+ type ConfigOptions = {
143
+ options?: BaseOptions;
144
+ } & MergableConfig;
145
+ declare const getConfig$1: ({ options, ...overrides }?: ConfigOptions) => Promise<KnipConfig$1>;
146
+ //#endregion
147
+ //#region src/config/schema.d.ts
148
+ export declare const configSchema: z.ZodObject<{
149
+ preCommitCommands: z.ZodOptional<z.ZodArray<z.ZodString>>;
150
+ verify: z.ZodDefault<z.ZodObject<{
151
+ minBunVersion: z.ZodDefault<z.ZodString>;
152
+ minNodeVersion: z.ZodDefault<z.ZodString>;
153
+ scripts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
154
+ }, z.core.$strip>>;
155
+ workflows: z.ZodOptional<z.ZodObject<{
156
+ branch: z.ZodOptional<z.ZodString>;
157
+ jobs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodCustom<GeneratedWorkflowTypes.NormalJob, GeneratedWorkflowTypes.NormalJob>>>;
158
+ workflows: z.ZodOptional<z.ZodArray<z.ZodCustom<Omit<GeneratedWorkflowTypes.Workflow, "name"> & {
159
+ name: string;
160
+ }, Omit<GeneratedWorkflowTypes.Workflow, "name"> & {
161
+ name: string;
162
+ }>>>;
163
+ }, z.core.$strip>>;
164
+ }, z.core.$strip>;
165
+ type ConfigInput = z.input<typeof configSchema>;
166
+ type ConfigOutput = z.output<typeof configSchema>;
167
+ //#endregion
168
+ export { type ConfigInput as Config, type ConfigOutput, getConfig as getFormatConfig, getConfig$1 as getKnipConfig, getConfig$2 as getLintConfig };
package/dist/index.mjs ADDED
@@ -0,0 +1,479 @@
1
+ import { n as baseIgnorePatterns, t as arraify } from "./common-B9SE4GL9.mjs";
2
+ import { t as configSchema } from "./schema-BuCl21uv.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
+ {
335
+ files: ["**/*.config.{j,t}s"],
336
+ rules: {
337
+ "import/no-default-export": "off",
338
+ "import/no-nodejs-modules": "off",
339
+ "node/no-top-level-await": "off"
340
+ }
341
+ },
342
+ {
343
+ files: ["**/*.d.ts"],
344
+ rules: { "typescript/triple-slash-reference": "off" }
345
+ },
346
+ {
347
+ files: ["workflows.config.ts"],
348
+ rules: { "eslint/no-template-curly-in-string": "off" }
349
+ }
350
+ ],
351
+ plugins: {
352
+ eslint: true,
353
+ import: true,
354
+ "jsx-a11y": true,
355
+ node: true,
356
+ oxc: true,
357
+ promise: true,
358
+ react: true,
359
+ "react-perf": true,
360
+ typescript: true,
361
+ unicorn: true
362
+ },
363
+ rules: {
364
+ ...disabledRules,
365
+ ...overridenRules
366
+ }
367
+ });
368
+ const getConfig$2 = async ({ tailwind, tanstackRouter, vitest, packageJson = true, playwright, serverSide, restricted, react, i18n, import: importOptions, ...config } = {}) => {
369
+ const baseConfig = getBaseConfig$1();
370
+ const tailwindConfig = await getTailwindConfig(tailwind);
371
+ const tanstackRouterConfig = await getTanstackRouterConfig(tanstackRouter);
372
+ const vitestConfig = getVitestConfig(vitest);
373
+ const packageJsonConfig = await getPackageJsonConfig(packageJson);
374
+ const playwrightConfig = await getPlaywrightConfig(playwright);
375
+ const serverSideConfig = getServerSideConfig(serverSide);
376
+ const reactConfig = getReactConfig(react);
377
+ const i18nConfig = getI18nConfig(i18n);
378
+ const importConfig = getImportConfig(importOptions);
379
+ const restrictedConfig = getRestrictedConfig(restricted);
380
+ const rawMergedConfig = mergeConfigs$1(baseConfig, vitestConfig, tanstackRouterConfig, packageJsonConfig, playwrightConfig, tailwindConfig, serverSideConfig, restrictedConfig, reactConfig, i18nConfig, importConfig, config);
381
+ const restrictedSyntaxConfig = getRestrictedSyntaxConfig({
382
+ banBarrelImport: importOptions?.banBarrel,
383
+ banReactMemo: react?.banMemo,
384
+ overrides: restricted?.syntaxOverrides,
385
+ previousOverrides: rawMergedConfig.overrides?.map((override) => override.rules?.["eslint-js/no-restricted-syntax"] === void 0 ? void 0 : {
386
+ files: override.files,
387
+ rules: override.rules["eslint-js/no-restricted-syntax"].slice(1)
388
+ }).filter(isNonNullish),
389
+ previousRules: (rawMergedConfig.rules?.["eslint-js/no-restricted-syntax"])?.slice(1),
390
+ rulesOverrides: restricted?.syntaxRulesOverrides
391
+ });
392
+ const { plugins: pluginsRecord = {}, ...mergedConfig } = mergeConfigs$1(rawMergedConfig, restrictedSyntaxConfig);
393
+ return {
394
+ ...mergedConfig,
395
+ plugins: Object.entries(pluginsRecord).filter(([, value]) => value).map(([key]) => key)
396
+ };
397
+ };
398
+ //#endregion
399
+ //#region src/oxfmt.ts
400
+ const getConfig = async ({ ignorePatterns = [], tailwind, imports, sortImports, ...rest } = {}) => ({
401
+ astro: true,
402
+ ignorePatterns: [...baseIgnorePatterns, ...ignorePatterns],
403
+ printWidth: 80,
404
+ sortImports: sortImports ?? (imports ? {
405
+ newlinesBetween: false,
406
+ order: "asc",
407
+ ...imports
408
+ } : true),
409
+ sortPackageJson: { sortScripts: true },
410
+ sortTailwindcss: tailwind ? {
411
+ functions: tailwind.functions,
412
+ stylesheet: tailwind.stylesheet
413
+ } : void 0,
414
+ useTabs: true,
415
+ ...rest
416
+ });
417
+ //#endregion
418
+ //#region src/knip.ts
419
+ 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 }) => ({
420
+ entry: [...arraify(entry), ...arraify(configEntry)],
421
+ ignore: [...arraify(ignore), ...arraify(configIgnore)],
422
+ ignoreDependencies: [...arraify(ignoreDependencies), ...arraify(configIgnoreDependencies)],
423
+ ignoreIssues: {
424
+ ...ignoreIssues,
425
+ ...configIgnoreIssues
426
+ },
427
+ include: {
428
+ ...include,
429
+ ...configInclude
430
+ },
431
+ workspaces: {
432
+ ...mapValues(workspaces, (workspace, key) => ({
433
+ ...workspace,
434
+ ...configWorkspaces[key]
435
+ })),
436
+ ...omitBy(configWorkspaces, (_value, key) => Boolean(workspaces[key]))
437
+ },
438
+ ...rest,
439
+ ...configRest
440
+ }), {});
441
+ const getBaseConfig = ({ opencode = false, reactNative = false, eslint = true, vitest = true, workspaces = false } = {}) => ({
442
+ entry: workspaces ? [] : ["**/*.config.ts"],
443
+ ignore: [process.env.CI ? void 0 : ".history/**", opencode ? ".opencode/**" : void 0].filter(isNonNullish),
444
+ ignoreDependencies: [
445
+ reactNative ? "expo-doctor" : void 0,
446
+ vitest ? "@vitest/coverage-v8" : void 0,
447
+ eslint ? "oxlint-plugin-eslint" : void 0
448
+ ].filter(isNonNullish),
449
+ ignoreIssues: { "**/*.gen.ts": ["types"] },
450
+ include: {
451
+ catalog: true,
452
+ catalogReferences: true,
453
+ cycles: true,
454
+ dependencies: true,
455
+ duplicates: true,
456
+ enumMembers: true,
457
+ exports: true,
458
+ files: true,
459
+ namespaceMembers: true,
460
+ nsExports: true,
461
+ nsTypes: true,
462
+ types: true,
463
+ unlisted: true,
464
+ unresolved: true
465
+ },
466
+ treatConfigHintsAsErrors: true,
467
+ treatTagHintsAsErrors: true,
468
+ workspaces: workspaces ? { ".": { entry: ["**/*.config.ts"] } } : {}
469
+ });
470
+ const getConfig$1 = async ({ options, ...overrides } = {}) => {
471
+ const baseConfig = getBaseConfig(options);
472
+ const { include: includeRecord = {}, ...mergedConfig } = mergeConfigs(baseConfig, overrides);
473
+ return {
474
+ ...mergedConfig,
475
+ include: Object.entries(includeRecord).filter(([, value]) => value).map(([key]) => key)
476
+ };
477
+ };
478
+ //#endregion
479
+ export { configSchema, disabledRules, getConfig as getFormatConfig, getConfig$1 as getKnipConfig, getConfig$2 as getLintConfig, overridenRules };
@@ -0,0 +1,14 @@
1
+ import { r as moduleName } from "./common-B9SE4GL9.mjs";
2
+ import { t as configSchema } from "./schema-BuCl21uv.mjs";
3
+ import { z } from "zod";
4
+ import { cosmiconfig } from "cosmiconfig";
5
+ //#region src/config/parse.ts
6
+ const explorer = cosmiconfig(moduleName);
7
+ const parse = async () => {
8
+ const rawConfig = await explorer.search();
9
+ const parsedConfig = z.safeParse(configSchema, rawConfig?.config ?? {});
10
+ if (!parsedConfig.success) throw new Error(`Validation error: ${parsedConfig.error.message}`);
11
+ return parsedConfig.data;
12
+ };
13
+ //#endregion
14
+ export { parse as t };
@@ -0,0 +1,23 @@
1
+ import { valid } from "semver";
2
+ import { z } from "zod";
3
+ //#region src/config/schema.ts
4
+ const MIN_NODE_VERSION = "26.0.0";
5
+ const MIN_BUN_VERSION = "1.4.4";
6
+ const configSchema = z.object({
7
+ preCommitCommands: z.string().array().optional(),
8
+ verify: z.object({
9
+ minBunVersion: z.string().refine((version) => valid(version)).default(() => MIN_BUN_VERSION),
10
+ minNodeVersion: z.string().refine((version) => valid(version)).default(() => MIN_NODE_VERSION),
11
+ scripts: z.record(z.string(), z.string()).optional()
12
+ }).default(() => ({
13
+ minBunVersion: MIN_BUN_VERSION,
14
+ minNodeVersion: MIN_NODE_VERSION
15
+ })),
16
+ workflows: z.object({
17
+ branch: z.string().optional(),
18
+ jobs: z.record(z.string(), z.custom()).optional(),
19
+ workflows: z.custom().array().optional()
20
+ }).optional()
21
+ });
22
+ //#endregion
23
+ export { configSchema as t };
@@ -0,0 +1,2 @@
1
+ import { a as getDefaultWorkflow, c as getLintJob, d as getTypecheckJob, f as getWorkflowsVerifyJob, i as getCheckJob, l as getPackageJsonVerifyJob, m as Workflow, n as generateWorkflows, o as getDepsJob, p as CompositeAction, r as DEFAULT_MACHINE, s as getFormatVerifyJob, t as GeneratedWorkflowTypes, u as getSetupAction } from "../index-DqMadVlO.mjs";
2
+ export { type CompositeAction, DEFAULT_MACHINE, type GeneratedWorkflowTypes, type Workflow, generateWorkflows, getCheckJob, getDefaultWorkflow, getDepsJob, getFormatVerifyJob, getLintJob, getPackageJsonVerifyJob, getSetupAction, getTypecheckJob, getWorkflowsVerifyJob };
@@ -0,0 +1 @@
1
+ export { n as DEFAULT_MACHINE, t as generateWorkflows, r as getCheckJob, i as getDefaultWorkflow, a as getDepsJob, o as getFormatVerifyJob, s as getLintJob, c as getPackageJsonVerifyJob, l as getSetupAction, u as getTypecheckJob, d as getWorkflowsVerifyJob } from "../generate-BGCgStVl.mjs";
package/package.json CHANGED
@@ -1,6 +1,85 @@
1
1
  {
2
- "name": "@oxiul/configs",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
2
+ "name": "@oxiul/configs",
3
+ "version": "0.4.0",
4
+ "license": "MIT",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/oxiul/configs.git"
8
+ },
9
+ "bin": {
10
+ "oxiul": "./dist/bin.mjs"
11
+ },
12
+ "files": [
13
+ "dist/**",
14
+ "scripts/postinstall.mjs"
15
+ ],
16
+ "type": "module",
17
+ "sideEffects": false,
18
+ "main": "./dist/index.mjs",
19
+ "module": "./dist/index.mjs",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.mts",
23
+ "default": "./dist/index.mjs"
24
+ },
25
+ "./workflows": {
26
+ "types": "./dist/workflows/index.d.mts",
27
+ "default": "./dist/workflows/index.mjs"
28
+ }
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "scripts": {
34
+ "build": "tsdown",
35
+ "changeset": "changeset add",
36
+ "deps": "knip",
37
+ "format": "oxfmt --write",
38
+ "format:verify": "oxfmt --check",
39
+ "lint": "oxlint",
40
+ "lint:fix": "oxlint --fix",
41
+ "oxiul:verify": "bun src/bin.ts verify",
42
+ "postinstall": "node scripts/postinstall.mjs",
43
+ "typecheck": "bun check",
44
+ "workflows": "bun src/bin.ts workflows --verify",
45
+ "workflows:generate": "bun src/bin.ts workflows --generate"
46
+ },
47
+ "dependencies": {
48
+ "@crustjs/core": "^0.5.6",
49
+ "@crustjs/extensions": "^0.5.6",
50
+ "@github-actions-workflow-ts/lib": "^2.6.1",
51
+ "cosmiconfig": "^10.0.1",
52
+ "listr2": "^11.4.0",
53
+ "oxlint-plugin-eslint": "^1.88.0",
54
+ "semver": "^7.8.5",
55
+ "yaml": "^2.9.1",
56
+ "zod": "^4.6.7"
57
+ },
58
+ "devDependencies": {
59
+ "@arethetypeswrong/core": "^0.18.5",
60
+ "@changesets/changelog-github": "^1.0.1",
61
+ "@changesets/cli": "^3.0.3",
62
+ "@tanstack/eslint-plugin-router": "^1.162.0",
63
+ "@types/bun": "1.4.3",
64
+ "@types/semver": "^7.8.0",
65
+ "eslint-plugin-better-tailwindcss": "^4.9.1",
66
+ "eslint-plugin-package-json": "^1.10.1",
67
+ "eslint-plugin-playwright": "^2.12.1",
68
+ "knip": "^6.42.0",
69
+ "oxfmt": "^0.73.0",
70
+ "oxlint": "^1.88.0",
71
+ "oxlint-tsgolint": "^7.0.2004",
72
+ "publint": "^0.3.25",
73
+ "remeda": "^2.52.0",
74
+ "tsdown": "^0.23.1"
75
+ },
76
+ "peerDependencies": {
77
+ "knip": "^6.42.0",
78
+ "oxfmt": "^0.73.0",
79
+ "oxlint": "^1.88.0"
80
+ },
81
+ "engines": {
82
+ "node": "26"
83
+ },
84
+ "packageManager": "bun@1.4.4"
85
+ }
@@ -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);