@gesslar/bedoc 1.4.10 → 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/Conveyor.js +62 -39
- package/src/core/Core.js +14 -37
- package/src/core/HookManager.js +7 -9
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
|
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,
|
|
121
|
+
const {status: printStatus, destFile, destContent} = printResult
|
|
110
122
|
const isNullish = value => value == null // Checks null or undefined
|
|
111
123
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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/HookManager.js
CHANGED
|
@@ -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
|
}
|