adapt-authoring-core 2.4.2 → 2.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.
@@ -11,7 +11,7 @@ export default class CoreModules {
11
11
 
12
12
  async getWorkflowBadges (homepage) {
13
13
  if (!homepage) return []
14
- const workflows = ['tests', 'standardjs', 'releases']
14
+ const workflows = ['standardjs', 'tests', 'releases']
15
15
  const results = await Promise.all(workflows.map(async w => {
16
16
  const url = `${homepage}/actions/workflows/${w}.yml`
17
17
  const badgeUrl = `${url}/badge.svg`
@@ -124,7 +124,7 @@ export default class Licensing {
124
124
 
125
125
  async generateMd () {
126
126
  let md = '<tr><th>Name</th><th>Version</th><th>License</th><th>Description</th></tr>\n'
127
- this.dependencies.forEach(pkg => {
127
+ this.dependencies.sort((a, b) => a.name.localeCompare(b.name)).forEach(pkg => {
128
128
  md += `<tr><td>${pkg.homepage ? `<a href="${pkg.homepage}" target="_blank">${pkg.name}</a>` : pkg.name}</td><td>${pkg.version}</td><td>${pkg.license}</td><td>${pkg.description}</tr>\n`
129
129
  })
130
130
  return `<details>\n<summary>Module dependency list</summary>\n<table>${md}</table>\n</details>`
package/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { default as AbstractModule } from './lib/AbstractModule.js'
2
2
  export { default as App } from './lib/App.js'
3
+ export { default as DataCache } from './lib/DataCache.js'
3
4
  export { default as DependencyLoader } from './lib/DependencyLoader.js'
4
5
  export { default as Hook } from './lib/Hook.js'
5
6
  export { metadataFileName, packageFileName, isObject, getArgs, spawn, readJson, writeJson, toBoolean, ensureDir, escapeRegExp, stringifyValues, loadDependencyFiles } from './lib/Utils.js'
@@ -0,0 +1,49 @@
1
+ import App from './App.js'
2
+ /**
3
+ * Time-limited data cache
4
+ * @memberof core
5
+ */
6
+ class DataCache {
7
+ /**
8
+ * @param {Object} options
9
+ * @param {Boolean} options.enable Whether the cache is enabled
10
+ * @param {Number} options.lifespan Cache entry lifespan in milliseconds
11
+ */
12
+ constructor ({ enable, lifespan }) {
13
+ this.isEnabled = enable === true
14
+ this.lifespan = lifespan
15
+ this.cache = {}
16
+ }
17
+
18
+ /**
19
+ * Retrieve cached data, or run fresh query if no cache exists or cache is invalid
20
+ * @param {Object} query
21
+ * @param {Object} options
22
+ * @param {Object} mongoOptions
23
+ * @returns {*} The cached data
24
+ */
25
+ async get (query, options, mongoOptions) {
26
+ const key = JSON.stringify(query) + JSON.stringify(options) + JSON.stringify(mongoOptions)
27
+ this.prune()
28
+ if (this.isEnabled && this.cache[key]) {
29
+ return this.cache[key].data
30
+ }
31
+ const mongodb = await App.instance.waitForModule('mongodb')
32
+ const data = await mongodb.find(options.collectionName, query, mongoOptions)
33
+ this.cache[key] = { data, timestamp: Date.now() }
34
+ return data
35
+ }
36
+
37
+ /**
38
+ * Removes invalid cache data
39
+ */
40
+ prune () {
41
+ Object.keys(this.cache).forEach(k => {
42
+ if (Date.now() > (this.cache[k].timestamp + this.lifespan)) {
43
+ delete this.cache[k]
44
+ }
45
+ })
46
+ }
47
+ }
48
+
49
+ export default DataCache
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adapt-authoring-core",
3
- "version": "2.4.2",
3
+ "version": "2.5.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,39 @@
1
+ import { describe, it } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import DataCache from '../lib/DataCache.js'
4
+
5
+ describe('DataCache', () => {
6
+ describe('#prune()', () => {
7
+ it('should remove expired entries from the cache', () => {
8
+ const instance = Object.create(DataCache.prototype)
9
+ instance.lifespan = 100
10
+ instance.cache = {
11
+ expired: { data: [1], timestamp: Date.now() - 200 },
12
+ valid: { data: [2], timestamp: Date.now() }
13
+ }
14
+ instance.prune()
15
+ assert.equal(instance.cache.expired, undefined)
16
+ assert.ok(instance.cache.valid)
17
+ })
18
+
19
+ it('should keep entries that have not expired', () => {
20
+ const instance = Object.create(DataCache.prototype)
21
+ instance.lifespan = 10000
22
+ instance.cache = {
23
+ a: { data: [1], timestamp: Date.now() },
24
+ b: { data: [2], timestamp: Date.now() }
25
+ }
26
+ instance.prune()
27
+ assert.ok(instance.cache.a)
28
+ assert.ok(instance.cache.b)
29
+ })
30
+
31
+ it('should handle an empty cache', () => {
32
+ const instance = Object.create(DataCache.prototype)
33
+ instance.lifespan = 100
34
+ instance.cache = {}
35
+ instance.prune()
36
+ assert.deepEqual(instance.cache, {})
37
+ })
38
+ })
39
+ })