comment-variables 0.6.2 → 0.8.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
@@ -68,8 +68,6 @@ const data = {
68
68
  definitions: Object.freeze({
69
69
  exitDueToFailure:
70
70
  "Terminates the whole process with a 'failure' code (1).", // $COMMENT#JSDOC#DEFINITIONS#EXITDUETOFAILURE
71
- escapeRegex:
72
- 'Escapes all regex characters with a `"\\"` in a string to prepare it for use in a regex.', // $COMMENT#JSDOC#DEFINITIONS#ESCAPEREGEX
73
71
  makeRuleResolve:
74
72
  "The utility that creates the resolve rule based on the flattened config data, used to transform $COMMENT#* placeholders into actual comments.", // $COMMENT#JSDOC#DEFINITIONS#MAKERULERESOLVE
75
73
  makeRuleCompress:
@@ -80,15 +78,10 @@ const data = {
80
78
  "The flow that resolves $COMMENT#* placeholders intro actual comments.", // $COMMENT#JSDOC#DEFINITIONS#RESOLVECOMMENTSFLOW
81
79
  compressCommentsFlow:
82
80
  "The flow that compresses actual comments into $COMMENT#* placeholders.", // $COMMENT#JSDOC#DEFINITIONS#COMPRESSCOMMENTSFLOW
83
- flattenConfigData:
84
- "Flattens the config's data property into a one-dimensional object of $COMMENT-*-like keys and string values.", // $COMMENT#JSDOC#DEFINITIONS#FLATTENCONFIGDATA
85
- resolveConfig:
86
- "Verifies, validates and resolves the config path to retrieve the config's data and ignores.", // $COMMENT#JSDOC#DEFINITIONS#RESOLVECONFIG
87
81
  logError:
88
82
  'Logs an error to the console depending on its type. (`"error"` or `"warning"`.)', // $COMMENT#JSDOC#DEFINITIONS#LOGERROR
89
83
  }),
90
84
  params: Object.freeze({
91
- string: "The string.", // $COMMENT#JSDOC#PARAMS#STRING
92
85
  flattenedConfigData:
93
86
  "The flattened config data, with $COMMENT#* placeholders as keys and actual comments as values.", // $COMMENT#JSDOC#PARAMS#FLATTENEDCONFIGDATA
94
87
  reversedFlattenedConfigData:
@@ -99,29 +92,16 @@ const data = {
99
92
  "The array of paths and globs for the flow's ESLint instance to ignore.", // $COMMENT#JSDOC#PARAMS#IGNORES
100
93
  eitherFlattenedConfigData:
101
94
  "Either the flattened config data or the reversed flattened config data, since they share the same structure.", // $COMMENT#JSDOC#PARAMS#EITHERFLATTENEDCONFIGDATA
102
- configData:
103
- "The config's data property. (Values are typed `unknown` given the limitations in typing recursive values in JSDoc.)", // $COMMENT#JSDOC#PARAMS#CONFIGDATA
104
- configDataMapOption:
105
- "The map housing the flattened keys with their values and sources through recursion, instantiated as a `new Map()`.", // $COMMENT#JSDOC#PARAMS#CONFIGDATAMAPOPTION
106
- parentKeysOption:
107
- "The list of keys that are parent to the key at hand given the recursive nature of the config's data's data structure, instantiated as an empty array of strings (`[]`).", // $COMMENT#JSDOC#PARAMS#PARENTKEYSOPTION
108
- configPath:
109
- 'The path of the config from `comments.config.js`, or from a config passed via the `--config` flag in the CLI, or from one passed via `"commentVariables.config": true` in `.vscode/settings.json` for the VS Code Extension.', // $COMMENT#JSDOC#PARAMS#CONFIGPATH
95
+ error: "The error object being handle for the logging.", // $COMMENT#JSDOC#PARAMS#ERROR
110
96
  options: "The additional options as follows:", // $COMMENT#JSDOC#PARAMS#OPTIONS
111
97
  settings: "The required settings as follows:", // $COMMENT#JSDOC#PARAMS#SETTINGS
112
- error: "The error object being handle for the logging.", // $COMMENT#JSDOC#PARAMS#ERROR
113
98
  }),
114
99
  returns: Object.freeze({
115
100
  exitDueToFailure:
116
101
  "Never. (Somehow typing needs to be explicit for unreachable code inference.)", // $COMMENT#JSDOC#RETURNS#EXITDUETOFAILURE
117
- escapeRegex: `The string with regex characters escaped.`, // $COMMENT#JSDOC#RETURNS#ESCAPEREGEX
118
102
  makeRuleResolve: "The resolve rule based on the flattened config data.", // $COMMENT#JSDOC#RETURNS#MAKERULERESOLVE
119
103
  makeRuleCompress:
120
104
  "The compress rule based on the reversed flattened config data.", // $COMMENT#JSDOC#RETURNS#MAKERULECOMPRESS
121
- flattenConfigData:
122
- "Both the flattened config data and its reversed version to ensure the strict reversibility of the `resolve` and `compress` commands in a success object (`success: true`). Errors are bubbled up during failures so they can be reused differently on the CLI and the VS Code Extension in a failure object (`success: false`).", // $COMMENT#JSDOC#RETURNS#FLATTENCONFIGDATA
123
- resolveConfig:
124
- "The flattened config data, the reverse flattened config data, the verified config path, the raw passed ignores, and the original config. Errors are returned during failures so they can be reused differently on the CLI and the VS Code Extension.", // $COMMENT#JSDOC#RETURNS#RESOLVECONFIG
125
105
  }),
126
106
  }),
127
107
  };
