adapt-authoring-config 1.0.0 → 1.1.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.
@@ -1,19 +1,15 @@
1
- name: Add to main project
1
+ # Calls the org-level reusable workflow to add PRs to the TODO Board
2
+
3
+ name: Add PR to Project
2
4
 
3
5
  on:
4
- issues:
5
- types:
6
- - opened
7
6
  pull_request:
8
7
  types:
9
8
  - opened
9
+ - reopened
10
10
 
11
11
  jobs:
12
12
  add-to-project:
13
- name: Add to main project
14
- runs-on: ubuntu-latest
15
- steps:
16
- - uses: actions/add-to-project@v0.1.0
17
- with:
18
- project-url: https://github.com/orgs/adapt-security/projects/5
19
- github-token: ${{ secrets.PROJECTS_SECRET }}
13
+ uses: adapt-security/.github/.github/workflows/new.yml@main
14
+ secrets:
15
+ PROJECTS_SECRET: ${{ secrets.PROJECTS_SECRET }}
@@ -3,10 +3,16 @@ on:
3
3
  push:
4
4
  branches:
5
5
  - master
6
+
6
7
  jobs:
7
8
  release:
8
9
  name: Release
9
10
  runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write # to be able to publish a GitHub release
13
+ issues: write # to be able to comment on released issues
14
+ pull-requests: write # to be able to comment on released pull requests
15
+ id-token: write # to enable use of OIDC for trusted publishing and npm provenance
10
16
  steps:
11
17
  - name: Checkout
12
18
  uses: actions/checkout@v3
@@ -16,10 +22,11 @@ jobs:
16
22
  uses: actions/setup-node@v3
17
23
  with:
18
24
  node-version: 'lts/*'
25
+ - name: Update npm
26
+ run: npm install -g npm@latest
19
27
  - name: Install dependencies
20
28
  run: npm ci
21
29
  - name: Release
22
30
  env:
23
31
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24
- NPM_TOKEN: ${{ secrets.AAT_NPM_TOKEN }}
25
- run: npx semantic-release
32
+ run: npx semantic-release
@@ -0,0 +1,13 @@
1
+ name: Standard.js formatting check
2
+ on: push
3
+ jobs:
4
+ default:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - uses: actions/checkout@master
8
+ - uses: actions/setup-node@master
9
+ with:
10
+ node-version: 'lts/*'
11
+ cache: 'npm'
12
+ - run: npm ci
13
+ - run: npx standard
@@ -1,70 +1,74 @@
1
- import fs from 'fs';
2
- import path from 'path';
1
+ import fs from 'fs'
2
+ import path from 'path'
3
3
 
4
4
  export default class Configuration {
5
- async run() {
6
- const schemas = this.loadSchemas();
7
- this.contents = Object.keys(schemas).sort();
8
- this.manualFile = 'configuration.md';
5
+ async run () {
6
+ const schemas = this.loadSchemas()
7
+ this.contents = Object.keys(schemas).sort()
8
+ this.manualFile = 'configuration.md'
9
9
  this.replace = {
10
- 'CODE_EXAMPLE': this.generateCodeExample(schemas),
11
- 'LIST': this.generateList(schemas)
12
- };
10
+ CODE_EXAMPLE: this.generateCodeExample(schemas),
11
+ LIST: this.generateList(schemas)
12
+ }
13
13
  }
14
- loadSchemas() {
15
- const schemas = {};
14
+
15
+ loadSchemas () {
16
+ const schemas = {}
16
17
  Object.values(this.app.dependencies).forEach(c => {
17
- const confDir = path.join(c.rootDir, 'conf');
18
+ const confDir = path.join(c.rootDir, 'conf')
18
19
  try {
19
- schemas[c.name] = JSON.parse(fs.readFileSync(path.join(confDir, 'config.schema.json')));
20
- } catch(e) {}
21
- });
22
- return schemas;
20
+ schemas[c.name] = JSON.parse(fs.readFileSync(path.join(confDir, 'config.schema.json')))
21
+ } catch (e) {}
22
+ })
23
+ return schemas
23
24
  }
