comment-variables 0.4.2 → 0.6.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.
@@ -31,11 +31,14 @@ const data = {
31
31
  "The flow that compresses actual comments into $COMMENT#* placeholders.", // $COMMENT#JSDOC#DEFINITIONS#COMPRESSCOMMENTSFLOW
32
32
  findAllImports:
33
33
  "Finds all import paths recursively related to a given file path.", // $COMMENT#JSDOC#DEFINITIONS#FINDALLIMPORTS
34
- processImport: "Processes recursively and resolves a single import path.", // $COMMENT#JSDOC#DEFINITIONS#PROCESSIMPORT
34
+ processImport:
35
+ "Processes recursively and resolves a single import path. (Unlike `findAllImports`, here `currentDir`, `cwd`, `visitedSet`, `depth`, and `maxDepth` aren't options because they are mandatory and not pre-parameterized.)", // $COMMENT#JSDOC#DEFINITIONS#PROCESSIMPORT
35
36
  flattenConfigData:
36
37
  "Flattens the config's data property into a one-dimensional object of $COMMENT-*-like keys and string values.", // $COMMENT#JSDOC#DEFINITIONS#FLATTENCONFIGDATA
37
38
  resolveConfig:
38
39
  "Verifies, validates and resolves the config path to retrieve the config's data and ignores.", // $COMMENT#JSDOC#DEFINITIONS#RESOLVECONFIG
40
+ logError:
41
+ 'Logs an error to the console depending on its type. (`"error"` or `"warning"`.)', // $COMMENT#JSDOC#DEFINITIONS#LOGERROR
39
42
  }),
