@wtf/project-oxlint 1.0.0 → 1.1.1

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
@@ -5,9 +5,10 @@ suspicious and perf rules as warnings, and `import/no-cycle`, `eqeqeq` and
5
5
  `typescript/no-explicit-any` as errors. It leaves the build and a generated reference in
6
6
  `packages/docs/api` alone. oxlint is a peer dependency.
7
7
 
8
- | Subpath | What you get |
9
- | ---------- | --------------------------------- |
10
- | `./config` | The config, as the default export |
8
+ | Subpath | What you get |
9
+ | ---------- | ------------------------------------------------------------------------------------------------------- |
10
+ | `./config` | The config, as the default export; `oxlintConfig(options)`, the config with options of your own over it |
11
+ | `./schema` | `oxlintSchema`: the Standard Schema of the options of `oxlintConfig()`, which gives their JSON Schema |
11
12
 
12
13
  ```ts
13
14
  // oxlint.config.ts
@@ -17,5 +18,37 @@ import { defineConfig } from 'oxlint'
17
18
  export default defineConfig({ extends: [preset] })
18
19
  ```
19
20
 
21
+ `oxlintConfig(options)` gives the config with your options over it: `categories`, `rules` and
22
+ `env` key by key over the preset's, and any other option, as `plugins` or `ignorePatterns`, in
23
+ place of the preset's.
24
+
20
25
  Run it as `oxlint --deny-warnings`, so a warning fails the lint just as an error does. See the