24
- generateCodeExample(schemas) {
25
- let output = '\`\`\`javascript\nexport default {\n';
25
+
26
+ generateCodeExample (schemas) {
27
+ let output = '```javascript\nexport default {\n'
26
28
  this.contents.forEach((name) => {
27
- const schema = schemas[name];
28
- output += ` '${name}': {\n`;
29
+ const schema = schemas[name]
30
+ output += ` '${name}': {\n`
29
31
  Object.entries(schema.properties).forEach(([attr, config]) => {
30
- const required = schema.required && schema.required.includes(attr);
31
- if(config.description) output += ` // ${config.description}\n`;
32
- output += ` ${attr}: ${this.defaultToMd(config)}, // ${config.type}, ${required ? 'required' : 'optional'}\n`;
33
- });
34
- output += ` },\n`;
35
- });
36
- output += `};\n\`\`\``;
37
- return output;
32
+ const required = schema.required && schema.required.includes(attr)
33
+ if (config.description) output += ` // ${config.description}\n`
34
+ output += ` ${attr}: ${this.defaultToMd(config)}, // ${config.type}, ${required ? 'required' : 'optional'}\n`
35
+ })
36
+ output += ' },\n'
37
+ })
38
+ output += '};\n```'
39
+ return output
38
40
  }
39
- generateList(schemas) {
40
- let output = '';
41
+
42
+ generateList (schemas) {
43
+ let output = ''
41
44
 
42
45
  this.contents.forEach(dep => {
43
- const schema = schemas[dep];
44
- output += `<h3 id="${dep}" class="dep">${dep}</h3>\n\n`;
45
- output += `<div class="options">\n`;
46
+ const schema = schemas[dep]
47
+ output += `<h3 id="${dep}" class="dep">${dep}</h3>\n\n`
48
+ output += '<div class="options">\n'
46
49
  Object.entries(schema.properties).forEach(([attr, config]) => {
47
- const required = schema.required && schema.required.includes(attr);
48
- output += `<div class="attribute">\n`;
49
- output += `<div class="title"><span class="main">${attr}</span> (${config.type || ''}, ${required ? 'required' : 'optional'})</div>\n`;
50
- output += `<div class="inner">\n`;
51
- output += `<div class="description">${config.description}</div>\n`;
52
- if(!required) {
53
- output += `<div class="default"><span class="label">Default</span>: <pre>${this.defaultToMd(config)}</pre></div>\n`;
50
+ const required = schema.required && schema.required.includes(attr)
51
+ output += '<div class="attribute">\n'
52
+ output += `<div class="title"><span class="main">${attr}</span> (${config.type || ''}, ${required ? 'required' : 'optional'})</div>\n`
53
+ output += '<div class="inner">\n'
54
+ output += `<div class="description">${config.description}</div>\n`
55
+ if (!required) {
56
+ output += `<div class="default"><span class="label">Default</span>: <pre>${this.defaultToMd(config)}</pre></div>\n`
54
57
  }
55
- output += `</div>\n`;
56
- output += `</div>\n`;
57
- });
58
- output += `</div>`;
59
- output += `\n\n`;
60
- });
58
+ output += '</div>\n'
59
+ output += '</div>\n'
60
+ })
61
+ output += '</div>'
62
+ output += '\n\n'
63
+ })
61
64
 
62
- return output;
65
+ return output
63
66
  }
67
+
64
68
  /**
65
69
  * Returns a string formatted nicely for markdown
66
70
  */
