nw-builder 4.22.0 → 4.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -195,7 +195,7 @@ const packagePath = await nwbuild({
195
195
  });
196
196
  ```
197
197
 
198
- `format` selects the packager to run. It defaults to `"AppImage"` on Linux and `"nsis"` on Windows. Only `"AppImage"` and `"nsis"` are implemented today - `deb`, `rpm`, `msix` and `dmg` are reserved for later.
198
+ `format` selects the packager to run. It defaults to `"AppImage"` on Linux, `"nsis"` on Windows and `"dmg"` on MacOS. Only `"AppImage"`, `"nsis"` and `"dmg"` are implemented today - `deb`, `rpm` and `msix` are reserved for later.
199
199
 
200
200
  ```javascript
201
201
  const appImagePath = await nwbuild({
@@ -295,38 +295,114 @@ const installerPath = await nwbuild({
295
295
 
296
296
  With the CLI, pass `--nsis.appId=com.example.demo --nsis.desktopShortcut=false`.
297
297
 
298
+ Set `publish` to make the installation self updatable with
299
+ [`@nwutils/updater`](https://www.npmjs.com/package/@nwutils/updater)'s
300
+ `NsisUpdater`, the same way as [for AppImages](#self-updating). The installer
301
+ puts an `app-update.yml` pointing at `publish` next to the app's executable,
302
+ and a `latest.yml` update info file (`latest-<arch>.yml` for architectures
303
+ other than `x64`) is written next to the installer. Upload both the installer
304
+ and `latest.yml` to every release. `NsisUpdater` downloads the new installer and
305
+ runs it silently: it waits for the app to exit, updates it, and starts the new
306
+ version, without asking for administrator rights. `sign` and
307
+ `updateInformation` are AppImage only.
308
+
309
+ ```json
310
+ {
311
+ "name": "demo",
312
+ "version": "1.2.0",
313
+ "nwbuild": {
314
+ "mode": "package",
315
+ "platform": "win",
316
+ "app": { "name": "Demo", "icon": "./icon.ico" },
317
+ "nsis": { "appId": "com.example.demo" },
318
+ "publish": { "provider": "github", "owner": "nwutils", "repo": "demo" }
319
+ }
320
+ }
321
+ ```
322
+
323
+ #### MacOS disk image (DMG)
324
+
325
+ With `platform: "osx"`, package mode builds a DMG, `<app.name>-<arch>.dmg`,
326
+ next to `outDir`. It holds the app next to a link to `/Applications`, so users
327
+ install it by dragging the app onto the link. It needs `hdiutil`, `ditto` and
328
+ `codesign`, which are part of MacOS, so DMGs are built on a MacOS host. Notarize
329
+ the DMG afterwards (eg. `xcrun notarytool submit --wait` and
330
+ `xcrun stapler staple`), so Gatekeeper lets users open it.
331
+
332
+ Options go in `dmg`:
333
+
334
+ | Name | Type | Default | Description |
335
+ | ------------ | -------- | ------------------- | ------------------------------------------------------------------------------------------- |
336
+ | signIdentity | `string` | | Code signing identity to sign the app with, or `"-"` to sign ad-hoc. Not signed by default. |
337
+ | volumeName | `string` | Value of `app.name` | Name of the volume the DMG mounts as. |
338
+ | hdiutilPath | `string` | `"hdiutil"` | Path to `hdiutil`. |
339
+ | dittoPath | `string` | `"ditto"` | Path to `ditto`. |
340
+ | codesignPath | `string` | `"codesign"` | Path to `codesign`. |
341
+
342
+ Set `publish` to make the app self updatable with
343
+ [`@nwutils/updater`](https://www.npmjs.com/package/@nwutils/updater)'s
344
+ `MacUpdater`. Updates don't use the DMG: an `app-update.yml` pointing at
345
+ `publish` is added to the app's `Contents/Resources`, and a
346
+ `<app.name>-<arch>-mac.zip` of the app and a `latest-mac.yml` update info file
347
+ (`latest-mac-<arch>.yml` for architectures other than `x64`) are written next to
348
+ the DMG. Upload all three to every release. The version comes from
349
+ `app.CFBundleShortVersionString`, which defaults to the `package.json`
350
+ `version`.
351
+
352
+ Adding `app-update.yml` changes the app, so sign it with `dmg.signIdentity`
353
+ rather than before packaging. A signed app only accepts updates signed by the
354
+ same team. `sign` and `updateInformation` are AppImage only.
355
+
356
+ ```json
357
+ {
358
+ "name": "demo",
359
+ "version": "1.2.0",
360
+ "nwbuild": {
361
+ "mode": "package",
362
+ "platform": "osx",
363
+ "arch": "arm64",
364
+ "app": { "name": "Demo", "icon": "./icon.icns" },
365
+ "dmg": { "signIdentity": "Developer ID Application: ACME (TEAMID)" },
366
+ "publish": { "provider": "github", "owner": "nwutils", "repo": "demo" }
367
+ }
368
+ }
369
+ ```
370
+
371
+ With the CLI, pass `--dmg.signIdentity=-` (ad-hoc).
372
+
298
373
  ## API Reference
299
374
 
300
375
  Options
301
376
 
302
- | Name | Type | Default | Description |
303
- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
304
- | mode | `"get" \| "run" \| "build" \| "package"` | `"build"` | Choose between get, run, build or package mode |
305
- | version | `string \| "latest" \| "stable"` | `"latest"` | Runtime version |
306
- | flavor | `"normal" \| "sdk"` | `"normal"` | Runtime flavor |
307
- | platform | `"linux" \| "osx" \| "win"` | | Host platform |
308
- | arch | `"ia32" \| "x64" \| "arm64"` | | Host architecture |
309
- | downloadUrl | `"https://dl.nwjs.io" \| "https://npm.taobao.org/mirrors/nwjs" \| https://npmmirror.com/mirrors/nwjs \| "https://github.com/corwin-of-amber/nw.js/releases/"` | `"https://dl.nwjs.io"` | Download server. Supports file systems too (for example `file:///home/localghost/nwjs_mirror`) |
310
- | manifestUrl | `"https://nwjs.io/versions.json" \| "https://raw.githubusercontent.com/nwutils/nw-builder/main/src/util/osx.arm.versions.json"` | `"https://nwjs.io/versions.json"` | Versions manifest URI, gotten via https or local file |
311
- | cacheDir | `string` | `"./cache"` | Directory to cache NW binaries |
312
- | cache | `boolean` | `true` | If true the existing cache is used. Otherwise it removes and redownloads it. |
313
- | ffmpeg | `boolean` | `false` | If true the chromium ffmpeg is replaced by community version with proprietary codecs. |
314
- | logLevel | `"error" \| "warn" \| "info" \| "debug"` | `"info"` | Specify level of logging. |
315
- | shaSum | `boolean` | `true` | Flag to enable/disable shasum checks. |
316
- | srcDir | `string` | `"./"` | File paths to application code |
317
- | argv | `string[]` | `[]` | Command line arguments to pass to NW executable in run mode. You can also define these in `chromium-args` in NW.js manifest. |
318
- | glob | `boolean` | `true` | If true file globbing is enabled when parsing `srcDir`. |
319
- | outDir | `string` | `"./out"` | Directory to store build artifacts |
320
- | managedManifest | `boolean \| string \| object` | `false` | Managed manifest |
321
- | nodeAddon | `boolean` | `false` | Rebuild Node native addons |
322
- | zip | `boolean \| "zip" \| "tar" \| "tgz"` | `false` | If true, "zip", "tar" or "tgz" the `outDir` directory is compressed. |
323
- | format | `"AppImage" \| "deb" \| "rpm" \| "msix" \| "nsis" \| "dmg"` | `"AppImage"` on Linux, `"nsis"` on Windows | Packaged output format, used in package mode. Only `"AppImage"` and `"nsis"` are implemented today. |
324
- | sign | `boolean` | `false` | If true, embed a GPG signature in the AppImage. Used in package mode. |
325
- | signKey | `string` | | ID of the GPG key to sign with. Requires `sign`. Used in package mode. |
326
- | publish | `{provider: "github", owner, repo} \| {provider: "generic", url}` | | Where releases are published. Makes the AppImage self updatable with `@nwutils/updater`. Used in package mode. |
327
- | updateInformation | `boolean \| string` | | AppImage zsync update information. `true` derives it from `publish`. Used in package mode. |
328
- | nsis | `object` | | NSIS installer options, used in package mode. See [Windows installer (NSIS)](#windows-installer-nsis). |
329
- | app | `LinuxRc \| WinRc \| OsxRc` | Additional options for each platform. (See below.) |
377
+ | Name | Type | Default | Description |
378
+ | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
379
+ | mode | `"get" \| "run" \| "build" \| "package"` | `"build"` | Choose between get, run, build or package mode |
380
+ | version | `string \| "latest" \| "stable"` | `"latest"` | Runtime version |
381
+ | flavor | `"normal" \| "sdk"` | `"normal"` | Runtime flavor |
382
+ | platform | `"linux" \| "osx" \| "win"` | | Host platform |
383
+ | arch | `"ia32" \| "x64" \| "arm64"` | | Host architecture |
384
+ | downloadUrl | `"https://dl.nwjs.io" \| "https://npm.taobao.org/mirrors/nwjs" \| https://npmmirror.com/mirrors/nwjs \| "https://github.com/corwin-of-amber/nw.js/releases/"` | `"https://dl.nwjs.io"` | Download server. Supports file systems too (for example `file:///home/localghost/nwjs_mirror`) |
385
+ | manifestUrl | `"https://nwjs.io/versions.json" \| "https://raw.githubusercontent.com/nwutils/nw-builder/main/src/util/osx.arm.versions.json"` | `"https://nwjs.io/versions.json"` | Versions manifest URI, gotten via https or local file |
386
+ | cacheDir | `string` | `"./cache"` | Directory to cache NW binaries |
387
+ | cache | `boolean` | `true` | If true the existing cache is used. Otherwise it removes and redownloads it. |
388
+ | ffmpeg | `boolean` | `false` | If true the chromium ffmpeg is replaced by community version with proprietary codecs. |
389
+ | logLevel | `"error" \| "warn" \| "info" \| "debug"` | `"info"` | Specify level of logging. |
390
+ | shaSum | `boolean` | `true` | Flag to enable/disable shasum checks. |
391
+ | srcDir | `string` | `"./"` | File paths to application code |
392
+ | argv | `string[]` | `[]` | Command line arguments to pass to NW executable in run mode. You can also define these in `chromium-args` in NW.js manifest. |
393
+ | glob | `boolean` | `true` | If true file globbing is enabled when parsing `srcDir`. |
394
+ | outDir | `string` | `"./out"` | Directory to store build artifacts |
395
+ | managedManifest | `boolean \| string \| object` | `false` | Managed manifest |
396
+ | nodeAddon | `boolean` | `false` | Rebuild Node native addons |
397
+ | zip | `boolean \| "zip" \| "tar" \| "tgz"` | `false` | If true, "zip", "tar" or "tgz" the `outDir` directory is compressed. |
398
+ | format | `"AppImage" \| "deb" \| "rpm" \| "msix" \| "nsis" \| "dmg"` | `"AppImage"` on Linux, `"nsis"` on Windows, `"dmg"` on MacOS | Packaged output format, used in package mode. Only `"AppImage"`, `"nsis"` and `"dmg"` are implemented today. |
399
+ | sign | `boolean` | `false` | If true, embed a GPG signature in the AppImage. Used in package mode. |
400
+ | signKey | `string` | | ID of the GPG key to sign with. Requires `sign`. Used in package mode. |
401
+ | publish | `{provider: "github", owner, repo} \| {provider: "generic", url}` | | Where releases are published. Makes the AppImage, NSIS installation or DMG app self updatable with `@nwutils/updater`. Package mode. |
402
+ | updateInformation | `boolean \| string` | | AppImage zsync update information. `true` derives it from `publish`. Used in package mode. |
403
+ | nsis | `object` | | NSIS installer options, used in package mode. See [Windows installer (NSIS)](#windows-installer-nsis). |
404
+ | dmg | `object` | | DMG options, used in package mode. See [MacOS disk image (DMG)](#macos-disk-image-dmg). |
405
+ | app | `LinuxRc \| WinRc \| OsxRc` | Additional options for each platform. (See below.) |
330
406
 
331
407
  ### `app` configuration object
332
408
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nw-builder",
3
- "version": "4.22.0",
3
+ "version": "4.24.0",
4
4
  "description": "Build NW.js desktop applications for MacOS, Windows and Linux.",
5
5
  "keywords": [
6
6
  "NW.js",
@@ -57,7 +57,7 @@
57
57
  "dependencies": {
58
58
  "@nwutils/builder": "^0.1.3",
59
59
  "@nwutils/getter": "^0.3.1",
60
- "@nwutils/packager": "^0.6.0",
60
+ "@nwutils/packager": "^0.8.0",
61
61
  "@nwutils/runner": "^0.2.7",
62
62
  "commander": "^15.0.0",
63
63
  "glob": "^13.0.6"
package/src/cli.js CHANGED
@@ -63,7 +63,7 @@ program
63
63
  .allowUnknownOption(true)
64
64
  .allowExcessArguments(true);
65
65
 
66
- // Handle unknown --app.*, --publish.* and --nsis.* arguments
66
+ // Handle unknown --app.*, --publish.*, --nsis.* and --dmg.* arguments
67
67
  const unknownArgs = program.parse(process.argv).args;
68
68
  /** @type {Record<string, string>} */
69
69
  const appConfig = {};
@@ -71,10 +71,17 @@ const appConfig = {};
71
71
  const publishConfig = {};
72
72
  /** @type {Record<string, string>} */
73
73
  const nsisConfig = {};
74
+ /** @type {Record<string, string>} */
75
+ const dmgConfig = {};
74
76
  /** @type {Record<string, Record<string, string>>} */
75
- const configs = { app: appConfig, publish: publishConfig, nsis: nsisConfig };
77
+ const configs = {
78
+ app: appConfig,
79
+ publish: publishConfig,
80
+ nsis: nsisConfig,
81
+ dmg: dmgConfig,
82
+ };
76
83
  for (const arg of unknownArgs) {
77
- const match = arg.match(/^--(app|publish|nsis)\.([^.=]+)=(.*)$/);
84
+ const match = arg.match(/^--(app|publish|nsis|dmg)\.([^.=]+)=(.*)$/);
78
85
  if (match) {
79
86
  const [, group, key, value] = match;
80
87
  configs[group][key] = value;
@@ -85,13 +92,21 @@ for (const arg of unknownArgs) {
85
92
  const opts = {
86
93
  ...program.opts(),
87
94
  app: appConfig,
88
- publish: Object.keys(publishConfig).length > 0 ? publishConfig : undefined,
95
+ /* The packager validates `publish`, so the raw --publish.* strings are passed as-is. */
96
+ publish:
97
+ Object.keys(publishConfig).length > 0
98
+ ? /** @type {import("./index.d.ts").PublishOptions} */ (
99
+ /** @type {unknown} */ (publishConfig)
100
+ )
101
+ : undefined,
89
102
  nsis: Object.keys(nsisConfig).length > 0 ? nsisConfig : undefined,
103
+ dmg: Object.keys(dmgConfig).length > 0 ? dmgConfig : undefined,
90
104
  srcDir: program.args.find(
91
105
  (arg) =>
92
106
  !arg.startsWith("--app") &&
93
107
  !arg.startsWith("--publish") &&
94
- !arg.startsWith("--nsis"),
108
+ !arg.startsWith("--nsis") &&
109
+ !arg.startsWith("--dmg"),
95
110
  ),
96
111
  cli: true,
97
112
  };
package/src/index.d.ts CHANGED
@@ -42,10 +42,45 @@ export interface Options<P extends SupportedPlatform = SupportedPlatform> {
42
42
  logLevel?: "error" | "warn" | "info" | "debug";
43
43
  /** Managed manifest */
44
44
  managedManifest?: boolean | string | object;
45
- /** Packaged output format, used in package mode. Defaults to `"AppImage"` on Linux and `"nsis"` on Windows. Only `"AppImage"` and `"nsis"` are implemented today - the others are reserved. */
45
+ /** Packaged output format, used in package mode. Defaults to `"AppImage"` on Linux, `"nsis"` on Windows and `"dmg"` on MacOS. Only `"AppImage"`, `"nsis"` and `"dmg"` are implemented today - the others are reserved. */
46
46
  format?: "AppImage" | "deb" | "rpm" | "msix" | "nsis" | "dmg";
47
47
  /** NSIS installer options, used in package mode. The installer's version, publisher, copyright and `.ico` icon come from `app`. */
48
48
  nsis?: NsisOptions;
49
+ /** DMG options, used in package mode. Build on a MacOS host. With `publish`, the version comes from `app.CFBundleShortVersionString`. */
50
+ dmg?: DmgOptions;
51
+ /** Where releases are published, used in package mode. Makes the AppImage, NSIS installation or DMG app self updatable with `@nwutils/updater`. */
52
+ publish?: PublishOptions;
53
+ }
54
+
55
+ /** Where releases are published */
56
+ export type PublishOptions =
57
+ | {
58
+ /** The latest (non draft, non prerelease) release of a GitHub repository */
59
+ provider: "github";
60
+ /** Owner of the GitHub repository */
61
+ owner: string;
62
+ /** Name of the GitHub repository */
63
+ repo: string;
64
+ }
65
+ | {
66
+ /** Any static file server */
67
+ provider: "generic";
68
+ /** Base URL the latest release's files are served from */
69
+ url: string;
70
+ };
71
+
72
+ /** DMG options that have no equivalent in `app` */
73
+ export interface DmgOptions {
74
+ /** Code signing identity the app is signed with, eg. `"Developer ID Application: ACME (TEAMID)"`, or `"-"` to sign ad-hoc. Not signed by default. Sign here rather than before packaging when `publish` is set. */
75
+ signIdentity?: string;
76
+ /** Name of the volume the DMG mounts as. Defaults to `app.name`. */
77
+ volumeName?: string;
78
+ /** Path to `hdiutil`. Defaults to `hdiutil` on the `PATH`. */
79
+ hdiutilPath?: string;
80
+ /** Path to `ditto`. Defaults to `ditto` on the `PATH`. */
81
+ dittoPath?: string;
82
+ /** Path to `codesign`. Defaults to `codesign` on the `PATH`. */
83
+ codesignPath?: string;
49
84
  }
50
85
 
51
86
  /** NSIS installer options that have no equivalent in `app` */
package/src/index.js CHANGED
@@ -33,11 +33,12 @@ import util from "./util.js";
33
33
  * @property {boolean} [nativeAddon = false] Get Node native addons
34
34
  * @property {boolean} [cli=false] If true the CLI is used to parse options. This option is used internally.
35
35
  * @property {string[]} [argv = []] CLI arguments passed to the NW.js process in run mode
36
- * @property {"AppImage" | "deb" | "rpm" | "msix" | "nsis" | "dmg"} [format] Packaged output format, used in package mode. Defaults to `"AppImage"` on Linux and `"nsis"` on Windows. Only `"AppImage"` and `"nsis"` are implemented today - the others are reserved.
36
+ * @property {"AppImage" | "deb" | "rpm" | "msix" | "nsis" | "dmg"} [format] Packaged output format, used in package mode. Defaults to `"AppImage"` on Linux, `"nsis"` on Windows and `"dmg"` on MacOS. Only `"AppImage"`, `"nsis"` and `"dmg"` are implemented today - the others are reserved.
37
37
  * @property {boolean} [sign=false] If true, embed a GPG signature in the AppImage, used in package mode.
38
38
  * @property {string} [signKey] ID of the GPG key to sign the AppImage with, used in package mode. Requires `sign`.
39
- * @property {import("@nwutils/packager").PublishOptions} [publish] Where releases are published, used in package mode. Makes the AppImage self updatable with `@nwutils/updater`.
39
+ * @property {import("@nwutils/packager").PublishOptions} [publish] Where releases are published, used in package mode. Makes the AppImage, NSIS installation or DMG app self updatable with `@nwutils/updater`.
40
40
  * @property {boolean | string} [updateInformation] AppImage zsync update information, used in package mode. `true` derives it from `publish`.
41
+ * @property {import("./util.js").DmgOptions} [dmg] DMG options, used in package mode. Build on a MacOS host. With `publish`, the version comes from `app.CFBundleShortVersionString`.
41
42
  * @property {import("./util.js").NsisOptions} [nsis] NSIS installer options, used in package mode. The installer's version, publisher, copyright and `.ico` icon come from `app`.
42
43
  */
43
44
 
@@ -222,6 +223,14 @@ async function nwbuild(options) {
222
223
  arch: resolved.arch,
223
224
  ...nsisOptions,
224
225
  });
226
+ } else if (resolved.format === "dmg") {
227
+ packagePath = await pkg({
228
+ format: resolved.format,
229
+ appDir: resolved.outDir,
230
+ appName: resolved.app.name,
231
+ arch: resolved.arch,
232
+ ...util.dmgOptions(resolved),
233
+ });
225
234
  } else {
226
235
  packagePath = await pkg({
227
236
  format: resolved.format,
package/src/util.js CHANGED
@@ -114,6 +114,7 @@ import * as GlobModule from "glob";
114
114
  * @property {import("@nwutils/packager").PublishOptions} [publish] Where releases are published, used in package mode
115
115
  * @property {boolean | string} [updateInformation] AppImage zsync update information, used in package mode
116
116
  * @property {NsisOptions} [nsis] NSIS installer options, used in package mode
117
+ * @property {DmgOptions} [dmg] DMG options, used in package mode
117
118
  * @property {string[]} [argv] CLI arguments passed to the NW.js process in run mode
118
119
  * @property {boolean | string} [glob] If true file globbing is enabled when parsing srcDir
119
120
  * @property {string | string[]} [srcDir] File paths to application code
@@ -141,7 +142,7 @@ import * as GlobModule from "glob";
141
142
  * Windows `options.app` values `@nwutils/builder` also writes into the
142
143
  * executable, so both agree.
143
144
  * @param {Options} options Options after `parse()`.
144
- * @returns {{version: string, icon: string | undefined, publisher: string | undefined, copyright: string | undefined, appId: string | undefined, license: string | undefined, desktopShortcut: boolean, startMenuShortcut: boolean, makensisPath: string | undefined}} Options for `nsis()`.
145
+ * @returns {{version: string, icon: string | undefined, publisher: string | undefined, copyright: string | undefined, appId: string | undefined, license: string | undefined, desktopShortcut: boolean, startMenuShortcut: boolean, makensisPath: string | undefined, publish: import("@nwutils/packager").PublishOptions | undefined}} Options for `nsis()`.
145
146
  */
146
147
  function nsisOptions(options) {
147
148
  const app = options.app ?? {};
@@ -169,6 +170,50 @@ function nsisOptions(options) {
169
170
  desktopShortcut: /** @type {boolean} */ (nsis.desktopShortcut ?? true),
170
171
  startMenuShortcut: /** @type {boolean} */ (nsis.startMenuShortcut ?? true),
171
172
  makensisPath: nsis.makensisPath,
173
+ publish: options.publish,
174
+ };
175
+ }
176
+
177
+ /**
178
+ * DMG options that have no equivalent in `options.app`.
179
+ * @typedef {object} DmgOptions
180
+ * @property {string} [signIdentity] Code signing identity the app is signed with, or `"-"` to sign ad-hoc. Not signed by default.
181
+ * @property {string} [volumeName] Name of the volume the DMG mounts as. Defaults to `app.name`.
182
+ * @property {string} [hdiutilPath] Path to `hdiutil`. Defaults to `hdiutil` on the `PATH`.
183
+ * @property {string} [dittoPath] Path to `ditto`. Defaults to `ditto` on the `PATH`.
184
+ * @property {string} [codesignPath] Path to `codesign`. Defaults to `codesign` on the `PATH`.
185
+ */
186
+
187
+ /**
188
+ * Map resolved options to the options `@nwutils/packager`'s `dmg()` takes,
189
+ * besides `appDir`, `appName` and `arch`. The version comes from the MacOS
190
+ * `options.app` value `@nwutils/builder` also writes into `Info.plist`, so both
191
+ * agree.
192
+ * @param {Options} options Options after `parse()`.
193
+ * @returns {{version: string | undefined, volumeName: string | undefined, signIdentity: string | undefined, hdiutilPath: string | undefined, dittoPath: string | undefined, codesignPath: string | undefined, publish: import("@nwutils/packager").PublishOptions | undefined}} Options for `dmg()`.
194
+ */
195
+ function dmgOptions(options) {
196
+ const app = options.app ?? {};
197
+ const dmg = options.dmg ?? {};
198
+
199
+ const version = app.CFBundleShortVersionString ?? app.CFBundleVersion;
200
+ if (
201
+ options.publish !== undefined &&
202
+ (typeof version !== "string" || version === "")
203
+ ) {
204
+ throw new Error(
205
+ 'options.format "dmg" with options.publish needs the application\'s version. Set "version" in package.json, or options.app.CFBundleShortVersionString.',
206
+ );
207
+ }
208
+
209
+ return {
210
+ version,
211
+ volumeName: dmg.volumeName,
212
+ signIdentity: dmg.signIdentity,
213
+ hdiutilPath: dmg.hdiutilPath,
214
+ dittoPath: dmg.dittoPath,
215
+ codesignPath: dmg.codesignPath,
216
+ publish: options.publish,
172
217
  };
173
218
  }
174
219
 
@@ -409,7 +454,9 @@ export const parse = async (options, pkg) => {
409
454
  ? "AppImage"
410
455
  : options.platform === "win"
411
456
  ? "nsis"
412
- : undefined);
457
+ : options.platform === "osx"
458
+ ? "dmg"
459
+ : undefined);
413
460
  options.sign = str2Bool(options.sign ?? false);
414
461
  options.updateInformation = str2Bool(options.updateInformation);
415
462
  if (options.format === "nsis") {
@@ -735,6 +782,48 @@ export const validate = async (options, releaseInfo) => {
735
782
  /* Throws now, before building, if the installer would have no version. */
736
783
  nsisOptions(options);
737
784
  }
785
+ if (options.format === "dmg") {
786
+ if (options.platform !== "osx") {
787
+ throw new Error(
788
+ `options.format "dmg" requires options.platform to be "osx". Got ${JSON.stringify(options.platform)}.`,
789
+ );
790
+ }
791
+ const dmg = options.dmg ?? {};
792
+ for (const key of /** @type {const} */ ([
793
+ "signIdentity",
794
+ "volumeName",
795
+ "hdiutilPath",
796
+ "dittoPath",
797
+ "codesignPath",
798
+ ])) {
799
+ if (
800
+ dmg[key] !== undefined &&
801
+ (typeof dmg[key] !== "string" || dmg[key] === "")
802
+ ) {
803
+ throw new Error(
804
+ `Expected options.dmg.${key} to be a non-empty string. Got ${JSON.stringify(dmg[key])}`,
805
+ );
806
+ }
807
+ }
808
+ /* Throws now, before building, if a self updating DMG would have no version. */
809
+ dmgOptions(options);
810
+ }
811
+ /* GPG signatures and zsync update information only exist for AppImages. */
812
+ if (options.format !== "AppImage") {
813
+ if (options.sign === true) {
814
+ throw new Error(
815
+ 'options.sign is only supported with options.format "AppImage". Use options.dmg.signIdentity to sign a MacOS app.',
816
+ );
817
+ }
818
+ if (
819
+ options.updateInformation !== undefined &&
820
+ options.updateInformation !== false
821
+ ) {
822
+ throw new Error(
823
+ 'options.updateInformation is only supported with options.format "AppImage". Other formats self update with options.publish alone.',
824
+ );
825
+ }
826
+ }
738
827
  }
739
828
 
740
829
  /* By the time validate() runs, parse() has already defaulted options.app to {}. */
@@ -1194,4 +1283,5 @@ export default {
1194
1283
  validate,
1195
1284
  log,
1196
1285
  nsisOptions,
1286
+ dmgOptions,
1197
1287
  };