From 47da04967531024c36f20213736123f3bdcdffce Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Fri, 21 Jun 2024 12:11:25 -0700 Subject: [PATCH] docs: clean up types and add API docs site (#320) --- .gitignore | 6 +- .prettierrc.json | 12 +- README.md | 339 +++++++++++++++++++---------------------------- package.json | 2 + src/flat.ts | 8 +- src/sign.ts | 8 +- src/types.ts | 231 ++++++++++++++++++++++++++++---- src/util.ts | 1 + typedoc.json | 7 + yarn.lock | 64 +++++++++ 10 files changed, 443 insertions(+), 235 deletions(-) create mode 100644 typedoc.json diff --git a/.gitignore b/.gitignore index aa245f2..3244bef 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ .DS_Store +.vscode + /.idea/ /node_modules/ @@ -8,4 +10,6 @@ /test/work/ -/dist/ \ No newline at end of file +/dist/ + +/docs/ diff --git a/.prettierrc.json b/.prettierrc.json index 632a3f5..f9dd2e1 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -3,5 +3,13 @@ "tabWidth": 2, "singleQuote": true, "printWidth": 100, - "parser": "typescript" -} \ No newline at end of file + "parser": "typescript", + "overrides": [ + { + "files": ["*.json", "*.jsonc", "*.json5"], + "options": { + "parser": "json" + } + } + ] +} diff --git a/README.md b/README.md index a7ce98b..407b8ed 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,13 @@ Codesign Electron macOS apps ## About -[`@electron/osx-sign`][electron-osx-sign] minimizes the extra work needed to eventually prepare your apps for shipping, providing the most basic tools and assets. Note that the bare necessities here are sufficient for enabling app sandbox, yet other configurations for network access etc. require additional work. +[`@electron/osx-sign`][electron-osx-sign] minimizes the extra work needed to eventually prepare +your apps for shipping, providing options that work out of the box for most applications. +Additional configuration is available via its API. -*NB: Since [`@electron/osx-sign`][electron-osx-sign] injects the entry `com.apple.security.application-groups` into the entitlements file as part of the pre-signing process, this would reportedly limit app transfer on iTunes Connect (see [#150](https://github.com/electron/osx-sign/issues/150)). However, opting out entitlements automation `opts['preAutoEntitlements'] === false` may result in worse graphics performance.* - -*The signing procedure implemented in this package is based on what described in [Code Signing Guide](https://github.com/electron/electron/blob/main/docs/tutorial/code-signing.md).* +There are two main functionalities exposed via this package: +* Signing macOS apps via `sign` functions. Under the hood, this uses the `codesign` utility. +* Creating `.pkg` installer packages via `flat` functions. Under the hood, this uses the `productbuild` utility. ## Installation @@ -22,17 +24,56 @@ You can also install `@electron/osx-sign` separately if your packaging pipeline npm install --save-dev @electron/osx-sign ``` -## Usage +## Code signing -### Code Signing +The signing procedure implemented in this package is based on what described in Electron's [Code Signing Guide](https://github.com/electron/electron/blob/main/docs/tutorial/code-signing.md). -#### From the API +### Prerequisites + +* You must be a registered member of the [Apple Developer Program](https://developer.apple.com/programs/). + Please note that you could be charged by Apple in order to get issued with the required certificates. +* You must have [Xcode](https://developer.apple.com/xcode/) installed from the + [Mac App Store](https://apps.apple.com/us/app/xcode/id497799835). It is not recommended to download your + copy from other 3rd party sources for security reasons. +* You must have Xcode Command Line Tools installed. To check whether it is available, + try `xcode-select --install` and follow the instructions. +* To distribute your app on the Mac App Store, You must create a Mac App on [App Store Connect](https://appstoreconnect.apple.com/). +* You must give your app a unique Bundle ID. +* You must give your app a version number. + +### Certificates + +In order to distribute your application either inside or outside the Mac App Store, +you will have to have the following certificates from Apple after becoming a registered developer. + +Certificates can be created through the +[Certificates, Identities & Profiles](https://developer.apple.com/account/resources/certificates/add) +page in the Apple Developer website or via [Account Preferences in Xcode](https://help.apple.com/xcode/mac/current/#/dev3a05256b8). + +For distribution inside the Mac App Store, you will need to create: +* Mac App Distribution: `3rd Party Mac Developer Application: * (*)` +* Mac Installer Distribution: `3rd Party Mac Developer Installer: * (*)` + +For distribution outside the Mac App Store: +* Developer ID Application: `Developer ID Application: * (*)` +* Developer ID Installer: `Developer ID Installer: * (*)` + +After you create the necessary certifications, download them and open each so that they are +installed in your keychain. We recommend installing them in your system default keychain so +that `@electron/osx-sign` can detect them automatically. + +**Note:** They appear to come in pairs. It is preferred to have every one of them installed so not to +are about which is not yet installed for future works. However, if you may only want to distribute +outside the Mac App Store, there is no need to have the 3rd Party Mac Developer ones installed and vice versa. + +### API ```javascript const { signAsync } = require('@electron/osx-sign') -signAsync({ +const opts = { app: 'path/to/my.app' -}) +}; +signAsync(opts) .then(function () { // Application signed }) @@ -41,113 +82,58 @@ signAsync({ }) ``` -###### opts - Options +The only mandatory option for `signAsync` is a path to your `.app` package. +Configuration for most Electron apps should work out of the box. +For full configuration options, see the [API documentation]. -**Required** +### Usage examples -`app` - *String* +#### Signing for Mac App Store distribution -Path to the application package. -Needs file extension `.app`. +```javascript +const { signAsync } = require('@electron/osx-sign') +const opts = { + app: 'path/to/my.app', + // optional parameters for additional customization + platform: "mas", // should be auto-detected if your app was packaged for MAS via Packager or Forge + type: "distribution", // defaults to "distribution" for submission to App Store Connect + provisioningProfile: 'path/to/my.provisionprofile', // defaults to the current working directory + keychain: 'my-keychain', // defaults to the system default login keychain +}; +signAsync(opts) + .then(function () { + // Application signed + }) + .catch(function (err) { + // Handle the error + }) +``` -**Optional** +Mac App Store apps require a [Provisioning Profile](https://www.electronjs.org/docs/latest/tutorial/mac-app-store-submission-guide#prepare-provisioning-profile) +for submission to App Store Connect. We recommend having the provisioning profile for distribution +placed in the current working directory and the signing identity installed in the default keychain. -`binaries` - *Array* +The app is not expected to run after codesigning since there is no provisioned device, and it is +intended only for submission to App Store Connect. Since `@electron/osx-sign` adds the entry +`com.apple.developer.team-identifier` to a temporary copy of the specified entitlements file +(with the default option `preAutoEntitlements`), distribution builds can no longer be run directly. -Path to additional binaries that will be signed along with built-ins of Electron. -Default to `undefined`. +To run an app codesigned for distribution locally after codesigning, you may manually add +`ElectronTeamID` in your `Info.plist` and `com.apple.security.application-groups` in the +entitlements file, and set `preAutoEntitlements: false` for `@electron/osx-sign` to avoid +this extra bit. Note that "certain features are only allowed across apps whose team-identifier value match" +([Technical Note TN2415](https://developer.apple.com/library/content/technotes/tn2415/_index.html#//apple_ref/doc/uid/DTS40016427-CH1-ENTITLEMENTSLIST)). -`optionsForFile` - *Function* - -Function that receives the path to a file and can return the entitlements to use for that file to override the default behavior. The -object this function returns can include any of the following optional keys. Any properties that are returned **override** the default -values that `@electron/osx-sign` generates. Any properties not returned use the default value. - -Take care when overriding the `entitlements` property as for security reasons different bundles within Electron are normally signed with -different entitlement files. See the [default implementation](https://github.com/electron/osx-sign/blob/806db73bda1400e82b327619d0c2a793acf576a7/src/sign.ts#L91-L122) -for a reference implementation. - -| Option | Description | Usage Example | -|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------| -| `entitlements` | String specifying the path to an `entitlements.plist` file. Will default to built-in entitlements files. Can also be an array of entitlement keys that osx-sign will write to an entitlements file for you. | `'path/to/entitlements'` | -| `hardenedRuntime` | Boolean flag to enable the Hardened Runtime when signing the app. Enabled by default. | `false` | -| `requirements` | Either a string beginning with `=` which specifies in plain text the [signing requirements](https://developer.apple.com/library/mac/documentation/Security/Conceptual/CodeSigningGuide/RequirementLang/RequirementLang.html) that you recommend to be used to evaluate the code signature, or a string specifying a path to a text or properly encoded `.rqset` file which contains those requirements. | `'=designated => identifier com.github.Electron'`
or
`'path/to/requirements.rqset'` | -| `signatureFlags` | List of [code signature flags](https://keith.github.io/xcode-man-pages/codesign.1.html#OPTION_FLAGS). Accepts an array of strings or a comma-separated string. | `['runtime']` | -| `timestamp` | String specifying the URL of the timestamp authority server. Defaults to the server provided by Apple. Please note that this default server may not support signatures not furnished by Apple. Disable the timestamp service with `none`. | `'https://different.timeserver'` | -| `additionalArguments` | Array of strings specifying additional arguments to pass to the `codesign` command used to sign a specific file. | `['--deep']` | - -**Note:** Only available via the JS API - -`identity` - *String* - -Name of certificate to use when signing. -Default to be selected with respect to `provisioning-profile` and `platform` from `keychain` or keychain by system default. - -Signing platform `mas` will look for `3rd Party Mac Developer Application: * (*)`, and platform `darwin` will look for `Developer ID Application: * (*)` by default. - -`identityValidation` - *Boolean* - -Flag to enable/disable validation for the signing identity. If enabled, the `identity` provided will be validated in the `keychain` specified. -Default to `true`. - -`keychain` - *String* - -The keychain name. -Default to system default keychain. - -`ignore` - *RegExp|Function|Array.<(RegExp|Function)>* - -Regex, function or an array of regex's and functions that signal skipping signing a file. -Elements of other types are treated as `RegExp`. -Default to `undefined`. - -`platform` - *String* - -Build platform of Electron. -Allowed values: `darwin`, `mas`. -Default to auto detect by presence of `Squirrel.framework` within the application bundle. - -`preAutoEntitlements` - *Boolean* - -Flag to enable/disable automation of `com.apple.security.application-groups` in entitlements file and update `Info.plist` with `ElectronTeamID`. -Default to `true`. - -`preEmbedProvisioningProfile` - *Boolean* - -Flag to enable/disable embedding of provisioning profile in the current working directory. -Default to `true`. - -`provisioningProfile` - *String* - -Path to provisioning profile. - -`strictVerify` - *Boolean|String|Array.* - -Flag to enable/disable `--strict` flag when verifying the signed application bundle. -If provided as a string, each component should be separated with comma (`,`). -If provided as an array, each item should be a string corresponding to a component. -Default to `true`. - -`type` - *String* - -Specify whether to sign app for development or for distribution. -Allowed values: `development`, `distribution`. -Default to `distribution`. - -`version` - *String* - -Build version of Electron. -Values may be like: `1.1.1`, `1.2.0`. -Default to latest Electron version. - -It is recommended to utilize this option for best support of specific Electron versions. This may trigger pre/post operations for signing: For example, automation of setting `com.apple.security.application-groups` in entitlements file and of updating `Info.plist` with `ElectronTeamID` is enabled for all versions starting from `1.1.1`; set `preAutoEntitlements` option to `false` to disable this feature. +Alternatively, set the app's `type` to `development` to codesign a development version of your app, +which will allow it to be run on your development provisioned machine. Apps signed for development +will not be eligible for submission via App Store Connect. #### Signing with `--deep` -Some subresources that you may include in your Electron app may need to be signed with `--deep`, this is not typically safe to apply to the entire Electron app and therefore should be applied to _just_ your file. +Some subresources that you may include in your Electron app may need to be signed with `--deep`. +This is not typically safe to apply to the entire Electron app and therefore should be applied to _just_ your file. -```js -const { signAsync } = require('@electron/osx-sign') +```javascript signAsync({ app: 'path/to/my.app', optionsForFile: (filePath) => { @@ -161,59 +147,36 @@ signAsync({ // Just use the default options for everything else return null; - } -}) - .then(function () { - // Application signed - }) - .catch(function (err) { - // Handle the error - }) + }, +}); ``` -#### From the Command Line +#### Signing legacy versions of Electron -```sh -electron-osx-sign app [embedded-binary ...] [options ...] +`@electron/osx-sign` maintains backwards compatibility with older versions of Electron, but +generally assumes that you are on the latest stable version. + +If you are running an older unsupported version of Electron, you should pass in the `version` +option as such: + +```javascript +signAsync({ + app: 'path/to/my.app', + version: '0.34.0', +}); ``` -##### Examples +## Flat installer packaging -Since `electron-osx-sign` adds the entry `com.apple.developer.team-identifier` to a temporary copy of the specified entitlements file (with the default option `--pre-auto-entitlements`) distribution builds can no longer be run directly. To run the app codesigned for distribution locally after codesigning, you may manually add `ElectronTeamID` in your `Info.plist` and `com.apple.security.application-groups` in the entitlements file, and provide the flag `--no-pre-auto-entitlements` for `electron-osx-sign` to avoid this extra bit. Note that "certain features are only allowed across apps whose team-identifier value match" ([Technical Note TN2415](https://developer.apple.com/library/content/technotes/tn2415/_index.html#//apple_ref/doc/uid/DTS40016427-CH1-ENTITLEMENTSLIST)). +This module also handles the creation of flat installer packages (`.pkg` installers). -The examples below assume that `--pre-auto-entitlements` is enabled. +> [!NOTE] +> Modern `.pkg` installers are also named "flat" packages for historical purposes. Prior +> to Mac OS X Leopard (10.5), installation packages were organized in hierarchical +> directories. OS X Leopard introduced a new flat package format that is used for modern +> `.pkg` installers. -- To sign a distribution version by default: - ```sh - electron-osx-sign path/to/my.app - ``` - For distribution in the Mac App Store: Have the provisioning profile for distribution placed in the current working directory and the signing identity installed in the default keychain. *The app is not expected to run after codesigning since there is no provisioned device, and it is intended only for submission to iTunes Connect.* - For distribution outside the Mac App Store: Have the signing identity for distribution installed in the default keychain and optionally place the provisioning profile in the current working directory. By default App Sandbox is not enabled. *The app should run on all devices.* - -- To sign development version: - ```sh - electron-osx-sign path/to/my.app --type=development - ``` - For testing Mac App Store builds: Have the provisioning profile for development placed in the current working directory and the signing identity installed in the default keychain. *The app will only run on provisioned devices.* - For testing apps for distribution outside the Mac App Store, have the signing identity for development installed in the default keychain and optionally the provisioning profile placed in the current working directory. *The app will only run on provisioned devices.* However, you may prefer to just go with signing a distribution version because the app is expected to launch properly after codesigned. - -- It is recommended to place the provisioning profile(s) under the working directory for `electron-osx-sign` to pick up automatically; however, to specify provisioning profile to be embedded explicitly: - ```sh - electron-osx-sign path/to/my.app --provisioning-profile=path/to/my.provisionprofile - ``` - -- To specify custom entitlements files you have to use the JS API. - -- It is recommended to make use of `--version` while signing legacy versions of Electron: - ```sh - electron-osx-sign path/to/my.app --version=0.34.0 - ``` - -Run `electron-osx-sign --help` or see [electron-osx-sign-usage.txt](https://github.com/electron/osx-sign/blob/main/bin/electron-osx-sign-usage.txt) for CLI-specific options. - -### electron-osx-flat - -#### From the API +### API usage ```javascript const { flatAsync } = require('@electron/osx-sign') @@ -228,76 +191,44 @@ flatAsync({ }) ``` -###### opts - Options +The only mandatory option for `flatAsync` is a path to your `.app` package. +For full configuration options, see the [API documentation]. -**Required** +## CLI -`app` - *String* - -Path to the application bundle. -Needs file extension `.app`. - -**Optional** - -`identity` - *String* - -Name of certificate to use when signing. -Default to be selected with respect to `platform` from `keychain` or keychain by system default. - -Flattening platform `mas` will look for `3rd Party Mac Developer Installer: * (*)`, and platform `darwin` will look for `Developer ID Installer: * (*)` by default. - -`identityValidation` - *Boolean* - -Flag to enable/disable validation for signing identity. If enabled, the `identity` provided will be validated in the `keychain` specified. -Default to `true`. - -`install` - *String* - -Path to install the bundle. -Default to `/Applications`. - -`keychain` - *String* - -The keychain name. -Default to system default keychain. - -`platform` - *String* - -Build platform of Electron. Allowed values: `darwin`, `mas`. -Default to auto detect by presence of `Squirrel.framework` within the application bundle. - -`pkg` - *String* - -Path to the output the flattened package. -Needs file extension `.pkg`. - -`scripts` - *String* -Path to a directory containing pre and/or post install scripts. -#### From the Command Line +`@electron/osx-sign` also exposes a legacy command-line interface (CLI) for both signing +and installer generation. However, we recommend using the JavaScript API as it has a more +complete API surface (e.g. `optionsForFile` is only available via JS). ```sh -electron-osx-flat app [options ...] +# install the package locally into devDependencies +npm install --save-dev @electron/osx-sign + +# Sign a packaged .app bundle +npx electron-osx-sign path/to/my.app [options ...] + +# Create a .pkg installer from a packaged .app bundle +npx electron-osx-flat path/to/my.app [options ...] ``` -Example: +For full options, use the `--help` flag for either command. -```sh -electron-osx-flat path/to/my.app -``` - -Run `electron-osx-flat --help` or see [electron-osx-flat-usage.txt](https://github.com/electron/osx-sign/blob/main/bin/electron-osx-flat-usage.txt) for CLI-specific options. ## Debug -As of release v0.3.1, external module `debug` is used to display logs and messages; remember to `export DEBUG=electron-osx-sign*` when necessary. +The [`debug`](https://www.npmjs.com/package/debug) module is used to display advanced logs and messages. +If you are having problems with signing your app with `@electron/osx-sign`, run your signing scripts with +the `DEBUG=electron-osx-sign*` environment variable. ## Test The project's configured to run automated tests on CircleCI. -If you wish to manually test the module, first comment out `opts.identity` in `test/basic.js` to enable auto discovery. Then run the command `npm test` from the dev directory. +If you wish to manually test the module, first comment out `opts.identity` in `test/basic.js` to enable +auto discovery. Then run the command `npm test` from the dev directory. -When this command is run for the first time: `@electron/get` will download macOS Electron releases defined in `test/config.json`, and save to `~/.electron/`, which might take up less than 1GB of disk space. +When this command is run for the first time: `@electron/get` will download macOS Electron releases defined +in `test/config.json`, and save to `~/.electron/`, which might take up less than 1GB of disk space. A successful testing should look something like: diff --git a/package.json b/package.json index be9d542..cdb0e55 100644 --- a/package.json +++ b/package.json @@ -55,10 +55,12 @@ "run-waterfall": "^1.1.7", "standard": "^17.0.0", "tape": "^4.7.1", + "typedoc": "~0.25.13", "typescript": "^4.9.3" }, "scripts": { "build": "tsc && tsc -p tsconfig.esm.json", + "docs:build": "npx typedoc", "lint": "eslint --ext .ts,.js src bin test", "pretest": "rimraf test/work", "test": "yarn lint && tape test", diff --git a/src/flat.ts b/src/flat.ts index 643ce30..c057da1 100644 --- a/src/flat.ts +++ b/src/flat.ts @@ -67,7 +67,10 @@ async function buildApplicationPkg (opts: ValidatedFlatOptions, identity: Identi } /** - * This function is exported and returns a promise flattening the application. + * Generates a flat `.pkg` installer for a packaged Electron `.app` bundle. + * @returns A void Promise once the flattening operation is complete. + * + * @category Flat */ export async function buildPkg (_opts: FlatOptions) { debugLog('@electron/osx-sign@%s', pkgVersion); @@ -139,7 +142,8 @@ export async function buildPkg (_opts: FlatOptions) { /** * This function is exported with normal callback implementation. * - * @deprecated Please use the promise based "buildPkg" method + * @deprecated Please use the Promise-based {@link flatAsync} method instead. + * @category Flat */ export const flat = (opts: FlatOptions, cb?: (error?: Error) => void) => { buildPkg(opts) diff --git a/src/sign.ts b/src/sign.ts index 5fc59f4..576ac6e 100644 --- a/src/sign.ts +++ b/src/sign.ts @@ -316,7 +316,10 @@ async function signApplication (opts: ValidatedSignOptions, identity: Identity) } /** - * This function returns a promise signing the application. + * Signs a macOS application. + * @returns A void Promise once the signing operation is complete. + * + * @category Codesign */ export async function signApp (_opts: SignOptions) { debugLog('electron-osx-sign@%s', pkgVersion); @@ -420,7 +423,8 @@ export async function signApp (_opts: SignOptions) { /** * This function is a legacy callback implementation. * - * @deprecated Please use the promise based "signApp" method + * @deprecated Please use the Promise-based {@link signAsync} method instead. + * @category Codesign */ export const sign = (opts: SignOptions, cb?: (error?: Error) => void) => { signApp(opts) diff --git a/src/types.ts b/src/types.ts index 2ac9450..7db6041 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,11 +1,52 @@ +/** + * macOS applications can be distributed via the Mac App Store (MAS) or directly + * downloaded from the developer's website. @electron/osx-sign distinguishes between + * MAS apps (`mas`) or non-MAS apps (`darwin`). + * @category Utility + */ export type ElectronMacPlatform = 'darwin' | 'mas'; -type SigningDistributionType = 'development' | 'distribution'; +/** + * MAS apps can be signed using Development or Distribution certificates. + + * See [Apple Documentation](https://developer.apple.com/help/account/create-certificates/certificates-overview/) for more info. + * @category Utility + */ +export type SigningDistributionType = 'development' | 'distribution'; + +/** + * @interface + * @internal + */ export type BaseSignOptions = Readonly<{ + /** + * Path to the application package. + * Needs to end with the file extension `.app`. + */ app: string; - identity?: string; - platform?: ElectronMacPlatform; + /** + * The keychain name. + * + * @defaultValue `login` + */ keychain?: string; + /** + * Build platform of your Electron app. + * Allowed values: `darwin` (Direct Download App), `mas` (Mac App Store). + * + * @defaultValue Determined by presence of `Squirrel.framework` within the application bundle, + * which is used for non-MAS apps. + */ + platform?: ElectronMacPlatform; + /** + * Name of the certificate to use when signing. + * + * @defaultValue Selected with respect to {@link SignOptions.provisioningProfile | provisioningProfile} + * and {@link SignOptions.platform | platform} from the selected {@link SignOptions.keychain | keychain}. + * * `mas` will look for `3rd Party Mac Developer Application: * (*)` + * * `darwin` will look for `Developer ID Application: * (*)` by default. + */ + identity?: string; }>; type OnlyValidatedBaseSignOptions = { @@ -13,53 +54,139 @@ type OnlyValidatedBaseSignOptions = { }; /** - * Any missing options will use the default values, providing a partial - * structure will shallow merge with the default values. + * A set of signing options that can be overriden on a per-file basis. + * Any missing options will use the default values, and providing a partial structure + * will shallow merge with the default values. + * @interface + * @category Codesign */ export type PerFileSignOptions = { /** - * The entitlements file to use when signing this file + * String specifying the path to an `entitlements.plist` file. + * Can also be an array of entitlement keys that osx-sign will write to an entitlements file for you. + * + * @defaultValue `@electron/osx-sign`'s built-in entitlements files. */ entitlements?: string | string[]; /** - * Whether to enable hardened runtime for this file. Enabled by default. + * Whether to enable [Hardened Runtime](https://developer.apple.com/documentation/security/hardened_runtime) + * for this file. + * + * Note: Hardened Runtime is a pre-requisite for notarization, which is mandatory for apps running on macOS 10.15 and above. + * + * @defaultValue `true` */ hardenedRuntime?: boolean; /** - * The designated requirements to embed when signing this file. Expects a path to a text file, - * or a string beginning with "=" specifying requirements in plain text + * Either a string beginning with `=` which specifies in plain text the + * [signing requirements](https://developer.apple.com/library/mac/documentation/Security/Conceptual/CodeSigningGuide/RequirementLang/RequirementLang.html) + * that you recommend to be used to evaluate the code signature, or a string specifying a path to a text or + * properly encoded `.rqset` file which contains those requirements. */ requirements?: string; /** - * See --options of the "codesign" command. + * When signing, a set of option flags can be specified to change the behavior of the system when using the signed code. + * Accepts an array of strings or a comma-separated string. * - * https://www.manpagez.com/man/1/codesign + * See --options of the `codesign` command. + * + * https://keith.github.io/xcode-man-pages/codesign.1.html#OPTION_FLAGS */ signatureFlags?: string | string[]; /** - * The timestamp server to use when signing, by default uses the Apple provided - * timestamp server. + * String specifying the URL of the timestamp authority server. + * Please note that this default server may not support signatures not furnished by Apple. + * Disable the timestamp service with `none`. + * + * @defaultValue Uses the Apple-provided timestamp server. */ timestamp?: string; /** - * Additional raw arguments to pass to the "codesign" command. + * Additional raw arguments to pass to the `codesign` command. * - * These can be things like "--deep" for instance when code signing specific resources that may + * These can be things like `--deep` for instance when code signing specific resources that may * require such arguments. + * + * https://keith.github.io/xcode-man-pages/codesign.1.html#OPTIONS */ additionalArguments?: string[]; -} +}; -type OnlySignOptions = { +/** + * @interface + * @internal + */ +export type OnlySignOptions = { + /** + * Array of paths to additional binaries that will be signed along with built-ins of Electron. + * + * @defaultValue `undefined` + */ binaries?: string[]; + /** + * Function that receives the path to a file and can return the entitlements to use for that file to override the default behavior. The + * object this function returns can include any of the following optional keys. Any properties that are returned **override** the default + * values that `@electron/osx-sign` generates. Any properties not returned use the default value. + * + * @param filePath Path to file + * @returns Override signing options + */ optionsForFile?: (filePath: string) => PerFileSignOptions; + /** + * Flag to enable/disable validation for the signing identity. + * If enabled, the {@link SignOptions.identity | identity} provided + * will be validated in the {@link BaseSignOptions.keychain | keychain} specified. + * + * @defaultValue `true` + */ identityValidation?: boolean; + /** + * Defines files that will be skipped during the code signing process. + * This property accepts a regex, function or an array of regexes and functions. + * Elements of other types are treated as `RegExp`. + * + * File paths matching a regex or returning a `true` value from a function will be ignored. + * + * @defaultValue `undefined` + */ ignore?: string | string[] | ((file: string) => boolean); + /** + * Flag to enable/disable entitlements automation tasks necessary for code signing most Electron apps. + * * Adds [`com.apple.security.application-groups`](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_application-groups) to the entitlements file + * * Fills in the `ElectronTeamID` property in `Info.plist` with the provisioning profile's Team Identifier or by parsing the identity name. + * + * @defaultValue `true` + */ preAutoEntitlements?: boolean; + /** + * Flag to enable/disable the embedding of a provisioning profile into the app's `Contents` folder. + * Will use the profile from {@link OnlySignOptions.provisioningProfile} if provided. Otherwise, it + * searches for a `.provisionprofile` file in the current working directory. + * + * @defaultValue `true` + */ preEmbedProvisioningProfile?: boolean; + /** + * Path to a provisioning profile, which can be used to grant restricted entitlements to your app. + * + * See [Apple Documentation](https://developer.apple.com/documentation/technotes/tn3125-inside-code-signing-provisioning-profiles) for more details. + */ provisioningProfile?: string; + /** + * Flag to enable/disable the `--strict` flag when verifying the signed application bundle. + * + * @defaultValue `true` + */ strictVerify?: boolean; + /** + * Type of certificate to use when signing a MAS app. + * @defaultValue `"distribution"` + */ type?: SigningDistributionType; + /** + * Build version of Electron. Values may be like: `1.1.1`, `1.2.0`. For use for signing legacy versions + * of Electron to ensure backwards compatibility. + */ version?: string; }; @@ -69,9 +196,31 @@ type OnlyValidatedSignOptions = { }; type OnlyFlatOptions = { + /** + * Flag to enable/disable validation for the signing identity. + * If enabled, the {@link BaseSignOptions.identity | identity} provided + * will be validated in the {@link BaseSignOptions.keychain | keychain} specified. + * + * @defaultValue `true` + */ identityValidation?: boolean; + /** + * Path to install the bundle. + * @defaultValue `"/Applications"` + */ install?: string; + /** + * Output path for the flattened installer package. + * Needs file extension `.pkg`. + * + * @defaultValue Inferred from the app name passed into `opts.app`. + */ pkg?: string; + /** + * Path to a directory containing `preinstall.sh` or `postinstall.sh` scripts. + * These must be executable and will run on pre/postinstall depending on the file + * name. + */ scripts?: string; }; @@ -80,12 +229,46 @@ type OnlyValidatedFlatOptions = { pkg: string; }; +/** + * Utility type that represents an `UnValidated` type after validation, + * replacing any properties in the unvalidated type that also exist in the + * `Validated` type with the validated versions. + * + * @template UnValidated - The type representing the unvalidated form. + * @template Validated - The type representing the validated form. + */ type ValidatedForm = Omit & Validated; -export type ValidatedBaseSignOptions = Readonly>; -export type SignOptions = Readonly; -export type ValidatedSignOptions = Readonly & - ValidatedBaseSignOptions>; -export type FlatOptions = Readonly; -export type ValidatedFlatOptions = Readonly & - ValidatedBaseSignOptions>; +type ValidatedBaseSignOptions = Readonly< + ValidatedForm +>; + +type _SignOptions = Readonly; + +/** + * Options for codesigning a packaged `.app` bundle. + * @category Codesign + */ +export interface SignOptions extends _SignOptions {} + +/** + * @internal + */ +export type ValidatedSignOptions = Readonly< + ValidatedForm & ValidatedBaseSignOptions +>; + +type _FlatOptions = Readonly; + +/** + * Options for creating a flat `.pkg` installer. + * @category Flat + */ +export interface FlatOptions extends _FlatOptions {} + +/** + * @internal + */ +export type ValidatedFlatOptions = Readonly< + ValidatedForm & ValidatedBaseSignOptions +>; diff --git a/src/util.ts b/src/util.ts index 9a7e5c4..00dc1c8 100644 --- a/src/util.ts +++ b/src/util.ts @@ -131,6 +131,7 @@ export async function validateOptsPlatform (opts: BaseSignOptions): Promise { debugLog('Walking... ' + dirPath); diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 0000000..efe08e7 --- /dev/null +++ b/typedoc.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "entryPoints": ["./src/index.ts"], + "excludeInternal": true, + "navigation": true, + "categoryOrder": ["Codesign", "Flat", "Utility"] +} diff --git a/yarn.lock b/yarn.lock index 02b3a4b..52cbfb7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -280,6 +280,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-sequence-parser@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz#e0aa1cdcbc8f8bb0b5bca625aac41f5f056973cf" + integrity sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg== + ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -372,6 +377,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + braces@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" @@ -1530,6 +1542,11 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" +jsonc-parser@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" + integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -1619,6 +1636,16 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + +marked@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" + integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== + matcher@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/matcher/-/matcher-3.0.0.tgz#bd9060f4c5b70aa8041ccc6f80368760994f30ca" @@ -1656,6 +1683,13 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^9.0.3: + version "9.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.6, minimist@~1.2.6: version "1.2.7" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" @@ -2113,6 +2147,16 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shiki@^0.14.7: + version "0.14.7" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.7.tgz#c3c9e1853e9737845f1d2ef81b31bcfb07056d4e" + integrity sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg== + dependencies: + ansi-sequence-parser "^1.1.0" + jsonc-parser "^3.2.0" + vscode-oniguruma "^1.7.0" + vscode-textmate "^8.0.0" + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -2331,6 +2375,16 @@ type-fest@^0.3.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== +typedoc@~0.25.13: + version "0.25.13" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.25.13.tgz#9a98819e3b2d155a6d78589b46fa4c03768f0922" + integrity sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ== + dependencies: + lunr "^2.3.9" + marked "^4.3.0" + minimatch "^9.0.3" + shiki "^0.14.7" + typescript@^4.9.3: version "4.9.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.3.tgz#3aea307c1746b8c384435d8ac36b8a2e580d85db" @@ -2373,6 +2427,16 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +vscode-oniguruma@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b" + integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA== + +vscode-textmate@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d" + integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg== + which-boxed-primitive@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"