@gesslar/bedoc 1.10.0 → 2.0.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/LICENSE.txt +12 -0
- package/README.md +15 -3
- package/dist/schema/bedoc.action.json +42 -0
- package/dist/types/Action.d.ts +3 -0
- package/dist/types/Action.d.ts.map +1 -0
- package/dist/types/BeDoc.d.ts +208 -0
- package/dist/types/BeDoc.d.ts.map +1 -0
- package/dist/types/Configuration.d.ts +11 -0
- package/dist/types/Configuration.d.ts.map +1 -0
- package/dist/types/ConfigurationParameters.d.ts +3 -0
- package/dist/types/ConfigurationParameters.d.ts.map +1 -0
- package/dist/types/Conveyor.d.ts +27 -0
- package/dist/types/Conveyor.d.ts.map +1 -0
- package/dist/types/Discovery.d.ts +215 -0
- package/dist/types/Discovery.d.ts.map +1 -0
- package/dist/types/Environment.d.ts +3 -0
- package/dist/types/Environment.d.ts.map +1 -0
- package/dist/types/Logger.d.ts +47 -0
- package/dist/types/Logger.d.ts.map +1 -0
- package/dist/types/Schema.d.ts +3 -0
- package/dist/types/Schema.d.ts.map +1 -0
- package/dist/types/cli.d.ts +2 -2
- package/dist/types/cli.d.ts.map +1 -10
- package/package.json +24 -23
- package/src/Action.js +9 -0
- package/src/BeDoc.js +276 -0
- package/src/CLIOutput.js +198 -0
- package/src/{core/Configuration.js → Configuration.js} +72 -58
- package/src/{core/ConfigurationParameters.js → ConfigurationParameters.js} +35 -27
- package/src/Conveyor.js +256 -0
- package/src/Discovery.js +442 -0
- package/src/Environment.js +8 -0
- package/src/{core/Logger.js → Logger.js} +30 -18
- package/src/Schema.js +6 -0
- package/src/cli.js +77 -34
- package/tsconfig.types.json +42 -0
- package/LICENSE +0 -24
- package/dist/types/core/ActionManager.d.ts +0 -58
- package/dist/types/core/ActionManager.d.ts.map +0 -10
- package/dist/types/core/Configuration.d.ts +0 -27
- package/dist/types/core/Configuration.d.ts.map +0 -10
- package/dist/types/core/ConfigurationParameters.d.ts +0 -38
- package/dist/types/core/ConfigurationParameters.d.ts.map +0 -10
- package/dist/types/core/Conveyor.d.ts +0 -49
- package/dist/types/core/Conveyor.d.ts.map +0 -10
- package/dist/types/core/Core.d.ts +0 -48
- package/dist/types/core/Core.d.ts.map +0 -10
- package/dist/types/core/Discovery.d.ts +0 -73
- package/dist/types/core/Discovery.d.ts.map +0 -10
- package/dist/types/core/HookManager.d.ts +0 -60
- package/dist/types/core/HookManager.d.ts.map +0 -10
- package/dist/types/core/Logger.d.ts +0 -63
- package/dist/types/core/Logger.d.ts.map +0 -10
- package/dist/types/core/action/ParseManager.d.ts +0 -8
- package/dist/types/core/action/ParseManager.d.ts.map +0 -10
- package/dist/types/core/action/PrintManager.d.ts +0 -8
- package/dist/types/core/action/PrintManager.d.ts.map +0 -10
- package/dist/types/core/util/ActionUtil.d.ts +0 -35
- package/dist/types/core/util/ActionUtil.d.ts.map +0 -10
- package/dist/types/core/util/DataUtil.d.ts +0 -52
- package/dist/types/core/util/DataUtil.d.ts.map +0 -10
- package/dist/types/core/util/FDUtil.d.ts +0 -171
- package/dist/types/core/util/FDUtil.d.ts.map +0 -10
- package/dist/types/core/util/ModuleUtil.d.ts +0 -27
- package/dist/types/core/util/ModuleUtil.d.ts.map +0 -10
- package/dist/types/core/util/StringUtil.d.ts +0 -5
- package/dist/types/core/util/StringUtil.d.ts.map +0 -10
- package/dist/types/core/util/TypeSpec.d.ts +0 -42
- package/dist/types/core/util/TypeSpec.d.ts.map +0 -10
- package/dist/types/core/util/ValidUtil.d.ts +0 -29
- package/dist/types/core/util/ValidUtil.d.ts.map +0 -10
- package/src/core/ActionManager.js +0 -147
- package/src/core/ContractManager.js +0 -112
- package/src/core/Conveyor.js +0 -185
- package/src/core/Core.js +0 -166
- package/src/core/Discovery.js +0 -403
- package/src/core/HookManager.js +0 -143
- package/src/core/action/ParseManager.js +0 -7
- package/src/core/action/PrintManager.js +0 -7
- package/src/core/contract/ParseContract.js +0 -7
- package/src/core/contract/PrintContract.js +0 -7
- package/src/core/util/ActionUtil.js +0 -53
- package/src/core/util/ContractUtil.js +0 -63
- package/src/core/util/DataUtil.js +0 -540
- package/src/core/util/FDUtil.js +0 -388
- package/src/core/util/ModuleUtil.js +0 -40
- package/src/core/util/StringUtil.js +0 -11
- package/src/core/util/TypeSpec.js +0 -114
- package/src/core/util/ValidUtil.js +0 -50
package/src/Discovery.js
ADDED
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import {Terms} from "@gesslar/negotiator"
|
|
2
|
+
import {Collection, Data, DirectoryObject, FileObject, Promised, Sass} from "@gesslar/toolkit"
|
|
3
|
+
import {execSync} from "child_process"
|
|
4
|
+
|
|
5
|
+
import Action from "./Action.js"
|
|
6
|
+
import {Schemer} from "@gesslar/negotiator/browser"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @import {Glog} from "@gesslar/toolkit"
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export default class Discovery {
|
|
13
|
+
/** @type {Glog} */
|
|
14
|
+
#glog
|
|
15
|
+
|
|
16
|
+
#options
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Constructor for Discovery.
|
|
20
|
+
*
|
|
21
|
+
* @param {object} arg - Constructor argument
|
|
22
|
+
* @param {object} arg.options - BeDoc options
|
|
23
|
+
* @param {Glog} arg.glog - Glog instance
|
|
24
|
+
*/
|
|
25
|
+
constructor({options = {}, glog}) {
|
|
26
|
+
this.#options = options
|
|
27
|
+
this.#glog = glog
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Discover actions from local or global node_modules
|
|
32
|
+
*
|
|
33
|
+
* @param {object} [specific] Configuration options for action discovery
|
|
34
|
+
* @param {FileObject} [specific.formatter] Print-related configuration options
|
|
35
|
+
* @param {FileObject} [specific.parser] Parse-related configuration options
|
|
36
|
+
* @param {Function} validateBeDocSchema - The validator function for BeDoc's action schema
|
|
37
|
+
* @returns {Promise<object>} A map of discovered modules
|
|
38
|
+
*/
|
|
39
|
+
async discoverActions(specific = {}, validateBeDocSchema) {
|
|
40
|
+
const glog = this.#glog
|
|
41
|
+
|
|
42
|
+
glog.debug("Discovering actions", 2)
|
|
43
|
+
|
|
44
|
+
glog.debug("Specific modules provided: %o", 2, Object.values(specific).filter(Boolean).length)
|
|
45
|
+
glog.debug("Specific modules provided: %j", 4, specific)
|
|
46
|
+
|
|
47
|
+
const files = []
|
|
48
|
+
const options = this.#options
|
|
49
|
+
const mock = options?.mock
|
|
50
|
+
? Data.isType(options.mock, "DirectoryObject")
|
|
51
|
+
? options.mock
|
|
52
|
+
: new DirectoryObject(options.mock)
|
|
53
|
+
: null
|
|
54
|
+
|
|
55
|
+
if(mock) {
|
|
56
|
+
glog.debug("Discovering mock actions in %o", 2, mock.path)
|
|
57
|
+
|
|
58
|
+
const {files: formatters} = await mock.glob("bedoc-*-formatter.js")
|
|
59
|
+
const {files: parsers} = await mock.glob("bedoc-*-parser.js")
|
|
60
|
+
|
|
61
|
+
files.push(...formatters, ...parsers)
|
|
62
|
+
} else {
|
|
63
|
+
glog.debug("Mock path not set, discovering actions in node_modules", 2)
|
|
64
|
+
|
|
65
|
+
glog.debug("Looking for actions in project's package.json", 2)
|
|
66
|
+
if(options.project) {
|
|
67
|
+
const exported = (options.project.actions || [])
|
|
68
|
+
.map(m => new FileObject(m, options.basePath))
|
|
69
|
+
.flat()
|
|
70
|
+
|
|
71
|
+
glog.debug("Found %o modules in project's package.json", 2, exported.length)
|
|
72
|
+
glog.debug("Found modules in project's package.json: %o", 2, exported)
|
|
73
|
+
|
|
74
|
+
files.push(...exported)
|
|
75
|
+
} else {
|
|
76
|
+
glog.debug("No modules found in project's package.json", 2)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
glog.debug("Looking for modules in node_modules (global and locally installed)", 2)
|
|
80
|
+
|
|
81
|
+
// `npm root -g` in particular is unreliable in Docker/CI/nvm/volta
|
|
82
|
+
// environments without a configured global prefix. Fall back to skipping
|
|
83
|
+
// any root that can't be resolved rather than aborting the whole run.
|
|
84
|
+
const npmRoot = cmd => {
|
|
85
|
+
try {
|
|
86
|
+
return execSync(cmd).toString().trim()
|
|
87
|
+
} catch {
|
|
88
|
+
glog.debug("`%o` failed; skipping", 2, cmd)
|
|
89
|
+
|
|
90
|
+
return ""
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const directories = [
|
|
95
|
+
npmRoot("npm root"),
|
|
96
|
+
npmRoot("npm root -g"),
|
|
97
|
+
]
|
|
98
|
+
.filter(Boolean)
|
|
99
|
+
.map(d => new DirectoryObject(d))
|
|
100
|
+
|
|
101
|
+
const nodeModulesDirs = await Data.asyncFilter(directories, d => d.exists)
|
|
102
|
+
|
|
103
|
+
glog.debug("Found %o directories to search for actions", 2, directories.length)
|
|
104
|
+
|
|
105
|
+
glog.debug("Directories to search for actions: %o", 4, directories)
|
|
106
|
+
|
|
107
|
+
for(const nodeModulesDir of nodeModulesDirs) {
|
|
108
|
+
const dirsToSearch = []
|
|
109
|
+
const {directories: moduleDirs} = await nodeModulesDir.read()
|
|
110
|
+
|
|
111
|
+
glog.debug("Found %o directories in %o", 2, moduleDirs.length, nodeModulesDir.path)
|
|
112
|
+
|
|
113
|
+
// Handle scoped packages (e.g., @bedoc/something)
|
|
114
|
+
const scopedDirs = moduleDirs.filter(d => d.name.startsWith("@"))
|
|
115
|
+
|
|
116
|
+
dirsToSearch.push(...moduleDirs)
|
|
117
|
+
|
|
118
|
+
// If we find a scope (e.g., "@bedoc"), look inside it for bedoc modules
|
|
119
|
+
for(const scopedDir of scopedDirs) {
|
|
120
|
+
const {directories: scopedPackages} = await scopedDir.read()
|
|
121
|
+
|
|
122
|
+
glog.debug("Found %o directories under scoped package %o", 2, directories.length, scopedDir.name)
|
|
123
|
+
glog.debug("Found directories under scoped package %o\n%o", 2, scopedDir.path, scopedPackages.map(d => d.path))
|
|
124
|
+
|
|
125
|
+
dirsToSearch.push(...scopedPackages)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
glog.debug("Found %o directories to search for actions", 2, dirsToSearch.length)
|
|
129
|
+
glog.debug("Found directories to search for actions: %o", 4, dirsToSearch)
|
|
130
|
+
|
|
131
|
+
const visibleDirs = dirsToSearch.filter(d => !d.name.startsWith("."))
|
|
132
|
+
|
|
133
|
+
for(const dir of visibleDirs) {
|
|
134
|
+
const packageJsonFile = new FileObject("package.json", dir)
|
|
135
|
+
|
|
136
|
+
if(!await packageJsonFile.exists)
|
|
137
|
+
continue
|
|
138
|
+
|
|
139
|
+
const packageJson = await packageJsonFile.loadData()
|
|
140
|
+
|
|
141
|
+
if(!packageJson.bedoc)
|
|
142
|
+
continue
|
|
143
|
+
|
|
144
|
+
const {actions} = packageJson.bedoc ?? null
|
|
145
|
+
|
|
146
|
+
if(!actions || !Array.isArray(actions))
|
|
147
|
+
continue
|
|
148
|
+
|
|
149
|
+
const moduleFileObjects = actions.map(f => new FileObject(f, dir))
|
|
150
|
+
const actionObjects = await Data.asyncFilter(
|
|
151
|
+
moduleFileObjects, f => f.exists)
|
|
152
|
+
|
|
153
|
+
glog.debug("Discovered %o modules from package.json file: %o", 2,
|
|
154
|
+
actions.length,
|
|
155
|
+
packageJsonFile.path
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
glog.debug("Discovered from package.json files: %o", 3, actions)
|
|
159
|
+
|
|
160
|
+
files.push(...actionObjects)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
glog.debug("Discovered %o modules", 2, files.length)
|
|
166
|
+
glog.debug("Discovered modules", 2, files.map(f => f.path))
|
|
167
|
+
glog.debug("Discovered modules %o", 3, files)
|
|
168
|
+
|
|
169
|
+
const loaded = await this.#loadActionsAndContracts(files, specific)
|
|
170
|
+
|
|
171
|
+
for(const [kind, actions] of Object.entries(loaded)) {
|
|
172
|
+
glog.debug("%o %o", 4, kind, actions)
|
|
173
|
+
|
|
174
|
+
for(const {file, terms} of actions) {
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
const isValid = validateBeDocSchema(terms)
|
|
178
|
+
if(!isValid) {
|
|
179
|
+
const {errors} = validateBeDocSchema
|
|
180
|
+
const report = Schemer.reportValidationErrors(errors)
|
|
181
|
+
|
|
182
|
+
throw Sass.new(report)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
} catch(error) {
|
|
186
|
+
glog.error(error)
|
|
187
|
+
|
|
188
|
+
throw Sass.new(`Validating schema for ${file.path}`, error)
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return loaded
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Process the discovered file objects and return the action and their
|
|
198
|
+
* respective contracts.
|
|
199
|
+
*
|
|
200
|
+
* @param {Array<FileObject>} moduleFiles - The module file objects to process
|
|
201
|
+
* @param {{parser: FileObject, formatter: FileObject}} specificModules - The specific modules to load
|
|
202
|
+
* @returns {Promise<object>} The discovered actions
|
|
203
|
+
*/
|
|
204
|
+
async #loadActionsAndContracts(moduleFiles, specificModules) {
|
|
205
|
+
const glog = this.#glog
|
|
206
|
+
|
|
207
|
+
glog.debug("Loading actions and contracts", 2)
|
|
208
|
+
glog.debug("Loading %o module files", 2, moduleFiles.length)
|
|
209
|
+
glog.debug("Specific modules to load: %o", 4, specificModules)
|
|
210
|
+
|
|
211
|
+
const resultActions = await Collection.allocateObject(
|
|
212
|
+
Action.actionTypes,
|
|
213
|
+
Action.actionTypes.map(() => new Array())
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
// Tag the specific actions to load, so we can filter them later
|
|
217
|
+
for(const [type, file] of Object.entries(specificModules)) {
|
|
218
|
+
if(file) {
|
|
219
|
+
glog.debug("Tagging specific module `%o` as `%o`", 3, file.path, type)
|
|
220
|
+
file.specificType = file.specificType || []
|
|
221
|
+
file.specificType.push(type)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const toLoad = [
|
|
226
|
+
...moduleFiles,
|
|
227
|
+
...Object.values(specificModules).filter(Boolean),
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
glog.debug("Loading %o discovered modules", 2, toLoad.length)
|
|
231
|
+
glog.debug("Modules to load: %o", 4, toLoad)
|
|
232
|
+
|
|
233
|
+
// Load the BeDoc action schema once for validating all contract terms
|
|
234
|
+
// const schemaValidator = await this.#loadSchemaValidator()
|
|
235
|
+
|
|
236
|
+
const settledLoading = await Promised.settle(
|
|
237
|
+
toLoad.map(async file => {
|
|
238
|
+
const action = await file.import()
|
|
239
|
+
|
|
240
|
+
if(!action.default?.meta)
|
|
241
|
+
return null
|
|
242
|
+
|
|
243
|
+
const {terms: actionTerms} = action.default.meta
|
|
244
|
+
|
|
245
|
+
const terms = await Terms.parse(actionTerms, file.parent)
|
|
246
|
+
|
|
247
|
+
return {file, action, terms}
|
|
248
|
+
})
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
if(Promised.hasRejected(settledLoading))
|
|
252
|
+
Promised.throw("Loading actions and contracts", settledLoading)
|
|
253
|
+
|
|
254
|
+
const loadedActions = Promised.values(settledLoading).filter(Boolean)
|
|
255
|
+
|
|
256
|
+
glog.debug("Loaded %o actions", 2, loadedActions.length)
|
|
257
|
+
glog.debug("Loaded actions", 4, loadedActions)
|
|
258
|
+
|
|
259
|
+
const filteredActions = []
|
|
260
|
+
|
|
261
|
+
for(const actionType of Action.actionTypes) {
|
|
262
|
+
const moduleFile = specificModules[actionType]
|
|
263
|
+
const matchingActions = []
|
|
264
|
+
|
|
265
|
+
if(moduleFile) {
|
|
266
|
+
glog.debug("Filtering actions for specific: %o", 2, actionType)
|
|
267
|
+
const found = loadedActions.find(
|
|
268
|
+
e => e.file.specificType?.includes(actionType) &&
|
|
269
|
+
e.action.default.meta.kind === actionType
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
if(!found)
|
|
273
|
+
throw Sass.new(`Could not find specific action: ${moduleFile.path}`)
|
|
274
|
+
|
|
275
|
+
matchingActions.push(found)
|
|
276
|
+
} else {
|
|
277
|
+
glog.debug("No specific action required for %o", 2, actionType)
|
|
278
|
+
|
|
279
|
+
const found = loadedActions.filter(
|
|
280
|
+
e => e.action.default.meta.kind === actionType
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
matchingActions.push(...found)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
glog.debug("Filtered %o actions for %o", 2,
|
|
287
|
+
matchingActions.length, actionType
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
filteredActions.push(...matchingActions)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
glog.debug("Filtered %o actions", 2, filteredActions.length)
|
|
294
|
+
glog.debug("Filtered actions %o", 4, filteredActions)
|
|
295
|
+
|
|
296
|
+
// Now check the metas for validity
|
|
297
|
+
for(const filtered of filteredActions) {
|
|
298
|
+
const {action, terms, file: moduleFile} = filtered
|
|
299
|
+
const {meta} = action.default
|
|
300
|
+
const {kind} = meta
|
|
301
|
+
|
|
302
|
+
glog.debug("Checking %o action", 2, kind)
|
|
303
|
+
|
|
304
|
+
const isValid = this.#validMeta(kind, {action, terms})
|
|
305
|
+
|
|
306
|
+
glog.debug("Meta in action %o in %o is %o", 3,
|
|
307
|
+
kind, moduleFile.module, isValid ? "valid" : "invalid"
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
if(isValid) {
|
|
311
|
+
glog.debug("Action is a valid %o action", 3, kind)
|
|
312
|
+
|
|
313
|
+
resultActions[kind].push({
|
|
314
|
+
file: moduleFile,
|
|
315
|
+
action,
|
|
316
|
+
terms,
|
|
317
|
+
})
|
|
318
|
+
} else {
|
|
319
|
+
glog.debug("Action is not a valid %o action", 3, kind)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
glog.debug("Processed %o action", 2, kind)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
for(const actionType of Action.actionTypes) {
|
|
326
|
+
const total = resultActions[actionType].length
|
|
327
|
+
|
|
328
|
+
glog.debug("Found %o %o actions", 2, total, actionType)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const total = Object.keys(resultActions).reduce((acc, curr) => {
|
|
332
|
+
return acc + resultActions[curr].length
|
|
333
|
+
}, 0)
|
|
334
|
+
|
|
335
|
+
glog.debug("Loaded %o action definitions from %o modules", 2,
|
|
336
|
+
total, moduleFiles.length
|
|
337
|
+
)
|
|
338
|
+
|
|
339
|
+
return resultActions
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
satisfyCriteria(actions, validatedConfig) {
|
|
343
|
+
const glog = this.#glog
|
|
344
|
+
|
|
345
|
+
glog.debug("Available actions to check %o", 4, actions)
|
|
346
|
+
|
|
347
|
+
const satisfied = {parser: [], formatter: []}
|
|
348
|
+
const toMatch = {
|
|
349
|
+
// TODO: investigate
|
|
350
|
+
parser: {metaKey: "input", configKey: "language", config: "parser"},
|
|
351
|
+
formatter: {metaKey: "format", configKey: "format", config: "formatter"},
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
glog.debug("Satisfying criteria for actions", 2)
|
|
355
|
+
for(const [actionType, search] of Object.entries(toMatch)) {
|
|
356
|
+
glog.debug("Satisfying criteria for %o actions", 2, actionType)
|
|
357
|
+
|
|
358
|
+
const {metaKey, configKey, config} = search
|
|
359
|
+
|
|
360
|
+
glog.debug("Meta key: %o, Config key: %o", 3, metaKey, configKey)
|
|
361
|
+
|
|
362
|
+
// First let's check if we wanted something specific
|
|
363
|
+
if(validatedConfig[config]) {
|
|
364
|
+
glog.debug("Checking for specific %o action", 3, actionType)
|
|
365
|
+
const found = actions[actionType].find(
|
|
366
|
+
a => a.file.specificType?.includes(actionType)
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
if(found) {
|
|
370
|
+
glog.debug("Found specific %o action", 3, actionType)
|
|
371
|
+
satisfied[actionType].push(found)
|
|
372
|
+
continue
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
glog.debug("No specific %o action found", 3, actionType)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Hmm! We didn't find anything specific. Let's check the criterion
|
|
379
|
+
glog.debug("Checking for %o actions with meta key %o", 3, actionType, metaKey)
|
|
380
|
+
glog.debug("Validated config to check against: %O", 3, validatedConfig)
|
|
381
|
+
|
|
382
|
+
const found = actions[actionType].filter(a => {
|
|
383
|
+
glog.debug("Meta criterion value: %o", 4, a.action.default.meta[metaKey])
|
|
384
|
+
glog.debug("Config criterion value: %o", 4, validatedConfig[configKey])
|
|
385
|
+
|
|
386
|
+
return a.action.default.meta[metaKey] === validatedConfig[configKey]
|
|
387
|
+
})
|
|
388
|
+
glog.debug("Found %o %o actions with criterion %o", 3, found.length, actionType, metaKey)
|
|
389
|
+
|
|
390
|
+
// Shove them into the result!
|
|
391
|
+
satisfied[actionType].push(...found)
|
|
392
|
+
|
|
393
|
+
// That should about cover it!
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return satisfied
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Validates the meta requirements for an action
|
|
401
|
+
*
|
|
402
|
+
* @param {string} actionType The action type to validate
|
|
403
|
+
* @param {object} toValidate - The action object to validate
|
|
404
|
+
* @returns {boolean} Whether the action object meets the meta requirements
|
|
405
|
+
*/
|
|
406
|
+
#validMeta(actionType, toValidate) {
|
|
407
|
+
const glog = this.#glog
|
|
408
|
+
|
|
409
|
+
glog.debug("Checking meta requirements for %o", 3, actionType)
|
|
410
|
+
|
|
411
|
+
const requirements = Action.actionMetaRequirements[actionType]
|
|
412
|
+
|
|
413
|
+
if(!requirements)
|
|
414
|
+
throw Sass.new(
|
|
415
|
+
`No meta requirements found for action type \`${actionType}\``,
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
for(const requirement of requirements) {
|
|
419
|
+
glog.debug("Checking requirement %o", 4, requirement)
|
|
420
|
+
|
|
421
|
+
if(Data.isType(requirement, "object")) {
|
|
422
|
+
for(const [key, value] of Object.entries(requirement)) {
|
|
423
|
+
glog.debug("Checking object requirement %o", 4, {key, value})
|
|
424
|
+
|
|
425
|
+
if(toValidate.action.default.meta[key] !== value)
|
|
426
|
+
return false
|
|
427
|
+
|
|
428
|
+
glog.debug("Requirement met: %o", 4, {key, value})
|
|
429
|
+
}
|
|
430
|
+
} else if(Data.isType(requirement, "string")) {
|
|
431
|
+
glog.debug("Checking string requirement: %o", 4, requirement)
|
|
432
|
+
|
|
433
|
+
if(!toValidate.action.default.meta[requirement])
|
|
434
|
+
return false
|
|
435
|
+
|
|
436
|
+
glog.debug("Requirement met: %o", 4, requirement)
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return true
|
|
441
|
+
}
|
|
442
|
+
}
|
|
@@ -23,15 +23,10 @@
|
|
|
23
23
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import console from "node:console"
|
|
27
26
|
import ErrorStackParser from "error-stack-parser"
|
|
28
|
-
import
|
|
29
|
-
|
|
30
|
-
import
|
|
31
|
-
import * as StringUtil from "./util/StringUtil.js"
|
|
32
|
-
|
|
33
|
-
const {resolveFilename} = FDUtil
|
|
34
|
-
const {capitalize} = StringUtil
|
|
27
|
+
import console from "node:console"
|
|
28
|
+
import Environment from "./Environment.js"
|
|
29
|
+
import {FileObject, Util} from "@gesslar/toolkit"
|
|
35
30
|
|
|
36
31
|
export const loggerColours = {
|
|
37
32
|
debug: [
|
|
@@ -71,15 +66,29 @@ export default class Logger {
|
|
|
71
66
|
|
|
72
67
|
constructor(options) {
|
|
73
68
|
this.#name = "BeDoc"
|
|
74
|
-
if(options)
|
|
69
|
+
if(options)
|
|
75
70
|
this.setOptions(options)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Create a Logger, performing any asynchronous setup (e.g. binding vscode
|
|
75
|
+
* notification handlers when running in an extension environment).
|
|
76
|
+
*
|
|
77
|
+
* @param {object} [options] - Logger options
|
|
78
|
+
* @returns {Promise<Logger>} The configured logger
|
|
79
|
+
*/
|
|
80
|
+
static async create(options) {
|
|
81
|
+
const logger = new Logger(options)
|
|
82
|
+
|
|
83
|
+
if(options?.env === Environment.EXTENSION) {
|
|
84
|
+
const vscode = await import("vscode")
|
|
85
|
+
|
|
86
|
+
logger.vscodeError = vscode.window.showErrorMessage
|
|
87
|
+
logger.vscodeWarn = vscode.window.showWarningMessage
|
|
88
|
+
logger.vscodeInfo = vscode.window.showInformationMessage
|
|
82
89
|
}
|
|
90
|
+
|
|
91
|
+
return logger
|
|
83
92
|
}
|
|
84
93
|
|
|
85
94
|
get name() {
|
|
@@ -103,7 +112,7 @@ export default class Logger {
|
|
|
103
112
|
}
|
|
104
113
|
|
|
105
114
|
#compose(level, message, debugLevel = 0) {
|
|
106
|
-
const tag = capitalize(level)
|
|
115
|
+
const tag = Util.capitalize(level)
|
|
107
116
|
|
|
108
117
|
if(level === "debug")
|
|
109
118
|
return `[${this.#name}] ${loggerColours[level][debugLevel]}${tag}${loggerColours.reset}: ${message}`
|
|
@@ -113,6 +122,7 @@ export default class Logger {
|
|
|
113
122
|
|
|
114
123
|
lastStackLine(error = new Error(), stepsRemoved = 3) {
|
|
115
124
|
const stack = ErrorStackParser.parse(error)
|
|
125
|
+
|
|
116
126
|
return stack[stepsRemoved]
|
|
117
127
|
}
|
|
118
128
|
|
|
@@ -125,9 +135,11 @@ export default class Logger {
|
|
|
125
135
|
columnNumber: col,
|
|
126
136
|
} = frame
|
|
127
137
|
|
|
128
|
-
const
|
|
138
|
+
const tempFile = new FileObject(file)
|
|
139
|
+
const {module, url} = tempFile
|
|
129
140
|
|
|
130
141
|
let functionName = func ?? "anonymous"
|
|
142
|
+
|
|
131
143
|
if(functionName.startsWith("#"))
|
|
132
144
|
functionName = `${module}.${functionName}`
|
|
133
145
|
|
|
@@ -149,7 +161,7 @@ export default class Logger {
|
|
|
149
161
|
result = `${result}:${line}:${col}`
|
|
150
162
|
|
|
151
163
|
if(level >= 3)
|
|
152
|
-
result = `${
|
|
164
|
+
result = `${url} ${result}`
|
|
153
165
|
|
|
154
166
|
return result
|
|
155
167
|
}
|