@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 +1 -0
- package/jsconfig.json +14 -0
- package/package.json +2 -2
- package/src/core/ActionManager.js +1 -1
- package/src/core/Configuration.js +6 -6
- package/src/core/Conveyor.js +64 -41
- package/src/core/Core.js +14 -37
- package/src/core/Discovery.js +7 -4
- package/src/core/HookManager.js +8 -10
- package/src/core/util/DataUtil.js +3 -3
- package/src/core/util/FDUtil.js +24 -8
- package/src/core/util/TypeSpec.js +4 -4
- package/tsconfig.json +0 -20
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
[](https://github.com/gesslar/BeDoc/actions/workflows/codeql.yml)
|
|
2
2
|
[](https://github.com/gesslar/BeDoc/actions/workflows/dependabot/dependabot-updates)
|
|
3
3
|
[](https://github.com/gesslar/BeDoc/actions/workflows/autopr-dev.yml)
|
|
4
|
+
[](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.
|
|
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, {
|
|
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(
|
|
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
|
-
|
|
61
|
+
key => !ConfigurationPriorityKeys.includes(key),
|
|
62
62
|
)
|
|
63
63
|
orderedSections.push(
|
|
64
|
-
...remainingSections.map(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
package/src/core/Conveyor.js
CHANGED
|
@@ -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
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
await
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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
|
|
49
|
-
await Promise.all(
|
|
60
|
+
// Wait for all processing to complete
|
|
61
|
+
await Promise.all(activePromises)
|
|
50
62
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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 =
|
|
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
|
|
94
|
-
const mess = format("No
|
|
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,
|
|
110
|
-
const isNullish =
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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,
|
|
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,
|
|
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}
|
|
157
|
+
* @param {string} destContent - File content.
|
|
136
158
|
* @returns {Promise<object>} - Resolves when the file is written.
|
|
137
159
|
*/
|
|
138
|
-
async #writeOutput(destFile,
|
|
160
|
+
async #writeOutput(destFile, destContent) {
|
|
139
161
|
const destFileMap = composeFilename(this.output.path, destFile)
|
|
162
|
+
|
|
140
163
|
try {
|
|
141
|
-
writeFile(destFileMap,
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
140
|
+
const processStart = hrtime.bigint()
|
|
141
141
|
|
|
142
142
|
// Initiate the conveyor
|
|
143
|
-
const
|
|
143
|
+
const processResult = await conveyor.convey(
|
|
144
|
+
input, this.options.maxConcurrent
|
|
145
|
+
)
|
|
144
146
|
|
|
145
147
|
debug("Conveyor complete", 1)
|
|
146
148
|
|
|
147
|
-
const
|
|
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
|
-
|
|
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)
|
package/src/core/Discovery.js
CHANGED
|
@@ -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,
|
|
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
|
|
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}
|
package/src/core/HookManager.js
CHANGED
|
@@ -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(
|
|
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 {
|
|
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,
|
|
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(`
|
|
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,
|
|
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(
|
|
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(
|
|
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 =
|
|
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) =>
|
package/src/core/util/FDUtil.js
CHANGED
|
@@ -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 =
|
|
13
|
+
const freeze = ob => Object.freeze(ob)
|
|
14
14
|
|
|
15
15
|
const fdTypes = freeze(["file", "directory"])
|
|
16
|
-
const upperFdTypes = freeze(fdTypes.map(
|
|
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(
|
|
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(
|
|
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(
|
|
249
|
+
.map(g => g.trim())
|
|
235
250
|
.filter(Boolean)
|
|
236
|
-
).map(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
-
}
|