adapt-authoring-docs 1.3.0 → 1.3.2

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.
@@ -25,7 +25,7 @@ jobs:
25
25
  - name: Update npm
26
26
  run: npm install -g npm@latest
27
27
  - name: Install dependencies
28
- run: npm ci
28
+ run: npm install
29
29
  - name: Release
30
30
  env:
31
31
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -8,6 +8,5 @@ jobs:
8
8
  - uses: actions/setup-node@master
9
9
  with:
10
10
  node-version: 'lts/*'
11
- cache: 'npm'
12
- - run: npm ci
11
+ - run: npm install
13
12
  - run: npx standard
@@ -10,6 +10,5 @@ jobs:
10
10
  - uses: actions/setup-node@v4
11
11
  with:
12
12
  node-version: 'lts/*'
13
- cache: 'npm'
14
- - run: npm ci
13
+ - run: npm install
15
14
  - run: npm test
@@ -0,0 +1,175 @@
1
+ # Adapt Authoring Tool — Architecture
2
+
3
+ ## System Architecture
4
+
5
+ ```mermaid
6
+ flowchart TB
7
+ subgraph Client["Client Layer"]
8
+ UI["Backbone.js UI · 18 pluggable modules · Rollup · Babel · Handlebars · LESS"]
9
+ end
10
+
11
+ subgraph Server["Server & API Layer"]
12
+ direction LR
13
+ express["Express.js 5.1 · Helmet · Compression · Body Parser · Rate Limiter"]
14
+ apiCore["REST API · JSON Schema Validation (AJV)"]
15
+ corefw["Core Framework · App Singleton · AbstractModule · DependencyLoader · Hook System"]
16
+ express -- "routes" --> apiCore -- "loads" --> corefw
17
+ end
18
+
19
+ subgraph Services["Service Modules"]
20
+ direction LR
21
+ subgraph AuthGroup["Authentication & Authorization"]
22
+ direction TB
23
+ auth["Auth"]
24
+ authLocal["Auth Local (bcrypt)"]
25
+ jwt["JWT Tokens"]
26
+ sessions["Sessions"]
27
+ roles["Roles (RBAC)"]
28
+ users["Users"]
29
+ usergroups["User Groups"]
30
+ auth ~~~ authLocal ~~~ jwt ~~~ sessions ~~~ roles ~~~ users ~~~ usergroups
31
+ end
32
+ subgraph ContentGroup["Content & Authoring"]
33
+ direction TB
34
+ content["Content"]
35
+ authored["Authored"]
36
+ tags["Tags"]
37
+ assets["Assets"]
38
+ courseAssets["Course Assets"]
39
+ courseTheme["Course Theme"]
40
+ defaultPlugins["Default Plugins"]
41
+ adaptFW["Adapt Framework"]
42
+ content ~~~ authored ~~~ tags ~~~ assets ~~~ courseAssets ~~~ courseTheme ~~~ defaultPlugins ~~~ adaptFW
43
+ end
44
+ subgraph SupportGroup["Support Services"]
45
+ direction TB
46
+ config["Config"]
47
+ logger["Logger"]
48
+ mongoLogger["MongoDB Logger"]
49
+ lang["Lang (i18n)"]
50
+ langpack["Language Pack (EN)"]
51
+ mailer["Mailer"]
52
+ collab["Collab (WebSocket)"]
53
+ errors["Errors"]
54
+ config ~~~ logger ~~~ mongoLogger ~~~ lang ~~~ langpack ~~~ mailer ~~~ collab ~~~ errors
55
+ end
56
+ end
57
+
58
+ subgraph Data["Data Layer"]
59
+ direction LR
60
+ mongodb[("MongoDB 7.0")]
61
+ sessionStore[("Session Store")]
62
+ logStore[("Log Store")]
63
+ end
64
+
65
+ Client -- "HTTP / REST" --> Server
66
+ Server -- "validates & dispatches" --> Services
67
+ Services -- "persists" --> Data
68
+
69
+ classDef clientStyle fill:#4A90D9,stroke:#2C5F8A,color:#fff
70
+ classDef serverStyle fill:#5BAE5B,stroke:#3A7A3A,color:#fff
71
+ classDef serviceStyle fill:#E67E22,stroke:#BA6518,color:#fff
72
+ classDef dataStyle fill:#3498DB,stroke:#2471A3,color:#fff
73
+
74
+ class Client clientStyle
75
+ class Server serverStyle
76
+ class Services serviceStyle
77
+ class Data dataStyle
78
+ ```
79
+
80
+ ## Module Dependency Hierarchy
81
+
82
+ ```mermaid
83
+ flowchart TD
84
+ core["core\n(App, AbstractModule,\nDependencyLoader, Hook)"]
85
+
86
+ core --> config
87
+ core --> logger
88
+ core --> errors
89
+ core --> server["server\n(Express.js)"]
90
+ core --> mongodb["mongodb\n(Native Driver)"]
91
+
92
+ server --> middleware["middleware\n(helmet, compression,\nbody-parser, rate-limiter)"]
93
+
94
+ core --> jsonschema["jsonschema\n(AJV)"]
95
+ core --> api["api\n(Abstract REST API)"]
96
+
97
+ api --> auth
98
+ api --> jsonschema
99
+ api --> mongodb
100
+
101
+ auth --> authLocal["auth-local\n(bcrypt)"]
102
+ auth --> sessions["sessions\n(connect-mongo)"]
103
+ auth --> roles
104
+ auth --> users
105
+ users --> usergroups
106
+
107
+ core --> lang
108
+ lang --> langpack["langpack-en"]
109
+
110
+ core --> content
111
+ content --> authored
112
+ content --> tags
113
+ content --> assets
114
+ content --> courseAssets["courseassets\n(FFmpeg)"]
115
+ content --> courseTheme["coursetheme"]
116
+ content --> defaultPlugins["defaultplugins"]
117
+
118
+ core --> adaptframework["adaptframework\n(adapt-cli)"]
119
+ adaptframework --> contentPlugin["contentplugin"]
120
+ adaptframework --> spoor["spoortracking\n(SCORM)"]
121
+ adaptframework --> browserslist
122
+ adaptframework --> zipper["_zipper\n(JSZip)"]
123
+
124
+ core --> mailer["mailer\n(Nodemailer)"]
125
+ core --> collab["collab\n(WebSocket)"]
126
+
127
+ logger --> mongodblogger["mongodblogger"]
128
+ mongodblogger --> mongodb
129
+
130
+ sessions --> mongodb
131
+
132
+ classDef coreNode fill:#9B59B6,stroke:#6C3483,color:#fff
133
+ classDef infraNode fill:#5BAE5B,stroke:#3A7A3A,color:#fff
134
+ classDef apiNode fill:#D4A843,stroke:#A07D2E,color:#fff
135
+ classDef authNode fill:#E74C3C,stroke:#B03A2E,color:#fff
136
+ classDef contentNode fill:#E67E22,stroke:#BA6518,color:#fff
137
+ classDef adaptNode fill:#3498DB,stroke:#2471A3,color:#fff
138
+ classDef supportNode fill:#1ABC9C,stroke:#148F77,color:#fff
139
+
140
+ class core coreNode
141
+ class config,logger,errors,server,middleware,mongodb infraNode
142
+ class api,jsonschema apiNode
143
+ class auth,authLocal,sessions,roles,users,usergroups authNode
144
+ class content,authored,tags,assets,courseAssets,courseTheme,defaultPlugins contentNode
145
+ class adaptframework,contentPlugin,spoor,browserslist,zipper adaptNode
146
+ class lang,langpack,mailer,collab,mongodblogger supportNode
147
+ ```
148
+
149
+ ## Technology Stack
150
+
151
+ | Layer | Technologies |
152
+ |---|---|
153
+ | **Runtime** | Node.js 24, ES Modules |
154
+ | **Frontend** | Backbone.js, jQuery, Underscore, Handlebars, LESS |
155
+ | **Frontend Build** | Rollup, Babel 7 |
156
+ | **Backend** | Express.js 5.1, custom module system |
157
+ | **Database** | MongoDB 7.0 (native driver) |
158
+ | **Auth** | bcryptjs, JWT, express-session, connect-mongo, RBAC |
159
+ | **Validation** | AJV (JSON Schema) |
160
+ | **Security** | Helmet, rate-limiter-flexible |
161
+ | **Media** | FFmpeg, FFprobe |
162
+ | **Email** | Nodemailer |
163
+ | **Real-time** | WebSocket (ws) |
164
+ | **i18n** | Custom lang module + language packs |
165
+ | **Logging** | Chalk (CLI), MongoDB (persistent) |
166
+ | **Packaging** | JSZip, adapt-cli |
167
+
168
+ ## Key Architectural Patterns
169
+
170
+ - **Plugin-based modularity** — Every feature is a separate npm package extending `AbstractModule` from `core`
171
+ - **Singleton App** — `App.instance` bootstraps and manages all modules via `DependencyLoader`
172
+ - **Hook system** — Lifecycle hooks for module initialization, ready states, and extensibility
173
+ - **RBAC** — Role-based access control with scoped permissions per API route
174
+ - **Event-driven UI** — `Origin` singleton (Backbone.Events) acts as a global event bus in the frontend
175
+ - **Schema-validated APIs** — All REST endpoints validated against JSON schemas using AJV
@@ -23,7 +23,7 @@ function generateSectionTitle (sectionName) {
23
23
  export default async function docsify (app, configs, outputdir, defaultPages) {
24
24
  const dir = path.resolve(outputdir, 'manual')
25
25
  const sectionsConf = app.config.get('adapt-authoring-docs.manualSections')
26
- const defaultSection = Object.entries(sectionsConf).reduce((m, [id, data]) => data.default ? id : m)
26
+ const defaultSection = Object.entries(sectionsConf).find(([, data]) => data.default)?.[0]
27
27
  /**
28
28
  * init docsify folder
29
29
  */
@@ -0,0 +1,57 @@
1
+ {
2
+ "source": {
3
+ "include": []
4
+ },
5
+ "docdash": {
6
+ "collapse": true,
7
+ "typedefs": true,
8
+ "search": true,
9
+ "static": true,
10
+ "menu": {
11
+ "<img class=\"logo\" src=\"assets/logo-outline-colour.png\" />Adapt authoring tool back-end API documentation<br><span class=\"version\">v2.5.0</span>": {
12
+ "class": "menu-title"
13
+ },
14
+ "Documentation home": {
15
+ "href": "https://adapt-security.github.io/adapt-authoring-documentation/",
16
+ "target": "_self",
17
+ "class": "menu-item",
18
+ "id": "home_link"
19
+ },
20
+ "Project Website": {
21
+ "href": "https://www.adaptlearning.org/",
22
+ "target": "_blank",
23
+ "class": "menu-item",
24
+ "id": "website_link"
25
+ },
26
+ "Technical Discussion Forum": {
27
+ "href": "https://community.adaptlearning.org/mod/forum/view.php?id=4",
28
+ "target": "_blank",
29
+ "class": "menu-item",
30
+ "id": "forum_link"
31
+ }
32
+ },
33
+ "sectionOrder": [
34
+ "Namespaces",
35
+ "Classes",
36
+ "Modules",
37
+ "Externals",
38
+ "Events",
39
+ "Mixins",
40
+ "Tutorials",
41
+ "Interfaces"
42
+ ],
43
+ "meta": {
44
+ "title": "Adapt authoring tool UI documentation",
45
+ "description": "Adapt authoring tool UI documentation",
46
+ "keyword": "v2.5.0"
47
+ },
48
+ "scripts": [
49
+ "styles/adapt.css",
50
+ "scripts/adapt.js"
51
+ ]
52
+ },
53
+ "opts": {
54
+ "destination": "/var/folders/28/8f7zyfj927z96jtjw_v0j9x80000gn/T/jsdoc-test-lPjKMQ/backend",
55
+ "template": "node_modules/docdash"
56
+ }
57
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adapt-authoring-docs",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Tools for auto-generating documentation for the Adapt authoring tool",
5
5
  "homepage": "https://github.com/adapt-security/adapt-authoring-docs",
6
6
  "license": "GPL-3.0",
@@ -205,18 +205,7 @@ describe('docsify', () => {
205
205
  })
206
206
 
207
207
  describe('bugs', () => {
208
- it('TODO: defaultSection reduce with single entry returns array tuple instead of string', async () => {
209
- // BUG: In docsify.js line 26, Object.entries(sectionsConf).reduce((m, [id, data]) => ...)
210
- // has no initial value. When there is only one section entry, reduce() returns
211
- // the entry itself (an [id, data] array) without calling the callback.
212
- // This causes generateSectionTitle to fail with:
213
- // TypeError: sectionName.slice(...).replaceAll is not a function
214
- // because sectionName is an array, not a string.
215
- //
216
- // To fix: add an initial value to reduce, e.g.:
217
- // Object.entries(sectionsConf).reduce((m, [id, data]) => data.default ? id : m, undefined)
218
- // or use Array.find instead:
219
- // Object.entries(sectionsConf).find(([, data]) => data.default)?.[0]
208
+ it('defaultSection reduce with single entry returns string section name', async () => {
220
209
  tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'docsify-test-'))
221
210
  const outputDir = tmpDir
222
211
  const docsSrcDir = await fs.mkdtemp(path.join(os.tmpdir(), 'docsify-src-'))
@@ -238,10 +227,8 @@ describe('docsify', () => {
238
227
  }]
239
228
 
240
229
  const { default: docsify } = await import('../docsify/docsify.js')
241
- // This should work but fails due to the bug described above
242
- await assert.rejects(
243
- () => docsify(mockApp, configs, outputDir, {}),
244
- TypeError
230
+ await assert.doesNotReject(
231
+ () => docsify(mockApp, configs, outputDir, {})
245
232
  )
246
233
 
247
234
  await fs.rm(docsSrcDir, { recursive: true, force: true })