40
43
  params: Object.freeze({
41
44
  string: "The string.", // $COMMENT#JSDOC#PARAMS#STRING
@@ -51,24 +54,33 @@ const data = {
51
54
  "Either the flattened config data or the reversed flattened config data, since they share the same structure.", // $COMMENT#JSDOC#PARAMS#EITHERFLATTENEDCONFIGDATA
52
55
  filePath:
53
56
  "The absolute path of the file whose imports are being recursively found, such as that of a project's `comments.config.js` file.", // $COMMENT#JSDOC#PARAMS#FILEPATH
54
- cwd: "The current working directory, set as `process.cwd()` by default.", // $COMMENT#JSDOC#PARAMS#CWD
55
- visitedSet:
56
- "The set of strings tracking the import paths that have already been visited, instantiated as a `new Set()` by default.", // $COMMENT#JSDOC#PARAMS#VISITEDSET
57
- depth:
58
- "The current depth of the recursion, instantiated at `0` by default.", // $COMMENT#JSDOC#PARAMS#DEPTH
59
- maxDepth:
60
- "The maximum depth allowed for the recursion, instantiated at `100` by default.", // $COMMENT#JSDOC#PARAMS#MAXDEPTH
57
+ cwdOption:
58
+ "The current working directory, set as `process.cwd()` by default.", // $COMMENT#JSDOC#PARAMS#CWDOPTION
59
+ visitedSetOption:
60
+ "The set of strings tracking the import paths that have already been visited, instantiated as a `new Set()` by default.", // $COMMENT#JSDOC#PARAMS#VISITEDSETOPTION
61
+ depthOption:
62
+ "The current depth of the recursion, instantiated at `0` by default.", // $COMMENT#JSDOC#PARAMS#DEPTHOPTION
63
+ maxDepthOption:
64
+ "The maximum depth allowed for the recursion, instantiated at `100` by default.", // $COMMENT#JSDOC#PARAMS#MAXDEPTHOPTION
61
65
  importPath: "The import path currently being addressed.", // $COMMENT#JSDOC#PARAMS#IMPORTPATH
62
- currentDir:
63
- "The directory containing the import path currently being addressed.", // $COMMENT#JSDOC#PARAMS#CURRENTDIR
66
+ currentDirSetting:
67
+ "The directory containing the import path currently being addressed.", // $COMMENT#JSDOC#PARAMS#CURRENTDIRSETTING
68
+ cwdSetting: "The current working directory.", // $COMMENT#JSDOC#PARAMS#CWDSETTING
69
+ visitedSetSetting:
70
+ "The set of strings tracking the import paths that have already been visited.", // $COMMENT#JSDOC#PARAMS#VISITEDSETSETTING
71
+ depthSetting: "The current depth of the recursion.", // $COMMENT#JSDOC#PARAMS#DEPTHSETTING
72
+ maxDepthSetting: "The maximum depth allowed for the recursion.", // $COMMENT#JSDOC#PARAMS#MAXDEPTHSETTING
64
73
  configData:
65
- "The config's data property. (Values are typed `any` given the limitations in typing recursive values in JSDoc.)", // $COMMENT#JSDOC#PARAMS#CONFIGDATA
66
- configDataMap:
67
- "The map housing the flattened keys with their values and sources through recursion, instantiated as a `new Map()`.", // $COMMENT#JSDOC#PARAMS#CONFIGDATAMAP
68
- parentKeys:
69
- "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#PARENTKEYS
74
+ "The config's data property. (Values are typed `unknown` given the limitations in typing recursive values in JSDoc.)", // $COMMENT#JSDOC#PARAMS#CONFIGDATA
75
+ configDataMapOption:
76
+ "The map housing the flattened keys with their values and sources through recursion, instantiated as a `new Map()`.", // $COMMENT#JSDOC#PARAMS#CONFIGDATAMAPOPTION
77
+ parentKeysOption:
78
+ "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
70
79
  configPath:
71
- "The path of the config, either from `comments.config.js` or from a config passed via the `--config` flag.", // $COMMENT#JSDOC#PARAMS#CONFIGPATH
80
+ '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
81
+ options: "The additional options as follows:", // $COMMENT#JSDOC#PARAMS#OPTIONS
82
+ settings: "The required settings as follows:", // $COMMENT#JSDOC#PARAMS#SETTINGS
83
+ error: "The error object being handle for the logging.", // $COMMENT#JSDOC#PARAMS#ERROR
72
84
  }),
73
85
  returns: Object.freeze({
74
86
  exitDueToFailure:
@@ -78,13 +90,13 @@ const data = {
78
90
  makeRuleCompress:
79
91
  "The compress rule based on the reversed flattened config data.", // $COMMENT#JSDOC#RETURNS#MAKERULECOMPRESS
80
92
  findAllImports:
81
- "The complete set of strings of import paths recursively related to the given file path, or `null` if an issue has arisen.", // $COMMENT#JSDOC#RETURNS#FINDALLIMPORTS
93
+ "The complete set of strings of import paths recursively related to the given file path in a success object (`success: true`). Errors are bubbled up during failures in a failure object (`success: false`).", // $COMMENT#JSDOC#RETURNS#FINDALLIMPORTS
82
94
  processImport:
83
- "`true` to skip unresolved paths, `false` if resolution fails at any level.", // $COMMENT#JSDOC#RETURNS#PROCESSIMPORT
95
+ "The results of the embedded round of `findAllImports`, since `findAllImports`'s recursion happens within `processImport`.", // $COMMENT#JSDOC#RETURNS#PROCESSIMPORT
84
96
  flattenConfigData:
85
- "Both the flattened config data and its reversed version to ensure the strict reversibility of the `resolve` and `compress` commands.", // $COMMENT#JSDOC#RETURNS#FLATTENCONFIGDATA
97
+ "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
86
98
  resolveConfig:
87
- "The flattened config data, the reverse flattened config data, the verified config path, the raw passed ignores, and the original config.", // $COMMENT#JSDOC#RETURNS#RESOLVECONFIG
99
+ "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
88
100
  }),
89
101
  }),
90
102
  };
@@ -18,10 +18,10 @@ export const hasPackageJson = fs.existsSync(path.join(cwd, "package.json"));
18
18
  // to prevent irreversible changes
19
19
  export const hasGitFolder = fs.existsSync(path.join(cwd, ".git"));
20
20
 
21
- // comments.config.js
21
+ // comments.config.js // comment-variables-resolve-config
22
22
  export const defaultConfigFileName = "comments.config.js";
23
23
 
