@venizia/dev-configs 0.3.0 → 0.3.1-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
@@ -6,12 +6,12 @@ it as a dev dependency in an application that wants the same rules.
6
6
  ## Install
7
7
 
8
8
  ```bash
9
- bun add -d @venizia/dev-configs oxlint oxlint-tsgolint oxfmt eslint jiti typescript
9
+ bun add -d @venizia/dev-configs oxlint oxlint-tsgolint oxfmt eslint typescript
10
10
  ```
11
11
 
12
12
  `oxlint` (>=1.88.0), `oxlint-tsgolint` (>=7.0.2004), `oxfmt` (>=0.73.0), `eslint` (9 or 10),
13
- `jiti` (>=2.2), `prettier` (3) and `typescript` (5 or 6) are optional peers. Install only the tools
14
- you use. ESLint loads an `eslint.config.mts` through `jiti`, so a project with one needs it. A
13
+ `prettier` (3) and `typescript` (5 or 6) are optional peers. Install only the tools you use. Keep the
14
+ ESLint config `.mjs`: a TypeScript one (`.mts`) makes ESLint require `jiti`, one more dependency. A
15
15
  project that still runs ESLint and Prettier installs `eslint prettier` and skips the oxc tools.
16
16
 
17
17
  ## Use it
@@ -35,7 +35,7 @@ export default defineConfig(oxfmtConfigs);
35
35
  ```
36
36
 
37
37
  ```typescript
38
- // .configs/eslint.config.mts - the one rule oxlint cannot run yet
38
+ // .configs/eslint.config.mjs - the one rule oxlint cannot run yet
39
39
  import { namingConventionConfigs } from '@venizia/dev-configs/linters';
40
40
 
41
41
  export default namingConventionConfigs;
@@ -43,7 +43,7 @@ export default namingConventionConfigs;
43
43
 
44
44
  ```bash
45
45
  oxlint -c .configs/oxlint.config.mts --deny-warnings
46
- eslint -c .configs/eslint.config.mts .
46
+ eslint -c .configs/eslint.config.mjs .
47
47
  oxfmt -c .configs/oxfmt.config.mts --check "**/*.{ts,tsx,mts,js,mjs}"
48
48
  ```
49
49
 
@@ -58,25 +58,53 @@ there.
58
58
  "outDir": "dist",
59
59
  "rootDir": "src",
60
60
  "experimentalDecorators": true,
61
- "emitDecoratorMetadata": true
61
+ "useDefineForClassFields": false
62
62
  },
63
63
  "include": ["src"]
64
64
  }
