@gesslar/bedoc 1.4.8 → 1.5.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/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  [![CodeQL Advanced](https://github.com/gesslar/BeDoc/actions/workflows/codeql.yml/badge.svg)](https://github.com/gesslar/BeDoc/actions/workflows/codeql.yml)
2
2
  [![Dependabot Updates](https://github.com/gesslar/BeDoc/actions/workflows/dependabot/dependabot-updates/badge.svg)](https://github.com/gesslar/BeDoc/actions/workflows/dependabot/dependabot-updates)
3
3
  [![Auto PR and Merge - dev 🤗](https://github.com/gesslar/BeDoc/actions/workflows/autopr-dev.yml/badge.svg?branch=dev)](https://github.com/gesslar/BeDoc/actions/workflows/autopr-dev.yml)
4
+ [![CodeFactor](https://www.codefactor.io/repository/github/gesslar/bedoc/badge)](https://www.codefactor.io/repository/github/gesslar/bedoc)
4
5
 
5
6
  # BeDoc
6
7
 
package/jsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "ESNext",
4
+ "moduleResolution": "Bundler",
5
+ "target": "ES2024",
6
+ "allowImportingTsExtensions": true,
7
+ "strictNullChecks": true,
8
+ "strictFunctionTypes": true
9
+ },
10
+ "exclude": [
11
+ "node_modules",
12
+ "**/node_modules/*"
13
+ ]
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gesslar/bedoc",
3
- "version": "1.4.8",
3
+ "version": "1.5.0",
4
4
  "description": "Pluggable documentation engine for any language and format",
5
5
  "publisher": "gesslar",
6
6
  "main": "./src/core/Core.js",
@@ -37,7 +37,6 @@
37
37
  "commander": "^13.0.0",
38
38
  "dotenv": "^16.4.7",
39
39
  "error-stack-parser": "^2.1.4",
40
- "eslint-plugin-jsdoc": "^50.6.2",
41
40
  "globby": "^14.0.2",
42
41
  "micromatch": "^4.0.8",
43
42
  "node-fetch": "^3.3.2",
@@ -49,6 +48,7 @@
49
48
  "@typescript-eslint/parser": "^8.22.0",
50
49
  "axios": "^1.7.9",
51
50
  "chokidar": "^4.0.3",
51
+ "eslint-plugin-jsdoc": "^50.6.3",
52
52
  "eslint": "^9.18.0",
53
53
  "form-data": "^4.0.1"
54
54
  },
@@ -119,7 +119,7 @@ export default class ActionManager {
119
119
  throw new Error(`No \`run\` function found for action \`${this.meta.action}\``)
120
120
 
121
121
  const actionResult = await func.call(
122
- this.action, {module: file.module, content}
122
+ this.action, {moduleName: file.module, moduleContent: content}
123
123
  )
124
124
 
125
125
  return actionResult
@@ -49,7 +49,7 @@ export default class Configuration {
49
49
  // Find them and add them to an array; the rest will be in pushed to the
50
50
  // end of the priority array.
51
51
  const orderedSections = []
52
- ConfigurationPriorityKeys.forEach((key) => {
52
+ ConfigurationPriorityKeys.forEach(key => {
53
53
  if(!ConfigurationParameters[key])
54
54
  throw new Error(`Invalid priority key: ${key}`)
55
55
 
@@ -58,10 +58,10 @@ export default class Configuration {
58
58
  })
59
59
 
60
60
  const remainingSections = Object.keys(ConfigurationParameters).filter(
61
- (key) => !ConfigurationPriorityKeys.includes(key),
61
+ key => !ConfigurationPriorityKeys.includes(key),
62
62
  )
63
63
  orderedSections.push(
64
- ...remainingSections.map((key) => {
64
+ ...remainingSections.map(key => {
65
65
  return {key, value: finalOptions[key]}
66
66
  }),
67
67
  )
@@ -106,7 +106,7 @@ export default class Configuration {
106
106
  if(key === "input" || key === "exclude") {
107
107
  if(isType(value, "array"))
108
108
  value = await Promise.all(
109
- value.map((pattern) => getFiles(pattern)),
109
+ value.map(pattern => getFiles(pattern)),
110
110
  )
111
111
  else if(isType(value, "string"))
112
112
  value = await getFiles(value)
@@ -251,7 +251,7 @@ export default class Configuration {
251
251
  */
252
252
  #getEnvironmentVariables() {
253
253
  const environmentVariables = {}
254
- const params = Object.keys(ConfigurationParameters).map((param) => {
254
+ const params = Object.keys(ConfigurationParameters).map(param => {
255
255
  return {
256
256
  param,
257
257
  env: `bedoc_${param}`.toUpperCase(),
@@ -280,7 +280,7 @@ export default class Configuration {
280
280
  const nonEntryOptions = allOptions.filter(
281
281
  option => option.source && option.source !== "entry",
282
282
  )
283
- const optionsOnly = nonEntryOptions.map((option) => option.options)
283
+ const optionsOnly = nonEntryOptions.map(option => option.options)
284
284
  const mergedOptions = optionsOnly.reduce((acc, options) => {
285
285
  for(const [key, value] of Object.entries(options)) acc[key] = value
286
286
 
@@ -24,33 +24,46 @@ export default class Conveyor {
24
24
  * @returns {Promise<object>} - Resolves when all files are processed.
25
25
  */
26
26
  async convey(files, maxConcurrent = 10) {
27
- const semaphore = Array(maxConcurrent).fill(Promise.resolve())
28
-
29
- // Set up the actions
30
- await this.parse.setupAction()
31
- await this.print.setupAction()
32
-
33
- for(const file of files) {
34
- const slot = Promise.race(semaphore) // Wait for an available slot
35
- semaphore.push(slot.then(async() => {
36
- const result = await this.#processFile(file)
37
- if(result.status === "success")
38
- this.#succeeded.push({input: file, output: result.file})
39
- else if(result.status === "warning")
40
- this.#warned.push({input: file, warning: result.warning})
41
- else {
42
- this.#errored.push({input: file, error: result.error})
27
+ const fileQueue = [...files]
28
+ const activePromises = []
29
+
30
+ await Promise.all([
31
+ this.parse.setupAction(),
32
+ this.print.setupAction()
33
+ ])
34
+
35
+ const processNextFile = file => {
36
+ return this.#processFile(file).then(processedResult => {
37
+ // Store result
38
+ if(processedResult.status === "success") {
39
+ this.#succeeded.push({input: file, output: processedResult.file})
40
+ } else if(processedResult.status === "warning") {
41
+ this.#warned.push({input: file, warning: processedResult.warning})
42
+ } else {
43
+ this.#errored.push({input: file, error: processedResult.error})
43
44
  }
44
- }))
45
- semaphore.shift() // Remove the oldest promise
45
+
46
+ // Start next job if queue isn't empty
47
+ if(fileQueue.length > 0) {
48
+ const nextFile = fileQueue.shift()
49
+ return processNextFile(nextFile)
50
+ }
51
+ })
52
+ }
53
+
54
+ // Initial fill of the worker pool
55
+ while(activePromises.length < maxConcurrent && fileQueue.length > 0) {
56
+ const file = fileQueue.shift()
57
+ activePromises.push(processNextFile(file))
46
58
  }
47
59
 
48
- // Wait for all tasks to complete
49
- await Promise.all(semaphore)
60
+ // Wait for all processing to complete
61
+ await Promise.all(activePromises)
50
62
 
51
- // Clean up actions
52
- await this.parse.cleanupAction()
53
- await this.print.cleanupAction()
63
+ await Promise.all([
64
+ this.parse.cleanupAction(),
65
+ this.print.cleanupAction()
66
+ ])
54
67
 
55
68
  return {
56
69
  succeeded: this.#succeeded,
@@ -67,14 +80,13 @@ export default class Conveyor {
67
80
  */
68
81
  async #processFile(file) {
69
82
  const debug = this.logger.newDebug()
70
- const warn = (...arg) => this.logger.warn(...arg)
71
83
  const {parse, print} = this
72
84
 
73
85
  try {
74
86
  debug("Processing file: `%s`", 2, file.path)
75
87
 
76
88
  // Step 1: Read file
77
- const fileContent = await readFile(file)
89
+ const fileContent = readFile(file)
78
90
  debug("Read file content `%s` (%d bytes)", 2, file.path, fileContent.length)
79
91
 
80
92
  // Step 2: Parse file
@@ -90,8 +102,8 @@ export default class Conveyor {
90
102
  else
91
103
  debug("Parsed file successfully: `%s`", 2, file.path)
92
104
 
93
- if(!parseResult.result?.functions?.length) {
94
- const mess = format("No functions found in `%s`. No file written.", file.path)
105
+ if(!parseResult.result) {
106
+ const mess = format("No content found in `%s`. No file written.", file.path)
95
107
  return {status: "warning", file, warning: mess}
96
108
  }
97
109
 
@@ -106,21 +118,31 @@ export default class Conveyor {
106
118
  debug("Printed file successfully: `%s`", 2, file.path)
107
119
 
108
120
  // Step 4: Write output
109
- const {status: printStatus, destFile, content} = printResult
110
- const isNullish = (value) => value == null // Checks null or undefined
111
-
112
- if(printStatus !== "success" || isNullish(destFile) || isNullish(content)) {
113
- return {status: "error", file, error: new Error("Invalid print result")}
114
- } else if(!destFile || !content) {
115
- const mess = format("No content or destination file for %s", file.path)
116
- warn(mess)
117
- return {status: "warning", file, warning: mess}
121
+ const {status: printStatus, destFile, destContent} = printResult
122
+ const isNullish = value => value == null // Checks null or undefined
123
+
124
+ switch(printStatus) {
125
+ case "warning":
126
+ case "error":
127
+ return printResult
128
+ case "success":
129
+ if(isNullish(destFile) || isNullish(destContent))
130
+ return {
131
+ status: "warning",
132
+ warning: format("No content or destination file for %s", file.path)
133
+ }
134
+
135
+ break
136
+ default:
137
+ throw new Error(`Invalid status received from printing ${file.module}`)
118
138
  }
119
139
 
120
- const writeResult = await this.#writeOutput(destFile, content)
140
+ const writeResult = await this.#writeOutput(destFile, destContent)
121
141
 
122
142
  if(writeResult.status === "success")
123
- debug("Wrote output for: `%s` (%d bytes)", 2, file.path, content.length)
143
+ debug("Wrote output for: `%s` (%d bytes)", 2, file.path, destContent.length)
144
+ else
145
+ debug("Error writing output for: `%s`", 2, file.path)
124
146
 
125
147
  return writeResult
126
148
  } catch(error) {
@@ -132,13 +154,14 @@ export default class Conveyor {
132
154
  * Writes the output to the destination.
133
155
  *
134
156
  * @param {string} destFile - Destination file path.
135
- * @param {string} content - File content.
157
+ * @param {string} destContent - File content.
136
158
  * @returns {Promise<object>} - Resolves when the file is written.
137
159
  */
138
- async #writeOutput(destFile, content) {
160
+ async #writeOutput(destFile, destContent) {
139
161
  const destFileMap = composeFilename(this.output.path, destFile)
162
+
140
163
  try {
141
- writeFile(destFileMap, content)
164
+ writeFile(destFileMap, destContent)
142
165
 
143
166
  return {status: "success", file: destFileMap}
144
167
  } catch(error) {
package/src/core/Core.js CHANGED
@@ -1,8 +1,8 @@
1
- import process from "node:process"
1
+ import {hrtime} from "node:process"
2
2
 
3
3
  import Discovery from "./Discovery.js"
4
4
  import HookManager from "./HookManager.js"
5
- import Logger, {loggerColours} from "./Logger.js"
5
+ import Logger from "./Logger.js"
6
6
  import ParseManager from "./action/ParseManager.js"
7
7
  import PrintManager from "./action/PrintManager.js"
8
8
  import Conveyor from "./Conveyor.js"
@@ -118,7 +118,7 @@ export default class Core {
118
118
  return instance
119
119
  }
120
120
 
121
- async processFiles(glob, startTime = process.hrtime()) {
121
+ async processFiles(glob) {
122
122
  const debug = this.logger.newDebug()
123
123
 
124
124
  debug("Starting file processing with conveyor", 1)
@@ -137,46 +137,23 @@ export default class Core {
137
137
  output,
138
138
  )
139
139
 
140
- const processStart = process.hrtime()
140
+ const processStart = hrtime.bigint()
141
141
 
142
142
  // Initiate the conveyor
143
- const result = await conveyor.convey(input, this.options.maxConcurrent)
143
+ const processResult = await conveyor.convey(
144
+ input, this.options.maxConcurrent
145
+ )
144
146
 
145
147
  debug("Conveyor complete", 1)
146
148
 
147
- const endTime = (process.hrtime(startTime)[1] / 1_000_000).toFixed(2)
148
- const processEnd = (process.hrtime(processStart)[1] / 1_000_000).toFixed(2)
149
-
150
- // Grab the results
151
- const totalFiles = input.length
152
- const succeeded = result.succeeded
153
- const warned = result.warned
154
- const errored = result.errored
155
-
156
- const {
157
- info: succeedColour, warn: warnColour, error: errorColour, reset
158
- } = loggerColours
159
-
160
-
161
- const success = `${succeedColour}${succeeded.length}${reset}`
162
- const warn = `${warnColour}${warned.length}${reset}`
163
- const error = `${errorColour}${errored.length}${reset}`
164
-
165
- const message = `Processed ${totalFiles} files: ${success} succeeded, ${error} errored, ` +
166
- `${warn} warned in ${processEnd}ms [total: ${endTime}ms]`
167
-
168
- this.logger.debug(message, 1)
169
-
170
- if(errored.length > 0) {
171
- // const failureRate = ((errored.length / totalFiles) * 100).toFixed(2)
172
- // const errorMessage =
173
- // `Errors processing ${errored.length} files [${failureRate}%]`
174
- // const errorLines = errored.map(r => {
175
- // const stackLine = log.lastStackLine(r.error, 0)
176
- // return `\n- ${r.input.module}: ${stackLine} - ${r.error.message}`
177
- // }).join("")
149
+ const processEnd = hrtime.bigint()
178
150
 
179
- // this.logger(errorMessage+errorLines)
151
+ const result = {
152
+ totalFiles: input.length,
153
+ succeeded: processResult.succeeded,
154
+ warned: processResult.warned,
155
+ errored: processResult.errored,
156
+ duration: ((Number(processEnd - processStart)) / 1_000_000).toFixed(2)
180
157
  }
181
158
 
182
159
  debug("File processing complete", 1)
@@ -5,8 +5,9 @@ import {execSync} from "child_process"
5
5
  import * as FDUtil from "./util/FDUtil.js"
6
6
  import * as ActionUtil from "./util/ActionUtil.js"
7
7
  import * as DataUtil from "./util/DataUtil.js"
8
+ import {composeDirectory,directoryExists} from "./util/FDUtil.js"
8
9
 
9
- const {ls, resolveDirectory, resolveFilename, getFiles} = FDUtil
10
+ const {ls,resolveFilename,getFiles} = FDUtil
10
11
  const {actionTypes, actionMetaRequirements, loadJson} = ActionUtil
11
12
  const {isType} = DataUtil
12
13
 
@@ -72,7 +73,9 @@ export default class Discovery {
72
73
  debug("Found %d directories to search for actions", 2, directories.length)
73
74
  debug("Directories to search for actions: %o", 3, directories)
74
75
 
75
- const moduleDirectories = directories.map(resolveDirectory)
76
+ const moduleDirectories = directories
77
+ .map(composeDirectory)
78
+ .filter(directoryExists)
76
79
  for(const moduleDirectory of moduleDirectories) {
77
80
  const {directories: dirs} = await ls(moduleDirectory.absolutePath)
78
81
 
@@ -310,9 +313,9 @@ export default class Discovery {
310
313
  async #loadModule(module) {
311
314
  const debug = this.#debug
312
315
 
313
- debug("Loading module `%j`", 2, module)
316
+ debug("2 Loading module `%j`", 2, module)
314
317
 
315
- const {absoluteUri} = module
318
+ const {absolutePath: absoluteUri} = module
316
319
  const moduleExports = await import(absoluteUri)
317
320
 
318
321
  return {file: module, ...moduleExports}
@@ -10,7 +10,7 @@ const freeze = Object.freeze
10
10
  const hookEvents = freeze(["start", "section_load", "enter", "exit", "end"])
11
11
  export const HookPoints = freeze(
12
12
  await allocateObject(
13
- hookEvents.map((event) => event.toUpperCase()),
13
+ hookEvents.map(event => event.toUpperCase()),
14
14
  hookEvents,
15
15
  ),
16
16
  )
@@ -101,10 +101,10 @@ export default class HookManager {
101
101
  * Trigger a hook
102
102
  *
103
103
  * @param {string} event - The type of hook to trigger
104
- * @param {...any} args - The hook arguments
104
+ * @param {object} args - The hook arguments as an object
105
105
  * @returns {Promise<any>} The result of the hook
106
106
  */
107
- async on(event, ...args) {
107
+ async on(event, args) {
108
108
  const debug = this.log.newDebug()
109
109
 
110
110
  debug("Triggering hook for event `%s`", 4, event)
@@ -113,18 +113,14 @@ export default class HookManager {
113
113
  throw new Error("Event type is required for hook invocation")
114
114
 
115
115
  if(!hookEvents.includes(event))
116
- throw new Error(`[HookManager.on] Invalid event type: ${event}`)
116
+ throw new Error(`Invalid event type: ${event}`)
117
117
 
118
118
  const hook = this.hooks[event]
119
119
 
120
120
  if(hook) {
121
- assert(
122
- isType(hook, "function"),
123
- `[HookManager.on] Hook "${event}" is not a function`,
124
- 1,
125
- )
121
+ assert(isType(hook, "function"), `Hook "${event}" is not a function`, 1)
126
122
 
127
- const hookExecution = await hook.call(this.hooks, ...args)
123
+ const hookExecution = await hook.call(this.hooks, args)
128
124
  const hookTimeout = this.parent.timeout
129
125
  const expireAsync = () =>
130
126
  timeoutPromise(
@@ -139,6 +135,8 @@ export default class HookManager {
139
135
  debug("Hook executed successfully for event: `%s`", 4, event)
140
136
 
141
137
  return result
138
+ } else {
139
+ return null
142
140
  }
143
141
  }
144
142
  }
@@ -38,7 +38,7 @@ const constructors = [
38
38
  "Float64Array",
39
39
  ]
40
40
 
41
- const dataTypes = [...primitives, ...constructors.map((c) => c.toLowerCase())]
41
+ const dataTypes = [...primitives, ...constructors.map(c => c.toLowerCase())]
42
42
 
43
43
  const emptyableTypes = ["string", "array", "object"]
44
44
 
@@ -96,7 +96,7 @@ function isArrayUnique(arr) {
96
96
  * @returns {Array} The intersection of the two arrays.
97
97
  */
98
98
  function arrayIntersection(arr1, arr2) {
99
- return arr1.filter((value) => arr2.includes(value))
99
+ return arr1.filter(value => arr2.includes(value))
100
100
  }
101
101
 
102
102
  /**
@@ -390,7 +390,7 @@ function deepFreezeObject(obj) {
390
390
  * @returns {boolean} - True if valid, throws an error otherwise.
391
391
  */
392
392
  function schemaCompare(schema, definition, stack = [], logger = new Logger()) {
393
- const breadcrumb = (key) => (stack.length ? `@${stack.join(".")}` : key)
393
+ const breadcrumb = key => (stack.length ? `@${stack.join(".")}` : key)
394
394
  const tag = "[DataUtil.schemaCompare]"
395
395
  const pad = `${" ".repeat(stack.length * 2)}${stack.length ? "└─ " : ""}`
396
396
  const debug = (message, key) =>
@@ -10,10 +10,10 @@ import * as ValidUtil from "./ValidUtil.js"
10
10
  const {isArrayUniform, isType, allocateObject} = DataUtil
11
11
  const {validType} = ValidUtil
12
12
 
13
- const freeze = (ob) => Object.freeze(ob)
13
+ const freeze = ob => Object.freeze(ob)
14
14
 
15
15
  const fdTypes = freeze(["file", "directory"])
16
- const upperFdTypes = freeze(fdTypes.map((type) => type.toUpperCase()))
16
+ const upperFdTypes = freeze(fdTypes.map(type => type.toUpperCase()))
17
17
  const fdType = freeze(await allocateObject(upperFdTypes, fdTypes))
18
18
 
19
19
  /**
@@ -67,7 +67,7 @@ function canWriteFile(FileMap) {
67
67
  try {
68
68
  fs.accessSync(FileMap.absolutePath, fs.constants.W_OK)
69
69
  return true
70
- } catch(error) {
70
+ } catch(_error) {
71
71
  return false
72
72
  }
73
73
  }
@@ -82,7 +82,22 @@ function fileExists(FileMap) {
82
82
  try {
83
83
  fs.accessSync(FileMap.absolutePath)
84
84
  return true
85
- } catch(error) {
85
+ } catch(_error) {
86
+ return false
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Check if a directory exists
92
+ *
93
+ * @param {object} DirectoryMap - The directory map to check
94
+ * @returns {boolean} Whether the directory exists
95
+ */
96
+ function directoryExists(DirectoryMap) {
97
+ try {
98
+ fs.accessSync(DirectoryMap.absolutePath)
99
+ return true
100
+ } catch(_error) {
86
101
  return false
87
102
  }
88
103
  }
@@ -231,9 +246,9 @@ async function getFiles(globPattern) {
231
246
  ? globPattern
232
247
  : globPattern
233
248
  .split("|")
234
- .map((g) => g.trim())
249
+ .map(g => g.trim())
235
250
  .filter(Boolean)
236
- ).map((g) => fixSlashes(g))
251
+ ).map(g => fixSlashes(g))
237
252
 
238
253
  if(
239
254
  Array.isArray(globbyArray) &&
@@ -246,7 +261,7 @@ async function getFiles(globPattern) {
246
261
 
247
262
  // Use Globby to fetch matching files
248
263
  const filesArray = await globby(globbyArray)
249
- const files = filesArray.map((file) => mapFilename(file))
264
+ const files = filesArray.map(file => mapFilename(file))
250
265
 
251
266
  // Flatten the result and remove duplicates
252
267
  return files
@@ -297,7 +312,7 @@ function composeDirectory(directory) {
297
312
  async function ls(directory) {
298
313
  const found = await fs.promises.readdir(directory, {withFileTypes: true})
299
314
  const results = await Promise.all(
300
- found.map(async(dirent) => {
315
+ found.map(async dirent => {
301
316
  const fullPath = path.join(directory, dirent.name)
302
317
  const stat = await fs.promises.stat(fullPath)
303
318
  return {dirent, stat, fullPath}
@@ -357,6 +372,7 @@ export {
357
372
  composeDirectory,
358
373
  composeFilename,
359
374
  deconstructFilenameToParts,
375
+ directoryExists,
360
376
  fileExists,
361
377
  fixSlashes,
362
378
  getFiles,
@@ -17,7 +17,7 @@ export default class TypeSpec {
17
17
 
18
18
  toString() {
19
19
  return this.#specs
20
- .map((spec) => {
20
+ .map(spec => {
21
21
  return `${spec.typeName}${spec.array ? "[]" : ""}`
22
22
  })
23
23
  .join("|")
@@ -61,7 +61,7 @@ export default class TypeSpec {
61
61
  // If we have a list of types, because the string was validly parsed,
62
62
  // we need to ensure that all of the types that were parsed are valid types
63
63
  // in JavaScript.
64
- if(this.length && !this.every((t) => isValidType(t.typeName)))
64
+ if(this.length && !this.every(t => isValidType(t.typeName)))
65
65
  return false
66
66
 
67
67
  // Now, let's do some checking with the types, respecting the array flag
@@ -71,7 +71,7 @@ export default class TypeSpec {
71
71
 
72
72
  // We need to ensure that we match the type and the consistency of the types
73
73
  // in an array, if it is an array and an array is allowed.
74
- const matchingTypeSpec = this.filter((spec) => {
74
+ const matchingTypeSpec = this.filter(spec => {
75
75
  const {typeName: allowedType, array: allowedArray} = spec
76
76
 
77
77
  if(valueType === allowedType && !isArray && !allowedArray)
@@ -97,7 +97,7 @@ export default class TypeSpec {
97
97
  const delimiter = options?.delimiter ?? "|"
98
98
  const parts = string.split(delimiter)
99
99
 
100
- this.#specs = parts.map((part) => {
100
+ this.#specs = parts.map(part => {
101
101
  const typeMatches = /(\w+)(\[\])?/.exec(part)
102
102
  if(!typeMatches || typeMatches.length !== 3)
103
103
  throw new TypeError(`Invalid type: ${part}`)
package/tsconfig.json DELETED
@@ -1,20 +0,0 @@
1
- {
2
- "include": ["src/**/*.js"], // Match all .js files in the src/ directory
3
- "exclude": ["node_modules"], // Ignore node_modules/ (but NOT src/)
4
- "compilerOptions": {
5
- "target": "ES2022", // Modern JavaScript output
6
- "allowJs": true, // Process .js files
7
- "declaration": true, // Generate .d.ts files
8
- "emitDeclarationOnly": true, // Only output .d.ts files
9
- "declarationMap": true, // Generate .d.ts.map for IDE support
10
- "module": "NodeNext", // Use ESM-compatible Node.js modules
11
- "moduleResolution": "nodenext", // Resolve ESM imports properly
12
- "rootDir": "src", // Base input directory
13
- "outDir": "dist/types", // Emit .d.ts files to a separate directory
14
- "strict": true, // Enable strict type-checking
15
- "esModuleInterop": true, // Interoperability for CommonJS modules
16
- "forceConsistentCasingInFileNames": true, // Avoid case-sensitive issues
17
- "skipLibCheck": true, // Skip checking .d.ts files in node_modules/
18
- "noEmitOnError": true // Prevent output if there are errors
19
- }
20
- }