24
- // flags
24
+ // flags // comment-variables-resolve-config
25
25
  export const configFlag = "--config";
26
26
  export const lintConfigImportsFlag = "--lint-config-imports";
27
27
  export const myIgnoresOnlyFlag = "--my-ignores-only";
@@ -29,11 +29,12 @@ export const myIgnoresOnlyFlag = "--my-ignores-only";
29
29
  // ESLint ignores
30
30
  export const knownIgnores = [
31
31
  "node_modules",
32
+ "dist",
33
+ "out",
32
34
  ".next",
33
35
  ".react-router",
34
36
  ".parcel-cache",
35
37
  ".react-router-parcel",
36
- "dist",
37
38
  ];
38
39
 
39
40
  // ESLint file globs
@@ -70,8 +71,21 @@ export const typeScriptAndJSXCompatible = {
70
71
  // messageId
71
72
  export const placeholderMessageId = "placeholderMessageId";
72
73
 
73
- // regexes
74
- export const configKeyRegex = /^[\p{Ll}\p{Lu}\p{Lo}\p{Pd}\p{Pc}\p{N}\s]+$/u;
75
- 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)
76
- export const flattenedConfigPlaceholderRegex =
77
- /\$COMMENT#([\p{Lu}\p{Lo}\p{Pd}\p{Pc}\p{N}_#]+)/gu; // same as flattenedConfigKeyRegex but taking the prefix $COMMENT# into consideration, removing ^ and $ in the capture group, globally
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
+ });
@@ -0,0 +1,13 @@
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,4 +1,4 @@
1
- import { placeholderMessageId } from "../constants/bases.js";
1
+ import { placeholderMessageId, $COMMENT } from "../constants/bases.js";
2
2
 
3
3
  import { escapeRegex } from "..//utilities/helpers.js";
4
4
 
@@ -49,7 +49,7 @@ const makeRule = (reversedFlattenedConfigData) => {
49
49
 
50
50
  fixedText = fixedText.replace(pattern, () => {
51
51
  modified = true;
52
- return `$COMMENT#${commentKey}`;
52
+ return `${$COMMENT}#${commentKey}`;
53
53
  });
54
54
  }
55
55
 
@@ -1,7 +1,5 @@
1
- import {
2
- placeholderMessageId,
3
- flattenedConfigPlaceholderRegex,
4
- } from "../constants/bases.js";
1
+ import { placeholderMessageId } from "../constants/bases.js";
2
+ import { flattenedConfigPlaceholderRegex } from "../constants/regexes.js";
5
3
 
6
4
  /**
7
5
  * The utility that creates the resolve rule based on the flattened config data, used to transform $COMMENT#* placeholders into actual comments.
@@ -1,11 +1,11 @@
1
1
  import { z } from "zod";
2
2
 
3
- import { configKeyRegex } from "../constants/bases.js";
3
+ import { configKeyRegex } from "../constants/regexes.js";
4
4
 
5
5
  export const ConfigDataSchema = z
6
6
  .lazy(() =>
7
7
  z.record(
8
- z.any().superRefine((val, ctx) => {
8
+ z.unknown().superRefine((val, ctx) => {
9
9
  if (typeof val === "string") {
10
10
  return;
11
11
  }
@@ -1,18 +1,30 @@
1
- import { flattenedConfigKeyRegex } from "../constants/bases.js";
1
+ import { successFalse, successTrue, typeError } from "../constants/bases.js";
2
+ import { flattenedConfigKeyRegex } from "../constants/regexes.js";
2
3
 
3
- import { exitDueToFailure } from "../utilities/helpers.js";
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
+ */
4
16
 
5
17
  /**
6
18
  * Flattens the config's data property into a one-dimensional object of $COMMENT-*-like keys and string values.
7
- * @param {Record<string, any>} configData The config's data property. (Values are typed `any` given the limitations in typing recursive values in JSDoc.)
8
- * @param {Map<string, {value: string; source: string}>} configDataMap The map housing the flattened keys with their values and sources through recursion, instantiated as a `new Map()`.
9
- * @param {string[]} 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.
10
- * @returns Both the flattened config data and its reversed version to ensure the strict reversibility of the `resolve` and `compress` commands.
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`).
11
24
  */
