@rustwrap/webpack 1.0.2 → 1.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
@@ -78,12 +78,14 @@ Taking the **strictest** clause on each line yields the declared range. Reading
78
78
  | **module.rules (loaders)** | Real loader chains via `loader-runner`: `test`/`include`/`exclude`/`resourceQuery`/`oneOf`/`enforce:pre|post`/`use` array/`options`/custom loaders. JS/TS/JSX transpilation is done by **Oxc** (transpile-only loaders `ts-loader`/`babel-loader`/`swc-loader`/`esbuild-loader` are skipped — equivalent, faster). |
79
79
  | **CSS** | Native: `.scss`/`.sass` (consumer's `sass`), `.less` (consumer's `less`), `.css`; style-injected, or **extracted** when `MiniCssExtractPlugin` is present. **CSS Modules** (`*.module.*`) are properly scoped via `postcss-modules` (scoped class names + `{local:scoped}` export map + `composes`). |
80
80
  | **Asset modules** | `asset/resource` (emit + URL), `asset/inline` (data URI), `asset/source`, `asset` (auto by `parser.dataUrlCondition.maxSize`); `generator.filename`/`output.assetModuleFilename`. |
81
- | **externals** | object map / array / RegExp / sync-callback function (`({request},cb)` & `(ctx,req,cb)`) / `{root}` external + `output.globals`. |
81
+ | **Node globals (browser target)** | Auto-polyfills `process`, `Buffer`, and `global` for `web` builds — parity with webpack's `ProvidePlugin`/node-libs-browser. Using real scope analysis (acorn + eslint-scope), a **`process` shim** (nextTick/env/platform/…), the **`buffer` package's `Buffer`**, and `global`→globalThis are injected **only into modules that reference them as free (unbound) identifiers**. So dependencies that assume Node (e.g. telemetry SDKs pulling in `readable-stream`/`buffer` such as `@aria/webjs-sdk`) work in the browser instead of throwing `process is not defined`. No-op on `target:'node'` and for code that never references them. |
82
+ | **externals** | object map / array / RegExp / sync-callback function (`({request},cb)` & `(ctx,req,cb)`) / `{root}` → external + `output.globals`. **Exact-request match** (webpack semantics): an entry like `{react:"React"}` externalizes `react` only, **not** subpaths like `react/jsx-runtime` (those are bundled, so e.g. the automatic JSX runtime keeps its `jsx`/`jsxs`). Externals are reachable from **both `import` and `require()`** — a bundled CommonJS dependency's internal `require("<external>")` is rewritten to the same global, so it never leaves a bare `require` (which would throw in the browser). |
83
+ | **TypeScript** | Transpiled by Oxc (types stripped, JSX per `tsconfig`). **Ambient `const enum` member accesses are inlined to literals** (tsc parity) by reading the const enums declared in the project's `.ts/.d.ts` and any pulled in via tsconfig `files`/`include` or triple-slash `/// <reference>` — without this, accesses like `XrmClientApi.Constants.X.Y` would survive as runtime references to a namespace that doesn't exist at runtime. Regular (non-const) `enum`s emit runtime objects as usual. |
82
84
  | **resolve** | `alias`, `extensions`, `mainFields`, `mainFiles`, `conditionNames`, `modules`, `extensionAlias`, `symlinks`, `fallback` (`false`→empty module), nearest `tsconfig.json` paths. |
83
85
  | **devtool (source maps)** | `source-map`, `inline-source-map`, `hidden-source-map`, `nosources-*`, `eval-*` (≈inline). Emits `.map` + `sourceMappingURL`. |
84
86
  | **target** | `web` (default) and `node`/`node*` (→ Rolldown `platform:'node'`, node builtins external). |
85
87
  | **optimization** | `minimize`; **`minimizer` TerserPlugin `terserOptions` mapped to Rolldown's minifier**: `compress.drop_console`/`drop_debugger`/`passes`/`ecma`(→target)/`keep_classnames`/`keep_fnames`, `mangle` on/off/`toplevel`/`keep_*`, `format.comments`→`legalComments`. `usedExports:false` disables tree-shaking. Tree-shaking + scope-hoisting are always on via Rolldown. |
86
- | **Built-in plugins** | `DefinePlugin` (nested keys), `EnvironmentPlugin`, `ProvidePlugin` (**real free-variable scope analysis** via acorn + eslint-scope), `BannerPlugin`, `IgnorePlugin`, `NormalModuleReplacementPlugin`, `SourceMapDevToolPlugin`/`EvalSourceMapDevToolPlugin`, `ProgressPlugin`, `optimize.LimitChunkCountPlugin` (forces single chunk), `LoaderOptionsPlugin`, `WatchIgnorePlugin`, `HotModuleReplacementPlugin` (enables `module.hot`), `ContextReplacementPlugin`. |
88
+ | **Built-in plugins** | `DefinePlugin` (nested keys; **AST-aware** — replaces expressions only, never the contents of string/template literals or comments), `EnvironmentPlugin`, `ProvidePlugin` (**real free-variable scope analysis** via acorn + eslint-scope), `BannerPlugin`, `IgnorePlugin`, `NormalModuleReplacementPlugin`, `SourceMapDevToolPlugin`/`EvalSourceMapDevToolPlugin`, `ProgressPlugin`, `optimize.LimitChunkCountPlugin` (forces single chunk), `LoaderOptionsPlugin`, `WatchIgnorePlugin`, `HotModuleReplacementPlugin` (enables `module.hot`), `ContextReplacementPlugin`. |
87
89
  | **Dev server / HMR** | `webpack serve` / `new webpack.DevServer(options, compiler)`. HTTP static serving (`static`), `historyApiFallback`, watch + rebuild, **SSE live-reload**, and a `module.hot`/`import.meta.hot` runtime so HMR-guarded code runs. (Hot updates apply via fast full reload — see Approximated.) |
88
90
  | **Third-party plugins** | Anything tapping `compilation.hooks.processAssets`/`compiler.hooks.emit`/`done`/etc. works (Copy-style, Html-style, Banner, analyzers). |
89
91
  | **performance** | `hints`/`maxAssetSize` enforced (warning/error). |
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  /*
4
- * rollpack CLI — a minimal `webpack`-compatible command. pcf-scripts uses the programmatic API
4
+ * @rustwrap/webpack CLI — a minimal `webpack`-compatible command. pcf-scripts uses the programmatic API
5
5
  * (require("webpack")(config, cb)), so this CLI only covers basic `webpack [--config f] [--mode m]`
6
6
  * invocations for direct use.
7
7
  */
@@ -11,7 +11,7 @@ const Module = require("module");
11
11
 
12
12
  // webpack.config.js files often `require()` webpack-ecosystem plugins (TerserPlugin, analyzer,
13
13
  // eslint-webpack-plugin, ...) that Rolldown doesn't need. Stub any that aren't resolvable so the
