diff --git a/packages/app-desktop/gulpfile.js b/packages/app-desktop/gulpfile.js index 8d4312a324..05c343e2af 100644 --- a/packages/app-desktop/gulpfile.js +++ b/packages/app-desktop/gulpfile.js @@ -1,13 +1,16 @@ const gulp = require('gulp'); const utils = require('@joplin/tools/gulp/utils'); const compileSass = require('@joplin/tools/compileSass'); +const compilePackageInfo = require('@joplin/tools/compilePackageInfo'); const tasks = { compileScripts: { fn: require('./tools/compileScripts'), }, compilePackageInfo: { - fn: require('./tools/compile-package-info.js'), + fn: async () => { + await compilePackageInfo(`${__dirname}/package.json`, `${__dirname}/packageInfo.js`); + }, }, copyPluginAssets: { fn: require('./tools/copyPluginAssets.js'), diff --git a/packages/server/gulpfile.js b/packages/server/gulpfile.js new file mode 100644 index 0000000000..e9924b82b1 --- /dev/null +++ b/packages/server/gulpfile.js @@ -0,0 +1,22 @@ +const gulp = require('gulp'); +const utils = require('@joplin/tools/gulp/utils'); +const compilePackageInfo = require('@joplin/tools/compilePackageInfo'); +const fs = require('fs-extra'); + +const tasks = { + compilePackageInfo: { + fn: async () => { + const targetDir = `${__dirname}/dist`; + await fs.mkdirp(targetDir); + await compilePackageInfo(`${__dirname}/package.json`, `${targetDir}/packageInfo.js`); + }, + }, +}; + +utils.registerGulpTasks(gulp, tasks); + +const buildParallel = [ + 'compilePackageInfo', +]; + +gulp.task('build', gulp.parallel(...buildParallel)); diff --git a/packages/server/package.json b/packages/server/package.json index c5668b20a5..07683f1617 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -5,6 +5,8 @@ "scripts": { "start-dev": "nodemon --config nodemon.json --ext ts,js,mustache,css,tsx dist/app.js --env dev", "start-dev-no-watch": "node dist/app.js --env dev", + "build": "gulp build", + "postinstall": "npm run build", "devCreateDb": "node dist/app.js --env dev --create-db", "devDropTables": "node dist/app.js --env dev --drop-tables", "devDropDb": "node dist/app.js --env dev --drop-db", @@ -65,6 +67,7 @@ "@types/nodemailer": "^6.4.1", "@types/yargs": "^13.0.2", "@types/zxcvbn": "^4.4.1", + "gulp": "^4.0.2", "jest": "^26.6.3", "jsdom": "^16.4.0", "node-mocks-http": "^1.10.0", diff --git a/packages/server/src/config.ts b/packages/server/src/config.ts index 1d87efc4aa..51b80014f6 100644 --- a/packages/server/src/config.ts +++ b/packages/server/src/config.ts @@ -1,9 +1,14 @@ import { rtrimSlashes } from '@joplin/lib/path-utils'; import { Config, DatabaseConfig, DatabaseConfigClient, Env, MailerConfig, RouteType, StripeConfig } from './utils/types'; import * as pathUtils from 'path'; -import { readFile } from 'fs-extra'; import { loadStripeConfig, StripePublicConfig } from '@joplin/lib/utils/joplinCloud'; +interface PackageJson { + version: string; +} + +const packageJson: PackageJson = require(`${__dirname}/packageInfo.js`); + export interface EnvVariables { APP_NAME?: string; @@ -148,25 +153,13 @@ function baseUrlFromEnv(env: any, appPort: number): string { } } -interface PackageJson { - version: string; -} - -async function readPackageJson(filePath: string): Promise { - const text = await readFile(filePath, 'utf8'); - return JSON.parse(text); -} - let config_: Config = null; export async function initConfig(envType: Env, env: EnvVariables, overrides: any = null) { runningInDocker_ = !!env.RUNNING_IN_DOCKER; const rootDir = pathUtils.dirname(__dirname); - - const packageJson = await readPackageJson(`${rootDir}/package.json`); const stripePublicConfig = loadStripeConfig(envType === Env.BuildTypes ? Env.Dev : envType, `${rootDir}/stripeConfig.json`); - const appName = env.APP_NAME || 'Joplin Server'; const viewDir = `${rootDir}/src/views`; const appPort = env.APP_PORT ? Number(env.APP_PORT) : 22300; diff --git a/packages/tools/compilePackageInfo.js b/packages/tools/compilePackageInfo.js new file mode 100644 index 0000000000..13e6c33230 --- /dev/null +++ b/packages/tools/compilePackageInfo.js @@ -0,0 +1,53 @@ +const fs = require('fs-extra'); +const { execSync } = require('child_process'); + +module.exports = async function compilePackageInfo(packageInfoPath, outputPath) { + const packageInfo = require(packageInfoPath); + + const removeKeys = [ + 'dependencies', + 'devDependencies', + 'main', + 'optionalDependencies', + 'private', + 'scripts', + ]; + + for (let i = 0; i < removeKeys.length; i++) { + delete packageInfo[removeKeys[i]]; + } + + // Relevant for desktop app + if (packageInfo.build) { + const appId = packageInfo.build.appId; + const productName = packageInfo.build.productName; + delete packageInfo.build; + packageInfo.build = { appId: appId }; + packageInfo.name = productName; + } + + let branch; + let hash; + try { + // Use stdio: 'pipe' so that execSync doesn't print error directly to stdout + branch = execSync('git rev-parse --abbrev-ref HEAD', { stdio: 'pipe' }).toString().trim(); + hash = execSync('git log --pretty="%h" -1', { stdio: 'pipe' }).toString().trim(); + // The builds in CI are done from a 'detached HEAD' state, thus the branch name will be 'HEAD' for CI builds. + } catch (err) { + // Don't display error object as it's a "fatal" error, but + // not for us, since is it not critical information + // https://github.com/laurent22/joplin/issues/2256 + console.info('Warning: Could not get git info (it will not be displayed in About dialog box)'); + } + if (typeof branch !== 'undefined' && typeof hash !== 'undefined') { + packageInfo.git = { branch: branch, hash: hash }; + } + + let fileContent = '// Auto-generated by compilePackageInfo.js\n// Do not change directly'; + fileContent += '\n'; + fileContent += `module.exports = ${JSON.stringify(packageInfo, null, '\t')};\n`; + + await fs.writeFile(outputPath, fileContent); + + console.info(`Generated ${outputPath}`); +};