@vinktarhq/cli 0.1.0

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.
Files changed (121) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/LICENSE +21 -0
  3. package/README.md +378 -0
  4. package/dist/bin.d.ts +2 -0
  5. package/dist/bin.js +28 -0
  6. package/dist/bin.js.map +1 -0
  7. package/dist/bundler/core.d.ts +140 -0
  8. package/dist/bundler/core.js +320 -0
  9. package/dist/bundler/core.js.map +1 -0
  10. package/dist/bundler/esbuild.d.ts +44 -0
  11. package/dist/bundler/esbuild.js +85 -0
  12. package/dist/bundler/esbuild.js.map +1 -0
  13. package/dist/bundler/rollup.d.ts +84 -0
  14. package/dist/bundler/rollup.js +221 -0
  15. package/dist/bundler/rollup.js.map +1 -0
  16. package/dist/bundler/rspack.d.ts +8 -0
  17. package/dist/bundler/rspack.js +8 -0
  18. package/dist/bundler/rspack.js.map +1 -0
  19. package/dist/bundler/webpack.d.ts +83 -0
  20. package/dist/bundler/webpack.js +104 -0
  21. package/dist/bundler/webpack.js.map +1 -0
  22. package/dist/cjs/bundler/core.d.ts +140 -0
  23. package/dist/cjs/bundler/core.js +331 -0
  24. package/dist/cjs/bundler/esbuild.d.ts +44 -0
  25. package/dist/cjs/bundler/esbuild.js +87 -0
  26. package/dist/cjs/bundler/rollup.d.ts +84 -0
  27. package/dist/cjs/bundler/rollup.js +226 -0
  28. package/dist/cjs/bundler/rspack.d.ts +8 -0
  29. package/dist/cjs/bundler/rspack.js +12 -0
  30. package/dist/cjs/bundler/webpack.d.ts +83 -0
  31. package/dist/cjs/bundler/webpack.js +107 -0
  32. package/dist/cjs/cli.d.ts +17 -0
  33. package/dist/cjs/cli.js +358 -0
  34. package/dist/cjs/commands/doctor.d.ts +15 -0
  35. package/dist/cjs/commands/doctor.js +134 -0
  36. package/dist/cjs/commands/inject.d.ts +70 -0
  37. package/dist/cjs/commands/inject.js +123 -0
  38. package/dist/cjs/commands/resolve.d.ts +32 -0
  39. package/dist/cjs/commands/resolve.js +130 -0
  40. package/dist/cjs/commands/upload.d.ts +74 -0
  41. package/dist/cjs/commands/upload.js +254 -0
  42. package/dist/cjs/config.d.ts +51 -0
  43. package/dist/cjs/config.js +152 -0
  44. package/dist/cjs/debug-id.d.ts +176 -0
  45. package/dist/cjs/debug-id.js +323 -0
  46. package/dist/cjs/discover.d.ts +50 -0
  47. package/dist/cjs/discover.js +235 -0
  48. package/dist/cjs/env.d.ts +22 -0
  49. package/dist/cjs/env.js +52 -0
  50. package/dist/cjs/glob.d.ts +34 -0
  51. package/dist/cjs/glob.js +112 -0
  52. package/dist/cjs/http.d.ts +68 -0
  53. package/dist/cjs/http.js +211 -0
  54. package/dist/cjs/index.d.ts +17 -0
  55. package/dist/cjs/index.js +53 -0
  56. package/dist/cjs/limits.d.ts +35 -0
  57. package/dist/cjs/limits.js +38 -0
  58. package/dist/cjs/multipart.d.ts +28 -0
  59. package/dist/cjs/multipart.js +44 -0
  60. package/dist/cjs/package.json +3 -0
  61. package/dist/cjs/upload.d.ts +178 -0
  62. package/dist/cjs/upload.js +394 -0
  63. package/dist/cjs/url.d.ts +25 -0
  64. package/dist/cjs/url.js +43 -0
  65. package/dist/cjs/version.d.ts +10 -0
  66. package/dist/cjs/version.js +13 -0
  67. package/dist/cli.d.ts +17 -0
  68. package/dist/cli.js +354 -0
  69. package/dist/cli.js.map +1 -0
  70. package/dist/commands/doctor.d.ts +15 -0
  71. package/dist/commands/doctor.js +132 -0
  72. package/dist/commands/doctor.js.map +1 -0
  73. package/dist/commands/inject.d.ts +70 -0
  74. package/dist/commands/inject.js +120 -0
  75. package/dist/commands/inject.js.map +1 -0
  76. package/dist/commands/resolve.d.ts +32 -0
  77. package/dist/commands/resolve.js +128 -0
  78. package/dist/commands/resolve.js.map +1 -0
  79. package/dist/commands/upload.d.ts +74 -0
  80. package/dist/commands/upload.js +252 -0
  81. package/dist/commands/upload.js.map +1 -0
  82. package/dist/config.d.ts +51 -0
  83. package/dist/config.js +150 -0
  84. package/dist/config.js.map +1 -0
  85. package/dist/debug-id.d.ts +176 -0
  86. package/dist/debug-id.js +307 -0
  87. package/dist/debug-id.js.map +1 -0
  88. package/dist/discover.d.ts +50 -0
  89. package/dist/discover.js +229 -0
  90. package/dist/discover.js.map +1 -0
  91. package/dist/env.d.ts +22 -0
  92. package/dist/env.js +50 -0
  93. package/dist/env.js.map +1 -0
  94. package/dist/glob.d.ts +34 -0
  95. package/dist/glob.js +109 -0
  96. package/dist/glob.js.map +1 -0
  97. package/dist/http.d.ts +68 -0
  98. package/dist/http.js +203 -0
  99. package/dist/http.js.map +1 -0
  100. package/dist/index.d.ts +17 -0
  101. package/dist/index.js +18 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/limits.d.ts +35 -0
  104. package/dist/limits.js +36 -0
  105. package/dist/limits.js.map +1 -0
  106. package/dist/multipart.d.ts +28 -0
  107. package/dist/multipart.js +41 -0
  108. package/dist/multipart.js.map +1 -0
  109. package/dist/upload.d.ts +178 -0
  110. package/dist/upload.js +383 -0
  111. package/dist/upload.js.map +1 -0
  112. package/dist/url.d.ts +25 -0
  113. package/dist/url.js +40 -0
  114. package/dist/url.js.map +1 -0
  115. package/dist/version.d.ts +10 -0
  116. package/dist/version.js +11 -0
  117. package/dist/version.js.map +1 -0
  118. package/dist/vite.d.ts +74 -0
  119. package/dist/vite.js +166 -0
  120. package/dist/vite.js.map +1 -0
  121. package/package.json +141 -0
