afterpack 0.2.2 → 0.2.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
@@ -105,7 +105,6 @@ the [configuration reference](https://www.afterpack.dev/docs/config). The
105
105
  [build.backup]: https://www.afterpack.dev/docs/config#build-backup
106
106
  [protectionMap.enabled]: https://www.afterpack.dev/docs/config#protectionMap-enabled
107
107
  [diagnostics.format]: https://www.afterpack.dev/docs/config#diagnostics-format
108
- [allowUnobfuscated]: https://www.afterpack.dev/docs/config#allowUnobfuscated
109
108
  [inflation.max]: https://www.afterpack.dev/docs/config#inflation-max
110
109
  [key]: https://www.afterpack.dev/docs/config#key
111
110
 
@@ -136,8 +135,10 @@ Pro](https://www.afterpack.dev/docs/pro).
136
135
  | --- | --- |
137
136
  | `0` | Success. |
138
137
  | `1` | Failure. Nothing was changed, or `verify`, `restore` or `audit` failed. |
139
- | `2` | Some files shipped unobfuscated. Only possible with [`allowUnobfuscated`][allowUnobfuscated]. |
138
+ | `2` | Partial. Reserved for a quota-exhausted build; no build returns it today. |
140
139
  | `3` | The size limit ([`inflation.max`][inflation.max]) stopped AfterPack before it reached the protection level. |
140
+ | `4` | A region directive that raises protection needs a Pro key. |
141
+ | `5` | A runtime-reflection pattern was not acknowledged. |
141
142
  | `6` | An update is required. The CLI prints the install command to run. |
142
143
  | `64` | Misuse: an unknown option or command, or a malformed value. |
143
144
 
package/SKILL.md CHANGED
@@ -107,7 +107,6 @@ minification.
107
107
  | [`protectionMap.enabled`][protectionMap.enabled] | write the Protection Map | on when an input map exists |
108
108
  | [`diagnostics.format`][diagnostics.format] | `text` or `json` | `text` |
109
109
  | [`diagnostics.level`][diagnostics.level] | `summary`, `all` or `none` (errors still print) | `summary` |
110
- | [`allowUnobfuscated`][allowUnobfuscated] | ship a file that could not be processed, instead of failing (exit `2`) | `false` |
111
110
  | [`build.autorun`][build.autorun] | `false` turns AfterPack off for the project, CLI and plugins alike | `true` |
112
111
  | [`telemetry.enabled`][telemetry.enabled] | anonymous diagnostics, sent only when a build is refused or partial | `true` |
113
112
 
@@ -126,7 +125,6 @@ https://www.afterpack.dev/docs/config
126
125
  [protectionMap.enabled]: https://www.afterpack.dev/docs/config#protectionMap-enabled
127
126
  [diagnostics.format]: https://www.afterpack.dev/docs/config#diagnostics-format
128
127
  [diagnostics.level]: https://www.afterpack.dev/docs/config#diagnostics-level
129
- [allowUnobfuscated]: https://www.afterpack.dev/docs/config#allowUnobfuscated
130
128
  [build.autorun]: https://www.afterpack.dev/docs/config#build-autorun
131
129
  [telemetry.enabled]: https://www.afterpack.dev/docs/config#telemetry-enabled
132
130
  [inflation.max]: https://www.afterpack.dev/docs/config#inflation-max
@@ -164,7 +162,7 @@ it too. Add `--diagnostics.level=none` for a run that prints nothing else.
164
162
  }
165
163
  ```
166
164
 
167
- `status` is `obfuscated`, `unchanged`, `unobfuscated` or `failed`. A failure is a document too,
165
+ `status` is `obfuscated`, `unchanged` or `failed`. A failure is a document too,
168
166
  with the same exit code and a `fix` field to act on:
169
167
 
170
168
  ```json
@@ -231,8 +229,10 @@ exits `1`. Anonymous use is rate-limited per 24 hours. Docs: https://www.afterpa
231
229
  | --- | --- |
232
230
  | `0` | Success. Also `--help` and `--version`. |
233
231
  | `1` | Failure: bad path, no JavaScript found, an engine error, an already-obfuscated tree, a failed `verify`, `restore` or scan, or an unreachable cloud on a Pro build. |
234
- | `2` | Partial: some files shipped unobfuscated. Only with [`allowUnobfuscated`][allowUnobfuscated]. |
232
+ | `2` | Partial. Reserved for a quota-exhausted build; no build returns it today. |
235
233
  | `3` | Size cap: [`inflation.max`][inflation.max] stopped the run before it reached the protection level. |
