diff --git a/README.md b/README.md index a60e1753..1a1f9576 100644 --- a/README.md +++ b/README.md @@ -385,6 +385,7 @@ nwbuild({ ### Chores +- chore: add Linux, MacOS and Windows fixtures - chore(docs): don't store JSDoc definitions in `typedef`s - get's hard to understand during development. - chore: annotate file paths as `fs.PathLike` instead of `string`. - chore(bld): factor out core build step diff --git a/package.json b/package.json index 46bdb9de..bb699cd4 100644 --- a/package.json +++ b/package.json @@ -47,8 +47,8 @@ "test": "vitest run --coverage", "test:cov": "vitest --coverage.enabled true", "demo:bld": "node ./tests/fixtures/demo.js", - "demo:exe": "./tests/fixtures/out/nwapp.app/Contents/MacOS/nwapp", - "demo:cli": "nwbuild --mode=run --version=0.92.0 --flavor=sdk --glob=false --cacheDir=./node_modules/nw ./tests/fixtures/app" + "demo:exe": "./tests/fixtures/out/Demo.app/Contents/MacOS/Demo", + "demo:cli": "nwbuild --mode=run --flavor=sdk --glob=false --cacheDir=./node_modules/nw ./tests/fixtures/app" }, "devDependencies": { "@eslint/js": "^9.12.0", diff --git a/src/bld.js b/src/bld.js index d2895854..9c11bfb2 100644 --- a/src/bld.js +++ b/src/bld.js @@ -133,7 +133,13 @@ async function bld({ await fs.promises.cp(nwDir, outDir, { recursive: true, verbatimSymlinks: true }); const files = await util.globFiles({ srcDir, glob }); - const manifest = await util.getNodeManifest({ srcDir, glob }); + let manifest = await util.getNodeManifest({ srcDir, glob }); + + /* Set `product_string` in manifest for MacOS. This is used in renaming the Helper apps. */ + if (platform === 'osx') { + manifest.json.product_string = app.name; + await fs.promises.writeFile(manifest.path, JSON.stringify(manifest.json)); + } if (glob) { for (let file of files) { @@ -169,7 +175,7 @@ async function bld({ typeof managedManifest === 'object' || typeof managedManifest === 'string' ) { - await manageManifest({ nwPkg: manifest, managedManifest, outDir, platform }); + await manageManifest({ nwPkg: manifest.json, managedManifest, outDir, platform }); } if (platform === 'linux') { diff --git a/src/index.js b/src/index.js index 995a3227..b77986d4 100644 --- a/src/index.js +++ b/src/index.js @@ -39,18 +39,21 @@ import util from './util.js'; async function nwbuild(options) { let built; let releaseInfo = {}; - let manifest = {}; + let manifest = { + path: '', + json: undefined, + }; try { // Parse options options = await util.parse(options, manifest); manifest = await util.getNodeManifest({ srcDir: options.srcDir, glob: options.glob }); - if (typeof manifest?.nwbuild === 'object') { - options = manifest.nwbuild; + if (typeof manifest.json?.nwbuild === 'object') { + options = manifest.json.nwbuild; } - options = await util.parse(options, manifest); + options = await util.parse(options, manifest.json); //TODO: impl logging diff --git a/src/util.js b/src/util.js index 370d30ae..6ff94c64 100644 --- a/src/util.js +++ b/src/util.js @@ -136,25 +136,30 @@ async function globFiles({ * @param {object} options - node manifest options * @param {string | string []} options.srcDir - src dir * @param {boolean} options.glob - glob flag - * @returns {object} - Node manifest + * @returns {Promise.<{path: string, json: object}>} - Node manifest */ async function getNodeManifest({ srcDir, glob }) { - let manifest; + let manifest = { + path: '', + json: undefined, + }; let files; if (glob) { files = await globFiles({ srcDir, glob }); for (const file of files) { if (path.basename(file) === 'package.json' && manifest === undefined) { - manifest = JSON.parse(await fs.promises.readFile(file)); + manifest.path = file; + manifest.json = JSON.parse(await fs.promises.readFile(file)); } } } else { - manifest = JSON.parse(await fs.promises.readFile(path.resolve(srcDir, 'package.json'))); + manifest.path = path.resolve(srcDir, 'package.json'); + manifest.json = JSON.parse(await fs.promises.readFile(path.resolve(srcDir, 'package.json'))); } - if (manifest === undefined) { + if (manifest.json === undefined) { throw new Error('package.json not found in srcDir file glob patterns.'); } @@ -220,8 +225,11 @@ export const parse = async (options, pkg) => { options.app = options.app ?? {}; options.app.name = options.app.name ?? pkg.name; - /* Remove special and control characters from app.name to mitigate potential path traversal. */ - options.app.name = options.app.name.replace(/[<>:"/\\|?*\u0000-\u001F]/g, ''); + /* Since the `parse` function is called twice, the first time `pkg` is `{}` and `options.app.name` is `undefined`. */ + if (options.app.name) { + /* Remove special and control characters from app.name to mitigate potential path traversal. */ + options.app.name = options.app.name.replace(/[<>:"/\\|?*\u0000-\u001F]/g, ''); + } options.app.icon = options.app.icon ?? undefined; // TODO(#737): move this out diff --git a/tests/fixtures/demo.js b/tests/fixtures/demo.js index 1dd5455f..ae29dfee 100644 --- a/tests/fixtures/demo.js +++ b/tests/fixtures/demo.js @@ -9,7 +9,7 @@ await nwbuild({ outDir: './tests/fixtures/out', glob: false, app: { - name: 'nwapp', + name: 'Demo', // MacOS options LSApplicationCategoryType: 'public.app-category.utilities', CFBundleIdentifier: 'io.nwutils.demo',