67
- defaultToMd(config) {
68
- return JSON.stringify(config.default);
71
+ defaultToMd (config) {
72
+ return JSON.stringify(config.default, null, 2)?.replaceAll('\n', '\n ')
69
73
  }
70
74
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adapt-authoring-config",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "A configuration module for the Adapt authoring tool.",
5
5
  "homepage": "https://github.com/adapt-security/adapt-authoring-config",
6
6
  "license": "GPL-3.0",
@@ -13,22 +13,21 @@
13
13
  "dependencies": {
14
14
  "adapt-authoring-core": "github:adapt-security/adapt-authoring-core",
15
15
  "chalk": "^5.3.0",
16
- "glob": "^11.0.0"
16
+ "glob": "^13.0.0"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "adapt-authoring-core": "github:adapt-security/adapt-authoring-core"
20
20
  },
21
21
  "devDependencies": {
22
- "eslint": "^9.12.0",
23
- "standard": "^17.1.0",
24
- "@semantic-release/commit-analyzer": "^9.0.2",
22
+ "@semantic-release/commit-analyzer": "^13.0.1",
25
23
  "@semantic-release/git": "^10.0.1",
26
- "@semantic-release/github": "^8.0.5",
27
- "@semantic-release/npm": "^9.0.1",
28
- "@semantic-release/release-notes-generator": "^10.0.3",
29
- "conventional-changelog-eslint": "^3.0.9",
30
- "semantic-release": "^21.0.1",
31
- "semantic-release-replace-plugin": "^1.2.7"
24
+ "@semantic-release/github": "^12.0.2",
25
+ "@semantic-release/npm": "^13.1.2",
26
+ "@semantic-release/release-notes-generator": "^14.1.0",
27
+ "conventional-changelog-eslint": "^6.0.0",
28
+ "semantic-release": "^25.0.2",
29
+ "semantic-release-replace-plugin": "^1.2.7",
30
+ "standard": "^17.1.0"
32
31
  },
33
32
  "release": {
34
33
  "plugins": [
@@ -1,61 +1,63 @@
1
- const Config = require('../lib/configUtils');
2
- const path = require('path');
3
- const should = require('should');
1
+ /* global before describe, it */
4
2
 
5
- describe('Config module', function() {
6
- before(function() {
7
- this.config = new Config(global.ADAPT.app, {});
8
- this.configJson = require(path.join(process.cwd(), 'conf', 'testing.config.js'));
9
- });
10
- describe('#initialise()', function() {
11
- it('should error on missing required attribute', runConfigInitialise('required'));
12
- it('should error on incorrect attribute type', runConfigInitialise('incorrecttype'));
13
- it('should error on validator fail', runConfigInitialise('invalid'));
14
- });
15
- describe('#has()', function() {
16
- it('should be able to verify a value exists', function() {
17
- const exists = this.config.has('adapt-authoring-testing.test');
18
- exists.should.be.true();
19
- });
20
- it('should be able to verify a value doesn\'t exist', function() {
21
- const exists = this.config.has('adapt-authoring-testing.nonono');
22
- exists.should.not.be.true();
23
- });
24
- });
25
- describe('#get()', function() {
26
- it('should be able to retrieve a value', function() {
27
- const actualValue = this.config.get('adapt-authoring-testing.test');
28
- const expectedValue = this.configJson['adapt-authoring-testing'].test;
29
- actualValue.should.equal(expectedValue);
30
- });
31
- });
32
- describe('#set()', function() {
33
- it('should be able to set a value', function() {
34
- const newValue = 'newtestvalue';
35
- this.config.set('adapt-authoring-testing.test', newValue);
36
- const actualValue = this.config.get('adapt-authoring-testing.test');
37
- actualValue.should.equal(newValue);
38
- });
39
- });
40
- describe('#getPublicConfig()', function() {
41
- it('should be able to retrieve values marked as public', function() {
42
- this.config.app.dependencies = [{ name: 'adapt-authoring-testing', dir: path.join(__dirname, 'data') }];
43
- this.config.initialise();
44
- const config = this.config.getPublicConfig();
45
- const value = config['adapt-authoring-testing.one'];
46
- config.should.be.an.Object();
47
- value.should.equal('default');
48
- });
49
- });
50
- });
3
+ const Config = require('../lib/configUtils')
4
+ const path = require('path')
5
+ // const should = require('should')
6
+
7
+ describe('Config module', function () {
8
+ before(function () {
9
+ this.config = new Config(global.ADAPT.app, {})
10
+ this.configJson = require(path.join(process.cwd(), 'conf', 'testing.config.js'))
11
+ })
12
+ describe('#initialise()', function () {
13
+ it('should error on missing required attribute', runConfigInitialise('required'))
14
+ it('should error on incorrect attribute type', runConfigInitialise('incorrecttype'))
15
+ it('should error on validator fail', runConfigInitialise('invalid'))
16
+ })
17
+ describe('#has()', function () {
18
+ it('should be able to verify a value exists', function () {
19
+ const exists = this.config.has('adapt-authoring-testing.test')
20
+ exists.should.be.true()
21
+ })
22
+ it('should be able to verify a value doesn\'t exist', function () {
23
+ const exists = this.config.has('adapt-authoring-testing.nonono')
24
+ exists.should.not.be.true()
25
+ })
26
+ })
27
+ describe('#get()', function () {
28
+ it('should be able to retrieve a value', function () {
29
+ const actualValue = this.config.get('adapt-authoring-testing.test')
30
+ const expectedValue = this.configJson['adapt-authoring-testing'].test
31
+ actualValue.should.equal(expectedValue)
32
+ })
33
+ })
34
+ describe('#set()', function () {
35
+ it('should be able to set a value', function () {
36
+ const newValue = 'newtestvalue'
37
+ this.config.set('adapt-authoring-testing.test', newValue)
38
+ const actualValue = this.config.get('adapt-authoring-testing.test')
39
+ actualValue.should.equal(newValue)
40
+ })
41
+ })
42
+ describe('#getPublicConfig()', function () {
43
+ it('should be able to retrieve values marked as public', function () {
44
+ this.config.app.dependencies = [{ name: 'adapt-authoring-testing', dir: path.join(__dirname, 'data') }]
45
+ this.config.initialise()
46
+ const config = this.config.getPublicConfig()
47
+ const value = config['adapt-authoring-testing.one']
48
+ config.should.be.an.Object()
49
+ value.should.equal('default')
50
+ })
51
+ })
52
+ })
51
53
  /**
52
54
  * Checks ConfigUtility#initialise
53
55
  * Loads the testing data in tests/data/dirname
54
56
  */
55
- function runConfigInitialise(dirname) {
56
- return function() {
57
- this.config.app.dependencies = [{ name: 'adapt-authoring-testing', dir: path.join(__dirname, 'data', dirname) }];
58
- this.config.initialise();
59
- this.config.errors.length.should.be.exactly(1);
60
- };
57
+ function runConfigInitialise (dirname) {
58
+ return function () {
59
+ this.config.app.dependencies = [{ name: 'adapt-authoring-testing', dir: path.join(__dirname, 'data', dirname) }]
60
+ this.config.initialise()
61
+ this.config.errors.length.should.be.exactly(1)
62
+ }
61
63
  }
@@ -1,34 +1,36 @@
1
- const path = require('path');
2
- const utils = require('../lib/ConfigUtils');
3
- const should = require('should');
1
+ /* global describe, it */
4
2
 
5
- describe('Config utils', function() {
6
- describe('#loadFile()', function() {
7
- it('should be able to load a valid file', function() {
8
- const filepath = path.join(__dirname, 'data', 'testfile.json');
9
- const actualContents = utils.loadFile(filepath);
10
- const expectedContents = require(filepath);
11
- actualContents.should.deepEqual(expectedContents);
12
- });
13
- it('should not error on a missing file', function() {
14
- should.doesNotThrow(function() {
15
- const contents = utils.loadFile(path.join('this', 'path', 'does', 'not', 'exist.xyz'));
16
- should(contents).be.undefined();
17
- });
18
- });
19
- });
20
- describe('#loadConfigSchema()', function() {
21
- it('should be able to load a valid schema file', function() {
22
- const dir = path.join(__dirname, 'data');
23
- const actualContents = utils.loadConfigSchema(dir);
24
- const expectedContents = require(path.join(dir, 'conf', 'config.schema.js'));
25
- actualContents.should.deepEqual(expectedContents);
26
- });
27
- it('should not error on a missing schema file', function() {
28
- should.doesNotThrow(function() {
29
- const contents = utils.loadConfigSchema(path.join(__dirname, 'doesntexist'));
30
- should(contents).be.undefined();
31
- });
32
- });
33
- });
34
- });
3
+ const path = require('path')
4
+ const utils = require('../lib/ConfigUtils')
5
+ const should = require('should')
6
+
7
+ describe('Config utils', function () {
8
+ describe('#loadFile()', function () {
9
+ it('should be able to load a valid file', function () {
10
+ const filepath = path.join(__dirname, 'data', 'testfile.json')
11
+ const actualContents = utils.loadFile(filepath)
12
+ const expectedContents = require(filepath)
13
+ actualContents.should.deepEqual(expectedContents)
14
+ })
15
+ it('should not error on a missing file', function () {
16
+ should.doesNotThrow(function () {
17
+ const contents = utils.loadFile(path.join('this', 'path', 'does', 'not', 'exist.xyz'))
18
+ should(contents).be.undefined()
19
+ })
20
+ })
21
+ })
22
+ describe('#loadConfigSchema()', function () {
23
+ it('should be able to load a valid schema file', function () {
24
+ const dir = path.join(__dirname, 'data')
25
+ const actualContents = utils.loadConfigSchema(dir)
26
+ const expectedContents = require(path.join(dir, 'conf', 'config.schema.js'))
27
+ actualContents.should.deepEqual(expectedContents)
28
+ })
29
+ it('should not error on a missing schema file', function () {
30
+ should.doesNotThrow(function () {
31
+ const contents = utils.loadConfigSchema(path.join(__dirname, 'doesntexist'))
32
+ should(contents).be.undefined()
33
+ })
34
+ })
35
+ })
36
+ })
@@ -7,4 +7,4 @@ module.exports = {
7
7
  public: true
8
8
  }
9
9
  }
10
- };
10
+ }
@@ -4,4 +4,4 @@ module.exports = {
4
4
  type: 'Number'
5
5
  }
6
6
  }