@@ -138,4 +118,4 @@ export default config;
138
118
 
139
119
  And yes, even comments within JavaScript and TypeScript blocks in Markdown files are addressed.
140
120
 
141
- _Leverage the full power of JavaScript to programmatically design your JavaScript comments._
121
+ _Leverage the power of JavaScript to programmatically design your JavaScript comments._
@@ -17,8 +17,6 @@ const data = {
17
17
  definitions: Object.freeze({
18
18
  exitDueToFailure:
19
19
  "Terminates the whole process with a 'failure' code (1).", // $COMMENT#JSDOC#DEFINITIONS#EXITDUETOFAILURE
20
- escapeRegex:
21
- 'Escapes all regex characters with a `"\\"` in a string to prepare it for use in a regex.', // $COMMENT#JSDOC#DEFINITIONS#ESCAPEREGEX
22
20
  makeRuleResolve:
23
21
  "The utility that creates the resolve rule based on the flattened config data, used to transform $COMMENT#* placeholders into actual comments.", // $COMMENT#JSDOC#DEFINITIONS#MAKERULERESOLVE
24
22
  makeRuleCompress:
@@ -29,15 +27,10 @@ const data = {
29
27
  "The flow that resolves $COMMENT#* placeholders intro actual comments.", // $COMMENT#JSDOC#DEFINITIONS#RESOLVECOMMENTSFLOW
30
28
  compressCommentsFlow:
31
29
  "The flow that compresses actual comments into $COMMENT#* placeholders.", // $COMMENT#JSDOC#DEFINITIONS#COMPRESSCOMMENTSFLOW
32
- flattenConfigData:
33
- "Flattens the config's data property into a one-dimensional object of $COMMENT-*-like keys and string values.", // $COMMENT#JSDOC#DEFINITIONS#FLATTENCONFIGDATA
34
- resolveConfig:
35
- "Verifies, validates and resolves the config path to retrieve the config's data and ignores.", // $COMMENT#JSDOC#DEFINITIONS#RESOLVECONFIG
36
30
  logError:
37
31
  'Logs an error to the console depending on its type. (`"error"` or `"warning"`.)', // $COMMENT#JSDOC#DEFINITIONS#LOGERROR
38
32
  }),
39
33
  params: Object.freeze({
40
- string: "The string.", // $COMMENT#JSDOC#PARAMS#STRING
41
34
  flattenedConfigData:
42
35
  "The flattened config data, with $COMMENT#* placeholders as keys and actual comments as values.", // $COMMENT#JSDOC#PARAMS#FLATTENEDCONFIGDATA
43
36
  reversedFlattenedConfigData:
@@ -48,29 +41,16 @@ const data = {
48
41
  "The array of paths and globs for the flow's ESLint instance to ignore.", // $COMMENT#JSDOC#PARAMS#IGNORES
49
42
  eitherFlattenedConfigData:
50
43
  "Either the flattened config data or the reversed flattened config data, since they share the same structure.", // $COMMENT#JSDOC#PARAMS#EITHERFLATTENEDCONFIGDATA
51
- configData:
52
- "The config's data property. (Values are typed `unknown` given the limitations in typing recursive values in JSDoc.)", // $COMMENT#JSDOC#PARAMS#CONFIGDATA
53
- configDataMapOption:
54
- "The map housing the flattened keys with their values and sources through recursion, instantiated as a `new Map()`.", // $COMMENT#JSDOC#PARAMS#CONFIGDATAMAPOPTION
55
- parentKeysOption:
56
- "The list of keys that are parent to the key at hand given the recursive nature of the config's data's data structure, instantiated as an empty array of strings (`[]`).", // $COMMENT#JSDOC#PARAMS#PARENTKEYSOPTION
57
- configPath:
58
- 'The path of the config from `comments.config.js`, or from a config passed via the `--config` flag in the CLI, or from one passed via `"commentVariables.config": true` in `.vscode/settings.json` for the VS Code Extension.', // $COMMENT#JSDOC#PARAMS#CONFIGPATH
44
+ error: "The error object being handle for the logging.", // $COMMENT#JSDOC#PARAMS#ERROR
59
45
  options: "The additional options as follows:", // $COMMENT#JSDOC#PARAMS#OPTIONS
60
46
  settings: "The required settings as follows:", // $COMMENT#JSDOC#PARAMS#SETTINGS
61
- error: "The error object being handle for the logging.", // $COMMENT#JSDOC#PARAMS#ERROR
62
47
  }),
63
48
  returns: Object.freeze({
64
49
  exitDueToFailure:
65
50
  "Never. (Somehow typing needs to be explicit for unreachable code inference.)", // $COMMENT#JSDOC#RETURNS#EXITDUETOFAILURE
66
- escapeRegex: `The string with regex characters escaped.`, // $COMMENT#JSDOC#RETURNS#ESCAPEREGEX
67
51
  makeRuleResolve: "The resolve rule based on the flattened config data.", // $COMMENT#JSDOC#RETURNS#MAKERULERESOLVE
68
52
  makeRuleCompress:
69
53
  "The compress rule based on the reversed flattened config data.", // $COMMENT#JSDOC#RETURNS#MAKERULECOMPRESS
70
- flattenConfigData:
71
- "Both the flattened config data and its reversed version to ensure the strict reversibility of the `resolve` and `compress` commands in a success object (`success: true`). Errors are bubbled up during failures so they can be reused differently on the CLI and the VS Code Extension in a failure object (`success: false`).", // $COMMENT#JSDOC#RETURNS#FLATTENCONFIGDATA
72
- resolveConfig:
73
- "The flattened config data, the reverse flattened config data, the verified config path, the raw passed ignores, and the original config. Errors are returned during failures so they can be reused differently on the CLI and the VS Code Extension.", // $COMMENT#JSDOC#RETURNS#RESOLVECONFIG
74
54
  }),
75
55
  }),
76
56
  };