65
65
  ```
66
66
 
67
- ## Declare the decorator flag in your own tsconfig
67
+ The two options in `compilerOptions` repeat the base on purpose - see
68
+ [Restate the runtime options](#restate-the-runtime-options-in-your-own-tsconfig).
68
69
 
69
- The base config sets `experimentalDecorators`. But Bun can miss a flag inherited through `extends`
70
- when it runs your source. Parameter decorators are then dropped with no error, and an `@inject`
71
- value is `undefined` at run time.
70
+ ### Browser and React projects
72
71
 
73
- Declare `experimentalDecorators: true` in your application's own `tsconfig.json`, as in the example
74
- earlier. Every IGNIS example does.
72
+ The presets above target a Bun or Node backend. Code that runs in a browser swaps each one for its
73
+ browser version. A React project swaps it for the React version, which builds on the browser one.
74
+
75
+ | Tool | Backend | Browser | React |
76
+ | :--- | :--- | :--- | :--- |
77
+ | oxlint | `oxlintConfigs` | `BrowserOxlintConfigs.create()` | `ReactOxlintConfigs.create()` |
78
+ | oxfmt | `oxfmtConfigs` | `browserOxfmtConfigs` | `browserOxfmtConfigs` |
79
+ | ESLint | `namingConventionConfigs` | `namingConventionConfigs` | `reactNamingConventionConfigs` |
80
+ | tsconfig | `tsconfig.common.json` | `tsconfig.browser.json` | `tsconfig.react.json` |
81
+
82
+ ## Restate the runtime options in your own tsconfig
83
+
84
+ Bun ignores an `extends` that names a package. With `"extends": "@venizia/dev-configs/tsconfig.common.json"`,
85
+ `bun run` and `bun test` see none of the preset's options - even one level deep (measured on Bun 1.4.2).
86
+ Bun then compiles TC39 decorators: a parameter decorator such as `@inject` is dropped with no error,
87
+ and a method decorator such as `@provide` receives the wrong arguments. Class fields get define
88
+ semantics, while the `tsc` build uses assign semantics.
89
+
90
+ `tsc` follows the whole chain, so typecheck and build stay green. Only what Bun runs diverges, which
91
+ is why nothing reports it.
92
+
93
+ In every `tsconfig.json` that Bun runs - an application, a package whose tests run under
94
+ `bun test`, a browser or React project tested with Bun - restate the options that change the emitted
95
+ code:
96
+
97
+ ```json
98
+ "experimentalDecorators": true,
99
+ "useDefineForClassFields": false
100
+ ```
101
+
102
+ Every IGNIS package and example does.
75
103
 
76
104
  | Flag | Base value | Why |
77
105
  | :--- | :--- | :--- |
78
106
  | `experimentalDecorators` | `true` | `@inject`, `@controller`, `@repository` and the other decorators need it |
79
- | `emitDecoratorMetadata` | `true` | Optional. IGNIS reads `design:paramtypes` once, to validate a `@repository` constructor, and skips the check when the metadata is absent |
107
+ | `emitDecoratorMetadata` | `true` | Optional - restate it only if your code reads `design:*` metadata. IGNIS reads `design:paramtypes` once, to validate a `@repository` constructor, and skips the check when the metadata is absent. Under Bun it turns an interface-typed constructor parameter into a runtime import, so import such names with `import type` |
80
108
  | `useDefineForClassFields` | `false` | Class fields are assigned, not defined, so a subclass field initializer does not shadow a value the base constructor set |
81
109
 
82
110
  ## Entry points
@@ -85,10 +113,12 @@ earlier. Every IGNIS example does.
85
113
  | :--- | :--- |
86
114
  | `@venizia/dev-configs` | Everything below, re-exported |
87
115
  | `@venizia/dev-configs/compilers` | `BunCompiler` |
88
- | `@venizia/dev-configs/formatters` | `oxfmtConfigs`, `prettierConfigs` |
89
- | `@venizia/dev-configs/linters` | `oxlintConfigs`, `namingConventionConfigs`, `eslintConfigs`, `ReactEslintConfigs`, the rule classes and their types |
116
+ | `@venizia/dev-configs/formatters` | `oxfmtConfigs`, `browserOxfmtConfigs`, `prettierConfigs` |
117
+ | `@venizia/dev-configs/linters` | `oxlintConfigs`, `BrowserOxlintConfigs`, `ReactOxlintConfigs`, `namingConventionConfigs`, `reactNamingConventionConfigs`, `eslintConfigs`, `ReactEslintConfigs`, the rule classes and their types |
90
118
  | `@venizia/dev-configs/tsconfig.base.json` | Target and lib ES2025, `module` Node16, strict mode with `noImplicitAny`, `strictPropertyInitialization` and `useUnknownInCatchVariables` off, `noEmitOnError`, tests excluded |
91
119
  | `@venizia/dev-configs/tsconfig.common.json` | Extends the base and switches `module` and `moduleResolution` to `nodenext` |
120
+ | `@venizia/dev-configs/tsconfig.browser.json` | Extends the base for a browser library built with a bundler: `module` ESNext, `moduleResolution` bundler, lib ES2025 + `DOM` + `DOM.Iterable`, `types: []` so no Bun types reach `dist` |
121
+ | `@venizia/dev-configs/tsconfig.react.json` | Extends `tsconfig.browser.json` and sets `jsx: react-jsx` |
92
122
 
93
123
  ## What each config sets
94
124
 
@@ -169,6 +199,13 @@ matches. oxfmt differs from Prettier on long union types, which it breaks with a
169
199
  | `bracketSpacing` | `true` |
170
200
  | `arrowParens` | `'avoid'` |
171
201
 
202
+ `browserOxfmtConfigs` is `oxfmtConfigs` with two changes for browser and React code:
203
+
204
+ | Setting | Value | Effect |
205
+ | :--- | :--- | :--- |
206
+ | `arrowParens` | `'always'` | `(x) => x` instead of `x => x` |
207
+ | `bracketSameLine` | `true` | The closing `>` of a multi-line JSX element stays on its last attribute line, which keeps JSX diffs small |
208
+
172
209
  ### eslintConfigs
173
210
 
174
211
  `eslintConfigs` keeps its shape and resolves to the same rules as before, but is now owned here instead
@@ -221,6 +258,21 @@ Rules the automatic JSX runtime or `tsc` already enforce (`react-in-jsx-scope`,
221
258
  - `consistent-type-imports` keeps the default `fixStyle`; a codebase that prefers
222
259
  `inline-type-imports` sets it on top.
223
260
 
261
+ ### BrowserOxlintConfigs
262
+
263
+ `BrowserOxlintConfigs.create()` is `oxlintConfigs` plus `NoRestrictedPropertiesRule.build()`. That
264
+ rule bans `crypto.randomUUID`, which exists only in a secure context (https, localhost). On a
265
+ plain-http origin or in a WebView, the method is `undefined`. Use this preset for browser code that
266
+ does not use React.
267
+
268
+ ```ts
269
+ // .configs/oxlint.config.mts
270
+ import { defineConfig } from 'oxlint';
271
+ import { BrowserOxlintConfigs } from '@venizia/dev-configs/linters';
272
+
273
+ export default defineConfig(BrowserOxlintConfigs.create());
274
+ ```
275
+
224
276
  ### ReactOxlintConfigs and reactNamingConventionConfigs
225
277
 
226
278
  The oxlint version of the React preset. oxlint runs the React, hooks and `jsx-a11y` rules natively, so
@@ -233,16 +285,14 @@ import { ReactOxlintConfigs } from '@venizia/dev-configs/linters';
233
285
 
234
286
  export default defineConfig(ReactOxlintConfigs.create());
235
287
 
236
- // .configs/eslint.config.mts
288
+ // .configs/eslint.config.mjs
237
289
  import { reactNamingConventionConfigs } from '@venizia/dev-configs/linters';
238
290
 
239
291
  export default reactNamingConventionConfigs;
240
292
  ```
