adapt-authoring-core 2.1.3 → 2.2.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.
@@ -10,8 +10,11 @@ export default class CoreModules {
10
10
  generateMd () {
11
11
  return Object.keys(this.app.dependencies).sort().reduce((s, name) => {
12
12
  const { version, description, homepage } = this.app.dependencies[name]
13
- const badge = homepage ? `[![Tests](${homepage}/actions/workflows/tests.yml/badge.svg)](${homepage}/actions/workflows/tests.yml)` : ''
14
- return `${s}\n| ${homepage ? `[${name}](${homepage})` : name} | ${version} | ${description} | ${badge} |`
15
- }, '| Name | Version | Description | Tests |\n| - | :-: | - | :-: |')
13
+ const workflows = ['tests', 'standardjs']
14
+ const badges = homepage
15
+ ? workflows.map(w => `[![${w}](${homepage}/actions/workflows/${w}.yml/badge.svg)](${homepage}/actions/workflows/${w}.yml)`).join('<br>')
16
+ : ''
17
+ return `${s}\n| ${homepage ? `[${name}](${homepage})` : name} | ${version} | ${description} | ${badges} |`
18
+ }, '| Name | Version | Description | Status |\n| - | :-: | - | :-: |')
16
19
  }
17
20
  }
package/index.js CHANGED
@@ -2,4 +2,4 @@ export { default as AbstractModule } from './lib/AbstractModule.js'
2
2
  export { default as App } from './lib/App.js'
3
3
  export { default as DependencyLoader } from './lib/DependencyLoader.js'
4
4
  export { default as Hook } from './lib/Hook.js'
5
- export { metadataFileName, packageFileName, isObject, getArgs, spawn, readJson, writeJson, toBoolean, ensureDir, escapeRegExp, stringifyValues } from './lib/Utils.js'
5
+ export { metadataFileName, packageFileName, isObject, getArgs, spawn, readJson, writeJson, toBoolean, ensureDir, escapeRegExp, stringifyValues, loadDependencyFiles } from './lib/Utils.js'
package/lib/Utils.js CHANGED
@@ -8,3 +8,4 @@ export { toBoolean } from './utils/toBoolean.js'
8
8
  export { ensureDir } from './utils/ensureDir.js'
9
9
  export { escapeRegExp } from './utils/escapeRegExp.js'
10
10
  export { stringifyValues } from './utils/stringifyValues.js'