14
- // config loads; rollpack reads the relevant intent (mode, externals, Define/Banner) from the object.
14
+ // config loads; @rustwrap/webpack reads the relevant intent (mode, externals, Define/Banner) from the object.
15
15
  const STUB_PKGS = new Set([
16
16
  "terser-webpack-plugin", "webpack-bundle-analyzer", "eslint-webpack-plugin",
17
17
  "css-minimizer-webpack-plugin", "mini-css-extract-plugin", "fork-ts-checker-webpack-plugin",
@@ -65,7 +65,7 @@ if (opts.mode) config.mode = opts.mode;
65
65
  if (opts.watch) config.watch = true;
66
66
 
67
67
  if (opts.serve) {
68
- // `rollpack serve` / `webpack serve` — start the dev server.
68
+ // `@rustwrap/webpack serve` / `webpack serve` — start the dev server.
69
69
  if (!config.mode) config.mode = "development";
70
70
  const devServerOpts = Object.assign({ hot: true }, config.devServer || {});
71
71
  if (opts.port) devServerOpts.port = opts.port;
package/lib/build.js CHANGED
@@ -116,16 +116,45 @@ function convertChunkTemplate(t) {
116
116
  function definePlugin(define) {
117
117
  const keys = Object.keys(define).sort((a, b) => b.length - a.length);
118
118
  if (!keys.length) return null;
119
+ const acorn = require("acorn");
120
+ const tt = acorn.tokTypes;
119
121
  const escaped = keys.map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
120
122
  const re = new RegExp(`(?<![\\w$.])(${escaped.join("|")})(?![\\w$])`, "g");
123
+ const replaceAll = (code) => code.replace(re, (m) => (define[m] != null ? define[m] : m));
121
124
  return {
122
- name: "rollpack:define",
125
+ name: "rustwrap:define",
123
126
  transform(code, id) {
124
127
  if (/[/\\]node_modules[/\\]/.test(id) && !/process\.env|typeof process|__DEV__/.test(code)) return null;
125
128
  re.lastIndex = 0;
126
129
  if (!re.test(code)) return null;
130
+ // Collect ranges of string/template/regex literals and comments. webpack's DefinePlugin
131
+ // replaces expressions only — never the contents of strings or comments — so we must skip
132
+ // any match landing inside these ranges (a raw text replace would corrupt string literals).
133
+ const protectedRanges = [];
134
+ try {
135
+ acorn.parse(code, {
136
+ ecmaVersion: "latest",
137
+ sourceType: "module",
138
+ allowReturnOutsideFunction: true,
139
+ allowAwaitOutsideFunction: true,
140
+ allowHashBang: true,
141
+ onComment: (_block, _text, start, end) => protectedRanges.push([start, end]),
142
+ onToken: (t) => {
143
+ // `template` tokens are the literal chunks between `${}` — protecting them leaves the
144
+ // interpolated `${expr}` code (separate tokens) eligible for replacement, like webpack.
145
+ if (t.type === tt.string || t.type === tt.template || t.type === tt.regexp) protectedRanges.push([t.start, t.end]);
146
+ },
147
+ });
148
+ } catch (_) {
149
+ // Unparseable (already-CJS/odd syntax) — fall back to the identifier-boundary regex rather
150
+ // than break the build. This preserves prior behavior for the rare unparseable module.
151
+ re.lastIndex = 0;
152
+ return { code: replaceAll(code), map: null };
153
+ }
154
+ const inProtected = (idx) => protectedRanges.some(([s, e]) => idx >= s && idx < e);
127
155
  re.lastIndex = 0;
128
- return { code: code.replace(re, (m) => (define[m] != null ? define[m] : m)), map: null };
156
+ const out = code.replace(re, (m, _g1, offset) => (inProtected(offset) ? m : (define[m] != null ? define[m] : m)));
157
+ return { code: out, map: null };
129
158
  },
130
159
  };
131
160
  }
@@ -137,13 +166,13 @@ function providePlugin(provide, _context) {
137
166
  const eslintScope = require("eslint-scope");
138
167
  const simple = entries.filter(([k]) => !k.includes("."));
139
168
  return {
140
- name: "rollpack:provide",
169
+ name: "rustwrap:provide",
141
170
  transform(code, id) {
142
171
  if (/\.(css|scss|sass|less|svg)$/.test(id) || !simple.length) return null;
143
172
  if (!simple.some(([k]) => code.includes(k))) return null;
144
173
  let ast;
145
174
  try {
146
- ast = acorn.parse(code, { ecmaVersion: "latest", sourceType: "module", allowReturnOutsideFunction: true, allowAwaitOutsideFunction: true, allowHashBang: true });
175
+ ast = acorn.parse(code, { ecmaVersion: "latest", sourceType: "module", ranges: true, allowReturnOutsideFunction: true, allowAwaitOutsideFunction: true, allowHashBang: true });
147
176
  } catch (_) { return null; } // unparseable (already-CJS/odd) — skip rather than break the build
148
177
  let manager;
149
178
  try { manager = eslintScope.analyze(ast, { ecmaVersion: 2022, sourceType: "module", ignoreEval: true, optimistic: true }); }
@@ -168,6 +197,78 @@ function providePlugin(provide, _context) {
168
197
  };
169
198
  }
170
199
 
200
+ // Bundled CommonJS modules can `require("<external>")` (e.g. React's CJS `react/jsx-runtime` does
201
+ // `require("react")`). rolldown maps externals to globals for ESM imports via output.globals, but it
202
+ // does NOT rewrite a CJS module's internal `require(external)` -> the global, leaving a bare
203
+ // `require(...)` that throws "require is not defined" in the browser. This transform rewrites
204
+ // `require("<external>")` to the same platform/global the external resolves to, restoring webpack's
205
+ // behavior (where externals are reachable from both `import` and `require`).
206
+ function externalRequirePlugin(isExternal, globals) {
207
+ if (typeof isExternal !== "function") return null;
208
+ const RE = /(?<![\w.$])require\(\s*(['"])([^'"]+)\1\s*\)/g;
209
+ return {
210
+ name: "rustwrap:external-require",
211
+ transform(code) {
212
+ if (code.indexOf("require(") === -1) return null;
213
+ let changed = false;
214
+ const out = code.replace(RE, (m, _q, dep) => {
215
+ let ext;
216
+ try { ext = isExternal(dep); } catch { ext = false; }
217
+ if (!ext) return m;
218
+ let g;
219
+ try { g = globals(dep); } catch { g = undefined; }
220
+ if (!g || !/^[A-Za-z_$][\w$]*$/.test(g)) return m; // only simple global identifiers
221
+ changed = true;
222
+ // Reference the platform-provided global (same one output.globals binds for ESM imports);
223
+ // fall back to globalThis lookup if the bare binding isn't in scope.
224
+ return `(typeof ${g}!=="undefined"?${g}:(typeof globalThis!=="undefined"?globalThis:window)[${JSON.stringify(g)}])`;
225
+ });
226
+ return changed ? { code: out, map: null } : null;
227
+ },
228
+ };
229
+ }
230
+
231
+ // Node-builtin globals polyfill for browser targets (parity with webpack's ProvidePlugin +
232
+ // node-libs-browser, and pcf-scripts' esbuild `pcfEsbuildNodePolyfills`). Rolldown/webpack-5 do not
233
+ // auto-provide these, so a dependency that assumes Node (e.g. telemetry SDKs pulling in
234
+ // readable-stream/buffer) can reference a bare `process.nextTick`/`Buffer` that throws in the
235
+ // browser. Using the same free-variable scope analysis as ProvidePlugin, we inject `process`
236
+ // (inline shim), `global` (globalThis), and `Buffer` (the `buffer` package) ONLY into modules that
237
+ // reference them as free (unbound) identifiers — so it's a no-op for code that doesn't need them.
238
+ function nodePolyfillPlugin(platform) {
239
+ if (platform === "node") return null; // node target: real builtins, no shim
240
+ const acorn = require("acorn");
241
+ const eslintScope = require("eslint-scope");
242
+ const resolveSafe = (id) => { try { return require.resolve(id); } catch { return null; } };
243
+ const bufferPath = resolveSafe("buffer/");
244
+ const processPath = path.join(__dirname, "shims", "process.js");
245
+ const globalPath = path.join(__dirname, "shims", "global.js");
246
+ const SHIM_PATHS = new Set([processPath, globalPath, bufferPath].filter(Boolean));
247
+ return {
248
+ name: "rustwrap:node-polyfill",
249
+ transform(code, id) {
250
+ if (SHIM_PATHS.has(path.normalize(id))) return null; // never inject into the shims themselves
251
+ // Skip rolldown's internal runtime/virtual modules — their interop helpers reference `Buffer`
252
+ // in `typeof` guards, which would otherwise pull the whole buffer polyfill into every bundle.
253
+ if (id.startsWith("\0") || /(?:^|[/\\])rolldown[/\\]|rolldown:/.test(id)) return null;
254
+ if (/\.(css|scss|sass|less|svg)$/.test(id)) return null;
255
+ if (!/(?<![\w.$])(process|Buffer|global)\b/.test(code)) return null;
256
+ let ast;
257
+ try { ast = acorn.parse(code, { ecmaVersion: "latest", sourceType: "module", ranges: true, allowReturnOutsideFunction: true, allowAwaitOutsideFunction: true, allowHashBang: true }); }
258
+ catch { return null; }
259
+ let mgr;
260
+ try { mgr = eslintScope.analyze(ast, { ecmaVersion: 2022, sourceType: "module", ignoreEval: true, optimistic: true }); }
261
+ catch { return null; }
262
+ const free = new Set(mgr.globalScope.through.map((r) => r.identifier.name));
263
+ let header = "";
264
+ if (free.has("process")) header += `import __rp_process from ${JSON.stringify(processPath)};\nvar process=__rp_process;\n`;
265
+ if (free.has("global")) header += `import __rp_global from ${JSON.stringify(globalPath)};\nvar global=__rp_global;\n`;
266
+ if (free.has("Buffer") && bufferPath) header += `import { Buffer as __rp_Buffer } from ${JSON.stringify(bufferPath)};\nvar Buffer=__rp_Buffer;\n`;
267
+ return header ? { code: header + code, map: null } : null;
268
+ },
269
+ };
270
+ }
271
+
171
272
  function ignorePlugin(ignores) {
172
273
  if (!ignores || !ignores.length) return null;
173
274
  const matches = (request, ctx) => ignores.some((opt) => {
@@ -177,9 +278,9 @@ function ignorePlugin(ignores) {
177
278
  if (typeof opt.checkResource === "function") return opt.checkResource(request, ctx);
178
279
  return false;
179
280
  });
180
- const VID = "\0rollpack-ignored";
281
+ const VID = "\0rustwrap-ignored";
181
282
  return {
182
- name: "rollpack:ignore",
283
+ name: "rustwrap:ignore",
183
284
  resolveId(source, importer) { if (matches(source, importer && path.dirname(importer))) return VID; return null; },
184
285
  load(id) { if (id === VID) return "export default {};"; return null; },
185
286
  };
@@ -188,7 +289,7 @@ function ignorePlugin(ignores) {
188
289
  function normalReplacePlugin(replacements) {
189
290
  if (!replacements || !replacements.length) return null;
190
291
  return {
191
- name: "rollpack:normal-replace",
292
+ name: "rustwrap:normal-replace",
192
293
  resolveId(source, importer) {
193
294
  for (const [re, repl] of replacements) {
194
295
  if (re.test(source)) {
@@ -209,17 +310,26 @@ function entryRel(e, chunkFileName) {
209
310
 
210
311
  async function runMake(compilation, cfg, context) {
211
312
  const compiler = compilation.compiler;
212
- const rp = compiler.$rollpack || {};
313
+ const rp = compiler.$rustwrap || {};
213
314
  const prod = cfg.mode !== "development" && cfg.mode !== "none";
214
315
  const minimize = readMinimize(cfg);
215
316
  const entries = normalizeEntries(cfg, context);
216
317
  const ext = buildExternals(cfg, context);
217
318
  const define = buildDefine(cfg, prod, rp.define);
319
+ // Inline ambient `const enum` member accesses to literals (tsc parity). Without this, oxc/rolldown
320
+ // leave e.g. `XrmClientApi.Constants.GlobalNotificationLevel.success` as a runtime reference to a
321
+ // namespace that doesn't exist at runtime -> "XrmClientApi is not defined". We feed the collected
322
+ // `Ns.Enum.Member` -> literal map through the same Define replacement. Explicit user defines win.
323
+ try {
324
+ const { collectConstEnumDefines } = require("./const-enum");
325
+ const ce = collectConstEnumDefines(context);
326
+ for (const k of Object.keys(ce)) if (define[k] == null) define[k] = ce[k];
327
+ } catch { /* typescript unavailable or parse failure -> skip inlining (non-fatal) */ }
218
328
  // When hot is enabled (dev server or HotModuleReplacementPlugin), make `module.hot` /
219
329
  // `import.meta.hot` resolve to the injected client runtime so HMR-guarded code runs.
220
330
  if (rp.hot) {
221
- define["module.hot"] = "(typeof window!=='undefined'&&window.__rollpack_hot__)";
222
- define["import.meta.hot"] = "(typeof window!=='undefined'&&window.__rollpack_hot__)";
331
+ define["module.hot"] = "(typeof window!=='undefined'&&window.__rustwrap_hot__)";
332
+ define["import.meta.hot"] = "(typeof window!=='undefined'&&window.__rustwrap_hot__)";
223
333
  }
224
334
  const resolve = buildResolve(cfg, context);
225
335
  const { sourcemap } = devtoolToRolldown(cfg.devtool);
@@ -232,6 +342,8 @@ async function runMake(compilation, cfg, context) {
232
342
  loaderPlugin(cfg, context, compilation),
233
343
  providePlugin(rp.provide, context),
234
344
  definePlugin(define),
345
+ externalRequirePlugin(ext.isExternal, ext.globals),
346
+ nodePolyfillPlugin(platform),
235
347
  ].filter(Boolean);
236
348
 
237
349
  const t0 = Date.now();
package/lib/compiler.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- * rollpack Compiler/Compilation — a tapable-based webpack lifecycle so real plugins (apply(compiler))
3
+ * @rustwrap/webpack Compiler/Compilation — a tapable-based webpack lifecycle so real plugins (apply(compiler))
4
4
  * run. The heavy lifting (producing entry bundles) happens in the `make` phase via Rolldown; plugins
5
5
  * then add/modify compilation.assets through processAssets/emit hooks before they're written.
6
6
  */
@@ -255,9 +255,24 @@ class Compiler {
255
255
  };
256
256
  run();
257
257
  let watcher;
258
+ // Ignore writes we cause ourselves (the build's own output dir) and irrelevant paths — otherwise
259
+ // emitting into output.path retriggers the watcher in an infinite rebuild/reload loop. fs.watch
260
+ // reports paths RELATIVE to root, so the output dir often has no leading separator (e.g.
261
+ // "out/controls/x/bundle.js") — anchor to start as well as after a separator.
262
+ const outPath = this.options && this.options.output && this.options.output.path;
263
+ const outRel = outPath ? path.relative(root, outPath).replace(/\\/g, "/") : "";
264
+ const ignored = (f) => {
265
+ if (!f) return false;
266
+ const n = f.replace(/\\/g, "/");
267
+ if (/(^|\/)(node_modules|\.git)(\/|$)/.test(n)) return true;
268
+ if (/\.d\.ts$/.test(n)) return true;
269
+ if (outRel && outRel !== "." && !outRel.startsWith("..") && (n === outRel || n.startsWith(outRel + "/"))) return true;
270
+ if (/^(out|dist)(\/|$)/.test(n)) return true; // fallback for default output dirs at the root
271
+ return false;
272
+ };
258
273
  try {
259
274
  watcher = fs.watch(root, { recursive: true }, (_ev, f) => {
260
- if (f && /node_modules|[\\/](out|dist)[\\/]|\.d\.ts$/.test(f)) return;
275
+ if (ignored(f)) return;
261
276
  if (building) return;
262
277
  this.hooks.invalid.call(f, Date.now());
263
278
  clearTimeout(timer); timer = setTimeout(run, (watchOptions && watchOptions.aggregateTimeout) || 200);
package/lib/config.js CHANGED
@@ -110,8 +110,11 @@ function buildExternals(cfg, context) {
110
110
  return undefined;
111
111
  };
112
112
  const resolveGlobal = (id) => {
113
- if (map[id]) return map[id];
114
- for (const k of Object.keys(map)) if (id === k || id.startsWith(k + "/")) return map[k];
113
+ // Webpack object externals match the EXACT request only (never subpaths). Matching subpaths
114
+ // (e.g. `react/jsx-runtime` under a `react` external) wrongly maps the automatic JSX runtime to
115
+ // the platform React global, which lacks jsx/jsxs -> "jsxs is not a function". Exact-match keeps
116
+ // react/jsx-runtime (and other subpath entrypoints) bundled, exactly as webpack does.
117
+ if (Object.prototype.hasOwnProperty.call(map, id)) return map[id];
115
118
  const f = callFn(id); if (f) return f;
116
119
  return undefined;
117
120
  };
@@ -125,8 +128,8 @@ function buildExternals(cfg, context) {
125
128
  return { isExternal, globals };
126
129
  }
127
130
 
128
- function buildDefine(cfg, prod, rollpackDefine) {
129
- const def = Object.assign({ "process.env.NODE_ENV": JSON.stringify(prod ? "production" : "development") }, rollpackDefine || {});
131
+ function buildDefine(cfg, prod, rustwrapDefine) {
132
+ const def = Object.assign({ "process.env.NODE_ENV": JSON.stringify(prod ? "production" : "development") }, rustwrapDefine || {});
130
133
  return def;
131
134
  }
132
135
 
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ /*
3
+ * Ambient `const enum` inlining (tsc-parity).
4
+ *
5
+ * tsc/ts-loader inline ambient `const enum` member accesses to literal values at compile time
6
+ * (e.g. `XrmClientApi.Constants.GlobalNotificationLevel.success` -> `1`). Fast TS transformers
7
+ * (oxc/rolldown, esbuild, swc) do NOT inline ambient const enums declared in `.d.ts`, leaving the
8
+ * member access as a runtime reference to a namespace object that doesn't exist at runtime ->
9
+ * "XrmClientApi is not defined".
10
+ *
11
+ * This module parses const enums (with their full namespace path) from the project's `.ts/.tsx`
12
+ * sources and any `.d.ts` they pull in via triple-slash `/// <reference path=.../>`, and returns a
13
+ * map of `Ns.Sub.Enum.Member` -> literal. build.js merges that map into the Define map so the
14
+ * existing (AST-aware) define replacement inlines them exactly like tsc would.
15
+ */
16
+ const fs = require("fs");
17
+ const path = require("path");
18
+
19
+ function loadTS(context) {
20
+ try { return require(require.resolve("typescript", { paths: [context, process.cwd()] })); }
21
+ catch { return null; }
22
+ }
23
+
24
+ // Walk a directory for .ts/.tsx sources (skipping node_modules/out/dist/dot-dirs).
25
+ function walkSources(dir, out, depth) {
26
+ if (depth > 10) return;
27
+ let entries;
28
+ try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
29
+ for (const e of entries) {
30
+ if (e.name === "node_modules" || e.name === "out" || e.name === "dist" || e.name.startsWith(".")) continue;
31
+ const full = path.join(dir, e.name);
32
+ if (e.isDirectory()) walkSources(full, out, depth + 1);
33
+ else if (/\.(ts|tsx)$/.test(e.name)) out.add(path.normalize(full));
34
+ }
35
+ }
36
+
37
+ // Resolve triple-slash `/// <reference path='...'/>` directives to absolute paths.
38
+ function refsIn(file) {
39
+ let text;
40
+ try { text = fs.readFileSync(file, "utf8"); } catch { return []; }
41
+ const out = [];
42
+ const re = /\/\/\/\s*<reference\s+path\s*=\s*['"]([^'"]+)['"]\s*\/>/g;
43
+ let m;
44
+ while ((m = re.exec(text))) out.push(path.resolve(path.dirname(file), m[1]));
45
+ return out;
46
+ }
47
+
48
+ // Parse one file's const enums into map[fullPath] = literalString.
49
+ function collectFile(ts, file, map) {
50
+ let text;
51
+ try { text = fs.readFileSync(file, "utf8"); } catch { return; }
52
+ if (!/const\s+enum/.test(text)) return; // fast skip — most files have none
53
+ let sf;
54
+ try { sf = ts.createSourceFile(file, text, ts.ScriptTarget.Latest, true); } catch { return; }
55
+ const nsStack = [];
56
+ const isConst = (node) => {
57
+ const mods = ts.canHaveModifiers ? ts.getModifiers(node) : node.modifiers;
58
+ return !!(mods && mods.some((m) => m.kind === ts.SyntaxKind.ConstKeyword));
59
+ };
60
+ const visit = (node) => {
61
+ if (ts.isModuleDeclaration(node) && node.name && node.body) {
62
+ nsStack.push(node.name.text);
63
+ ts.forEachChild(node.body, visit);
64
+ nsStack.pop();
65
+ return;
66
+ }
67
+ if (ts.isEnumDeclaration(node) && isConst(node)) {
68
+ const enumName = node.name.text;
69
+ let auto = 0;
70
+ for (const member of node.members) {
71
+ let memberName;
72
+ try { memberName = member.name.getText(sf).replace(/^['"]|['"]$/g, ""); } catch { continue; }
73
+ let value;
74
+ const init = member.initializer;
75
+ if (!init) {
76
+ value = auto; auto += 1;
77
+ } else if (ts.isNumericLiteral(init)) {
78
+ value = Number(init.text); auto = value + 1;
79
+ } else if (ts.isPrefixUnaryExpression(init) && init.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(init.operand)) {
80
+ value = -Number(init.operand.text); auto = value + 1;
81
+ } else if (ts.isStringLiteral(init)) {
82
+ value = init.text; // string enum member — no auto-increment afterwards
83
+ } else {
84
+ continue; // computed/complex initializer — cannot safely inline
85
+ }
86
+ const literal = typeof value === "string" ? JSON.stringify(value) : String(value);
87
+ map[[...nsStack, enumName, memberName].join(".")] = literal;
88
+ }
89
+ return;
90
+ }
91
+ ts.forEachChild(node, visit);
92
+ };
93
+ visit(sf);
94
+ }
95
+
96
+ // Build the const-enum -> literal map for a build rooted at `context`.
97
+ function collectConstEnumDefines(context) {
98
+ const ts = loadTS(context);
99
+ if (!ts) return {}; // typescript not installed -> no-op (degrade to prior behavior)
100
+
101
+ const files = new Set();
102
+
103
+ // Primary: resolve the tsconfig exactly as tsc would (honoring `extends`, `files`, `include`,
104
+ // `exclude`). This is what pulls in ambient typings declared via `files` in a base tsconfig
105
+ // (e.g. XrmClientApi.d.ts), which triple-slash scanning alone would miss.
106
+ try {
107
+ const configPath = ts.findConfigFile(context, ts.sys.fileExists, "tsconfig.json");
108
+ if (configPath) {
109
+ const host = Object.assign({}, ts.sys, { onUnRecoverableConfigFileDiagnostic() {} });
110
+ const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, host);
111
+ if (parsed && parsed.fileNames) for (const f of parsed.fileNames) files.add(path.normalize(f));
112
+ }
113
+ } catch { /* fall through to source walk */ }
114
+
115
+ // Fallback / supplement: walk sources under context when tsconfig resolution yields nothing.
116
+ if (files.size === 0) walkSources(context, files, 0);
117
+
118
+ // Always also follow triple-slash `/// <reference path>` directives transitively (covers files
119
+ // referenced directly from source but not listed by the tsconfig).
120
+ const queue = Array.from(files);
121
+ while (queue.length) {
122
+ const f = queue.shift();
123
+ for (const r of refsIn(f)) {
124
+ const n = path.normalize(r);
125
+ if (!files.has(n)) { files.add(n); queue.push(n); }
126
+ }
127
+ }
128
+
129
+ const map = {};
130
+ for (const f of files) {
131
+ try { collectFile(ts, f, map); } catch { /* keep going */ }
132
+ }
133
+ return map;
134
+ }
135
+
136
+ module.exports = { collectConstEnumDefines };
package/lib/css.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /*
3
3
  * Native CSS pipeline (webpack's css-loader/style-loader emit webpack-runtime-coupled output that a
4
- * non-webpack bundler can't consume, so rollpack handles CSS itself, Vite-style):
4
+ * non-webpack bundler can't consume, so @rustwrap/webpack handles CSS itself, Vite-style):
5
5
  * - .scss/.sass -> compiled with the consumer's `sass` (or node-sass) if available.
6
6
  * - .less -> compiled with the consumer's `less` if available.
7
7
  * - .css -> used as-is.
@@ -27,7 +27,7 @@ function compile(resource, context, compilation) {
27
27
  if (sass && sass.compile) return sass.compile(resource, { style: "compressed", loadPaths: [path.dirname(resource)] }).css;
28
28
  const nodeSass = resolveFrom("node-sass", dirs);
29
29
  if (nodeSass && nodeSass.renderSync) return nodeSass.renderSync({ file: resource, outputStyle: "compressed" }).css.toString();
30
- compilation && compilation.warnings.push({ message: `rollpack: no 'sass' available to compile ${path.basename(resource)} — emitting empty CSS` });
30
+ compilation && compilation.warnings.push({ message: `@rustwrap/webpack: no 'sass' available to compile ${path.basename(resource)} — emitting empty CSS` });
31
31
  return "";
32
32
  }
33
33
  if (ext === ".less") {
@@ -37,7 +37,7 @@ function compile(resource, context, compilation) {
37
37
  }
38
38
  return fs.readFileSync(resource, "utf8");
39
39
  } catch (e) {
40
- compilation && compilation.errors.push({ message: `rollpack CSS (${path.basename(resource)}): ${e && e.message || e}` });
40
+ compilation && compilation.errors.push({ message: `@rustwrap/webpack CSS (${path.basename(resource)}): ${e && e.message || e}` });
41
41
  return "";
42
42
  }
43
43
  }
@@ -91,7 +91,7 @@ async function handleCss(resource, cfg, compilation, prod, context, extract) {
91
91
  return { code: exportDefault, moduleType: "js" };
92
92
  }
93
93
 
94
- const inject = `(function(){if(typeof document==='undefined')return;var c=${JSON.stringify(css)};if(!c)return;var s=document.createElement('style');s.setAttribute('data-rollpack','');s.appendChild(document.createTextNode(c));document.head.appendChild(s);})();`;
94
+ const inject = `(function(){if(typeof document==='undefined')return;var c=${JSON.stringify(css)};if(!c)return;var s=document.createElement('style');s.setAttribute('data-rustwrap','');s.appendChild(document.createTextNode(c));document.head.appendChild(s);})();`;
95
95
  return { code: `${inject}\n${exportDefault}`, moduleType: "js" };
96
96
  }
97
97
 
package/lib/dev-server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- * rollpack dev server — a webpack-dev-server-shaped dev server over the rollpack Compiler.
3
+ * @rustwrap/webpack dev server — a webpack-dev-server-shaped dev server over the @rustwrap/webpack Compiler.
4
4
  *
5
5
  * It serves the compiled assets (+ static dirs) over HTTP, watches sources and rebuilds via the
6
6
  * Compiler, and pushes updates to the browser over Server-Sent Events. The injected client either
@@ -27,7 +27,7 @@ function mime(file) { return MIME[path.extname(file).toLowerCase()] || "applicat
27
27
  // Browser client: connects SSE, applies hot dispose handlers, then reloads on each successful build.
28
28
  const CLIENT = `(function(){
29
29
  if (typeof window === "undefined" || !window.EventSource) return;
30
- var hot = window.__rollpack_hot__ || (window.__rollpack_hot__ = (function(){
30
+ var hot = window.__rustwrap_hot__ || (window.__rustwrap_hot__ = (function(){
31
31
  var accepts = [], disposes = [], statusHandlers = [], status = "idle", data = {};
32
32
  function setStatus(s){ status = s; statusHandlers.forEach(function(h){ try { h(s); } catch(e){} }); }
33
33
  return {
@@ -40,15 +40,15 @@ const CLIENT = `(function(){
40
40
  };
41
41
  })());
42
42
  var first = true;
43
- var es = new EventSource("/__rollpack_sse");
43
+ var es = new EventSource("/__rustwrap_sse");
44
44
  es.addEventListener("message", function(ev){
45
45
  var msg; try { msg = JSON.parse(ev.data); } catch(e){ return; }
46
46
  if (msg.type === "connected") { first = false; return; }
47
- if (msg.type === "errors") { console.error("%c[rollpack] build failed", "color:red", "\\n" + (msg.errors||[]).join("\\n")); return; }
47
+ if (msg.type === "errors") { console.error("%c[@rustwrap/webpack] build failed", "color:red", "\\n" + (msg.errors||[]).join("\\n")); return; }
48
48
  if (msg.type === "ok") {
49
49
  hot._setStatus("check");
50
50
  try { hot._disposes.forEach(function(cb){ try { cb(hot.data); } catch(e){} }); } catch(e){}
51
- console.log("[rollpack] update — reloading");
51
+ console.log("[@rustwrap/webpack] update — reloading");
52
52
  hot._setStatus("apply");
53
53
  location.reload();
54
54
  }
@@ -68,7 +68,7 @@ function normalizeStatic(stat, context) {
68
68
  }
69
69
 
70
70
  function injectClient(html) {
71
- const tag = `<script src="/__rollpack_hmr_client.js"></script>`;
71
+ const tag = `<script src="/__rustwrap_hmr_client.js"></script>`;
72
72
  if (/<\/body>/i.test(html)) return html.replace(/<\/body>/i, tag + "</body>");
73
73
  if (/<\/head>/i.test(html)) return html.replace(/<\/head>/i, tag + "</head>");
74
74
  return html + "\n" + tag;
@@ -98,14 +98,14 @@ class DevServer {
98
98
  historyApiFallback: o.historyApiFallback,
99
99
  };
100
100
  // Enable hot defines for the build.
101
- if (o.hot !== false) { compiler.$rollpack = compiler.$rollpack || {}; compiler.$rollpack.hot = true; }
101
+ if (o.hot !== false) { compiler.$rustwrap = compiler.$rustwrap || {}; compiler.$rustwrap.hot = true; }
102
102
 
103
103
  this.server = http.createServer((req, res) => this.handle(req, res, ctx));
104
104
  return new Promise((resolve) => {
105
105
  this.server.listen(port, host, () => {
106
106
  const actualPort = (this.server.address() && this.server.address().port) || port;
107
107
  const url = `http://${host === "0.0.0.0" ? "localhost" : host}:${actualPort}/`;
108
- console.log(`\x1b[36m\x1b[1mrollpack\x1b[0m dev server running at \x1b[33m${url}\x1b[0m`);
108
+ console.log(`\x1b[36m\x1b[1m@rustwrap/webpack\x1b[0m dev server running at \x1b[33m${url}\x1b[0m`);
109
109
  // Build + watch, push updates to clients.
110
110
  this.watching = compiler.watch(compiler.options.watchOptions || {}, (err, stats) => {
111
111
  if (err) { console.error(err); return; }
@@ -128,8 +128,8 @@ class DevServer {
128
128
 
129
129
  handle(req, res, ctx) {
130
130
  const url = decodeURIComponent((req.url || "/").split("?")[0]);
131
- if (url === "/__rollpack_sse") return this.sse(res);
132
- if (url === "/__rollpack_hmr_client.js") { res.writeHead(200, { "Content-Type": "application/javascript", "Cache-Control": "no-cache" }); return res.end(CLIENT); }
131
+ if (url === "/__rustwrap_sse") return this.sse(res);
132
+ if (url === "/__rustwrap_hmr_client.js") { res.writeHead(200, { "Content-Type": "application/javascript", "Cache-Control": "no-cache" }); return res.end(CLIENT); }
133
133
  const rel = url.replace(/^\/+/, "") || "index.html";
134
134
  const bases = [ctx.outDir, ...ctx.staticDirs];
135
135
  for (const b of bases) if (this.serveFile(path.join(b, rel), res)) return;
@@ -138,7 +138,7 @@ class DevServer {
138
138
  for (const b of bases) if (this.serveFile(path.join(b, "index.html"), res)) return;
139
139
  }
140
140
  res.writeHead(404, { "Content-Type": "text/plain" });
141
- res.end("rollpack dev server: not found — " + url);
141
+ res.end("@rustwrap/webpack dev server: not found — " + url);
142
142
  }
143
143
 
144
144
  serveFile(file, res) {
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- * rollpack — a webpack-compatible Node API and CLI backed by the Rolldown bundler.
3
+ * @rustwrap/webpack — a webpack-compatible Node API and CLI backed by the Rolldown bundler.
4
4
  *
5
5
  * This is the public entry: the `webpack(options, callback)` factory, the Compiler/Compilation
6
6
  * lifecycle (tapable hooks, so real plugins run), and the full `webpack.*` namespace. The actual
@@ -32,11 +32,11 @@ function webpack(options, callback) {
32
32
  function createCompiler(options) {
33
33
  const context = options.context || process.cwd();
34
34
  const compiler = new Compiler(context, options);
35
- compiler.$rollpack = { define: {}, provide: {}, ignore: [], normalReplace: [] };
35
+ compiler.$rustwrap = { define: {}, provide: {}, ignore: [], normalReplace: [] };
36
36
  compiler.hooks.environment.call();
37
37
  compiler.hooks.afterEnvironment.call();
38
38
 
39
- // Apply user plugins (real apply(compiler) — taps hooks / populates $rollpack).
39
+ // Apply user plugins (real apply(compiler) — taps hooks / populates $rustwrap).
40
40
  for (const p of options.plugins || []) {
41
41
  try {
42
42
  if (p && typeof p.apply === "function") p.apply(compiler);
@@ -47,16 +47,16 @@ function createCompiler(options) {
47
47
  compiler.hooks.afterResolvers.call(compiler);
48
48
 
49
49
  // The make phase: Rolldown build -> compilation.assets.
50
- compiler.hooks.make.tapPromise("rollpack", (compilation) => runMake(compilation, options, context));
50
+ compiler.hooks.make.tapPromise("rustwrap", (compilation) => runMake(compilation, options, context));
51
51
 
52
52
  // After assets are produced: performance hints + ignoreWarnings (before Stats is created).
53
- compiler.hooks.afterEmit.tapPromise("rollpack:post", async (compilation) => {
53
+ compiler.hooks.afterEmit.tapPromise("rustwrap:post", async (compilation) => {
54
54
  applyPerformance(options, compilation);
55
55
  filterWarnings(options, compilation);
56
56
  });
57
57
 
58
58
  // Default console summary (unless stats are silenced).
59
- compiler.hooks.done.tapPromise("rollpack:summary", async (stats) => {
59
+ compiler.hooks.done.tapPromise("rustwrap:summary", async (stats) => {
60
60
  const quiet = options.stats === false || options.stats === "none" || options.stats === "errors-only"
61
61
  || (options.infrastructureLogging && (options.infrastructureLogging.level === "none" || options.infrastructureLogging.level === "error"));
62
62
  if (!quiet) printSummary(stats);
@@ -95,7 +95,7 @@ function printSummary(stats) {
95
95
  const total = (j.assets || []).reduce((s, a) => s + a.size, 0);
96
96
  for (const e of j.errors || []) console.log(`${C.y}ERROR${C.r} ${e.message}`);
97
97
  for (const w of j.warnings || []) console.log(`${C.y}WARNING${C.r} ${w.message}`);
98
- console.log(`${C.c}${C.b}rollpack${C.r} ${C.g}${(j.assets || []).length} assets${C.r} ${C.m}${fmtSize(total)}${C.r} ${C.d}via rolldown in${C.r} ${C.y}${fmtTime(j.time || 0)}${C.r}`);
98
+ console.log(`${C.c}${C.b}@rustwrap/webpack${C.r} ${C.g}${(j.assets || []).length} assets${C.r} ${C.m}${fmtSize(total)}${C.r} ${C.d}via rolldown in${C.r} ${C.y}${fmtTime(j.time || 0)}${C.r}`);
99
99
  for (const a of j.assets || []) console.log(` ${C.d}asset${C.r} ${C.c}${a.name}${C.r} ${C.m}${fmtSize(a.size)}${C.r}`);
100
100
  }
101
101
 
package/lib/loaders.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  /*
3
- * rollpack loader system — runs real webpack loader chains (module.rules) via loader-runner, so
3
+ * @rustwrap/webpack loader system — runs real webpack loader chains (module.rules) via loader-runner, so
4
4
  * css-loader/style-loader/sass-loader/@svgr/raw-loader/url-loader/file-loader/custom loaders work.
5
5
  *
6
6
  * JS/TS/JSX transpilation is left to Rolldown/Oxc (faster, equivalent output), so the well-known
@@ -129,7 +129,7 @@ function loaderPlugin(cfg, context, compilation) {
129
129
  const cssExtract = require("./css").cssExtractEnabled(cfg);
130
130
  const hasRules = buckets.pre.length || buckets.normal.length || buckets.post.length || (buckets._oneOf && buckets._oneOf.length);
131
131
  return {
132
- name: "rollpack:loaders",
132
+ name: "rustwrap:loaders",
133
133
  async load(id) {
134
134
  const [resource, query] = id.split("?");
135
135
  // Native CSS pipeline, independent of configured css/style loaders.
package/lib/plugins.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  /*
3
3
  * Built-in webpack plugins. Bundler-affecting plugins (Define/Provide/Environment/Ignore/
4
- * NormalModuleReplacement) populate `compiler.$rollpack`, which build.js reads during the Rolldown
4
+ * NormalModuleReplacement) populate `compiler.$rustwrap`, which build.js reads during the Rolldown
5
5
  * make phase. Asset-affecting plugins (Banner) tap compilation.processAssets. The rest are faithful
6
6
  * no-ops or thin shims so configs load and run.
7
7
  */
@@ -18,14 +18,14 @@ function flattenDefinitions(defs, prefix, out) {
18
18
 
19
19
  class DefinePlugin {
20
20
  constructor(definitions) { this.definitions = definitions || {}; }
21
- apply(compiler) { Object.assign(compiler.$rollpack.define, flattenDefinitions(this.definitions, "", {})); }
21
+ apply(compiler) { Object.assign(compiler.$rustwrap.define, flattenDefinitions(this.definitions, "", {})); }
22
22
  }
23
23
  DefinePlugin.runtimeValue = (fn, deps) => { const v = fn({}); return typeof v === "string" ? v : JSON.stringify(v); };
24
24
 
25
25
  class EnvironmentPlugin {
26
26
  constructor(...keys) { this.keys = Array.isArray(keys[0]) ? keys[0] : (typeof keys[0] === "object" ? keys[0] : keys); }
27
27
  apply(compiler) {
28
- const d = compiler.$rollpack.define;
28
+ const d = compiler.$rustwrap.define;
29
29
  if (Array.isArray(this.keys)) for (const k of this.keys) d[`process.env.${k}`] = JSON.stringify(process.env[k] !== undefined ? process.env[k] : "");
30
30
  else for (const [k, def] of Object.entries(this.keys)) d[`process.env.${k}`] = JSON.stringify(process.env[k] !== undefined ? process.env[k] : def);
31
31
  }
@@ -33,7 +33,7 @@ class EnvironmentPlugin {
33
33
 
34
34
  class ProvidePlugin {
35
35
  constructor(definitions) { this.definitions = definitions || {}; }
36
- apply(compiler) { Object.assign(compiler.$rollpack.provide, this.definitions); }
36
+ apply(compiler) { Object.assign(compiler.$rustwrap.provide, this.definitions); }
37
37
  }
38
38
 
39
39
  class BannerPlugin {
@@ -69,12 +69,12 @@ class BannerPlugin {
69
69
 
70
70
  class IgnorePlugin {
71
71
  constructor(options) { this.options = (options && options.resourceRegExp) ? options : { resourceRegExp: options && options.checkResource ? undefined : options, checkResource: options && options.checkResource }; }
72
- apply(compiler) { compiler.$rollpack.ignore.push(this.options); }
72
+ apply(compiler) { compiler.$rustwrap.ignore.push(this.options); }
73
73
  }
74
74
 
75
75
  class NormalModuleReplacementPlugin {
76
76
  constructor(resourceRegExp, newResource) { this.resourceRegExp = resourceRegExp; this.newResource = newResource; }
77
- apply(compiler) { compiler.$rollpack.normalReplace.push([this.resourceRegExp, this.newResource]); }
77
+ apply(compiler) { compiler.$rustwrap.normalReplace.push([this.resourceRegExp, this.newResource]); }
78
78
  }
79
79
 
80
80
  class ContextReplacementPlugin {
@@ -110,7 +110,7 @@ class RuntimeChunkPlugin extends NoopPlugin {}
110
110
  class SplitChunksPlugin extends NoopPlugin {}
111
111
  class WatchIgnorePlugin extends NoopPlugin {}
112
112
  class LoaderOptionsPlugin extends NoopPlugin {}
113
- class HotModuleReplacementPlugin { apply(compiler) { compiler.$rollpack = compiler.$rollpack || {}; compiler.$rollpack.hot = true; } }
113
+ class HotModuleReplacementPlugin { apply(compiler) { compiler.$rustwrap = compiler.$rustwrap || {}; compiler.$rustwrap.hot = true; } }
114
114
  class DllPlugin extends NoopPlugin {}
115
115
  class DllReferencePlugin extends NoopPlugin {}
116
116
  class HashedModuleIdsPlugin extends NoopPlugin {}
@@ -0,0 +1,8 @@
1
+ // Browser `global` shim (parity with webpack, which maps `global` -> the global object).
2
+ export default (typeof globalThis !== "undefined"
3
+ ? globalThis
4
+ : typeof self !== "undefined"
5
+ ? self
6
+ : typeof window !== "undefined"
7
+ ? window
8
+ : this);
@@ -0,0 +1,31 @@
1
+ // Browser `process` shim (parity with webpack's process/browser). Covers what readable-stream and
2
+ // most Node-assuming libraries touch (nextTick, env, platform, versions, no-op event methods).
3
+ var process = {
4
+ env: {},
5
+ argv: [],
6
+ browser: true,
7
+ platform: "browser",
8
+ arch: "browser",
9
+ version: "",
10
+ versions: {},
11
+ title: "browser",
12
+ nextTick: function (cb) {
13
+ var args = [].slice.call(arguments, 1);
14
+ var run = function () { cb.apply(null, args); };
15
+ (typeof queueMicrotask !== "undefined" ? queueMicrotask : function (f) { setTimeout(f, 0); })(run);
16
+ },
17
+ cwd: function () { return "/"; },
18
+ chdir: function () {},
19
+ on: function () { return process; },
20
+ once: function () { return process; },
21
+ off: function () { return process; },
22
+ addListener: function () { return process; },
23
+ removeListener: function () { return process; },
24
+ removeAllListeners: function () { return process; },
25
+ emit: function () { return false; },
26
+ prependListener: function () { return process; },
27
+ listeners: function () { return []; },
28
+ binding: function () { throw new Error("process.binding is not supported in the browser"); },
29
+ umask: function () { return 0; },
30
+ };
31
+ export default process;
package/lib/stats.js CHANGED
@@ -21,7 +21,7 @@ function createStats(compilation) {
21
21
  toJson(opts) {
22
22
  return {
23
23
  version: require("../package.json").version,
24
- rollpack: true,
24
+ rustwrap: true,
25
25
  hash: compilation.hash || "",
26
26
  time,
27
27
  builtAt: Date.now(),
@@ -47,7 +47,7 @@ function createStats(compilation) {
47
47
  for (const e of errors) lines.push(`${C.y}ERROR${C.r} ` + (e.message || String(e)));
48
48
  for (const w of warnings) lines.push(`${C.y}WARNING${C.r} ` + (w.message || String(w)));
49
49
  const total = assetList.reduce((s, a) => s + a.size, 0);
50
- lines.push(`${C.c}rollpack${C.r} ${C.g}${assetList.length} assets${C.r} ${C.d}${fmt(total)} in ${time}ms${C.r}`);
50
+ lines.push(`${C.c}@rustwrap/webpack${C.r} ${C.g}${assetList.length} assets${C.r} ${C.d}${fmt(total)} in ${time}ms${C.r}`);
51
51
  for (const a of assetList) lines.push(` ${C.d}asset${C.r} ${C.c}${a.name}${C.r} ${fmt(a.size)}`);
52
52
  return lines.join("\n");
53
53
  },
package/package.json CHANGED
@@ -1,45 +1,46 @@
1
- {
2
- "name": "@rustwrap/webpack",
3
- "version": "1.0.2",
4
- "description": "A webpack-compatible Node API and CLI backed by the Rolldown bundler (Rust/Oxc) for fast builds and excellent tree-shaking. Drop-in `webpack` override for pcf-scripts and webpack-based pipelines.",
5
- "main": "lib/index.js",
6
- "publishConfig": {
7
- "access": "public"
8
- },
9
- "scripts": {
10
- "test": "node test/run.js"
11
- },
12
- "bin": {
13
- "webpack": "bin/rollpack.js",
14
- "rollpack": "bin/rollpack.js"
15
- },
16
- "files": [
17
- "lib/",
18
- "bin/",
19
- "README.md"
20
- ],
21
- "dependencies": {
22
- "acorn": "^8.17.0",
23
- "eslint-scope": "^9.1.2",
24
- "loader-runner": "^4.3.2",
25
- "mime-types": "^3.0.2",
26
- "postcss": "^8.5.16",
27
- "postcss-modules": "^6.0.1",
28
- "rolldown": "^1.1.3",
29
- "schema-utils": "^4.3.3",
30
- "tapable": "^2.3.3",
31
- "terser-webpack-plugin": "^5.6.1",
32
- "webpack-sources": "^3.5.0"
33
- },
34
- "keywords": [
35
- "webpack",
36
- "rolldown",
37
- "bundler",
38
- "pcf",
39
- "tree-shaking"
40
- ],
41
- "license": "MIT",
42
- "engines": {
43
- "node": "^20.19.0 || ^22.13.0 || >=24"
44
- }
45
- }
1
+ {
2
+ "name": "@rustwrap/webpack",
3
+ "version": "1.0.3",
4
+ "description": "A webpack-compatible Node API and CLI backed by the Rolldown bundler (Rust/Oxc) for fast builds and excellent tree-shaking. Drop-in `webpack` override for pcf-scripts and webpack-based pipelines.",
5
+ "main": "lib/index.js",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "scripts": {
10
+ "test": "node test/run.js"
11
+ },
12
+ "bin": {
13
+ "webpack": "bin/rustwrap-webpack.js",
14
+ "rustwrap-webpack": "bin/rustwrap-webpack.js"
15
+ },
16
+ "files": [
17
+ "lib/",
18
+ "bin/",
19
+ "README.md"
20
+ ],
21
+ "dependencies": {
22
+ "acorn": "^8.17.0",
23
+ "eslint-scope": "^9.1.2",
24
+ "loader-runner": "^4.3.2",
25
+ "mime-types": "^3.0.2",
26
+ "postcss": "^8.5.16",
27
+ "postcss-modules": "^6.0.1",
28
+ "rolldown": "^1.1.3",
29
+ "schema-utils": "^4.3.3",
30
+ "tapable": "^2.3.3",
31
+ "terser-webpack-plugin": "^5.6.1",
32
+ "webpack-sources": "^3.5.0",
33
+ "buffer": "^6.0.3"
34
+ },
35
+ "keywords": [
36
+ "webpack",
37
+ "rolldown",
38
+ "bundler",
39
+ "pcf",
40
+ "tree-shaking"
41
+ ],
42
+ "license": "MIT",
43
+ "engines": {
44
+ "node": "^20.19.0 || ^22.13.0 || >=24"
45
+ }
46
+ }