@gesslar/bedoc 1.7.0 → 1.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gesslar/bedoc",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "Pluggable documentation engine for any language and format",
5
5
  "publisher": "gesslar",
6
6
  "author": "gesslar",
@@ -7,10 +7,12 @@ export default class ActionManager {
7
7
  #log
8
8
  #debug
9
9
  #file
10
+ #variables
10
11
 
11
- constructor(actionDefinition, logger) {
12
+ constructor({actionDefinition, logger, variables}) {
12
13
  this.#log = logger
13
14
  this.#debug = this.#log.newDebug()
15
+ this.#variables = variables
14
16
 
15
17
  this.#initialize(actionDefinition)
16
18
  }
@@ -65,6 +67,10 @@ export default class ActionManager {
65
67
  return this.#log
66
68
  }
67
69
 
70
+ get variables() {
71
+ return this.#variables
72
+ }
73
+
68
74
  async #setupAction() {
69
75
  const setup = this.action?.setup
70
76
 
@@ -90,7 +96,11 @@ export default class ActionManager {
90
96
  return
91
97
 
92
98
  await this.hookManager.setup.call(
93
- this.hookManager.hooks, {parent: this.action, log: this.#log}
99
+ this.hookManager.hooks, {
100
+ action: this.action,
101
+ variables: this.#variables,
102
+ log: this.#log
103
+ }
94
104
  )
95
105
  }
96
106
 
@@ -246,9 +246,22 @@ export default class Configuration {
246
246
  if(!configFile)
247
247
  throw new Error("No config file specified")
248
248
 
249
- const config = loadJson(configFile)
250
-
251
- allOptions.push({source: "config", options: config})
249
+ const configObject = loadJson(configFile)
250
+ const subConfigName =
251
+ entryOptions?.sub ||
252
+ packageJson?.sub ||
253
+ environmentVariables?.sub
254
+
255
+ // If we didn't specify a subconfiguration, let's just remove
256
+ // it so it doesn't pollute anything.
257
+ if(!subConfigName)
258
+ delete configObject.sub
259
+
260
+ const finalConfig = subConfigName?.value
261
+ ? this.#resolveSubconfigs(configObject, subConfigName.value)
262
+ : configObject
263
+
264
+ allOptions.push({source: "config", options: finalConfig})
252
265
  }
253
266
 
254
267
  allOptions.push({source: "entry", options: entryOptions})
@@ -256,6 +269,21 @@ export default class Configuration {
256
269
  return allOptions
257
270
  }
258
271
 
272
+ #resolveSubconfigs(configObject, subConfigName) {
273
+ const subConfig = configObject.sub?.find(sub => sub.name === subConfigName)
274
+
275
+ if(!subConfig)
276
+ throw new Error(`No such subconfiguration \`${subConfigName}\``)
277
+
278
+ // We don't need this anymore
279
+ delete subConfig.name
280
+
281
+ for(const [key,val] of Object.entries(subConfig))
282
+ configObject[key] = val
283
+
284
+ return configObject
285
+ }
286
+
259
287
  /**
260
288
  * Get environment variables
261
289
  *
@@ -120,6 +120,14 @@ const ConfigurationParameters = Object.freeze({
120
120
  mustExist: true,
121
121
  },
122
122
  },
123
+ sub: {
124
+ short: "s",
125
+ param: "name",
126
+ description: "Specify a subconfiguration",
127
+ type: newTypeSpec("string"),
128
+ required: false,
129
+ dependent: "config",
130
+ },
123
131
  debug: {
124
132
  short: "d",
125
133
  description: "Enable debug mode",
package/src/core/Core.js CHANGED
@@ -91,14 +91,18 @@ export default class Core {
91
91
 
92
92
  // Adding to instance
93
93
  instance.actions = {}
94
+ const {variables} = validConfig
94
95
  const managers = {print: PrintManager, parse: ParseManager}
95
- for(const [, value] of Object.entries(finalActions)) {
96
- const {action: actionType} = value.action.meta
96
+ for(const [, actionDefinition] of Object.entries(finalActions)) {
97
+ const {action: actionType} = actionDefinition.action.meta
97
98
 
98
99
  debug("Attaching %o action to instance", 2, actionType)
99
- instance.actions[actionType] = new managers[actionType](
100
- value, instance.logger
101
- )
100
+ instance.actions[actionType] =
101
+ new managers[actionType] ({
102
+ actionDefinition,
103
+ logger: instance.logger,
104
+ variables
105
+ })
102
106
 
103
107
  if(validConfig.hooks) {
104
108
  const hookManager = await HookManager.new({
@@ -7,7 +7,7 @@ import * as ActionUtil from "./util/ActionUtil.js"
7
7
  import * as DataUtil from "./util/DataUtil.js"
8
8
  import {composeDirectory,directoryExists} from "./util/FDUtil.js"
9
9
 
10
- const {ls,resolveFilename,getFiles} = FDUtil
10
+ const {ls,fileExists,composeFilename,getFiles} = FDUtil
11
11
  const {actionTypes, actionMetaRequirements, loadJson} = ActionUtil
12
12
  const {isType} = DataUtil
13
13
 
@@ -52,6 +52,7 @@ export default class Discovery {
52
52
  debug("Mock path not set, discovering actions in node_modules", 2)
53
53
 
54
54
  debug("Looking for actions in project's package.json", 2)
55
+
55
56
  if(this.core.packageJson?.modules) {
56
57
  const actions = this.core.packageJson?.modules
57
58
 
@@ -66,30 +67,46 @@ export default class Discovery {
66
67
  debug("No actions found in project's package.json", 2)
67
68
  }
68
69
 
69
- debug("Looking for actions in node_modules (global and locally installed", 2)
70
+ debug("Looking for actions in node_modules (global and locally installed)", 2)
70
71
  const directories = [
71
- "./node_modules",
72
+ execSync("npm root").toString().trim(),
72
73
  execSync("npm root -g").toString().trim(),
73
- ]
74
+ ].filter(Boolean)
75
+
76
+ const nodeModulesDirs = directories
77
+ .map(composeDirectory)
78
+ .filter(directoryExists)
74
79
 
75
80
  debug("Found %o directories to search for actions", 2, directories.length)
76
81
  debug("Directories to search for actions: %o", 3, directories)
77
82
 
78
- const moduleDirectories = directories
79
- .map(composeDirectory)
80
- .filter(directoryExists)
81
- for(const moduleDirectory of moduleDirectories) {
82
- const {directories: dirs} = await ls(moduleDirectory.absolutePath)
83
+ for(const nodeModulesDir of nodeModulesDirs) {
84
+ const dirsToSearch = []
85
+ const {directories: moduleDirs} = await ls(nodeModulesDir.absolutePath)
83
86
 
84
- debug("Found %o directories in `%s`", 2,
85
- dirs.length, moduleDirectory.absolutePath
86
- )
87
+ debug("Found %o directories in %o", 2, moduleDirs.length, nodeModulesDir.absolutePath)
88
+
89
+ // Handle scoped packages (e.g., @bedoc/something)
90
+ const scopedDirs = moduleDirs.filter(d => d.name.startsWith("@"))
87
91
 
88
- const bedocDirs = dirs.filter(d => d.name.startsWith("bedoc-"))
89
- debug("Found %o bedoc directories under %s", 2, bedocDirs.length, moduleDirectory.absolutePath)
92
+ dirsToSearch.push(...moduleDirs)
90
93
 
91
- const exports = bedocDirs.map(d => this.#getModuleExports(d))
92
- debug("Found %o module exports under %s", 2, exports.length, moduleDirectory.absolutePath)
94
+ // If we find a scope (e.g., "@bedoc"), look inside it for bedoc modules
95
+ for(const scopedDir of scopedDirs) {
96
+ const {directories: scopedPackages} = await ls(scopedDir.absolutePath)
97
+
98
+ debug("Found %o directories under scoped package %o", 2, directories.length, scopedDir.name)
99
+
100
+ dirsToSearch.push(...scopedPackages)
101
+ }
102
+
103
+ debug("Found %o directories to search for actions", 2, dirsToSearch.length)
104
+
105
+ const exports = dirsToSearch
106
+ .filter(d => !d.name.startsWith("."))
107
+ .map(d => this.#getModuleExports(d))
108
+
109
+ debug("Found %o module exports under %o", 2, exports.length, nodeModulesDir.absolutePath)
93
110
 
94
111
  bucket.push(...exports.flat())
95
112
  }
@@ -108,18 +125,27 @@ export default class Discovery {
108
125
  */
109
126
  #getModuleExports(dirMap) {
110
127
  const debug = this.#debug
111
- debug("Getting module exports from `%s`", 3, dirMap.absolutePath)
128
+ debug("Getting module exports from %o", 3, dirMap.absolutePath)
129
+
130
+ const packageJsonFile = composeFilename(dirMap, "package.json")
131
+ if(!fileExists(packageJsonFile))
132
+ return []
112
133
 
113
- const packageJsonFile = resolveFilename("package.json", dirMap)
114
- debug("Loading package.json from `%s`", 3, packageJsonFile.absolutePath)
134
+ debug("Loading package.json from %o", 3, packageJsonFile.absolutePath)
115
135
 
116
136
  const packageJson = loadJson(packageJsonFile)
117
- debug("Loaded package.json from `%s`", 3, packageJsonFile.absolutePath)
137
+ debug("Loaded package.json from %o", 3, packageJsonFile.absolutePath)
118
138
 
119
139
  const bedocPackageJsonModules = packageJson.bedoc?.modules ?? []
120
- const bedocModuleFiles = bedocPackageJsonModules.map(file =>
121
- resolveFilename(file, dirMap)
122
- )
140
+
141
+ debug("Discovered %o published modules", 2, bedocPackageJsonModules.length)
142
+ debug("Published modules %o", 3, bedocPackageJsonModules)
143
+
144
+ const bedocModuleFiles = bedocPackageJsonModules
145
+ .map(m => composeFilename(dirMap, m))
146
+ .filter(m => fileExists(m))
147
+
148
+ debug("Composed modules %o", 3, bedocModuleFiles)
123
149
 
124
150
  return bedocModuleFiles
125
151
  }
@@ -225,7 +251,7 @@ export default class Discovery {
225
251
  JSON.stringify(moduleFile, null, 2) + "\n" +
226
252
  JSON.stringify(action, null, 2))
227
253
 
228
- debug("Checking action `%s`", 2, metaAction)
254
+ debug("Checking action %o", 2, metaAction)
229
255
 
230
256
  const isValid = this.#validMeta(metaAction, {action, contract})
231
257
 
@@ -246,7 +272,7 @@ export default class Discovery {
246
272
 
247
273
  for(const actionType of actionTypes) {
248
274
  const total = resultActions[actionType].length
249
- debug("Found %o `%o` actions", 2, total, actionType)
275
+ debug("Found %o %o actions", 2, total, actionType)
250
276
  }
251
277
 
252
278
  const total = Object.keys(resultActions).reduce((acc, curr) => {
@@ -280,7 +306,7 @@ export default class Discovery {
280
306
 
281
307
  // First let's check if we wanted something specific
282
308
  if(validatedConfig[config]) {
283
- debug("Checking for specific `%s` action", 3, actionType)
309
+ debug("Checking for specific %o action", 3, actionType)
284
310
  const found = actions[actionType].find(
285
311
  a => a.file.specificType.includes(actionType)
286
312
  )
@@ -294,7 +320,7 @@ export default class Discovery {
294
320
  }
295
321
 
296
322
  // Hmm! We didn't find anything specific. Let's check the criterion
297
- debug("Checking for `%s` actions with criterion `%s`", 3, actionType, criterion)
323
+ debug("Checking for %o actions with criterion %o", 3, actionType, criterion)
298
324
  debug("Validated config to check against: %o", 3, validatedConfig)
299
325
  const found = actions[actionType].filter(a => {
300
326
  debug("Meta criterion value: %o", 4, a.action.meta[criterion])
@@ -341,7 +367,7 @@ export default class Discovery {
341
367
  */
342
368
  #validMeta(actionType, toValidate) {
343
369
  const debug = this.#debug
344
- debug("Checking meta requirements for `%s`", 3, actionType)
370
+ debug("Checking meta requirements for %o", 3, actionType)
345
371
 
346
372
  const requirements = actionMetaRequirements[actionType]
347
373
  if(!requirements)