12
25
  export const flattenConfigData = (
13
26
  configData,
14
- configDataMap = new Map(),
15
- parentKeys = []
27
+ { configDataMap = new Map(), parentKeys = [] } = {}
16
28
  ) => {
17
29
  for (const [key, value] of Object.entries(configData)) {
18
30
  const newKeys = [...parentKeys, key];
@@ -24,12 +36,18 @@ export const flattenConfigData = (
24
36
 
25
37
  if (typeof value === "string") {
26
38
  if (configDataMap.has(normalizedKey)) {
27
- console.error(
28
- `ERROR. The normalized key "${normalizedKey}" has already been assigned. Check between the two following key paths: \n"${
29
- configDataMap.get(normalizedKey).source
30
- }" \n"${source}"`
31
- );
32
- exitDueToFailure();
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
+ };
33
51
  }
34
52
 
35
53
  configDataMap.set(normalizedKey, {
@@ -37,10 +55,13 @@ export const flattenConfigData = (
37
55
  source,
38
56
  });
39
57
  } else if (typeof value === "object" && value && !Array.isArray(value)) {
40
- /** @type {Record<string, any>} */
41
- const typedValue = value;
58
+ const subConfigData = /** @type {ConfigData} */ (value);
59
+ const flattenConfigDataOptions = { configDataMap, parentKeys: newKeys };
42
60
 
43
- flattenConfigData(typedValue, configDataMap, newKeys);
61
+ const flattenConfigDataResults = /** @type {FlattenConfigDataResults} */ (
62
+ flattenConfigData(subConfigData, flattenConfigDataOptions)
63
+ );
64
+ if (!flattenConfigDataResults.success) return flattenConfigDataResults;
44
65
  }
45
66
  }
46
67
 
@@ -63,36 +84,52 @@ export const flattenConfigData = (
63
84
  const flattenedConfigDataValuesArray = Object.values(flattenedConfigData);
64
85
  const flattenedConfigDataValuesSet = new Set(flattenedConfigDataValuesArray);
65
86
 
66
- flattenedConfigDataKeysSet.forEach((key) => {
67
- // checks the reversability of flattenedConfigData
87
+ for (const key of flattenedConfigDataKeysSet) {
68
88
  if (flattenedConfigDataValuesSet.has(key)) {
69
- console.error(
70
- `ERROR. The key "${key}" is and shouldn't be among the values of flattenedConfigData.`
71
- );
72
- exitDueToFailure();
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
+ };
73
99
  }
74
100
  if (!flattenedConfigKeyRegex.test(key)) {
75
101
  // checks if each key for flattenedConfigData passes the flattenedConfigKeyRegex test
76
- console.error(
77
- `ERROR. Somehow the key "${key}" is not properly formatted. (This is mostly an internal mistake.)`
78
- );
79
- exitDueToFailure();
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
+ };
80
111
  }
81
- });
112
+ }
82
113
 
83
114
  /** @type {Set<string>} */
84
115
  const set = new Set();
85
116
 
86
- flattenedConfigDataValuesArray.forEach((value) => {
117
+ for (const value of flattenedConfigDataValuesArray) {
87
118
  if (set.has(value)) {
119
+ console.log("errors, duplicate value");
88
120
  // checks that no two values are duplicate
89
- console.error(
90
- `ERROR. The value "${value}" is already assigned to an existing key.`
91
- );
92
- exitDueToFailure();
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
+ };
93
130
  }
94
131
  set.add(value);
95
- });
132
+ }
96
133
 
97
134
  // Also including the reversed flattened config data.
98
135
 
@@ -101,6 +138,7 @@ export const flattenConfigData = (
101
138
  );
102
139
 
103
140
  return {
141
+ ...successTrue,
104
142
  flattenedConfigData,
105
143
  reversedFlattenedConfigData,
106
144
  };
@@ -6,7 +6,25 @@
6
6
  */
7
7
  export const exitDueToFailure = () => process.exit(1);
8
8
 
