Skip to content

Commit 2faddb8

Browse files
committed
New: Support content-only builds via outputDir option
When outputDir is passed and the directory already exists, the build skips framework source copy and CLI compilation, writing only course content JSON and assets. This enables multilang to run a single full build for the default language and content-only builds for the rest.
1 parent d6510e0 commit 2faddb8

1 file changed

Lines changed: 28 additions & 11 deletions

File tree

lib/AdaptFrameworkBuild.js

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,12 @@ class AdaptFrameworkBuild {
4040
* @property {String} userId The user executing the build
4141
* @property {String} expiresAt When the build expires
4242
* @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)
4344
*
4445
* @constructor
4546
* @param {AdaptFrameworkBuildOptions} options
4647
*/
47-
constructor ({ action, courseId, userId, expiresAt, compress }) {
48+
constructor ({ action, courseId, userId, expiresAt, compress, outputDir }) {
4849
/**
4950
* The MongoDB collection name
5051
* @type {String}
@@ -150,6 +151,11 @@ class AdaptFrameworkBuild {
150151
* @type {Hook}
151152
*/
152153
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
153159
}
154160

155161
/**
@@ -164,39 +170,50 @@ class AdaptFrameworkBuild {
164170
if (!this.expiresAt) {
165171
this.expiresAt = await AdaptFrameworkBuild.getBuildExpiry()
166172
}
167-
// random suffix to account for parallel builds executed at exactly the same millisecond
168-
const randomSuffix = `_${Math.floor(Math.random() * 1000).toString().padStart(4, '0')}`
169-
this.dir = path.resolve(framework.getConfig('buildDir'), Date.now() + randomSuffix)
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+
}
170180
this.buildDir = path.join(this.dir, 'build')
171181
this.courseDir = path.join(this.buildDir, 'course')
172182

183+
const dirExists = await fs.access(this.dir).then(() => true, () => false)
184+
const contentOnly = this.outputDir && dirExists
185+
173186
const cacheDir = path.join(framework.getConfig('buildDir'), 'cache')
174187

175188
await ensureDir(this.dir)
176189
await ensureDir(this.buildDir)
177-
await ensureDir(cacheDir)
190+
if (!contentOnly) {
191+
await ensureDir(cacheDir)
192+
}
178193

179194
logDir('dir', this.dir)
180195
logDir('buildDir', this.buildDir)
181196
logDir('cacheDir', this.cacheDir)
182197

183198
await this.loadCourseData()
184199

185-
await Promise.all([
186-
this.copyAssets(),
187-
copyFrameworkSource({
200+
const tasks = [this.copyAssets()]
201+
if (!contentOnly) {
202+
tasks.push(copyFrameworkSource({
188203
destDir: this.dir,
189204
enabledPlugins: this.enabledPlugins.map(p => p.name),
190205
linkNodeModules: !this.isExport
191-
})
192-
])
206+
}))
207+
}
208+
await Promise.all(tasks)
209+
193210
await this.preBuildHook.invoke(this)
194211

195212
await this.writeContentJson()
196213

197214
logDir('courseDir', this.courseDir)
198215

199-
if (!this.isExport) {
216+
if (!contentOnly && !this.isExport) {
200217
try {
201218
logMemory()
202219
await AdaptCli.buildCourse({

0 commit comments

Comments
 (0)