7
- };
7
+ }
@@ -5,4 +5,4 @@ module.exports = {
5
5
  validator: val => val === 4
6
6
  }
7
7
  }
8
- };
8
+ }
@@ -5,4 +5,4 @@ module.exports = {
5
5
  required: true
6
6
  }
7
7
  }
8
- };
8
+ }
package/.eslintignore DELETED
@@ -1 +0,0 @@
1
- node_modules
package/.eslintrc DELETED
@@ -1,14 +0,0 @@
1
- {
2
- "env": {
3
- "browser": false,
4
- "node": true,
5
- "commonjs": false,
6
- "es2020": true
7
- },
8
- "extends": [
9
- "standard"
10
- ],
11
- "parserOptions": {
12
- "ecmaVersion": 2020
13
- }
14
- }
@@ -1,16 +0,0 @@
1
- name: Add labelled PRs to project
2
-
3
- on:
4
- pull_request:
5
- types: [ labeled ]
6
-
7
- jobs:
8
- add-to-project:
9
- if: ${{ github.event.label.name == 'dependencies' }}
10
- name: Add to main project
11
- runs-on: ubuntu-latest
12
- steps:
13
- - uses: actions/add-to-project@v0.1.0
14
- with:
15
- project-url: https://github.com/orgs/adapt-security/projects/5
16
- github-token: ${{ secrets.PROJECTS_SECRET }}
@@ -1,63 +0,0 @@
1
- # Defining module configuration
2
-
3
- As a module developer, you will likely have a number of user-configurable attributes for adjusting the functionality of your module. This is great from a user perspective as it allows customisation, but can introduce various bugs as a result of bad user input (missing or unexpected values etc.)
4
-
5
- The Adapt authoring tool's configuration module aims to pre-empt as many of these issues as possible through the use of configuration **schemas**, which can define the following:
6
- - Required attributes
7
- - Default values for optional attributes
8
- - Expected type for values (e.g. number, string, array)
9
- - Validation constraints (see JSON schema spec)
10
-
11
- ## Defining module configuration
12
- _**Note**: it is not mandatory to include a config schema for your module, but it may help your general wellbeing/code neatness..._
13
-
14
- All that's needed to enable this feature is to include a `config.schema.json` to a directory named `conf` in the root of your module.
15
-
16
- This file must export a valid JSON object. See the JSON schema docs for more information.
17
-
18
- ### Example configuration schema
19
- The below example shows a few common configuration use-cases:
20
-
21
- ```json
22
- {
23
- "$schema": "https://json-schema.org/draft/2020-12/schema",
24
- "type": "object",
25
- "properties": {
26
- "requiredAttribute": {
27
- "type": "Number",
28
- "description": "This option is required"
29
- },
30
- "optionalAttribute": {
31
- "type": "String",
32
- "default": "This will be the default value",
33
- "description": "An optional attribute with a default value"
34
- },
35
- },
36
- "required": ["requiredAttribute"]
37
- }
38
- ```
39
-
40
- ## Directory paths
41
-
42
- It may be necessary to define directory paths in your config schema (e.g. the assets module defines an `uploadDir` attribute). To make this simpler from a developer _and_ user perspective, you can make use of the special `isDirectory` JSON schema keyword which will automatically populate the value with a number of global directory paths.
43
-
44
- If `isDirectory` is set in a config schema, the configuration module will look for the following keys and replace them with the corresponding `adapt-authoring-core` config values:
45
-
46
- - `$ROOT` -> `adapt-authoring-core.rootDir`
47
- - `$DATA` -> `adapt-authoring-core.dataDir`
48
- - `$TEMP` -> `adapt-authoring-core.tempDir`
49
-
50
- This allows the user to specify just the `dataDir` and `tempDir` attributes, and you can be safe in the knowledge that your config schema value will resolve to the correct location.
51
-
52
- See the following JSON schema snippet as an example:
53
-
54
- ```json
55
- {
56
- "uploadDir": {
57
- "type": "String",
58
- "description": "Temporary file upload directory for myplugin",
59
- "isDirectory": true,
60
- "default": "$TEMP/myfiles"
61
- },
62
- }
63
- ```