234
+ | `4` | Pro required: a region directive that raises protection needs a Pro key (`DIAG_PRO_DIRECTIVE_REQUIRES_KEY`). |
235
+ | `5` | Reflection: a runtime-reflection pattern was not acknowledged (`DIAG_REFLECTION_NOT_ACKNOWLEDGED`). |
236
236
  | `6` | Update required. Run the install command it prints, for example `npm install afterpack@latest @afterpack/core@<version>`. Nothing was written. |
237
237
  | `64` | Misuse: unknown flag or command, malformed value, or two path arguments. |
238
238
 
package/dist/cli.js CHANGED
@@ -170,20 +170,28 @@ const EXIT = {
170
170
  usage: 64
171
171
  };
172
172
  const SIZE_CAP_CODE = "DIAG_SIZE_CAP_REACHED";
173
+ const PRO_REQUIRED_CODE = "DIAG_PRO_DIRECTIVE_REQUIRES_KEY";
174
+ const REFLECTION_CODE = "DIAG_REFLECTION_NOT_ACKNOWLEDGED";
173
175
  const EXIT_CODE_HELP = `Exit codes:
174
176
  0 success — every collected file was obfuscated and written
175
177
  1 total failure — nothing usable was produced (also: a Pro build whose
176
178
  cloud call failed; it never falls back to a local build)
177
- 2 partial — some files shipped unobfuscated; only reachable with
178
- \`--allowUnobfuscated\`
179
+ 2 partial — reserved for a quota-exhausted build; no build returns it today
179
180
  3 size cap — \`inflation.max\` could not reach the complexity target
180
181
  (${SIZE_CAP_CODE})
182
+ 4 Pro required — a region directive that raises protection needs a Pro key
183
+ (${PRO_REQUIRED_CODE})
184
+ 5 reflection — a runtime-reflection pattern was not acknowledged
185
+ (${REFLECTION_CODE})
181
186
  6 update required — the AfterPack cloud API, or this afterpack, needs a
182
187
  newer @afterpack/core; nothing was written
183
188
  64 misuse — an unknown flag or command, or a malformed value`;
184
189
  function failureExitCode(diagnostics) {
185
- const sizeCap = diagnostics.some((d) => d.code === SIZE_CAP_CODE && d.severity !== "info");
186
- return sizeCap ? EXIT.sizeCap : EXIT.failure;
190
+ const has = (code) => diagnostics.some((d) => d.code === code && d.severity !== "info");
191
+ if (has(PRO_REQUIRED_CODE)) return EXIT.proRequired;
192
+ if (has(REFLECTION_CODE)) return EXIT.reflection;
193
+ if (has(SIZE_CAP_CODE)) return EXIT.sizeCap;
194
+ return EXIT.failure;
187
195
  }
188
196
 
189
197
  //#endregion
