adapt-authoring-server 2.2.3 → 2.2.5
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,32 +1,16 @@
|
|
|
1
1
|
name: Release
|
|
2
|
+
|
|
2
3
|
on:
|
|
3
4
|
push:
|
|
4
5
|
branches:
|
|
5
6
|
- master
|
|
6
7
|
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
issues: write
|
|
11
|
+
pull-requests: write
|
|
12
|
+
id-token: write
|
|
13
|
+
|
|
7
14
|
jobs:
|
|
8
15
|
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
|
|
16
|
-
steps:
|
|
17
|
-
- name: Checkout
|
|
18
|
-
uses: actions/checkout@v3
|
|
19
|
-
with:
|
|
20
|
-
fetch-depth: 0
|
|
21
|
-
- name: Setup Node.js
|
|
22
|
-
uses: actions/setup-node@v3
|
|
23
|
-
with:
|
|
24
|
-
node-version: 'lts/*'
|
|
25
|
-
- name: Update npm
|
|
26
|
-
run: npm install -g npm@latest
|
|
27
|
-
- name: Install dependencies
|
|
28
|
-
run: npm install
|
|
29
|
-
- name: Release
|
|
30
|
-
env:
|
|
31
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
32
|
-
run: npx semantic-release
|
|
16
|
+
uses: adaptlearning/semantic-release-config/.github/workflows/release.yml@master
|
package/lib/ServerUtils.js
CHANGED
|
@@ -66,7 +66,7 @@ export async function loadRouteConfig (rootDir, target, options = {}) {
|
|
|
66
66
|
? resolveHandlers(config.routes, target, aliases)
|
|
67
67
|
: []
|
|
68
68
|
|
|
69
|
-
// Prepend default routes from template if provided
|
|
69
|
+
// Prepend default routes from template if provided
|
|
70
70
|
if (options.defaults && config.useDefaultRoutes !== false) {
|
|
71
71
|
const template = await readJson(options.defaults)
|
|
72
72
|
const defaultRoutes = resolveHandlers(template.routes || [], target, aliases)
|
|
@@ -83,7 +83,8 @@ export async function loadRouteConfig (rootDir, target, options = {}) {
|
|
|
83
83
|
return { ...d, ...rest, handlers: { ...d.handlers, ...rest.handlers } }
|
|
84
84
|
})
|
|
85
85
|
const remaining = customRoutes.filter(r => !r.override || !matched.has(r.route))
|
|
86
|
-
|
|
86
|
+
// Custom routes must come before defaults so they take priority in Express's first-match routing
|
|
87
|
+
config.routes = [...remaining, ...mergedDefaults]
|
|
87
88
|
} else {
|
|
88
89
|
config.routes = customRoutes
|
|
89
90
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adapt-authoring-server",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.5",
|
|
4
4
|
"description": "Provides an Express application routing and more",
|
|
5
5
|
"homepage": "https://github.com/adapt-security/adapt-authoring-server",
|
|
6
6
|
"license": "GPL-3.0",
|
|
@@ -17,37 +17,11 @@
|
|
|
17
17
|
"lodash": "^4.17.21"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@semantic-release
|
|
20
|
+
"@adaptlearning/semantic-release-config": "^1.0.0",
|
|
21
21
|
"adapt-schemas": "^1.1.0",
|
|
22
|
-
"conventional-changelog-eslint": "^6.0.0",
|
|
23
|
-
"semantic-release": "^25.0.2",
|
|
24
22
|
"standard": "^17.1.0"
|
|
25
23
|
},
|
|
26
24
|
"release": {
|
|
27
|
-
"
|
|
28
|
-
[
|
|
29
|
-
"@semantic-release/commit-analyzer",
|
|
30
|
-
{
|
|
31
|
-
"preset": "eslint"
|
|
32
|
-
}
|
|
33
|
-
],
|
|
34
|
-
[
|
|
35
|
-
"@semantic-release/release-notes-generator",
|
|
36
|
-
{
|
|
37
|
-
"preset": "eslint"
|
|
38
|
-
}
|
|
39
|
-
],
|
|
40
|
-
"@semantic-release/npm",
|
|
41
|
-
"@semantic-release/github",
|
|
42
|
-
[
|
|
43
|
-
"@semantic-release/git",
|
|
44
|
-
{
|
|
45
|
-
"assets": [
|
|
46
|
-
"package.json"
|
|
47
|
-
],
|
|
48
|
-
"message": "Chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
]
|
|
25
|
+
"extends": "@adaptlearning/semantic-release-config"
|
|
52
26
|
}
|
|
53
27
|
}
|
|
@@ -17,6 +17,18 @@ describe('ServerUtils', () => {
|
|
|
17
17
|
})
|
|
18
18
|
|
|
19
19
|
describe('#addErrorHandler()', () => {
|
|
20
|
+
/** Set up a res with addErrorHandler + status/json capture */
|
|
21
|
+
function createSendErrorSetup (reqOverrides = {}) {
|
|
22
|
+
const req = { translate: (error) => error.message, ...reqOverrides }
|
|
23
|
+
const res = {}
|
|
24
|
+
ServerUtils.addErrorHandler(req, res, () => {})
|
|
25
|
+
let statusCode
|
|
26
|
+
let jsonData
|
|
27
|
+
res.status = (code) => { statusCode = code; return res }
|
|
28
|
+
res.json = (data) => { jsonData = data }
|
|
29
|
+
return { req, res, getStatus: () => statusCode, getJson: () => jsonData }
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
it('should add sendError method to response object', () => {
|
|
21
33
|
const req = {}
|
|
22
34
|
const res = {}
|
|
@@ -30,28 +42,18 @@ describe('ServerUtils', () => {
|
|
|
30
42
|
})
|
|
31
43
|
|
|
32
44
|
it('sendError should send AdaptError as JSON with status code', () => {
|
|
33
|
-
const
|
|
34
|
-
const res = {}
|
|
35
|
-
const next = () => {}
|
|
36
|
-
|
|
37
|
-
ServerUtils.addErrorHandler(req, res, next)
|
|
38
|
-
|
|
39
|
-
let statusCode
|
|
40
|
-
let jsonData
|
|
41
|
-
res.status = (code) => { statusCode = code; return res }
|
|
42
|
-
res.json = (data) => { jsonData = data }
|
|
45
|
+
const { res, getStatus, getJson } = createSendErrorSetup()
|
|
43
46
|
|
|
44
|
-
|
|
47
|
+
res.sendError({
|
|
45
48
|
constructor: { name: 'AdaptError' },
|
|
46
49
|
statusCode: 404,
|
|
47
50
|
code: 'NOT_FOUND',
|
|
48
51
|
message: 'Not found'
|
|
49
|
-
}
|
|
50
|
-
res.sendError(adaptError)
|
|
52
|
+
})
|
|
51
53
|
|
|
52
|
-
assert.equal(
|
|
53
|
-
assert.equal(
|
|
54
|
-
assert.equal(
|
|
54
|
+
assert.equal(getStatus(), 404)
|
|
55
|
+
assert.equal(getJson().code, 'NOT_FOUND')
|
|
56
|
+
assert.equal(getJson().message, 'Not found')
|
|
55
57
|
})
|
|
56
58
|
|
|
57
59
|
it('sendError should fall back to SERVER_ERROR for unknown errors', () => {
|
|
@@ -63,21 +65,12 @@ describe('ServerUtils', () => {
|
|
|
63
65
|
message: 'Internal server error'
|
|
64
66
|
}
|
|
65
67
|
|
|
66
|
-
const
|
|
67
|
-
const res = {}
|
|
68
|
-
const next = () => {}
|
|
69
|
-
|
|
70
|
-
ServerUtils.addErrorHandler(req, res, next)
|
|
71
|
-
|
|
72
|
-
let statusCode
|
|
73
|
-
let jsonData
|
|
74
|
-
res.status = (code) => { statusCode = code; return res }
|
|
75
|
-
res.json = (data) => { jsonData = data }
|
|
68
|
+
const { res, getStatus, getJson } = createSendErrorSetup()
|
|
76
69
|
|
|
77
70
|
res.sendError(new Error('something broke'))
|
|
78
71
|
|
|
79
|
-
assert.equal(
|
|
80
|
-
assert.equal(
|
|
72
|
+
assert.equal(getStatus(), 500)
|
|
73
|
+
assert.equal(getJson().code, 'SERVER_ERROR')
|
|
81
74
|
})
|
|
82
75
|
|
|
83
76
|
it('sendError should look up known error codes on non-AdaptError', () => {
|
|
@@ -88,68 +81,60 @@ describe('ServerUtils', () => {
|
|
|
88
81
|
message: 'Custom error'
|
|
89
82
|
}
|
|
90
83
|
|
|
91
|
-
const
|
|
92
|
-
const res = {}
|
|
93
|
-
const next = () => {}
|
|
94
|
-
|
|
95
|
-
ServerUtils.addErrorHandler(req, res, next)
|
|
96
|
-
|
|
97
|
-
let statusCode
|
|
98
|
-
let jsonData
|
|
99
|
-
res.status = (code) => { statusCode = code; return res }
|
|
100
|
-
res.json = (data) => { jsonData = data }
|
|
84
|
+
const { res, getStatus, getJson } = createSendErrorSetup()
|
|
101
85
|
|
|
102
86
|
const error = new Error('details')
|
|
103
87
|
error.code = 'CUSTOM_CODE'
|
|
104
88
|
res.sendError(error)
|
|
105
89
|
|
|
106
|
-
assert.equal(
|
|
107
|
-
assert.equal(
|
|
90
|
+
assert.equal(getStatus(), 422)
|
|
91
|
+
assert.equal(getJson().code, 'CUSTOM_CODE')
|
|
108
92
|
})
|
|
109
93
|
|
|
110
|
-
it('sendError should
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
94
|
+
it('sendError should copy data from non-AdaptError to looked-up error', () => {
|
|
95
|
+
App.instance.errors = App.instance.errors || {}
|
|
96
|
+
App.instance.errors.VALIDATION_FAILED = {
|
|
97
|
+
statusCode: 400,
|
|
98
|
+
code: 'VALIDATION_FAILED',
|
|
99
|
+
message: 'Validation failed',
|
|
100
|
+
setData (data) { this.data = data; return this }
|
|
101
|
+
}
|
|
114
102
|
|
|
115
|
-
|
|
103
|
+
const { res, getJson } = createSendErrorSetup()
|
|
116
104
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
105
|
+
const error = new Error('Validation failed')
|
|
106
|
+
error.code = 'VALIDATION_FAILED'
|
|
107
|
+
error.data = { errors: '/title is required', schemaName: 'config' }
|
|
108
|
+
res.sendError(error)
|
|
120
109
|
|
|
121
|
-
|
|
110
|
+
assert.deepEqual(getJson().data, { errors: '/title is required', schemaName: 'config' })
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('sendError should include data field in response', () => {
|
|
114
|
+
const { res, getJson } = createSendErrorSetup()
|
|
115
|
+
|
|
116
|
+
res.sendError({
|
|
122
117
|
constructor: { name: 'AdaptError' },
|
|
123
118
|
statusCode: 400,
|
|
124
119
|
code: 'BAD_REQUEST',
|
|
125
120
|
message: 'Bad request',
|
|
126
121
|
data: { field: 'email' }
|
|
127
|
-
}
|
|
128
|
-
res.sendError(adaptError)
|
|
122
|
+
})
|
|
129
123
|
|
|
130
|
-
assert.deepEqual(
|
|
124
|
+
assert.deepEqual(getJson().data, { field: 'email' })
|
|
131
125
|
})
|
|
132
126
|
|
|
133
127
|
it('sendError should use error.message when req.translate is not available', () => {
|
|
134
|
-
const
|
|
135
|
-
const res = {}
|
|
136
|
-
const next = () => {}
|
|
128
|
+
const { res, getJson } = createSendErrorSetup({ translate: undefined })
|
|
137
129
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
let jsonData
|
|
141
|
-
res.status = () => res
|
|
142
|
-
res.json = (data) => { jsonData = data }
|
|
143
|
-
|
|
144
|
-
const adaptError = {
|
|
130
|
+
res.sendError({
|
|
145
131
|
constructor: { name: 'AdaptError' },
|
|
146
132
|
statusCode: 500,
|
|
147
133
|
code: 'ERR',
|
|
148
134
|
message: 'fallback message'
|
|
149
|
-
}
|
|
150
|
-
res.sendError(adaptError)
|
|
135
|
+
})
|
|
151
136
|
|
|
152
|
-
assert.equal(
|
|
137
|
+
assert.equal(getJson().message, 'fallback message')
|
|
153
138
|
})
|
|
154
139
|
})
|
|
155
140
|
|
|
@@ -301,7 +301,7 @@ describe('loadRouteConfig()', () => {
|
|
|
301
301
|
})
|
|
302
302
|
|
|
303
303
|
describe('defaults option', () => {
|
|
304
|
-
it('should
|
|
304
|
+
it('should place custom routes before default routes for correct Express matching', async () => {
|
|
305
305
|
const dir = path.join(tmpDir, 'with-defaults')
|
|
306
306
|
await mkdir(dir, { recursive: true })
|
|
307
307
|
await writeJson(path.join(dir, 'routes.json'), {
|
|
@@ -318,8 +318,8 @@ describe('loadRouteConfig()', () => {
|
|
|
318
318
|
}
|
|
319
319
|
const config = await loadRouteConfig(dir, target, { defaults: defaultsPath })
|
|
320
320
|
assert.equal(config.routes.length, 2)
|
|
321
|
-
assert.equal(config.routes[0].route, '/')
|
|
322
|
-
assert.equal(config.routes[1].route, '/
|
|
321
|
+
assert.equal(config.routes[0].route, '/custom')
|
|
322
|
+
assert.equal(config.routes[1].route, '/')
|
|
323
323
|
})
|
|
324
324
|
|
|
325
325
|
it('should resolve handler strings in default routes using handlerAliases', async () => {
|
|
@@ -450,8 +450,8 @@ describe('loadRouteConfig()', () => {
|
|
|
450
450
|
})
|
|
451
451
|
const config = await loadRouteConfig(dir, { myHandler: () => {} }, { defaults: defaultsPath })
|
|
452
452
|
assert.equal(config.routes.length, 2)
|
|
453
|
-
assert.equal(config.routes[0].route, '/')
|
|
454
|
-
assert.equal(config.routes[1].route, '/
|
|
453
|
+
assert.equal(config.routes[0].route, '/nomatch')
|
|
454
|
+
assert.equal(config.routes[1].route, '/')
|
|
455
455
|
})
|
|
456
456
|
|
|
457
457
|
it('should strip the override flag from merged route', async () => {
|