@@ -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