241
293
 
242
- `ReactOxlintConfigs.create()` is `oxlintConfigs` plus the same rules as the ESLint table above, as
243
- strict as the base. `react/no-deprecated` is left out: oxlint has no port of it. `crypto.randomUUID`
244
- is banned because it exists only in a secure context (https, localhost), and is `undefined` on a
245
- plain-http origin or in a WebView.
294
+ `ReactOxlintConfigs.create()` is `BrowserOxlintConfigs.create()` plus the same rules as the ESLint
295
+ table above, as strict as the base. `react/no-deprecated` is left out: oxlint has no port of it.
246
296
 
247
297
  The presets start strict. An application that wants less overrides the rule after the preset:
248
298
 
@@ -256,8 +306,7 @@ export default defineConfig({
256
306
  ```
257
307
 
258
308
  `reactNamingConventionConfigs` is `namingConventionConfigs` plus PascalCase functions in `.jsx` and
259
- `.tsx` files. To ban `crypto.randomUUID` in a project without React, add
260
- `[NoRestrictedPropertiesRule.NAME]: NoRestrictedPropertiesRule.build()` to its rules.
309
+ `.tsx` files.
261
310
 
262
311
  ### BunCompiler
263
312
 
@@ -11,4 +11,18 @@ import type { OxfmtConfig } from 'oxfmt';
11
11
  * ```
12
12
  */
13
13
  export declare const oxfmtConfigs: OxfmtConfig;
14
+ /**
15
+ * `oxfmtConfigs` for browser and React code: arrow parameters always in parentheses (`(x) => x`),
16
+ * and the closing `>` of a multi-line JSX element on its last attribute line, which keeps JSX diffs
17
+ * small. `bracketSameLine` changes nothing outside JSX.
18
+ *
19
+ * ```ts
20
+ * // .configs/oxfmt.config.mts
21
+ * import { defineConfig } from 'oxfmt';
22
+ * import { browserOxfmtConfigs } from '@venizia/dev-configs/formatters';
23
+ *
24
+ * export default defineConfig(browserOxfmtConfigs);
25
+ * ```
26
+ */
27
+ export declare const browserOxfmtConfigs: OxfmtConfig;
14
28
  //# sourceMappingURL=oxfmt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"oxfmt.d.ts","sourceRoot":"","sources":["../../src/formatters/oxfmt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEzC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,WAQ1B,CAAC"}
1
+ {"version":3,"file":"oxfmt.d.ts","sourceRoot":"","sources":["../../src/formatters/oxfmt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEzC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAE,WAQ1B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAIjC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.oxfmtConfigs = void 0;
3
+ exports.browserOxfmtConfigs = exports.oxfmtConfigs = void 0;
4
4
  /**
5
5
  * The oxfmt port of `prettierConfigs` - the same seven options, so the output matches Prettier's.
6
6
  *
@@ -21,4 +21,22 @@ exports.oxfmtConfigs = {
21
21
  arrowParens: 'avoid',
22
22
  semi: true,
23
23
  };
24
+ /**
25
+ * `oxfmtConfigs` for browser and React code: arrow parameters always in parentheses (`(x) => x`),
26
+ * and the closing `>` of a multi-line JSX element on its last attribute line, which keeps JSX diffs
27
+ * small. `bracketSameLine` changes nothing outside JSX.
28
+ *
29
+ * ```ts
30
+ * // .configs/oxfmt.config.mts
31
+ * import { defineConfig } from 'oxfmt';
32
+ * import { browserOxfmtConfigs } from '@venizia/dev-configs/formatters';
33
+ *
34
+ * export default defineConfig(browserOxfmtConfigs);
35
+ * ```
36
+ */
37
+ exports.browserOxfmtConfigs = {
38
+ ...exports.oxfmtConfigs,
39
+ arrowParens: 'always',
40
+ bracketSameLine: true,
41
+ };
24
42
  //# sourceMappingURL=oxfmt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"oxfmt.js","sourceRoot":"","sources":["../../src/formatters/oxfmt.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;GAUG;AACU,QAAA,YAAY,GAAgB;IACvC,cAAc,EAAE,IAAI;IACpB,WAAW,EAAE,IAAI;IACjB,UAAU,EAAE,GAAG;IACf,QAAQ,EAAE,CAAC;IACX,aAAa,EAAE,KAAK;IACpB,WAAW,EAAE,OAAO;IACpB,IAAI,EAAE,IAAI;CACX,CAAC"}
1
+ {"version":3,"file":"oxfmt.js","sourceRoot":"","sources":["../../src/formatters/oxfmt.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;GAUG;AACU,QAAA,YAAY,GAAgB;IACvC,cAAc,EAAE,IAAI;IACpB,WAAW,EAAE,IAAI;IACjB,UAAU,EAAE,GAAG;IACf,QAAQ,EAAE,CAAC;IACX,aAAa,EAAE,KAAK;IACpB,WAAW,EAAE,OAAO;IACpB,IAAI,EAAE,IAAI;CACX,CAAC;AAEF;;;;;;;;;;;;GAYG;AACU,QAAA,mBAAmB,GAAgB;IAC9C,GAAG,oBAAY;IACf,WAAW,EAAE,QAAQ;IACrB,eAAe,EAAE,IAAI;CACtB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { OxlintConfig } from 'oxlint';
2
+ /**
3
+ * `oxlintConfigs` for code that runs in a browser, React or not: the base rules plus the
4
+ * secure-context ban (`crypto.randomUUID` is `undefined` on a plain-http origin). Nothing in the base
5
+ * is relaxed. `ReactOxlintConfigs` builds on this preset.
6
+ *
7
+ * ```ts
8
+ * // .configs/oxlint.config.mts
9
+ * import { defineConfig } from 'oxlint';
10
+ * import { BrowserOxlintConfigs } from '@venizia/dev-configs/linters';
11
+ *
12
+ * export default defineConfig(BrowserOxlintConfigs.create());
13
+ * ```
14
+ */
15
+ export declare class BrowserOxlintConfigs {
16
+ static create(): OxlintConfig;
17
+ }
18
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/linters/browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAI3C;;;;;;;;;;;;GAYG;AACH,qBAAa,oBAAoB;IAC/B,MAAM,CAAC,MAAM,IAAI,YAAY;CAS9B"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BrowserOxlintConfigs = void 0;
4
+ const oxlint_1 = require("./oxlint");
5
+ const rules_1 = require("./rules");
6
+ /**
7
+ * `oxlintConfigs` for code that runs in a browser, React or not: the base rules plus the
8
+ * secure-context ban (`crypto.randomUUID` is `undefined` on a plain-http origin). Nothing in the base
9
+ * is relaxed. `ReactOxlintConfigs` builds on this preset.
10
+ *
11
+ * ```ts
12
+ * // .configs/oxlint.config.mts
13
+ * import { defineConfig } from 'oxlint';
14
+ * import { BrowserOxlintConfigs } from '@venizia/dev-configs/linters';
15
+ *
16
+ * export default defineConfig(BrowserOxlintConfigs.create());
17
+ * ```
18
+ */
19
+ class BrowserOxlintConfigs {
20
+ static create() {
21
+ return {
22
+ ...oxlint_1.oxlintConfigs,
23
+ rules: {
24
+ ...oxlint_1.oxlintConfigs.rules,
25
+ [rules_1.NoRestrictedPropertiesRule.NAME]: rules_1.NoRestrictedPropertiesRule.build(),
26
+ },
27
+ };
28
+ }
29
+ }
30
+ exports.BrowserOxlintConfigs = BrowserOxlintConfigs;
31
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/linters/browser.ts"],"names":[],"mappings":";;;AACA,qCAAyC;AACzC,mCAAqD;AAErD;;;;;;;;;;;;GAYG;AACH,MAAa,oBAAoB;IAC/B,MAAM,CAAC,MAAM;QACX,OAAO;YACL,GAAG,sBAAa;YAChB,KAAK,EAAE;gBACL,GAAG,sBAAa,CAAC,KAAK;gBACtB,CAAC,kCAA0B,CAAC,IAAI,CAAC,EAAE,kCAA0B,CAAC,KAAK,EAAE;aACtE;SACF,CAAC;IACJ,CAAC;CACF;AAVD,oDAUC"}
@@ -10,7 +10,7 @@ export declare const eslintConfigs: Linter.Config[];
10
10
  * next to `oxlintConfigs`. It needs no type information, so ESLint stays fast.
11
11
  *
12
12
  * ```js
13
- * // .configs/eslint.config.mts
13
+ * // .configs/eslint.config.mjs
14
14
  * import { namingConventionConfigs } from '@venizia/dev-configs/linters';
15
15
  *
16
16
  * export default namingConventionConfigs;
@@ -131,7 +131,7 @@ exports.eslintConfigs = (0, config_1.defineConfig)([
131
131
  * next to `oxlintConfigs`. It needs no type information, so ESLint stays fast.
132
132
  *
133
133
  * ```js
134
- * // .configs/eslint.config.mts
134
+ * // .configs/eslint.config.mjs
135
135
  * import { namingConventionConfigs } from '@venizia/dev-configs/linters';
136
136
  *
137
137
  * export default namingConventionConfigs;
@@ -1,3 +1,4 @@
1
+ export * from './browser';
1
2
  export * from './eslint';
2
3
  export * from './oxlint';
3
4
  export * from './react';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/linters/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/linters/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
@@ -14,6 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./browser"), exports);
17
18
  __exportStar(require("./eslint"), exports);
18
19
  __exportStar(require("./oxlint"), exports);
19
20
  __exportStar(require("./react"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/linters/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAyB;AACzB,2CAAyB;AACzB,0CAAwB;AACxB,0CAAwB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/linters/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,2CAAyB;AACzB,2CAAyB;AACzB,0CAAwB;AACxB,0CAAwB"}
@@ -31,9 +31,10 @@ export declare class ReactEslintConfigs {
31
31
  }): Linter.Config[];
32
32
  }
33
33
  /**
34
- * The oxlint counterpart of `ReactEslintConfigs`: `oxlintConfigs` plus the React, hooks and
35
- * accessibility rules, `consistent-type-imports`, and the secure-context ban. oxlint runs these
36
- * plugins natively, so nothing is passed in. `react/no-deprecated` has no oxlint port and is left out.
34
+ * The oxlint counterpart of `ReactEslintConfigs`: `BrowserOxlintConfigs` (the base rules plus the
35
+ * secure-context ban) plus the React, hooks and accessibility rules and `consistent-type-imports`.
36
+ * oxlint runs these plugins natively, so nothing is passed in. `react/no-deprecated` has no oxlint
37
+ * port and is left out.
37
38
  *
38
39
  * Nothing in the base is relaxed - frontend code meets the backend's standard - and
39
40
  * `exhaustive-deps` is an error.
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/linters/react.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAM3C,sGAAsG;AACtG,KAAK,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEnD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,YAAY,CAAC;IACpB,UAAU,EAAE,YAAY,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,kBAAkB;IAC7B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,mBAAmB,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE;CA8D9F;AAQD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,kBAAkB;IAC7B,MAAM,CAAC,MAAM,IAAI,YAAY;CAgD9B;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAAC,MAAM,EAYvD,CAAC"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../src/linters/react.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAM3C,sGAAsG;AACtG,KAAK,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEnD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,YAAY,CAAC;IACpB,UAAU,EAAE,YAAY,CAAC;IACzB,OAAO,EAAE,YAAY,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,kBAAkB;IAC7B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,mBAAmB,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE;CA8D9F;AAQD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,kBAAkB;IAC7B,MAAM,CAAC,MAAM,IAAI,YAAY;CAiD9B;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,MAAM,CAAC,MAAM,EAYvD,CAAC"}
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.reactNamingConventionConfigs = exports.ReactOxlintConfigs = exports.ReactEslintConfigs = void 0;
7
7
  const typescript_eslint_1 = __importDefault(require("typescript-eslint"));
8
+ const browser_1 = require("./browser");
8
9
  const eslint_1 = require("./eslint");
9
- const oxlint_1 = require("./oxlint");
10
10
  const rules_1 = require("./rules");
11
11
  /**
12
12
  * The base preset plus what a React frontend needs on top: the React, hooks and accessibility rules.
@@ -92,9 +92,10 @@ const SOURCE_FILES = ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx', '**/*.mts',
92
92
  /** A component is declared as `function App()`, so functions may be PascalCase too. */
93
93
  const COMPONENT_FUNCTION_SELECTOR = { selector: 'function', format: ['camelCase', 'PascalCase'] };
94
94
  /**
95
- * The oxlint counterpart of `ReactEslintConfigs`: `oxlintConfigs` plus the React, hooks and
96
- * accessibility rules, `consistent-type-imports`, and the secure-context ban. oxlint runs these
97
- * plugins natively, so nothing is passed in. `react/no-deprecated` has no oxlint port and is left out.
95
+ * The oxlint counterpart of `ReactEslintConfigs`: `BrowserOxlintConfigs` (the base rules plus the
96
+ * secure-context ban) plus the React, hooks and accessibility rules and `consistent-type-imports`.
97
+ * oxlint runs these plugins natively, so nothing is passed in. `react/no-deprecated` has no oxlint
98
+ * port and is left out.
98
99
  *
99
100
  * Nothing in the base is relaxed - frontend code meets the backend's standard - and
100
101
  * `exhaustive-deps` is an error.
@@ -109,11 +110,12 @@ const COMPONENT_FUNCTION_SELECTOR = { selector: 'function', format: ['camelCase'
109
110
  */
110
111
  class ReactOxlintConfigs {
111
112
  static create() {
113
+ const browserConfigs = browser_1.BrowserOxlintConfigs.create();
112
114
  return {
113
- ...oxlint_1.oxlintConfigs,
114
- plugins: [...new Set([...(oxlint_1.oxlintConfigs.plugins ?? []), 'react', 'jsx-a11y'])],
115
+ ...browserConfigs,
116
+ plugins: [...new Set([...(browserConfigs.plugins ?? []), 'react', 'jsx-a11y'])],
115
117
  overrides: [
116
- ...(oxlint_1.oxlintConfigs.overrides ?? []),
118
+ ...(browserConfigs.overrides ?? []),
117
119
  {
118
120
  files: JSX_FILES,
119
121
  rules: {
@@ -149,7 +151,6 @@ class ReactOxlintConfigs {
149
151
  'react/rules-of-hooks': 'error',
150
152
  'react/exhaustive-deps': 'error',
151
153
  'typescript/consistent-type-imports': ['error', { prefer: 'type-imports' }],
152
- [rules_1.NoRestrictedPropertiesRule.NAME]: rules_1.NoRestrictedPropertiesRule.build(),
153
154
  },
154
155
  },
155
156
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/linters/react.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/linters/react.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@venizia/dev-configs",
3
- "version": "0.3.0",
3
+ "version": "0.3.1-0",
4
4
  "description": "Shareable development configurations for TypeScript projects: oxlint and oxfmt presets with per-rule builders, the ESLint naming-convention rule, the legacy ESLint flat config and Prettier presets, and TypeScript compiler options with critical decorator support (experimentalDecorators, emitDecoratorMetadata, useDefineForClassFields). Single source of truth for consistent code style, type checking, and build settings across monorepo packages.",
5
5
  "keywords": [
6
6
  "build-tools",
@@ -80,6 +80,8 @@
80
80
  },
81
81
  "./tsconfig.base.json": "./src/tsconfig/tsconfig.base.json",
82
82
  "./tsconfig.common.json": "./src/tsconfig/tsconfig.common.json",
83
+ "./tsconfig.browser.json": "./src/tsconfig/tsconfig.browser.json",
84
+ "./tsconfig.react.json": "./src/tsconfig/tsconfig.react.json",
83
85
  "./package.json": "./package.json"
84
86
  },
85
87
  "files": [
@@ -106,7 +108,6 @@
106
108
  },
107
109
  "peerDependencies": {
108
110
  "eslint": "^9.0.0 || ^10.0.0",
109
- "jiti": ">=2.2.0",
110
111
  "oxfmt": ">=0.73.0",
111
112
  "oxlint": ">=1.88.0",
112
113
  "oxlint-tsgolint": ">=7.0.2004",
@@ -117,9 +118,6 @@
117
118
  "eslint": {
118
119
  "optional": true
119
120
  },
120
- "jiti": {
121
- "optional": true
122
- },
123
121
  "oxfmt": {
124
122
  "optional": true
125
123
  },
@@ -139,7 +137,6 @@
139
137
  "devDependencies": {
140
138
  "@types/bun": "^1.4.1",
141
139
  "eslint": "^10.10.0",
142
- "jiti": "^2.7.0",
143
140
  "oxfmt": "0.73.0",
144
141
  "oxlint": "1.88.0",
145
142
  "oxlint-tsgolint": "7.0.2004",
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "http://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.base.json",
4
+ "compilerOptions": {
5
+ /* A browser library: a bundler (Vite, webpack) resolves the imports, the DOM is there, Bun is not */
6
+ "lib": ["ES2025", "DOM", "DOM.Iterable"],
7
+ "types": [],
8
+ "module": "ESNext",
9
+ "moduleResolution": "bundler"
10
+ }
11
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "http://json.schemastore.org/tsconfig",
3
+ "extends": "./tsconfig.browser.json",
4
+ "compilerOptions": {
5
+ "jsx": "react-jsx"
6
+ }
7
+ }