adapt-authoring-core 0.0.1

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/.eslintignore ADDED
@@ -0,0 +1 @@
1
+ node_modules
package/.eslintrc ADDED
@@ -0,0 +1,14 @@
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
+ }
@@ -0,0 +1,55 @@
1
+ name: Bug Report
2
+ description: File a bug report
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to fill out this bug report!
9
+ - type: textarea
10
+ id: description
11
+ attributes:
12
+ label: What happened?
13
+ description: Please describe the issue
14
+ validations:
15
+ required: true
16
+ - type: textarea
17
+ id: expected
18
+ attributes:
19
+ label: Expected behaviour
20
+ description: Tell us what should have happened
21
+ - type: textarea
22
+ id: repro-steps
23
+ attributes:
24
+ label: Steps to reproduce
25
+ description: Tell us how to reproduce the issue
26
+ validations:
27
+ required: true
28
+ - type: input
29
+ id: aat-version
30
+ attributes:
31
+ label: Authoring tool version
32
+ description: What version of the Adapt authoring tool are you running?
33
+ validations:
34
+ required: true
35
+ - type: input
36
+ id: fw-version
37
+ attributes:
38
+ label: Framework version
39
+ description: What version of the Adapt framework are you running?
40
+ - type: dropdown
41
+ id: browsers
42
+ attributes:
43
+ label: What browsers are you seeing the problem on?
44
+ multiple: true
45
+ options:
46
+ - Firefox
47
+ - Chrome
48
+ - Safari
49
+ - Microsoft Edge
50
+ - type: textarea
51
+ id: logs
52
+ attributes:
53
+ label: Relevant log output
54
+ description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
55
+ render: sh
@@ -0,0 +1 @@
1
+ blank_issues_enabled: false
@@ -0,0 +1,22 @@
1
+ name: Feature request
2
+ description: Request a new feature
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to request a new feature in the Adapt authoring tool! The Adapt team will consider all new feature requests, but unfortunately cannot commit to every one.
9
+ - type: textarea
10
+ id: description
11
+ attributes:
12
+ label: Feature description
13
+ description: Please describe your feature request
14
+ validations:
15
+ required: true
16
+ - type: checkboxes
17
+ id: contribute
18
+ attributes:
19
+ label: Can you work on this feature?
20
+ description: If you are able to commit your own time to work on this feature, it will greatly increase the liklihood of it being implemented by the core dev team. Otherwise, it will be triaged and prioritised alongside the core team's current priorities.
21
+ options:
22
+ - label: I can contribute
@@ -0,0 +1,11 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: "npm" # See documentation for possible values
9
+ directory: "/" # Location of package manifests
10
+ schedule:
11
+ interval: "weekly"
@@ -0,0 +1,25 @@
1
+ [//]: # (Please title your PR according to eslint commit conventions)
2
+ [//]: # (See https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-eslint#eslint-convention for details)
3
+
4
+ [//]: # (Add a link to the original issue)
5
+
6
+ [//]: # (Delete as appropriate)
7
+ ### Fix
8
+ * A sentence describing each fix
9
+
10
+ ### Update
11
+ * A sentence describing each udpate
12
+
13
+ ### New
14
+ * A sentence describing each new feature
15
+
16
+ ### Breaking
17
+ * A sentence describing each breaking change
18
+
19
+ [//]: # (List appropriate steps for testing if needed)
20
+ ### Testing
21
+ 1. Steps for testing
22
+
23
+ [//]: # (Mention any other dependencies)
24
+
25
+
@@ -0,0 +1,16 @@
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 }}
@@ -0,0 +1,19 @@
1
+ name: Add to main project
2
+
3
+ on:
4
+ issues:
5
+ types:
6
+ - opened
7
+ pull_request:
8
+ types:
9
+ - opened
10
+
11
+ jobs:
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 }}
@@ -0,0 +1,23 @@
1
+ {
2
+ "module": false,
3
+ "documentation": {
4
+ "enable": true,
5
+ "manualIndex": "docs/index-manual.md",
6
+ "sourceIndex": "docs/index-backend.md",
7
+ "manualPages": {
8
+ "binscripts.md": "reference",
9
+ "coremodules.md": "reference",
10
+ "data-folder.md": "basics",
11
+ "customising.md": "advanced",
12
+ "licensing.md": "reference",
13
+ "temp-folder.md": "basics",
14
+ "writing-a-module.md": "basics",
15
+ "writing-core-code.md": "contributing"
16
+ },
17
+ "manualPlugins": [
18
+ "docs/plugins/binscripts.js",
19
+ "docs/plugins/coremodules.js",
20
+ "docs/plugins/licensing.js"
21
+ ]
22
+ }
23
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "type": "object",
4
+ "properties": {
5
+ "isProduction": {
6
+ "description": "Whether this app configuration is a production environment",
7
+ "type": "boolean",
8
+ "default": true
9
+ },
10
+ "dataDir": {
11
+ "description": "Directory for persistant application data",
12
+ "type": "string",
13
+ "isDirectory": true,
14
+ "default": "$ROOT/APP_DATA/data"
15
+ },
16
+ "tempDir": {
17
+ "description": "Temporary directory for application data",
18
+ "type": "string",
19
+ "isDirectory": true,
20
+ "default": "$ROOT/APP_DATA/temp"
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,13 @@
1
+ # Customising the application
2
+ The Adapt authoring tool architecture has been designed from the ground up to support full customisation, be it in the form of adding extra self-contained pieces of functionality, or replacing/removing entire chunks of the core feature-set. It is also incredibly simple to add extra functionality that has been written by other developers.
3
+
4
+ ## Module security concerns
5
+ Before using any third-party code, please be aware that any modules you choose to install have the potential to cause catastrophic problems for your server. This could include (but is not limited to):
6
+ - Unexpectedly modifying database data
7
+ - Transmitting personal data to external parties
8
+ - Crashing the server
9
+ - Erasing of entire hard-disk contents
10
+
11
+ Most of these issues can be mitigated by making sure your server is correctly configured by an experienced system administrator (i.e. setting correct permissions etc.), but please be **VERY** careful when trusting third-party code.
12
+
13
+ #### If in doubt, leave it out!
@@ -0,0 +1,4 @@
1
+ # The data folder
2
+ The data folder is used to store persistant application data and **should not in any circumstances be modified or removed**. Doing so will result in data loss and generally cause unexpected runtime issues.
3
+
4
+ As a module developer, you should store any data in here which should persist between app restarts. You can make use of the `isDirectory` schema keyword to make configuration simpler for end-users. See the [schemas page](schemas-introduction#isdirectory) for more information.
@@ -0,0 +1,19 @@
1
+ # Welcome!
2
+
3
+ This is the home of the official API reference documentation for the Node.js back-end of the Adapt authoring tool (for the front-end docs, see [this page]()).
4
+
5
+ The Adapt authoring tool is a server-based user interface for authoring eLearning courses using the Adapt framework.
6
+
7
+ *This documentation is auto-generated using the tools packaged with the Adapt authoring tool [core repository](https://github.com/adaptlearning/adapt-authoring).*
8
+
9
+ ## Contributing
10
+ If you come across any errors or omissions in this documentation, please submit an issue on our [GitHub page](https://github.com/adaptlearning/adapt_authoring/issues).
11
+
12
+ If you also have time to fix the issue, please see our [contribution guide](https://github.com/adaptlearning/adapt_framework/wiki/Contributing-code) on how to submit a fix.
13
+
14
+ ## Useful links
15
+
16
+ - [Project website](https://www.adaptlearning.org/)
17
+ - [GitHub project](https://github.com/adapt-security/adapt-authoring)
18
+ - [Technical discussion forum](https://community.adaptlearning.org/mod/forum/view.php?id=4)
19
+ - [Gitter chatrooms](https://www.adaptlearning.org/)
@@ -0,0 +1,11 @@
1
+ ![](https://www.adaptlearning.org/wp-content/uploads/2015/11/home-icon-03.png)
2
+
3
+ # Adapt authoring tool
4
+
5
+ ## Developer guides
6
+
7
+ > Handy guides and how-to information to help understand and make use of the Adapt authoring tool APIs in a practical way.
8
+
9
+ [<i class="material-icons">download</i> Install](install)
10
+ [<i class="material-icons">settings</i> Configure](configuration)
11
+ [<i class="material-icons">flight_takeoff</i> Run](run)
@@ -0,0 +1,45 @@
1
+ import fs from 'fs-extra';
2
+ import { parse } from 'comment-parser';
3
+
4
+ export default class BinScripts {
5
+ async run() {
6
+ this.manualFile = 'binscripts.md';
7
+ this.replace = { CONTENT: await this.generateMd() }
8
+ }
9
+ async generateMd() {
10
+ const allDeps = await Promise.all(Object.values(this.app.dependencies).map(this.processDep));
11
+ return allDeps
12
+ .reduce((m, d) => d ? m.concat(d) : m, [])
13
+ .sort((a,b) => a.name.localeCompare(b.name))
14
+ .map(d => this.dataToMd(d))
15
+ .join('\n');
16
+ }
17
+ async processDep({ name, bin, rootDir }) {
18
+ if(!bin || typeof bin === 'string') {
19
+ return;
20
+ }
21
+ return await Promise.all(Object.entries(bin).map(async ([scriptName, filePath]) => {
22
+ const data = { name: scriptName, description: 'No description provided.', moduleName: name };
23
+ const contents = (await fs.readFile(`${rootDir}/${filePath}`)).toString();
24
+ const match = contents.match(/^#!\/usr\/bin\/env node(\s*)?\/\*\*([\s\S]+?)\*\//);
25
+ if(match) {
26
+ const [{ description, tags }] = parse(match[0]);
27
+ const params = tags.reduce((m,t) => {
28
+ if(t.tag === 'param') m.push({ name: t.name, description: t.description });
29
+ return m;
30
+ }, []);
31
+ data.description = description;
32
+ if(params.length) data.params = params;
33
+ }
34
+ return data;
35
+ }));
36
+ }
37
+ dataToMd({ name, description, moduleName, params }) {
38
+ let content = `<h2 class="script" id="${name}">${name} <span class="module">from ${moduleName}</span></h2>`
39
+ content += `<div class="details"><p class="description">${description}</p>`;
40
+ if(params) {
41
+ content += `<p><b>Params</b><ul>${params.reduce((s,p) => `${s}<li><code>${p.name}</code> ${p.description}</li>`, '')}</ul></p>`;
42
+ }
43
+ return content;
44
+ }
45
+ }
@@ -0,0 +1,33 @@
1
+ # Bin scripts
2
+ The authoring tool core bundle includes a number of useful scripts which make setting up and using the tool more straightforward. This page outlines these scripts and how they function, along with any parameters they may expect.
3
+
4
+ ## Running a bin script
5
+
6
+ To run a bin script, you must use the npx command which comes bundled with npm which and used to execute node modules. Scripts are run using the following format: **npx** followed by the **script name**, with any **flags or parameters** coming at the end.
7
+
8
+ As an example, a task called `at-myscript` may be run like so:
9
+
10
+ > We prefix any core authoring tool scripts `at-` for transparency (as an added bonus they also come towards the top of the `bin/` folder in `node_modules`!).
11
+
12
+ ```bash
13
+ npx at-myscript --test=true
14
+ ```
15
+
16
+ See the [official npx docs](https://docs.npmjs.com/cli/v7/commands/npx) for more information on npx.
17
+
18
+ {{{CONTENT}}}
19
+
20
+ <style>
21
+ h2.script {
22
+ margin-bottom: 5px;
23
+ }
24
+ h2.script .module {
25
+ font-weight: 300;
26
+ font-size: 16px;
27
+ vertical-align: middle;
28
+ }
29
+ p.description,
30
+ .details ul {
31
+ margin: 0;
32
+ }
33
+ </style>
@@ -0,0 +1,15 @@
1
+ export default class CoreModules {
2
+ async run() {
3
+ this.manualFile = 'coremodules.md';
4
+ this.replace = {
5
+ VERSION: this.app.pkg.version,
6
+ MODULES: this.generateMd()
7
+ };
8
+ }
9
+ generateMd() {
10
+ return Object.keys(this.app.dependencies).sort().reduce((s, name) => {
11
+ const { version, description, homepage } = this.app.dependencies[name];
12
+ return s += `\n| ${homepage ? `[${name}](${homepage})` : name} | ${version} | ${description} |`;
13
+ }, '| Name | Version | Description |\n| - | :-: | - |');
14
+ }
15
+ }
@@ -0,0 +1,4 @@
1
+ # Core module list
2
+ The following modules are included in Adapt authoring v{{{VERSION}}} core package of modules, and are supported by the core dev team.
3
+
4
+ {{{MODULES}}}
@@ -0,0 +1,119 @@
1
+ import fetch from 'node-fetch'
2
+ import fs from 'fs/promises'
3
+ import { glob } from 'glob'
4
+ import path from 'path'
5
+
6
+ export default class Licensing {
7
+ async run () {
8
+ this.manualFile = 'licensing.md'
9
+ this.licenses = {}
10
+ this.dependencies = []
11
+
12
+ await this.loadDependencies()
13
+
14
+ const adaptLicense = this.licenses[JSON.parse((await fs.readFile(path.resolve(this.config.app.rootDir, 'package.json'))).toString()).license]
15
+
16
+ this.replace = {
17
+ ADAPT_LICENSE: adaptLicense.name,
18
+ ADAPT_LICENSE_TEXT: adaptLicense.description,
19
+ ADAPT_LICENSE_PERMISSIONS: adaptLicense.permissions.map(p => `- ${this.permissionsMap(p)}`).join('\n'),
20
+ LICENSES: await this.generateLicenseSummaryMd(),
21
+ LICENSE_DETAILS: await this.generateLicenseDetailsMd(),
22
+ MODULES: await this.generateMd(),
23
+ MODULE_COUNT: this.dependencies.length,
24
+ UNKNOWN_LICENSES: this.generateUnknownLicenseMd()
25
+ }
26
+ }
27
+
28
+ async loadDependencies () {
29
+ const files = await glob('node_modules/*/package.json')
30
+ await Promise.all(files.map(async f => {
31
+ const packageName = path.dirname(f).replace('node_modules/', '')
32
+ if (packageName.startsWith('adapt-authoring')) {
33
+ return
34
+ }
35
+ const pkg = JSON.parse((await fs.readFile(f)).toString())
36
+ this.dependencies.push(pkg)
37
+ await this.storeLicenseData(pkg)
38
+ }))
39
+ }
40
+
41
+ async storeLicenseData (pkg) {
42
+ if (!pkg.license) {
43
+ return
44
+ }
45
+ if (typeof pkg.license === 'object') {
46
+ pkg.license = pkg.license.type
47
+ }
48
+ const licenses = pkg.license.replace('(', '').replace(')', '').split(/\s(?:AND|OR)\s/)
49
+ for (let l of licenses) {
50
+ l = this.licenseNameMap(l)
51
+ if (this.licenses[l]) {
52
+ return this.licenses[l].count++
53
+ }
54
+ this.licenses[l] = { count: 1 }
55
+ try {
56
+ const { GITHUB_USER, GITHUB_TOKEN } = process.env
57
+ const res = await fetch(`https://api.github.com/licenses/${l.toLowerCase()}`, { headers: { Authorization: `Basic ${Buffer.from(`${GITHUB_USER}:${GITHUB_TOKEN}`).toString('base64')}` } })
58
+ if (res.status === 200) Object.assign(this.licenses[l], await res.json())
59
+ if (res.status > 299) console.error(`Failed to fetch '${l}' license: (${res.status}) ${(await res.json()).message}`)
60
+ } catch (e) {
61
+ console.error(e)
62
+ }
63
+ }
64
+ }
65
+
66
+ licenseNameMap (name) {
67
+ switch (name) {
68
+ case 'Apache2':
69
+ return 'Apache-2.0'
70
+ case 'GPL-3.0-or-later':
71
+ return 'GPL-3.0'
72
+ default:
73
+ return name
74
+ }
75
+ }
76
+
77
+ permissionsMap (p) {
78
+ return `${p[0].toUpperCase()}${p.slice(1).replaceAll('-', ' ')}`
79
+ }
80
+
81
+ async generateLicenseSummaryMd () {
82
+ let md = '| License | Modules using license |\n| - | :-: |\n'
83
+
84
+ Object.keys(this.licenses)
85
+ .sort()
86
+ .forEach(l => md += `| ${l} | ${this.licenses[l].count} |\n`)
87
+
88
+ return md
89
+ }
90
+
91
+ async generateLicenseDetailsMd () {
92
+ let md = ''
93
+ Object.entries(this.licenses).forEach(([key, { name, spdx_id, description, body, permissions }]) => {
94
+ if (!name) return
95
+ md += '<details>\n'
96
+ md += `<summary>${name} (${spdx_id})</summary>\n`
97
+ md += `<p>${description}</p>\n`
98
+ md += `<p>This license allows the following:\n<ul>${permissions.map(p => `<li>${this.permissionsMap(p)}</li>`).join('\n')}</ul></p>\n`
99
+ md += '<p>The original license text is as follows:</p>\n'
100
+ md += `<pre>${body}</pre>\n`
101
+ md += '</details>\n\n'
102
+ })
103
+ return md
104
+ }
105
+
106
+ generateUnknownLicenseMd () {
107
+ const unknowns = []
108
+ Object.entries(this.licenses).forEach(([key, { name }]) => !name && unknowns.push(key))
109
+ if (unknowns.length) {
110
+ return `No information is held on the following licenses, please do your own research to dermine their suitability.\n\n${unknowns.map(u => `- ${u}`).join('\n')}\n`
111
+ }
112
+ }
113
+
114
+ async generateMd () {
115
+ let md = '<tr><th>Name</th><th>Version</th><th>License</th><th>Description</th></tr>\n'
116
+ this.dependencies.forEach(pkg => 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`)
117
+ return `<details>\n<summary>Module dependency list</summary>\n<table>${md}</table>\n</details>`
118
+ }
119
+ }
@@ -0,0 +1,36 @@
1
+ # Licensing
2
+ When building a business around an open-source product, it is crucially important to understand how that code is licensed, and how those licenses apply to your business. This page aims to clarify which licenses apply to the Adapt authoring tool core package, and gives details on how those licenses may affect its use. **This page is not intended to provide legal advice; qualified legal professionals should be consulted to advise on how your own business may be affected.**
3
+
4
+ The Adapt authoring tool core package is licensed under the **{{{ADAPT_LICENSE}}}**, which is summarised as follows:
5
+
6
+ _{{{ADAPT_LICENSE_TEXT}}}_
7
+
8
+ The {{{ADAPT_LICENSE}}} allows the following:
9
+
10
+ {{{ADAPT_LICENSE_PERMISSIONS}}}
11
+
12
+ You can view more information on the {{{ADAPT_LICENSE}}} license in [License details](#license-details).
13
+
14
+ ## Third-party dependencies
15
+
16
+ The Adapt authoring tool makes use of {{{MODULE_COUNT}}} third-party Node.js modules. These include transient dependencies (i.e. dependencies not directly imported by the authoring tool code, but used by its dependencies). Each module has its own license which must be taken into consideration when building a business around Adapt products.
17
+
18
+ The below table lists all licenses used, as well as the number of dependencies which use each license.
19
+
20
+ {{{LICENSES}}}
21
+
22
+ ## License details
23
+
24
+ Listed below are all licenses used by the Adapt authoring tool and its dependencies. Click each heading to view detailed information, including the full licenses themselves.
25
+
26
+ {{{LICENSE_DETAILS}}}
27
+
28
+ {{{UNKNOWN_LICENSES}}}
29
+
30
+ ### Full dependency list
31
+
32
+ Click the heading below to view a complete list of all third-party dependencies.
33
+
34
+ {{{MODULES}}}
35
+
36
+ ## Commonly asked questions
@@ -0,0 +1,12 @@
1
+ # The temp folder
2
+ The `temp` folder (note: this path will vary depending on your local configuration) is, as the name suggests, a temporary store for files used at runtime by the application. These files can be related to any number of things such as file uploads, course builds, documentation builds and so on.
3
+
4
+ ## Using the temp folder
5
+ As a module developer, it is recommended that you store any temporary files needed by your module in here. Please be aware however, that due to its non-permanent nature, any data stored in the temp folder has the potential to be removed at any time. We therefore recommend running relevant checks during the startup of your module, and reinitialise any missing files at that point.
6
+
7
+ It is safe to assume that the temp folder will *not* be removed while the app is running; anyone choosing to do so should expect fatal errors.
8
+
9
+ ## Removing the temp folder
10
+ It is perfectly safe to remove the temp folder. You may wish to do this in the event of low disk space, before an update, or even as a regular housekeeping task.
11
+
12
+ > If you do remove the temp folder, this must be done while the app is stopped, or your users may encounter errors while using the app. Restarting the application will ensure that any vital files are reinstated.