adapt-authoring-core 2.5.0 → 3.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.
@@ -0,0 +1,649 @@
1
+ # Developer workflow
2
+
3
+ This guide covers day-to-day development workflows for the Adapt authoring tool, with a focus on managing parallel streams of work across the multi-repo architecture.
4
+
5
+ ## Quick navigation
6
+
7
+ - [How the project is structured](#how-the-project-is-structured)
8
+ - [Local development environment](#local-development-environment)
9
+ - [Workflow 1: Single-module bug fix](#workflow-1-single-module-bug-fix)
10
+ - [Workflow 2: Multi-module feature](#workflow-2-multi-module-feature)
11
+ - [Workflow 3: Hotfix during feature work](#workflow-3-hotfix-during-feature-work)
12
+ - [Workflow 4: Patching an older release line](#workflow-4-patching-an-older-release-line)
13
+ - [Coordinating releases](#coordinating-releases)
14
+ - [Version pinning strategy](#version-pinning-strategy)
15
+ - [Common pitfalls](#common-pitfalls)
16
+
17
+ ## How the project is structured
18
+
19
+ Understanding the release pipeline is essential to choosing the right workflow.
20
+
21
+ ```
22
+ ┌─────────────────────────────────────────────────────────┐
23
+ │ adapt-authoring (parent) │
24
+ │ ├── Depends on 43+ adapt-authoring-* modules │
25
+ │ ├── Released manually via workflow_dispatch │
26
+ │ └── Runs integration tests across all modules │
27
+ │ │
28
+ │ Each module (api/, core/, auth/, server/, etc.) │
29
+ │ ├── Is a separate git repository │
30
+ │ ├── Has its own CI (linting, tests, releases) │
31
+ │ ├── Releases automatically on merge to master │
32
+ │ └── Published to npm or GitHub Packages │
33
+ └─────────────────────────────────────────────────────────┘
34
+ ```
35
+
36
+ **Key implication:** Merging a PR to a module's `master` branch triggers an immediate release via semantic-release. There is no staging step between merge and publish. This makes merge timing critical when coordinating multi-module changes.
37
+
38
+ ## Local development environment
39
+
40
+ ### Directory layout
41
+
42
+ The recommended local setup keeps all repos in a single parent directory:
43
+
44
+ ```
45
+ AAT/
46
+ ├── adapt-authoring/ # Parent application (npm workspaces)
47
+ ├── api/ # adapt-authoring-api (own git repo)
48
+ ├── auth/ # adapt-authoring-auth (own git repo)
49
+ ├── core/ # adapt-authoring-core (own git repo)
50
+ ├── mongodb/ # adapt-authoring-mongodb (own git repo)
51
+ ├── server/ # adapt-authoring-server (own git repo)
52
+ ├── ... # 40+ more module repos
53
+ └── adapt-authoring/
54
+ └── local_adapt_modules/ # Symlinks or clones used by workspaces
55
+ ```
56
+
57
+ ### How local testing works
58
+
59
+ The parent `adapt-authoring/` uses npm workspaces pointed at `local_adapt_modules/*`. When a module is present in that directory, npm resolves it locally instead of from the registry. This means you can test changes to any module without publishing first.
60
+
61
+ ```bash
62
+ # Link a module for local development
63
+ cd adapt-authoring/local_adapt_modules
64
+ ln -s ../../api adapt-authoring-api
65
+
66
+ # Reinstall to pick up the local link
67
+ cd ..
68
+ npm install --legacy-peer-deps
69
+ ```
70
+
71
+ ### Running the application locally
72
+
73
+ ```bash
74
+ cd adapt-authoring
75
+ npm start # Production mode
76
+ npm run debug # With --inspect flag for debugger
77
+ ```
78
+
79
+ ### Running tests
80
+
81
+ ```bash
82
+ # Integration tests (from parent — boots app + MongoDB)
83
+ cd adapt-authoring
84
+ npm test
85
+
86
+ # Unit tests (from a specific module)
87
+ cd api
88
+ npm test # Runs: node --test tests/**/*.spec.js
89
+
90
+ # Linting (from any module)
91
+ npx standard
92
+ ```
93
+
94
+ ## Workflow 1: Single-module bug fix
95
+
96
+ This is the most common workflow. A bug exists in one module and needs to be fixed and released.
97
+
98
+ ### Steps
99
+
100
+ ```bash
101
+ # 1. Start from a clean master
102
+ cd api
103
+ git checkout master && git pull origin master
104
+
105
+ # 2. Create a branch
106
+ git checkout -b issue/1234
107
+
108
+ # 3. Make changes, lint, and test
109
+ # ... edit files ...
110
+ npx standard
111
+ npm test
112
+
113
+ # 4. Commit with the correct prefix
114
+ git commit -m "Fix: Prevent crash when uploading empty file (fixes #1234)"
115
+
116
+ # 5. Push and create PR
117
+ git push -u origin issue/1234
118
+ gh pr create --title "Fix: Prevent crash when uploading empty file" \
119
+ --body "### Fixes #1234
120
+
121
+ ### Fix
122
+ * Prevent crash when req.file is undefined on upload endpoint
123
+
124
+ ### Testing
125
+ 1. Upload an empty file via the UI
126
+ 2. Verify no 500 error"
127
+ ```
128
+
129
+ ### What happens after merge
130
+
131
+ 1. GitHub Actions runs semantic-release on the module
132
+ 2. A new patch version is published (e.g. `3.3.0` → `3.3.1`)
133
+ 3. The parent `adapt-authoring` repo still pins the old exact version — **the fix does not reach production until you explicitly bump it**
134
+ 4. A main repo release (manual) picks up the new version when you're ready
135
+
136
+ This is by design. The parent uses [exact version pinning](#version-pinning-strategy), so no module update reaches production until a developer deliberately updates `package.json`.
137
+
138
+ ### Getting the fix to production
139
+
140
+ Update the pinned version in the parent to the newly released patch:
141
+
142
+ ```bash
143
+ cd adapt-authoring
144
+ git checkout master && git pull origin master
145
+
146
+ # Update the dependency to the specific patch version
147
+ npm install adapt-authoring-api@3.3.1 --save-exact --legacy-peer-deps
148
+
149
+ # Commit the dependency bump
150
+ git add package.json package-lock.json
151
+ git commit -m "Upgrade: Bump adapt-authoring-api to v3.3.1 (refs #1234)"
152
+ git push origin master
153
+
154
+ # Trigger the release workflow from GitHub Actions UI
155
+ # or via CLI:
156
+ gh workflow run release.yml
157
+ ```
158
+
159
+ Because versions are pinned exactly, this bump includes *only* the bugfix — no unrelated features are pulled in.
160
+
161
+ ## Workflow 2: Multi-module feature
162
+
163
+ A new feature spans multiple modules — for example, adding batch export support might touch `content`, `assets`, `api`, and `ui`.
164
+
165
+ ### Phase 1: Branch all affected modules
166
+
167
+ ```bash
168
+ # Create feature branches in each affected module
169
+ for module in content assets api ui; do
170
+ cd /path/to/AAT/$module
171
+ git checkout master && git pull origin master
172
+ git checkout -b feature/batch-export
173
+ done
174
+ ```
175
+
176
+ Use a consistent branch name across all modules — this makes it obvious which branches belong together.
177
+
178
+ ### Phase 2: Develop and test locally
179
+
180
+ Work across the modules as needed. The local workspace setup means all your changes are picked up without publishing:
181
+
182
+ ```bash
183
+ # Run the full application with all your local changes
184
+ cd adapt-authoring
185
+ npm start
186
+
187
+ # Run integration tests against your combined changes
188
+ npm test
189
+ ```
190
+
191
+ **Important:** Regularly test your feature branches against `master` of all other modules. This catches integration issues early and prevents surprises at merge time.
192
+
193
+ ### Phase 3: Create PRs — but do not merge yet
194
+
195
+ Create a PR in each affected module. Use the PR description to cross-reference the related PRs:
196
+
197
+ ```bash
198
+ cd content
199
+ git push -u origin feature/batch-export
200
+ gh pr create --title "New: Add batch export support" \
201
+ --body "### Fixes #42
202
+
203
+ Part of the batch export feature. Related PRs:
204
+ - <org>/<module-assets-repo>#15
205
+ - <org>/<module-api-repo>#28
206
+ - <org>/<module-ui-repo>#33
207
+
208
+ ### New
209
+ * Add batch selection to content schema
210
+
211
+ ### Testing
212
+ 1. Select multiple items and trigger export
213
+ 2. Verify export completes with all items"
214
+ ```
215
+
216
+ ### Phase 4: Review and approve all PRs
217
+
218
+ Get all PRs reviewed and approved, but **do not merge them individually**. Merging one module triggers a release of that module, and the feature may not work without the other modules being updated simultaneously.
219
+
220
+ ### Phase 5: Merge in dependency order
221
+
222
+ Once all PRs are approved and CI is green, merge them in dependency order — modules that others depend on should be merged first:
223
+
224
+ ```
225
+ 1. core (if changed) — foundational, no module deps
226
+ 2. api — depends on core
227
+ 3. assets — depends on api
228
+ 4. content — depends on assets, api
229
+ 5. ui — depends on api
230
+ ```
231
+
232
+ Wait for each module's release workflow to complete before merging the next, so that downstream modules can resolve the new version as a peer dependency.
233
+
234
+ ```bash
235
+ # Check that the release completed
236
+ gh run list --repo <org>/adapt-authoring-api --limit 3
237
+ ```
238
+
239
+ ### Phase 6: Update and release the parent
240
+
241
+ Update the parent to pin the exact new versions of each changed module:
242
+
243
+ ```bash
244
+ cd adapt-authoring
245
+ git checkout master && git pull origin master
246
+
247
+ # Update all changed dependencies to their exact new versions
248
+ npm install adapt-authoring-api@3.5.0 \
249
+ adapt-authoring-assets@1.6.0 \
250
+ adapt-authoring-content@1.1.0 \
251
+ adapt-authoring-ui@2.1.0 \
252
+ --save-exact --legacy-peer-deps
253
+
254
+ # Run integration tests
255
+ npm test
256
+
257
+ # Commit and push
258
+ git add package.json package-lock.json
259
+ git commit -m "New: Add batch export support (fixes #100)"
260
+ git push origin master
261
+
262
+ # Trigger release
263
+ gh workflow run release.yml
264
+ ```
265
+
266
+ ## Workflow 3: Hotfix during feature work
267
+
268
+ You're midway through a multi-module feature when a critical bug is reported in production. Here's how to handle it without disrupting your feature work.
269
+
270
+ ### The situation
271
+
272
+ ```
273
+ You are working on:
274
+ content → branch: feature/batch-export
275
+ assets → branch: feature/batch-export
276
+ api → branch: feature/batch-export
277
+
278
+ Bug reported in: api (unrelated to your feature)
279
+ ```
280
+
281
+ ### Step 1: Fix the bug on a separate branch
282
+
283
+ The multi-repo structure helps here — the bug is in one module and your feature branches are unaffected:
284
+
285
+ ```bash
286
+ cd api
287
+
288
+ # Stash or commit any in-progress feature work
289
+ git stash # or commit to the feature branch
290
+
291
+ # Create a hotfix branch from master
292
+ git checkout master && git pull origin master
293
+ git checkout -b issue/5678
294
+
295
+ # Fix the bug
296
+ # ... edit files ...
297
+ npx standard
298
+ npm test
299
+
300
+ # Commit and PR
301
+ git commit -m "Fix: Correct pagination offset in list endpoint (fixes #5678)"
302
+ git push -u origin issue/5678
303
+ gh pr create --title "Fix: Correct pagination offset in list endpoint" \
304
+ --body "### Fixes #5678
305
+
306
+ ### Fix
307
+ * Off-by-one error in pagination calculation
308
+
309
+ ### Testing
310
+ 1. Request page 2 of any list endpoint
311
+ 2. Verify correct items are returned"
312
+ ```
313
+
314
+ ### Step 2: Get the fix merged and released
315
+
316
+ Follow the normal review process. Once merged, semantic-release publishes the patch.
317
+
318
+ ### Step 3: Push the fix to production
319
+
320
+ Because versions are pinned exactly, you can bump *only* the patched module — no unreleased features from other modules are pulled in:
321
+
322
+ ```bash
323
+ cd adapt-authoring
324
+ git checkout master && git pull origin master
325
+ npm install adapt-authoring-api@3.3.1 --save-exact --legacy-peer-deps
326
+ git add package.json package-lock.json
327
+ git commit -m "Upgrade: Bump adapt-authoring-api to v3.3.1 (fixes #5678)"
328
+ git push origin master
329
+ gh workflow run release.yml
330
+ ```
331
+
332
+ ### Step 4: Rebase your feature branch
333
+
334
+ Back on your feature work, rebase to pick up the hotfix (especially important if your feature touches the same module):
335
+
336
+ ```bash
337
+ cd api
338
+ git checkout feature/batch-export
339
+ git rebase master
340
+
341
+ # If you stashed earlier
342
+ git stash pop
343
+ ```
344
+
345
+ If there are no conflicts, you're done. If there are conflicts, resolve them — the fix is now part of your feature branch's history.
346
+
347
+ ### Step 5: Test the feature against the updated master
348
+
349
+ ```bash
350
+ cd adapt-authoring
351
+ npm test
352
+ ```
353
+
354
+ This ensures your feature still works with the hotfix in place.
355
+
356
+ ## Workflow 4: Patching an older release line
357
+
358
+ A feature has been developed and released as a new minor version (`v1.1.0`), but production is still pinned to `v1.0.0`. A bug is now found that needs fixing in the `v1.0.x` line *without* including the `v1.1.0` changes. The fix also needs to be in `v1.1.x` going forward.
359
+
360
+ **This requires two releases:** a patch on the old line (`v1.0.1`) and a patch on the current line (`v1.1.1`).
361
+
362
+ ### Prerequisites: maintenance branch support
363
+
364
+ Modules need semantic-release configured to support maintenance branches. This is a one-time setup per module — see [Configuring maintenance branch support](#configuring-maintenance-branch-support) below.
365
+
366
+ ### Step 1: Create the maintenance branch
367
+
368
+ Branch from the tag of the version you need to patch:
369
+
370
+ ```bash
371
+ cd my-module
372
+ git fetch --tags
373
+ git checkout -b 1.0.x v1.0.0
374
+ ```
375
+
376
+ The branch name **must** match the pattern configured in semantic-release (e.g. `1.0.x`, `1.1.x`). This tells semantic-release to release within that version range.
377
+
378
+ ### Step 2: Fix the bug on the maintenance branch
379
+
380
+ ```bash
381
+ git checkout -b issue/5678 1.0.x
382
+
383
+ # Make the fix
384
+ npx standard
385
+ npm test
386
+
387
+ git commit -m "Fix: Handle null values in export (fixes #5678)"
388
+ git push -u origin issue/5678
389
+
390
+ # PR targets the 1.0.x branch, NOT master
391
+ gh pr create --base 1.0.x \
392
+ --title "Fix: Handle null values in export" \
393
+ --body "### Fixes #5678
394
+
395
+ ### Fix
396
+ * Guard against null values during content export
397
+
398
+ ### Testing
399
+ 1. Export a course with empty optional fields
400
+ 2. Verify export completes without error"
401
+ ```
402
+
403
+ ### Step 3: Merge and release v1.0.1
404
+
405
+ Once the PR is reviewed and merged into the `1.0.x` branch, semantic-release runs and publishes `v1.0.1`. This version contains only the `v1.0.0` code plus the bugfix — no `v1.1.0` feature code.
406
+
407
+ Push the maintenance branch to trigger the release:
408
+
409
+ ```bash
410
+ # The 1.0.x branch needs to exist on the remote for the workflow to trigger
411
+ git push origin 1.0.x
412
+ ```
413
+
414
+ ### Step 4: Update production
415
+
416
+ ```bash
417
+ cd adapt-authoring
418
+ git checkout master && git pull origin master
419
+ npm install adapt-authoring-mymodule@1.0.1 --save-exact --legacy-peer-deps
420
+ git add package.json package-lock.json
421
+ git commit -m "Upgrade: Bump adapt-authoring-mymodule to v1.0.1 (fixes #5678)"
422
+ git push origin master
423
+ gh workflow run release.yml
424
+ ```
425
+
426
+ Production now has the bugfix without the feature.
427
+
428
+ ### Step 5: Cherry-pick the fix to master
429
+
430
+ The fix also needs to be in the `v1.1.x` line. Cherry-pick it onto master:
431
+
432
+ ```bash
433
+ cd my-module
434
+ git checkout master && git pull origin master
435
+ git checkout -b issue/5678-forward
436
+
437
+ # Cherry-pick the fix commit (use the actual SHA)
438
+ git cherry-pick <commit-sha>
439
+
440
+ # Resolve conflicts if any — the code may have changed between v1.0.0 and v1.1.0
441
+ npx standard
442
+ npm test
443
+
444
+ git push -u origin issue/5678-forward
445
+ gh pr create --title "Fix: Handle null values in export (fixes #5678)" \
446
+ --body "### Fixes #5678
447
+
448
+ Cherry-pick of the fix from the 1.0.x maintenance branch.
449
+
450
+ ### Fix
451
+ * Guard against null values during content export"
452
+ ```
453
+
454
+ Once merged to master, semantic-release publishes `v1.1.1` with the fix included.
455
+
456
+ ### Visual timeline
457
+
458
+ ```
459
+ master: v1.0.0 ──── New: feature ──── v1.1.0 ──── cherry-pick fix ──── v1.1.1
460
+ \ ↑
461
+ 1.0.x: └──────────────── Fix: bug ──── v1.0.1 │
462
+ │ │
463
+ └────────────────────┘
464
+ (same fix, both lines)
465
+ ```
466
+
467
+ ### Configuring maintenance branch support
468
+
469
+ This is a one-time setup per module. Two files need updating:
470
+
471
+ **1. `package.json` — add `branches` to the release config:**
472
+
473
+ ```json
474
+ "release": {
475
+ "branches": [
476
+ "+([0-9]).+([0-9]).x",
477
+ "master"
478
+ ],
479
+ "plugins": [
480
+ ["@semantic-release/commit-analyzer", { "preset": "eslint" }],
481
+ ["@semantic-release/release-notes-generator", { "preset": "eslint" }],
482
+ "@semantic-release/npm",
483
+ "@semantic-release/github",
484
+ "@semantic-release/git"
485
+ ]
486
+ }
487
+ ```
488
+
489
+ The `+([0-9]).+([0-9]).x` pattern matches branches like `1.0.x`, `2.3.x`, etc. The `master` entry keeps the existing behaviour for normal releases. Order matters — maintenance branches must come before the main branch.
490
+
491
+ **2. `.github/workflows/releases.yml` — trigger on maintenance branches:**
492
+
493
+ ```yaml
494
+ name: Release
495
+ on:
496
+ push:
497
+ branches:
498
+ - master
499
+ - '+([0-9]).+([0-9]).x'
500
+
501
+ jobs:
502
+ release:
503
+ name: Release
504
+ runs-on: ubuntu-latest
505
+ permissions:
506
+ contents: write
507
+ issues: write
508
+ pull-requests: write
509
+ id-token: write
510
+ steps:
511
+ - name: Checkout
512
+ uses: actions/checkout@v3
513
+ with:
514
+ fetch-depth: 0
515
+ - name: Setup Node.js
516
+ uses: actions/setup-node@v3
517
+ with:
518
+ node-version: 'lts/*'
519
+ - name: Update npm
520
+ run: npm install -g npm@latest
521
+ - name: Install dependencies
522
+ run: npm install
523
+ - name: Release
524
+ env:
525
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
526
+ run: npx semantic-release
527
+ ```
528
+
529
+ The key change is adding `'+([0-9]).+([0-9]).x'` to the `branches` trigger so pushes to maintenance branches also run the release workflow.
530
+
531
+ ### When to create maintenance branches
532
+
533
+ Don't create maintenance branches preemptively. Create them only when you actually need to patch an older release line. Once a maintenance branch is no longer needed (e.g. production has moved to `v1.1.x`), it can be left as-is — it won't interfere with future releases.
534
+
535
+ ### Cleaning up maintenance branches
536
+
537
+ Maintenance branches can be deleted from the remote once production has moved past that version line:
538
+
539
+ ```bash
540
+ # Only after production is on v1.1.x or later
541
+ git push origin --delete 1.0.x
542
+ ```
543
+
544
+ ## Coordinating releases
545
+
546
+ ### Module releases (automatic)
547
+
548
+ Every merge to a module's `master` (or a maintenance branch like `1.0.x`) triggers semantic-release. The commit message prefix determines the version bump:
549
+
550
+ | Merge contains | Version bump | Example |
551
+ |---|---|---|
552
+ | `Fix:` commits only | Patch (0.0.x) | 3.3.0 → 3.3.1 |
553
+ | `Update:` or `New:` | Minor (0.x.0) | 3.3.0 → 3.4.0 |
554
+ | `Breaking:` | Major (x.0.0) | 3.3.0 → 4.0.0 |
555
+ | `Docs:`, `Chore:` only | No release | — |
556
+
557
+ ### Main repository releases (manual)
558
+
559
+ The parent `adapt-authoring` repo aggregates module updates and releases on its own cadence:
560
+
561
+ 1. Module releases accumulate on npm/GitHub Packages
562
+ 2. A developer updates `package.json` in the parent to reference new versions
563
+ 3. Integration tests run to validate the combination
564
+ 4. The release workflow is triggered manually via `gh workflow run release.yml`
565
+ 5. `at-utils version-check` determines the appropriate version bump based on which modules changed
566
+
567
+ ### When to release the parent
568
+
569
+ - **After a hotfix:** Immediately, to get the fix to production
570
+ - **After a feature:** Once all module PRs are merged, their releases complete, and integration tests pass
571
+ - **On a regular cadence:** Periodically, to batch smaller improvements
572
+
573
+ ## Version pinning strategy
574
+
575
+ The parent `adapt-authoring/package.json` uses **exact version pinning** (no `^` or `~` prefix) for all module dependencies. This is the foundation that makes the hotfix-during-feature-work workflow safe.
576
+
577
+ ### Why exact versions?
578
+
579
+ The problem with caret ranges (`^`):
580
+
581
+ ```
582
+ Timeline:
583
+ 1. adapt-authoring-api is at 3.3.0 in production
584
+ 2. Developer ships a new feature → api 3.4.0 released to npm
585
+ 3. A bug is found in production
586
+ 4. Developer fixes the bug → api 3.4.1 released to npm
587
+ 5. Production site runs npm ci...
588
+ ```
589
+
590
+ With `"adapt-authoring-api": "^3.3.0"`, step 5 installs `3.4.1` — which includes the untested feature from step 2 alongside the bugfix. The production site gets changes that haven't been through a full release cycle.
591
+
592
+ With `"adapt-authoring-api": "3.3.0"` (exact), step 5 installs exactly `3.3.0`. The developer then explicitly bumps to `3.3.1` (bugfix only) or `3.4.1` (bugfix + feature) depending on what's appropriate.
593
+
594
+ ### How it works in practice
595
+
596
+ | Scenario | What to bump to | Command |
597
+ |---|---|---|
598
+ | Hotfix only | The patch version | `npm install adapt-authoring-api@3.3.1 --save-exact` |
599
+ | Feature ready for release | The minor version (includes all patches) | `npm install adapt-authoring-api@3.4.1 --save-exact` |
600
+ | Breaking change | The major version | `npm install adapt-authoring-api@4.0.0 --save-exact` |
601
+
602
+ ### Rules
603
+
604
+ 1. **Always use `--save-exact`** when updating dependencies in the parent repo (or set `save-exact=true` in `.npmrc`)
605
+ 2. **Never use `@latest`** in the parent repo — always specify the exact version you intend to deploy
606
+ 3. **One concern per bump** — if you're shipping a hotfix, only bump the module that was patched; don't bundle in other module updates
607
+ 4. **Batch feature updates** into planned releases — update multiple modules together only when you're ready to test and release the full set
608
+
609
+ ### What about peer dependencies in modules?
610
+
611
+ Module-to-module peer dependencies (e.g. `"adapt-authoring-core": "^2.0.0"` in `adapt-authoring-api/package.json`) should continue using caret ranges. These express compatibility ranges, not deployment targets. The parent's exact pins determine what actually runs together in production.
612
+
613
+ ## Common pitfalls
614
+
615
+ ### Shipping unreleased features with a hotfix
616
+
617
+ **Problem:** A module has a new feature (minor release) and a subsequent bugfix (patch release). You bump the parent to get the bugfix, but the new feature comes along for the ride because both are on `master`.
618
+
619
+ **Solution:** This is exactly why the parent uses exact version pinning. When bumping for a hotfix, specify the patch version explicitly (`3.3.1`), not `@latest`. If the bugfix was released *after* a feature (i.e. `master` already has `v3.4.0` and you need to patch `v3.3.0`), use a [maintenance branch](#workflow-4-patching-an-older-release-line) to release `v3.3.1` from the old line. In most cases, plan your merge order so that hotfixes land before features on the module's master branch.
620
+
621
+ ### Merging a multi-module feature one PR at a time
622
+
623
+ **Problem:** You merge the API changes but not the UI changes. The API release publishes a new version that the UI hasn't been updated to work with. Users who update get a broken combination.
624
+
625
+ **Solution:** Merge in dependency order, wait for each release, and don't leave partial features merged overnight.
626
+
627
+ ### Forgetting to rebase after a hotfix
628
+
629
+ **Problem:** Your feature branch diverges from master after a hotfix lands. When you eventually merge, you may introduce conflicts or accidentally revert the hotfix.
630
+
631
+ **Solution:** Rebase feature branches promptly after any hotfix to the same module.
632
+
633
+ ### Committing with the wrong prefix
634
+
635
+ **Problem:** A `Fix:` commit triggers a patch release, but your change is actually a breaking change. Consumers don't expect a major API shift in a patch version.
636
+
637
+ **Solution:** Double-check your commit prefix. Use `Breaking:` for anything that changes existing behaviour in a non-backwards-compatible way. See [commit message guidelines](contributing-code#commit-messages) for details.
638
+
639
+ ### Testing only the module, not the integration
640
+
641
+ **Problem:** Module-level tests pass, but the feature breaks when modules interact.
642
+
643
+ **Solution:** Always run `npm test` from the parent `adapt-authoring/` directory before marking your work as ready for review. This runs integration tests that boot the full application.
644
+
645
+ ### Publishing a dependency bump without testing
646
+
647
+ **Problem:** You update `adapt-authoring/package.json` to reference new module versions and release without running integration tests. A subtle incompatibility ships.
648
+
649
+ **Solution:** Always run integration tests locally (or let CI run them) before triggering the parent release workflow.
@@ -0,0 +1,49 @@
1
+ # Error handling
2
+ Handling errors correctly is a key aspect of writing stable software. This guide will give some tips on how you should deal with errors, as well as the utilities available to make error handling simpler.
3
+
4
+ Before going into specifics, it would be useful to discuss application errors in general terms. The errors you experience are likely to fall into one of the following broad groups:
5
+ - **Initialisation errors**: i.e. problems during start-up
6
+ - **General server errors**: errors which occur outside of user requests, possibly during automated tasks
7
+ - **User errors**: errors which are a direct result of a user request
8
+
9
+ You will need to deal with each category of error differently. Below are some general tips on handling each type of error.
10
+
11
+ ## Initialisation errors
12
+ Any errors which occur during initialisation should be captured and logged as appropriate. Depending on the type of error, it may or may not be considered fatal to your code.
13
+
14
+ Some examples:
15
+ - For a database-handler module, failing to connect to the database would be considered a fatal error, as no further actions can be executed. In this case, the code should perform any clean-up and exit.
16
+ - For a configuration module, failing to load the user configuration file may not be fatal if the application can run without it (e.g. with default settings). In this case the error should be logged, but the code can continue to initialise post-error.
17
+ - For a module which attempts to load a specific file in each module connected to the core system, failing to load a single configuration file may not be an error as such, but rather an expected outcome if the configuration file in question is not something that's required to be defined for every module. In this case, the code can continue and it may not even be necessary to log a message.
18
+
19
+ ## General server errors
20
+ 'General server errors' is a broad category which covers other errors that don't take place at either initialisation or as a result of direct user action. Again, depending on the specific error, these may or may not be fatal.
21
+
22
+ Some examples:
23
+ - For a database-handler module, disconnecting from the database is an expected error, and can be handled and rectified easily.
24
+
25
+ ## User errors
26
+ User errors are any errors which are caused as a direct result of a user performing an action incorrectly. It is even *more* critical with user errors that the error is as specific and descriptive as possible, as the response needs to be informative and instructive to the user that caused the error. Failing to do so will result in an unpleasant user experience.
27
+
28
+ Some examples:
29
+ - A user uploads a file in an invalid format. This definitely isn't a fatal error, as the code can continue post-error. The returned error should inform the user of the issue, as well as how it can be rectified.
30
+
31
+ ## Defining errors
32
+ Depending on the kinds of error that you're dealing with in your code, it may be useful to include a set of custom error definitions specific to your code.
33
+
34
+ Defining useful errors is a critical part of any software system. The error registry makes it easy to define errors for your own modules, and make use of errors defined in other modules.
35
+
36
+ ## Catching errors
37
+
38
+ ## Throwing errors
39
+ As mentioned above, it is preferable to catch errors internally in your code and re-throw these errors.
40
+
41
+ The error registry acts as a central store for all errors defined in the system, and errors can be accessed and thrown from here. For convenience, the errors registry is available directly as a property of the main App instance via `app.errors`:
42
+
43
+ ```js
44
+ try {
45
+ // do something here
46
+ } catch(e) {
47
+ throw this.app.errors.MY_ERROR
48
+ }
49
+ ```