adapt-authoring-adaptframework 1.1.1 → 1.2.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.
|
@@ -2,8 +2,8 @@ import _ from 'lodash'
|
|
|
2
2
|
import { App, Hook } from 'adapt-authoring-core'
|
|
3
3
|
import { createWriteStream } from 'fs'
|
|
4
4
|
import AdaptCli from 'adapt-cli'
|
|
5
|
-
import
|
|
6
|
-
import fs from 'fs
|
|
5
|
+
import FWUtils from './AdaptFrameworkUtils.js'
|
|
6
|
+
import fs from 'fs/promises'
|
|
7
7
|
import path from 'upath'
|
|
8
8
|
import semver from 'semver'
|
|
9
9
|
import zipper from 'zipper'
|
|
@@ -187,9 +187,9 @@ class AdaptFrameworkBuild {
|
|
|
187
187
|
await this.ensureDir(this.buildDir)
|
|
188
188
|
await this.ensureDir(cacheDir)
|
|
189
189
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
190
|
+
FWUtils.logDir('dir', this.dir)
|
|
191
|
+
FWUtils.logDir('buildDir', this.buildDir)
|
|
192
|
+
FWUtils.logDir('cacheDir', this.cacheDir)
|
|
193
193
|
|
|
194
194
|
await this.loadCourseData()
|
|
195
195
|
|
|
@@ -202,11 +202,11 @@ class AdaptFrameworkBuild {
|
|
|
202
202
|
|
|
203
203
|
await this.writeContentJson()
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
FWUtils.logDir('courseDir', this.courseDir)
|
|
206
206
|
|
|
207
207
|
if (!this.isExport) {
|
|
208
208
|
try {
|
|
209
|
-
|
|
209
|
+
FWUtils.logMemory()
|
|
210
210
|
await AdaptCli.buildCourse({
|
|
211
211
|
cwd: this.dir,
|
|
212
212
|
sourceMaps: !this.isPublish,
|
|
@@ -214,9 +214,9 @@ class AdaptFrameworkBuild {
|
|
|
214
214
|
cachePath: path.resolve(cacheDir, this.courseId),
|
|
215
215
|
logger: { log: (...args) => App.instance.logger.log('debug', 'adapt-cli', ...args) }
|
|
216
216
|
})
|
|
217
|
-
|
|
217
|
+
FWUtils.logMemory()
|
|
218
218
|
} catch (e) {
|
|
219
|
-
|
|
219
|
+
FWUtils.logMemory()
|
|
220
220
|
throw App.instance.errors.FW_CLI_BUILD_FAILED
|
|
221
221
|
.setData(e)
|
|
222
222
|
}
|
|
@@ -399,10 +399,11 @@ class AdaptFrameworkBuild {
|
|
|
399
399
|
*/
|
|
400
400
|
async copySource () {
|
|
401
401
|
const { path: fwPath } = await App.instance.waitForModule('adaptframework')
|
|
402
|
-
const BLACKLIST = ['.git', '.DS_Store', 'thumbs.db', 'node_modules', 'course']
|
|
402
|
+
const BLACKLIST = ['.git', '.DS_Store', 'thumbs.db', 'node_modules', 'course', 'migrations']
|
|
403
403
|
const ENABLED_PLUGINS = this.enabledPlugins.map(p => p.name)
|
|
404
404
|
const srcDir = path.join(fwPath, 'src')
|
|
405
|
-
await fs.
|
|
405
|
+
await fs.cp(fwPath, this.dir, {
|
|
406
|
+
recursive: true,
|
|
406
407
|
filter: f => {
|
|
407
408
|
f = path.normalize(f)
|
|
408
409
|
const [type, name] = path.relative(srcDir, f).split('/')
|
|
@@ -458,8 +459,8 @@ class AdaptFrameworkBuild {
|
|
|
458
459
|
return Promise.all(data.map(async ({ dir, fileName, data }) => {
|
|
459
460
|
await this.ensureDir(dir)
|
|
460
461
|
const filepath = path.join(dir, fileName)
|
|
461
|
-
const returnData = await
|
|
462
|
-
|
|
462
|
+
const returnData = await FWUtils.writeJson(filepath, data)
|
|
463
|
+
FWUtils.log('debug', 'WRITE', filepath)
|
|
463
464
|
return returnData
|
|
464
465
|
}))
|
|
465
466
|
}
|
|
@@ -470,9 +471,9 @@ class AdaptFrameworkBuild {
|
|
|
470
471
|
*/
|
|
471
472
|
async createPreview () {
|
|
472
473
|
const tempName = `${this.dir}_temp`
|
|
473
|
-
await fs.
|
|
474
|
-
await fs.
|
|
475
|
-
await fs.
|
|
474
|
+
await fs.rename(path.join(this.dir, 'build'), tempName)
|
|
475
|
+
await fs.rm(this.dir, { recursive: true })
|
|
476
|
+
await fs.rename(tempName, this.dir)
|
|
476
477
|
this.location = this.dir
|
|
477
478
|
}
|
|
478
479
|
|
|
@@ -488,7 +489,7 @@ class AdaptFrameworkBuild {
|
|
|
488
489
|
}
|
|
489
490
|
const outputPath = `${this.dir}.zip`
|
|
490
491
|
await zipper.zip(zipPath, outputPath, { removeSource: true })
|
|
491
|
-
await fs.
|
|
492
|
+
await fs.rm(this.dir, { recursive: true })
|
|
492
493
|
this.location = outputPath
|
|
493
494
|
}
|
|
494
495
|
|
|
@@ -520,7 +521,13 @@ class AdaptFrameworkBuild {
|
|
|
520
521
|
const mongodb = await App.instance.waitForModule('mongodb')
|
|
521
522
|
const query = { action: this.action, createdBy: this.userId }
|
|
522
523
|
const oldBuilds = await mongodb.find(this.collectionName, query)
|
|
523
|
-
await Promise.all(oldBuilds.map(b =>
|
|
524
|
+
await Promise.all(oldBuilds.map(async b => {
|
|
525
|
+
try {
|
|
526
|
+
await fs.rm(b.location, { recursive: true })
|
|
527
|
+
} catch (e) {
|
|
528
|
+
if (e.code !== 'ENOENT') throw e
|
|
529
|
+
}
|
|
530
|
+
}))
|
|
524
531
|
return mongodb.deleteMany(this.collectionName, query)
|
|
525
532
|
}
|
|
526
533
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { App } from 'adapt-authoring-core'
|
|
2
|
-
import fs from 'fs
|
|
2
|
+
import fs from 'fs/promises'
|
|
3
3
|
import { glob } from 'glob'
|
|
4
4
|
import octopus from 'adapt-octopus'
|
|
5
5
|
import path from 'upath'
|
|
6
6
|
import semver from 'semver'
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import FWUtils from './AdaptFrameworkUtils.js'
|
|
9
9
|
|
|
10
10
|
import ComponentTransform from './migrations/component.js'
|
|
11
11
|
import ConfigTransform from './migrations/config.js'
|
|
@@ -217,9 +217,9 @@ class AdaptFrameworkImport {
|
|
|
217
217
|
*/
|
|
218
218
|
this.jsonschema = jsonschema
|
|
219
219
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
FWUtils.log('info', `running with settings ${JSON.stringify(this.settings, null, 2)}`)
|
|
221
|
+
FWUtils.log('debug', 'IMPORT_SETTINGS', JSON.stringify(this.settings, null, 2))
|
|
222
|
+
FWUtils.log('debug', 'IMPORT_USER', this.userId)
|
|
223
223
|
|
|
224
224
|
const { isDryRun, importContent, importPlugins } = this.settings
|
|
225
225
|
const tasks = [
|
|
@@ -257,8 +257,8 @@ class AdaptFrameworkImport {
|
|
|
257
257
|
const nestDir = `${this.unzipPath}/${files[0]}`
|
|
258
258
|
await fs.stat(`${nestDir}/package.json`)
|
|
259
259
|
const newDir = path.join(`${this.unzipPath}_2`)
|
|
260
|
-
await fs.
|
|
261
|
-
await fs.
|
|
260
|
+
await fs.rename(nestDir, newDir)
|
|
261
|
+
await fs.rm(this.unzipPath, { recursive: true })
|
|
262
262
|
this.unzipPath = newDir
|
|
263
263
|
}
|
|
264
264
|
} catch (e) {
|
|
@@ -269,15 +269,15 @@ class AdaptFrameworkImport {
|
|
|
269
269
|
await fs.stat(f)
|
|
270
270
|
this.coursePath = f
|
|
271
271
|
}))
|
|
272
|
-
|
|
272
|
+
FWUtils.logDir('unzipPath', this.unzipPath)
|
|
273
273
|
|
|
274
274
|
if (!this.coursePath) {
|
|
275
275
|
throw App.instance.errors.FW_IMPORT_INVALID_COURSE
|
|
276
276
|
}
|
|
277
|
-
|
|
277
|
+
FWUtils.logDir('coursePath', this.coursePath)
|
|
278
278
|
|
|
279
279
|
try {
|
|
280
|
-
/** @ignore */this.pkg = await
|
|
280
|
+
/** @ignore */this.pkg = await FWUtils.readJson(`${this.unzipPath}/package.json`)
|
|
281
281
|
} catch (e) {
|
|
282
282
|
throw App.instance.errors.FW_IMPORT_INVALID
|
|
283
283
|
}
|
|
@@ -294,7 +294,7 @@ class AdaptFrameworkImport {
|
|
|
294
294
|
this.statusReport.info.push({ code: 'MIGRATE_CONTENT', data })
|
|
295
295
|
}
|
|
296
296
|
await this.convertSchemas()
|
|
297
|
-
|
|
297
|
+
FWUtils.log('debug', 'preparation tasks completed successfully')
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
/**
|
|
@@ -304,7 +304,7 @@ class AdaptFrameworkImport {
|
|
|
304
304
|
async convertSchemas () {
|
|
305
305
|
return octopus.runRecursive({
|
|
306
306
|
cwd: this.unzipPath,
|
|
307
|
-
logger: { log: (...args) =>
|
|
307
|
+
logger: { log: (...args) => FWUtils.log('debug', ...args) }
|
|
308
308
|
})
|
|
309
309
|
}
|
|
310
310
|
|
|
@@ -319,11 +319,11 @@ class AdaptFrameworkImport {
|
|
|
319
319
|
}
|
|
320
320
|
try {
|
|
321
321
|
const customStyle = await fs.readFile(customStylePath, 'utf8')
|
|
322
|
-
const courseJson = await
|
|
323
|
-
await
|
|
324
|
-
|
|
322
|
+
const courseJson = await FWUtils.readJson(courseJsonPath)
|
|
323
|
+
await FWUtils.writeJson(courseJsonPath, { customStyle, ...courseJson })
|
|
324
|
+
FWUtils.log('info', 'patched course customStyle')
|
|
325
325
|
} catch (e) {
|
|
326
|
-
|
|
326
|
+
FWUtils.log('warn', 'failed to patch course customStyle', e)
|
|
327
327
|
}
|
|
328
328
|
}
|
|
329
329
|
|
|
@@ -333,12 +333,13 @@ class AdaptFrameworkImport {
|
|
|
333
333
|
async patchThemeName () {
|
|
334
334
|
const [configJsonPath] = await glob('**/config.json', { cwd: this.coursePath, absolute: true })
|
|
335
335
|
try {
|
|
336
|
-
const configJson = await
|
|
336
|
+
const configJson = await FWUtils.readJson(configJsonPath)
|
|
337
337
|
if (configJson._theme) return
|
|
338
|
-
|
|
339
|
-
|
|
338
|
+
configJson._theme = Object.values(this.usedContentPlugins).find(p => p.type === 'theme').name
|
|
339
|
+
await FWUtils.writeJson(configJsonPath, configJson)
|
|
340
|
+
FWUtils.log('info', 'patched config _theme')
|
|
340
341
|
} catch (e) {
|
|
341
|
-
|
|
342
|
+
FWUtils.log('warn', 'failed to patch config _theme', e)
|
|
342
343
|
}
|
|
343
344
|
}
|
|
344
345
|
|
|
@@ -350,14 +351,14 @@ class AdaptFrameworkImport {
|
|
|
350
351
|
this.assetData = []
|
|
351
352
|
const metaFiles = await glob(`${this.coursePath}/*/assets.json`, { absolute: true })
|
|
352
353
|
if (metaFiles.length) { // process included asset metadata
|
|
353
|
-
|
|
354
|
+
FWUtils.log('debug', 'processing metadata files', metaFiles)
|
|
354
355
|
await Promise.all(metaFiles.map(async f => {
|
|
355
|
-
const metaJson = await
|
|
356
|
+
const metaJson = await FWUtils.readJson(f)
|
|
356
357
|
Object.entries(metaJson).forEach(([filename, metadata]) => this.assetData.push({ filename, ...metadata }))
|
|
357
358
|
}))
|
|
358
359
|
} else { // process the file metadata manually
|
|
359
360
|
const assetFiles = await glob(`${this.coursePath}/*/*/*`, { absolute: true })
|
|
360
|
-
|
|
361
|
+
FWUtils.log('debug', 'processing asset files manually', assetFiles.length)
|
|
361
362
|
this.assetData.push(...assetFiles.map(f => Object.assign({}, { title: path.basename(f), filepath: f })))
|
|
362
363
|
}
|
|
363
364
|
const hasGlobalTags = !!this.tags.length
|
|
@@ -380,9 +381,9 @@ class AdaptFrameworkImport {
|
|
|
380
381
|
}
|
|
381
382
|
}
|
|
382
383
|
await Promise.all(usedPluginPaths.map(async p => {
|
|
383
|
-
const bowerJson = await
|
|
384
|
+
const bowerJson = await FWUtils.readJson(`${p}/bower.json`)
|
|
384
385
|
const { name, version, targetAttribute } = bowerJson
|
|
385
|
-
|
|
386
|
+
FWUtils.log('debug', 'found plugin', name)
|
|
386
387
|
this.usedContentPlugins[path.basename(p)] = { name, path: p, version, targetAttribute, type: getPluginType(bowerJson) }
|
|
387
388
|
}))
|
|
388
389
|
}
|
|
@@ -394,8 +395,8 @@ class AdaptFrameworkImport {
|
|
|
394
395
|
async loadCourseData () {
|
|
395
396
|
const files = await glob('**/*.json', { cwd: this.coursePath, absolute: true, ignore: { ignored: p => p.name === 'assets.json' } })
|
|
396
397
|
const mapped = await Promise.all(files.map(f => this.loadContentFile(f)))
|
|
397
|
-
this.statusReport.info.push({ code: 'CONTENT_IMPORTED', data:
|
|
398
|
-
|
|
398
|
+
this.statusReport.info.push({ code: 'CONTENT_IMPORTED', data: FWUtils.getImportContentCounts(this.contentJson) })
|
|
399
|
+
FWUtils.log('info', 'loaded course data successfully')
|
|
399
400
|
return mapped
|
|
400
401
|
}
|
|
401
402
|
|
|
@@ -404,7 +405,7 @@ class AdaptFrameworkImport {
|
|
|
404
405
|
* @return {Promise}
|
|
405
406
|
*/
|
|
406
407
|
async loadContentFile (filePath) {
|
|
407
|
-
const contents = await
|
|
408
|
+
const contents = await FWUtils.readJson(filePath)
|
|
408
409
|
if (contents._type === 'course') {
|
|
409
410
|
this.contentJson.course = contents
|
|
410
411
|
return
|
|
@@ -422,12 +423,12 @@ class AdaptFrameworkImport {
|
|
|
422
423
|
contents.forEach(c => {
|
|
423
424
|
this.contentJson.contentObjects[c._id] = c
|
|
424
425
|
if (!c._type) {
|
|
425
|
-
|
|
426
|
+
FWUtils.log('warn', App.instance.errors.FW_IMPORT_INVALID_CONTENT.setData({ item: c }))
|
|
426
427
|
this.statusReport.warn.push({ code: 'INVALID_CONTENT', data: c })
|
|
427
428
|
}
|
|
428
429
|
})
|
|
429
430
|
}
|
|
430
|
-
|
|
431
|
+
FWUtils.log('debug', 'LOAD_CONTENT', path.resolve(filePath))
|
|
431
432
|
}
|
|
432
433
|
|
|
433
434
|
/**
|
|
@@ -435,7 +436,7 @@ class AdaptFrameworkImport {
|
|
|
435
436
|
* @return {Promise}
|
|
436
437
|
*/
|
|
437
438
|
async runGruntTask (subTask, { outputDir, captureDir, outputFilePath }) {
|
|
438
|
-
const output = await
|
|
439
|
+
const output = await FWUtils.spawnPromise('npx', ['grunt', `migration:${subTask}`, `--outputdir=${outputDir}`, `--capturedir=${captureDir}`])
|
|
439
440
|
if (outputFilePath) await fs.writeFile(outputFilePath, output)
|
|
440
441
|
}
|
|
441
442
|
|
|
@@ -449,22 +450,22 @@ class AdaptFrameworkImport {
|
|
|
449
450
|
|
|
450
451
|
const folderName = `${this.userId}-migrations`
|
|
451
452
|
const relativePath = path.relative(this.framework.path, this.unzipPath)
|
|
452
|
-
const outputDir =
|
|
453
|
+
const outputDir = await FWUtils.exists(path.join(this.unzipPath, 'build'))
|
|
453
454
|
? path.join(relativePath, 'build')
|
|
454
455
|
: path.join(relativePath, 'src')
|
|
455
456
|
const captureDir = path.join('./', folderName)
|
|
456
457
|
|
|
457
|
-
|
|
458
|
-
|
|
458
|
+
FWUtils.logDir('captureDir', path.join(this.framework.path, captureDir))
|
|
459
|
+
FWUtils.logDir('outputDir', path.join(this.unzipPath, outputDir))
|
|
459
460
|
|
|
460
461
|
const opts = { outputDir, captureDir, outputFilePath: path.join(this.framework.path, 'migrations', `${this.userId}.txt`) }
|
|
461
462
|
await this.runGruntTask('capture', opts)
|
|
462
463
|
await this.runGruntTask('migrate', opts)
|
|
463
464
|
|
|
464
465
|
const captureFolder = path.join(this.framework.path, captureDir)
|
|
465
|
-
await fs.
|
|
466
|
+
await fs.rm(captureFolder, { recursive: true })
|
|
466
467
|
} catch (error) {
|
|
467
|
-
|
|
468
|
+
FWUtils.log('error', 'Migration process failed', error)
|
|
468
469
|
throw new Error(`Migration process failed: ${error.message}`)
|
|
469
470
|
}
|
|
470
471
|
}
|
|
@@ -505,7 +506,7 @@ class AdaptFrameworkImport {
|
|
|
505
506
|
if (course.tags) {
|
|
506
507
|
course.tags = course.tags.map(t => existingTagMap[t])
|
|
507
508
|
}
|
|
508
|
-
|
|
509
|
+
FWUtils.log('debug', 'imported tags successfully')
|
|
509
510
|
}
|
|
510
511
|
|
|
511
512
|
/**
|
|
@@ -539,7 +540,7 @@ class AdaptFrameworkImport {
|
|
|
539
540
|
}
|
|
540
541
|
imagesImported++
|
|
541
542
|
}))
|
|
542
|
-
|
|
543
|
+
FWUtils.log('debug', 'imported course assets successfully')
|
|
543
544
|
this.statusReport.info.push({ code: 'ASSETS_IMPORTED_SUCCESSFULLY', data: { count: imagesImported } })
|
|
544
545
|
}
|
|
545
546
|
|
|
@@ -571,7 +572,7 @@ class AdaptFrameworkImport {
|
|
|
571
572
|
const { version: installedVersion, isLocalInstall } = installedP
|
|
572
573
|
if (semver.lt(importVersion, installedVersion)) {
|
|
573
574
|
this.statusReport.info.push({ code: 'PLUGIN_INSTALL_MIGRATING', data: { name: p, installedVersion, importVersion } })
|
|
574
|
-
|
|
575
|
+
FWUtils.log('debug', `migrating '${p}@${importVersion}' during import, installed version is newer (${installedVersion})`)
|
|
575
576
|
this.pluginsToMigrate.push(p)
|
|
576
577
|
return
|
|
577
578
|
}
|
|
@@ -580,12 +581,12 @@ class AdaptFrameworkImport {
|
|
|
580
581
|
}
|
|
581
582
|
if (semver.eq(importVersion, installedVersion)) {
|
|
582
583
|
this.statusReport.info.push({ code: 'PLUGIN_INSTALL_NOT_NEWER', data: { name: p, installedVersion, importVersion } })
|
|
583
|
-
|
|
584
|
+
FWUtils.log('debug', `not updating '${p}@${importVersion}' during import, installed version is equal to (${installedVersion})`)
|
|
584
585
|
return
|
|
585
586
|
}
|
|
586
587
|
if (!isLocalInstall) {
|
|
587
588
|
this.statusReport.warn.push({ code: 'MANAGED_PLUGIN_INSTALL_SKIPPED', data: { name: p, installedVersion, importVersion } })
|
|
588
|
-
|
|
589
|
+
FWUtils.log('debug', `cannot update '${p}' during import, plugin managed via UI`)
|
|
589
590
|
}
|
|
590
591
|
pluginsToUpdate.push(p)
|
|
591
592
|
})
|
|
@@ -600,10 +601,10 @@ class AdaptFrameworkImport {
|
|
|
600
601
|
try {
|
|
601
602
|
// try and infer a targetAttribute if there isn't one
|
|
602
603
|
const pluginBowerPath = path.join(this.usedContentPlugins[p].path, 'bower.json')
|
|
603
|
-
const bowerJson = await
|
|
604
|
+
const bowerJson = await FWUtils.readJson(pluginBowerPath)
|
|
604
605
|
if (!bowerJson.targetAttribute) {
|
|
605
606
|
bowerJson.targetAttribute = `_${bowerJson.component || bowerJson.extension || bowerJson.menu || bowerJson.theme}`
|
|
606
|
-
await
|
|
607
|
+
await FWUtils.writeJson(pluginBowerPath, bowerJson)
|
|
607
608
|
}
|
|
608
609
|
if (!this.settings.isDryRun) {
|
|
609
610
|
const [pluginData] = await this.contentplugin.installPlugins([[p, this.usedContentPlugins[p].path]], { strict: true })
|
|
@@ -612,7 +613,7 @@ class AdaptFrameworkImport {
|
|
|
612
613
|
this.statusReport.info.push({ code: 'INSTALL_PLUGIN', data: { name: p, version: bowerJson.version } })
|
|
613
614
|
} catch (e) {
|
|
614
615
|
if (e.code !== 'EEXIST') {
|
|
615
|
-
|
|
616
|
+
FWUtils.log('error', 'PLUGIN_IMPORT_FAILED', p, e)
|
|
616
617
|
errors.push({ plugin: p, error: e.data.errors[0] })
|
|
617
618
|
} else {
|
|
618
619
|
errors.push(e)
|
|
@@ -627,7 +628,7 @@ class AdaptFrameworkImport {
|
|
|
627
628
|
this.componentNameMap = Object.values({ ...this.installedPlugins, ...this.newContentPlugins }).reduce((m, v) => {
|
|
628
629
|
return { ...m, [v.targetAttribute.slice(1)]: v.name }
|
|
629
630
|
}, {})
|
|
630
|
-
|
|
631
|
+
FWUtils.log('debug', 'imported course plugins successfully')
|
|
631
632
|
}
|
|
632
633
|
|
|
633
634
|
/**
|
|
@@ -665,7 +666,7 @@ class AdaptFrameworkImport {
|
|
|
665
666
|
}
|
|
666
667
|
}
|
|
667
668
|
if (errors.length) throw App.instance.errors.FW_IMPORT_CONTENT_FAILED.setData({ errors: errors.join('; ') })
|
|
668
|
-
|
|
669
|
+
FWUtils.log('debug', 'imported course data successfully')
|
|
669
670
|
}
|
|
670
671
|
|
|
671
672
|
/**
|
|
@@ -711,7 +712,7 @@ class AdaptFrameworkImport {
|
|
|
711
712
|
try {
|
|
712
713
|
this.extractAssets(schema.built.properties, insertData)
|
|
713
714
|
} catch (e) {
|
|
714
|
-
|
|
715
|
+
FWUtils.log('error', `failed to extract asset data for attribute '${e.attribute}' of schema '${schemaName}', ${e}`)
|
|
715
716
|
}
|
|
716
717
|
insertData = await schema.sanitise(insertData)
|
|
717
718
|
let doc
|
|
@@ -770,7 +771,7 @@ class AdaptFrameworkImport {
|
|
|
770
771
|
async cleanUp (error) {
|
|
771
772
|
try {
|
|
772
773
|
const tasks = [
|
|
773
|
-
fs.
|
|
774
|
+
fs.rm(this.unzipPath, { recursive: true })
|
|
774
775
|
]
|
|
775
776
|
if (error) {
|
|
776
777
|
tasks.push(
|
|
@@ -105,13 +105,13 @@ class AdaptFrameworkModule extends AbstractModule {
|
|
|
105
105
|
const modsPath = path.resolve(this.path, '..', 'node_modules')
|
|
106
106
|
try {
|
|
107
107
|
await fs.stat(modsPath)
|
|
108
|
-
await fs.
|
|
108
|
+
await fs.readFile(path.resolve(this.path, 'package.json'))
|
|
109
109
|
if (!force) {
|
|
110
110
|
this.log('verbose', 'INSTALL no action, force !== true')
|
|
111
111
|
return
|
|
112
112
|
}
|
|
113
113
|
this.log('verbose', 'INSTALL forcing new framework install')
|
|
114
|
-
await fs.
|
|
114
|
+
await fs.rm(this.path, { recursive: true })
|
|
115
115
|
} catch (e) {
|
|
116
116
|
// if src and node_modules are missing, install required
|
|
117
117
|
}
|
|
@@ -119,10 +119,10 @@ class AdaptFrameworkModule extends AbstractModule {
|
|
|
119
119
|
// move node_modules into place
|
|
120
120
|
this.log('verbose', 'INSTALL node_modules')
|
|
121
121
|
try {
|
|
122
|
-
await fs.
|
|
122
|
+
await fs.rm(modsPath, { recursive: true })
|
|
123
123
|
} catch (e) {}
|
|
124
124
|
// move node_modules so it can be shared with all builds
|
|
125
|
-
await fs.
|
|
125
|
+
await fs.rename(path.join(this.path, 'node_modules'), modsPath)
|
|
126
126
|
} catch (e) {
|
|
127
127
|
this.log('error', `failed to install framework, ${e.message}`)
|
|
128
128
|
throw this.app.errors.FW_INSTALL_FAILED
|
|
@@ -149,7 +149,7 @@ class AdaptFrameworkModule extends AbstractModule {
|
|
|
149
149
|
* @return {Promise}
|
|
150
150
|
*/
|
|
151
151
|
async getManifestPlugins () {
|
|
152
|
-
const manifest = await
|
|
152
|
+
const manifest = await FWUtils.readJson(path.resolve(this.path, 'adapt.json'))
|
|
153
153
|
return Object.entries(manifest.dependencies)
|
|
154
154
|
}
|
|
155
155
|
|
|
@@ -3,7 +3,8 @@ import { App } from 'adapt-authoring-core'
|
|
|
3
3
|
import bytes from 'bytes'
|
|
4
4
|
import FrameworkBuild from './AdaptFrameworkBuild.js'
|
|
5
5
|
import FrameworkImport from './AdaptFrameworkImport.js'
|
|
6
|
-
import fs from 'fs'
|
|
6
|
+
import fs from 'fs/promises'
|
|
7
|
+
/* eslint-disable import/no-named-default */import { default as fsSync } from 'fs'
|
|
7
8
|
import path from 'upath'
|
|
8
9
|
import semver from 'semver'
|
|
9
10
|
import { spawn } from 'child_process'
|
|
@@ -51,7 +52,7 @@ class AdaptFrameworkUtils {
|
|
|
51
52
|
try {
|
|
52
53
|
const resolved = dir ? path.resolve(dir) : undefined
|
|
53
54
|
AdaptFrameworkUtils.log('verbose', 'DIR', label, resolved)
|
|
54
|
-
if (resolved) AdaptFrameworkUtils.log('verbose', 'DIR_MODE', label,
|
|
55
|
+
if (resolved) AdaptFrameworkUtils.log('verbose', 'DIR_MODE', label, fsSync.statSync(resolved).mode)
|
|
55
56
|
} catch (e) {
|
|
56
57
|
AdaptFrameworkUtils.log('warn', `failed to log dir ${label} (${dir}), ${e.code}`)
|
|
57
58
|
}
|
|
@@ -61,6 +62,26 @@ class AdaptFrameworkUtils {
|
|
|
61
62
|
AdaptFrameworkUtils.log('verbose', 'MEMORY', Object.entries(process.memoryUsage()).reduce((m, [k, v]) => Object.assign(m, { [k]: bytes.parse(v) }), {}))
|
|
62
63
|
}
|
|
63
64
|
|
|
65
|
+
static async readJson (filepath) {
|
|
66
|
+
return JSON.parse(await fs.readFile(filepath))
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
static writeJson (filepath, data) {
|
|
70
|
+
return fs.writeFile(filepath, (JSON.stringify(data, null, 2)))
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static async exists (filepath) {
|
|
74
|
+
try {
|
|
75
|
+
await fs.stat(filepath)
|
|
76
|
+
return true
|
|
77
|
+
} catch (e) {
|
|
78
|
+
if (e.code === 'ENOENT') {
|
|
79
|
+
return false
|
|
80
|
+
}
|
|
81
|
+
throw e
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
64
85
|
/**
|
|
65
86
|
* Infers the framework action to be executed from a given request URL
|
|
66
87
|
* @param {external:ExpressRequest} req
|
|
@@ -220,11 +241,11 @@ class AdaptFrameworkUtils {
|
|
|
220
241
|
}
|
|
221
242
|
const filePath = path.resolve(buildData.location, req.path.slice(req.path.indexOf(id) + id.length + 1) || 'index.html')
|
|
222
243
|
try {
|
|
223
|
-
await
|
|
224
|
-
|
|
244
|
+
await AdaptFrameworkUtils.exists(filePath)
|
|
245
|
+
? res.sendFile(filePath)
|
|
246
|
+
: next(App.instance.errors.NOT_FOUND.setData({ type: 'file', id: filePath }))
|
|
225
247
|
} catch (e) {
|
|
226
|
-
if (e.code === 'ENOENT') return next(
|
|
227
|
-
return next(e)
|
|
248
|
+
if (e.code === 'ENOENT') return next(e)
|
|
228
249
|
}
|
|
229
250
|
}
|
|
230
251
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adapt-authoring-adaptframework",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.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",
|