diff --git a/package.json b/package.json index 3fc637f7..fc484ab3 100644 --- a/package.json +++ b/package.json @@ -16,17 +16,15 @@ "postpack": "rimraf build", "prebuild": "npm run clean -s && mkdir -p build/static/", "clean": "rimraf build", - "clean:all": "rimraf build data src/static/fonts src/static/note-editor src/static/pdf-reader src/static/pdf-worker", - "build": "NODE_ENV=production run-s \"build:prepare\" \"build:all\" \"build:postprocess\"", + "clean:all": "rimraf build data tmp src/static/fonts src/static/note-editor src/static/pdf-reader src/static/pdf-worker", + "build": "npm run build:prepare && NODE_ENV=production npm run build:all && npm run build:postprocess", "build:tests": "NODE_ENV=testing run-s \"build:prepare\" \"build:all\" \"build:postprocess\" \"build:layout-only-css\"", "build:all": "run-p 'build:js -s' 'build:scss -s' 'build:html -s' 'build:static -s'", "build:js": "mkdir -p build/static && rollup -c", "build:scss": "for f in src/scss/*.scss; do sass --no-source-map $f build/static/`basename $f .scss`.css; done;", "build:html": "mkdir -p build/ && rsync -vazL src/html/* build/", "build:styles-json": "node scripts/build-styles-json.cjs", - "build:pdf-reader": "node scripts/fetch-pdf-reader.cjs", - "build:pdf-worker": "node scripts/fetch-pdf-worker.cjs", - "build:note-editor": "node scripts/fetch-note-editor.cjs", + "build:fetch-or-build-modules": "node scripts/fetch-or-build-modules.cjs", "build:fonts": "node scripts/fetch-fonts.cjs", "build:locale": "node scripts/fetch-locale.cjs", "build:date-formats": "node scripts/fetch-date-formats.cjs", @@ -34,7 +32,7 @@ "build:static": "mkdir -p build/static && rsync -vazL src/static/* build/static/", "build:postprocess": "postcss build/static/zotero-web-library.css --use autoprefixer --no-map -r", "build:check-icons": "node scripts/check-icons.js", - "build:prepare": "run-p \"build:version\" \"build:locale\" \"build:date-formats\" \"build:pdf-reader\" \"build:pdf-worker\" \"build:note-editor\" \"build:fonts\" \"build:styles-json\" \"build:check-icons\"", + "build:prepare": "run-p \"build:version\" \"build:locale\" \"build:date-formats\" \"build:fetch-or-build-modules\" \"build:fonts\" \"build:styles-json\" \"build:check-icons\"", "build:layout-only-css": "node scripts/build-layout-only-css.js", "devel": "run-p 'devel:js -s' 'devel:scss -s' 'devel:html -s' 'devel:static -s'", "devel:js": "rollup -c -w", diff --git a/scripts/fetch-note-editor.cjs b/scripts/fetch-note-editor.cjs deleted file mode 100644 index 55580bd6..00000000 --- a/scripts/fetch-note-editor.cjs +++ /dev/null @@ -1,51 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); -const util = require('util'); -const exec = util.promisify(require('child_process').exec); - -const buildsURL = 'https://zotero-download.s3.amazonaws.com/ci/'; - -(async () => { - const noteEditorPath = path.join(__dirname, '..', 'modules', 'note-editor'); - const modulesFilePath = path.join(__dirname, '..', 'data', 'modules.json'); - let modulesData = {}; - try { - modulesData = await fs.readJson(modulesFilePath); - } catch (_) { - // modules data file is missing or invalid json, ignore. - } - - const { noteEditor: storedHash } = modulesData; - const { stdout } = await exec('git rev-parse HEAD', { cwd: noteEditorPath }); - const actualHash = stdout.trim(); - - if (!storedHash || storedHash !== actualHash) { - const targetDir = path.join(__dirname, '..', 'src', 'static', 'note-editor'); - try { - const filename = actualHash + '.zip'; - const tmpDir = path.join(__dirname, '..', 'tmp', 'builds', 'note-editor'); - const url = buildsURL + 'client-note-editor/' + filename; - - await fs.remove(targetDir); - await fs.ensureDir(targetDir); - await fs.ensureDir(tmpDir); - - await exec( - `cd ${tmpDir}` - + ` && (test -f ${filename} || curl -f ${url} -o ${filename})` - + ` && unzip ${filename} zotero/* -d ${targetDir}` - + ` && mv ${path.join(targetDir, 'zotero', '*')} ${targetDir}` - ); - console.log(`Obtained note-reader from ${url}`); - await fs.remove(tmpDir); - } - catch (e) { - console.log(`Unable to fetch note-editor, will build instead...`); - await exec('npm ci', { cwd: noteEditorPath }); - await exec('npm run build', { cwd: noteEditorPath }); - await fs.copy(path.join(noteEditorPath, 'build', 'web'), targetDir); - console.log(`note-editor build complete`); - } - await fs.writeJson(modulesFilePath, { ...modulesData, noteEditor: actualHash }); - } -})(); \ No newline at end of file diff --git a/scripts/fetch-or-build-modules.cjs b/scripts/fetch-or-build-modules.cjs new file mode 100644 index 00000000..0e728a0d --- /dev/null +++ b/scripts/fetch-or-build-modules.cjs @@ -0,0 +1,91 @@ +const fs = require('fs-extra'); +const path = require('path'); +const util = require('util'); +const exec = util.promisify(require('child_process').exec); + +const buildsURL = 'https://zotero-download.s3.amazonaws.com/ci/'; +const modulesFilePath = path.join(__dirname, '..', 'data', 'modules.json'); + +const modulesConfig = [ + { + name: 'pdf-reader', + key: 'pdfReader', + URLpath: 'client-pdf-reader', + buildPath: ['build', 'web'], + exec: (url, filename, tmpDir, targetDir) => `cd ${tmpDir}` + + ` && (test -f ${filename} || curl -f ${url} -o ${filename})` + + ` && mkdir -p ${targetDir}` + + ` && unzip ${filename} web/* -d ${targetDir}` + + ` && mv ${targetDir}/web/* ${targetDir}/` + + ` && rm -r ${targetDir}/web` + }, + { + name: 'pdf-worker', + key: 'pdfWorker', + URLpath: 'client-pdf-worker', + buildPath: ['build'], + exec: (url, filename, tmpDir, targetDir) => `cd ${tmpDir}` + + ` && (test -f ${filename} || curl -f ${url} -o ${filename})` + + ` && mkdir -p ${targetDir}` + + ` && unzip -o ${filename} -d ${targetDir}` + }, + { + name: 'note-editor', + key: 'noteEditor', + URLpath: 'client-note-editor', + buildPath: ['build', 'web'], + exec: (url, filename, tmpDir, targetDir) => `cd ${tmpDir}` + + ` && (test -f ${filename} || curl -f ${url} -o ${filename})` + + ` && unzip ${filename} zotero/* -d ${targetDir}` + + ` && mv ${path.join(targetDir, 'zotero', '*')} ${targetDir}` + } +]; + +(async () => { + let modulesData = {}; + try { + modulesData = await fs.readJson(modulesFilePath); + } catch (_) { + // modules data file is missing or invalid json, ignore. + } + + const promises = modulesConfig.map(async moduleConfig => { + const srcPath = path.join(__dirname, '..', 'modules', moduleConfig.name); + const storedHash = modulesData[moduleConfig.key]; + const { stdout } = await exec('git rev-parse HEAD', { cwd: srcPath }); + const actualHash = stdout.trim(); + const targetDir = path.join(__dirname, '..', 'src', 'static', moduleConfig.name); + const targetDirExists = await fs.pathExists(targetDir); + const tmpDir = path.join(__dirname, '..', 'tmp', 'builds', moduleConfig.name); + if (!targetDirExists || !storedHash || storedHash !== actualHash) { + try { + const filename = actualHash + '.zip'; + const url = buildsURL + moduleConfig.URLpath + '/' + filename; + + await fs.remove(targetDir); + await fs.ensureDir(targetDir); + await fs.ensureDir(tmpDir); + + await exec(moduleConfig.exec(url, filename, tmpDir, targetDir)); + console.log(`Obtained ${moduleConfig.name} from ${url}`); + } catch (e) { + console.log(`Unable to fetch ${moduleConfig.name}, will build instead...`); + await exec('npm ci', { cwd: srcPath }); + await exec('npm run build', { cwd: srcPath }); + await fs.copy(path.join(srcPath, ...moduleConfig.buildPath), targetDir); + console.log(`${moduleConfig.name} build complete`); + } finally { + await fs.remove(tmpDir); + } + modulesData[moduleConfig.key] = actualHash; + } else { + console.log(`Skipping ${moduleConfig.name} fetch/build, already up to date`); + } + }); + + await Promise.all(promises); + await fs.ensureDir(path.dirname(modulesFilePath)); + await fs.writeJson(modulesFilePath, modulesData); +})(); + + diff --git a/scripts/fetch-pdf-reader.cjs b/scripts/fetch-pdf-reader.cjs deleted file mode 100644 index 1595faf0..00000000 --- a/scripts/fetch-pdf-reader.cjs +++ /dev/null @@ -1,52 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); -const util = require('util'); -const exec = util.promisify(require('child_process').exec); - -const buildsURL = 'https://zotero-download.s3.amazonaws.com/ci/'; - -(async () => { - const pdfReaderPath = path.join(__dirname, '..', 'modules', 'pdf-reader'); - const modulesFilePath = path.join(__dirname, '..', 'data', 'modules.json'); - let modulesData = {}; - try { - modulesData = await fs.readJson(modulesFilePath); - } catch(_) { - // modules data file is missing or invalid json, ignore. - } - - const { pdfReader: storedHash } = modulesData; - const { stdout } = await exec('git rev-parse HEAD', { cwd: pdfReaderPath }); - const actualHash = stdout.trim(); - - if (!storedHash || storedHash !== actualHash) { - const targetDir = path.join(__dirname, '..', 'src', 'static', 'pdf-reader'); - try { - const filename = actualHash + '.zip'; - const tmpDir = path.join(__dirname, '..', 'tmp', 'builds', 'pdf-reader'); - const url = buildsURL + 'client-pdf-reader/' + filename; - - await fs.remove(targetDir); - await fs.ensureDir(targetDir); - await fs.ensureDir(tmpDir); - - await exec( - `cd ${tmpDir}` - + ` && (test -f ${filename} || curl -f ${url} -o ${filename})` - + ` && mkdir -p ${targetDir}` - + ` && unzip ${filename} web/* -d ${targetDir}` - + ` && mv ${targetDir}/web/* ${targetDir}/` - + ` && rm -r ${targetDir}/web` - ); - console.log(`Obtained pdf-reader from ${url}`); - await fs.remove(tmpDir); - } catch (e) { - console.log(`Unable to fetch pdf-reader, will build instead...`); - await exec('npm ci', { cwd: pdfReaderPath }); - await exec('npm run build', { cwd: pdfReaderPath }); - await fs.copy(path.join(pdfReaderPath, 'build', 'web'), targetDir); - console.log(`pdf-reader build complete`); - } - await fs.writeJson(modulesFilePath, { ...modulesData, pdfReader: actualHash }) - } -})(); \ No newline at end of file diff --git a/scripts/fetch-pdf-worker.cjs b/scripts/fetch-pdf-worker.cjs deleted file mode 100644 index d33c3820..00000000 --- a/scripts/fetch-pdf-worker.cjs +++ /dev/null @@ -1,50 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); -const util = require('util'); -const exec = util.promisify(require('child_process').exec); - -const buildsURL = 'https://zotero-download.s3.amazonaws.com/ci/'; - -(async () => { - const pdfWorkerPath = path.join(__dirname, '..', 'modules', 'pdf-worker'); - const modulesFilePath = path.join(__dirname, '..', 'data', 'modules.json'); - let modulesData = {}; - try { - modulesData = await fs.readJson(modulesFilePath); - } catch(_) { - // modules data file is missing or invalid json, ignore. - } - - const { pdfWorker: storedHash } = modulesData; - const { stdout } = await exec('git rev-parse HEAD', { cwd: pdfWorkerPath }); - const actualHash = stdout.trim(); - - if (!storedHash || storedHash !== actualHash) { - const targetDir = path.join(__dirname, '..', 'src', 'static', 'pdf-worker'); - try { - const filename = actualHash + '.zip'; - const tmpDir = path.join(__dirname, '..', 'tmp', 'builds', 'pdf-worker'); - const url = buildsURL + 'client-pdf-worker/' + filename; - - await fs.remove(targetDir); - await fs.ensureDir(targetDir); - await fs.ensureDir(tmpDir); - - await exec( - `cd ${tmpDir}` - + ` && (test -f ${filename} || curl -f ${url} -o ${filename})` - + ` && mkdir -p ${targetDir}` - + ` && unzip -o ${filename} -d ${targetDir}` - ); - console.log(`Obtained pdf-worker from ${url}`); - await fs.remove(tmpDir); - } catch (e) { - console.log(`Unable to fetch pdf-worker, will build instead...`); - await exec('npm ci', { cwd: pdfWorkerPath }); - await exec('npm run build', { cwd: pdfWorkerPath }); - await fs.copy(path.join(pdfWorkerPath, 'build'), targetDir); - console.log(`pdf-worker build complete`); - } - await fs.writeJson(modulesFilePath, { ...modulesData, pdfWorker: actualHash }) - } -})(); \ No newline at end of file