9
- /* escapeRegex */
9
+ /**
10
+ * Logs an error to the console depending on its type. (`"error"` or `"warning"`.)
11
+ * @param {{type: "error" | "warning"; message: string}} error The error object being handle for the logging.
12
+ */
13
+ export const logError = (error) => {
14
+ switch (error.type) {
15
+ case "error":
16
+ console.error(error.message);
17
+ break;
18
+ case "warning":
19
+ console.warn(error.message);
20
+ break;
21
+ default:
22
+ console.error("ERROR. Error type unrecognized.");
23
+ break;
24
+ }
25
+ };
26
+
27
+ /* escapeRegex */ // comment-variables-resolve-config
10
28
 
11
29
  /**
12
30
  * Escapes all regex characters with a `"\"` in a string to prepare it for use in a regex.
@@ -1,5 +1,7 @@
1
- import { existsSync } from "fs";
2
- import { pathToFileURL } from "url";
1
+ import fs from "fs";
2
+ import url from "url";
3
+
4
+ import { successFalse, typeError } from "../constants/bases.js";
3
5
 
4
6
  import { flattenConfigData } from "./flatten-config-data.js";
5
7
 
@@ -7,39 +9,64 @@ import { ConfigDataSchema, ConfigIgnoresSchema } from "../schemas/config.js";
7
9
 
8
10
  /**
9
11
  * Verifies, validates and resolves the config path to retrieve the config's data and ignores.
10
- * @param {string} configPath The path of the config, either from `comments.config.js` or from a config passed via the `--config` flag.
11
- * @returns The flattened config data, the reverse flattened config data, the verified config path, the raw passed ignores, and the original config.
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.
12
14
  */
13
15
  export async function resolveConfig(configPath) {
14
16
  // Step 1: Checks if config file exists
15
17
 
16
- if (!existsSync(configPath)) {
17
- console.warn("No config file found. Exiting gracefully.");
18
- return null;
18
+ if (!fs.existsSync(configPath)) {
19
+ return {
20
+ ...successFalse,
21
+ errors: [
22
+ {
23
+ ...typeError,
24
+ message: "ERROR. No config file found.",
25
+ },
26
+ ],
27
+ };
19
28
  }
20
29
 
21
30
  // Step 2: Imports the config dynamically
22
31
 
23
- const configModule = await import(pathToFileURL(configPath));
24
- const config = configModule.default;
32
+ const configModule = /** @type {unknown} */ (
33
+ await import(url.pathToFileURL(configPath))
34
+ );
35
+ const config = /** @type {unknown} */ (configModule.default);
25
36
 
26
37
  // Step 3: Validates config object
27
38
 
28
39
  // validates config
29
40
  if (!config || typeof config !== "object" || Array.isArray(config)) {
30
- console.warn(
31
- "Invalid config format. The config should be an object. Exiting."
32
- );
33
- return null;
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
+ };
34
51
  }
35
52
 
36
53
  // validates config.data
37
54
  const configDataResult = ConfigDataSchema.safeParse(config.data);
38
55
 
39
56
  if (!configDataResult.success) {
40
- console.warn("Config data could not pass validation from zod.");
41
- configDataResult.error.errors.map((e) => console.log(e.message));
42
- return null;
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
+ };
43
70
  }
44
71
 
45
72
  // validates config.ignores
@@ -48,9 +75,25 @@ export async function resolveConfig(configPath) {
48
75
  );
49
76
 
50
77
  if (!configIgnoresSchemaResult.success) {
51
- console.warn("Config ignores could not pass validation from zod.");
52
- configIgnoresSchemaResult.error.errors.map((e) => console.log(e.message));
53
- return null;
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;
54
97
  }
55
98
 
56
99
  // sends back:
