adapt-authoring-adaptframework 1.1.0 → 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 AdaptFrameworkUtils from './AdaptFrameworkUtils.js'
6
- import fs from 'fs-extra'
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'
@@ -175,7 +175,9 @@ class AdaptFrameworkBuild {
175
175
  if (!this.expiresAt) {
176
176
  this.expiresAt = await AdaptFrameworkBuild.getBuildExpiry()
177
177
  }
178
- this.dir = path.resolve(framework.getConfig('buildDir'), new Date().getTime().toString())
178
+ // random suffix to account for parallel builds executed at exactly the same millisecond
179
+ const randomSuffix = `_${Math.floor(Math.random() * 1000).toString().padStart(4, '0')}`
180
+ this.dir = path.resolve(framework.getConfig('buildDir'), Date.now() + randomSuffix)
179
181
  this.buildDir = path.join(this.dir, 'build')
180
182
  this.courseDir = path.join(this.buildDir, 'course')
181
183
 
@@ -185,9 +187,9 @@ class AdaptFrameworkBuild {
185
187
  await this.ensureDir(this.buildDir)
186
188
  await this.ensureDir(cacheDir)
187
189
 
188
- AdaptFrameworkUtils.logDir('dir', this.dir)
189
- AdaptFrameworkUtils.logDir('buildDir', this.buildDir)
190
- AdaptFrameworkUtils.logDir('cacheDir', this.cacheDir)
190
+ FWUtils.logDir('dir', this.dir)
191
+ FWUtils.logDir('buildDir', this.buildDir)
192
+ FWUtils.logDir('cacheDir', this.cacheDir)
191
193
 
192
194
  await this.loadCourseData()
193
195
 
@@ -200,11 +202,11 @@ class AdaptFrameworkBuild {
200
202
 
201
203
  await this.writeContentJson()
202
204
 
203
- AdaptFrameworkUtils.logDir('courseDir', this.courseDir)
205
+ FWUtils.logDir('courseDir', this.courseDir)
204
206
 
205
207
  if (!this.isExport) {
206
208
  try {
207
- AdaptFrameworkUtils.logMemory()
209
+ FWUtils.logMemory()
208
210
  await AdaptCli.buildCourse({
209
211
  cwd: this.dir,
210
212
  sourceMaps: !this.isPublish,
@@ -212,9 +214,9 @@ class AdaptFrameworkBuild {
212
214
  cachePath: path.resolve(cacheDir, this.courseId),
213
215
  logger: { log: (...args) => App.instance.logger.log('debug', 'adapt-cli', ...args) }
214
216
  })
215
- AdaptFrameworkUtils.logMemory()
217
+ FWUtils.logMemory()
216
218
  } catch (e) {
217
- AdaptFrameworkUtils.logMemory()
219
+ FWUtils.logMemory()
218
220
  throw App.instance.errors.FW_CLI_BUILD_FAILED
219
221
  .setData(e)
220
222
  }
@@ -397,10 +399,11 @@ class AdaptFrameworkBuild {
397
399
  */
398
400
  async copySource () {
399
401
  const { path: fwPath } = await App.instance.waitForModule('adaptframework')
400
- const BLACKLIST = ['.git', '.DS_Store', 'thumbs.db', 'node_modules', 'course']
402
+ const BLACKLIST = ['.git', '.DS_Store', 'thumbs.db', 'node_modules', 'course', 'migrations']
401
403
  const ENABLED_PLUGINS = this.enabledPlugins.map(p => p.name)
402
404
  const srcDir = path.join(fwPath, 'src')
403
- await fs.copy(fwPath, this.dir, {
405
+ await fs.cp(fwPath, this.dir, {
406
+ recursive: true,
404
407
  filter: f => {
405
408
  f = path.normalize(f)
406
409
  const [type, name] = path.relative(srcDir, f).split('/')
@@ -456,8 +459,8 @@ class AdaptFrameworkBuild {
456
459
  return Promise.all(data.map(async ({ dir, fileName, data }) => {
457
460
  await this.ensureDir(dir)
458
461
  const filepath = path.join(dir, fileName)
459
- const returnData = await fs.writeJson(filepath, data, { spaces: 2 })
460
- AdaptFrameworkUtils.log('debug', 'WRITE', filepath)
462
+ const returnData = await FWUtils.writeJson(filepath, data)
463
+ FWUtils.log('debug', 'WRITE', filepath)
461
464
  return returnData
462
465
  }))
463
466
  }
@@ -468,9 +471,9 @@ class AdaptFrameworkBuild {
468
471
  */
469
472
  async createPreview () {
470
473
  const tempName = `${this.dir}_temp`
471
- await fs.move(path.join(this.dir, 'build'), tempName)
472
- await fs.remove(this.dir)
473
- await fs.move(tempName, this.dir)
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)
474
477
  this.location = this.dir
475
478
  }
476
479
 
@@ -486,7 +489,7 @@ class AdaptFrameworkBuild {
486
489
  }
487
490
  const outputPath = `${this.dir}.zip`
488
491
  await zipper.zip(zipPath, outputPath, { removeSource: true })
489
- await fs.remove(this.dir)
492
+ await fs.rm(this.dir, { recursive: true })
490
493
  this.location = outputPath
491
494
  }
492
495
 
@@ -518,7 +521,13 @@ class AdaptFrameworkBuild {
518
521
  const mongodb = await App.instance.waitForModule('mongodb')
519
522
  const query = { action: this.action, createdBy: this.userId }
520
523
  const oldBuilds = await mongodb.find(this.collectionName, query)
521
- await Promise.all(oldBuilds.map(b => fs.remove(b.location)))
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
+ }))
522
531
  return mongodb.deleteMany(this.collectionName, query)
523
532
  }
524
533
  }
@@ -1,11 +1,11 @@
1
1
  import { App } from 'adapt-authoring-core'
2
- import fs from 'fs-extra'
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 AdaptFrameworkUtils from './AdaptFrameworkUtils.js'
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
- AdaptFrameworkUtils.log('info', `running with settings ${JSON.stringify(this.settings, null, 2)}`)
221
- AdaptFrameworkUtils.log('debug', 'IMPORT_SETTINGS', JSON.stringify(this.settings, null, 2))
222
- AdaptFrameworkUtils.log('debug', 'IMPORT_USER', this.userId)
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.move(nestDir, newDir)
261
- await fs.remove(this.unzipPath)
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
- AdaptFrameworkUtils.logDir('unzipPath', this.unzipPath)
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
- AdaptFrameworkUtils.logDir('coursePath', this.coursePath)
277
+ FWUtils.logDir('coursePath', this.coursePath)
278
278
 
279
279
  try {
280
- /** @ignore */this.pkg = await fs.readJson(`${this.unzipPath}/package.json`)
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
- AdaptFrameworkUtils.log('debug', 'preparation tasks completed successfully')
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) => AdaptFrameworkUtils.log('debug', ...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 fs.readJSON(courseJsonPath)
323
- await fs.writeJSON(courseJsonPath, { customStyle, ...courseJson })
324
- AdaptFrameworkUtils.log('info', 'patched course customStyle')
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
- AdaptFrameworkUtils.log('warn', 'failed to patch course customStyle', e)
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 fs.readJSON(configJsonPath)
336
+ const configJson = await FWUtils.readJson(configJsonPath)
337
337
  if (configJson._theme) return
338
- await fs.writeJSON(configJsonPath, { ...configJson, _theme: Object.values(this.usedContentPlugins).find(p => p.type === 'theme').name })
339
- AdaptFrameworkUtils.log('info', 'patched config _theme')
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
- AdaptFrameworkUtils.log('warn', 'failed to patch config _theme', e)
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
- AdaptFrameworkUtils.log('debug', 'processing metadata files', metaFiles)
354
+ FWUtils.log('debug', 'processing metadata files', metaFiles)
354
355
  await Promise.all(metaFiles.map(async f => {
355
- const metaJson = await fs.readJson(f)
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
- AdaptFrameworkUtils.log('debug', 'processing asset files manually', assetFiles.length)
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 fs.readJson(`${p}/bower.json`)
384
+ const bowerJson = await FWUtils.readJson(`${p}/bower.json`)
384
385
  const { name, version, targetAttribute } = bowerJson
385
- AdaptFrameworkUtils.log('debug', 'found plugin', name)
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: AdaptFrameworkUtils.getImportContentCounts(this.contentJson) })
398
- AdaptFrameworkUtils.log('info', 'loaded course data successfully')
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 fs.readJson(filePath)
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
- AdaptFrameworkUtils.log('warn', App.instance.errors.FW_IMPORT_INVALID_CONTENT.setData({ item: c }))
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
- AdaptFrameworkUtils.log('debug', 'LOAD_CONTENT', path.resolve(filePath))
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 AdaptFrameworkUtils.spawnPromise('npx', ['grunt', `migration:${subTask}`, `--outputdir=${outputDir}`, `--capturedir=${captureDir}`])
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 = fs.existsSync(path.join(this.unzipPath, 'build'))
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
- AdaptFrameworkUtils.logDir('captureDir', path.join(this.framework.path, captureDir))
458
- AdaptFrameworkUtils.logDir('outputDir', path.join(this.unzipPath, outputDir))
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.remove(captureFolder)
466
+ await fs.rm(captureFolder, { recursive: true })
466
467
  } catch (error) {
467
- AdaptFrameworkUtils.log('error', 'Migration process failed', error)
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
- AdaptFrameworkUtils.log('debug', 'imported tags successfully')
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
- AdaptFrameworkUtils.log('debug', 'imported course assets successfully')
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
- AdaptFrameworkUtils.log('debug', `migrating '${p}@${importVersion}' during import, installed version is newer (${installedVersion})`)
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
- AdaptFrameworkUtils.log('debug', `not updating '${p}@${importVersion}' during import, installed version is equal to (${installedVersion})`)
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
- AdaptFrameworkUtils.log('debug', `cannot update '${p}' during import, plugin managed via UI`)
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 fs.readJson(pluginBowerPath)
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 fs.writeJson(pluginBowerPath, bowerJson, { spaces: 2 })
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
- AdaptFrameworkUtils.log('error', 'PLUGIN_IMPORT_FAILED', p, e)
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
- AdaptFrameworkUtils.log('debug', 'imported course plugins successfully')
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
- AdaptFrameworkUtils.log('debug', 'imported course data successfully')
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
- AdaptFrameworkUtils.log('error', `failed to extract asset data for attribute '${e.attribute}' of schema '${schemaName}', ${e}`)
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.remove(this.unzipPath)
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.readJson(path.resolve(this.path, 'package.json'))
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.remove(this.path)
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.remove(modsPath)
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.move(path.join(this.path, 'node_modules'), modsPath)
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 fs.readJson(path.resolve(this.path, 'adapt.json'))
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, fs.statSync(resolved).mode)
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 fs.promises.stat(filePath)
224
- res.sendFile(filePath)
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(App.instance.errors.NOT_FOUND.setData({ type: 'file', id: filePath }))
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.1.0",
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",