@afterpack/esbuild 0.2.2 → 0.2.4

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
@@ -34,9 +34,11 @@ them there. If that matters to you, use a bundler with an in-memory plugin, such
34
34
  [`@afterpack/vite`](https://www.npmjs.com/package/@afterpack/vite) or
35
35
  [`@afterpack/rollup`](https://www.npmjs.com/package/@afterpack/rollup).
36
36
 
37
- Each build writes a protection receipt, `.afterpack-protection.json`, into the output directory.
38
- Run `npx afterpack verify dist` in your deploy step to check that what you ship is what was
39
- obfuscated.
37
+ Each build writes a protection receipt to `.afterpack/receipts/`, one per output directory
38
+ (`.afterpack/receipts/dist.json` for `dist`). `.afterpack/` sits next to your project's lockfile,
39
+ `afterpack.json` or `.git` (failing those, its `package.json`), otherwise beside the build
40
+ directory, so the receipt never ships with your build. Run `npx afterpack verify dist` in your
41
+ deploy step to check that what you ship is what was obfuscated.
40
42
 
41
43
  ## Options
42
44
 
@@ -50,7 +52,7 @@ afterpackEsbuild({ preset: "hard", seed: "git" });
50
52
  | [`seed`][seed] | a number or string; `"git"` uses the current commit | a new random seed per build |
51
53
  | [`identifiers.reserved`][identifiers.reserved] | names never to rename | none |
52
54
  | [`paths.exclude`][paths.exclude] | globs for files to leave untouched | none |
53
- | [`sourceMap.enabled`][sourceMap.enabled] | write source maps for the obfuscated output | on in development when esbuild emits a map, off in production |
55
+ | [`sourceMap.enabled`][sourceMap.enabled] | write source maps for the obfuscated output | off; on in development mode (`build.mode` or `NODE_ENV=development`) when esbuild emits a map |
54
56
  | [`protectionMap.enabled`][protectionMap.enabled] | write the Protection Map | on when esbuild's `sourcemap` is set |
55
57
  | [`build.autorun`][build.autorun] | `false` turns AfterPack off | `true` |
56
58
 
package/dist/index.cjs CHANGED
@@ -27,24 +27,32 @@ const __afterpack_core = __toESM(require("@afterpack/core"));
27
27
  const __afterpack_integration_utils = __toESM(require("@afterpack/integration-utils"));
28
28
 
29
29
  //#region src/index.ts
30
+ function outputBuildDir(io, cwd) {
31
+ if (io.outdir) return (0, node_path.isAbsolute)(io.outdir) ? io.outdir : (0, node_path.resolve)(cwd, io.outdir);
32
+ if (io.outfile) return (0, node_path.dirname)((0, node_path.isAbsolute)(io.outfile) ? io.outfile : (0, node_path.resolve)(cwd, io.outfile));
33
+ return cwd;
34
+ }
30
35
  function resolveOutputs(io, cwd, include) {
31
36
  if (io.outdir) {
32
37
  const dir = (0, node_path.isAbsolute)(io.outdir) ? io.outdir : (0, node_path.resolve)(cwd, io.outdir);
33
38
  return {
34
39
  files: (0, __afterpack_integration_utils.collectJsFiles)(dir, { include }),
35
- buildDir: dir
40
+ buildDir: dir,
41
+ sweepDir: dir
36
42
  };
37
43
  }
38
44
  if (io.outfile) {
39
45
  const file = (0, node_path.isAbsolute)(io.outfile) ? io.outfile : (0, node_path.resolve)(cwd, io.outfile);
40
46
  return {
41
47
  files: (0, node_fs.existsSync)(file) ? [file] : [],
42
- buildDir: (0, node_path.dirname)(file)
48
+ buildDir: (0, node_path.dirname)(file),
49
+ sweepDir: null
43
50
  };
44
51
  }
45
52
  return {
46
53
  files: [],
47
- buildDir: cwd
54
+ buildDir: cwd,
55
+ sweepDir: null
48
56
  };
49
57
  }
50
58
  const POST_MINIFY_DIRECTIVE_RECOVERY = true;
@@ -56,19 +64,37 @@ function afterpackEsbuild(options = {}) {
56
64
  const settings = resolved.options;
57
65
  return {
58
66
  name: "afterpack-esbuild",
59
- setup(build) {
67
+ async setup(build) {
68
+ const autorun = settings.build?.autorun ?? true;
69
+ const initial = build.initialOptions;
70
+ if (!autorun || initial.write === false) return;
71
+ const initialCwd = initial.absWorkingDir ?? process.cwd();
72
+ const hashSalt = await (0, __afterpack_integration_utils.prepareHashSalt)({
73
+ seed: settings.seed,
74
+ root: initialCwd,
75
+ leg: outputBuildDir(initial, initialCwd),
76
+ localEngineVersion: await (0, __afterpack_integration_utils.readEngineVersion)({ version: __afterpack_core.version }),
77
+ settings: (0, __afterpack_integration_utils.saltSettings)((0, __afterpack_integration_utils.passSettings)(resolved), {
78
+ format: initial.format ?? null,
79
+ sourcemap: initial.sourcemap ?? null,
80
+ pathsInclude: settings.paths?.include ?? null,
81
+ ...(0, __afterpack_integration_utils.reportPolicySaltBits)(process.env, settings.artifactOptions, Boolean(initial.sourcemap))
82
+ }),
83
+ warn: (message) => console.warn(message)
84
+ });
85
+ const banner = initial.banner?.js;
86
+ initial.banner = {
87
+ ...initial.banner,
88
+ js: `${banner ? `${banner}\n` : ""}/*afterpack:${hashSalt.salt}*/`
89
+ };
60
90
  build.onEnd(async (result) => {
61
- const autorun = settings.build?.autorun ?? true;
62
- if (!autorun) return;
63
91
  if (result.errors.length > 0) return;
64
92
  const io = build.initialOptions;
65
- if (io.write === false) return;
66
93
  const startedBeforeOutputWalk = Date.now();
67
94
  const cwd = io.absWorkingDir ?? process.cwd();
68
- const { files, buildDir } = resolveOutputs(io, cwd, settings.paths?.include);
95
+ const { files, buildDir, sweepDir } = resolveOutputs(io, cwd, settings.paths?.include);
69
96
  if (files.length === 0) return;
70
- const gitignoredNonServedAfterpackDir = (0, node_path.join)(cwd, ".afterpack");
71
- await (0, __afterpack_integration_utils.runObfuscationPass)({
97
+ const pass = await (0, __afterpack_integration_utils.runObfuscationPass)({
72
98
  files,
73
99
  engine: {
74
100
  processBatch: __afterpack_core.processBatch,
@@ -78,11 +104,11 @@ function afterpackEsbuild(options = {}) {
78
104
  telemetry: (0, __afterpack_integration_utils.createTelemetryReporter)(),
79
105
  label: "afterpack-esbuild",
80
106
  cwd,
107
+ resolvedSeed: hashSalt.resolvedSeed,
108
+ cloudEngineExpectation: hashSalt.engine,
81
109
  startedAt: startedBeforeOutputWalk,
82
- combinedProtectionMap: {
83
- buildDir,
84
- afterpackDir: gitignoredNonServedAfterpackDir
85
- },
110
+ combinedProtectionMap: { buildDir },
111
+ sourceMapSweepDir: sweepDir,
86
112
  ...(0, __afterpack_integration_utils.passSettings)(resolved),
87
113
  sourceType: (0, __afterpack_integration_utils.sourceTypeForOutputFormat)(io.format),
88
114
  hasBundlerSourcemap: Boolean(io.sourcemap),
@@ -92,6 +118,11 @@ function afterpackEsbuild(options = {}) {
92
118
  directivesNeedClientMaps: "`directives.enabled` is true but no emitted file carried a source map with `sourcesContent`; set `sourcemap: true` so `/* @afterpack ... */` directives can be recovered from the emitted chunks. No directive was applied to this build."
93
119
  }
94
120
  });
121
+ if (sweepDir === null && !pass.policy.sourceMap) {
122
+ const css = `${files[0].replace(/\.[cm]?js$/, "")}.css`;
123
+ (0, __afterpack_integration_utils.removeSourceMaps)([`${css}.map`], "afterpack-esbuild");
124
+ (0, __afterpack_integration_utils.stripCssSourceMappingURLs)([css]);
125
+ }
95
126
  });
96
127
  }
97
128
  };
package/dist/index.js CHANGED
@@ -1,27 +1,35 @@
1
1
  import { existsSync } from "node:fs";
2
- import { dirname, isAbsolute, join, resolve } from "node:path";
2
+ import { dirname, isAbsolute, resolve } from "node:path";
3
3
  import { processBatch, version } from "@afterpack/core";
4
- import { collectJsFiles, createTelemetryReporter, passSettings, resolveClientIdentity, resolvePluginConfig, runObfuscationPass, sourceTypeForOutputFormat } from "@afterpack/integration-utils";
4
+ import { collectJsFiles, createTelemetryReporter, passSettings, prepareHashSalt, readEngineVersion, removeSourceMaps, reportPolicySaltBits, resolveClientIdentity, resolvePluginConfig, runObfuscationPass, saltSettings, sourceTypeForOutputFormat, stripCssSourceMappingURLs } from "@afterpack/integration-utils";
5
5
 
6
6
  //#region src/index.ts
7
+ function outputBuildDir(io, cwd) {
8
+ if (io.outdir) return isAbsolute(io.outdir) ? io.outdir : resolve(cwd, io.outdir);
9
+ if (io.outfile) return dirname(isAbsolute(io.outfile) ? io.outfile : resolve(cwd, io.outfile));
10
+ return cwd;
11
+ }
7
12
  function resolveOutputs(io, cwd, include) {
8
13
  if (io.outdir) {
9
14
  const dir = isAbsolute(io.outdir) ? io.outdir : resolve(cwd, io.outdir);
10
15
  return {
11
16
  files: collectJsFiles(dir, { include }),
12
- buildDir: dir
17
+ buildDir: dir,
18
+ sweepDir: dir
13
19
  };
14
20
  }
15
21
  if (io.outfile) {
16
22
  const file = isAbsolute(io.outfile) ? io.outfile : resolve(cwd, io.outfile);
17
23
  return {
18
24
  files: existsSync(file) ? [file] : [],
19
- buildDir: dirname(file)
25
+ buildDir: dirname(file),
26
+ sweepDir: null
20
27
  };
21
28
  }
22
29
  return {
23
30
  files: [],
24
- buildDir: cwd
31
+ buildDir: cwd,
32
+ sweepDir: null
25
33
  };
26
34
  }
27
35
  const POST_MINIFY_DIRECTIVE_RECOVERY = true;
@@ -33,19 +41,37 @@ function afterpackEsbuild(options = {}) {
33
41
  const settings = resolved.options;
34
42
  return {
35
43
  name: "afterpack-esbuild",
36
- setup(build) {
44
+ async setup(build) {
45
+ const autorun = settings.build?.autorun ?? true;
46
+ const initial = build.initialOptions;
47
+ if (!autorun || initial.write === false) return;
48
+ const initialCwd = initial.absWorkingDir ?? process.cwd();
49
+ const hashSalt = await prepareHashSalt({
50
+ seed: settings.seed,
51
+ root: initialCwd,
52
+ leg: outputBuildDir(initial, initialCwd),
53
+ localEngineVersion: await readEngineVersion({ version }),
54
+ settings: saltSettings(passSettings(resolved), {
55
+ format: initial.format ?? null,
56
+ sourcemap: initial.sourcemap ?? null,
57
+ pathsInclude: settings.paths?.include ?? null,
58
+ ...reportPolicySaltBits(process.env, settings.artifactOptions, Boolean(initial.sourcemap))
59
+ }),
60
+ warn: (message) => console.warn(message)
61
+ });
62
+ const banner = initial.banner?.js;
63
+ initial.banner = {
64
+ ...initial.banner,
65
+ js: `${banner ? `${banner}\n` : ""}/*afterpack:${hashSalt.salt}*/`
66
+ };
37
67
  build.onEnd(async (result) => {
38
- const autorun = settings.build?.autorun ?? true;
39
- if (!autorun) return;
40
68
  if (result.errors.length > 0) return;
41
69
  const io = build.initialOptions;
42
- if (io.write === false) return;
43
70
  const startedBeforeOutputWalk = Date.now();
44
71
  const cwd = io.absWorkingDir ?? process.cwd();
45
- const { files, buildDir } = resolveOutputs(io, cwd, settings.paths?.include);
72
+ const { files, buildDir, sweepDir } = resolveOutputs(io, cwd, settings.paths?.include);
46
73
  if (files.length === 0) return;
47
- const gitignoredNonServedAfterpackDir = join(cwd, ".afterpack");
48
- await runObfuscationPass({
74
+ const pass = await runObfuscationPass({
49
75
  files,
50
76
  engine: {
51
77
  processBatch,
@@ -55,11 +81,11 @@ function afterpackEsbuild(options = {}) {
55
81
  telemetry: createTelemetryReporter(),
56
82
  label: "afterpack-esbuild",
57
83
  cwd,
84
+ resolvedSeed: hashSalt.resolvedSeed,
85
+ cloudEngineExpectation: hashSalt.engine,
58
86
  startedAt: startedBeforeOutputWalk,
59
- combinedProtectionMap: {
60
- buildDir,
61
- afterpackDir: gitignoredNonServedAfterpackDir
62
- },
87
+ combinedProtectionMap: { buildDir },
88
+ sourceMapSweepDir: sweepDir,
63
89
  ...passSettings(resolved),
64
90
  sourceType: sourceTypeForOutputFormat(io.format),
65
91
  hasBundlerSourcemap: Boolean(io.sourcemap),
@@ -69,6 +95,11 @@ function afterpackEsbuild(options = {}) {
69
95
  directivesNeedClientMaps: "`directives.enabled` is true but no emitted file carried a source map with `sourcesContent`; set `sourcemap: true` so `/* @afterpack ... */` directives can be recovered from the emitted chunks. No directive was applied to this build."
70
96
  }
71
97
  });
98
+ if (sweepDir === null && !pass.policy.sourceMap) {
99
+ const css = `${files[0].replace(/\.[cm]?js$/, "")}.css`;
100
+ removeSourceMaps([`${css}.map`], "afterpack-esbuild");
101
+ stripCssSourceMappingURLs([css]);
102
+ }
72
103
  });
73
104
  }
74
105
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afterpack/esbuild",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "esbuild plugin for AfterPack: obfuscate your JavaScript output when the esbuild build finishes",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -28,8 +28,8 @@
28
28
  "esbuild": ">=0.17.0"
29
29
  },
30
30
  "dependencies": {
31
- "@afterpack/core": "~0.2.3",
32
- "@afterpack/integration-utils": "0.2.2"
31
+ "@afterpack/core": "~0.2.5",
32
+ "@afterpack/integration-utils": "0.2.4"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@biomejs/biome": "2.4.4",