21
- [presets guide](../docs/guides/presets.md).
26
+ [presets guide](../project-docs/guides/presets.md).
27
+
28
+ ## From the wtf configuration
29
+
30
+ The config reads no file of its own. Keep its options in the `oxlint` section of the repo's `wtf`
31
+ configuration, load it with [`@wtf/project-config`](../project-config/README.md), and spread the
32
+ section in, checked by `oxlintSchema`. oxlint imports `oxlint.config.ts`, so the config may await
33
+ the load, and a `wtf.config.ts` is read too:
34
+
35
+ ```ts
36
+ // oxlint.config.ts
37
+ import { loadConfig } from '@wtf/project-config/node'
38
+ import { sectionOf } from '@wtf/project-config/section'
39
+ import { oxlintConfig } from '@wtf/project-oxlint/config'
40
+ import { oxlintSchema } from '@wtf/project-oxlint/schema'
41
+ import { defineConfig } from 'oxlint'
42
+
43
+ const config = await loadConfig()
44
+ export default defineConfig({
45
+ extends: [oxlintConfig({ ...(await sectionOf(config, 'oxlint', oxlintSchema)) })]
46
+ })
47
+ ```
48
+
49
+ ```json
50
+ { "oxlint": { "rules": { "no-console": "error" }, "ignorePatterns": ["**/dist/**", "site/**"] } }
51
+ ```
52
+
53
+ A key that starts with `//` is a comment, as `"//": "why"`: `oxlintSchema` takes it, at the top of
54
+ the section, and leaves it out of the options it gives.
package/dist/config.d.ts CHANGED
@@ -1,4 +1,22 @@
1
- declare const _default: {
1
+ /**
2
+ * oxlint's shared config, which a repo's oxlint.config.ts extends: the typescript, unicorn and
3
+ * import plugins, correctness as errors, suspicious and perf as warnings, and `import/no-cycle`,
4
+ * `eqeqeq` and `typescript/no-explicit-any` as errors. Run it with `--deny-warnings`.
5
+ *
6
+ * The default export is the preset; {@link oxlintConfig} gives it with options of a repo's own
7
+ * over it, as a section of its configuration spread in (`oxlintSchema` of ./schema).
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ import { type OxlintConfig } from 'oxlint';
12
+ /**
13
+ * What {@link oxlintConfig} takes: any option of oxlint's config. `categories`, `rules` and `env`
14
+ * are laid over the preset's, key by key; each other option, as `plugins` or `ignorePatterns`,
15
+ * replaces the preset's.
16
+ */
17
+ export type OxlintOptions = OxlintConfig;
18
+ /** The preset's own options, which {@link oxlintConfig} lays a repo's over. */
19
+ export declare const OXLINT_DEFAULTS: {
2
20
  plugins: ("unicorn" | "typescript" | "import")[];
3
21
  categories: {
4
22
  correctness: "error";
@@ -22,4 +40,19 @@ declare const _default: {
22
40
  };
23
41
  ignorePatterns: string[];
24
42
  };
43
+ /**
44
+ * The preset with `options` over it: `categories`, `rules` and `env` key by key over the preset's,
45
+ * so a rule given is set and every other kept; and each other option in place of the preset's.
46
+ *
47
+ * ```ts
48
+ * // oxlint.config.ts
49
+ * import { oxlintConfig } from '@wtf/project-oxlint/config'
50
+ * import { defineConfig } from 'oxlint'
51
+ *
52
+ * export default defineConfig({ extends: [oxlintConfig({ rules: { 'no-console': 'error' } })] })
53
+ * ```
54
+ */
55
+ export declare function oxlintConfig(options?: OxlintOptions): OxlintConfig;
56
+ /** The preset, with no options of a repo's own: {@link oxlintConfig} of none. */
57
+ declare const _default: OxlintConfig;
25
58
  export default _default;
package/dist/config.js CHANGED
@@ -3,10 +3,14 @@
3
3
  * import plugins, correctness as errors, suspicious and perf as warnings, and `import/no-cycle`,
4
4
  * `eqeqeq` and `typescript/no-explicit-any` as errors. Run it with `--deny-warnings`.
5
5
  *
6
+ * The default export is the preset; {@link oxlintConfig} gives it with options of a repo's own
7
+ * over it, as a section of its configuration spread in (`oxlintSchema` of ./schema).
8
+ *
6
9
  * @packageDocumentation
7
10
  */
8
11
  import { defineConfig } from 'oxlint';
9
- export default defineConfig({
12
+ /** The preset's own options, which {@link oxlintConfig} lays a repo's over. */
13
+ export const OXLINT_DEFAULTS = {
10
14
  plugins: ['typescript', 'unicorn', 'import'],
11
15
  categories: {
12
16
  correctness: 'error',
@@ -23,5 +27,29 @@ export default defineConfig({
23
27
  },
24
28
  env: { es2025: true, node: true },
25
29
  ignorePatterns: ['**/dist/**', 'packages/docs/api/**']
26
- });
30
+ };
31
+ /**
32
+ * The preset with `options` over it: `categories`, `rules` and `env` key by key over the preset's,
33
+ * so a rule given is set and every other kept; and each other option in place of the preset's.
34
+ *
35
+ * ```ts
36
+ * // oxlint.config.ts
37
+ * import { oxlintConfig } from '@wtf/project-oxlint/config'
38
+ * import { defineConfig } from 'oxlint'
39
+ *
40
+ * export default defineConfig({ extends: [oxlintConfig({ rules: { 'no-console': 'error' } })] })
41
+ * ```
42
+ */
43
+ export function oxlintConfig(options = {}) {
44
+ const { categories, rules, env, ...rest } = options;
45
+ return defineConfig({
46
+ ...OXLINT_DEFAULTS,
47
+ ...rest,
48
+ categories: { ...OXLINT_DEFAULTS.categories, ...categories },
49
+ rules: { ...OXLINT_DEFAULTS.rules, ...rules },
50
+ env: { ...OXLINT_DEFAULTS.env, ...env }
51
+ });
52
+ }
53
+ /** The preset, with no options of a repo's own: {@link oxlintConfig} of none. */
54
+ export default oxlintConfig();
27
55
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AAErC,eAAe,YAAY,CAAC;IAC1B,OAAO,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,QAAQ,CAAC;IAC5C,UAAU,EAAE;QACV,WAAW,EAAE,OAAO;QACpB,UAAU,EAAE,MAAM;QAClB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,KAAK;KACb;IACD,KAAK,EAAE;QACL,iBAAiB,EAAE,OAAO;QAC1B,MAAM,EAAE,OAAO;QACf,4BAA4B,EAAE,OAAO;QACrC,2BAA2B,EAAE,CAAC,OAAO,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;KAC7F;IACD,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;IACjC,cAAc,EAAE,CAAC,YAAY,EAAE,sBAAsB,CAAC;CACvD,CAAC,CAAA","sourcesContent":["/**\n * oxlint's shared config, which a repo's oxlint.config.ts extends: the typescript, unicorn and\n * import plugins, correctness as errors, suspicious and perf as warnings, and `import/no-cycle`,\n * `eqeqeq` and `typescript/no-explicit-any` as errors. Run it with `--deny-warnings`.\n *\n * @packageDocumentation\n */\nimport { defineConfig } from 'oxlint'\n\nexport default defineConfig({\n plugins: ['typescript', 'unicorn', 'import'],\n categories: {\n correctness: 'error',\n suspicious: 'warn',\n pedantic: 'off',\n perf: 'warn',\n style: 'off'\n },\n rules: {\n 'import/no-cycle': 'error',\n eqeqeq: 'error',\n 'typescript/no-explicit-any': 'error',\n 'typescript/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }]\n },\n env: { es2025: true, node: true },\n ignorePatterns: ['**/dist/**', 'packages/docs/api/**']\n})\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAqB,MAAM,QAAQ,CAAA;AASxD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,OAAO,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,QAAQ,CAAC;IAC5C,UAAU,EAAE;QACV,WAAW,EAAE,OAAO;QACpB,UAAU,EAAE,MAAM;QAClB,QAAQ,EAAE,KAAK;QACf,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,KAAK;KACb;IACD,KAAK,EAAE;QACL,iBAAiB,EAAE,OAAO;QAC1B,MAAM,EAAE,OAAO;QACf,4BAA4B,EAAE,OAAO;QACrC,2BAA2B,EAAE,CAAC,OAAO,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;KAC7F;IACD,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;IACjC,cAAc,EAAE,CAAC,YAAY,EAAE,sBAAsB,CAAC;CAChC,CAAA;AAExB;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAAC,UAAyB,EAAE;IACtD,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAA;IACnD,OAAO,YAAY,CAAC;QAClB,GAAG,eAAe;QAClB,GAAG,IAAI;QACP,UAAU,EAAE,EAAE,GAAG,eAAe,CAAC,UAAU,EAAE,GAAG,UAAU,EAAE;QAC5D,KAAK,EAAE,EAAE,GAAG,eAAe,CAAC,KAAK,EAAE,GAAG,KAAK,EAAE;QAC7C,GAAG,EAAE,EAAE,GAAG,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE;KACxC,CAAC,CAAA;AACJ,CAAC;AAED,iFAAiF;AACjF,eAAe,YAAY,EAAE,CAAA","sourcesContent":["/**\n * oxlint's shared config, which a repo's oxlint.config.ts extends: the typescript, unicorn and\n * import plugins, correctness as errors, suspicious and perf as warnings, and `import/no-cycle`,\n * `eqeqeq` and `typescript/no-explicit-any` as errors. Run it with `--deny-warnings`.\n *\n * The default export is the preset; {@link oxlintConfig} gives it with options of a repo's own\n * over it, as a section of its configuration spread in (`oxlintSchema` of ./schema).\n *\n * @packageDocumentation\n */\nimport { defineConfig, type OxlintConfig } from 'oxlint'\n\n/**\n * What {@link oxlintConfig} takes: any option of oxlint's config. `categories`, `rules` and `env`\n * are laid over the preset's, key by key; each other option, as `plugins` or `ignorePatterns`,\n * replaces the preset's.\n */\nexport type OxlintOptions = OxlintConfig\n\n/** The preset's own options, which {@link oxlintConfig} lays a repo's over. */\nexport const OXLINT_DEFAULTS = {\n plugins: ['typescript', 'unicorn', 'import'],\n categories: {\n correctness: 'error',\n suspicious: 'warn',\n pedantic: 'off',\n perf: 'warn',\n style: 'off'\n },\n rules: {\n 'import/no-cycle': 'error',\n eqeqeq: 'error',\n 'typescript/no-explicit-any': 'error',\n 'typescript/no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }]\n },\n env: { es2025: true, node: true },\n ignorePatterns: ['**/dist/**', 'packages/docs/api/**']\n} satisfies OxlintConfig\n\n/**\n * The preset with `options` over it: `categories`, `rules` and `env` key by key over the preset's,\n * so a rule given is set and every other kept; and each other option in place of the preset's.\n *\n * ```ts\n * // oxlint.config.ts\n * import { oxlintConfig } from '@wtf/project-oxlint/config'\n * import { defineConfig } from 'oxlint'\n *\n * export default defineConfig({ extends: [oxlintConfig({ rules: { 'no-console': 'error' } })] })\n * ```\n */\nexport function oxlintConfig(options: OxlintOptions = {}): OxlintConfig {\n const { categories, rules, env, ...rest } = options\n return defineConfig({\n ...OXLINT_DEFAULTS,\n ...rest,\n categories: { ...OXLINT_DEFAULTS.categories, ...categories },\n rules: { ...OXLINT_DEFAULTS.rules, ...rules },\n env: { ...OXLINT_DEFAULTS.env, ...env }\n })\n}\n\n/** The preset, with no options of a repo's own: {@link oxlintConfig} of none. */\nexport default oxlintConfig()\n"]}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * The schema of the options of `oxlintConfig()` of ./config: {@link oxlintSchema}, a Standard
3
+ * Schema that checks them and gives their JSON Schema, so a repo can keep them in its
4
+ * configuration, as the `oxlint` section of `wtf.config.json`, check them, and spread them into
5
+ * `oxlintConfig()`. oxlint imports an oxlint.config.ts, so the config can await the load, of a code
6
+ * config too.
7
+ *
8
+ * ```ts
9
+ * // oxlint.config.ts
10
+ * import { loadConfig } from '@wtf/project-config/node'
11
+ * import { sectionOf } from '@wtf/project-config/section'
12
+ * import { oxlintConfig } from '@wtf/project-oxlint/config'
13
+ * import { oxlintSchema } from '@wtf/project-oxlint/schema'
14
+ * import { defineConfig } from 'oxlint'
15
+ *
16
+ * const config = await loadConfig()
17
+ * export default defineConfig({
18
+ * extends: [oxlintConfig({ ...(await sectionOf(config, 'oxlint', oxlintSchema)) })]
19
+ * })
20
+ * ```
21
+ *
22
+ * @packageDocumentation
23
+ */
24
+ import type { StandardJSONSchemaV1, StandardSchemaV1 } from '@standard-schema/spec';
25
+ import type { OxlintOptions } from './config.ts';
26
+ /**
27
+ * The schema of the options of `oxlintConfig()` of ./config: oxlint's config, of its `plugins`,
28
+ * `categories`, `rules`, `env` and `ignorePatterns` checked, and any other option of oxlint.
29
+ */
30
+ export declare const oxlintSchema: StandardSchemaV1<OxlintOptions> & StandardJSONSchemaV1<OxlintOptions>;
package/dist/schema.js ADDED
@@ -0,0 +1,45 @@
1
+ import { optionsSchema } from "./standard.js";
2
+ /** A rule's or a category's severity, as oxlint takes it. */
3
+ const severity = {
4
+ description: 'a severity: off, warn, error, allow or deny, or 0, 1 or 2',
5
+ anyOf: [{ enum: ['off', 'warn', 'error', 'allow', 'deny'] }, { enum: [0, 1, 2] }]
6
+ };
7
+ /** The JSON Schema of the options of {@link oxlintSchema}: the preset's, and oxlint's own. */
8
+ const json = {
9
+ type: 'object',
10
+ properties: {
11
+ plugins: {
12
+ description: 'The plugins, in place of the preset’s.',
13
+ type: 'array',
14
+ items: { type: 'string' }
15
+ },
16
+ categories: {
17
+ description: 'The severity of each category, over the preset’s.',
18
+ type: 'object',
19
+ additionalProperties: severity
20
+ },
21
+ rules: {
22
+ description: 'Each rule, by its severity or a list of it and its options, over the preset’s.',
23
+ type: 'object',
24
+ additionalProperties: { anyOf: [severity, { type: 'array' }] }
25
+ },
26
+ env: {
27
+ description: 'The environments, each on or off, over the preset’s.',
28
+ type: 'object',
29
+ additionalProperties: { type: 'boolean' }
30
+ },
31
+ ignorePatterns: {
32
+ description: 'The paths left alone, in place of the preset’s.',
33
+ type: 'array',
34
+ items: { type: 'string' }
35
+ }
36
+ },
37
+ // Each other option is oxlint's, which oxlint checks itself.
38
+ additionalProperties: true
39
+ };
40
+ /**
41
+ * The schema of the options of `oxlintConfig()` of ./config: oxlint's config, of its `plugins`,
42
+ * `categories`, `rules`, `env` and `ignorePatterns` checked, and any other option of oxlint.
43
+ */
44
+ export const oxlintSchema = optionsSchema('@wtf/project-oxlint', json);
45
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAmB,aAAa,EAAE,MAAM,eAAe,CAAA;AAE9D,6DAA6D;AAC7D,MAAM,QAAQ,GAAe;IAC3B,WAAW,EAAE,2DAA2D;IACxE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;CAClF,CAAA;AAED,8FAA8F;AAC9F,MAAM,IAAI,GAAe;IACvB,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,OAAO,EAAE;YACP,WAAW,EAAE,wCAAwC;YACrD,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SAC1B;QACD,UAAU,EAAE;YACV,WAAW,EAAE,mDAAmD;YAChE,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,QAAQ;SAC/B;QACD,KAAK,EAAE;YACL,WAAW,EAAE,gFAAgF;YAC7F,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE;SAC/D;QACD,GAAG,EAAE;YACH,WAAW,EAAE,sDAAsD;YACnE,IAAI,EAAE,QAAQ;YACd,oBAAoB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;SAC1C;QACD,cAAc,EAAE;YACd,WAAW,EAAE,iDAAiD;YAC9D,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;SAC1B;KACF;IACD,6DAA6D;IAC7D,oBAAoB,EAAE,IAAI;CAC3B,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GACvB,aAAa,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAA","sourcesContent":["/**\n * The schema of the options of `oxlintConfig()` of ./config: {@link oxlintSchema}, a Standard\n * Schema that checks them and gives their JSON Schema, so a repo can keep them in its\n * configuration, as the `oxlint` section of `wtf.config.json`, check them, and spread them into\n * `oxlintConfig()`. oxlint imports an oxlint.config.ts, so the config can await the load, of a code\n * config too.\n *\n * ```ts\n * // oxlint.config.ts\n * import { loadConfig } from '@wtf/project-config/node'\n * import { sectionOf } from '@wtf/project-config/section'\n * import { oxlintConfig } from '@wtf/project-oxlint/config'\n * import { oxlintSchema } from '@wtf/project-oxlint/schema'\n * import { defineConfig } from 'oxlint'\n *\n * const config = await loadConfig()\n * export default defineConfig({\n * extends: [oxlintConfig({ ...(await sectionOf(config, 'oxlint', oxlintSchema)) })]\n * })\n * ```\n *\n * @packageDocumentation\n */\nimport type { StandardJSONSchemaV1, StandardSchemaV1 } from '@standard-schema/spec'\nimport type { OxlintOptions } from './config.ts'\nimport { type JsonSchema, optionsSchema } from './standard.ts'\n\n/** A rule's or a category's severity, as oxlint takes it. */\nconst severity: JsonSchema = {\n description: 'a severity: off, warn, error, allow or deny, or 0, 1 or 2',\n anyOf: [{ enum: ['off', 'warn', 'error', 'allow', 'deny'] }, { enum: [0, 1, 2] }]\n}\n\n/** The JSON Schema of the options of {@link oxlintSchema}: the preset's, and oxlint's own. */\nconst json: JsonSchema = {\n type: 'object',\n properties: {\n plugins: {\n description: 'The plugins, in place of the preset’s.',\n type: 'array',\n items: { type: 'string' }\n },\n categories: {\n description: 'The severity of each category, over the preset’s.',\n type: 'object',\n additionalProperties: severity\n },\n rules: {\n description: 'Each rule, by its severity or a list of it and its options, over the preset’s.',\n type: 'object',\n additionalProperties: { anyOf: [severity, { type: 'array' }] }\n },\n env: {\n description: 'The environments, each on or off, over the preset’s.',\n type: 'object',\n additionalProperties: { type: 'boolean' }\n },\n ignorePatterns: {\n description: 'The paths left alone, in place of the preset’s.',\n type: 'array',\n items: { type: 'string' }\n }\n },\n // Each other option is oxlint's, which oxlint checks itself.\n additionalProperties: true\n}\n\n/**\n * The schema of the options of `oxlintConfig()` of ./config: oxlint's config, of its `plugins`,\n * `categories`, `rules`, `env` and `ignorePatterns` checked, and any other option of oxlint.\n */\nexport const oxlintSchema: StandardSchemaV1<OxlintOptions> & StandardJSONSchemaV1<OxlintOptions> =\n optionsSchema('@wtf/project-oxlint', json)\n"]}
@@ -0,0 +1,31 @@
1
+ import type { StandardJSONSchemaV1, StandardSchemaV1 } from '@standard-schema/spec';
2
+ /**
3
+ * A JSON Schema of the keywords the check knows: the `type` of a value, its `const` or `enum`, a
4
+ * number's `minimum`, a string's `pattern`, a list's `items`, an object's `properties`,
5
+ * `patternProperties` and `additionalProperties`, and `anyOf`; a `description` says what a value
6
+ * is. A schema of no keyword takes any value, as a function a code config gives.
7
+ */
8
+ export type JsonSchema = {
9
+ readonly type?: string | readonly string[];
10
+ readonly const?: unknown;
11
+ readonly enum?: readonly unknown[];
12
+ readonly minimum?: number;
13
+ readonly pattern?: string;
14
+ readonly items?: JsonSchema;
15
+ readonly properties?: Readonly<Record<string, JsonSchema>>;
16
+ readonly patternProperties?: Readonly<Record<string, JsonSchema>>;
17
+ readonly additionalProperties?: boolean | JsonSchema;
18
+ readonly anyOf?: readonly JsonSchema[];
19
+ readonly description?: string;
20
+ };
21
+ /** The schema of the options `T`: a Standard Schema that checks them, and gives their JSON Schema. */
22
+ export type OptionsSchema<T> = StandardSchemaV1<T> & StandardJSONSchemaV1<T>;
23
+ /**
24
+ * The schema of the options `T` of a preset, `vendor`, of their JSON Schema `json`: it checks a
25
+ * value by the keywords of `json`, as {@link JsonSchema} has them, and gives `json`, of draft
26
+ * 2020-12, as the JSON Schema of its input and of its output alike. A key that starts with `//` is
27
+ * a comment, of the options and of each object in them that takes no key but its `properties`, and
28
+ * the JSON Schema takes it by `patternProperties`: the check takes it, and leaves it out of the
29
+ * value it gives, as it leaves each value else as it is.
30
+ */
31
+ export declare function optionsSchema<T>(vendor: string, json: JsonSchema): OptionsSchema<T>;
@@ -0,0 +1,142 @@
1
+ /** The draft of the JSON Schema an options schema gives. */
2
+ const DRAFT = 'https://json-schema.org/draft/2020-12/schema';
3
+ const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
4
+ /** The pattern of the key of a comment, of `patternProperties`: a key that starts with `//`. */
5
+ const COMMENT = '^//';
6
+ /** Whether `key` is the key of a comment. */
7
+ const isComment = (key) => key.startsWith('//');
8
+ /** Whether `schema` is of an object, of the keys it names or of any. */
9
+ const isObjectSchema = (schema) => schema.properties !== undefined ||
10
+ schema.patternProperties !== undefined ||
11
+ schema.additionalProperties !== undefined;
12
+ /**
13
+ * The schema of the value of `key` of an object of `schema`: of its `properties`, else of the
14
+ * first of its `patternProperties` that `key` matches, else its `additionalProperties`, else any.
15
+ */
16
+ const propertyOf = (schema, key) => schema.properties?.[key] ??
17
+ Object.entries(schema.patternProperties ?? {}).find(([pattern]) => new RegExp(pattern, 'u').test(key))?.[1] ??
18
+ schema.additionalProperties ??
19
+ true;
20
+ /** The type of `value`, as a JSON Schema names it, and `function` of a function. */
21
+ const typeOf = (value) => value === null
22
+ ? 'null'
23
+ : Array.isArray(value)
24
+ ? 'array'
25
+ : Number.isInteger(value)
26
+ ? 'integer'
27
+ : typeof value;
28
+ /** Whether `value` is of one of the `types`: an integer is a number. */
29
+ const isOfType = (value, types) => {
30
+ const type = typeOf(value);
31
+ return [types].flat().some((each) => each === type || (each === 'number' && type === 'integer'));
32
+ };
33
+ /** What is wrong with `value` of `schema`, at `path`. */
34
+ function issuesOf(value, schema, path) {
35
+ const issue = (message) => [{ message, path }];
36
+ if (schema.anyOf !== undefined && !schema.anyOf.some((each) => check(value, each).length === 0))
37
+ return issue(schema.description === undefined ? 'is none of its forms' : `is no ${schema.description}`);
38
+ if ('const' in schema && value !== schema.const)
39
+ return issue(`is not ${JSON.stringify(schema.const)}`);
40
+ if (schema.enum !== undefined && !schema.enum.includes(value))
41
+ return issue(`is none of ${schema.enum.map((each) => JSON.stringify(each)).join(', ')}`);
42
+ if (schema.type !== undefined && !isOfType(value, schema.type))
43
+ return issue(`is no ${[schema.type].flat().join(' or ')}`);
44
+ if (typeof value === 'number' && schema.minimum !== undefined && value < schema.minimum)
45
+ return issue(`is less than ${schema.minimum}`);
46
+ if (typeof value === 'string' &&
47
+ schema.pattern !== undefined &&
48
+ !new RegExp(schema.pattern, 'u').test(value))
49
+ return issue(`does not match ${schema.pattern}`);
50
+ if (Array.isArray(value) && schema.items !== undefined) {
51
+ const items = schema.items;
52
+ return value.flatMap((item, index) => issuesOf(item, items, [...path, index]));
53
+ }
54
+ if (isObject(value) && isObjectSchema(schema))
55
+ return Object.entries(value).flatMap(([key, item]) => {
56
+ const property = propertyOf(schema, key);
57
+ if (property === true)
58
+ return [];
59
+ if (property === false)
60
+ return [{ message: 'is no option it takes', path: [...path, key] }];
61
+ return issuesOf(item, property, [...path, key]);
62
+ });
63
+ return [];
64
+ }
65
+ /** What is wrong with `value` of `schema`, none when it is valid. */
66
+ const check = (value, schema) => issuesOf(value, schema, []);
67
+ /**
68
+ * `schema` with a comment taken by each object of options in it, by `patternProperties` of
69
+ * {@link COMMENT}: the options themselves, at the `top`, whatever keys they take, and each object
70
+ * in them that takes no key but its `properties`. A map, of a schema of `additionalProperties`,
71
+ * takes each key as one of its own.
72
+ */
73
+ function withComments(schema, top) {
74
+ const { properties, items, additionalProperties, anyOf } = schema;
75
+ const takes = top ? isObjectSchema(schema) : additionalProperties === false;
76
+ return {
77
+ ...schema,
78
+ ...(properties !== undefined && {
79
+ properties: Object.fromEntries(Object.entries(properties).map(([key, each]) => [key, withComments(each, false)]))
80
+ }),
81
+ ...(items !== undefined && { items: withComments(items, false) }),
82
+ ...(typeof additionalProperties === 'object' && {
83
+ additionalProperties: withComments(additionalProperties, false)
84
+ }),
85
+ ...(anyOf !== undefined && { anyOf: anyOf.map((each) => withComments(each, top)) }),
86
+ ...(takes && {
87
+ patternProperties: {
88
+ ...schema.patternProperties,
89
+ [COMMENT]: { description: 'A comment, which the options leave out.' }
90
+ }
91
+ })
92
+ };
93
+ }
94
+ /**
95
+ * `value`, valid of `schema`, without its comments: each key of a comment of an object whose schema
96
+ * takes them by {@link COMMENT}, and its `properties` do not name. A value of none is itself.
97
+ */
98
+ function withoutComments(value, schema) {
99
+ const form = schema.anyOf?.find((each) => check(value, each).length === 0);
100
+ const read = form === undefined ? value : withoutComments(value, form);
101
+ const { items } = schema;
102
+ if (Array.isArray(read) && items !== undefined) {
103
+ const each = read.map((item) => withoutComments(item, items));
104
+ return each.every((item, index) => item === read[index]) ? read : each;
105
+ }
106
+ if (!isObject(read) || !isObjectSchema(schema))
107
+ return read;
108
+ const takes = schema.patternProperties?.[COMMENT] !== undefined;
109
+ const entries = Object.entries(read).flatMap(([key, item]) => {
110
+ if (takes && isComment(key) && schema.properties?.[key] === undefined)
111
+ return [];
112
+ const property = propertyOf(schema, key);
113
+ return [[key, typeof property === 'object' ? withoutComments(item, property) : item]];
114
+ });
115
+ const same = entries.length === Object.keys(read).length &&
116
+ entries.every(([key, item]) => item === read[key]);
117
+ return same ? read : Object.fromEntries(entries);
118
+ }
119
+ /**
120
+ * The schema of the options `T` of a preset, `vendor`, of their JSON Schema `json`: it checks a
121
+ * value by the keywords of `json`, as {@link JsonSchema} has them, and gives `json`, of draft
122
+ * 2020-12, as the JSON Schema of its input and of its output alike. A key that starts with `//` is
123
+ * a comment, of the options and of each object in them that takes no key but its `properties`, and
124
+ * the JSON Schema takes it by `patternProperties`: the check takes it, and leaves it out of the
125
+ * value it gives, as it leaves each value else as it is.
126
+ */
127
+ export function optionsSchema(vendor, json) {
128
+ const schema = withComments(json, true);
129
+ const jsonSchema = () => ({ $schema: DRAFT, ...schema });
130
+ return {
131
+ '~standard': {
132
+ version: 1,
133
+ vendor,
134
+ validate: (value) => {
135
+ const issues = check(value, schema);
136
+ return issues.length === 0 ? { value: withoutComments(value, schema) } : { issues };
137
+ },
138
+ jsonSchema: { input: jsonSchema, output: jsonSchema }
139
+ }
140
+ };
141
+ }
142
+ //# sourceMappingURL=standard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard.js","sourceRoot":"","sources":["../src/standard.ts"],"names":[],"mappings":"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","sourcesContent":["// The Standard Schema of a preset's options, of their JSON Schema: `optionsSchema` gives an object\n// of the Standard Schema and Standard JSON Schema interfaces of `@standard-schema/spec`, which checks\n// a value by the keywords of the JSON Schema it is written in, and gives that JSON Schema, so a\n// config of the options can be checked, and an editor completes it. The same file is in each\n// preset, which depends on no package of a schema (test/workspace.test.ts holds the copies alike).\n// A key that starts with `//`, of the options or of an object of options in them, is a comment: the\n// check takes it, and leaves it out of the value it gives.\n// Internal: no export map entry names it.\nimport type { StandardJSONSchemaV1, StandardSchemaV1 } from '@standard-schema/spec'\n\n/**\n * A JSON Schema of the keywords the check knows: the `type` of a value, its `const` or `enum`, a\n * number's `minimum`, a string's `pattern`, a list's `items`, an object's `properties`,\n * `patternProperties` and `additionalProperties`, and `anyOf`; a `description` says what a value\n * is. A schema of no keyword takes any value, as a function a code config gives.\n */\nexport type JsonSchema = {\n readonly type?: string | readonly string[]\n readonly const?: unknown\n readonly enum?: readonly unknown[]\n readonly minimum?: number\n readonly pattern?: string\n readonly items?: JsonSchema\n readonly properties?: Readonly<Record<string, JsonSchema>>\n readonly patternProperties?: Readonly<Record<string, JsonSchema>>\n readonly additionalProperties?: boolean | JsonSchema\n readonly anyOf?: readonly JsonSchema[]\n readonly description?: string\n}\n\n/** The schema of the options `T`: a Standard Schema that checks them, and gives their JSON Schema. */\nexport type OptionsSchema<T> = StandardSchemaV1<T> & StandardJSONSchemaV1<T>\n\n/** The draft of the JSON Schema an options schema gives. */\nconst DRAFT = 'https://json-schema.org/draft/2020-12/schema'\n\ntype Issue = StandardSchemaV1.Issue\ntype Path = readonly PropertyKey[]\n\nconst isObject = (value: unknown): value is Readonly<Record<string, unknown>> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/** The pattern of the key of a comment, of `patternProperties`: a key that starts with `//`. */\nconst COMMENT = '^//'\n\n/** Whether `key` is the key of a comment. */\nconst isComment = (key: string): boolean => key.startsWith('//')\n\n/** Whether `schema` is of an object, of the keys it names or of any. */\nconst isObjectSchema = (schema: JsonSchema): boolean =>\n schema.properties !== undefined ||\n schema.patternProperties !== undefined ||\n schema.additionalProperties !== undefined\n\n/**\n * The schema of the value of `key` of an object of `schema`: of its `properties`, else of the\n * first of its `patternProperties` that `key` matches, else its `additionalProperties`, else any.\n */\nconst propertyOf = (schema: JsonSchema, key: string): JsonSchema | boolean =>\n schema.properties?.[key] ??\n Object.entries(schema.patternProperties ?? {}).find(([pattern]) =>\n new RegExp(pattern, 'u').test(key)\n )?.[1] ??\n schema.additionalProperties ??\n true\n\n/** The type of `value`, as a JSON Schema names it, and `function` of a function. */\nconst typeOf = (value: unknown): string =>\n value === null\n ? 'null'\n : Array.isArray(value)\n ? 'array'\n : Number.isInteger(value)\n ? 'integer'\n : typeof value\n\n/** Whether `value` is of one of the `types`: an integer is a number. */\nconst isOfType = (value: unknown, types: string | readonly string[]): boolean => {\n const type = typeOf(value)\n return [types].flat().some((each) => each === type || (each === 'number' && type === 'integer'))\n}\n\n/** What is wrong with `value` of `schema`, at `path`. */\nfunction issuesOf(value: unknown, schema: JsonSchema, path: Path): Issue[] {\n const issue = (message: string): Issue[] => [{ message, path }]\n if (schema.anyOf !== undefined && !schema.anyOf.some((each) => check(value, each).length === 0))\n return issue(\n schema.description === undefined ? 'is none of its forms' : `is no ${schema.description}`\n )\n if ('const' in schema && value !== schema.const)\n return issue(`is not ${JSON.stringify(schema.const)}`)\n if (schema.enum !== undefined && !schema.enum.includes(value))\n return issue(`is none of ${schema.enum.map((each) => JSON.stringify(each)).join(', ')}`)\n if (schema.type !== undefined && !isOfType(value, schema.type))\n return issue(`is no ${[schema.type].flat().join(' or ')}`)\n if (typeof value === 'number' && schema.minimum !== undefined && value < schema.minimum)\n return issue(`is less than ${schema.minimum}`)\n if (\n typeof value === 'string' &&\n schema.pattern !== undefined &&\n !new RegExp(schema.pattern, 'u').test(value)\n )\n return issue(`does not match ${schema.pattern}`)\n if (Array.isArray(value) && schema.items !== undefined) {\n const items = schema.items\n return value.flatMap((item: unknown, index) => issuesOf(item, items, [...path, index]))\n }\n if (isObject(value) && isObjectSchema(schema))\n return Object.entries(value).flatMap(([key, item]) => {\n const property = propertyOf(schema, key)\n if (property === true) return []\n if (property === false) return [{ message: 'is no option it takes', path: [...path, key] }]\n return issuesOf(item, property, [...path, key])\n })\n return []\n}\n\n/** What is wrong with `value` of `schema`, none when it is valid. */\nconst check = (value: unknown, schema: JsonSchema): Issue[] => issuesOf(value, schema, [])\n\n/**\n * `schema` with a comment taken by each object of options in it, by `patternProperties` of\n * {@link COMMENT}: the options themselves, at the `top`, whatever keys they take, and each object\n * in them that takes no key but its `properties`. A map, of a schema of `additionalProperties`,\n * takes each key as one of its own.\n */\nfunction withComments(schema: JsonSchema, top: boolean): JsonSchema {\n const { properties, items, additionalProperties, anyOf } = schema\n const takes = top ? isObjectSchema(schema) : additionalProperties === false\n return {\n ...schema,\n ...(properties !== undefined && {\n properties: Object.fromEntries(\n Object.entries(properties).map(([key, each]) => [key, withComments(each, false)])\n )\n }),\n ...(items !== undefined && { items: withComments(items, false) }),\n ...(typeof additionalProperties === 'object' && {\n additionalProperties: withComments(additionalProperties, false)\n }),\n ...(anyOf !== undefined && { anyOf: anyOf.map((each) => withComments(each, top)) }),\n ...(takes && {\n patternProperties: {\n ...schema.patternProperties,\n [COMMENT]: { description: 'A comment, which the options leave out.' }\n }\n })\n }\n}\n\n/**\n * `value`, valid of `schema`, without its comments: each key of a comment of an object whose schema\n * takes them by {@link COMMENT}, and its `properties` do not name. A value of none is itself.\n */\nfunction withoutComments(value: unknown, schema: JsonSchema): unknown {\n const form = schema.anyOf?.find((each) => check(value, each).length === 0)\n const read = form === undefined ? value : withoutComments(value, form)\n const { items } = schema\n if (Array.isArray(read) && items !== undefined) {\n const each = read.map((item: unknown) => withoutComments(item, items))\n return each.every((item, index) => item === read[index]) ? read : each\n }\n if (!isObject(read) || !isObjectSchema(schema)) return read\n const takes = schema.patternProperties?.[COMMENT] !== undefined\n const entries = Object.entries(read).flatMap(([key, item]): [string, unknown][] => {\n if (takes && isComment(key) && schema.properties?.[key] === undefined) return []\n const property = propertyOf(schema, key)\n return [[key, typeof property === 'object' ? withoutComments(item, property) : item]]\n })\n const same =\n entries.length === Object.keys(read).length &&\n entries.every(([key, item]) => item === read[key])\n return same ? read : Object.fromEntries(entries)\n}\n\n/**\n * The schema of the options `T` of a preset, `vendor`, of their JSON Schema `json`: it checks a\n * value by the keywords of `json`, as {@link JsonSchema} has them, and gives `json`, of draft\n * 2020-12, as the JSON Schema of its input and of its output alike. A key that starts with `//` is\n * a comment, of the options and of each object in them that takes no key but its `properties`, and\n * the JSON Schema takes it by `patternProperties`: the check takes it, and leaves it out of the\n * value it gives, as it leaves each value else as it is.\n */\nexport function optionsSchema<T>(vendor: string, json: JsonSchema): OptionsSchema<T> {\n const schema = withComments(json, true)\n const jsonSchema = (): Record<string, unknown> => ({ $schema: DRAFT, ...schema })\n return {\n '~standard': {\n version: 1,\n vendor,\n validate: (value) => {\n const issues = check(value, schema)\n return issues.length === 0 ? { value: withoutComments(value, schema) as T } : { issues }\n },\n jsonSchema: { input: jsonSchema, output: jsonSchema }\n }\n }\n}\n"]}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@wtf/project-oxlint",
3
- "version": "1.0.0",
4
- "description": "The shared oxlint config (./config): the typescript, unicorn and import plugins, correctness rules as errors, suspicious and perf rules as warnings, and import cycles, loose equality and explicit any as errors.",
5
- "homepage": "https://gitlab.com/wetryfun/project/project/-/tree/main/packages/oxlint",
3
+ "version": "1.1.1",
4
+ "description": "The shared oxlint config (./config): the typescript, unicorn and import plugins, correctness rules as errors, suspicious and perf rules as warnings, and import cycles, loose equality and explicit any as errors. oxlintConfig(options) gives it with a repo's options over it; the schema of those (./schema), oxlintSchema, a Standard Schema that gives their JSON Schema, checks the oxlint section of a repo's configuration before it spreads it in.",
5
+ "homepage": "https://gitlab.com/wetryfun/project/project/-/tree/main/packages/project-oxlint",
6
6
  "bugs": {
7
7
  "url": "https://gitlab.com/wetryfun/project/project/-/issues"
8
8
  },
@@ -11,7 +11,7 @@
11
11
  "repository": {
12
12
  "type": "git",
13
13
  "url": "git+https://gitlab.com/wetryfun/project/project.git",
14
- "directory": "packages/oxlint"
14
+ "directory": "packages/project-oxlint"
15
15
  },
16
16
  "files": [
17
17
  "dist"
@@ -21,6 +21,10 @@
21
21
  "./config": {
22
22
  "types": "./dist/config.d.ts",
23
23
  "default": "./dist/config.js"
24
+ },
25
+ "./schema": {
26
+ "types": "./dist/schema.d.ts",
27
+ "default": "./dist/schema.js"
24
28
  }
25
29
  },
26
30
  "publishConfig": {
@@ -29,6 +33,9 @@
29
33
  "scripts": {
30
34
  "build": "tsc -b"
31
35
  },
36
+ "dependencies": {
37
+ "@standard-schema/spec": "^1.1.0"
38
+ },
32
39
  "peerDependencies": {
33
40
  "oxlint": "^1.0.0"
34
41
  },