@octoberswimmer/aer-sf-plugin 0.0.1 → 0.0.3

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
@@ -20,9 +20,10 @@ copy.
20
20
  ## Requirements
21
21
 
22
22
  - [Salesforce CLI](https://developer.salesforce.com/tools/salesforcecli) (`sf`)
23
- - [aer](https://github.com/octoberswimmer/aer-dist) on `PATH` (or set
24
- `AER_BIN=/abs/path/to/aer`)
25
23
  - Node.js >= 18
24
+ - [aer](https://github.com/octoberswimmer/aer-dist) — the plugin will offer to
25
+ download the right build for your platform on first use if it can't find one
26
+ already (see [Locating the aer binary](#locating-the-aer-binary) below).
26
27
 
27
28
  ## Install
28
29
 
@@ -64,6 +65,44 @@ With code coverage:
64
65
  sf aer apex run test --code-coverage --output-dir test-results
65
66
  ```
66
67
 
68
+ ## Locating the aer binary
69
+
70
+ When the plugin needs to invoke `aer`, it tries these sources in order:
71
+
72
+ 1. The `AER_BIN` environment variable, when it points to an executable file.
73
+ 2. A copy previously downloaded by this plugin, stored under a platform-specific
74
+ data directory:
75
+ - Linux: `$XDG_DATA_HOME/aer-sf-plugin/aer-bin/` (default
76
+ `~/.local/share/aer-sf-plugin/aer-bin/`)
77
+ - macOS: `~/Library/Application Support/aer-sf-plugin/aer-bin/`
78
+ - Windows: `%LOCALAPPDATA%\aer-sf-plugin\aer-bin\`
79
+ 3. `aer` discovered on `PATH`.
80
+ 4. If none of the above match and the terminal is interactive, the plugin asks
81
+ for confirmation, then downloads the latest
82
+ [aer-dist](https://github.com/octoberswimmer/aer-dist) release for your
83
+ platform, extracts it into the data directory above, and uses it for that
84
+ run and all later runs.
85
+
86
+ ### Update checks
87
+
88
+ Once the plugin has downloaded its own copy of `aer`, each subsequent run starts
89
+ a background GitHub query (rate-limited to one check every 12 hours) to see
90
+ whether a newer release has been published. The query runs in parallel with
91
+ staging and the test execution, so it does not slow tests down. After the test
92
+ run finishes, if a newer release is available you'll be prompted to install it.
93
+ Decline and the same version won't be re-offered until something newer ships.
94
+
95
+ The check is skipped entirely when:
96
+
97
+ - `AER_BIN` is set or `aer` is on `PATH` (i.e. the user manages their own copy).
98
+ - The terminal is non-interactive (`--json`, no TTY).
99
+
100
+ To force an update outside the 12-hour window, delete the contents of the
101
+ `aer-bin/` directory (or the whole `aer-sf-plugin/` directory) and rerun.
102
+
103
+ In non-interactive environments (CI, `--json`) the plugin will not prompt; set
104
+ `AER_BIN` or install `aer` on `PATH` ahead of time.
105
+
67
106
  ## How source is staged
68
107
 
69
108
  The plugin copies the project's Apex source into a temp directory before
package/lib/aer.d.ts CHANGED
@@ -8,5 +8,4 @@ export type AerInvocation = {
8
8
  verbose: boolean;
9
9
  };
10
10
  export declare function buildAerArgs(inv: AerInvocation): string[];
11
- export declare function aerBinary(): string;
12
- export declare function runAer(args: string[], cwd: string): Promise<number>;
11
+ export declare function runAer(binaryPath: string, args: string[], cwd: string): Promise<number>;
package/lib/aer.js CHANGED
@@ -19,18 +19,21 @@ export function buildAerArgs(inv) {
19
19
  }
20
20
  return args;
21
21
  }
22
- export function aerBinary() {
23
- return process.env.AER_BIN ?? 'aer';
24
- }
25
- export async function runAer(args, cwd) {
22
+ export async function runAer(binaryPath, args, cwd) {
26
23
  return new Promise((resolvePromise, rejectPromise) => {
27
- const child = spawn(aerBinary(), args, {
24
+ const child = spawn(binaryPath, args, {
28
25
  cwd,
29
26
  stdio: 'inherit',
27
+ env: {
28
+ ...process.env,
29
+ // Suppress aer's own version-check notification — the plugin
30
+ // surfaces its own prompt to upgrade.
31
+ AER_AUTOUPDATE_DISABLED: '1',
32
+ },
30
33
  });
31
34
  child.on('error', (err) => {
32
35
  if (err.code === 'ENOENT') {
33
- rejectPromise(new Error(`Could not find the 'aer' binary on PATH. Install aer from https://github.com/octoberswimmer/aer-dist or set AER_BIN to its absolute path.`));
36
+ rejectPromise(new Error(`Could not execute aer at ${binaryPath}. The file may have been moved or deleted.`));
34
37
  return;
35
38
  }
36
39
  rejectPromise(err);
package/lib/aer.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"aer.js","sourceRoot":"","sources":["../src/aer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAa3C,MAAM,UAAU,YAAY,CAAC,GAAkB;IAC9C,MAAM,IAAI,GAAa,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,KAAK,OAAO,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;SAAM,IAAI,GAAG,CAAC,YAAY,KAAK,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QAC1D,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,GAAG,CAAC,YAAY,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;QAC3D,+CAA+C;QAC/C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,UAAU,SAAS;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,KAAK,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc,EAAE,GAAW;IACvD,OAAO,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,aAAa,EAAE,EAAE;QACpD,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE;YACtC,GAAG;YACH,KAAK,EAAE,SAAS;SAChB,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YAChD,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,aAAa,CACZ,IAAI,KAAK,CACR,2IAA2I,CAC3I,CACD,CAAC;gBACF,OAAO;YACR,CAAC;YACD,aAAa,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACjC,IAAI,MAAM,EAAE,CAAC;gBACZ,cAAc,CAAC,GAAG,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjF,CAAC;iBAAM,CAAC;gBACP,cAAc,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;YAC3B,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"aer.js","sourceRoot":"","sources":["../src/aer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAa3C,MAAM,UAAU,YAAY,CAAC,GAAkB;IAC9C,MAAM,IAAI,GAAa,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,KAAK,OAAO,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACpD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACtC,CAAC;SAAM,IAAI,GAAG,CAAC,YAAY,KAAK,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QAC1D,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,GAAG,CAAC,YAAY,KAAK,MAAM,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;QAC3D,+CAA+C;QAC/C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrB,CAAC;IACD,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;IAC3C,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,UAAkB,EAAE,IAAc,EAAE,GAAW;IAC3E,OAAO,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,aAAa,EAAE,EAAE;QACpD,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE;YACrC,GAAG;YACH,KAAK,EAAE,SAAS;YAChB,GAAG,EAAE;gBACJ,GAAG,OAAO,CAAC,GAAG;gBACd,6DAA6D;gBAC7D,sCAAsC;gBACtC,uBAAuB,EAAE,GAAG;aAC5B;SACD,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YAChD,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC3B,aAAa,CACZ,IAAI,KAAK,CACR,4BAA4B,UAAU,4CAA4C,CAClF,CACD,CAAC;gBACF,OAAO;YACR,CAAC;YACD,aAAa,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;YACjC,IAAI,MAAM,EAAE,CAAC;gBACZ,cAAc,CAAC,GAAG,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACjF,CAAC;iBAAM,CAAC;gBACP,cAAc,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC;YAC3B,CAAC;QACF,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,114 @@
1
+ export type ConfirmFn = (message: string) => Promise<boolean>;
2
+ export type LogFn = (message: string) => void;
3
+ export type EnsureAerOptions = {
4
+ /** When false, never prompt — throw if binary cannot be resolved. Defaults to true. */
5
+ allowPrompt?: boolean;
6
+ /** Prompt callback for yes/no confirmation. Required when allowPrompt is true. */
7
+ confirm?: ConfirmFn;
8
+ /** Informational log callback. */
9
+ log?: LogFn;
10
+ /** Warning log callback. */
11
+ warn?: LogFn;
12
+ /** Override the storage directory (for testing). */
13
+ storageDir?: string;
14
+ };
15
+ /**
16
+ * Resolve the aer binary path. Resolution order:
17
+ * 1. AER_BIN env var (must be executable).
18
+ * 2. Previously downloaded copy in the plugin's storage dir.
19
+ * 3. `aer` on PATH.
20
+ * 4. Prompt to download the latest release into the plugin's storage dir.
21
+ */
22
+ export declare function ensureAerBinary(opts?: EnsureAerOptions): Promise<string>;
23
+ /** For tests: forget any cached binary path so the next call re-resolves. */
24
+ export declare function _resetAerBinaryCache(): void;
25
+ /** Module-private internals exposed for tests only. Not part of the public API. */
26
+ export declare const _internals: {
27
+ readonly replaceBinary: typeof replaceBinary;
28
+ };
29
+ /**
30
+ * Default storage directory for binaries downloaded by this plugin. Mirrors the
31
+ * conventions used by `envPaths` / oclif: respects XDG on Linux, Library/Application
32
+ * Support on macOS, and LOCALAPPDATA on Windows.
33
+ */
34
+ export declare function defaultStorageDir(): string;
35
+ /**
36
+ * Install a new binary at `target`, using the same atomic-rename strategy as
37
+ * `aer upgrade` so that an in-use executable (notably on Windows) doesn't
38
+ * cause the install to fail.
39
+ *
40
+ * Unix: write to `.{name}.new`, then rename over the target — atomic.
41
+ * Windows: write to `.{name}.new`, rename existing target to `.{name}.old`,
42
+ * rename `.{name}.new` into place, then best-effort delete `.old`
43
+ * (which may stay around briefly if the file is still held open).
44
+ */
45
+ declare function replaceBinary(binDir: string, binaryName: string, data: Buffer, target: string): Promise<void>;
46
+ export declare function platformDetails(version: string): {
47
+ platformKey: 'linux' | 'darwin' | 'windows';
48
+ cpuKey: 'amd64' | 'arm64';
49
+ binaryName: string;
50
+ archiveName: string;
51
+ };
52
+ export declare function readStoredVersion(storageDir: string): Promise<string | null>;
53
+ export type UpdateState = {
54
+ lastCheck?: number;
55
+ lastPromptVersion?: string;
56
+ };
57
+ export type PendingUpdate = {
58
+ installed: string;
59
+ latest: string;
60
+ };
61
+ export type UpdateCheckOptions = {
62
+ /** Absolute path to the aer binary to query for its --version. */
63
+ aerPath: string;
64
+ storageDir?: string;
65
+ log?: LogFn;
66
+ /** Override the rate-limit interval in ms (default 12h). Useful in tests. */
67
+ intervalMs?: number;
68
+ /** When true, ignore the rate-limit and always perform the GitHub query. */
69
+ force?: boolean;
70
+ /** Inject a clock for testing. */
71
+ now?: () => number;
72
+ /** Override the latest-version resolver (for testing). */
73
+ resolveLatest?: () => Promise<string>;
74
+ /** Override the installed-version resolver (for testing). */
75
+ queryInstalled?: (binaryPath: string) => Promise<string | null>;
76
+ };
77
+ /**
78
+ * Begin a background check for a newer aer release. Resolves with details about
79
+ * an available update, or null when no upgrade is needed for any of the following
80
+ * reasons: the rate-limit window hasn't elapsed since the last check, the binary
81
+ * couldn't be queried for its version, the latest tag matches what's installed,
82
+ * the user was already prompted for this version, or the network call failed
83
+ * (logged but not re-thrown).
84
+ *
85
+ * The installed version is read by running `<aerPath> --version` rather than
86
+ * trusting any cached VERSION file — that way the check survives upgrades
87
+ * performed outside the plugin (e.g. by `aer upgrade`) and also works for users
88
+ * who installed aer themselves on PATH.
89
+ *
90
+ * The lastCheck timestamp is persisted as soon as the GitHub query runs, so
91
+ * we don't query repeatedly even if no update is found. The lastPromptVersion
92
+ * is NOT persisted here — callers must invoke `recordPromptedVersion` once
93
+ * they've actually surfaced the prompt to the user.
94
+ */
95
+ export declare function checkForUpdate(opts: UpdateCheckOptions): Promise<PendingUpdate | null>;
96
+ /**
97
+ * Run the given aer binary with `--version` and parse the reported version.
98
+ * Returns null if the binary doesn't run, doesn't print recognizable output,
99
+ * or takes too long.
100
+ */
101
+ export declare function queryBinaryVersion(binaryPath: string): Promise<string | null>;
102
+ /**
103
+ * Persist that the user has been prompted about a version, so subsequent
104
+ * commands don't repeat the prompt for that same version.
105
+ */
106
+ export declare function recordPromptedVersion(version: string, opts?: {
107
+ storageDir?: string;
108
+ }): Promise<void>;
109
+ /** Download and install a specific aer version into the plugin's storage dir. */
110
+ export declare function installAerVersion(version: string, opts?: {
111
+ storageDir?: string;
112
+ log?: LogFn;
113
+ }): Promise<string>;
114
+ export {};
@@ -0,0 +1,510 @@
1
+ import { chmod, mkdir, mkdtemp, readFile, rename, rm, stat, writeFile, access } from 'node:fs/promises';
2
+ import { constants as fsConstants, createWriteStream } from 'node:fs';
3
+ import { spawn } from 'node:child_process';
4
+ import { delimiter, join, resolve } from 'node:path';
5
+ import { homedir, tmpdir } from 'node:os';
6
+ import { get as httpsGet } from 'node:https';
7
+ import AdmZip from 'adm-zip';
8
+ const REPO = 'octoberswimmer/aer-dist';
9
+ const BINARY_NAME = process.platform === 'win32' ? 'aer.exe' : 'aer';
10
+ const VERSION_FILE = 'VERSION';
11
+ const PLUGIN_DIR_NAME = 'aer-sf-plugin';
12
+ const BIN_SUBDIR = 'aer-bin';
13
+ const UPDATE_STATE_FILE = 'update-check.json';
14
+ const UPDATE_CHECK_INTERVAL_MS = 1000 * 60 * 60 * 12; // 12 hours
15
+ let cachedAerPath = null;
16
+ let resolving = null;
17
+ /**
18
+ * Resolve the aer binary path. Resolution order:
19
+ * 1. AER_BIN env var (must be executable).
20
+ * 2. Previously downloaded copy in the plugin's storage dir.
21
+ * 3. `aer` on PATH.
22
+ * 4. Prompt to download the latest release into the plugin's storage dir.
23
+ */
24
+ export async function ensureAerBinary(opts = {}) {
25
+ if (resolving) {
26
+ return resolving;
27
+ }
28
+ const log = opts.log ?? (() => { });
29
+ const warn = opts.warn ?? (() => { });
30
+ const allowPrompt = opts.allowPrompt ?? true;
31
+ const storageDir = opts.storageDir ?? defaultStorageDir();
32
+ resolving = (async () => {
33
+ const envBin = process.env.AER_BIN;
34
+ if (envBin) {
35
+ const resolved = await resolveExecutable(envBin);
36
+ if (resolved) {
37
+ cachedAerPath = resolved;
38
+ return resolved;
39
+ }
40
+ warn(`AER_BIN is set to "${envBin}" but the file was not found or is not executable; falling back.`);
41
+ }
42
+ const downloaded = join(storageDir, BIN_SUBDIR, BINARY_NAME);
43
+ if (await isExecutable(downloaded)) {
44
+ cachedAerPath = downloaded;
45
+ return downloaded;
46
+ }
47
+ const fromPath = await resolveExecutable('aer');
48
+ if (fromPath) {
49
+ cachedAerPath = fromPath;
50
+ return fromPath;
51
+ }
52
+ if (cachedAerPath && (await isExecutable(cachedAerPath))) {
53
+ return cachedAerPath;
54
+ }
55
+ if (!allowPrompt || !opts.confirm) {
56
+ throw new Error(`Could not find the 'aer' binary. Install aer from https://github.com/${REPO}, set AER_BIN to its absolute path, or rerun interactively to download it automatically.`);
57
+ }
58
+ const yes = await opts.confirm("aer was not found on PATH. Download the latest release from GitHub?");
59
+ if (!yes) {
60
+ throw new Error(`aer is required but was not installed.`);
61
+ }
62
+ const binPath = await downloadLatest(storageDir, log);
63
+ cachedAerPath = binPath;
64
+ return binPath;
65
+ })().finally(() => {
66
+ resolving = null;
67
+ });
68
+ return resolving;
69
+ }
70
+ /** For tests: forget any cached binary path so the next call re-resolves. */
71
+ export function _resetAerBinaryCache() {
72
+ cachedAerPath = null;
73
+ resolving = null;
74
+ }
75
+ /** Module-private internals exposed for tests only. Not part of the public API. */
76
+ export const _internals = {
77
+ get replaceBinary() {
78
+ return replaceBinary;
79
+ },
80
+ };
81
+ /**
82
+ * Default storage directory for binaries downloaded by this plugin. Mirrors the
83
+ * conventions used by `envPaths` / oclif: respects XDG on Linux, Library/Application
84
+ * Support on macOS, and LOCALAPPDATA on Windows.
85
+ */
86
+ export function defaultStorageDir() {
87
+ const home = homedir();
88
+ switch (process.platform) {
89
+ case 'win32': {
90
+ const base = process.env.LOCALAPPDATA ?? join(home, 'AppData', 'Local');
91
+ return join(base, PLUGIN_DIR_NAME);
92
+ }
93
+ case 'darwin':
94
+ return join(home, 'Library', 'Application Support', PLUGIN_DIR_NAME);
95
+ default: {
96
+ const base = process.env.XDG_DATA_HOME ?? join(home, '.local', 'share');
97
+ return join(base, PLUGIN_DIR_NAME);
98
+ }
99
+ }
100
+ }
101
+ async function downloadLatest(storageDir, log) {
102
+ const version = await resolveLatestVersion();
103
+ log(`Downloading aer ${version}…`);
104
+ return downloadAndExtract(storageDir, version, log);
105
+ }
106
+ async function downloadAndExtract(storageDir, version, log) {
107
+ const { binaryName, archiveName } = platformDetails(version);
108
+ const url = `https://github.com/${REPO}/releases/download/${version}/${archiveName}`;
109
+ const binDir = join(storageDir, BIN_SUBDIR);
110
+ await mkdir(binDir, { recursive: true, mode: 0o755 });
111
+ const tempDir = await mkdtemp(join(tmpdir(), 'aer-download-'));
112
+ const archivePath = join(tempDir, archiveName);
113
+ try {
114
+ log(`Fetching ${url}`);
115
+ await downloadFile(url, archivePath);
116
+ log(`Extracting ${binaryName}…`);
117
+ const data = readBinaryFromArchive(archivePath, binaryName);
118
+ const target = join(binDir, binaryName);
119
+ await replaceBinary(binDir, binaryName, data, target);
120
+ await writeFile(join(binDir, VERSION_FILE), version, 'utf8');
121
+ return target;
122
+ }
123
+ finally {
124
+ await rm(tempDir, { recursive: true, force: true });
125
+ }
126
+ }
127
+ /**
128
+ * Install a new binary at `target`, using the same atomic-rename strategy as
129
+ * `aer upgrade` so that an in-use executable (notably on Windows) doesn't
130
+ * cause the install to fail.
131
+ *
132
+ * Unix: write to `.{name}.new`, then rename over the target — atomic.
133
+ * Windows: write to `.{name}.new`, rename existing target to `.{name}.old`,
134
+ * rename `.{name}.new` into place, then best-effort delete `.old`
135
+ * (which may stay around briefly if the file is still held open).
136
+ */
137
+ async function replaceBinary(binDir, binaryName, data, target) {
138
+ const newPath = join(binDir, `.${binaryName}.new`);
139
+ const oldPath = join(binDir, `.${binaryName}.old`);
140
+ await rm(newPath, { force: true });
141
+ await writeFile(newPath, data, { mode: 0o755 });
142
+ if (process.platform !== 'win32') {
143
+ // writeFile honors `mode` only on file creation; chmod explicitly so
144
+ // a leftover `.new` from a prior failed install still ends up +x.
145
+ await chmod(newPath, 0o755);
146
+ }
147
+ if (process.platform === 'win32') {
148
+ await rm(oldPath, { force: true });
149
+ const targetExists = await pathExists(target);
150
+ if (targetExists) {
151
+ try {
152
+ await rename(target, oldPath);
153
+ }
154
+ catch (err) {
155
+ await rm(newPath, { force: true }).catch(() => { });
156
+ throw new Error(`Failed to move current aer executable aside: ${err.message}`);
157
+ }
158
+ }
159
+ try {
160
+ await rename(newPath, target);
161
+ }
162
+ catch (err) {
163
+ if (targetExists) {
164
+ await rename(oldPath, target).catch(() => { });
165
+ }
166
+ throw new Error(`Failed to move new aer executable into place: ${err.message}`);
167
+ }
168
+ // Best-effort cleanup; on Windows this may fail if the binary is
169
+ // still mapped into a running process. The leftover .old file will
170
+ // be removed by the next install.
171
+ await rm(oldPath, { force: true }).catch(() => { });
172
+ }
173
+ else {
174
+ // rename(2) on Unix atomically replaces the target.
175
+ await rename(newPath, target);
176
+ }
177
+ }
178
+ async function pathExists(filePath) {
179
+ try {
180
+ await stat(filePath);
181
+ return true;
182
+ }
183
+ catch {
184
+ return false;
185
+ }
186
+ }
187
+ export function platformDetails(version) {
188
+ const platformKey = normalizeOS();
189
+ const cpuKey = normalizeArch();
190
+ const binaryName = platformKey === 'windows' ? 'aer.exe' : 'aer';
191
+ const archiveName = `aer_${platformKey}_${cpuKey}_${version}.zip`;
192
+ return { platformKey, cpuKey, binaryName, archiveName };
193
+ }
194
+ function normalizeOS() {
195
+ switch (process.platform) {
196
+ case 'linux':
197
+ return 'linux';
198
+ case 'darwin':
199
+ return 'darwin';
200
+ case 'win32':
201
+ return 'windows';
202
+ default:
203
+ throw new Error(`Unsupported operating system: ${process.platform}`);
204
+ }
205
+ }
206
+ function normalizeArch() {
207
+ switch (process.arch) {
208
+ case 'x64':
209
+ return 'amd64';
210
+ case 'arm64':
211
+ return 'arm64';
212
+ default:
213
+ throw new Error(`Unsupported architecture: ${process.arch}`);
214
+ }
215
+ }
216
+ export async function readStoredVersion(storageDir) {
217
+ try {
218
+ const contents = await readFile(join(storageDir, BIN_SUBDIR, VERSION_FILE), 'utf8');
219
+ return contents.trim() || null;
220
+ }
221
+ catch {
222
+ return null;
223
+ }
224
+ }
225
+ /**
226
+ * Begin a background check for a newer aer release. Resolves with details about
227
+ * an available update, or null when no upgrade is needed for any of the following
228
+ * reasons: the rate-limit window hasn't elapsed since the last check, the binary
229
+ * couldn't be queried for its version, the latest tag matches what's installed,
230
+ * the user was already prompted for this version, or the network call failed
231
+ * (logged but not re-thrown).
232
+ *
233
+ * The installed version is read by running `<aerPath> --version` rather than
234
+ * trusting any cached VERSION file — that way the check survives upgrades
235
+ * performed outside the plugin (e.g. by `aer upgrade`) and also works for users
236
+ * who installed aer themselves on PATH.
237
+ *
238
+ * The lastCheck timestamp is persisted as soon as the GitHub query runs, so
239
+ * we don't query repeatedly even if no update is found. The lastPromptVersion
240
+ * is NOT persisted here — callers must invoke `recordPromptedVersion` once
241
+ * they've actually surfaced the prompt to the user.
242
+ */
243
+ export async function checkForUpdate(opts) {
244
+ const storageDir = opts.storageDir ?? defaultStorageDir();
245
+ const log = opts.log ?? (() => { });
246
+ const intervalMs = opts.intervalMs ?? UPDATE_CHECK_INTERVAL_MS;
247
+ const now = opts.now?.() ?? Date.now();
248
+ const state = await readUpdateState(storageDir);
249
+ if (!opts.force && state.lastCheck && now - state.lastCheck < intervalMs) {
250
+ return null;
251
+ }
252
+ const queryFn = opts.queryInstalled ?? queryBinaryVersion;
253
+ const installed = await queryFn(opts.aerPath);
254
+ if (!installed) {
255
+ log(`aer update check skipped: could not determine installed version from ${opts.aerPath}`);
256
+ return null;
257
+ }
258
+ const resolver = opts.resolveLatest ?? resolveLatestVersion;
259
+ let latest;
260
+ try {
261
+ latest = await resolver();
262
+ }
263
+ catch (err) {
264
+ log(`aer update check failed: ${err.message}`);
265
+ return null;
266
+ }
267
+ await writeUpdateState(storageDir, { ...state, lastCheck: now });
268
+ if (!latest || normalizeVersion(latest) === normalizeVersion(installed)) {
269
+ return null;
270
+ }
271
+ if (state.lastPromptVersion && normalizeVersion(state.lastPromptVersion) === normalizeVersion(latest)) {
272
+ return null;
273
+ }
274
+ return { installed, latest };
275
+ }
276
+ function normalizeVersion(v) {
277
+ const trimmed = v.trim();
278
+ return trimmed.startsWith('v') ? trimmed.slice(1) : trimmed;
279
+ }
280
+ /**
281
+ * Run the given aer binary with `--version` and parse the reported version.
282
+ * Returns null if the binary doesn't run, doesn't print recognizable output,
283
+ * or takes too long.
284
+ */
285
+ export async function queryBinaryVersion(binaryPath) {
286
+ return new Promise((resolvePromise) => {
287
+ let stdout = '';
288
+ let stderr = '';
289
+ let settled = false;
290
+ const finish = (result) => {
291
+ if (settled)
292
+ return;
293
+ settled = true;
294
+ resolvePromise(result);
295
+ };
296
+ let child;
297
+ try {
298
+ child = spawn(binaryPath, ['--version'], {
299
+ stdio: ['ignore', 'pipe', 'pipe'],
300
+ env: { ...process.env, AER_AUTOUPDATE_DISABLED: '1' },
301
+ });
302
+ }
303
+ catch {
304
+ finish(null);
305
+ return;
306
+ }
307
+ const timer = setTimeout(() => {
308
+ child.kill();
309
+ finish(null);
310
+ }, 5000);
311
+ child.stdout?.on('data', (chunk) => {
312
+ stdout += chunk.toString();
313
+ });
314
+ child.stderr?.on('data', (chunk) => {
315
+ stderr += chunk.toString();
316
+ });
317
+ child.on('error', () => {
318
+ clearTimeout(timer);
319
+ finish(null);
320
+ });
321
+ child.on('exit', (code) => {
322
+ clearTimeout(timer);
323
+ if (code !== 0) {
324
+ finish(null);
325
+ return;
326
+ }
327
+ const output = stdout || stderr;
328
+ // Match strings like "v1.0.0-beta.5" or "1.0.0".
329
+ const match = output.match(/v?\d+\.\d+\.\d+(?:[\w.-]+)?/);
330
+ if (!match) {
331
+ finish(null);
332
+ return;
333
+ }
334
+ const raw = match[0];
335
+ finish(raw.startsWith('v') ? raw : `v${raw}`);
336
+ });
337
+ });
338
+ }
339
+ /**
340
+ * Persist that the user has been prompted about a version, so subsequent
341
+ * commands don't repeat the prompt for that same version.
342
+ */
343
+ export async function recordPromptedVersion(version, opts = {}) {
344
+ const storageDir = opts.storageDir ?? defaultStorageDir();
345
+ const state = await readUpdateState(storageDir);
346
+ await writeUpdateState(storageDir, { ...state, lastPromptVersion: version });
347
+ }
348
+ /** Download and install a specific aer version into the plugin's storage dir. */
349
+ export async function installAerVersion(version, opts = {}) {
350
+ const storageDir = opts.storageDir ?? defaultStorageDir();
351
+ const log = opts.log ?? (() => { });
352
+ const newPath = await downloadAndExtract(storageDir, version, log);
353
+ cachedAerPath = newPath;
354
+ return newPath;
355
+ }
356
+ async function readUpdateState(storageDir) {
357
+ try {
358
+ const contents = await readFile(join(storageDir, UPDATE_STATE_FILE), 'utf8');
359
+ const parsed = JSON.parse(contents);
360
+ if (parsed && typeof parsed === 'object') {
361
+ return parsed;
362
+ }
363
+ }
364
+ catch {
365
+ // Missing or corrupt state — treat as empty.
366
+ }
367
+ return {};
368
+ }
369
+ async function writeUpdateState(storageDir, state) {
370
+ await mkdir(storageDir, { recursive: true });
371
+ await writeFile(join(storageDir, UPDATE_STATE_FILE), JSON.stringify(state), 'utf8');
372
+ }
373
+ async function resolveLatestVersion() {
374
+ const latest = await requestJson(`https://api.github.com/repos/${REPO}/releases/latest`);
375
+ if (latest.statusCode === 404) {
376
+ return latestFromList();
377
+ }
378
+ if (latest.statusCode >= 400) {
379
+ throw new Error(`GitHub API returned ${latest.statusCode} while resolving latest aer release.`);
380
+ }
381
+ const tag = latest.body?.tag_name;
382
+ if (!tag) {
383
+ throw new Error('Latest aer release response is missing tag_name.');
384
+ }
385
+ return String(tag);
386
+ }
387
+ async function latestFromList() {
388
+ const res = await requestJson(`https://api.github.com/repos/${REPO}/releases?per_page=10`);
389
+ if (res.statusCode >= 400) {
390
+ throw new Error(`GitHub API returned ${res.statusCode} while listing aer releases.`);
391
+ }
392
+ if (!Array.isArray(res.body)) {
393
+ throw new Error('Unexpected response while listing aer releases.');
394
+ }
395
+ for (const rel of res.body) {
396
+ if (!rel?.draft && rel?.tag_name) {
397
+ return String(rel.tag_name);
398
+ }
399
+ }
400
+ throw new Error('No published aer releases were found.');
401
+ }
402
+ async function resolveExecutable(cmd) {
403
+ if (cmd.includes('/') || cmd.includes('\\')) {
404
+ const candidate = resolve(cmd);
405
+ return (await isExecutable(candidate)) ? candidate : null;
406
+ }
407
+ const pathVar = process.env.PATH ?? '';
408
+ const extensions = process.platform === 'win32' ? ['.exe', '.cmd', '.bat', ''] : [''];
409
+ for (const segment of pathVar.split(delimiter)) {
410
+ if (!segment)
411
+ continue;
412
+ for (const ext of extensions) {
413
+ const candidate = join(segment, cmd + ext);
414
+ if (await isExecutable(candidate)) {
415
+ return candidate;
416
+ }
417
+ }
418
+ }
419
+ return null;
420
+ }
421
+ async function isExecutable(filePath) {
422
+ try {
423
+ const stats = await stat(filePath);
424
+ if (!stats.isFile())
425
+ return false;
426
+ if (process.platform === 'win32')
427
+ return true;
428
+ await access(filePath, fsConstants.X_OK);
429
+ return true;
430
+ }
431
+ catch {
432
+ return false;
433
+ }
434
+ }
435
+ function readBinaryFromArchive(archivePath, binaryName) {
436
+ const zip = new AdmZip(archivePath);
437
+ const entry = zip
438
+ .getEntries()
439
+ .find((e) => !e.isDirectory && e.entryName.replace(/\/$/, '').endsWith(binaryName));
440
+ if (!entry) {
441
+ throw new Error(`${binaryName} was not found inside the downloaded archive.`);
442
+ }
443
+ return entry.getData();
444
+ }
445
+ async function requestJson(url) {
446
+ const res = await httpRequest(url);
447
+ try {
448
+ return { statusCode: res.statusCode, body: JSON.parse(res.text) };
449
+ }
450
+ catch {
451
+ return { statusCode: res.statusCode, body: null };
452
+ }
453
+ }
454
+ async function downloadFile(url, dest) {
455
+ return new Promise((resolvePromise, rejectPromise) => {
456
+ const file = createWriteStream(dest);
457
+ const handle = (currentUrl, redirects) => {
458
+ const req = httpsGet(currentUrl, { headers: requestHeaders() }, (res) => {
459
+ if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
460
+ if (redirects > 5) {
461
+ rejectPromise(new Error('Too many redirects while downloading aer.'));
462
+ return;
463
+ }
464
+ res.resume();
465
+ req.destroy();
466
+ handle(res.headers.location, redirects + 1);
467
+ return;
468
+ }
469
+ if (!res.statusCode || res.statusCode >= 400) {
470
+ file.close();
471
+ rejectPromise(new Error(`Failed to download aer (HTTP ${res.statusCode ?? 'unknown'}).`));
472
+ return;
473
+ }
474
+ res.pipe(file);
475
+ res.on('error', (err) => {
476
+ file.close();
477
+ rejectPromise(err);
478
+ });
479
+ file.on('finish', () => file.close((err) => (err ? rejectPromise(err) : resolvePromise())));
480
+ file.on('error', rejectPromise);
481
+ });
482
+ req.on('error', (err) => {
483
+ file.close();
484
+ rejectPromise(err);
485
+ });
486
+ };
487
+ handle(url, 0);
488
+ });
489
+ }
490
+ async function httpRequest(url) {
491
+ return new Promise((resolvePromise, rejectPromise) => {
492
+ const req = httpsGet(url, { headers: requestHeaders() }, (res) => {
493
+ let data = '';
494
+ res.on('data', (chunk) => {
495
+ data += chunk;
496
+ });
497
+ res.on('end', () => {
498
+ resolvePromise({ statusCode: res.statusCode ?? 0, text: data });
499
+ });
500
+ });
501
+ req.on('error', rejectPromise);
502
+ });
503
+ }
504
+ function requestHeaders() {
505
+ return {
506
+ 'User-Agent': '@octoberswimmer/aer-sf-plugin',
507
+ Accept: 'application/vnd.github+json',
508
+ };
509
+ }
510
+ //# sourceMappingURL=aerBinary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aerBinary.js","sourceRoot":"","sources":["../src/aerBinary.ts"],"names":[],"mappings":"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"}
@@ -27,5 +27,6 @@ export default class AerApexRunTest extends SfCommand<AerApexRunTestResult> {
27
27
  'api-version': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
28
28
  };
29
29
  run(): Promise<AerApexRunTestResult>;
30
+ private maybePromptForUpdate;
30
31
  }
31
32
  export {};
@@ -4,6 +4,7 @@ import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
4
4
  import { Messages, SfProject } from '@salesforce/core';
5
5
  import { stageSource } from '../../../../staging.js';
6
6
  import { buildAerArgs, runAer } from '../../../../aer.js';
7
+ import { checkForUpdate, ensureAerBinary, installAerVersion, recordPromptedVersion, } from '../../../../aerBinary.js';
7
8
  Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
8
9
  const messages = Messages.loadMessages('@octoberswimmer/aer-sf-plugin', 'aer.apex.run.test');
9
10
  export default class AerApexRunTest extends SfCommand {
@@ -113,6 +114,20 @@ export default class AerApexRunTest extends SfCommand {
113
114
  if (ignoredFlags.length > 0) {
114
115
  this.warn(messages.getMessage('warn.ignoredFlags', [ignoredFlags.join(', ')]));
115
116
  }
117
+ const interactive = !this.jsonEnabled() && Boolean(process.stdin.isTTY);
118
+ const aerPath = await ensureAerBinary({
119
+ allowPrompt: interactive,
120
+ // Long timeout so a user with the prompt buried in scrollback still has
121
+ // time to react; default-no keeps CI/headless runs safe.
122
+ confirm: (message) => this.confirm({ message, ms: 5 * 60 * 1000, defaultAnswer: false }),
123
+ log: (m) => this.log(m),
124
+ warn: (m) => this.warn(m),
125
+ });
126
+ // Kick off the update check in parallel with staging and the test run.
127
+ // Errors are swallowed — we never want this to fail the command.
128
+ const updateCheck = interactive
129
+ ? checkForUpdate({ aerPath, log: (m) => this.log(m) }).catch(() => null)
130
+ : Promise.resolve(null);
116
131
  const staged = await stageSource({
117
132
  projectRoot,
118
133
  packageDirectories,
@@ -148,7 +163,7 @@ export default class AerApexRunTest extends SfCommand {
148
163
  });
149
164
  let exitCode = 0;
150
165
  try {
151
- exitCode = await runAer(args, projectRoot);
166
+ exitCode = await runAer(aerPath, args, projectRoot);
152
167
  }
153
168
  finally {
154
169
  await staged.cleanup();
@@ -156,12 +171,44 @@ export default class AerApexRunTest extends SfCommand {
156
171
  if (exitCode !== 0 && !this.jsonEnabled()) {
157
172
  this.warn(messages.getMessage('warn.aerExit', [String(exitCode)]));
158
173
  }
174
+ await this.maybePromptForUpdate(updateCheck);
159
175
  return {
160
176
  stagedDir: staged.dir,
161
177
  filters,
162
178
  exitCode,
163
179
  };
164
180
  }
181
+ async maybePromptForUpdate(check) {
182
+ let update;
183
+ try {
184
+ update = await check;
185
+ }
186
+ catch {
187
+ return;
188
+ }
189
+ if (!update)
190
+ return;
191
+ this.log('');
192
+ const yes = await this.confirm({
193
+ message: messages.getMessage('prompt.updateAvailable', [update.installed, update.latest]),
194
+ ms: 5 * 60 * 1000,
195
+ defaultAnswer: false,
196
+ });
197
+ if (!yes) {
198
+ // Record only after the user has been asked and declined, so a
199
+ // failed prompt doesn't accidentally suppress future ones.
200
+ await recordPromptedVersion(update.latest).catch(() => { });
201
+ this.log(messages.getMessage('info.updateDeferred'));
202
+ return;
203
+ }
204
+ try {
205
+ const newPath = await installAerVersion(update.latest, { log: (m) => this.log(m) });
206
+ this.log(messages.getMessage('info.updateInstalled', [update.latest, newPath]));
207
+ }
208
+ catch (err) {
209
+ this.warn(messages.getMessage('warn.updateFailed', [err.message]));
210
+ }
211
+ }
165
212
  }
166
213
  function buildFilters(classNames, tests) {
167
214
  const out = [];
@@ -1 +1 @@
1
- {"version":3,"file":"test.js","sourceRoot":"","sources":["../../../../../src/commands/aer/apex/run/test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../../../../../src/commands/aer/apex/run/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAA2C,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACN,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,qBAAqB,GAErB,MAAM,0BAA0B,CAAC;AAElC,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,+BAA+B,EAAE,mBAAmB,CAAC,CAAC;AAgB7F,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,SAA+B;IACnE,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,MAAM,CAAU,KAAK,GAAG;QAC9B,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC;YAC1B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;YACxD,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,8BAA8B,CAAC;SAChE,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,MAAM,CAAY;YACrC,OAAO,EAAE,CAAC,eAAe,EAAE,kBAAkB,EAAE,mBAAmB,CAAC;SACnE,CAAC,CAAC;YACF,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;SACxD,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;YAC3B,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;SACzD,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;YAC3B,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;SACzD,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC;SACnD,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,MAAM,CAAe;YAC3C,OAAO,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC;SAC1C,CAAC,CAAC;YACF,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC;YAC3D,OAAO,EAAE,OAAO;SAChB,CAAC;QACF,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC;YAC7B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,0BAA0B,CAAC;SACxD,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC;YAC9B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC;SAC3D,CAAC;QACF,mBAAmB,EAAE,KAAK,CAAC,OAAO,CAAC;YAClC,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,iCAAiC,CAAC;YAC/D,SAAS,EAAE,CAAC,eAAe,CAAC;SAC5B,CAAC;QACF,WAAW,EAAE,KAAK,CAAC,OAAO,CAAC;YAC1B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;SACzD,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,oBAAoB,CAAC;SAClD,CAAC;QACF,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC;YAC9B,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,6BAA6B,CAAC;SAC3D,CAAC;QACF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC;YACtB,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,uBAAuB,CAAC;SACrD,CAAC;QACF,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC;YAC3B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,2BAA2B,CAAC;SACzD,CAAC;KACF,CAAC;IAEK,KAAK,CAAC,GAAG;QACf,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QAEnD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC;QAC1C,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,WAAW,EAAsC,CAAC;QAC9F,MAAM,kBAAkB,GAAG,QAAQ,CAAC,kBAAkB,IAAI,EAAE,CAAC;QAC7D,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,QAAQ,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAEhE,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;QACtC,IAAI,SAAS,KAAK,kBAAkB,EAAE,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,gCAAgC,CAAC,CAAC,CAAC;QAClE,CAAC;QAED,IAAI,KAAK,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7D,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,4BAA4B,CAAC,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,YAAY,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3D,IAAI,KAAK,CAAC,WAAW;YAAE,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC1D,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;YAAE,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1D,IAAI,KAAK,CAAC,eAAe,CAAC,KAAK,SAAS;YAAE,YAAY,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC/E,IAAI,KAAK,CAAC,aAAa,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7D,IAAI,KAAK,CAAC,mBAAmB,CAAC;YAAE,YAAY,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACzE,IAAI,KAAK,CAAC,OAAO;YAAE,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,KAAK,CAAC,eAAe,CAAC,KAAK,KAAK;YAAE,YAAY,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;QACrG,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAChF,CAAC;QAED,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAExE,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC;YACrC,WAAW,EAAE,WAAW;YACxB,wEAAwE;YACxE,yDAAyD;YACzD,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;YACxF,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACvB,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;SACzB,CAAC,CAAC;QAEH,uEAAuE;QACvE,iEAAiE;QACjE,MAAM,WAAW,GAAkC,WAAW;YAC7D,CAAC,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;YACxE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAEzB,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;YAChC,WAAW;YACX,kBAAkB;YAClB,YAAY,EAAE,QAAQ,CAAC,YAAY;SACnC,CAAC,CAAC;QAEH,IAAI,UAA8B,CAAC;QACnC,IAAI,YAAgC,CAAC;QACrC,MAAM,eAAe,GACpB,KAAK,CAAC,eAAe,CAAC,KAAK,OAAO;YACjC,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,MAAM;gBAClC,CAAC,CAAC,MAAM;gBACR,CAAC,CAAC,OAAO,CAAC;QACb,IAAI,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;YACzD,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACzC,IAAI,eAAe,KAAK,OAAO,EAAE,CAAC;gBACjC,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;YAC9C,CAAC;iBAAM,IAAI,eAAe,KAAK,MAAM,EAAE,CAAC;gBACvC,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;YAC/C,CAAC;YACD,IAAI,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC;gBAC5B,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE,+BAA+B,CAAC,CAAC;YAC9D,CAAC;QACF,CAAC;QAED,MAAM,IAAI,GAAG,YAAY,CAAC;YACzB,SAAS,EAAE,MAAM,CAAC,GAAG;YACrB,OAAO;YACP,YAAY,EAAE,eAAe;YAC7B,UAAU;YACV,YAAY;YACZ,OAAO,EAAE,KAAK,CAAC,mBAAmB,CAAC,IAAI,KAAK;SAC5C,CAAC,CAAC;QAEH,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC;YACJ,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;QACrD,CAAC;gBAAS,CAAC;YACV,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC;QACxB,CAAC;QAED,IAAI,QAAQ,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC;QAE7C,OAAO;YACN,SAAS,EAAE,MAAM,CAAC,GAAG;YACrB,OAAO;YACP,QAAQ;SACR,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAAC,KAAoC;QACtE,IAAI,MAA4B,CAAC;QACjC,IAAI,CAAC;YACJ,MAAM,GAAG,MAAM,KAAK,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACR,OAAO;QACR,CAAC;QACD,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC;YAC9B,OAAO,EAAE,QAAQ,CAAC,UAAU,CAAC,wBAAwB,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACzF,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;YACjB,aAAa,EAAE,KAAK;SACpB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,EAAE,CAAC;YACV,+DAA+D;YAC/D,2DAA2D;YAC3D,MAAM,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC3D,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC;YACrD,OAAO;QACR,CAAC;QAED,IAAI,CAAC;YACJ,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpF,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QACjF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,mBAAmB,EAAE,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/E,CAAC;IACF,CAAC;;AAGF,SAAS,YAAY,CAAC,UAAgC,EAAE,KAA2B;IAClF,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,EAAE,IAAI,UAAU,IAAI,EAAE,EAAE,CAAC;QACnC,wFAAwF;QACxF,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACrB,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;QAC7B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACb,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC"}
@@ -13,7 +13,12 @@ Source is staged into a temporary directory before invoking aer. The staging ste
13
13
  1. When the same Apex class name appears in more than one packageDirectories entry, the copy whose full path sorts alphabetically last wins.
14
14
  2. The `replacements` configuration in sfdx-project.json (stringToReplace / regexToReplace + replaceWithFile / replaceWithEnv) is applied to file contents during staging.
15
15
 
16
- The `aer` binary (https://github.com/octoberswimmer/aer-dist) must be installed and on PATH. Set the `AER_BIN` environment variable to override the path.
16
+ The `aer` binary (https://github.com/octoberswimmer/aer-dist) is resolved in the following order:
17
+
18
+ 1. The `AER_BIN` environment variable, when set to an executable file.
19
+ 2. A copy previously downloaded by this plugin (stored under a platform-specific data directory, e.g. `~/.local/share/aer-sf-plugin/aer-bin/`).
20
+ 3. `aer` discovered on `PATH`.
21
+ 4. If none of the above match and the terminal is interactive, you'll be prompted to download the latest release for your platform from GitHub; the binary is then stored in the plugin's data directory and used for subsequent runs.
17
22
 
18
23
  # examples
19
24
 
@@ -116,3 +121,19 @@ aer exited with non-zero status %s.
116
121
  # error.noPackageDirectories
117
122
 
118
123
  sfdx-project.json must contain at least one packageDirectories entry.
124
+
125
+ # prompt.updateAvailable
126
+
127
+ A newer aer release is available (installed: %s, latest: %s). Update now?
128
+
129
+ # info.updateDeferred
130
+
131
+ Skipping aer update. You'll be prompted again the next time a new release is published.
132
+
133
+ # info.updateInstalled
134
+
135
+ Installed aer %s to %s. The new version will be used on the next run.
136
+
137
+ # warn.updateFailed
138
+
139
+ Failed to update aer: %s
@@ -3,7 +3,7 @@
3
3
  "aer:apex:run:test": {
4
4
  "aliases": [],
5
5
  "args": {},
6
- "description": "Run Apex tests against a local sandbox using aer instead of submitting them to a Salesforce org.\n\nThis command accepts the same flags as `sf apex run test` so it can be used as a drop-in replacement, but flags that only make sense when running against a real org (--target-org, --wait, --poll-interval, --synchronous, --api-version) are accepted for compatibility and otherwise ignored.\n\nSource is staged into a temporary directory before invoking aer. The staging step reproduces two behaviors of `sf project deploy start` that aer does not implement natively:\n\n1. When the same Apex class name appears in more than one packageDirectories entry, the copy whose full path sorts alphabetically last wins.\n2. The `replacements` configuration in sfdx-project.json (stringToReplace / regexToReplace + replaceWithFile / replaceWithEnv) is applied to file contents during staging.\n\nThe `aer` binary (https://github.com/octoberswimmer/aer-dist) must be installed and on PATH. Set the `AER_BIN` environment variable to override the path.",
6
+ "description": "Run Apex tests against a local sandbox using aer instead of submitting them to a Salesforce org.\n\nThis command accepts the same flags as `sf apex run test` so it can be used as a drop-in replacement, but flags that only make sense when running against a real org (--target-org, --wait, --poll-interval, --synchronous, --api-version) are accepted for compatibility and otherwise ignored.\n\nSource is staged into a temporary directory before invoking aer. The staging step reproduces two behaviors of `sf project deploy start` that aer does not implement natively:\n\n1. When the same Apex class name appears in more than one packageDirectories entry, the copy whose full path sorts alphabetically last wins.\n2. The `replacements` configuration in sfdx-project.json (stringToReplace / regexToReplace + replaceWithFile / replaceWithEnv) is applied to file contents during staging.\n\nThe `aer` binary (https://github.com/octoberswimmer/aer-dist) is resolved in the following order:\n\n1. The `AER_BIN` environment variable, when set to an executable file.\n2. A copy previously downloaded by this plugin (stored under a platform-specific data directory, e.g. `~/.local/share/aer-sf-plugin/aer-bin/`).\n3. `aer` discovered on `PATH`.\n4. If none of the above match and the terminal is interactive, you'll be prompted to download the latest release for your platform from GitHub; the binary is then stored in the plugin's data directory and used for subsequent runs.",
7
7
  "examples": [
8
8
  "Run every Apex test in the project:\n<%= config.bin %> <%= command.id %>",
9
9
  "Run a specific Apex test class:\n<%= config.bin %> <%= command.id %> --class-names MyClassTest",
@@ -197,5 +197,5 @@
197
197
  ]
198
198
  }
199
199
  },
200
- "version": "0.0.1"
200
+ "version": "0.0.3"
201
201
  }
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@octoberswimmer/aer-sf-plugin",
3
3
  "description": "Salesforce CLI plugin that runs Apex tests locally using aer.",
4
- "version": "0.0.1",
4
+ "version": "0.0.3",
5
5
  "author": "Christian G. Warden",
6
6
  "bugs": "https://github.com/octoberswimmer/aer-sf-plugin/issues",
7
7
  "homepage": "https://github.com/octoberswimmer/aer-sf-plugin",
8
- "repository": "octoberswimmer/aer-sf-plugin",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/octoberswimmer/aer-sf-plugin.git"
11
+ },
9
12
  "type": "module",
10
13
  "exports": "./lib/index.js",
11
14
  "engines": {
@@ -58,9 +61,11 @@
58
61
  "@oclif/core": "^4",
59
62
  "@salesforce/core": "^8",
60
63
  "@salesforce/sf-plugins-core": "^12",
64
+ "adm-zip": "0.5.17",
61
65
  "minimatch": "^9"
62
66
  },
63
67
  "devDependencies": {
68
+ "@types/adm-zip": "0.5.8",
64
69
  "@types/chai": "^4.3.16",
65
70
  "@types/mocha": "^10.0.6",
66
71
  "@types/node": "^20.12.12",