@@ -59,7 +102,7 @@ export async function resolveConfig(configPath) {
59
102
  // - the verified config path
60
103
  // - and the raw passed ignores
61
104
  return {
62
- ...flattenConfigData(configDataResult.data), // finalized
105
+ ...flattenedConfigDataResults, // finalized
63
106
  configPath, // finalized
64
107
  passedIgnores: configIgnoresSchemaResult.data, // addressed with --lint-config-imports and --my-ignores-only to be finalized
65
108
  config, // and the config itself too
package/library/index.js CHANGED
@@ -7,18 +7,18 @@ import {
7
7
  cwd,
8
8
  hasPackageJson,
9
9
  hasGitFolder,
10
- defaultConfigFileName,
11
- configFlag,
12
- lintConfigImportsFlag,
13
- myIgnoresOnlyFlag,
14
- knownIgnores,
10
+ defaultConfigFileName, // shared
11
+ configFlag, // shared
12
+ lintConfigImportsFlag, // shared
13
+ myIgnoresOnlyFlag, // shared
14
+ knownIgnores, // shared
15
15
  resolveRuleName,
16
16
  compressRuleName,
17
17
  } from "./_commons/constants/bases.js";
18
18
 
19
- import { exitDueToFailure } from "./_commons/utilities/helpers.js";
20
- import { resolveConfig } from "./_commons/utilities/resolve-config.js";
21
- import { findAllImports } from "./_commons/utilities/find-all-imports.js";
19
+ 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
22
  import {
23
23
  resolveCommentsFlow,
24
24
  compressCommentsFlow,
@@ -61,8 +61,9 @@ const passedConfigPath =
61
61
  // defaults to comments.config.js if no --config flag is set
62
62
  const rawConfigPath = passedConfigPath ?? path.join(cwd, defaultConfigFileName);
63
63
 
64
- const results = await resolveConfig(rawConfigPath);
65
- if (!results) {
64
+ const resolveConfigResults = await resolveConfig(rawConfigPath);
65
+ if (!resolveConfigResults.success) {
66
+ resolveConfigResults.errors.forEach((e) => logError(e));
66
67
  exitDueToFailure();
67
68
  }
68
69
 
@@ -72,21 +73,36 @@ const {
72
73
  reversedFlattenedConfigData,
73
74
  configPath,
74
75
  passedIgnores,
75
- } = results;
76
+ } = resolveConfigResults;
76
77
 
77
78
  skipDetails || console.log("Running with config:", config);
78
- skipDetails || console.log("Flattened config is:", flattenedConfigData);
79
+ skipDetails || console.log("Flattened config data is:", flattenedConfigData);
79
80
  skipDetails ||
80
- console.log("Reversed flattened config is:", reversedFlattenedConfigData);
81
+ console.log(
82
+ "Reversed flattened config data is:",
83
+ reversedFlattenedConfigData
84
+ );
81
85
  skipDetails || console.log("Config path is:", configPath);
82
86
  skipDetails || console.log("Passed ignores are:", passedIgnores);
83
87
 
84
88
  // ADDRESSES THE --lint-config-imports FLAG, GIVEN THAT THE FILES IMPORTED BY THE CONFIG ARE IGNORED BY DEFAULT.
85
89
 
86
90
  const lintConfigImports = commands.indexOf(lintConfigImportsFlag) >= 2;
87
- const rawConfigPathIgnores = lintConfigImports
88
- ? [configPath]
89
- : [...(findAllImports(configPath) ?? [])];
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
+ }
90
106
 
91
107
  // the ignore paths must be relative
92
108
  const configPathIgnores = rawConfigPathIgnores.map((e) =>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "comment-variables",
3
- "version": "0.4.2",
3
+ "version": "0.6.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",
@@ -27,8 +27,7 @@
27
27
  "dependencies": {
28
28
  "@eslint/markdown": "^6.5.0",
29
29
  "eslint": "^9.29.0",
30
- "get-sourcecode-from-file-path": "^1.0.1",
31
- "resolve-importing-path": "^1.0.2",
30
+ "find-all-js-imports": "^1.0.0",
32
31
  "tsconfig-paths": "^4.2.0",
33
32
  "typescript-eslint": "^8.34.1",
34
33
  "zod": "^3.25.67"
@@ -1,120 +0,0 @@
1
- import fs from "fs";
2
- import path from "path";
3
-
4
- import { resolveImportingPath } from "resolve-importing-path";
5
- import { getSourceCodeFromFilePath } from "get-sourcecode-from-file-path";
6
-
7
- /* findAllImports */
8
-
9
- /**
10
- * Processes recursively and resolves a single import path.
11
- * @param {string} importPath The import path currently being addressed.
12
- * @param {string} currentDir The directory containing the import path currently being addressed.
13
- * @param {string} cwd The current working directory, set as `process.cwd()` by default.
14
- * @param {Set<string>} visitedSet The set of strings tracking the import paths that have already been visited, instantiated as a `new Set()` by default.
15
- * @param {number} depth The current depth of the recursion, instantiated at `0` by default.
16
- * @param {number} maxDepth The maximum depth allowed for the recursion, instantiated at `100` by default.
17
- * @returns `true` to skip unresolved paths, `false` if resolution fails at any level.
18
- */
19
- const processImport = (
20
- importPath,
21
- currentDir,
22
- cwd,
23
- visitedSet,
24
- depth,
25
- maxDepth
26
- ) => {
27
- const resolvedPath = resolveImportingPath(currentDir, importPath, cwd);
28
- if (!resolvedPath) return true;
29
-
30
- const result = findAllImports(
31
- resolvedPath,
32
- cwd,
33
- visitedSet,
34
- depth + 1,
35
- maxDepth
36
- );
37
- return result !== null; // Returns false if child failed.
38
- };
39
-
40
- /**
41
- * Finds all import paths recursively related to a given file path.
42
- * @param {string} filePath The absolute path of the file whose imports are being recursively found, such as that of a project's `comments.config.js` file.
43
- * @param {string} cwd The current working directory, set as `process.cwd()` by default.
44
- * @param {Set<string>} visitedSet The set of strings tracking the import paths that have already been visited, instantiated as a `new Set()` by default.
45
- * @param {number} depth The current depth of the recursion, instantiated at `0` by default.
46
- * @param {number} maxDepth The maximum depth allowed for the recursion, instantiated at `100` by default.
47
- * @returns The complete set of strings of import paths recursively related to the given file path, or `null` if an issue has arisen.
48
- */
49
- export const findAllImports = (
50
- filePath,
51
- cwd = process.cwd(),
52
- visitedSet = new Set(),
53
- depth = 0,
54
- maxDepth = 100
55
- ) => {
56
- // Fails early if max depth is recursively reached.
57
- if (depth > maxDepth) {
58
- console.error(`ERROR. Max depth ${maxDepth} reached at ${filePath}.`);
59
- return null;
60
- }
61
- // Fails early if no file is found.
62
- if (!fs.existsSync(filePath)) {
63
- console.error(`ERROR. File not found at ${filePath}.`);
64
- return null;
65
- }
66
-
67
- // Updates the visited set.
68
- if (visitedSet.has(filePath)) return visitedSet;
69
- visitedSet.add(filePath);
70
-
71
- // Parses the file's source code AST.
72
- const sourceCode = getSourceCodeFromFilePath(filePath);
73
- if (!sourceCode?.ast) {
74
- console.error(`ERROR. Failed to parse AST for ${filePath}.`);
75
- return null;
76
- }
77
-
78
- // Processes all imports.
79
- const currentDir = path.dirname(filePath);
80
- for (const node of sourceCode.ast.body) {
81
- // ES Modules (import x from 'y')
82
- if (node.type === "ImportDeclaration") {
83
- if (
84
- !processImport(
85
- node.source.value,
86
- currentDir,
87
- cwd,
88
- visitedSet,
89
- depth,
90
- maxDepth
91
- )
92
- ) {
93
- return null;
94
- }
95
- }
96
-
97
- // CommonJS (require('x'))
98
- if (
99
- node.type === "ExpressionStatement" &&
100
- node.expression.type === "CallExpression" &&
101
- node.expression.callee.name === "require" &&
102
- node.expression.arguments[0]?.type === "Literal"
103
- ) {
104
- if (
105
- !processImport(
106
- node.expression.arguments[0].value,
107
- currentDir,
108
- cwd,
109
- visitedSet,
110
- depth,
111
- maxDepth
112
- )
113
- ) {
114
- return null;
115
- }
116
- }
117
- }
118
-
119
- return visitedSet; // success
120
- };