adapt-authoring-adaptframework 2.3.4 → 2.5.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.
- package/adapt-authoring.json +3 -0
- package/errors/errors.json +9 -0
- package/lib/AdaptFrameworkBuild.js +28 -11
- package/lib/AdaptFrameworkModule.js +49 -6
- package/package.json +1 -1
package/adapt-authoring.json
CHANGED
package/errors/errors.json
CHANGED
|
@@ -126,5 +126,14 @@
|
|
|
126
126
|
},
|
|
127
127
|
"description": "Plugin is missing a dependency",
|
|
128
128
|
"statusCode": 500
|
|
129
|
+
},
|
|
130
|
+
"FW_VERSION_NOT_ALLOWED": {
|
|
131
|
+
"data": {
|
|
132
|
+
"version": "The version that is not allowed",
|
|
133
|
+
"targetMajorVersion": "The allowed major version number",
|
|
134
|
+
"allowedRange": "The allowed semver range"
|
|
135
|
+
},
|
|
136
|
+
"description": "Framework version is outside the allowed major version",
|
|
137
|
+
"statusCode": 400
|
|
129
138
|
}
|
|
130
139
|
}
|
|
@@ -40,11 +40,12 @@ class AdaptFrameworkBuild {
|
|
|
40
40
|
* @property {String} userId The user executing the build
|
|
41
41
|
* @property {String} expiresAt When the build expires
|
|
42
42
|
* @property {Boolean} compress Whether output files should be compressed into an archive file
|
|
43
|
+
* @property {String} outputDir If set, uses this as the build root. If the directory already exists, only content data and assets are written (framework copy and compilation are skipped)
|
|
43
44
|
*
|
|
44
45
|
* @constructor
|
|
45
46
|
* @param {AdaptFrameworkBuildOptions} options
|
|
46
47
|
*/
|
|
47
|
-
constructor ({ action, courseId, userId, expiresAt, compress }) {
|
|
48
|
+
constructor ({ action, courseId, userId, expiresAt, compress, outputDir }) {
|
|
48
49
|
/**
|
|
49
50
|
* The MongoDB collection name
|
|
50
51
|
* @type {String}
|
|
@@ -150,6 +151,11 @@ class AdaptFrameworkBuild {
|
|
|
150
151
|
* @type {Hook}
|
|
151
152
|
*/
|
|
152
153
|
this.postBuildHook = new Hook({ mutable: true })
|
|
154
|
+
/**
|
|
155
|
+
* Custom output directory. If the directory already exists, only content and assets are written
|
|
156
|
+
* @type {String}
|
|
157
|
+
*/
|
|
158
|
+
this.outputDir = outputDir ?? null
|
|
153
159
|
}
|
|
154
160
|
|
|
155
161
|
/**
|
|
@@ -164,17 +170,26 @@ class AdaptFrameworkBuild {
|
|
|
164
170
|
if (!this.expiresAt) {
|
|
165
171
|
this.expiresAt = await AdaptFrameworkBuild.getBuildExpiry()
|
|
166
172
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
173
|
+
if (this.outputDir) {
|
|
174
|
+
this.dir = this.outputDir
|
|
175
|
+
} else {
|
|
176
|
+
// random suffix to account for parallel builds executed at exactly the same millisecond
|
|
177
|
+
const randomSuffix = `_${Math.floor(Math.random() * 1000).toString().padStart(4, '0')}`
|
|
178
|
+
this.dir = path.resolve(framework.getConfig('buildDir'), Date.now() + randomSuffix)
|
|
179
|
+
}
|
|
170
180
|
this.buildDir = path.join(this.dir, 'build')
|
|
171
181
|
this.courseDir = path.join(this.buildDir, 'course')
|
|
172
182
|
|
|
183
|
+
const dirExists = await fs.access(this.dir).then(() => true, () => false)
|
|
184
|
+
const contentOnly = this.outputDir && dirExists
|
|
185
|
+
|
|
173
186
|
const cacheDir = path.join(framework.getConfig('buildDir'), 'cache')
|
|
174
187
|
|
|
175
188
|
await ensureDir(this.dir)
|
|
176
189
|
await ensureDir(this.buildDir)
|
|
177
|
-
|
|
190
|
+
if (!contentOnly) {
|
|
191
|
+
await ensureDir(cacheDir)
|
|
192
|
+
}
|
|
178
193
|
|
|
179
194
|
logDir('dir', this.dir)
|
|
180
195
|
logDir('buildDir', this.buildDir)
|
|
@@ -182,21 +197,23 @@ class AdaptFrameworkBuild {
|
|
|
182
197
|
|
|
183
198
|
await this.loadCourseData()
|
|
184
199
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
copyFrameworkSource({
|
|
200
|
+
const tasks = [this.copyAssets()]
|
|
201
|
+
if (!contentOnly) {
|
|
202
|
+
tasks.push(copyFrameworkSource({
|
|
188
203
|
destDir: this.dir,
|
|
189
204
|
enabledPlugins: this.enabledPlugins.map(p => p.name),
|
|
190
205
|
linkNodeModules: !this.isExport
|
|
191
|
-
})
|
|
192
|
-
|
|
206
|
+
}))
|
|
207
|
+
}
|
|
208
|
+
await Promise.all(tasks)
|
|
209
|
+
|
|
193
210
|
await this.preBuildHook.invoke(this)
|
|
194
211
|
|
|
195
212
|
await this.writeContentJson()
|
|
196
213
|
|
|
197
214
|
logDir('courseDir', this.courseDir)
|
|
198
215
|
|
|
199
|
-
if (!this.isExport) {
|
|
216
|
+
if (!contentOnly && !this.isExport) {
|
|
200
217
|
try {
|
|
201
218
|
logMemory()
|
|
202
219
|
await AdaptCli.buildCourse({
|
|
@@ -70,6 +70,13 @@ class AdaptFrameworkModule extends AbstractModule {
|
|
|
70
70
|
*/
|
|
71
71
|
this.contentMigrations = []
|
|
72
72
|
|
|
73
|
+
const meta = await readJson(path.resolve(this.rootDir, 'adapt-authoring.json'))
|
|
74
|
+
/**
|
|
75
|
+
* The major version of the Adapt framework this module is designed to work with
|
|
76
|
+
* @type {Number}
|
|
77
|
+
*/
|
|
78
|
+
this._targetFrameworkVersion = meta.framework?.targetVersion
|
|
79
|
+
|
|
73
80
|
this.app.waitForModule('content').then(content => {
|
|
74
81
|
content.accessCheckHook.tap(this.checkContentAccess.bind(this))
|
|
75
82
|
})
|
|
@@ -103,6 +110,36 @@ class AdaptFrameworkModule extends AbstractModule {
|
|
|
103
110
|
return this._version
|
|
104
111
|
}
|
|
105
112
|
|
|
113
|
+
/**
|
|
114
|
+
* The major version of the Adapt framework this module is designed to work with
|
|
115
|
+
* @type {Number|undefined}
|
|
116
|
+
*/
|
|
117
|
+
get targetFrameworkVersion () {
|
|
118
|
+
return this._targetFrameworkVersion
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Returns a semver range string constrained to the target major version, or undefined if no target is set
|
|
123
|
+
* @type {String|undefined}
|
|
124
|
+
*/
|
|
125
|
+
get targetVersionRange () {
|
|
126
|
+
if (this._targetFrameworkVersion === undefined) return undefined
|
|
127
|
+
return `>=${this._targetFrameworkVersion}.0.0 <${this._targetFrameworkVersion + 1}.0.0`
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Checks whether the given version is compatible with the configured target major version
|
|
132
|
+
* @param {string} version Semver version string to check
|
|
133
|
+
* @throws If the version's major does not match the target major version
|
|
134
|
+
*/
|
|
135
|
+
checkVersionCompatibility (version) {
|
|
136
|
+
if (this._targetFrameworkVersion === undefined) return
|
|
137
|
+
const major = semver.major(version)
|
|
138
|
+
if (major !== this._targetFrameworkVersion) {
|
|
139
|
+
throw this.app.errors.FW_VERSION_NOT_ALLOWED.setData({ version, targetMajorVersion: this._targetFrameworkVersion, allowedRange: this.targetVersionRange })
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
106
143
|
/**
|
|
107
144
|
* Installs a local copy of the Adapt framework
|
|
108
145
|
* @return {Promise}
|
|
@@ -121,10 +158,13 @@ class AdaptFrameworkModule extends AbstractModule {
|
|
|
121
158
|
} catch (e) {
|
|
122
159
|
// package is missing, an install is required
|
|
123
160
|
}
|
|
124
|
-
|
|
161
|
+
if (version) {
|
|
162
|
+
this.checkVersionCompatibility(version)
|
|
163
|
+
}
|
|
164
|
+
await this.runCliCommand('installFramework', { version: version ?? this.targetVersionRange })
|
|
125
165
|
} catch (e) {
|
|
126
166
|
this.log('error', `failed to install framework, ${e.message}`)
|
|
127
|
-
throw this.app.errors.FW_INSTALL_FAILED.setData({ reason: e.message })
|
|
167
|
+
throw e.statusCode ? e : this.app.errors.FW_INSTALL_FAILED.setData({ reason: e.message })
|
|
128
168
|
}
|
|
129
169
|
this.log('verbose', 'INSTALL hook invoke')
|
|
130
170
|
await this.postInstallHook.invoke()
|
|
@@ -136,7 +176,7 @@ class AdaptFrameworkModule extends AbstractModule {
|
|
|
136
176
|
*/
|
|
137
177
|
async getLatestVersion () {
|
|
138
178
|
try {
|
|
139
|
-
return semver.clean(await this.runCliCommand('getLatestFrameworkVersion'))
|
|
179
|
+
return semver.clean(await this.runCliCommand('getLatestFrameworkVersion', { version: this.targetVersionRange }))
|
|
140
180
|
} catch (e) {
|
|
141
181
|
this.log('error', `failed to retrieve framework update data, ${e.message}`)
|
|
142
182
|
throw this.app.errors.FW_LATEST_VERSION_FAILED.setData({ reason: e.message })
|
|
@@ -167,11 +207,14 @@ class AdaptFrameworkModule extends AbstractModule {
|
|
|
167
207
|
*/
|
|
168
208
|
async updateFramework (version) {
|
|
169
209
|
try {
|
|
170
|
-
|
|
210
|
+
if (version) {
|
|
211
|
+
this.checkVersionCompatibility(version)
|
|
212
|
+
}
|
|
213
|
+
await this.runCliCommand('updateFramework', { version: version ?? this.targetVersionRange })
|
|
171
214
|
this._version = await this.runCliCommand('getCurrentFrameworkVersion')
|
|
172
215
|
} catch (e) {
|
|
173
216
|
this.log('error', `failed to update framework, ${e.message}`)
|
|
174
|
-
throw this.app.errors.FW_UPDATE_FAILED.setData({ reason: e.message })
|
|
217
|
+
throw e.statusCode ? e : this.app.errors.FW_UPDATE_FAILED.setData({ reason: e.message })
|
|
175
218
|
}
|
|
176
219
|
this.postUpdateHook.invoke()
|
|
177
220
|
}
|
|
@@ -181,7 +224,7 @@ class AdaptFrameworkModule extends AbstractModule {
|
|
|
181
224
|
*/
|
|
182
225
|
async logStatus () {
|
|
183
226
|
const current = this.version
|
|
184
|
-
const latest = await this.
|
|
227
|
+
const latest = await this.getLatestVersion()
|
|
185
228
|
|
|
186
229
|
this.log('info', `local adapt_framework v${current} installed`)
|
|
187
230
|
if (semver.lt(current, latest)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adapt-authoring-adaptframework",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Adapt framework integration for the Adapt authoring tool",
|
|
5
5
|
"homepage": "https://github.com/adapt-security/adapt-authoring-adaptframework",
|
|
6
6
|
"license": "GPL-3.0",
|