diff --git a/README.md b/README.md index 6190b68..4f795c6 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,13 @@ This is the Node.js 24+ CommonJS modernization of the original `appdmg` library. The first stage keeps the JSON format and the EventEmitter API while moving the maintained package under the `@appdmg` npm scope. +Related package: + +- `@appdmg/cli` provides the `appdmg-cli` command-line executable. + +See [docs/node24-migration.md](docs/node24-migration.md) for the v1.0.0 +migration and release notes. + ## Installation ```sh @@ -64,6 +71,22 @@ const { appdmg, schema, AppDmgError } = require('@appdmg/appdmg') runtime validation is intentionally limited to basic data type and required field checks in this stage. +The schema can also be loaded directly: + +```javascript +const schema = require('@appdmg/appdmg/schema.json') +``` + +## Migration Notes + +The old unscoped package is not reused for the Node.js 24 release. Install +`@appdmg/appdmg` for library usage and `@appdmg/cli` for the executable. + +The library keeps the `appdmg(options)` EventEmitter contract and still parses +the existing JSON specification format, including legacy conversion. The first +intentional breaks are package naming, the Node.js `>=24` runtime floor, and +the separate CLI package. + ## JSON Specification Paths are resolved relative to the JSON file path, or relative to `basepath` diff --git a/docs/node24-migration.md b/docs/node24-migration.md new file mode 100644 index 0000000..fe90a9d --- /dev/null +++ b/docs/node24-migration.md @@ -0,0 +1,175 @@ +# Node.js 24 migration and v1.0.0 release notes + +This document records the first-stage modernization contract for the appdmg +Node.js 24 release. It is written for maintainers and package consumers who are +moving from the original unscoped `appdmg` package to the appdmg-owned scoped +packages. + +## Package names + +The maintained packages now live under the `@appdmg` npm scope. + +| Old surface | New surface | Notes | +| --- | --- | --- | +| `appdmg` package | `@appdmg/appdmg` | Library package. Owns JSON parsing and DMG generation. | +| `appdmg` executable | `appdmg-cli` from `@appdmg/cli` | No `appdmg` compatibility alias is provided. | +| helper packages from old dependency tree | `@appdmg/*` helper packages where needed | Helpers are scoped only when appdmg needs release control. | + +The v1.0.0 line intentionally starts a new dependency tree. It does not try to +publish compatibility bridge packages for unscoped names that the appdmg +organization does not control. + +## Runtime and module format + +- Node.js `>=24` is required. +- CommonJS remains the module format for this stage. +- Packages should install on non-Darwin platforms when dependencies allow it. +- Actual DMG creation remains Darwin-only because it calls macOS tools such as + `hdiutil`, `tiffutil`, `bless`, and optionally `codesign`. + +On non-Darwin platforms, `@appdmg/appdmg` fails early with +`APPDMG_UNSUPPORTED_PLATFORM` before trying to create a disk image. + +## CLI migration + +Install the CLI package: + +```sh +npm install --global @appdmg/cli +``` + +Run the new executable: + +```sh +appdmg-cli +``` + +The positional argument contract is unchanged: the first argument is the JSON +specification path and the second argument is the output DMG path. + +Output behavior is intentionally strict: + +- stdout remains empty; +- human-readable output goes to stderr; +- `--quiet` suppresses progress, success, and error output, so the exit code is + the only result signal; +- `--verbose` prints detailed diagnostics on failure and wins over `--quiet`; +- `--help` and `--version` are supported. + +`@appdmg/cli` depends on `@appdmg/appdmg` with an exact version. The CLI is a +thin wrapper and does not own JSON parsing or schema behavior. + +## Library migration + +Install the library package: + +```sh +npm install @appdmg/appdmg +``` + +The primary API remains the `appdmg(options)` function returning an +EventEmitter: + +```js +const appdmg = require('@appdmg/appdmg') + +const image = appdmg({ + source: 'appdmg.json', + target: 'Example.dmg' +}) + +image.on('progress', (info) => {}) +image.on('finish', () => {}) +image.on('error', (err) => {}) +``` + +Named exports are also available: + +```js +const { appdmg, schema, AppDmgError } = require('@appdmg/appdmg') +``` + +The following public behavior is preserved: + +- `appdmg({ source, target })`; +- `appdmg({ basepath, specification, target })`; +- `progress`, `finish`, and `error` events; +- progress payload fields `type`, `current`, `total`, `title`, and `status`; +- existing JSON specification format; +- legacy JSON conversion. + +Exact progress step count, step titles, and internal step order are not public +compatibility guarantees. + +## JSON schema and validation + +`@appdmg/appdmg` exports the JSON Schema as public API: + +```js +const schema = require('@appdmg/appdmg/schema.json') +``` + +The schema dialect is JSON Schema 2020-12. + +Runtime validation is deliberately smaller than full JSON Schema validation in +v1.0.0. The library performs minimum operational checks so failures happen +early and produce stable errors: + +- required operational fields; +- basic data types; +- non-empty required strings; +- NUL-byte rejection for strings; +- array and object shape checks needed by the DMG pipeline. + +The first stage does not add a runtime schema validator such as Ajv and does not +invent arbitrary maximum string lengths without macOS API evidence. + +## Error codes + +Appdmg-owned failures use stable `.code` values. + +Current public codes: + +- `APPDMG_INVALID_OPTIONS` +- `APPDMG_UNSUPPORTED_PLATFORM` +- `APPDMG_SOURCE_NOT_FOUND` +- `APPDMG_INVALID_JSON` +- `APPDMG_INVALID_SPEC` +- `APPDMG_TARGET_EXISTS` +- `APPDMG_FILE_NOT_FOUND` +- `APPDMG_COMMAND_FAILED` + +Command failures are wrapped as `APPDMG_COMMAND_FAILED` and include structured +details for the command, arguments, exit code, stdout, and stderr when +available. + +## Dependency and release status + +The package rewrite removes old utility dependencies where Node.js 24 provides +the behavior directly, including callback orchestration, temporary directory +helpers, simple path-existence helpers, and CLI argument parsing. + +The scoped release chain is: + +1. `@appdmg/bplist-creator` +2. `@appdmg/tn1150` +3. `@appdmg/macos-alias` +4. `@appdmg/ds-store` +5. `@appdmg/appdmg` +6. `@appdmg/cli` + +Before publishing the final CLI to npm, verify that each scoped helper package +is available from npm at the intended version and that a clean install of +`@appdmg/cli` resolves only npm-published artifacts. + +## Test coverage + +The rewrite is backed by AVA tests. + +Cross-platform unit tests cover option parsing, JSON parsing, legacy +conversion, minimum validation, stable errors, EventEmitter behavior, CLI +argument handling, quiet/verbose output, and non-Darwin fail-fast behavior. + +macOS integration tests create real DMGs with `hdiutil`, mount them, inspect +their contents and Finder metadata files, and detach them. This replaces the +old default screenshot-comparison path for release confidence. diff --git a/packages/cli/README.md b/packages/cli/README.md index 8376ed5..3cc3907 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -2,6 +2,13 @@ Command line interface for `@appdmg/appdmg`. +This package provides the Node.js 24+ replacement command for the original +unscoped `appdmg` executable. The command is intentionally named +`appdmg-cli`; there is no `appdmg` compatibility alias. + +See [../../docs/node24-migration.md](../../docs/node24-migration.md) for the +v1.0.0 migration and release notes. + ## Installation ```sh @@ -20,9 +27,24 @@ appdmg-cli The command writes human-readable output to stderr and writes nothing to stdout in this first stage. +DMG creation is supported on Darwin only. On other platforms the CLI can be +installed and argument parsing can run, but generation exits with the library +platform error before calling macOS tools. + ## Options - `--help`: print usage - `--version`: print the CLI package version -- `--quiet`: suppress progress, success, and error output -- `--verbose`, `-v`: print verbose diagnostics; this wins over `--quiet` +- `--quiet`: suppress progress, success, and error output; the exit code is the + only result signal +- `--verbose`, `-v`: print verbose diagnostics; this wins over `--quiet` on + failures + +All user-facing output goes to stderr. stdout is reserved and remains empty. + +## Library Dependency + +`@appdmg/cli` depends on `@appdmg/appdmg` with an exact version. The CLI does +not parse the JSON specification itself; it passes `{ source, target }` to the +library so JSON loading, legacy conversion, schema ownership, validation, +events, and DMG generation stay in one public API.