@@ -0,0 +1,226 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stampChunk = stampChunk;
4
+ exports.repairChunks = repairChunks;
5
+ exports.writeMaps = writeMaps;
6
+ exports.vinktarRollup = vinktarRollup;
7
+ const promises_1 = require("node:fs/promises");
8
+ const node_path_1 = require("node:path");
9
+ const debug_id_js_1 = require("../debug-id.js");
10
+ const discover_js_1 = require("../discover.js");
11
+ const core_js_1 = require("./core.js");
12
+ /**
13
+ * Whether the snippet can go at the TOP of this chunk without corrupting its map.
14
+ *
15
+ * Under Rollup it can: nothing re-derives the map after `renderChunk`, so the inserted line is
16
+ * accounted for exactly, in `repairChunks`.
17
+ *
18
+ * Under Rolldown it cannot, and this is the difference between a working map and a meaningless
19
+ * one. Rolldown's Oxc minifier runs AFTER every `renderChunk` hook and rebuilds the chunk's map
20
+ * from the code we hand it, composed against a base that knows nothing about our extra line — so
21
+ * every mapping in the file lands inside the snippet. A build proved it: the first segment of a
22
+ * Vite 8 chunk pointed at generated column 1, which is the middle of the injected IIFE.
23
+ *
24
+ * There is no hook between those two steps, and expressing the insertion as a real transform map
25
+ * would mean emitting a segment per token for every chunk — which is what both incumbents do, and
26
+ * what their magic-string dependency is for. Appending moves nothing, so it needs no map at all;
27
+ * the cost is that a chunk which throws while initialising does not register its id there.
28
+ *
29
+ * `this.meta.rolldownVersion` is Rolldown's own marker, absent under Rollup.
30
+ */
31
+ function prependable(context) {
32
+ return context?.meta?.rolldownVersion === undefined;
33
+ }
34
+ /**
35
+ * The name a chunk answers to in every hook.
36
+ *
37
+ * `fileName` still holds a hash PLACEHOLDER during `renderChunk` — the whole point of the hook is
38
+ * that the hash has not been computed yet — so keying on it there and looking it up by the final
39
+ * name later matched nothing at all. `preliminaryFileName` is the one that is stable across both.
40
+ */
41
+ function keyOf(chunk) {
42
+ return chunk.preliminaryFileName ?? chunk.fileName ?? '';
43
+ }
44
+ /** Stamp one chunk and remember what its map will owe. Shared with the Vite plugin. */
45
+ function stampChunk(code, rawChunk, tracked, context) {
46
+ const chunk = (rawChunk ?? {});
47
+ const stamped = (0, core_js_1.stamp)(code, { prepend: prependable(context) });
48
+ tracked.set(keyOf(chunk), { debugId: stamped.debugId, line: stamped.line });
49
+ /**
50
+ * `map: null`, and it must be exactly that — not an omitted key.
51
+ *
52
+ * Rollup reads it as a strict null check: `null` keeps this transform OUT of the chunk's
53
+ * sourcemap chain and leaves the existing map alone, while `undefined` (an omitted key) enters
54
+ * the chain as a MISSING link, which makes Rollup log `SOURCEMAP_BROKEN` and collapse the whole
55
+ * chain to empty mappings. The line this inserted is accounted for in {@link repairChunks}
56
+ * instead, exactly, rather than through a generated transform map.
57
+ */
58
+ return stamped.changed ? { code: stamped.code, map: null } : null;
59
+ }
60
+ /**
61
+ * Square the chunk's map up with the snippet, and put back the comment that ran after us.
62
+ *
63
+ * Both halves belong in `generateBundle` with `order: 'pre'`, and both are load-bearing:
64
+ *
65
+ * - **The comment.** Vite 8 is Rolldown, and its Oxc minifier runs after `renderChunk`: it strips
66
+ * the `//# debugId=` line and leaves the snippet, so the uploader read no id, derived a fresh
67
+ * one from the minified bytes and filed the map under an id no stack frame reports. The
68
+ * embedded marker survives minification and is what this package reads back, but the comment is
69
+ * what every OTHER tool reads.
70
+ * - **The mappings.** Inserting a line above the code shifts every generated line below it by
71
+ * one, and splicing one empty group into `mappings` is the exact repair. It has to happen HERE,
72
+ * before any other plugin's `generateBundle`, because Vite's own
73
+ * `vite:build-import-analysis` rewrites the entry chunk and then does
74
+ * `combineSourcemaps(fileName, [itsMap, chunk.map])`. Its map is measured against the code
75
+ * INCLUDING our line; combining it with a `chunk.map` that is one line short does not merely
76
+ * lose precision, it collapses to empty mappings — the entry chunk of every Vite build with a
77
+ * dynamic import, silently resolving nothing.
78
+ *
79
+ * `order: 'pre'` is therefore not politeness; it is the difference between a working map and an
80
+ * empty one.
81
+ */
82
+ function repairChunks(bundle, tracked) {
83
+ for (const asset of Object.values(bundle)) {
84
+ const chunk = asset;
85
+ if (chunk.type !== 'chunk' || typeof chunk.code !== 'string')
86
+ continue;
87
+ const found = tracked.get(keyOf(chunk));
88
+ if (found === undefined)
89
+ continue;
90
+ // Placed the way `inject` places it — before a trailing `sourceMappingURL`, never after.
91
+ // Devtools stop reading at the mapping comment, so a debugId line below it would make the map
92
+ // unreachable, which is a strange way to fix a source-map tool.
93
+ chunk.code = (0, debug_id_js_1.setDebugIdComment)(chunk.code, found.debugId);
94
+ const map = chunk.map;
95
+ if (map === null || map === undefined || typeof map.mappings !== 'string')
96
+ continue;
97
+ if (found.line !== null) {
98
+ map.mappings = String((0, debug_id_js_1.shiftMappings)({ mappings: map.mappings }, found.line)['mappings']);
99
+ }
100
+ // Vite carries `debugId` across its own re-combination by name, and nothing else, so this is
101
+ // the one field worth setting here rather than only on disk.
102
+ map['debugId'] = found.debugId;
103
+ }
104
+ }
105
+ /**
106
+ * Write each chunk's map to disk, because Rollup will not write ours.
107
+ *
108
+ * Rollup emits a chunk's map from the reference it captured while rendering, so an edit made in
109
+ * `generateBundle` reaches the bundle object every other plugin sees and never reaches the file.
110
+ * It survived for chunks a later Vite plugin happened to rebuild and vanished for the rest, which
111
+ * is the worst shape a bug of this kind can take: half the maps in a build one line out, and no
112
+ * warning from anything.
113
+ *
114
+ * Writing the file afterwards is safe in a way that rewriting a chunk would not be. Nothing hashes
115
+ * a source map: its name comes from the chunk's, no integrity attribute covers it, and no importer
116
+ * reads its contents.
117
+ */
118
+ async function writeMaps(dir, bundle, tracked, done) {
119
+ const chunks = Object.values(bundle).filter((asset) => {
120
+ const chunk = asset;
121
+ return chunk.type === 'chunk' && tracked.has(keyOf(chunk));
122
+ });
123
+ if (process.env['VINKTAR_DEBUG_TRACK'])
124
+ console.log('WRITEMAPS', dir, chunks.length, [...tracked.keys()], Object.keys(bundle));
125
+ if (chunks.length === 0)
126
+ return;
127
+ // One walk of the output, reusing the chunk-to-map resolution the uploader uses — which asks
128
+ // the chunk what its map is called before assuming a `<file>.map` sibling, and so copes with
129
+ // `output.sourcemapFileNames`.
130
+ const { artifacts } = await (0, discover_js_1.discover)(dir).catch(() => ({ artifacts: [] }));
131
+ const maps = new Map(artifacts.map((artifact) => [artifact.file, artifact.map]));
132
+ for (const chunk of chunks) {
133
+ const found = tracked.get(keyOf(chunk));
134
+ const map = chunk.map;
135
+ if (map === null || map === undefined || typeof map.mappings !== 'string')
136
+ continue;
137
+ const path = maps.get((0, node_path_1.join)(dir, chunk.fileName ?? ''));
138
+ if (process.env['VINKTAR_DEBUG_TRACK'])
139
+ console.log('WM', chunk.fileName, path, found.line, typeof map.mappings);
140
+ // Idempotent per file per build: `writeBundle` fires once per output, and two outputs writing
141
+ // into one directory must not each rewrite the other's maps.
142
+ if (path === undefined || path === null || done.has(path))
143
+ continue;
144
+ done.add(path);
145
+ try {
146
+ await (0, promises_1.writeFile)(path, JSON.stringify({ ...map, debugId: found.debugId, debug_id: found.debugId }), 'utf8');
147
+ }
148
+ catch {
149
+ // A read-only volume, or a map the bundler did not actually write. The chunk still carries
150
+ // its id, and the uploader will stamp whatever map it does find.
151
+ }
152
+ }
153
+ }
154
+ function vinktarRollup(options = {}) {
155
+ if ((0, core_js_1.disabled)(options))
156
+ return inert();
157
+ const tracked = new Map();
158
+ const repaired = new Set();
159
+ const stamping = options.injectDebugIds !== false;
160
+ const run = (0, core_js_1.session)(options);
161
+ return {
162
+ name: 'vinktar',
163
+ buildStart() {
164
+ // A watch rebuild rewrites every file, so last build's bookkeeping would suppress this
165
+ // build's repairs.
166
+ tracked.clear();
167
+ repaired.clear();
168
+ },
169
+ renderChunk: {
170
+ order: 'post',
171
+ handler(code, chunk) {
172
+ return stamping ? stampChunk(code, chunk, tracked, this) : null;
173
+ },
174
+ },
175
+ generateBundle: {
176
+ order: 'pre',
177
+ handler(_options, bundle) {
178
+ repairChunks(bundle, tracked);
179
+ },
180
+ },
181
+ /**
182
+ * Every output, not the first one.
183
+ *
184
+ * The previous version latched on the output directory and returned early for the rest, so a
185
+ * build with a client output and an SSR output — SvelteKit, Nuxt, Remix, or plain
186
+ * `output: [a, b]` — uploaded the first and silently dropped the second. Re-uploading costs
187
+ * nothing: the content hashes are checked against the server before any bytes are sent.
188
+ */
189
+ async writeBundle(output, bundle) {
190
+ const dir = outputDir(output);
191
+ if (dir === '')
192
+ return;
193
+ await writeMaps(dir, bundle, tracked, repaired);
194
+ await run.upload(dir);
195
+ // Deleting here rather than only in `closeBundle`, because `closeBundle` fires only when the
196
+ // caller closes the bundle — Vite and the Rollup CLI do, `rollup.rollup().write()` does not.
197
+ // Leaving the maps in a public directory on that path is the exact leak this deletes.
198
+ await run.cleanup();
199
+ },
200
+ async closeBundle() {
201
+ await run.cleanup();
202
+ },
203
+ };
204
+ }
205
+ /**
206
+ * The plugin that does nothing, for `disable: true`.
207
+ *
208
+ * A whole plugin rather than a flag threaded through every hook, so that a config reused by
209
+ * vitest or Storybook costs a function call and not a directory walk.
210
+ */
211
+ function inert() {
212
+ return {
213
+ name: 'vinktar',
214
+ buildStart() { },
215
+ renderChunk: { order: 'post', handler: () => null },
216
+ generateBundle: { order: 'pre', handler: () => { } },
217
+ writeBundle: async () => { },
218
+ closeBundle: async () => { },
219
+ };
220
+ }
221
+ function outputDir(output) {
222
+ const dir = output.dir ?? (output.file === undefined ? '' : (0, node_path_1.join)(output.file, '..'));
223
+ if (dir === '')
224
+ return '';
225
+ return (0, node_path_1.isAbsolute)(dir) ? dir : (0, node_path_1.join)(process.cwd(), dir);
226
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * rspack reimplements webpack's plugin API — `thisCompilation`, `processAssets`, the stage
3
+ * constants and `compilation.updateAsset` all behave the same way — so the plugin is the same
4
+ * plugin. This module exists so an rspack config can say `vinktarRspack` and read correctly,
5
+ * rather than importing something called "webpack" into a build that is not one.
6
+ */
7
+ export { VinktarWebpackPlugin as VinktarRspackPlugin, vinktarWebpack as vinktarRspack } from './webpack.js';
8
+ export type { BundlerOptions } from './core.js';
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.vinktarRspack = exports.VinktarRspackPlugin = void 0;
4
+ /**
5
+ * rspack reimplements webpack's plugin API — `thisCompilation`, `processAssets`, the stage
6
+ * constants and `compilation.updateAsset` all behave the same way — so the plugin is the same
7
+ * plugin. This module exists so an rspack config can say `vinktarRspack` and read correctly,
8
+ * rather than importing something called "webpack" into a build that is not one.
9
+ */
10
+ var webpack_js_1 = require("./webpack.js");
11
+ Object.defineProperty(exports, "VinktarRspackPlugin", { enumerable: true, get: function () { return webpack_js_1.VinktarWebpackPlugin; } });
12
+ Object.defineProperty(exports, "vinktarRspack", { enumerable: true, get: function () { return webpack_js_1.vinktarWebpack; } });
@@ -0,0 +1,83 @@
1
+ import { type BundlerOptions } from './core.js';
2
+ /**
3
+ * The webpack plugin, which is also the rspack plugin.
4
+ *
5
+ * ```js
6
+ * const { vinktarWebpack } = require('@vinktarhq/cli/webpack');
7
+ * module.exports = { plugins: [new vinktarWebpack({ urlPrefix: '/static/' })] };
8
+ * ```
9
+ *
10
+ * rspack reimplements webpack's plugin API, including `processAssets` and its stage constants, so
11
+ * one class serves both. `@vinktarhq/cli/rspack` re-exports this under its own name because that is
12
+ * what a reader of an rspack config expects to see.
13
+ *
14
+ * ## The stage matters
15
+ *
16
+ * `PROCESS_ASSETS_STAGE_OPTIMIZE_HASH` is the documented point for "changing the asset in a way
17
+ * that affects its hash", and it is where the real content hashes are computed. Doing this any
18
+ * later — in `afterEmit`, say — means the file on disk no longer matches the hash in its own name,
19
+ * and everything downstream that recorded that hash (a PWA precache manifest, an integrity
20
+ * attribute, a precompressed copy) is pointing at bytes that are gone.
21
+ *
22
+ * One BEFORE it, though, not at it. Taps sharing a stage run in registration order, and rspack's
23
+ * real-content-hash pass is native and registered before any user plugin — so at the stage itself
24
+ * the hash was computed from the pre-injection bytes and the filename described a file that never
25
+ * existed. A build proved it: with the plugin and without it, rspack emitted the same
26
+ * `main.<hash>.js` for different content. webpack is unaffected either way, so both take the
27
+ * earlier slot.
28
+ *
29
+ * It is also after `PROCESS_ASSETS_STAGE_DEV_TOOLING`, which is where `SourceMapDevToolPlugin`
30
+ * emits the `.map` assets and appends the `sourceMappingURL` comment. That ordering is what lets
31
+ * the map be corrected in the same pass as the chunk: the injected line shifts every mapping
32
+ * below it, and a map fixed in a later hook would already have been hashed and written.
33
+ */
34
+ /** Just enough of webpack's shape to compile without depending on it. */
35
+ interface Compiler {
36
+ hooks: {
37
+ thisCompilation: {
38
+ tap(name: string, fn: (compilation: Compilation) => void): void;
39
+ };
40
+ afterEmit: {
41
+ tapPromise(name: string, fn: (compilation: Compilation) => Promise<void>): void;
42
+ };
43
+ };
44
+ options: {
45
+ output?: {
46
+ path?: string;
47
+ };
48
+ };
49
+ webpack?: {
50
+ Compilation?: {
51
+ PROCESS_ASSETS_STAGE_OPTIMIZE_HASH?: number;
52
+ };
53
+ sources?: SourceLibrary;
54
+ };
55
+ }
56
+ interface SourceLibrary {
57
+ RawSource: new (value: string) => unknown;
58
+ }
59
+ interface Compilation {
60
+ hooks: {
61
+ processAssets: {
62
+ tap(options: {
63
+ name: string;
64
+ stage: number;
65
+ }, fn: (assets: Record<string, Asset>) => void): void;
66
+ };
67
+ };
68
+ updateAsset(name: string, source: unknown): void;
69
+ getAsset(name: string): {
70
+ source: Asset;
71
+ } | undefined;
72
+ }
73
+ interface Asset {
74
+ source(): string | Buffer;
75
+ }
76
+ export declare class VinktarWebpackPlugin {
77
+ private readonly options;
78
+ constructor(options?: BundlerOptions);
79
+ apply(compiler: Compiler): void;
80
+ }
81
+ /** Named for how a config reads: `new vinktarWebpack({ … })`. */
82
+ export declare const vinktarWebpack: typeof VinktarWebpackPlugin;
83
+ export type { BundlerOptions } from './core.js';
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.vinktarWebpack = exports.VinktarWebpackPlugin = void 0;
4
+ const core_js_1 = require("./core.js");
5
+ const NAME = 'vinktar';
6
+ /** webpack's own value for this stage, when the compiler does not expose the constant. */
7
+ const STAGE_OPTIMIZE_HASH = 2500;
8
+ class VinktarWebpackPlugin {
9
+ options;
10
+ constructor(options = {}) {
11
+ this.options = options;
12
+ }
13
+ apply(compiler) {
14
+ if ((0, core_js_1.disabled)(this.options))
15
+ return;
16
+ const stamping = this.options.injectDebugIds !== false;
17
+ const RawSource = compiler.webpack?.sources?.RawSource;
18
+ const stage = (compiler.webpack?.Compilation?.PROCESS_ASSETS_STAGE_OPTIMIZE_HASH ?? STAGE_OPTIMIZE_HASH) - 1;
19
+ const run = (0, core_js_1.session)(this.options);
20
+ compiler.hooks.thisCompilation.tap(NAME, (compilation) => {
21
+ compilation.hooks.processAssets.tap({ name: NAME, stage }, (assets) => {
22
+ if (!stamping)
23
+ return;
24
+ const write = (name, value) => {
25
+ // `RawSource` is reached through the compiler rather than imported, so this file has no
26
+ // build-time dependency on webpack at all — and so rspack's own sources are used under
27
+ // rspack rather than webpack's.
28
+ compilation.updateAsset(name, RawSource === undefined ? value : new RawSource(value));
29
+ };
30
+ for (const name of Object.keys(assets)) {
31
+ if (!(0, core_js_1.isScript)(name))
32
+ continue;
33
+ const asset = compilation.getAsset(name);
34
+ if (asset === undefined)
35
+ continue;
36
+ const code = String(asset.source.source());
37
+ const stamped = (0, core_js_1.stamp)(code);
38
+ if (!stamped.changed)
39
+ continue;
40
+ write(name, stamped.code);
41
+ // The map is corrected in the same stage, from the same bytes. Skipping it leaves every
42
+ // line one out of step, which is worse than no map: the frame resolves, to the wrong
43
+ // line, and nobody doubts a source map that answered.
44
+ const mapName = mapAssetOf(name, code, assets);
45
+ if (mapName === null)
46
+ continue;
47
+ const map = compilation.getAsset(mapName);
48
+ if (map === undefined)
49
+ continue;
50
+ try {
51
+ write(mapName, (0, core_js_1.injectIntoMap)(String(map.source.source()), stamped.debugId, stamped.line));
52
+ }
53
+ catch {
54
+ // A map asset that is not JSON is not ours to rewrite.
55
+ }
56
+ }
57
+ });
58
+ });
59
+ compiler.hooks.afterEmit.tapPromise(NAME, async () => {
60
+ const dir = compiler.options.output?.path ?? '';
61
+ if (dir === '')
62
+ return;
63
+ await run.upload(dir);
64
+ await run.cleanup();
65
+ });
66
+ }
67
+ }
68
+ exports.VinktarWebpackPlugin = VinktarWebpackPlugin;
69
+ const SOURCE_MAPPING_COMMENT = /^\/\/[#@] sourceMappingURL=(.*)$/gm;
70
+ /**
71
+ * The map asset belonging to a chunk asset.
72
+ *
73
+ * `output.sourceMapFilename` is configurable — `[file].map` is only the default, and a build that
74
+ * puts maps under `sourcemaps/[name].map` has no `<file>.map` asset at all. The chunk names its
75
+ * own map in the comment `SourceMapDevToolPlugin` just appended, so that is asked first and the
76
+ * sibling is the fallback.
77
+ */
78
+ function mapAssetOf(name, code, assets) {
79
+ let last = null;
80
+ for (const match of code.matchAll(SOURCE_MAPPING_COMMENT))
81
+ last = match;
82
+ const referenced = last?.[1]?.trim();
83
+ if (referenced !== undefined && referenced !== '' && !referenced.startsWith('data:')) {
84
+ const slash = name.lastIndexOf('/');
85
+ const directory = slash === -1 ? '' : name.slice(0, slash + 1);
86
+ const target = normalise(`${directory}${(referenced.split('?')[0] ?? '').split('#')[0] ?? ''}`);
87
+ if (target in assets)
88
+ return target;
89
+ }
90
+ return `${name}.map` in assets ? `${name}.map` : null;
91
+ }
92
+ /** Collapse `a/../b` and `./b`, which a relative sourceMappingURL legitimately contains. */
93
+ function normalise(path) {
94
+ const parts = [];
95
+ for (const segment of path.split('/')) {
96
+ if (segment === '.' || segment === '')
97
+ continue;
98
+ if (segment === '..') {
99
+ parts.pop();
100
+ continue;
101
+ }
102
+ parts.push(segment);
103
+ }
104
+ return parts.join('/');
105
+ }
106
+ /** Named for how a config reads: `new vinktarWebpack({ … })`. */
107
+ exports.vinktarWebpack = VinktarWebpackPlugin;
@@ -0,0 +1,17 @@
1
+ import { VERSION } from './version.js';
2
+ export interface Args {
3
+ readonly positional: string[];
4
+ readonly flags: Map<string, string | boolean>;
5
+ /** Values of repeatable flags, in order. `--ignore` and `--header` are the two. */
6
+ readonly repeated: Map<string, string[]>;
7
+ }
8
+ export declare function parse(argv: readonly string[]): Args;
9
+ /**
10
+ * Exit codes: 0 fine, 1 the thing did not work, 2 it worked and something is wrong anyway.
11
+ *
12
+ * Two rather than one for `--strict`, so a pipeline can tell "the upload failed" from "the upload
13
+ * succeeded and half your chunks have no maps" — which are different problems with different
14
+ * owners, and merging them means neither gets fixed.
15
+ */
16
+ export declare function run(argv: readonly string[], log?: (message?: any, ...optionalParams: any[]) => void, fail?: (message?: any, ...optionalParams: any[]) => void): Promise<number>;
17
+ export { VERSION };