Skip to content

Commit b7be8c7

Browse files
authored
Fix: Apply schema defaults to build output (fixes #182) (#183)
1 parent 732c199 commit b7be8c7

1 file changed

Lines changed: 55 additions & 0 deletions

File tree

lib/AdaptFrameworkBuild.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ class AdaptFrameworkBuild {
211211

212212
await this.preBuildHook.invoke(this)
213213

214+
await this.applySchemaDefaults()
214215
await this.writeContentJson()
215216

216217
logDir('courseDir', this.courseDir)
@@ -425,6 +426,60 @@ class AdaptFrameworkBuild {
425426
}))
426427
}
427428

429+
/**
430+
* Applies schema defaults to the in-memory course and config data using
431+
* the jsonschema module. Replicates what grunt's schema-defaults task does.
432+
*
433+
* TODO: replace validateWithDefaults workaround with schema.validate(data, { ignoreErrors: true })
434+
* once migrated to adapt-schemas v3.x (see #184)
435+
* @return {Promise}
436+
*/
437+
async applySchemaDefaults () {
438+
const [jsonschema, contentplugin] = await App.instance.waitForModule('jsonschema', 'contentplugin')
439+
440+
const enabledPluginSchemas = this.enabledPlugins
441+
.reduce((m, p) => [...m, ...contentplugin.getPluginSchemas(p.name)], [])
442+
const extensionFilter = s => contentplugin.isPluginSchema(s) ? enabledPluginSchemas.includes(s) : true
443+
const getSchema = name => jsonschema.getSchema(name, { useCache: false, extensionFilter })
444+
445+
/**
446+
* Applies defaults via validate(), catching and ignoring validation errors.
447+
* The validated+defaulted data is returned from validate() on success, or
448+
* extracted from the error on failure (validate clones internally).
449+
*/
450+
const validateWithDefaults = (schema, data) => {
451+
try {
452+
return schema.validate(data, { useDefaults: true, ignoreRequired: true })
453+
} catch (e) {
454+
return e.data.data
455+
}
456+
}
457+
458+
const [courseSchema, configSchema] = await Promise.all([
459+
getSchema('course'),
460+
getSchema('config')
461+
])
462+
Object.assign(this.courseData.course.data, validateWithDefaults(courseSchema, this.courseData.course.data))
463+
Object.assign(this.courseData.config.data, validateWithDefaults(configSchema, this.courseData.config.data))
464+
465+
for (const type of ['contentObject', 'article', 'block']) {
466+
const schemaName = type === 'contentObject' ? 'contentobject' : type
467+
const schema = await getSchema(schemaName)
468+
for (const item of this.courseData[type].data) {
469+
Object.assign(item, validateWithDefaults(schema, item))
470+
}
471+
}
472+
473+
const componentSchemas = {}
474+
for (const item of this.courseData.component.data) {
475+
const schemaName = `${item._component}-component`
476+
if (!componentSchemas[schemaName]) {
477+
componentSchemas[schemaName] = await getSchema(schemaName)
478+
}
479+
Object.assign(item, validateWithDefaults(componentSchemas[schemaName], item))
480+
}
481+
}
482+
428483
/**
429484
* Outputs all course data to the required JSON files
430485
* @return {Promise}

0 commit comments

Comments
 (0)