11
+ export { loadDependencyFiles } from './utils/loadDependencyFiles.js'
@@ -0,0 +1,25 @@
1
+ import fs from 'fs/promises'
2
+ import { glob } from 'glob'
3
+ import App from '../App.js'
4
+
5
+ /**
6
+ * Scans files matching a glob pattern across all module dependency directories.
7
+ * @param {string} pattern - Glob pattern to match files (e.g. 'errors/*.json')
8
+ * @param {Object} [options] - Options
9
+ * @param {boolean} [options.parse=false] - If true, reads and parses each matched file as JSON
10
+ * @param {Object} [options.dependencies] - Custom dependencies map (defaults to App.instance.dependencies)
11
+ * @returns {Promise<Object>} Map of module name to array of file paths (or parsed JSON objects if parse is true)
12
+ */
13
+ export async function loadDependencyFiles (pattern, options = {}) {
14
+ const { parse = false, dependencies = App.instance.dependencies } = options
15
+ const results = {}
16
+ await Promise.all(Object.values(dependencies).map(async dep => {
17
+ const files = await glob(pattern, { cwd: dep.rootDir, absolute: true })
18
+ if (!files.length) return
19
+ results[dep.name] = await Promise.all(files.map(async f => {
20
+ if (parse) return JSON.parse(await fs.readFile(f, 'utf8'))
21
+ return f
22
+ }))
23
+ }))
24
+ return results
25
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adapt-authoring-core",
3
- "version": "2.1.3",
3
+ "version": "2.2.0",
4
4
  "description": "A bundle of reusable 'core' functionality",
5
5
  "homepage": "https://github.com/adapt-security/adapt-authoring-core",
6
6
  "license": "GPL-3.0",
@@ -0,0 +1,91 @@
1
+ import { describe, it } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import fs from 'fs/promises'
4
+ import path from 'path'
5
+ import os from 'os'
6
+
7
+ import { loadDependencyFiles } from '../lib/utils/loadDependencyFiles.js'
8
+
9
+ async function makeTempDir (suffix) {
10
+ return fs.mkdtemp(path.join(os.tmpdir(), `loadDepFiles-${suffix}-`))
11
+ }
12
+
13
+ describe('loadDependencyFiles()', () => {
14
+ it('should return file paths grouped by module name', async () => {
15
+ const dir = await makeTempDir('paths')
16
+ await fs.writeFile(path.join(dir, 'a.json'), '{"x":1}')
17
+ const deps = { mymod: { name: 'mymod', rootDir: dir } }
18
+ try {
19
+ const result = await loadDependencyFiles('*.json', { dependencies: deps })
20
+ assert.ok(result.mymod, 'should have entry for mymod')
21
+ assert.equal(result.mymod.length, 1)
22
+ assert.ok(result.mymod[0].endsWith('a.json'))
23
+ } finally {
24
+ await fs.rm(dir, { recursive: true })
25
+ }
26
+ })
27
+
28
+ it('should parse JSON when parse option is true', async () => {
29
+ const dir = await makeTempDir('parse')
30
+ await fs.writeFile(path.join(dir, 'b.json'), '{"key":"value"}')
31
+ const deps = { mymod: { name: 'mymod', rootDir: dir } }
32
+ try {
33
+ const result = await loadDependencyFiles('*.json', { parse: true, dependencies: deps })
34
+ assert.ok(result.mymod, 'should have entry for mymod')
35
+ assert.equal(result.mymod.length, 1)
36
+ assert.deepEqual(result.mymod[0], { key: 'value' })
37
+ } finally {
38
+ await fs.rm(dir, { recursive: true })
39
+ }
40
+ })
41
+
42
+ it('should return empty object when no files match', async () => {
43
+ const dir = await makeTempDir('nomatch')
44
+ const deps = { mymod: { name: 'mymod', rootDir: dir } }
45
+ try {
46
+ const result = await loadDependencyFiles('errors/*.json', { dependencies: deps })
47
+ assert.deepEqual(result, {})
48
+ } finally {
49
+ await fs.rm(dir, { recursive: true })
50
+ }
51
+ })
52
+
53
+ it('should group files by module name across multiple deps', async () => {
54
+ const dir1 = await makeTempDir('multi1')
55
+ const dir2 = await makeTempDir('multi2')
56
+ await fs.writeFile(path.join(dir1, 'x.json'), '"a"')
57
+ await fs.writeFile(path.join(dir2, 'y.json'), '"b"')
58
+ const deps = {
59
+ mod1: { name: 'mod1', rootDir: dir1 },
60
+ mod2: { name: 'mod2', rootDir: dir2 }
61
+ }
62
+ try {
63
+ const result = await loadDependencyFiles('*.json', { dependencies: deps })
64
+ assert.ok(result.mod1)
65
+ assert.ok(result.mod2)
66
+ assert.equal(result.mod1.length, 1)
67
+ assert.equal(result.mod2.length, 1)
68
+ } finally {
69
+ await fs.rm(dir1, { recursive: true })
70
+ await fs.rm(dir2, { recursive: true })
71
+ }
72
+ })
73
+
74
+ it('should not include modules with no matching files', async () => {
75
+ const dir1 = await makeTempDir('partial1')
76
+ const dir2 = await makeTempDir('partial2')
77
+ await fs.writeFile(path.join(dir1, 'match.json'), '{}')
78
+ const deps = {
79
+ mod1: { name: 'mod1', rootDir: dir1 },
80
+ mod2: { name: 'mod2', rootDir: dir2 }
81
+ }
82
+ try {
83
+ const result = await loadDependencyFiles('*.json', { dependencies: deps })
84
+ assert.ok(result.mod1)
85
+ assert.equal(result.mod2, undefined)
86
+ } finally {
87
+ await fs.rm(dir1, { recursive: true })
88
+ await fs.rm(dir2, { recursive: true })
89
+ }
90
+ })
91
+ })