@w5s/dev 3.3.2 → 3.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/dist/index.cjs CHANGED
@@ -1,54 +1,73 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region src/ESLintConfig.ts
3
- function toArray(value) {
4
- if (value == null) return [];
5
- if (Array.isArray(value)) return value;
6
- return [value];
7
- }
8
- function concatArray(left, right) {
9
- return [...toArray(left), ...toArray(right)];
3
+ /**
4
+ * Return a new merged flat configuration
5
+ *
6
+ * @param configs
7
+ */
8
+ function merge(...configs) {
9
+ const keys = new Set(configs.flatMap((i) => Object.keys(i)));
10
+ const merged = configs.reduce((acc, cur) => {
11
+ return {
12
+ ...acc,
13
+ ...cur,
14
+ files: [...acc.files ?? [], ...cur.files ?? []],
15
+ ignores: [...acc.ignores ?? [], ...cur.ignores ?? []],
16
+ plugins: {
17
+ ...acc.plugins,
18
+ ...cur.plugins
19
+ },
20
+ rules: {
21
+ ...acc.rules,
22
+ ...cur.rules
23
+ },
24
+ languageOptions: {
25
+ ...acc.languageOptions,
26
+ ...cur.languageOptions
27
+ },
28
+ linterOptions: {
29
+ ...acc.linterOptions,
30
+ ...cur.linterOptions
31
+ }
32
+ };
33
+ }, {});
34
+ for (const key of Object.keys(merged)) if (!keys.has(key)) delete merged[key];
35
+ return merged;
10
36
  }
11
37
  /**
38
+ * Concat multiple flat configs into a single flat config array.
39
+ *
40
+ * It also resolves promises and flattens the result.
12
41
  *
42
+ * @example
43
+ *
44
+ * ```ts
45
+ * import eslint from '@eslint/js'
46
+ *
47
+ * export default ESLintConfig.concat(
48
+ * {
49
+ * plugins: {},
50
+ * rules: {},
51
+ * },
52
+ * // It can also takes a array of configs:
53
+ * [
54
+ * {
55
+ * plugins: {},
56
+ * rules: {},
57
+ * }
58
+ * // ...
59
+ * ],
60
+ * // Or promises:
61
+ * Promise.resolve({
62
+ * files: ['*.ts'],
63
+ * rules: {},
64
+ * })
65
+ * );
66
+ * ```
13
67
  * @param configs
14
68
  */
15
- function concat(...configs) {
16
- return configs.reduce((returnValue, config) => ({
17
- ...returnValue,
18
- ...config,
19
- env: {
20
- ...returnValue.env,
21
- ...config.env
22
- },
23
- extends: concatArray(returnValue.extends, config.extends),
24
- globals: {
25
- ...returnValue.globals,
26
- ...config.globals
27
- },
28
- overrides: concatArray(returnValue.overrides, config.overrides),
29
- parserOptions: {
30
- ...returnValue.parserOptions,
31
- ...config.parserOptions
32
- },
33
- plugins: concatArray(returnValue.plugins, config.plugins),
34
- rules: {
35
- ...returnValue.rules,
36
- ...config.rules
37
- },
38
- settings: {
39
- ...returnValue.settings,
40
- ...config.settings
41
- }
42
- }), {
43
- env: {},
44
- extends: [],
45
- globals: {},
46
- overrides: [],
47
- parserOptions: {},
48
- plugins: [],
49
- rules: {},
50
- settings: {}
51
- });
69
+ async function concat(...configs) {
70
+ return (await Promise.all(configs)).flat();
52
71
  }
53
72
  /**
54
73
  * Always return 'off'. `_status` is the previous rule value.
@@ -79,6 +98,7 @@ function renameRules(rules, map) {
79
98
  * @namespace
80
99
  */
81
100
  const ESLintConfig = Object.freeze({
101
+ merge,
82
102
  concat,
83
103
  fixme,
84
104
  renameRules
@@ -93,7 +113,7 @@ function interopDefault(m) {
93
113
  //#region src/meta.ts
94
114
  const meta = Object.freeze({
95
115
  name: "@w5s/dev",
96
- version: "3.3.2",
116
+ version: "3.4.0",
97
117
  buildNumber: 1
98
118
  });
99
119
  //#endregion
@@ -232,6 +252,7 @@ function ignored() {
232
252
  function extensionsToMatcher(extensions) {
233
253
  return new RegExp(`(${extensions.map(escapeRegExp).join("|")})$`);
234
254
  }
255
+ const reExtension = /^\./;
235
256
  /**
236
257
  * Return a glob matcher that will match any list of extensions
237
258
  *
@@ -242,7 +263,7 @@ function extensionsToMatcher(extensions) {
242
263
  * ```
243
264
  */
244
265
  function extensionsToGlob(extensions) {
245
- return `*.+(${extensions.map((_) => _.replace(/^\./, "")).join("|")})`;
266
+ return `*.+(${extensions.map((_) => _.replace(reExtension, "")).join("|")})`;
246
267
  }
247
268
  const Project = Object.freeze({
248
269
  ecmaVersion,
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/ESLintConfig.ts","../src/interopDefault.ts","../src/meta.ts","../src/Project.ts","../src/ProjectScript.ts"],"sourcesContent":["import type { ESLint } from 'eslint';\n\nfunction toArray<T>(value: T[] | T | undefined): T[] {\n if (value == null) {\n return [];\n }\n if (Array.isArray(value)) {\n return value;\n }\n return [value];\n}\n\nfunction concatArray<T>(left: T[] | T | undefined, right: T[] | T | undefined): T[] {\n return [...toArray(left), ...toArray(right)];\n}\n\n/**\n *\n * @param configs\n */\nfunction concat(...configs: ESLint.ConfigData[]): ESLint.ConfigData {\n return configs.reduce(\n (returnValue, config) => ({\n ...returnValue,\n ...config,\n env: { ...returnValue.env, ...config.env },\n extends: concatArray(returnValue.extends, config.extends),\n globals: { ...returnValue.globals, ...config.globals },\n overrides: concatArray(returnValue.overrides, config.overrides),\n parserOptions: { ...returnValue.parserOptions, ...config.parserOptions },\n plugins: concatArray(returnValue.plugins, config.plugins),\n rules: { ...returnValue.rules, ...config.rules },\n settings: { ...returnValue.settings, ...config.settings },\n }),\n {\n env: {},\n extends: [],\n globals: {},\n overrides: [],\n parserOptions: {},\n plugins: [],\n rules: {},\n settings: {},\n },\n );\n}\n\n/**\n * Always return 'off'. `_status` is the previous rule value.\n *\n * @param _status\n */\nfunction fixme(_status: string | number | [string | number, ...any[]] | undefined) {\n return 'off' as const;\n}\n\n/**\n * Renames rules in the given object according to the given map.\n *\n * Given a map `{ 'old-prefix': 'new-prefix' }`, and a rule object\n * `{ 'old-prefix/rule-name': 'error' }`, this function will return\n * `{ 'new-prefix/rule-name': 'error' }`.\n *\n * @param rules The object containing the rules to rename.\n * @param map The object containing the rename map.\n */\nfunction renameRules(rules: Record<string, any>, map: Record<string, string>): Record<string, any> {\n return Object.fromEntries(\n Object.entries(rules).map(([key, value]) => {\n for (const [from, to] of Object.entries(map)) {\n if (key.startsWith(`${from}/`)) return [to + key.slice(from.length), value];\n else if (from === '' && !key.includes('/') && to !== '') return [to + key, value];\n }\n return [key, value];\n }),\n );\n}\n\n/**\n * @namespace\n */\nexport const ESLintConfig = Object.freeze({\n concat,\n fixme,\n renameRules,\n});\n","const getDefaultOrElse = (_: any) => _?.default ?? _;\n\n/**\n * Resolves a module or promise-like object, returning the default export if available.\n *\n * @example\n * ```ts\n * // modules.ts\n * export default {\n * foo: true\n * };\n * // Async API\n * const modPromise = import('./module');\n * interopDefault(modPromise); // == Promise.resolve({ foo: true })\n * // Sync API\n * const mod = await import('./module');\n * interopDefault(mod); // == { foo: true }\n * ```\n *\n * @template T - The type of the module or promise-like object.\n * @param m The module or promise-like object to resolve.\n */\nexport function interopDefault<T>(m: PromiseLike<T>): Promise<T extends { default: infer U } ? U : T>;\nexport function interopDefault<T>(m: T): T extends { default: infer U } ? U : T;\nexport function interopDefault<T>(m: T | PromiseLike<T>): Promise<T extends { default: infer U } ? U : T> {\n // @ts-ignore We know what we are doing\n return m != null && typeof m.then === 'function' ? Promise.resolve(m).then(getDefaultOrElse) : getDefaultOrElse(m);\n}\n","export const meta = Object.freeze({\n // @ts-ignore - these variables are injected at build time\n name: (typeof __PACKAGE_NAME__ === 'undefined' ? '' : __PACKAGE_NAME__) as string,\n // @ts-ignore - these variables are injected at build time\n version: (typeof __PACKAGE_VERSION__ === 'undefined' ? '' : __PACKAGE_VERSION__) as string,\n // @ts-ignore - these variables are injected at build time\n buildNumber: 1 as number, // (typeof __PACKAGE_BUILD_NUMBER__ === 'undefined' ? 0 : __PACKAGE_BUILD_NUMBER__) as number,\n});\n","import type { LanguageId } from './LanguageId.js';\n\n/**\n * A type of a file extension\n */\nexport type Extension = `.${string}`;\n\n/**\n * Object hash of all well-known file extension category to file extensions mapping\n */\nexport type ExtensionRegistry = { [K in LanguageId]: readonly Extension[] };\n\nfunction escapeRegExp(value: string) {\n // eslint-disable-next-line unicorn/prefer-string-raw\n return value.replaceAll(/[$()*+.?[\\\\\\]^{|}]/g, '\\\\$&'); // $& means the whole matched string\n}\n\n/**\n * Supported ECMA version\n *\n * @example\n * ```ts\n * Project.ecmaVersion() // 2022\n * ```\n */\nfunction ecmaVersion() {\n return 2022 as const;\n}\n\nconst registry: ExtensionRegistry = {\n css: ['.css'],\n graphql: ['.gql', '.graphql'],\n javascript: ['.js', '.cjs', '.mjs'],\n javascriptreact: ['.jsx'],\n jpeg: ['.jpg', '.jpeg'],\n json: ['.json'],\n jsonc: ['.jsonc'],\n less: ['.less'],\n markdown: ['.markdown', '.mdown', '.mkd', '.md'],\n sass: ['.sass'],\n scss: ['.scss'],\n typescript: ['.ts', '.cts', '.mts'],\n typescriptreact: ['.tsx'],\n vue: ['.vue'],\n yaml: ['.yaml', '.yml'],\n};\n\n/**\n * Return a list of extensions\n *\n * @example\n * ```ts\n * Project.queryExtensions(['javascript']); // ['.js', '.cjs', ...]\n * Project.queryExtensions(['typescript', 'typescriptreact']); // ['.ts', '.mts', ..., '.tsx']\n * ```\n *\n * @param languages\n */\nfunction queryExtensions(languages: LanguageId[]): readonly Extension[] {\n return languages\n .reduce<Extension[]>((previousValue, currentValue) =>\n // eslint-disable-next-line unicorn/prefer-spread\n previousValue.concat(registry[currentValue] ?? ([] as Extension[])), [])\n // eslint-disable-next-line unicorn/no-array-sort\n .sort();\n}\n\n/**\n * Supported file extensions\n *\n * @example\n * ```ts\n * Project.sourceExtensions() // ['.ts', '.js', ...]\n * ```\n */\nfunction sourceExtensions() {\n return queryExtensions(['javascript', 'javascriptreact', 'typescript', 'typescriptreact']);\n}\n\nconst RESOURCE_EXTENSIONS: readonly Extension[] = Object.freeze([\n '.gif',\n '.png',\n '.svg',\n ...queryExtensions(['css', 'graphql', 'jpeg', 'less', 'sass', 'sass', 'yaml']),\n]);\n\n/**\n * Resource file extensions\n *\n * @example\n * ```ts\n * Project.resourceExtensions() // ['.css', '.sass', ...]\n * ```\n */\nfunction resourceExtensions() {\n return RESOURCE_EXTENSIONS;\n}\n\nconst IGNORED = Object.freeze([\n 'node_modules/',\n 'build/',\n 'cjs/',\n 'coverage/',\n 'dist/',\n 'dts/',\n 'esm/',\n 'lib/',\n 'mjs/',\n 'umd/',\n]);\n\n/**\n * Files and folders to always ignore\n *\n * @example\n * ```ts\n * IGNORED // ['node_modules/', 'build/', ...]\n * ```\n */\nfunction ignored() {\n return IGNORED;\n}\n\n/**\n * Return a RegExp that will match any list of extensions\n *\n * @param extensions\n * @example\n * ```ts\n * Project.extensionsToMatcher(['.js', '.ts']) // RegExp = /(\\.js|\\.ts)$/\n * ```\n */\nfunction extensionsToMatcher(extensions: readonly Extension[]): RegExp {\n return new RegExp(`(${extensions.map(escapeRegExp).join('|')})$`);\n}\n\n/**\n * Return a glob matcher that will match any list of extensions\n *\n * @param extensions\n * @example\n * ```ts\n * Project.extensionsToGlob(['.js', '.ts']) // '*.+(js|ts)'\n * ```\n */\nfunction extensionsToGlob(extensions: readonly Extension[]): string {\n return `*.+(${extensions.map((_) => _.replace(/^\\./, '')).join('|')})`;\n}\n\nexport const Project = Object.freeze({\n ecmaVersion,\n extensionsToGlob,\n extensionsToMatcher,\n ignored,\n queryExtensions,\n resourceExtensions,\n sourceExtensions,\n});\n","/**\n * Project common scripts\n */\nexport const ProjectScript = {\n Build: 'build',\n Clean: 'clean',\n CodeAnalysis: 'code-analysis',\n Coverage: 'coverage',\n Develop: 'develop',\n Docs: 'docs',\n Format: 'format',\n Install: 'install',\n Lint: 'lint',\n Prepare: 'prepare',\n Release: 'release',\n Rescue: 'rescue',\n Spellcheck: 'spellcheck',\n Test: 'test',\n Typecheck: 'typecheck',\n Validate: 'validate',\n} as const;\nexport type ProjectScript = (typeof ProjectScript)[keyof typeof ProjectScript];\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/ESLintConfig.ts","../src/interopDefault.ts","../src/meta.ts","../src/Project.ts","../src/ProjectScript.ts"],"sourcesContent":["import type { Linter } from 'eslint';\n\n/**\n * Return a new merged flat configuration\n *\n * @param configs\n */\nfunction merge<T extends Linter.Config = Linter.Config>(...configs: Array<T>): T {\n const keys = new Set(configs.flatMap((i) => Object.keys(i)));\n const merged = configs.reduce((acc, cur) => {\n return {\n ...acc,\n ...cur,\n files: [\n ...(acc.files ?? []),\n ...(cur.files ?? []),\n ],\n ignores: [\n ...(acc.ignores ?? []),\n ...(cur.ignores ?? []),\n ],\n plugins: {\n ...acc.plugins,\n ...cur.plugins,\n },\n rules: {\n ...acc.rules,\n ...cur.rules,\n },\n languageOptions: {\n ...acc.languageOptions,\n ...cur.languageOptions,\n },\n linterOptions: {\n ...acc.linterOptions,\n ...cur.linterOptions,\n },\n };\n // eslint-disable-next-line ts/consistent-type-assertions\n }, {} as T);\n\n // Remove unused keys\n for (const key of Object.keys(merged)) {\n if (!keys.has(key))\n // eslint-disable-next-line ts/no-dynamic-delete\n delete (merged as any)[key];\n }\n\n return merged as T;\n}\n\n/**\n * Concat multiple flat configs into a single flat config array.\n *\n * It also resolves promises and flattens the result.\n *\n * @example\n *\n * ```ts\n * import eslint from '@eslint/js'\n *\n * export default ESLintConfig.concat(\n * {\n * plugins: {},\n * rules: {},\n * },\n * // It can also takes a array of configs:\n * [\n * {\n * plugins: {},\n * rules: {},\n * }\n * // ...\n * ],\n * // Or promises:\n * Promise.resolve({\n * files: ['*.ts'],\n * rules: {},\n * })\n * );\n * ```\n * @param configs\n */\nasync function concat<T extends Linter.Config = Linter.Config>(\n ...configs: Array<T | ReadonlyArray<T> | Promise<T> | Promise<ReadonlyArray<T>>>\n): Promise<Array<T>> {\n const resolved = await Promise.all(configs);\n return resolved.flat() as Array<T>;\n}\n\n/**\n * Always return 'off'. `_status` is the previous rule value.\n *\n * @param _status\n */\nfunction fixme(_status: string | number | [string | number, ...any[]] | undefined) {\n return 'off' as const;\n}\n\n/**\n * Renames rules in the given object according to the given map.\n *\n * Given a map `{ 'old-prefix': 'new-prefix' }`, and a rule object\n * `{ 'old-prefix/rule-name': 'error' }`, this function will return\n * `{ 'new-prefix/rule-name': 'error' }`.\n *\n * @param rules The object containing the rules to rename.\n * @param map The object containing the rename map.\n */\nfunction renameRules(rules: Record<string, any>, map: Record<string, string>): Record<string, any> {\n return Object.fromEntries(\n Object.entries(rules).map(([key, value]) => {\n for (const [from, to] of Object.entries(map)) {\n if (key.startsWith(`${from}/`)) return [to + key.slice(from.length), value];\n else if (from === '' && !key.includes('/') && to !== '') return [to + key, value];\n }\n return [key, value];\n }),\n );\n}\n\n/**\n * @namespace\n */\nexport const ESLintConfig = Object.freeze({\n merge,\n concat,\n fixme,\n renameRules,\n});\n","const getDefaultOrElse = (_: any) => _?.default ?? _;\n\n/**\n * Resolves a module or promise-like object, returning the default export if available.\n *\n * @example\n * ```ts\n * // modules.ts\n * export default {\n * foo: true\n * };\n * // Async API\n * const modPromise = import('./module');\n * interopDefault(modPromise); // == Promise.resolve({ foo: true })\n * // Sync API\n * const mod = await import('./module');\n * interopDefault(mod); // == { foo: true }\n * ```\n *\n * @template T - The type of the module or promise-like object.\n * @param m The module or promise-like object to resolve.\n */\nexport function interopDefault<T>(m: PromiseLike<T>): Promise<T extends { default: infer U } ? U : T>;\nexport function interopDefault<T>(m: T): T extends { default: infer U } ? U : T;\nexport function interopDefault<T>(m: T | PromiseLike<T>): Promise<T extends { default: infer U } ? U : T> {\n // @ts-ignore We know what we are doing\n return m != null && typeof m.then === 'function' ? Promise.resolve(m).then(getDefaultOrElse) : getDefaultOrElse(m);\n}\n","export const meta = Object.freeze({\n // @ts-ignore - these variables are injected at build time\n name: (typeof __PACKAGE_NAME__ === 'undefined' ? '' : __PACKAGE_NAME__) as string,\n // @ts-ignore - these variables are injected at build time\n version: (typeof __PACKAGE_VERSION__ === 'undefined' ? '' : __PACKAGE_VERSION__) as string,\n // @ts-ignore - these variables are injected at build time\n buildNumber: 1 as number, // (typeof __PACKAGE_BUILD_NUMBER__ === 'undefined' ? 0 : __PACKAGE_BUILD_NUMBER__) as number,\n});\n","import type { LanguageId } from './LanguageId.js';\n\n/**\n * A type of a file extension\n */\nexport type Extension = `.${string}`;\n\n/**\n * Object hash of all well-known file extension category to file extensions mapping\n */\nexport type ExtensionRegistry = { [K in LanguageId]: readonly Extension[] };\n\nfunction escapeRegExp(value: string) {\n // eslint-disable-next-line unicorn/prefer-string-raw\n return value.replaceAll(/[$()*+.?[\\\\\\]^{|}]/g, '\\\\$&'); // $& means the whole matched string\n}\n\n/**\n * Supported ECMA version\n *\n * @example\n * ```ts\n * Project.ecmaVersion() // 2022\n * ```\n */\nfunction ecmaVersion() {\n return 2022 as const;\n}\n\nconst registry: ExtensionRegistry = {\n css: ['.css'],\n graphql: ['.gql', '.graphql'],\n javascript: ['.js', '.cjs', '.mjs'],\n javascriptreact: ['.jsx'],\n jpeg: ['.jpg', '.jpeg'],\n json: ['.json'],\n jsonc: ['.jsonc'],\n less: ['.less'],\n markdown: ['.markdown', '.mdown', '.mkd', '.md'],\n sass: ['.sass'],\n scss: ['.scss'],\n typescript: ['.ts', '.cts', '.mts'],\n typescriptreact: ['.tsx'],\n vue: ['.vue'],\n yaml: ['.yaml', '.yml'],\n};\n\n/**\n * Return a list of extensions\n *\n * @example\n * ```ts\n * Project.queryExtensions(['javascript']); // ['.js', '.cjs', ...]\n * Project.queryExtensions(['typescript', 'typescriptreact']); // ['.ts', '.mts', ..., '.tsx']\n * ```\n *\n * @param languages\n */\nfunction queryExtensions(languages: LanguageId[]): readonly Extension[] {\n return languages\n .reduce<Extension[]>((previousValue, currentValue) =>\n // eslint-disable-next-line unicorn/prefer-spread\n previousValue.concat(registry[currentValue] ?? ([] as Extension[])), [])\n // eslint-disable-next-line unicorn/no-array-sort\n .sort();\n}\n\n/**\n * Supported file extensions\n *\n * @example\n * ```ts\n * Project.sourceExtensions() // ['.ts', '.js', ...]\n * ```\n */\nfunction sourceExtensions() {\n return queryExtensions(['javascript', 'javascriptreact', 'typescript', 'typescriptreact']);\n}\n\nconst RESOURCE_EXTENSIONS: readonly Extension[] = Object.freeze([\n '.gif',\n '.png',\n '.svg',\n ...queryExtensions(['css', 'graphql', 'jpeg', 'less', 'sass', 'sass', 'yaml']),\n]);\n\n/**\n * Resource file extensions\n *\n * @example\n * ```ts\n * Project.resourceExtensions() // ['.css', '.sass', ...]\n * ```\n */\nfunction resourceExtensions() {\n return RESOURCE_EXTENSIONS;\n}\n\nconst IGNORED = Object.freeze([\n 'node_modules/',\n 'build/',\n 'cjs/',\n 'coverage/',\n 'dist/',\n 'dts/',\n 'esm/',\n 'lib/',\n 'mjs/',\n 'umd/',\n]);\n\n/**\n * Files and folders to always ignore\n *\n * @example\n * ```ts\n * IGNORED // ['node_modules/', 'build/', ...]\n * ```\n */\nfunction ignored() {\n return IGNORED;\n}\n\n/**\n * Return a RegExp that will match any list of extensions\n *\n * @param extensions\n * @example\n * ```ts\n * Project.extensionsToMatcher(['.js', '.ts']) // RegExp = /(\\.js|\\.ts)$/\n * ```\n */\nfunction extensionsToMatcher(extensions: readonly Extension[]): RegExp {\n return new RegExp(`(${extensions.map(escapeRegExp).join('|')})$`);\n}\n\nconst reExtension = /^\\./;\n\n/**\n * Return a glob matcher that will match any list of extensions\n *\n * @param extensions\n * @example\n * ```ts\n * Project.extensionsToGlob(['.js', '.ts']) // '*.+(js|ts)'\n * ```\n */\nfunction extensionsToGlob(extensions: readonly Extension[]): string {\n return `*.+(${extensions.map((_) => _.replace(reExtension, '')).join('|')})`;\n}\n\nexport const Project = Object.freeze({\n ecmaVersion,\n extensionsToGlob,\n extensionsToMatcher,\n ignored,\n queryExtensions,\n resourceExtensions,\n sourceExtensions,\n});\n","/**\n * Project common scripts\n */\nexport const ProjectScript = {\n Build: 'build',\n Clean: 'clean',\n CodeAnalysis: 'code-analysis',\n Coverage: 'coverage',\n Develop: 'develop',\n Docs: 'docs',\n Format: 'format',\n Install: 'install',\n Lint: 'lint',\n Prepare: 'prepare',\n Release: 'release',\n Rescue: 'rescue',\n Spellcheck: 'spellcheck',\n Test: 'test',\n Typecheck: 'typecheck',\n Validate: 'validate',\n} as const;\nexport type ProjectScript = (typeof ProjectScript)[keyof typeof ProjectScript];\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -1,11 +1,45 @@
1
- import { ESLint } from "eslint";
1
+ import { Linter } from "eslint";
2
2
 
3
3
  //#region src/ESLintConfig.d.ts
4
4
  /**
5
+ * Return a new merged flat configuration
5
6
  *
6
7
  * @param configs
7
8
  */
8
- declare function concat(...configs: ESLint.ConfigData[]): ESLint.ConfigData;
9
+ declare function merge<T extends Linter.Config = Linter.Config>(...configs: Array<T>): T;
10
+ /**
11
+ * Concat multiple flat configs into a single flat config array.
12
+ *
13
+ * It also resolves promises and flattens the result.
14
+ *
15
+ * @example
16
+ *
17
+ * ```ts
18
+ * import eslint from '@eslint/js'
19
+ *
20
+ * export default ESLintConfig.concat(
21
+ * {
22
+ * plugins: {},
23
+ * rules: {},
24
+ * },
25
+ * // It can also takes a array of configs:
26
+ * [
27
+ * {
28
+ * plugins: {},
29
+ * rules: {},
30
+ * }
31
+ * // ...
32
+ * ],
33
+ * // Or promises:
34
+ * Promise.resolve({
35
+ * files: ['*.ts'],
36
+ * rules: {},
37
+ * })
38
+ * );
39
+ * ```
40
+ * @param configs
41
+ */
42
+ declare function concat<T extends Linter.Config = Linter.Config>(...configs: Array<T | ReadonlyArray<T> | Promise<T> | Promise<ReadonlyArray<T>>>): Promise<Array<T>>;
9
43
  /**
10
44
  * Always return 'off'. `_status` is the previous rule value.
11
45
  *
@@ -27,6 +61,7 @@ declare function renameRules(rules: Record<string, any>, map: Record<string, str
27
61
  * @namespace
28
62
  */
29
63
  declare const ESLintConfig: Readonly<{
64
+ merge: typeof merge;
30
65
  concat: typeof concat;
31
66
  fixme: typeof fixme;
32
67
  renameRules: typeof renameRules;
package/dist/index.d.ts CHANGED
@@ -1,11 +1,45 @@
1
- import { ESLint } from "eslint";
1
+ import { Linter } from "eslint";
2
2
 
3
3
  //#region src/ESLintConfig.d.ts
4
4
  /**
5
+ * Return a new merged flat configuration
5
6
  *
6
7
  * @param configs
7
8
  */
8
- declare function concat(...configs: ESLint.ConfigData[]): ESLint.ConfigData;
9
+ declare function merge<T extends Linter.Config = Linter.Config>(...configs: Array<T>): T;
10
+ /**
11
+ * Concat multiple flat configs into a single flat config array.
12
+ *
13
+ * It also resolves promises and flattens the result.
14
+ *
15
+ * @example
16
+ *
17
+ * ```ts
18
+ * import eslint from '@eslint/js'
19
+ *
20
+ * export default ESLintConfig.concat(
21
+ * {
22
+ * plugins: {},
23
+ * rules: {},
24
+ * },
25
+ * // It can also takes a array of configs:
26
+ * [
27
+ * {
28
+ * plugins: {},
29
+ * rules: {},
30
+ * }
31
+ * // ...
32
+ * ],
33
+ * // Or promises:
34
+ * Promise.resolve({
35
+ * files: ['*.ts'],
36
+ * rules: {},
37
+ * })
38
+ * );
39
+ * ```
40
+ * @param configs
41
+ */
42
+ declare function concat<T extends Linter.Config = Linter.Config>(...configs: Array<T | ReadonlyArray<T> | Promise<T> | Promise<ReadonlyArray<T>>>): Promise<Array<T>>;
9
43
  /**
10
44
  * Always return 'off'. `_status` is the previous rule value.
11
45
  *
@@ -27,6 +61,7 @@ declare function renameRules(rules: Record<string, any>, map: Record<string, str
27
61
  * @namespace
28
62
  */
29
63
  declare const ESLintConfig: Readonly<{
64
+ merge: typeof merge;
30
65
  concat: typeof concat;
31
66
  fixme: typeof fixme;
32
67
  renameRules: typeof renameRules;
package/dist/index.js CHANGED
@@ -1,53 +1,72 @@
1
1
  //#region src/ESLintConfig.ts
2
- function toArray(value) {
3
- if (value == null) return [];
4
- if (Array.isArray(value)) return value;
5
- return [value];
6
- }
7
- function concatArray(left, right) {
8
- return [...toArray(left), ...toArray(right)];
2
+ /**
3
+ * Return a new merged flat configuration
4
+ *
5
+ * @param configs
6
+ */
7
+ function merge(...configs) {
8
+ const keys = new Set(configs.flatMap((i) => Object.keys(i)));
9
+ const merged = configs.reduce((acc, cur) => {
10
+ return {
11
+ ...acc,
12
+ ...cur,
13
+ files: [...acc.files ?? [], ...cur.files ?? []],
14
+ ignores: [...acc.ignores ?? [], ...cur.ignores ?? []],
15
+ plugins: {
16
+ ...acc.plugins,
17
+ ...cur.plugins
18
+ },
19
+ rules: {
20
+ ...acc.rules,
21
+ ...cur.rules
22
+ },
23
+ languageOptions: {
24
+ ...acc.languageOptions,
25
+ ...cur.languageOptions
26
+ },
27
+ linterOptions: {
28
+ ...acc.linterOptions,
29
+ ...cur.linterOptions
30
+ }
31
+ };
32
+ }, {});
33
+ for (const key of Object.keys(merged)) if (!keys.has(key)) delete merged[key];
34
+ return merged;
9
35
  }
10
36
  /**
37
+ * Concat multiple flat configs into a single flat config array.
38
+ *
39
+ * It also resolves promises and flattens the result.
11
40
  *
41
+ * @example
42
+ *
43
+ * ```ts
44
+ * import eslint from '@eslint/js'
45
+ *
46
+ * export default ESLintConfig.concat(
47
+ * {
48
+ * plugins: {},
49
+ * rules: {},
50
+ * },
51
+ * // It can also takes a array of configs:
52
+ * [
53
+ * {
54
+ * plugins: {},
55
+ * rules: {},
56
+ * }
57
+ * // ...
58
+ * ],
59
+ * // Or promises:
60
+ * Promise.resolve({
61
+ * files: ['*.ts'],
62
+ * rules: {},
63
+ * })
64
+ * );
65
+ * ```
12
66
  * @param configs
13
67
  */
14
- function concat(...configs) {
15
- return configs.reduce((returnValue, config) => ({
16
- ...returnValue,
17
- ...config,
18
- env: {
19
- ...returnValue.env,
20
- ...config.env
21
- },
22
- extends: concatArray(returnValue.extends, config.extends),
23
- globals: {
24
- ...returnValue.globals,
25
- ...config.globals
26
- },
27
- overrides: concatArray(returnValue.overrides, config.overrides),
28
- parserOptions: {
29
- ...returnValue.parserOptions,
30
- ...config.parserOptions
31
- },
32
- plugins: concatArray(returnValue.plugins, config.plugins),
33
- rules: {
34
- ...returnValue.rules,
35
- ...config.rules
36
- },
37
- settings: {
38
- ...returnValue.settings,
39
- ...config.settings
40
- }
41
- }), {
42
- env: {},
43
- extends: [],
44
- globals: {},
45
- overrides: [],
46
- parserOptions: {},
47
- plugins: [],
48
- rules: {},
49
- settings: {}
50
- });
68
+ async function concat(...configs) {
69
+ return (await Promise.all(configs)).flat();
51
70
  }
52
71
  /**
53
72
  * Always return 'off'. `_status` is the previous rule value.
@@ -78,6 +97,7 @@ function renameRules(rules, map) {
78
97
  * @namespace
79
98
  */
80
99
  const ESLintConfig = Object.freeze({
100
+ merge,
81
101
  concat,
82
102
  fixme,
83
103
  renameRules
@@ -92,7 +112,7 @@ function interopDefault(m) {
92
112
  //#region src/meta.ts
93
113
  const meta = Object.freeze({
94
114
  name: "@w5s/dev",
95
- version: "3.3.2",
115
+ version: "3.4.0",
96
116
  buildNumber: 1
97
117
  });
98
118
  //#endregion
@@ -231,6 +251,7 @@ function ignored() {
231
251
  function extensionsToMatcher(extensions) {
232
252
  return new RegExp(`(${extensions.map(escapeRegExp).join("|")})$`);
233
253
  }
254
+ const reExtension = /^\./;
234
255
  /**
235
256
  * Return a glob matcher that will match any list of extensions
236
257
  *
@@ -241,7 +262,7 @@ function extensionsToMatcher(extensions) {
241
262
  * ```
242
263
  */
243
264
  function extensionsToGlob(extensions) {
244
- return `*.+(${extensions.map((_) => _.replace(/^\./, "")).join("|")})`;
265
+ return `*.+(${extensions.map((_) => _.replace(reExtension, "")).join("|")})`;
245
266
  }
246
267
  const Project = Object.freeze({
247
268
  ecmaVersion,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/ESLintConfig.ts","../src/interopDefault.ts","../src/meta.ts","../src/Project.ts","../src/ProjectScript.ts"],"sourcesContent":["import type { ESLint } from 'eslint';\n\nfunction toArray<T>(value: T[] | T | undefined): T[] {\n if (value == null) {\n return [];\n }\n if (Array.isArray(value)) {\n return value;\n }\n return [value];\n}\n\nfunction concatArray<T>(left: T[] | T | undefined, right: T[] | T | undefined): T[] {\n return [...toArray(left), ...toArray(right)];\n}\n\n/**\n *\n * @param configs\n */\nfunction concat(...configs: ESLint.ConfigData[]): ESLint.ConfigData {\n return configs.reduce(\n (returnValue, config) => ({\n ...returnValue,\n ...config,\n env: { ...returnValue.env, ...config.env },\n extends: concatArray(returnValue.extends, config.extends),\n globals: { ...returnValue.globals, ...config.globals },\n overrides: concatArray(returnValue.overrides, config.overrides),\n parserOptions: { ...returnValue.parserOptions, ...config.parserOptions },\n plugins: concatArray(returnValue.plugins, config.plugins),\n rules: { ...returnValue.rules, ...config.rules },\n settings: { ...returnValue.settings, ...config.settings },\n }),\n {\n env: {},\n extends: [],\n globals: {},\n overrides: [],\n parserOptions: {},\n plugins: [],\n rules: {},\n settings: {},\n },\n );\n}\n\n/**\n * Always return 'off'. `_status` is the previous rule value.\n *\n * @param _status\n */\nfunction fixme(_status: string | number | [string | number, ...any[]] | undefined) {\n return 'off' as const;\n}\n\n/**\n * Renames rules in the given object according to the given map.\n *\n * Given a map `{ 'old-prefix': 'new-prefix' }`, and a rule object\n * `{ 'old-prefix/rule-name': 'error' }`, this function will return\n * `{ 'new-prefix/rule-name': 'error' }`.\n *\n * @param rules The object containing the rules to rename.\n * @param map The object containing the rename map.\n */\nfunction renameRules(rules: Record<string, any>, map: Record<string, string>): Record<string, any> {\n return Object.fromEntries(\n Object.entries(rules).map(([key, value]) => {\n for (const [from, to] of Object.entries(map)) {\n if (key.startsWith(`${from}/`)) return [to + key.slice(from.length), value];\n else if (from === '' && !key.includes('/') && to !== '') return [to + key, value];\n }\n return [key, value];\n }),\n );\n}\n\n/**\n * @namespace\n */\nexport const ESLintConfig = Object.freeze({\n concat,\n fixme,\n renameRules,\n});\n","const getDefaultOrElse = (_: any) => _?.default ?? _;\n\n/**\n * Resolves a module or promise-like object, returning the default export if available.\n *\n * @example\n * ```ts\n * // modules.ts\n * export default {\n * foo: true\n * };\n * // Async API\n * const modPromise = import('./module');\n * interopDefault(modPromise); // == Promise.resolve({ foo: true })\n * // Sync API\n * const mod = await import('./module');\n * interopDefault(mod); // == { foo: true }\n * ```\n *\n * @template T - The type of the module or promise-like object.\n * @param m The module or promise-like object to resolve.\n */\nexport function interopDefault<T>(m: PromiseLike<T>): Promise<T extends { default: infer U } ? U : T>;\nexport function interopDefault<T>(m: T): T extends { default: infer U } ? U : T;\nexport function interopDefault<T>(m: T | PromiseLike<T>): Promise<T extends { default: infer U } ? U : T> {\n // @ts-ignore We know what we are doing\n return m != null && typeof m.then === 'function' ? Promise.resolve(m).then(getDefaultOrElse) : getDefaultOrElse(m);\n}\n","export const meta = Object.freeze({\n // @ts-ignore - these variables are injected at build time\n name: (typeof __PACKAGE_NAME__ === 'undefined' ? '' : __PACKAGE_NAME__) as string,\n // @ts-ignore - these variables are injected at build time\n version: (typeof __PACKAGE_VERSION__ === 'undefined' ? '' : __PACKAGE_VERSION__) as string,\n // @ts-ignore - these variables are injected at build time\n buildNumber: 1 as number, // (typeof __PACKAGE_BUILD_NUMBER__ === 'undefined' ? 0 : __PACKAGE_BUILD_NUMBER__) as number,\n});\n","import type { LanguageId } from './LanguageId.js';\n\n/**\n * A type of a file extension\n */\nexport type Extension = `.${string}`;\n\n/**\n * Object hash of all well-known file extension category to file extensions mapping\n */\nexport type ExtensionRegistry = { [K in LanguageId]: readonly Extension[] };\n\nfunction escapeRegExp(value: string) {\n // eslint-disable-next-line unicorn/prefer-string-raw\n return value.replaceAll(/[$()*+.?[\\\\\\]^{|}]/g, '\\\\$&'); // $& means the whole matched string\n}\n\n/**\n * Supported ECMA version\n *\n * @example\n * ```ts\n * Project.ecmaVersion() // 2022\n * ```\n */\nfunction ecmaVersion() {\n return 2022 as const;\n}\n\nconst registry: ExtensionRegistry = {\n css: ['.css'],\n graphql: ['.gql', '.graphql'],\n javascript: ['.js', '.cjs', '.mjs'],\n javascriptreact: ['.jsx'],\n jpeg: ['.jpg', '.jpeg'],\n json: ['.json'],\n jsonc: ['.jsonc'],\n less: ['.less'],\n markdown: ['.markdown', '.mdown', '.mkd', '.md'],\n sass: ['.sass'],\n scss: ['.scss'],\n typescript: ['.ts', '.cts', '.mts'],\n typescriptreact: ['.tsx'],\n vue: ['.vue'],\n yaml: ['.yaml', '.yml'],\n};\n\n/**\n * Return a list of extensions\n *\n * @example\n * ```ts\n * Project.queryExtensions(['javascript']); // ['.js', '.cjs', ...]\n * Project.queryExtensions(['typescript', 'typescriptreact']); // ['.ts', '.mts', ..., '.tsx']\n * ```\n *\n * @param languages\n */\nfunction queryExtensions(languages: LanguageId[]): readonly Extension[] {\n return languages\n .reduce<Extension[]>((previousValue, currentValue) =>\n // eslint-disable-next-line unicorn/prefer-spread\n previousValue.concat(registry[currentValue] ?? ([] as Extension[])), [])\n // eslint-disable-next-line unicorn/no-array-sort\n .sort();\n}\n\n/**\n * Supported file extensions\n *\n * @example\n * ```ts\n * Project.sourceExtensions() // ['.ts', '.js', ...]\n * ```\n */\nfunction sourceExtensions() {\n return queryExtensions(['javascript', 'javascriptreact', 'typescript', 'typescriptreact']);\n}\n\nconst RESOURCE_EXTENSIONS: readonly Extension[] = Object.freeze([\n '.gif',\n '.png',\n '.svg',\n ...queryExtensions(['css', 'graphql', 'jpeg', 'less', 'sass', 'sass', 'yaml']),\n]);\n\n/**\n * Resource file extensions\n *\n * @example\n * ```ts\n * Project.resourceExtensions() // ['.css', '.sass', ...]\n * ```\n */\nfunction resourceExtensions() {\n return RESOURCE_EXTENSIONS;\n}\n\nconst IGNORED = Object.freeze([\n 'node_modules/',\n 'build/',\n 'cjs/',\n 'coverage/',\n 'dist/',\n 'dts/',\n 'esm/',\n 'lib/',\n 'mjs/',\n 'umd/',\n]);\n\n/**\n * Files and folders to always ignore\n *\n * @example\n * ```ts\n * IGNORED // ['node_modules/', 'build/', ...]\n * ```\n */\nfunction ignored() {\n return IGNORED;\n}\n\n/**\n * Return a RegExp that will match any list of extensions\n *\n * @param extensions\n * @example\n * ```ts\n * Project.extensionsToMatcher(['.js', '.ts']) // RegExp = /(\\.js|\\.ts)$/\n * ```\n */\nfunction extensionsToMatcher(extensions: readonly Extension[]): RegExp {\n return new RegExp(`(${extensions.map(escapeRegExp).join('|')})$`);\n}\n\n/**\n * Return a glob matcher that will match any list of extensions\n *\n * @param extensions\n * @example\n * ```ts\n * Project.extensionsToGlob(['.js', '.ts']) // '*.+(js|ts)'\n * ```\n */\nfunction extensionsToGlob(extensions: readonly Extension[]): string {\n return `*.+(${extensions.map((_) => _.replace(/^\\./, '')).join('|')})`;\n}\n\nexport const Project = Object.freeze({\n ecmaVersion,\n extensionsToGlob,\n extensionsToMatcher,\n ignored,\n queryExtensions,\n resourceExtensions,\n sourceExtensions,\n});\n","/**\n * Project common scripts\n */\nexport const ProjectScript = {\n Build: 'build',\n Clean: 'clean',\n CodeAnalysis: 'code-analysis',\n Coverage: 'coverage',\n Develop: 'develop',\n Docs: 'docs',\n Format: 'format',\n Install: 'install',\n Lint: 'lint',\n Prepare: 'prepare',\n Release: 'release',\n Rescue: 'rescue',\n Spellcheck: 'spellcheck',\n Test: 'test',\n Typecheck: 'typecheck',\n Validate: 'validate',\n} as const;\nexport type ProjectScript = (typeof ProjectScript)[keyof typeof ProjectScript];\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/ESLintConfig.ts","../src/interopDefault.ts","../src/meta.ts","../src/Project.ts","../src/ProjectScript.ts"],"sourcesContent":["import type { Linter } from 'eslint';\n\n/**\n * Return a new merged flat configuration\n *\n * @param configs\n */\nfunction merge<T extends Linter.Config = Linter.Config>(...configs: Array<T>): T {\n const keys = new Set(configs.flatMap((i) => Object.keys(i)));\n const merged = configs.reduce((acc, cur) => {\n return {\n ...acc,\n ...cur,\n files: [\n ...(acc.files ?? []),\n ...(cur.files ?? []),\n ],\n ignores: [\n ...(acc.ignores ?? []),\n ...(cur.ignores ?? []),\n ],\n plugins: {\n ...acc.plugins,\n ...cur.plugins,\n },\n rules: {\n ...acc.rules,\n ...cur.rules,\n },\n languageOptions: {\n ...acc.languageOptions,\n ...cur.languageOptions,\n },\n linterOptions: {\n ...acc.linterOptions,\n ...cur.linterOptions,\n },\n };\n // eslint-disable-next-line ts/consistent-type-assertions\n }, {} as T);\n\n // Remove unused keys\n for (const key of Object.keys(merged)) {\n if (!keys.has(key))\n // eslint-disable-next-line ts/no-dynamic-delete\n delete (merged as any)[key];\n }\n\n return merged as T;\n}\n\n/**\n * Concat multiple flat configs into a single flat config array.\n *\n * It also resolves promises and flattens the result.\n *\n * @example\n *\n * ```ts\n * import eslint from '@eslint/js'\n *\n * export default ESLintConfig.concat(\n * {\n * plugins: {},\n * rules: {},\n * },\n * // It can also takes a array of configs:\n * [\n * {\n * plugins: {},\n * rules: {},\n * }\n * // ...\n * ],\n * // Or promises:\n * Promise.resolve({\n * files: ['*.ts'],\n * rules: {},\n * })\n * );\n * ```\n * @param configs\n */\nasync function concat<T extends Linter.Config = Linter.Config>(\n ...configs: Array<T | ReadonlyArray<T> | Promise<T> | Promise<ReadonlyArray<T>>>\n): Promise<Array<T>> {\n const resolved = await Promise.all(configs);\n return resolved.flat() as Array<T>;\n}\n\n/**\n * Always return 'off'. `_status` is the previous rule value.\n *\n * @param _status\n */\nfunction fixme(_status: string | number | [string | number, ...any[]] | undefined) {\n return 'off' as const;\n}\n\n/**\n * Renames rules in the given object according to the given map.\n *\n * Given a map `{ 'old-prefix': 'new-prefix' }`, and a rule object\n * `{ 'old-prefix/rule-name': 'error' }`, this function will return\n * `{ 'new-prefix/rule-name': 'error' }`.\n *\n * @param rules The object containing the rules to rename.\n * @param map The object containing the rename map.\n */\nfunction renameRules(rules: Record<string, any>, map: Record<string, string>): Record<string, any> {\n return Object.fromEntries(\n Object.entries(rules).map(([key, value]) => {\n for (const [from, to] of Object.entries(map)) {\n if (key.startsWith(`${from}/`)) return [to + key.slice(from.length), value];\n else if (from === '' && !key.includes('/') && to !== '') return [to + key, value];\n }\n return [key, value];\n }),\n );\n}\n\n/**\n * @namespace\n */\nexport const ESLintConfig = Object.freeze({\n merge,\n concat,\n fixme,\n renameRules,\n});\n","const getDefaultOrElse = (_: any) => _?.default ?? _;\n\n/**\n * Resolves a module or promise-like object, returning the default export if available.\n *\n * @example\n * ```ts\n * // modules.ts\n * export default {\n * foo: true\n * };\n * // Async API\n * const modPromise = import('./module');\n * interopDefault(modPromise); // == Promise.resolve({ foo: true })\n * // Sync API\n * const mod = await import('./module');\n * interopDefault(mod); // == { foo: true }\n * ```\n *\n * @template T - The type of the module or promise-like object.\n * @param m The module or promise-like object to resolve.\n */\nexport function interopDefault<T>(m: PromiseLike<T>): Promise<T extends { default: infer U } ? U : T>;\nexport function interopDefault<T>(m: T): T extends { default: infer U } ? U : T;\nexport function interopDefault<T>(m: T | PromiseLike<T>): Promise<T extends { default: infer U } ? U : T> {\n // @ts-ignore We know what we are doing\n return m != null && typeof m.then === 'function' ? Promise.resolve(m).then(getDefaultOrElse) : getDefaultOrElse(m);\n}\n","export const meta = Object.freeze({\n // @ts-ignore - these variables are injected at build time\n name: (typeof __PACKAGE_NAME__ === 'undefined' ? '' : __PACKAGE_NAME__) as string,\n // @ts-ignore - these variables are injected at build time\n version: (typeof __PACKAGE_VERSION__ === 'undefined' ? '' : __PACKAGE_VERSION__) as string,\n // @ts-ignore - these variables are injected at build time\n buildNumber: 1 as number, // (typeof __PACKAGE_BUILD_NUMBER__ === 'undefined' ? 0 : __PACKAGE_BUILD_NUMBER__) as number,\n});\n","import type { LanguageId } from './LanguageId.js';\n\n/**\n * A type of a file extension\n */\nexport type Extension = `.${string}`;\n\n/**\n * Object hash of all well-known file extension category to file extensions mapping\n */\nexport type ExtensionRegistry = { [K in LanguageId]: readonly Extension[] };\n\nfunction escapeRegExp(value: string) {\n // eslint-disable-next-line unicorn/prefer-string-raw\n return value.replaceAll(/[$()*+.?[\\\\\\]^{|}]/g, '\\\\$&'); // $& means the whole matched string\n}\n\n/**\n * Supported ECMA version\n *\n * @example\n * ```ts\n * Project.ecmaVersion() // 2022\n * ```\n */\nfunction ecmaVersion() {\n return 2022 as const;\n}\n\nconst registry: ExtensionRegistry = {\n css: ['.css'],\n graphql: ['.gql', '.graphql'],\n javascript: ['.js', '.cjs', '.mjs'],\n javascriptreact: ['.jsx'],\n jpeg: ['.jpg', '.jpeg'],\n json: ['.json'],\n jsonc: ['.jsonc'],\n less: ['.less'],\n markdown: ['.markdown', '.mdown', '.mkd', '.md'],\n sass: ['.sass'],\n scss: ['.scss'],\n typescript: ['.ts', '.cts', '.mts'],\n typescriptreact: ['.tsx'],\n vue: ['.vue'],\n yaml: ['.yaml', '.yml'],\n};\n\n/**\n * Return a list of extensions\n *\n * @example\n * ```ts\n * Project.queryExtensions(['javascript']); // ['.js', '.cjs', ...]\n * Project.queryExtensions(['typescript', 'typescriptreact']); // ['.ts', '.mts', ..., '.tsx']\n * ```\n *\n * @param languages\n */\nfunction queryExtensions(languages: LanguageId[]): readonly Extension[] {\n return languages\n .reduce<Extension[]>((previousValue, currentValue) =>\n // eslint-disable-next-line unicorn/prefer-spread\n previousValue.concat(registry[currentValue] ?? ([] as Extension[])), [])\n // eslint-disable-next-line unicorn/no-array-sort\n .sort();\n}\n\n/**\n * Supported file extensions\n *\n * @example\n * ```ts\n * Project.sourceExtensions() // ['.ts', '.js', ...]\n * ```\n */\nfunction sourceExtensions() {\n return queryExtensions(['javascript', 'javascriptreact', 'typescript', 'typescriptreact']);\n}\n\nconst RESOURCE_EXTENSIONS: readonly Extension[] = Object.freeze([\n '.gif',\n '.png',\n '.svg',\n ...queryExtensions(['css', 'graphql', 'jpeg', 'less', 'sass', 'sass', 'yaml']),\n]);\n\n/**\n * Resource file extensions\n *\n * @example\n * ```ts\n * Project.resourceExtensions() // ['.css', '.sass', ...]\n * ```\n */\nfunction resourceExtensions() {\n return RESOURCE_EXTENSIONS;\n}\n\nconst IGNORED = Object.freeze([\n 'node_modules/',\n 'build/',\n 'cjs/',\n 'coverage/',\n 'dist/',\n 'dts/',\n 'esm/',\n 'lib/',\n 'mjs/',\n 'umd/',\n]);\n\n/**\n * Files and folders to always ignore\n *\n * @example\n * ```ts\n * IGNORED // ['node_modules/', 'build/', ...]\n * ```\n */\nfunction ignored() {\n return IGNORED;\n}\n\n/**\n * Return a RegExp that will match any list of extensions\n *\n * @param extensions\n * @example\n * ```ts\n * Project.extensionsToMatcher(['.js', '.ts']) // RegExp = /(\\.js|\\.ts)$/\n * ```\n */\nfunction extensionsToMatcher(extensions: readonly Extension[]): RegExp {\n return new RegExp(`(${extensions.map(escapeRegExp).join('|')})$`);\n}\n\nconst reExtension = /^\\./;\n\n/**\n * Return a glob matcher that will match any list of extensions\n *\n * @param extensions\n * @example\n * ```ts\n * Project.extensionsToGlob(['.js', '.ts']) // '*.+(js|ts)'\n * ```\n */\nfunction extensionsToGlob(extensions: readonly Extension[]): string {\n return `*.+(${extensions.map((_) => _.replace(reExtension, '')).join('|')})`;\n}\n\nexport const Project = Object.freeze({\n ecmaVersion,\n extensionsToGlob,\n extensionsToMatcher,\n ignored,\n queryExtensions,\n resourceExtensions,\n sourceExtensions,\n});\n","/**\n * Project common scripts\n */\nexport const ProjectScript = {\n Build: 'build',\n Clean: 'clean',\n CodeAnalysis: 'code-analysis',\n Coverage: 'coverage',\n Develop: 'develop',\n Docs: 'docs',\n Format: 'format',\n Install: 'install',\n Lint: 'lint',\n Prepare: 'prepare',\n Release: 'release',\n Rescue: 'rescue',\n Spellcheck: 'spellcheck',\n Test: 'test',\n Typecheck: 'typecheck',\n Validate: 'validate',\n} as const;\nexport type ProjectScript = (typeof ProjectScript)[keyof typeof ProjectScript];\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@w5s/dev",
3
- "version": "3.3.2",
3
+ "version": "3.4.0",
4
4
  "description": "Shared development constants and functions",
5
5
  "keywords": [
6
6
  "config",
@@ -54,5 +54,5 @@
54
54
  "access": "public"
55
55
  },
56
56
  "sideEffect": false,
57
- "gitHead": "ab7987a57772b2e7fb3ef7eb4cadb3cedd9cc9ae"
57
+ "gitHead": "9102f7149f4d1faa4a9c96e7e910cbb296bd63e5"
58
58
  }
@@ -1,48 +1,91 @@
1
- import type { ESLint } from 'eslint';
1
+ import type { Linter } from 'eslint';
2
2
 
3
- function toArray<T>(value: T[] | T | undefined): T[] {
4
- if (value == null) {
5
- return [];
6
- }
7
- if (Array.isArray(value)) {
8
- return value;
3
+ /**
4
+ * Return a new merged flat configuration
5
+ *
6
+ * @param configs
7
+ */
8
+ function merge<T extends Linter.Config = Linter.Config>(...configs: Array<T>): T {
9
+ const keys = new Set(configs.flatMap((i) => Object.keys(i)));
10
+ const merged = configs.reduce((acc, cur) => {
11
+ return {
12
+ ...acc,
13
+ ...cur,
14
+ files: [
15
+ ...(acc.files ?? []),
16
+ ...(cur.files ?? []),
17
+ ],
18
+ ignores: [
19
+ ...(acc.ignores ?? []),
20
+ ...(cur.ignores ?? []),
21
+ ],
22
+ plugins: {
23
+ ...acc.plugins,
24
+ ...cur.plugins,
25
+ },
26
+ rules: {
27
+ ...acc.rules,
28
+ ...cur.rules,
29
+ },
30
+ languageOptions: {
31
+ ...acc.languageOptions,
32
+ ...cur.languageOptions,
33
+ },
34
+ linterOptions: {
35
+ ...acc.linterOptions,
36
+ ...cur.linterOptions,
37
+ },
38
+ };
39
+ // eslint-disable-next-line ts/consistent-type-assertions
40
+ }, {} as T);
41
+
42
+ // Remove unused keys
43
+ for (const key of Object.keys(merged)) {
44
+ if (!keys.has(key))
45
+ // eslint-disable-next-line ts/no-dynamic-delete
46
+ delete (merged as any)[key];
9
47
  }
10
- return [value];
11
- }
12
48
 
13
- function concatArray<T>(left: T[] | T | undefined, right: T[] | T | undefined): T[] {
14
- return [...toArray(left), ...toArray(right)];
49
+ return merged as T;
15
50
  }
16
51
 
17
52
  /**
53
+ * Concat multiple flat configs into a single flat config array.
54
+ *
55
+ * It also resolves promises and flattens the result.
56
+ *
57
+ * @example
18
58
  *
59
+ * ```ts
60
+ * import eslint from '@eslint/js'
61
+ *
62
+ * export default ESLintConfig.concat(
63
+ * {
64
+ * plugins: {},
65
+ * rules: {},
66
+ * },
67
+ * // It can also takes a array of configs:
68
+ * [
69
+ * {
70
+ * plugins: {},
71
+ * rules: {},
72
+ * }
73
+ * // ...
74
+ * ],
75
+ * // Or promises:
76
+ * Promise.resolve({
77
+ * files: ['*.ts'],
78
+ * rules: {},
79
+ * })
80
+ * );
81
+ * ```
19
82
  * @param configs
20
83
  */
21
- function concat(...configs: ESLint.ConfigData[]): ESLint.ConfigData {
22
- return configs.reduce(
23
- (returnValue, config) => ({
24
- ...returnValue,
25
- ...config,
26
- env: { ...returnValue.env, ...config.env },
27
- extends: concatArray(returnValue.extends, config.extends),
28
- globals: { ...returnValue.globals, ...config.globals },
29
- overrides: concatArray(returnValue.overrides, config.overrides),
30
- parserOptions: { ...returnValue.parserOptions, ...config.parserOptions },
31
- plugins: concatArray(returnValue.plugins, config.plugins),
32
- rules: { ...returnValue.rules, ...config.rules },
33
- settings: { ...returnValue.settings, ...config.settings },
34
- }),
35
- {
36
- env: {},
37
- extends: [],
38
- globals: {},
39
- overrides: [],
40
- parserOptions: {},
41
- plugins: [],
42
- rules: {},
43
- settings: {},
44
- },
45
- );
84
+ async function concat<T extends Linter.Config = Linter.Config>(
85
+ ...configs: Array<T | ReadonlyArray<T> | Promise<T> | Promise<ReadonlyArray<T>>>
86
+ ): Promise<Array<T>> {
87
+ const resolved = await Promise.all(configs);
88
+ return resolved.flat() as Array<T>;
46
89
  }
47
90
 
48
91
  /**
@@ -80,6 +123,7 @@ function renameRules(rules: Record<string, any>, map: Record<string, string>): R
80
123
  * @namespace
81
124
  */
82
125
  export const ESLintConfig = Object.freeze({
126
+ merge,
83
127
  concat,
84
128
  fixme,
85
129
  renameRules,
package/src/Project.ts CHANGED
@@ -134,6 +134,8 @@ function extensionsToMatcher(extensions: readonly Extension[]): RegExp {
134
134
  return new RegExp(`(${extensions.map(escapeRegExp).join('|')})$`);
135
135
  }
136
136
 
137
+ const reExtension = /^\./;
138
+
137
139
  /**
138
140
  * Return a glob matcher that will match any list of extensions
139
141
  *
@@ -144,7 +146,7 @@ function extensionsToMatcher(extensions: readonly Extension[]): RegExp {
144
146
  * ```
145
147
  */
146
148
  function extensionsToGlob(extensions: readonly Extension[]): string {
147
- return `*.+(${extensions.map((_) => _.replace(/^\./, '')).join('|')})`;
149
+ return `*.+(${extensions.map((_) => _.replace(reExtension, '')).join('|')})`;
148
150
  }
149
151
 
150
152
  export const Project = Object.freeze({