@@ -1469,7 +1477,6 @@ function captureFile(file, bytesIn) {
1469
1477
  bytesIn,
1470
1478
  bytesOut: Buffer.byteLength(file.code),
1471
1479
  status: file.status,
1472
- unobfuscated: file.unobfuscated === true,
1473
1480
  diagnostics: sanitizeEngineDiagnostics(file.diagnostics).map((d) => ({
1474
1481
  ...d,
1475
1482
  file: d.file ?? file.path
@@ -1481,9 +1488,28 @@ function alignRow(label, value) {
1481
1488
  }
1482
1489
  function fileStatus(file) {
1483
1490
  if (file.status !== "success") return "failed";
1484
- if (file.unobfuscated) return "unobfuscated";
1485
1491
  return file.bytesOut === file.bytesIn && file.diagnostics.length === 0 ? "unchanged" : "obfuscated";
1486
1492
  }
1493
+ function failureDetail(exitCode) {
1494
+ switch (exitCode) {
1495
+ case EXIT.sizeCap: return {
1496
+ code: SIZE_CAP_CODE,
1497
+ fix: "Raise --inflation.max, or lower --complexity, so the target fits the size budget."
1498
+ };
1499
+ case EXIT.proRequired: return {
1500
+ code: PRO_REQUIRED_CODE,
1501
+ fix: "A region directive raises protection, which needs a Pro key. Add --key=<ap_live_…>, or remove the directive."
1502
+ };
1503
+ case EXIT.reflection: return {
1504
+ code: REFLECTION_CODE,
1505
+ fix: "Acknowledge the runtime-reflection pattern with --reflection.allow=<value> (the diagnostic above names the value), carve the file out with --paths.exclude=<glob>, or (Pro) mark it with an @afterpack allow-reflection directive."
1506
+ };
1507
+ default: return {
1508
+ code: "BUILD_FAILED",
1509
+ fix: "Fix the diagnostic(s) above, or carve the file out with --paths.exclude=<glob>. Your build output was left exactly as your bundler wrote it."
1510
+ };
1511
+ }
1512
+ }
1487
1513
  function buildDocument(input) {
1488
1514
  const { cwd, files, result } = input;
1489
1515
  const asJson = (d) => {
@@ -1512,7 +1538,6 @@ function buildDocument(input) {
1512
1538
  summary: {
1513
1539
  files: files.length,
1514
1540
  transformed: input.transformed.size,
1515
- unobfuscated: files.filter((f) => f.unobfuscated).length,
1516
1541
  failed: files.filter((f) => f.status !== "success").length,
1517
1542
  bytesIn: files.reduce((n, f) => n + f.bytesIn, 0),
1518
1543
  bytesOut: files.reduce((n, f) => n + f.bytesOut, 0),
@@ -1922,12 +1947,12 @@ async function run(deps) {
1922
1947
  warn: (m) => logger.warn(m),
1923
1948
  error: (m) => logger.error(m)
1924
1949
  };
1925
- const refuseHere = (exitCode$1, code, message, fix, detail) => refuse({
1950
+ const refuseHere = (exitCode, code, message, fix, detail) => refuse({
1926
1951
  logger,
1927
1952
  mode,
1928
1953
  version: version$1,
1929
1954
  command: "obfuscate",
1930
- exitCode: exitCode$1,
1955
+ exitCode,
1931
1956
  code,
1932
1957
  message,
1933
1958
  fix,
@@ -2050,27 +2075,20 @@ async function run(deps) {
2050
2075
  }
2051
2076
  const diagnostics = captured.flatMap((f) => f.diagnostics);
2052
2077
  if (failure !== null) {
2053
- const exitCode$1 = failureExitCode(diagnostics);
2054
- return refuseHere(exitCode$1, exitCode$1 === EXIT.sizeCap ? SIZE_CAP_CODE : "BUILD_FAILED", failure, exitCode$1 === EXIT.sizeCap ? "Raise --inflation.max, or lower --complexity, so the target fits the size budget." : "Fix the diagnostic(s) above, or carve the file out with --paths.exclude=<glob>. Your build output was left exactly as your bundler wrote it.");
2078
+ const exitCode = failureExitCode(diagnostics);
2079
+ const { code, fix } = failureDetail(exitCode);
2080
+ return refuseHere(exitCode, code, failure, fix);
2055
2081
  }
2056
- const unobfuscated = captured.filter((f) => f.unobfuscated);
2057
- const exitCode = unobfuscated.length > 0 ? EXIT.partial : EXIT.ok;
2058
2082
  if (mode.format === "json") {
2059
2083
  emitJson(logger, buildDocument({
2060
2084
  version: version$1,
2061
2085
  cwd,
2062
- exitCode,
2086
+ exitCode: EXIT.ok,
2063
2087
  files: captured,
2064
2088
  result,
2065
2089
  transformed: new Set(result?.transformedFiles ?? [])
2066
2090
  }));
2067
- return exitCode;
2068
- }
2069
- if (exitCode === EXIT.partial) {
2070
- logger.error(`${yellow("⚠")} ${unobfuscated.length} ${unobfuscated.length === 1 ? "file" : "files"} shipped UNOBFUSCATED — drop --allowUnobfuscated to fail closed instead.`);
2071
- logger.error("");
2072
- logger.error(dim(CONTACT_FOOTER));
2073
- return exitCode;
2091
+ return EXIT.ok;
2074
2092
  }
2075
2093
  renderNextSteps({
2076
2094
  report,
@@ -2082,7 +2100,7 @@ async function run(deps) {
2082
2100
  backupWritten,
2083
2101
  hasConfiguredKey
2084
2102
  });
2085
- return exitCode;
2103
+ return EXIT.ok;
2086
2104
  }
2087
2105
  const SUBCOMMAND_HELP = {
2088
2106
  verify: VERIFY_HELP,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "afterpack",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "AfterPack CLI: obfuscate the JavaScript in any build output, verify a build before deploy, and scan a live site",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,8 +14,8 @@
14
14
  "dist"
15
15
  ],
16
16
  "dependencies": {
17
- "@afterpack/core": "~0.2.3",
18
- "@afterpack/integration-utils": "0.2.2"
17
+ "@afterpack/core": "~0.2.4",
18
+ "@afterpack/integration-utils": "0.2.3"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@biomejs/biome": "2.4.4",