load-oxfmt-config 0.23.0 → 0.25.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.
Files changed (4) hide show
  1. package/README.md +57 -11
  2. package/dist/index.d.mts +146 -129
  3. package/dist/index.mjs +571 -466
  4. package/package.json +22 -44
package/README.md CHANGED
@@ -1,12 +1,14 @@
1
1
  # load-oxfmt-config
2
2
 
3
- [![CI](https://github.com/ntnyq/load-oxfmt-config/workflows/CI/badge.svg)](https://github.com/ntnyq/load-oxfmt-config/actions)
3
+ [![CI](https://github.com/ntnyq/eslint-plugin-oxfmt/workflows/CI/badge.svg)](https://github.com/ntnyq/eslint-plugin-oxfmt/actions)
4
4
  [![NPM VERSION](https://img.shields.io/npm/v/load-oxfmt-config.svg)](https://www.npmjs.com/package/load-oxfmt-config)
5
5
  [![NPM DOWNLOADS](https://img.shields.io/npm/dy/load-oxfmt-config.svg)](https://www.npmjs.com/package/load-oxfmt-config)
6
- [![LICENSE](https://img.shields.io/github/license/ntnyq/load-oxfmt-config.svg)](https://github.com/ntnyq/load-oxfmt-config/blob/main/LICENSE)
6
+ [![LICENSE](https://img.shields.io/github/license/ntnyq/eslint-plugin-oxfmt.svg)](https://github.com/ntnyq/eslint-plugin-oxfmt/blob/main/LICENSE)
7
7
 
8
8
  > Load and resolve oxfmt configuration files, including explicit JS/TS config paths, and merge supported `.editorconfig` settings for [oxfmt](https://oxc.rs/docs/guide/usage/formatter.html).
9
9
 
10
+ Maintained in the [eslint-plugin-oxfmt monorepo](https://github.com/ntnyq/eslint-plugin-oxfmt). See the root README for development and release instructions.
11
+
10
12
  ## Features
11
13
 
12
14
  - 🔍 **Auto-discovery** - Automatically searches for config files in current and parent directories
@@ -20,18 +22,18 @@
20
22
  ## Install
21
23
 
22
24
  ```shell
23
- npm install load-oxfmt-config
25
+ npm install oxfmt load-oxfmt-config
24
26
  ```
25
27
 
26
28
  ```shell
27
- yarn add load-oxfmt-config
29
+ yarn add oxfmt load-oxfmt-config
28
30
  ```
29
31
 
30
32
  ```shell
31
- pnpm add load-oxfmt-config
33
+ pnpm add oxfmt load-oxfmt-config
32
34
  ```
33
35
 
34
- > `oxfmt` is a peer dependency and should be installed alongside this package.
36
+ > `oxfmt >=0.70.0` is a peer dependency and is installed alongside this package.
35
37
  > Node.js `^22.13.0 || >=24` is supported.
36
38
 
37
39
  ## Usage
@@ -76,6 +78,27 @@ const result = await loadOxfmtConfig({
76
78
  })
77
79
  ```
78
80
 
81
+ ### Resolve EditorConfig for One File
82
+
83
+ Use `loadOxfmtConfigForFile()` when formatting a specific file, especially when
84
+ its oxfmt config and `.editorconfig` live in different directories:
85
+
86
+ ```ts
87
+ import { loadOxfmtConfigForFile } from 'load-oxfmt-config'
88
+
89
+ const result = await loadOxfmtConfigForFile({
90
+ cwd: '/path/to/project',
91
+ filepath: 'packages/app/src/index.ts',
92
+ })
93
+ ```
94
+
95
+ This accepts the same options as `loadOxfmtConfig()`, with `filepath` required.
96
+ EditorConfig sections are matched relative to their own directory and applied
97
+ in source order, including later `[*]` sections. The resulting EditorConfig
98
+ defaults are merged below explicit oxfmt root options. Explicit oxfmt `overrides`
99
+ remain in the returned config and must still be applied by the caller, relative
100
+ to `result.dirname`. Config metadata retains the same meaning as in the static API.
101
+
79
102
  ### Get Config Metadata
80
103
 
81
104
  ```ts
@@ -342,6 +365,16 @@ Whether to use in-memory cache.
342
365
 
343
366
  Whether to include ignore patterns defined in the resolved config file.
344
367
 
368
+ #### `includeDefaultIgnores`
369
+
370
+ - **Type:** `boolean`
371
+ - **Default:** `true`
372
+
373
+ Whether to apply default directories, lockfiles, and ignore files (`.gitignore`,
374
+ Git info exclude, `.prettierignore`, and explicit `ignorePath` files).
375
+ Set to `false` to evaluate only config `ignorePatterns`. This does not disable
376
+ config loading or matching; use the separate config options for that.
377
+
345
378
  #### `loadConfigForIgnorePatterns`
346
379
 
347
380
  - **Type:** `boolean`
@@ -435,7 +468,12 @@ The loader reads the nearest `.editorconfig` file and maps the subset of fields
435
468
  - `insert_final_newline` → `insertFinalNewline`
436
469
  - `quote_type` → `singleQuote`
437
470
 
438
- Only `[*]` is treated as a global section to match oxfmt. Other sections such as `[**]` and `[*.ts]` are converted into returned `overrides` entries.
471
+ In the static API, `[*]` provides root defaults. A `[*]` section after scoped
472
+ sections also generates an override to preserve source order. Other sections
473
+ such as `[**]` and `[*.ts]` are converted into returned `overrides` entries;
474
+ basename patterns such as `*.ts` are normalized to `**/*.ts` to match descendants.
475
+ The per-file API evaluates matching sections directly, without rebasing them to
476
+ the oxfmt config directory.
439
477
 
440
478
  ## Ignore Strategy
441
479
 
@@ -483,7 +521,12 @@ Section-specific `.editorconfig` entries are represented as generated `overrides
483
521
 
484
522
  ## Limitations
485
523
 
486
- `loadOxfmtConfig()` returns a static merged `OxfmtOptions` shape. That means `.editorconfig` support is represented as merged root + overrides config data, not as per-file runtime evaluation. In practice this works well for common root settings and section-based overrides, but it is not a full replacement for oxfmt's own file-by-file config resolution.
524
+ `loadOxfmtConfig()` returns a static merged `OxfmtOptions` shape. Its generated
525
+ EditorConfig globs cannot represent every relationship between config directories,
526
+ particularly an ancestor EditorConfig with a nested oxfmt config. Use
527
+ `loadOxfmtConfigForFile()` to resolve EditorConfig against its original directory
528
+ for a specific target file. Both APIs retain the nearest-file discovery strategy;
529
+ they do not merge multiple EditorConfig files.
487
530
 
488
531
  ## Error Handling
489
532
 
@@ -501,16 +544,19 @@ try {
501
544
 
502
545
  ## Caching Behavior
503
546
 
504
- The caching system maintains two separate caches:
547
+ The caching system maintains bounded caches for:
505
548
 
506
549
  1. **Path Resolution Cache:** Stores resolved config file paths
507
- 2. **Config Content Cache:** Stores parsed configuration objects
550
+ 2. **Config Sources:** Shares parsed oxfmt files and EditorConfig sections between target files
551
+ 3. **Config Results:** Stores merged static or per-file configuration objects
552
+ 4. **EditorConfig Matchers:** Reuses compiled section patterns
508
553
 
509
554
  **Cache keys are based on:**
510
555
 
511
556
  - `cwd` + `configPath` for path resolution
512
557
  - or `dirname(filepath)` + `configPath` when `filepath` is provided and nested lookup is enabled
513
558
  - Resolved oxfmt path and resolved `.editorconfig` path for config content
559
+ - The target file path for per-file results, isolated from static results
514
560
 
515
561
  **Cache invalidation:**
516
562
 
@@ -527,4 +573,4 @@ The caching system maintains two separate caches:
527
573
 
528
574
  ## License
529
575
 
530
- [MIT](./LICENSE) License © 2025-PRESENT [ntnyq](https://github.com/ntnyq)
576
+ [MIT](https://github.com/ntnyq/eslint-plugin-oxfmt/blob/main/LICENSE) License © 2025-PRESENT [ntnyq](https://github.com/ntnyq)
package/dist/index.d.mts CHANGED
@@ -4,13 +4,6 @@ import { FormatConfig } from "oxfmt";
4
4
  * Object-form `.editorconfig` option for fine-grained lookup control.
5
5
  */
6
6
  export interface EditorconfigOption {
7
- /**
8
- * When `true`, only look for `.editorconfig` in the `cwd` directory itself
9
- * (no upward traversal).
10
- *
11
- * @default false
12
- */
13
- onlyCwd?: boolean;
14
7
  /**
15
8
  * Override the directory from which `.editorconfig` resolution starts.
16
9
  *
@@ -20,23 +13,92 @@ export interface EditorconfigOption {
20
13
  * directory, such as each file's directory.
21
14
  */
22
15
  cwd?: string;
16
+ /**
17
+ * When `true`, only look for `.editorconfig` in the `cwd` directory itself
18
+ * (no upward traversal).
19
+ *
20
+ * @default false
21
+ */
22
+ onlyCwd?: boolean;
23
23
  }
24
24
  /**
25
- * Format option override for a single matching rule.
25
+ * Options for resolving whether a single file should be ignored.
26
26
  */
27
- export interface OxfmtConfigOverride {
27
+ export interface IsOxfmtIgnoredOptions {
28
28
  /**
29
- * Glob patterns to match files.
29
+ * File path to test.
30
30
  */
31
- files: string[];
31
+ filepath: string;
32
32
  /**
33
- * Glob patterns to exclude files.
33
+ * Explicit oxfmt config path.
34
+ *
35
+ * When provided, nested config lookup is disabled (same as oxfmt CLI -c).
34
36
  */
35
- excludeFiles?: string[];
37
+ configPath?: string;
36
38
  /**
37
- * Format options to apply.
39
+ * Current working directory.
40
+ *
41
+ * Also the base directory for default `.prettierignore` lookup.
38
42
  */
39
- options?: FormatConfig;
43
+ cwd?: string;
44
+ /**
45
+ * Disable nested config lookup.
46
+ *
47
+ * @default false
48
+ */
49
+ disableNestedConfig?: boolean;
50
+ /**
51
+ * Ignore files to use instead of the default cwd `.prettierignore`.
52
+ *
53
+ * Explicit ignore paths do not replace `.gitignore` or `.git/info/exclude`
54
+ * handling. They can be passed multiple times in CLI style.
55
+ */
56
+ ignorePath?: string | string[];
57
+ /**
58
+ * Whether to include ignore patterns defined in the config file.
59
+ *
60
+ * @default true
61
+ */
62
+ includeConfigIgnorePatterns?: boolean;
63
+ /**
64
+ * Apply default directories, lockfiles, and ignore files independently of config patterns.
65
+ *
66
+ * @default true
67
+ */
68
+ includeDefaultIgnores?: boolean;
69
+ /**
70
+ * Whether to load resolved oxfmt config when evaluating config ignore patterns.
71
+ *
72
+ * When false, only global ignore is applied and config loading is skipped.
73
+ *
74
+ * @default true
75
+ */
76
+ loadConfigForIgnorePatterns?: boolean;
77
+ /**
78
+ * Whether to use in-memory cache.
79
+ *
80
+ * @default true
81
+ */
82
+ useCache?: boolean;
83
+ /**
84
+ * Whether node_modules should be included.
85
+ *
86
+ * @default false
87
+ */
88
+ withNodeModules?: boolean;
89
+ }
90
+ /**
91
+ * Ignore resolution result.
92
+ */
93
+ export interface IsOxfmtIgnoredResult {
94
+ /**
95
+ * Whether the file should be ignored.
96
+ */
97
+ ignored: boolean;
98
+ /**
99
+ * Matched ignore source when `ignored` is true.
100
+ */
101
+ reason?: 'config-ignore-patterns' | 'default-dir' | 'git-info-exclude' | 'gitignore' | 'ignore-path' | 'lockfile' | 'prettierignore';
40
102
  }
41
103
  /**
42
104
  * Options for loading and merging oxfmt configuration.
@@ -50,12 +112,6 @@ export interface LoadOxfmtConfigOptions {
50
112
  * Current working directory.
51
113
  */
52
114
  cwd?: string;
53
- /**
54
- * File path being formatted. When provided (and `configPath` is not set),
55
- * config discovery starts from this file's directory to match oxfmt nested
56
- * config behavior.
57
- */
58
- filepath?: string;
59
115
  /**
60
116
  * Disable nested config lookup.
61
117
  * When true, config discovery is anchored to `cwd` (or explicit `configPath`).
@@ -63,12 +119,6 @@ export interface LoadOxfmtConfigOptions {
63
119
  * @default false
64
120
  */
65
121
  disableNestedConfig?: boolean;
66
- /**
67
- * Whether to use in-memory caches for path resolution and parsed config contents.
68
- *
69
- * @default true
70
- */
71
- useCache?: boolean;
72
122
  /**
73
123
  * Control `.editorconfig` reading.
74
124
  * - `true` (default): read and merge `.editorconfig`, walking up from the config
@@ -79,22 +129,18 @@ export interface LoadOxfmtConfigOptions {
79
129
  * @default true
80
130
  */
81
131
  editorconfig?: boolean | EditorconfigOption;
82
- }
83
- /**
84
- * Final oxfmt options, including config `ignorePatterns` and `overrides`.
85
- */
86
- export interface OxfmtOptions extends FormatConfig {
87
132
  /**
88
- * Ignore files matching these glob patterns.
89
- *
90
- * Patterns use gitignore-style matching rooted at the oxfmt configuration
91
- * directory. Parent-directory (`..`) path segments are rejected.
133
+ * File path being formatted. When provided (and `configPath` is not set),
134
+ * config discovery starts from this file's directory to match oxfmt nested
135
+ * config behavior.
92
136
  */
93
- ignorePatterns?: string[];
137
+ filepath?: string;
94
138
  /**
95
- * Array of format option overrides.
139
+ * Whether to use in-memory caches for path resolution and parsed config contents.
140
+ *
141
+ * @default true
96
142
  */
97
- overrides?: OxfmtConfigOverride[];
143
+ useCache?: boolean;
98
144
  }
99
145
  /**
100
146
  * Result object with metadata about resolved oxfmt config.
@@ -104,87 +150,47 @@ export interface LoadOxfmtConfigResult {
104
150
  * Final merged config from oxfmt and optional `.editorconfig` mapping.
105
151
  */
106
152
  config: OxfmtOptions;
107
- /**
108
- * Absolute path of resolved config file.
109
- */
110
- filepath?: string;
111
153
  /**
112
154
  * Directory of resolved config file.
113
155
  */
114
156
  dirname?: string;
157
+ /**
158
+ * Absolute path of resolved config file.
159
+ */
160
+ filepath?: string;
115
161
  }
116
162
  /**
117
- * Options for resolving whether a single file should be ignored.
163
+ * Format option override for a single matching rule.
118
164
  */
119
- export interface IsOxfmtIgnoredOptions {
120
- /**
121
- * Current working directory.
122
- *
123
- * Also the base directory for default `.prettierignore` lookup.
124
- */
125
- cwd?: string;
126
- /**
127
- * File path to test.
128
- */
129
- filepath: string;
130
- /**
131
- * Explicit oxfmt config path.
132
- *
133
- * When provided, nested config lookup is disabled (same as oxfmt CLI -c).
134
- */
135
- configPath?: string;
136
- /**
137
- * Ignore files to use instead of the default cwd `.prettierignore`.
138
- *
139
- * Explicit ignore paths do not replace `.gitignore` or `.git/info/exclude`
140
- * handling. They can be passed multiple times in CLI style.
141
- */
142
- ignorePath?: string | string[];
143
- /**
144
- * Whether node_modules should be included.
145
- *
146
- * @default false
147
- */
148
- withNodeModules?: boolean;
149
- /**
150
- * Disable nested config lookup.
151
- *
152
- * @default false
153
- */
154
- disableNestedConfig?: boolean;
165
+ export interface OxfmtConfigOverride {
155
166
  /**
156
- * Whether to use in-memory cache.
157
- *
158
- * @default true
167
+ * Glob patterns to match files.
159
168
  */
160
- useCache?: boolean;
169
+ files: string[];
161
170
  /**
162
- * Whether to include ignore patterns defined in the config file.
163
- *
164
- * @default true
171
+ * Glob patterns to exclude files.
165
172
  */
166
- includeConfigIgnorePatterns?: boolean;
173
+ excludeFiles?: string[];
167
174
  /**
168
- * Whether to load resolved oxfmt config when evaluating config ignore patterns.
169
- *
170
- * When false, only global ignore is applied and config loading is skipped.
171
- *
172
- * @default true
175
+ * Format options to apply.
173
176
  */
174
- loadConfigForIgnorePatterns?: boolean;
177
+ options?: FormatConfig;
175
178
  }
176
179
  /**
177
- * Ignore resolution result.
180
+ * Final oxfmt options, including config `ignorePatterns` and `overrides`.
178
181
  */
179
- export interface IsOxfmtIgnoredResult {
182
+ export interface OxfmtOptions extends FormatConfig {
180
183
  /**
181
- * Whether the file should be ignored.
184
+ * Ignore files matching these glob patterns.
185
+ *
186
+ * Patterns use gitignore-style matching rooted at the oxfmt configuration
187
+ * directory. Parent-directory (`..`) path segments are rejected.
182
188
  */
183
- ignored: boolean;
189
+ ignorePatterns?: string[];
184
190
  /**
185
- * Matched ignore source when `ignored` is true.
191
+ * Array of format option overrides.
186
192
  */
187
- reason?: 'default-dir' | 'lockfile' | 'gitignore' | 'git-info-exclude' | 'prettierignore' | 'ignore-path' | 'config-ignore-patterns';
193
+ overrides?: OxfmtConfigOverride[];
188
194
  }
189
195
  //#endregion
190
196
  //#region src/core.d.ts
@@ -203,27 +209,27 @@ export interface IsOxfmtIgnoredResult {
203
209
  * ```
204
210
  */
205
211
  export declare function loadOxfmtConfig(options?: LoadOxfmtConfigOptions): Promise<LoadOxfmtConfigResult>;
206
- //#endregion
207
- //#region src/ignore.d.ts
208
212
  /**
209
- * Resolve whether a file should be ignored using oxfmt-like CLI semantics.
213
+ * Load config with EditorConfig fallbacks resolved for one file.
214
+ * Explicit oxfmt overrides remain unevaluated and retain their config-relative globs.
210
215
  *
211
- * @param options - Ignore resolution options.
212
- * @returns Ignore status with optional reason.
213
- *
214
- * @example
215
- * ```ts
216
- * import { isOxfmtIgnored } from 'load-oxfmt-config'
217
- *
218
- * const result = await isOxfmtIgnored({
219
- * cwd: process.cwd(),
220
- * filepath: 'src/generated/file.ts',
221
- * })
222
- * ```
216
+ * @param options - Loader settings with the target file path.
217
+ * @returns Config with per-file EditorConfig defaults and config metadata.
223
218
  */
224
- export declare function isOxfmtIgnored(options: IsOxfmtIgnoredOptions): Promise<IsOxfmtIgnoredResult>;
219
+ export declare function loadOxfmtConfigForFile(options: LoadOxfmtConfigOptions & {
220
+ filepath: string;
221
+ }): Promise<LoadOxfmtConfigResult>;
225
222
  //#endregion
226
223
  //#region src/config.d.ts
224
+ /**
225
+ * Build a cache key for config content; prefixes missing entries.
226
+ *
227
+ * @param resolvedPath - Resolved oxfmt config path.
228
+ * @param editorconfigPath - Resolved editorconfig path.
229
+ * @param resolveKey - Resolution cache key.
230
+ * @returns Cache key for config content cache.
231
+ */
232
+ export declare function getConfigCacheKey(resolvedPath: string | undefined, editorconfigPath: string | undefined, resolveKey: string): string;
227
233
  /**
228
234
  * Build a cache key for path resolution (cwd + configPath).
229
235
  *
@@ -233,14 +239,16 @@ export declare function isOxfmtIgnored(options: IsOxfmtIgnoredOptions): Promise<
233
239
  */
234
240
  export declare function getResolveCacheKey(cwd: string, configPath?: string): string;
235
241
  /**
236
- * Build a cache key for config content; prefixes missing entries.
242
+ * Read and parse an oxfmt config file.
237
243
  *
238
- * @param resolvedPath - Resolved oxfmt config path.
239
- * @param editorconfigPath - Resolved editorconfig path.
240
- * @param resolveKey - Resolution cache key.
241
- * @returns Cache key for config content cache.
244
+ * @param resolvedPath - Absolute path to config file.
245
+ * @param options - Config loading options.
246
+ * @param options.useCache - Whether to reuse cached config modules.
247
+ * @returns Parsed config object.
242
248
  */
243
- export declare function getConfigCacheKey(resolvedPath: string | undefined, editorconfigPath: string | undefined, resolveKey: string): string;
249
+ export declare function readConfigFromFile(resolvedPath: string, options?: {
250
+ useCache?: boolean;
251
+ }): Promise<OxfmtOptions>;
244
252
  /**
245
253
  * Resolve the oxfmt config file path.
246
254
  *
@@ -260,14 +268,23 @@ export declare function getConfigCacheKey(resolvedPath: string | undefined, edit
260
268
  * ```
261
269
  */
262
270
  export declare function resolveOxfmtrcPath(cwd: string, configPath?: string): Promise<string | undefined>;
271
+ //#endregion
272
+ //#region src/ignore.d.ts
263
273
  /**
264
- * Read and parse an oxfmt config file.
274
+ * Resolve whether a file should be ignored using oxfmt-like CLI semantics.
265
275
  *
266
- * @param resolvedPath - Absolute path to config file.
267
- * @param options - Config loading options.
268
- * @returns Parsed config object.
276
+ * @param options - Ignore resolution options.
277
+ * @returns Ignore status with optional reason.
278
+ *
279
+ * @example
280
+ * ```ts
281
+ * import { isOxfmtIgnored } from 'load-oxfmt-config'
282
+ *
283
+ * const result = await isOxfmtIgnored({
284
+ * cwd: process.cwd(),
285
+ * filepath: 'src/generated/file.ts',
286
+ * })
287
+ * ```
269
288
  */
270
- export declare function readConfigFromFile(resolvedPath: string, options?: {
271
- useCache?: boolean;
272
- }): Promise<OxfmtOptions>;
289
+ export declare function isOxfmtIgnored(options: IsOxfmtIgnoredOptions): Promise<IsOxfmtIgnoredResult>;
273
290
  //#endregion