@@ -1,11 +1,6 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
3
 
4
- import tseslint from "typescript-eslint";
5
-
6
- // plugin name
7
- export const commentVariablesPluginName = "comment-variables";
8
-
9
4
  // rule names
10
5
  export const resolveRuleName = "resolve";
11
6
  export const compressRuleName = "compress";
@@ -18,25 +13,6 @@ export const hasPackageJson = fs.existsSync(path.join(cwd, "package.json"));
18
13
  // to prevent irreversible changes
19
14
  export const hasGitFolder = fs.existsSync(path.join(cwd, ".git"));
20
15
 
21
- // comments.config.js // comment-variables-resolve-config
22
- export const defaultConfigFileName = "comments.config.js";
23
-
24
- // flags // comment-variables-resolve-config
25
- export const configFlag = "--config";
26
- export const lintConfigImportsFlag = "--lint-config-imports";
27
- export const myIgnoresOnlyFlag = "--my-ignores-only";
28
-
29
- // ESLint ignores
30
- export const knownIgnores = [
31
- "node_modules",
32
- "dist",
33
- "out",
34
- ".next",
35
- ".react-router",
36
- ".parcel-cache",
37
- ".react-router-parcel",
38
- ];
39
-
40
16
  // ESLint file globs
41
17
  export const allJSTSFileGlobs = [
42
18
  "**/*.js",
@@ -55,37 +31,3 @@ export const allMDVirtualJSTSFileGlobs = [
55
31
  "**/*.md/*.cjs",
56
32
  "**/*.md/*.mjs",
57
33
  ];
58
-
59
- // default ESLint config language options
60
- export const typeScriptAndJSXCompatible = {
61
- // for compatibility with TypeScript (.ts and .tsx)
62
- parser: tseslint.parser,
63
- // for compatibility with JSX (React, etc.)
64
- parserOptions: {
65
- ecmaFeatures: {
66
- jsx: true,
67
- },
68
- },
69
- };
70
-
71
- // messageId
72
- export const placeholderMessageId = "placeholderMessageId";
73
-
74
- // placeholder prefix // comment-variables-resolve-config
75
- export const $COMMENT = "$COMMENT";
76
-
77
- // success objects // comment-variables-resolve-config
78
- export const successFalse = Object.freeze({
79
- success: false,
80
- });
81
- export const successTrue = Object.freeze({
82
- success: true,
83
- });
84
-
85
- // error objects // comment-variables-resolve-config
86
- export const typeError = Object.freeze({
87
- type: "error",
88
- });
89
- export const typeWarning = Object.freeze({
90
- type: "warning",
91
- });
@@ -1,6 +1,8 @@
1
- import { placeholderMessageId, $COMMENT } from "../constants/bases.js";
2
-
3
- import { escapeRegex } from "..//utilities/helpers.js";
1
+ import {
2
+ $COMMENT,
3
+ placeholderMessageId,
4
+ makeIsolatedStringRegex,
5
+ } from "comment-variables-resolve-config";
4
6
 
5
7
  /**
6
8
  * The utility that creates the compress rule based on the reversed flattened config data, used to transform actual comments into $COMMENT#* placeholders.
@@ -42,10 +44,7 @@ const makeRule = (reversedFlattenedConfigData) => {
42
44
  resolvedValue,
43
45
  commentKey,
44
46
  ] of sortedReversedFlattenedConfigData) {
45
- const pattern = new RegExp(
46
- `(?<=\\s|^)${escapeRegex(resolvedValue)}(?=\\s|$)`,
47
- "g"
48
- );
47
+ const pattern = makeIsolatedStringRegex(resolvedValue);
49
48
 
50
49
  fixedText = fixedText.replace(pattern, () => {
51
50
  modified = true;
@@ -1,5 +1,7 @@
1
- import { placeholderMessageId } from "../constants/bases.js";
2
- import { flattenedConfigPlaceholderRegex } from "../constants/regexes.js";
1
+ import {
2
+ flattenedConfigPlaceholderRegex,
3
+ placeholderMessageId,
4
+ } from "comment-variables-resolve-config";
3
5
 
4
6
  /**
5
7
  * The utility that creates the resolve rule based on the flattened config data, used to transform $COMMENT#* placeholders into actual comments.
@@ -3,12 +3,15 @@ import markdown from "@eslint/markdown";
3
3
 
4
4
  import {
5
5
  commentVariablesPluginName,
6
+ typeScriptAndJSXCompatible,
7
+ } from "comment-variables-resolve-config";
8
+
9
+ import {
6
10
  resolveRuleName,
7
11
  compressRuleName,
8
12
  allJSTSFileGlobs,
9
13
  allMDFileGlobs,
10
14
  allMDVirtualJSTSFileGlobs,
11
- typeScriptAndJSXCompatible,
12
15
  } from "../constants/bases.js";
13
16
  import { ruleNames_makeRules } from "../constants/rules.js";
14
17
 
@@ -6,6 +6,8 @@
6
6
  */
7
7
  export const exitDueToFailure = () => process.exit(1);
8
8
 
9
+ /* logError */
10
+
9
11
  /**
10
12
  * Logs an error to the console depending on its type. (`"error"` or `"warning"`.)
11
13
  * @param {{type: "error" | "warning"; message: string}} error The error object being handle for the logging.
@@ -23,13 +25,3 @@ export const logError = (error) => {
23
25
  break;
24
26
  }
25
27
  };
26
-
27
- /* escapeRegex */ // comment-variables-resolve-config
28
-
29
- /**
30
- * Escapes all regex characters with a `"\"` in a string to prepare it for use in a regex.
31
- * @param {string} string The string.
32
- * @returns The string with regex characters escaped.
33
- */
34
- export const escapeRegex = (string) =>
35
- string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
package/library/index.js CHANGED
@@ -3,22 +3,23 @@
3
3
 
4
4
  import path from "path";
5
5
 
6
+ import resolveConfig, {
7
+ defaultConfigFileName,
8
+ configFlag,
9
+ lintConfigImportsFlag,
10
+ myIgnoresOnlyFlag,
11
+ knownIgnores,
12
+ } from "comment-variables-resolve-config";
13
+
6
14
  import {
7
15
  cwd,
8
16
  hasPackageJson,
9
17
  hasGitFolder,
10
- defaultConfigFileName, // shared
11
- configFlag, // shared
12
- lintConfigImportsFlag, // shared
13
- myIgnoresOnlyFlag, // shared
14
- knownIgnores, // shared
15
18
  resolveRuleName,
16
19
  compressRuleName,
17
20
  } from "./_commons/constants/bases.js";
18
21
 
19
22
  import { exitDueToFailure, logError } from "./_commons/utilities/helpers.js";
20
- import { resolveConfig } from "./_commons/utilities/resolve-config.js"; // shared
21
- import { findAllImports } from "find-all-js-imports"; // own package
22
23
  import {
23
24
  resolveCommentsFlow,
24
25
  compressCommentsFlow,
@@ -61,18 +62,23 @@ const passedConfigPath =
61
62
  // defaults to comments.config.js if no --config flag is set
62
63
  const rawConfigPath = passedConfigPath ?? path.join(cwd, defaultConfigFileName);
63
64
 
65
+ console.log(`Resolving config at ${rawConfigPath}...`);
66
+
64
67
  const resolveConfigResults = await resolveConfig(rawConfigPath);
65
68
  if (!resolveConfigResults.success) {
66
69
  resolveConfigResults.errors.forEach((e) => logError(e));
67
70
  exitDueToFailure();
68
71
  }
69
72
 
73
+ console.log("Config resolved.");
74
+
70
75
  const {
71
76
  config,
72
77
  flattenedConfigData,
73
78
  reversedFlattenedConfigData,
74
79
  configPath,
75
80
  passedIgnores,
81
+ rawConfigAndImportPaths,
76
82
  } = resolveConfigResults;
77
83
 
78
84
  skipDetails || console.log("Running with config:", config);
@@ -88,21 +94,9 @@ skipDetails || console.log("Passed ignores are:", passedIgnores);
88
94
  // ADDRESSES THE --lint-config-imports FLAG, GIVEN THAT THE FILES IMPORTED BY THE CONFIG ARE IGNORED BY DEFAULT.
89
95
 
90
96
  const lintConfigImports = commands.indexOf(lintConfigImportsFlag) >= 2;
91
- let rawConfigPathIgnores = [configPath];
92
-
93
- if (!lintConfigImports) {
94
- const findAllImportsResults = findAllImports(configPath);
95
- if (!findAllImportsResults.success) {
96
- findAllImportsResults.errors.forEach((e) => logError(e));
97
- console.warn(
98
- "Defaulting to --lint-config-imports flag behavior, not ignoring config path imports, only the config path itself."
99
- );
100
- } else {
101
- rawConfigPathIgnores = [...findAllImportsResults.visitedSet] ?? [
102
- configPath,
103
- ];
104
- }
105
- }
97
+ const rawConfigPathIgnores = lintConfigImports
98
+ ? [configPath]
99
+ : rawConfigAndImportPaths;
106
100
 
107
101
  // the ignore paths must be relative
108
102
  const configPathIgnores = rawConfigPathIgnores.map((e) =>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comment-variables",
3
- "version": "0.6.2",
3
+ "version": "0.8.1",
4
4
  "description": "A CLI tool for configuring, managing and maintaining JavaScript comments as JavaScript variables.",
5
5
  "bin": {
6
6
  "jscomments": "./library/index.js",
@@ -26,10 +26,8 @@
26
26
  "type": "module",
27
27
  "dependencies": {
28
28
  "@eslint/markdown": "^6.5.0",
29
+ "comment-variables-resolve-config": "^1.3.2",
29
30
  "eslint": "^9.29.0",
30
- "find-all-js-imports": "^1.0.0",
31
- "tsconfig-paths": "^4.2.0",
32
- "typescript-eslint": "^8.34.1",
33
31
  "zod": "^3.25.67"
34
32
  },
35
33
  "devDependencies": {
@@ -1,13 +0,0 @@
1
- import { $COMMENT } from "./bases.js";
2
-
3
- import { escapeRegex } from "../utilities/helpers.js";
4
-
5
- // comment-variables-resolve-config
6
- export const configKeyRegex = /^[\p{Ll}\p{Lu}\p{Lo}\p{Pd}\p{Pc}\p{N}\s]+$/u;
7
- // comment-variables-resolve-config
8
- export const flattenedConfigKeyRegex = /^[\p{Lu}\p{Lo}\p{Pd}\p{Pc}\p{N}#]+$/u; // same as configKeyRegex but without lowercase letters (\p{Ll}), without whitespaces (\s which are replaced by underscores) and with the '#' character (that links each subkey together)
9
- // comment-variables-resolve-config
10
- export const flattenedConfigPlaceholderRegex = new RegExp(
11
- `${escapeRegex($COMMENT)}#([\\p{Lu}\\p{Lo}\\p{Pd}\\p{Pc}\\p{N}#_]+)`,
12
- "gu"
13
- ); // same as flattenedConfigKeyRegex but taking the prefix $COMMENT and its # into consideration, removing ^ and $ in the capture group, and using _ as replacement for whitesplaces, globally
@@ -1,67 +0,0 @@
1
- import { z } from "zod";
2
-
3
- import { configKeyRegex } from "../constants/regexes.js";
4
-
5
- export const ConfigDataSchema = z
6
- .lazy(() =>
7
- z.record(
8
- z.unknown().superRefine((val, ctx) => {
9
- if (typeof val === "string") {
10
- return;
11
- }
12
-
13
- if (typeof val === "object" && val && !Array.isArray(val)) {
14
- const parsed = ConfigDataSchema.safeParse(val);
15
- if (!parsed.success) {
16
- for (const issue of parsed.error.issues) {
17
- ctx.addIssue({
18
- ...issue,
19
- path: [...ctx.path, ...issue.path],
20
- });
21
- }
22
- }
23
- return;
24
- }
25
-
26
- ctx.addIssue({
27
- code: z.ZodIssueCode.custom,
28
- message: `Value \`${val}\` of type "${typeof val}" should be a string or a nested object.`,
29
- path: ctx.path,
30
- });
31
- })
32
- )
33
- )
34
- .superRefine((obj, ctx) => {
35
- for (const key of Object.keys(obj)) {
36
- if (key.includes("$")) {
37
- ctx.addIssue({
38
- code: z.ZodIssueCode.custom,
39
- message: `Key "${key}" should not include the "$" character.`,
40
- path: [key],
41
- });
42
- }
43
- if (key.includes("#")) {
44
- ctx.addIssue({
45
- code: z.ZodIssueCode.custom,
46
- message: `Key "${key}" should not include the "#" character.`,
47
- path: [key],
48
- });
49
- }
50
- if (!configKeyRegex.test(key)) {
51
- ctx.addIssue({
52
- code: z.ZodIssueCode.custom,
53
- message: `Key "${key}" should only include whitespaces (s), lowercase letters (Ll), uppercase letters (Lu), other letters (Lo), numbers (N), dash punctuation (Pd), and connector punctuation (Pc).`,
54
- path: [key],
55
- });
56
- }
57
- }
58
- });
59
-
60
- export const ConfigIgnoresSchema = z.array(
61
- z.string({
62
- message: `The config's "ignores" key array should be made of string or be empty.`,
63
- }),
64
- {
65
- message: `The config's "ignores" key value should be an array of strings (or at the very least an empty array).`,
66
- }
67
- );
@@ -1,145 +0,0 @@
1
- import { successFalse, successTrue, typeError } from "../constants/bases.js";
2
- import { flattenedConfigKeyRegex } from "../constants/regexes.js";
3
-
4
- /**
5
- * @typedef {Record<string, unknown>} ConfigData
6
- *
7
- * @typedef {{
8
- * success: false;
9
- * errors: Array<{ type: "error" | "warning"; message: string }>;
10
- * } | {
11
- * success: true;
12
- * flattenedConfigData: Record<string, string>;
13
- * reversedFlattenedConfigData: Record<string, string>;
14
- * }} FlattenConfigDataResults
15
- */
16
-
17
- /**
18
- * Flattens the config's data property into a one-dimensional object of $COMMENT-*-like keys and string values.
19
- * @param {ConfigData} configData The config's data property. (Values are typed `unknown` given the limitations in typing recursive values in JSDoc.)
20
- * @param {Object} [options] The additional options as follows:
21
- * @param {Map<string, {value: string; source: string}>} [options.configDataMap] The map housing the flattened keys with their values and sources through recursion, instantiated as a `new Map()`.
22
- * @param {string[]} [options.parentKeys] The list of keys that are parent to the key at hand given the recursive nature of the config's data's data structure, instantiated as an empty array of strings (`[]`).
23
- * @returns Both the flattened config data and its reversed version to ensure the strict reversibility of the `resolve` and `compress` commands in a success object (`success: true`). Errors are bubbled up during failures so they can be reused differently on the CLI and the VS Code Extension in a failure object (`success: false`).
24
- */
25
- export const flattenConfigData = (
26
- configData,
27
- { configDataMap = new Map(), parentKeys = [] } = {}
28
- ) => {
29
- for (const [key, value] of Object.entries(configData)) {
30
- const newKeys = [...parentKeys, key];
31
- const normalizedKey = newKeys
32
- .map((k) => k.toUpperCase())
33
- .join("#")
34
- .replace(/\s/g, "_");
35
- const source = newKeys.join(" > ");
36
-
37
- if (typeof value === "string") {
38
- if (configDataMap.has(normalizedKey)) {
39
- // checks the uniqueness of each normalized key
40
- return {
41
- ...successFalse,
42
- errors: [
43
- {
44
- ...typeError,
45
- message: `ERROR. The normalized key "${normalizedKey}" has already been assigned. Check between the two following key paths: \n"${
46
- configDataMap.get(normalizedKey).source
47
- }" \n"${source}"`,
48
- },
49
- ],
50
- };
51
- }
52
-
53
- configDataMap.set(normalizedKey, {
54
- value,
55
- source,
56
- });
57
- } else if (typeof value === "object" && value && !Array.isArray(value)) {
58
- const subConfigData = /** @type {ConfigData} */ (value);
59
- const flattenConfigDataOptions = { configDataMap, parentKeys: newKeys };
60
-
61
- const flattenConfigDataResults = /** @type {FlattenConfigDataResults} */ (
62
- flattenConfigData(subConfigData, flattenConfigDataOptions)
63
- );
64
- if (!flattenConfigDataResults.success) return flattenConfigDataResults;
65
- }
66
- }
67
-
68
- // At this point we're out of the recursion, and we can start working with the complete data.
69
-
70
- // strips metadata
71
- /**@type {Map<string, string>} */
72
- const map = new Map();
73
- configDataMap.forEach((value, key) => {
74
- map.set(key, value.value);
75
- });
76
-
77
- // makes the flattened config data object
78
- const flattenedConfigData = Object.fromEntries(map);
79
-
80
- // The integrity of the flattened config data needs to be established before working with it safely.
81
-
82
- const flattenedConfigDataKeysSet = new Set(Object.keys(flattenedConfigData));
83
-
84
- const flattenedConfigDataValuesArray = Object.values(flattenedConfigData);
85
- const flattenedConfigDataValuesSet = new Set(flattenedConfigDataValuesArray);
86
-
87
- for (const key of flattenedConfigDataKeysSet) {
88
- if (flattenedConfigDataValuesSet.has(key)) {
89
- // checks the reversability of flattenedConfigData
90
- return {
91
- ...successFalse,
92
- errors: [
93
- {
94
- ...typeError,
95
- message: `ERROR. The key "${key}" is and shouldn't be among the values of flattenedConfigData.`,
96
- },
97
- ],
98
- };
99
- }
100
- if (!flattenedConfigKeyRegex.test(key)) {
101
- // checks if each key for flattenedConfigData passes the flattenedConfigKeyRegex test
102
- return {
103
- ...successFalse,
104
- errors: [
105
- {
106
- ...typeError,
107
- message: `ERROR. Somehow the key "${key}" is not properly formatted. (This is mostly an internal mistake.)`,
108
- },
109
- ],
110
- };
111
- }
112
- }
113
-
114
- /** @type {Set<string>} */
115
- const set = new Set();
116
-
117
- for (const value of flattenedConfigDataValuesArray) {
118
- if (set.has(value)) {
119
- console.log("errors, duplicate value");
120
- // checks that no two values are duplicate
121
- return {
122
- ...successFalse,
123
- errors: [
124
- {
125
- ...typeError,
126
- message: `ERROR. The value "${value}" is already assigned to an existing key.`,
127
- },
128
- ],
129
- };
130
- }
131
- set.add(value);
132
- }
133
-
134
- // Also including the reversed flattened config data.
135
-
136
- const reversedFlattenedConfigData = Object.fromEntries(
137
- Object.entries(flattenedConfigData).map(([key, value]) => [value, key])
138
- );
139
-
140
- return {
141
- ...successTrue,
142
- flattenedConfigData,
143
- reversedFlattenedConfigData,
144
- };
145
- };
@@ -1,110 +0,0 @@
1
- import fs from "fs";
2
- import url from "url";
3
-
4
- import { successFalse, typeError } from "../constants/bases.js";
5
-
6
- import { flattenConfigData } from "./flatten-config-data.js";
7
-
8
- import { ConfigDataSchema, ConfigIgnoresSchema } from "../schemas/config.js";
9
-
10
- /**
11
- * Verifies, validates and resolves the config path to retrieve the config's data and ignores.
12
- * @param {string} configPath The path of the config from `comments.config.js`, or from a config passed via the `--config` flag in the CLI, or from one passed via `"commentVariables.config": true` in `.vscode/settings.json` for the VS Code Extension.
13
- * @returns The flattened config data, the reverse flattened config data, the verified config path, the raw passed ignores, and the original config. Errors are returned during failures so they can be reused differently on the CLI and the VS Code Extension.
14
- */
15
- export async function resolveConfig(configPath) {
16
- // Step 1: Checks if config file exists
17
-
18
- if (!fs.existsSync(configPath)) {
19
- return {
20
- ...successFalse,
21
- errors: [
22
- {
23
- ...typeError,
24
- message: "ERROR. No config file found.",
25
- },
26
- ],
27
- };
28
- }
29
-
30
- // Step 2: Imports the config dynamically
31
-
32
- const configModule = /** @type {unknown} */ (
33
- await import(url.pathToFileURL(configPath))
34
- );
35
- const config = /** @type {unknown} */ (configModule.default);
36
-
37
- // Step 3: Validates config object
38
-
39
- // validates config
40
- if (!config || typeof config !== "object" || Array.isArray(config)) {
41
- return {
42
- ...successFalse,
43
- errors: [
44
- {
45
- ...typeError,
46
- message:
47
- "ERROR. Invalid config format. The config should be an object.",
48
- },
49
- ],
50
- };
51
- }
52
-
53
- // validates config.data
54
- const configDataResult = ConfigDataSchema.safeParse(config.data);
55
-
56
- if (!configDataResult.success) {
57
- return {
58
- ...successFalse,
59
- errors: [
60
- {
61
- ...typeError,
62
- message: "ERROR. Config data could not pass validation from zod.",
63
- },
64
- ...configDataResult.error.errors.map((e) => ({
65
- ...typeError,
66
- message: e.message,
67
- })),
68
- ],
69
- };
70
- }
71
-
72
- // validates config.ignores
73
- const configIgnoresSchemaResult = ConfigIgnoresSchema.safeParse(
74
- config.ignores
75
- );
76
-
77
- if (!configIgnoresSchemaResult.success) {
78
- return {
79
- ...successFalse,
80
- errors: [
81
- {
82
- ...typeError,
83
- message: "ERROR. Config ignores could not pass validation from zod.",
84
- },
85
- ...configIgnoresSchemaResult.error.errors.map((e) => ({
86
- ...typeError,
87
- message: e.message,
88
- })),
89
- ],
90
- };
91
- }
92
-
93
- const flattenedConfigDataResults = flattenConfigData(configDataResult.data);
94
-
95
- if (!flattenedConfigDataResults.success) {
96
- return flattenedConfigDataResults;
97
- }
98
-
99
- // sends back:
100
- // - the flattened config data,
101
- // - the reverse flattened config data,
102
- // - the verified config path
103
- // - and the raw passed ignores
104
- return {
105
- ...flattenedConfigDataResults, // finalized
106
- configPath, // finalized
107
- passedIgnores: configIgnoresSchemaResult.data, // addressed with --lint-config-imports and --my-ignores-only to be finalized
108
- config, // and the config itself too
109
- };
110
- }