@afterpack/rollup 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 +6 -4
- package/dist/index.cjs +51 -6
- package/dist/index.js +53 -8
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -26,9 +26,11 @@ The plugin runs last, after every other plugin, and obfuscates each JavaScript c
|
|
|
26
26
|
writes it. The readable bundle never reaches disk. If obfuscation fails, the build fails and the
|
|
27
27
|
output directory is left untouched.
|
|
28
28
|
|
|
29
|
-
Each build writes a protection receipt
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
Each build writes a protection receipt to `.afterpack/receipts/`, one per output directory
|
|
30
|
+
(`.afterpack/receipts/dist.json` for `dist`). `.afterpack/` sits next to your project's lockfile,
|
|
31
|
+
`afterpack.json` or `.git` (failing those, its `package.json`), otherwise beside the build
|
|
32
|
+
directory, so the receipt never ships with your build. Run `npx afterpack verify dist` in your
|
|
33
|
+
deploy step to check that what you ship is what was obfuscated.
|
|
32
34
|
|
|
33
35
|
## Options
|
|
34
36
|
|
|
@@ -42,7 +44,7 @@ afterpackRollup({ preset: "hard", seed: "git" });
|
|
|
42
44
|
| [`seed`][seed] | a number or string; `"git"` uses the current commit | a new random seed per build |
|
|
43
45
|
| [`identifiers.reserved`][identifiers.reserved] | names never to rename | none |
|
|
44
46
|
| [`paths.exclude`][paths.exclude] | globs for files to leave untouched | none |
|
|
45
|
-
| [`sourceMap.enabled`][sourceMap.enabled] | write source maps for the obfuscated output; off also drops the build's CSS maps | on in development when Rollup emits a map
|
|
47
|
+
| [`sourceMap.enabled`][sourceMap.enabled] | write source maps for the obfuscated output; off also drops the build's CSS maps | off; on in development mode (`build.mode` or `NODE_ENV=development`) when Rollup emits a map |
|
|
46
48
|
| [`protectionMap.enabled`][protectionMap.enabled] | write the Protection Map | on when `output.sourcemap` is set |
|
|
47
49
|
| [`build.autorun`][build.autorun] | `false` turns AfterPack off | `true` |
|
|
48
50
|
|
package/dist/index.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
21
21
|
}) : target, mod));
|
|
22
22
|
|
|
23
23
|
//#endregion
|
|
24
|
+
const node_crypto = __toESM(require("node:crypto"));
|
|
24
25
|
const node_path = __toESM(require("node:path"));
|
|
25
26
|
const __afterpack_core = __toESM(require("@afterpack/core"));
|
|
26
27
|
const __afterpack_integration_utils = __toESM(require("@afterpack/integration-utils"));
|
|
@@ -43,8 +44,47 @@ function afterpackRollup(options = {}) {
|
|
|
43
44
|
const preMinifyCapturedModulesById = new Map();
|
|
44
45
|
const captureDiagnostics = [];
|
|
45
46
|
const deferredReceiptByOutDir = new Map();
|
|
47
|
+
const hashSaltByOutDir = new Map();
|
|
48
|
+
let latestSalt;
|
|
49
|
+
const directiveSalt = (moduleIds) => {
|
|
50
|
+
if (!moduleIds || preMinifyCapturedModulesById.size === 0) return "";
|
|
51
|
+
const parts = [];
|
|
52
|
+
for (const id of moduleIds) {
|
|
53
|
+
const cap = preMinifyCapturedModulesById.get(id);
|
|
54
|
+
if (cap && (cap.directives.length > 0 || cap.renameGlobals)) parts.push(JSON.stringify({
|
|
55
|
+
id,
|
|
56
|
+
d: cap.directives,
|
|
57
|
+
g: cap.renameGlobals
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
if (parts.length === 0) return "";
|
|
61
|
+
return (0, node_crypto.createHash)("sha256").update(parts.sort().join("\0")).digest("hex").slice(0, 16);
|
|
62
|
+
};
|
|
46
63
|
return {
|
|
47
64
|
name: "afterpack-rollup",
|
|
65
|
+
buildStart() {
|
|
66
|
+
hashSaltByOutDir.clear();
|
|
67
|
+
latestSalt = void 0;
|
|
68
|
+
},
|
|
69
|
+
async renderStart(outputOptions) {
|
|
70
|
+
if (!autorun) return;
|
|
71
|
+
const outDir = outputDir(outputOptions);
|
|
72
|
+
if (!outDir) return;
|
|
73
|
+
const prepared = await (0, __afterpack_integration_utils.prepareHashSalt)({
|
|
74
|
+
seed: settings.seed,
|
|
75
|
+
root: process.cwd(),
|
|
76
|
+
leg: outDir,
|
|
77
|
+
localEngineVersion: await (0, __afterpack_integration_utils.readEngineVersion)({ version: __afterpack_core.version }),
|
|
78
|
+
settings: (0, __afterpack_integration_utils.saltSettings)((0, __afterpack_integration_utils.passSettings)(resolved), { ...(0, __afterpack_integration_utils.reportPolicySaltBits)(process.env, settings.artifactOptions, Boolean(outputOptions.sourcemap)) }),
|
|
79
|
+
warn: (message) => console.warn(message)
|
|
80
|
+
});
|
|
81
|
+
hashSaltByOutDir.set(outDir, prepared);
|
|
82
|
+
latestSalt = prepared.salt;
|
|
83
|
+
},
|
|
84
|
+
augmentChunkHash(chunk) {
|
|
85
|
+
if (latestSalt === void 0) return void 0;
|
|
86
|
+
return latestSalt + directiveSalt(chunk?.moduleIds);
|
|
87
|
+
},
|
|
48
88
|
transform: {
|
|
49
89
|
order: "pre",
|
|
50
90
|
handler(code, id) {
|
|
@@ -71,6 +111,8 @@ function afterpackRollup(options = {}) {
|
|
|
71
111
|
const startedBeforeBundleWalk = Date.now();
|
|
72
112
|
const { files, inputs, entries } = (0, __afterpack_integration_utils.collectBundleJs)(bundle, outDir);
|
|
73
113
|
if (files.length === 0) return;
|
|
114
|
+
const unsalted = (0, __afterpack_integration_utils.unsaltedAssetsWarning)(entries, new Set());
|
|
115
|
+
if (unsalted) console.warn(`[afterpack-rollup] ${unsalted}`);
|
|
74
116
|
const capturedByFile = new Map();
|
|
75
117
|
if (preMinifyCapturedModulesById.size > 0) for (const [filePath, entry] of entries) {
|
|
76
118
|
const mods = [];
|
|
@@ -91,7 +133,6 @@ function afterpackRollup(options = {}) {
|
|
|
91
133
|
for (const message of captureDiagnostics) console.warn(`[afterpack-rollup] directive ${message}`);
|
|
92
134
|
captureDiagnostics.length = 0;
|
|
93
135
|
const cwd = process.cwd();
|
|
94
|
-
const gitignoredNonServedAfterpackDir = (0, node_path.join)(cwd, ".afterpack");
|
|
95
136
|
const result = await (0, __afterpack_integration_utils.runObfuscationPass)({
|
|
96
137
|
files,
|
|
97
138
|
inputs,
|
|
@@ -104,22 +145,26 @@ function afterpackRollup(options = {}) {
|
|
|
104
145
|
telemetry: (0, __afterpack_integration_utils.createTelemetryReporter)(),
|
|
105
146
|
label: "afterpack-rollup",
|
|
106
147
|
cwd,
|
|
148
|
+
resolvedSeed: hashSaltByOutDir.get(outDir)?.resolvedSeed,
|
|
149
|
+
cloudEngineExpectation: hashSaltByOutDir.get(outDir)?.engine,
|
|
107
150
|
startedAt: startedBeforeBundleWalk,
|
|
108
151
|
capturedByFile: capturedByFile.size > 0 ? capturedByFile : void 0,
|
|
109
|
-
combinedProtectionMap: {
|
|
110
|
-
buildDir: outDir,
|
|
111
|
-
afterpackDir: gitignoredNonServedAfterpackDir
|
|
112
|
-
},
|
|
152
|
+
combinedProtectionMap: { buildDir: outDir },
|
|
113
153
|
...(0, __afterpack_integration_utils.passSettings)(resolved),
|
|
114
154
|
sourceType: (0, __afterpack_integration_utils.sourceTypeForBundle)(outputOptions.format, entries.values()),
|
|
115
155
|
hasBundlerSourcemap: Boolean(outputOptions.sourcemap),
|
|
116
156
|
messages: { autoEnableBundlerSourcemap: "protectionMap:true but no bundler sourcemap was found; set `output.sourcemap: true` so future builds can render original source in the map." }
|
|
117
157
|
});
|
|
158
|
+
const obfuscated = new Set();
|
|
118
159
|
for (const out of result.outputs ?? []) {
|
|
119
160
|
const entry = entries.get(out.path);
|
|
120
|
-
if (entry)
|
|
161
|
+
if (entry) {
|
|
162
|
+
(0, __afterpack_integration_utils.applyBundleOutput)(bundle, entry, out, result.policy);
|
|
163
|
+
obfuscated.add(entry.fileName);
|
|
164
|
+
}
|
|
121
165
|
}
|
|
122
166
|
if (!result.policy.sourceMap) (0, __afterpack_integration_utils.stripBundleCssSourceMaps)(bundle);
|
|
167
|
+
(0, __afterpack_integration_utils.regenerateCompressedSiblings)(bundle, obfuscated, "afterpack-rollup");
|
|
123
168
|
if (result.deferredReceipt) deferredReceiptByOutDir.set(outDir, result.deferredReceipt);
|
|
124
169
|
}
|
|
125
170
|
},
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { dirname } from "node:path";
|
|
2
3
|
import { processBatch, version } from "@afterpack/core";
|
|
3
|
-
import { applyBundleOutput, collectBundleJs, createTelemetryReporter, passSettings, resolveClientIdentity, resolvePluginConfig, runObfuscationPass, scanDirectives, sourceTypeForBundle, stripBundleCssSourceMaps, writeDeferredProtectionReceipt } from "@afterpack/integration-utils";
|
|
4
|
+
import { applyBundleOutput, collectBundleJs, createTelemetryReporter, passSettings, prepareHashSalt, readEngineVersion, regenerateCompressedSiblings, reportPolicySaltBits, resolveClientIdentity, resolvePluginConfig, runObfuscationPass, saltSettings, scanDirectives, sourceTypeForBundle, stripBundleCssSourceMaps, unsaltedAssetsWarning, writeDeferredProtectionReceipt } from "@afterpack/integration-utils";
|
|
4
5
|
|
|
5
6
|
//#region src/index.ts
|
|
6
7
|
const PATHS_INCLUDE_UNSUPPORTED = "this plugin obfuscates Rollup's own bundle, in the pipeline — there is no output-directory walk for a glob to re-admit anything into. Use `npx afterpack <dir> --paths.include=...` for a disk walk, or drop the key.";
|
|
@@ -20,8 +21,47 @@ function afterpackRollup(options = {}) {
|
|
|
20
21
|
const preMinifyCapturedModulesById = new Map();
|
|
21
22
|
const captureDiagnostics = [];
|
|
22
23
|
const deferredReceiptByOutDir = new Map();
|
|
24
|
+
const hashSaltByOutDir = new Map();
|
|
25
|
+
let latestSalt;
|
|
26
|
+
const directiveSalt = (moduleIds) => {
|
|
27
|
+
if (!moduleIds || preMinifyCapturedModulesById.size === 0) return "";
|
|
28
|
+
const parts = [];
|
|
29
|
+
for (const id of moduleIds) {
|
|
30
|
+
const cap = preMinifyCapturedModulesById.get(id);
|
|
31
|
+
if (cap && (cap.directives.length > 0 || cap.renameGlobals)) parts.push(JSON.stringify({
|
|
32
|
+
id,
|
|
33
|
+
d: cap.directives,
|
|
34
|
+
g: cap.renameGlobals
|
|
35
|
+
}));
|
|
36
|
+
}
|
|
37
|
+
if (parts.length === 0) return "";
|
|
38
|
+
return createHash("sha256").update(parts.sort().join("\0")).digest("hex").slice(0, 16);
|
|
39
|
+
};
|
|
23
40
|
return {
|
|
24
41
|
name: "afterpack-rollup",
|
|
42
|
+
buildStart() {
|
|
43
|
+
hashSaltByOutDir.clear();
|
|
44
|
+
latestSalt = void 0;
|
|
45
|
+
},
|
|
46
|
+
async renderStart(outputOptions) {
|
|
47
|
+
if (!autorun) return;
|
|
48
|
+
const outDir = outputDir(outputOptions);
|
|
49
|
+
if (!outDir) return;
|
|
50
|
+
const prepared = await prepareHashSalt({
|
|
51
|
+
seed: settings.seed,
|
|
52
|
+
root: process.cwd(),
|
|
53
|
+
leg: outDir,
|
|
54
|
+
localEngineVersion: await readEngineVersion({ version }),
|
|
55
|
+
settings: saltSettings(passSettings(resolved), { ...reportPolicySaltBits(process.env, settings.artifactOptions, Boolean(outputOptions.sourcemap)) }),
|
|
56
|
+
warn: (message) => console.warn(message)
|
|
57
|
+
});
|
|
58
|
+
hashSaltByOutDir.set(outDir, prepared);
|
|
59
|
+
latestSalt = prepared.salt;
|
|
60
|
+
},
|
|
61
|
+
augmentChunkHash(chunk) {
|
|
62
|
+
if (latestSalt === void 0) return void 0;
|
|
63
|
+
return latestSalt + directiveSalt(chunk?.moduleIds);
|
|
64
|
+
},
|
|
25
65
|
transform: {
|
|
26
66
|
order: "pre",
|
|
27
67
|
handler(code, id) {
|
|
@@ -48,6 +88,8 @@ function afterpackRollup(options = {}) {
|
|
|
48
88
|
const startedBeforeBundleWalk = Date.now();
|
|
49
89
|
const { files, inputs, entries } = collectBundleJs(bundle, outDir);
|
|
50
90
|
if (files.length === 0) return;
|
|
91
|
+
const unsalted = unsaltedAssetsWarning(entries, new Set());
|
|
92
|
+
if (unsalted) console.warn(`[afterpack-rollup] ${unsalted}`);
|
|
51
93
|
const capturedByFile = new Map();
|
|
52
94
|
if (preMinifyCapturedModulesById.size > 0) for (const [filePath, entry] of entries) {
|
|
53
95
|
const mods = [];
|
|
@@ -68,7 +110,6 @@ function afterpackRollup(options = {}) {
|
|
|
68
110
|
for (const message of captureDiagnostics) console.warn(`[afterpack-rollup] directive ${message}`);
|
|
69
111
|
captureDiagnostics.length = 0;
|
|
70
112
|
const cwd = process.cwd();
|
|
71
|
-
const gitignoredNonServedAfterpackDir = join(cwd, ".afterpack");
|
|
72
113
|
const result = await runObfuscationPass({
|
|
73
114
|
files,
|
|
74
115
|
inputs,
|
|
@@ -81,22 +122,26 @@ function afterpackRollup(options = {}) {
|
|
|
81
122
|
telemetry: createTelemetryReporter(),
|
|
82
123
|
label: "afterpack-rollup",
|
|
83
124
|
cwd,
|
|
125
|
+
resolvedSeed: hashSaltByOutDir.get(outDir)?.resolvedSeed,
|
|
126
|
+
cloudEngineExpectation: hashSaltByOutDir.get(outDir)?.engine,
|
|
84
127
|
startedAt: startedBeforeBundleWalk,
|
|
85
128
|
capturedByFile: capturedByFile.size > 0 ? capturedByFile : void 0,
|
|
86
|
-
combinedProtectionMap: {
|
|
87
|
-
buildDir: outDir,
|
|
88
|
-
afterpackDir: gitignoredNonServedAfterpackDir
|
|
89
|
-
},
|
|
129
|
+
combinedProtectionMap: { buildDir: outDir },
|
|
90
130
|
...passSettings(resolved),
|
|
91
131
|
sourceType: sourceTypeForBundle(outputOptions.format, entries.values()),
|
|
92
132
|
hasBundlerSourcemap: Boolean(outputOptions.sourcemap),
|
|
93
133
|
messages: { autoEnableBundlerSourcemap: "protectionMap:true but no bundler sourcemap was found; set `output.sourcemap: true` so future builds can render original source in the map." }
|
|
94
134
|
});
|
|
135
|
+
const obfuscated = new Set();
|
|
95
136
|
for (const out of result.outputs ?? []) {
|
|
96
137
|
const entry = entries.get(out.path);
|
|
97
|
-
if (entry)
|
|
138
|
+
if (entry) {
|
|
139
|
+
applyBundleOutput(bundle, entry, out, result.policy);
|
|
140
|
+
obfuscated.add(entry.fileName);
|
|
141
|
+
}
|
|
98
142
|
}
|
|
99
143
|
if (!result.policy.sourceMap) stripBundleCssSourceMaps(bundle);
|
|
144
|
+
regenerateCompressedSiblings(bundle, obfuscated, "afterpack-rollup");
|
|
100
145
|
if (result.deferredReceipt) deferredReceiptByOutDir.set(outDir, result.deferredReceipt);
|
|
101
146
|
}
|
|
102
147
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@afterpack/rollup",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Rollup plugin for AfterPack: obfuscate your JavaScript output during the Rollup build",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"rollup": "^3.0.0 || ^4.0.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@afterpack/core": "~0.2.
|
|
32
|
-
"@afterpack/integration-utils": "0.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",
|