@nx/angular-rspack 19.0.0-alpha.30

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 (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/code-pushup.config.ts +13 -0
  4. package/dist/lib/config/create-config.d.ts +11 -0
  5. package/dist/lib/config/create-config.d.ts.map +1 -0
  6. package/dist/lib/config/create-config.js +417 -0
  7. package/dist/lib/config/dev-server-config-utils.d.ts +3 -0
  8. package/dist/lib/config/dev-server-config-utils.d.ts.map +1 -0
  9. package/dist/lib/config/dev-server-config-utils.js +101 -0
  10. package/dist/lib/config/helpers.d.ts +3 -0
  11. package/dist/lib/config/helpers.d.ts.map +1 -0
  12. package/dist/lib/config/helpers.js +37 -0
  13. package/dist/lib/config/style-config-utils.d.ts +261 -0
  14. package/dist/lib/config/style-config-utils.d.ts.map +1 -0
  15. package/dist/lib/config/style-config-utils.js +62 -0
  16. package/dist/lib/index.d.ts +3 -0
  17. package/dist/lib/index.d.ts.map +1 -0
  18. package/dist/lib/index.js +5 -0
  19. package/dist/lib/models/angular-rspack-plugin-options.d.ts +114 -0
  20. package/dist/lib/models/angular-rspack-plugin-options.d.ts.map +1 -0
  21. package/dist/lib/models/angular-rspack-plugin-options.js +2 -0
  22. package/dist/lib/models/augmented-compilation.d.ts +11 -0
  23. package/dist/lib/models/augmented-compilation.d.ts.map +1 -0
  24. package/dist/lib/models/augmented-compilation.js +4 -0
  25. package/dist/lib/models/index.d.ts +4 -0
  26. package/dist/lib/models/index.d.ts.map +1 -0
  27. package/dist/lib/models/index.js +6 -0
  28. package/dist/lib/models/normalize-options.d.ts +16 -0
  29. package/dist/lib/models/normalize-options.d.ts.map +1 -0
  30. package/dist/lib/models/normalize-options.js +362 -0
  31. package/dist/lib/plugins/angular-rspack-plugin.d.ts +9 -0
  32. package/dist/lib/plugins/angular-rspack-plugin.d.ts.map +1 -0
  33. package/dist/lib/plugins/angular-rspack-plugin.js +148 -0
  34. package/dist/lib/plugins/angular-ssr-dev-server.d.ts +8 -0
  35. package/dist/lib/plugins/angular-ssr-dev-server.d.ts.map +1 -0
  36. package/dist/lib/plugins/angular-ssr-dev-server.js +49 -0
  37. package/dist/lib/plugins/client/ssr-reload-client.d.ts +2 -0
  38. package/dist/lib/plugins/client/ssr-reload-client.d.ts.map +1 -0
  39. package/dist/lib/plugins/client/ssr-reload-client.js +16 -0
  40. package/dist/lib/plugins/loaders/angular-partial-transform.loader.d.ts +3 -0
  41. package/dist/lib/plugins/loaders/angular-partial-transform.loader.d.ts.map +1 -0
  42. package/dist/lib/plugins/loaders/angular-partial-transform.loader.js +36 -0
  43. package/dist/lib/plugins/loaders/angular-transform.loader.d.ts +3 -0
  44. package/dist/lib/plugins/loaders/angular-transform.loader.d.ts.map +1 -0
  45. package/dist/lib/plugins/loaders/angular-transform.loader.js +39 -0
  46. package/dist/lib/plugins/ng-rspack.d.ts +8 -0
  47. package/dist/lib/plugins/ng-rspack.d.ts.map +1 -0
  48. package/dist/lib/plugins/ng-rspack.js +114 -0
  49. package/dist/lib/plugins/rxjs-esm-resolution.d.ts +5 -0
  50. package/dist/lib/plugins/rxjs-esm-resolution.d.ts.map +1 -0
  51. package/dist/lib/plugins/rxjs-esm-resolution.js +15 -0
  52. package/dist/lib/plugins/server/ssr-reload-server.d.ts +6 -0
  53. package/dist/lib/plugins/server/ssr-reload-server.d.ts.map +1 -0
  54. package/dist/lib/plugins/server/ssr-reload-server.js +18 -0
  55. package/dist/lib/plugins/tools/dev-tools-ignore-plugin.d.ts +17 -0
  56. package/dist/lib/plugins/tools/dev-tools-ignore-plugin.d.ts.map +1 -0
  57. package/dist/lib/plugins/tools/dev-tools-ignore-plugin.js +57 -0
  58. package/dist/lib/ssr/server.d.ts +13 -0
  59. package/dist/lib/ssr/server.d.ts.map +1 -0
  60. package/dist/lib/ssr/server.js +47 -0
  61. package/eslint.next.config.js +42 -0
  62. package/package.json +83 -0
  63. package/vitest.config.mts +21 -0
  64. package/vitest.integration.config.mts +28 -0
@@ -0,0 +1,362 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.INDEX_HTML_CSR = void 0;
4
+ exports.resolveFileReplacements = resolveFileReplacements;
5
+ exports.getHasServer = getHasServer;
6
+ exports.validateSsr = validateSsr;
7
+ exports.validateOptimization = validateOptimization;
8
+ exports.normalizeOptions = normalizeOptions;
9
+ const tslib_1 = require("tslib");
10
+ const devkit_1 = require("@nx/devkit");
11
+ const node_assert_1 = tslib_1.__importDefault(require("node:assert"));
12
+ const node_fs_1 = require("node:fs");
13
+ const node_path_1 = require("node:path");
14
+ const find_project_for_path_1 = require("nx/src/project-graph/utils/find-project-for-path");
15
+ exports.INDEX_HTML_CSR = 'index.csr.html';
16
+ /**
17
+ * Resolves file replacement paths to absolute paths based on the provided root directory.
18
+ *
19
+ * @param fileReplacements - Array of file replacements with relative paths.
20
+ * @param root - The root directory to resolve the paths against.
21
+ * @returns Array of file replacements resolved against the root.
22
+ */
23
+ function resolveFileReplacements(fileReplacements, root) {
24
+ return fileReplacements.map((fileReplacement) => ({
25
+ replace: (0, node_path_1.resolve)(root, fileReplacement.replace),
26
+ with: (0, node_path_1.resolve)(root, fileReplacement.with),
27
+ }));
28
+ }
29
+ function getHasServer(root, server, ssr) {
30
+ return !!(server &&
31
+ ssr &&
32
+ ssr.entry &&
33
+ (0, node_fs_1.existsSync)((0, node_path_1.join)(root, server)) &&
34
+ (0, node_fs_1.existsSync)((0, node_path_1.join)(root, ssr.entry)));
35
+ }
36
+ function validateSsr(ssr) {
37
+ if (!ssr) {
38
+ return;
39
+ }
40
+ if (ssr === true) {
41
+ throw new Error('The "ssr" option should be an object or false. Please check the documentation.');
42
+ }
43
+ if (typeof ssr === 'object')
44
+ if (!ssr.entry) {
45
+ throw new Error('The "ssr" option should have an "entry" property. Please check the documentation.');
46
+ }
47
+ else if (ssr.experimentalPlatform === 'neutral') {
48
+ console.warn('The "ssr.experimentalPlatform" option is not currently supported. Node will be used as the platform.');
49
+ }
50
+ }
51
+ function validateOptimization(optimization) {
52
+ if (typeof optimization === 'boolean' || optimization === undefined) {
53
+ return;
54
+ }
55
+ if (typeof optimization === 'object')
56
+ console.warn('The "optimization" option currently only supports a boolean value. Please check the documentation.');
57
+ }
58
+ function normalizeOptions(options) {
59
+ const { fileReplacements = [], server, ssr, optimization } = options;
60
+ validateSsr(ssr);
61
+ const normalizedSsr = !ssr
62
+ ? false
63
+ : typeof ssr === 'object'
64
+ ? {
65
+ entry: ssr.entry,
66
+ experimentalPlatform: 'node', // @TODO: Add support for neutral platform
67
+ }
68
+ : ssr;
69
+ validateOptimization(optimization);
70
+ const normalizedOptimization = optimization !== false; // @TODO: Add support for optimization options
71
+ const root = options.root ?? process.cwd();
72
+ const tsConfig = options.tsConfig
73
+ ? (0, node_path_1.resolve)(root, options.tsConfig)
74
+ : (0, node_path_1.join)(root, 'tsconfig.app.json');
75
+ const aot = options.aot ?? true;
76
+ // @TODO: use this once we support granular optimization options
77
+ // const advancedOptimizations = aot && normalizedOptimization.scripts;
78
+ const advancedOptimizations = aot && normalizedOptimization;
79
+ const project = getProject(root);
80
+ const assets = project && options.assets?.length
81
+ ? normalizeAssetPatterns(options.assets, root, project.data.root, project.data.sourceRoot)
82
+ : [];
83
+ const globalStyles = normalizeGlobalEntries(options.styles, 'styles');
84
+ const globalScripts = normalizeGlobalEntries(options.scripts, 'scripts');
85
+ if (options.index === false) {
86
+ console.warn('Disabling the "index" option is not yet supported. Defaulting to "src/index.html".');
87
+ options.index = (0, node_path_1.join)(root, 'src/index.html');
88
+ }
89
+ let index;
90
+ // index can never have a value of `true` but in the schema it's of type `boolean`.
91
+ if (typeof options.index !== 'boolean') {
92
+ let indexOutput;
93
+ // The output file will be created within the configured output path
94
+ if (typeof options.index === 'string') {
95
+ indexOutput = options.index;
96
+ }
97
+ else {
98
+ if (options.index.preloadInitial) {
99
+ console.warn(`The "index.preloadInitial" option is not yet supported.`);
100
+ }
101
+ if (options.index.output) {
102
+ console.warn(`The "index.output" option is not yet supported.`);
103
+ }
104
+ indexOutput = options.index.output || 'index.html';
105
+ }
106
+ /**
107
+ * If SSR is activated, create a distinct entry file for the `index.html`.
108
+ * This is necessary because numerous server/cloud providers automatically serve the `index.html` as a static file
109
+ * if it exists (handling SSG).
110
+ *
111
+ * For instance, accessing `foo.com/` would lead to `foo.com/index.html` being served instead of hitting the server.
112
+ *
113
+ * This approach can also be applied to service workers, where the `index.csr.html` is served instead of the prerendered `index.html`.
114
+ */
115
+ const indexBaseName = (0, node_path_1.basename)(indexOutput);
116
+ indexOutput =
117
+ // @TODO: use this once we support prerenderOptions
118
+ // (normalizedSsr || prerenderOptions) && indexBaseName === 'index.html'
119
+ normalizedSsr && indexBaseName === 'index.html'
120
+ ? exports.INDEX_HTML_CSR
121
+ : indexBaseName;
122
+ index = {
123
+ input: (0, node_path_1.resolve)(root, typeof options.index === 'string' ? options.index : options.index.input),
124
+ output: indexOutput,
125
+ insertionOrder: [
126
+ ['polyfills', true],
127
+ ...globalStyles.filter((s) => s.initial).map((s) => [s.name, false]),
128
+ ...globalScripts.filter((s) => s.initial).map((s) => [s.name, false]),
129
+ ['main', true],
130
+ // [name, esm]
131
+ ],
132
+ // @TODO: Add support for transformer
133
+ transformer: undefined,
134
+ // Preload initial defaults to true
135
+ preloadInitial: typeof options.index !== 'object' ||
136
+ (options.index.preloadInitial ?? true),
137
+ };
138
+ }
139
+ return {
140
+ index,
141
+ browser: options.browser ?? './src/main.ts',
142
+ ...(server ? { server } : {}),
143
+ ...(ssr ? { ssr: normalizedSsr } : {}),
144
+ optimization: normalizedOptimization,
145
+ advancedOptimizations,
146
+ polyfills: options.polyfills ?? [],
147
+ assets,
148
+ globalStyles,
149
+ globalScripts,
150
+ outputPath: normalizeOutputPath(root, options.outputPath),
151
+ fileReplacements: resolveFileReplacements(fileReplacements, root),
152
+ aot,
153
+ outputHashing: options.outputHashing ?? 'all',
154
+ inlineStyleLanguage: options.inlineStyleLanguage ?? 'css',
155
+ tsConfig,
156
+ sourceMap: normalizeSourceMap(options.sourceMap),
157
+ hasServer: getHasServer(root, server, normalizedSsr),
158
+ skipTypeChecking: options.skipTypeChecking ?? false,
159
+ useTsProjectReferences: options.useTsProjectReferences ?? false,
160
+ namedChunks: options.namedChunks ?? false,
161
+ vendorChunk: options.vendorChunk ?? false,
162
+ commonChunk: options.commonChunk ?? true,
163
+ devServer: normalizeDevServer(options.devServer),
164
+ extractLicenses: options.extractLicenses ?? true,
165
+ root,
166
+ };
167
+ }
168
+ function normalizeSourceMap(sourceMap) {
169
+ if (sourceMap === undefined || sourceMap === true) {
170
+ return {
171
+ scripts: true,
172
+ styles: true,
173
+ hidden: false,
174
+ vendor: false,
175
+ };
176
+ }
177
+ if (sourceMap === false) {
178
+ return {
179
+ scripts: false,
180
+ styles: false,
181
+ hidden: false,
182
+ vendor: false,
183
+ };
184
+ }
185
+ return {
186
+ scripts: sourceMap.scripts ?? true,
187
+ styles: sourceMap.styles ?? true,
188
+ hidden: sourceMap.hidden ?? false,
189
+ vendor: sourceMap.vendor ?? false,
190
+ };
191
+ }
192
+ function normalizeDevServer(devServer) {
193
+ const defaultPort = 4200;
194
+ if (!devServer) {
195
+ return { port: defaultPort };
196
+ }
197
+ return {
198
+ ...devServer,
199
+ port: devServer.port ?? defaultPort,
200
+ };
201
+ }
202
+ function normalizeOutputPath(root, outputPath) {
203
+ const defaultBase = (0, node_path_1.join)(root, 'dist');
204
+ const defaultBrowser = (0, node_path_1.join)(defaultBase, 'browser');
205
+ if (!outputPath) {
206
+ return {
207
+ base: defaultBase,
208
+ browser: defaultBrowser,
209
+ server: (0, node_path_1.join)(defaultBase, 'server'),
210
+ media: (0, node_path_1.join)(defaultBrowser, 'media'),
211
+ };
212
+ }
213
+ if (typeof outputPath === 'string') {
214
+ if (!outputPath.startsWith(root)) {
215
+ outputPath = (0, node_path_1.join)(root, outputPath);
216
+ }
217
+ return {
218
+ base: outputPath,
219
+ browser: (0, node_path_1.join)(outputPath, 'browser'),
220
+ server: (0, node_path_1.join)(outputPath, 'server'),
221
+ media: (0, node_path_1.join)(outputPath, 'browser', 'media'),
222
+ };
223
+ }
224
+ if (outputPath.base && !outputPath.base.startsWith(root)) {
225
+ outputPath.base = (0, node_path_1.join)(root, outputPath.base);
226
+ }
227
+ if (outputPath.browser && !outputPath.browser.startsWith(root)) {
228
+ outputPath.browser = (0, node_path_1.join)(root, outputPath.browser);
229
+ }
230
+ if (outputPath.server && !outputPath.server.startsWith(root)) {
231
+ outputPath.server = (0, node_path_1.join)(root, outputPath.server);
232
+ }
233
+ if (outputPath.browser &&
234
+ !outputPath.browser.startsWith(outputPath.browser)) {
235
+ outputPath.browser = (0, node_path_1.join)(outputPath.browser, outputPath.browser);
236
+ }
237
+ const providedBase = outputPath.base ?? defaultBase;
238
+ const providedBrowser = outputPath.browser ?? (0, node_path_1.join)(providedBase, 'browser');
239
+ return {
240
+ base: providedBase,
241
+ browser: providedBrowser,
242
+ server: outputPath.server ?? (0, node_path_1.join)(outputPath.base ?? defaultBase, 'server'),
243
+ media: outputPath.media ?? (0, node_path_1.join)(providedBrowser, 'media'),
244
+ };
245
+ }
246
+ function normalizeAssetPatterns(assets, root, projectRoot, projectSourceRoot) {
247
+ if (assets.length === 0) {
248
+ return [];
249
+ }
250
+ // When sourceRoot is not available, we default to ${projectRoot}/src.
251
+ const sourceRoot = projectSourceRoot || (0, node_path_1.join)(projectRoot, 'src');
252
+ const resolvedSourceRoot = (0, node_path_1.resolve)(root, sourceRoot);
253
+ return assets.map((assetPattern) => {
254
+ // Normalize string asset patterns to objects.
255
+ if (typeof assetPattern === 'string') {
256
+ const assetPath = (0, node_path_1.normalize)(assetPattern);
257
+ const resolvedAssetPath = (0, node_path_1.resolve)(root, assetPath);
258
+ // Check if the string asset is within sourceRoot.
259
+ if (!resolvedAssetPath.startsWith(resolvedSourceRoot)) {
260
+ throw new Error(`The ${assetPattern} asset path must start with the project source root.`);
261
+ }
262
+ let glob, input;
263
+ let isDirectory = false;
264
+ try {
265
+ isDirectory = (0, node_fs_1.statSync)(resolvedAssetPath).isDirectory();
266
+ }
267
+ catch {
268
+ isDirectory = true;
269
+ }
270
+ if (isDirectory) {
271
+ // Folders get a recursive star glob.
272
+ glob = '**/*';
273
+ // Input directory is their original path.
274
+ input = assetPath;
275
+ }
276
+ else {
277
+ // Files are their own glob.
278
+ glob = (0, node_path_1.basename)(assetPath);
279
+ // Input directory is their original dirname.
280
+ input = (0, node_path_1.dirname)(assetPath);
281
+ }
282
+ // Output directory for both is the relative path from source root to input.
283
+ const output = (0, node_path_1.relative)(resolvedSourceRoot, (0, node_path_1.resolve)(root, input));
284
+ assetPattern = { glob, input, output };
285
+ }
286
+ else {
287
+ assetPattern.output = (0, node_path_1.join)('.', assetPattern.output ?? '');
288
+ }
289
+ (0, node_assert_1.default)(assetPattern.output !== undefined);
290
+ if (assetPattern.output.startsWith('..')) {
291
+ throw new Error('An asset cannot be written to a location outside of the output path.');
292
+ }
293
+ return assetPattern;
294
+ });
295
+ }
296
+ function normalizeGlobalEntries(rawEntries, _defaultName) {
297
+ if (!rawEntries?.length) {
298
+ return [];
299
+ }
300
+ const bundles = new Map();
301
+ let warnForInject = false;
302
+ let warnForBundleName = false;
303
+ for (const rawEntry of rawEntries) {
304
+ let entry;
305
+ if (typeof rawEntry === 'string') {
306
+ // string entries use default bundle name and inject values
307
+ entry = { input: rawEntry };
308
+ }
309
+ else {
310
+ entry = rawEntry;
311
+ }
312
+ const { bundleName, input, inject = true } = entry;
313
+ // @TODO: remove this once we support inject
314
+ if (inject === false) {
315
+ warnForInject = true;
316
+ }
317
+ // @TODO: remove this once we support bundleName
318
+ if (bundleName) {
319
+ warnForBundleName = true;
320
+ }
321
+ // @TODO: use this once we support inject and bundleName
322
+ // Non-injected entries default to the file name
323
+ // const name =
324
+ // bundleName || (inject ? defaultName : basename(input, extname(input)));
325
+ const name = (0, node_path_1.basename)(input, (0, node_path_1.extname)(input));
326
+ const existing = bundles.get(name);
327
+ if (!existing) {
328
+ // @TODO: use this once we support inject
329
+ // bundles.set(name, { name, files: [input], initial: inject });
330
+ bundles.set(name, { name, files: [input], initial: true });
331
+ continue;
332
+ }
333
+ // @TODO: uncomment this once we support inject
334
+ // if (existing.initial !== inject) {
335
+ // throw new Error(
336
+ // `The "${name}" bundle is mixing injected and non-injected entries. ` +
337
+ // 'Verify that the project options are correct.'
338
+ // );
339
+ // }
340
+ existing.files.push(input);
341
+ }
342
+ if (warnForInject) {
343
+ console.warn(`The "inject" option for scripts/styles is not yet supported.`);
344
+ }
345
+ if (warnForBundleName) {
346
+ console.warn(`The "bundleName" option for scripts/styles is not yet supported.`);
347
+ }
348
+ return [...bundles.values()];
349
+ }
350
+ function getProject(root) {
351
+ if (global.NX_GRAPH_CREATION) {
352
+ return undefined;
353
+ }
354
+ const projectGraph = (0, devkit_1.readCachedProjectGraph)();
355
+ let projectName = process.env.NX_TASK_TARGET_PROJECT;
356
+ if (!projectName) {
357
+ const projectRootMappings = (0, find_project_for_path_1.createProjectRootMappings)(projectGraph.nodes);
358
+ projectName = (0, find_project_for_path_1.findProjectForPath)(root, projectRootMappings) ?? undefined;
359
+ }
360
+ (0, node_assert_1.default)(projectName, 'Cannot find the project. Please make sure to run this task with the Nx CLI and set "root" to a directory contained in a project.');
361
+ return projectGraph.nodes[projectName];
362
+ }
@@ -0,0 +1,9 @@
1
+ import { Compiler, RspackPluginInstance } from '@rspack/core';
2
+ import { type NormalizedAngularRspackPluginOptions } from '../models';
3
+ export declare class AngularRspackPlugin implements RspackPluginInstance {
4
+ #private;
5
+ constructor(options: NormalizedAngularRspackPluginOptions);
6
+ apply(compiler: Compiler): void;
7
+ private setupCompilation;
8
+ }
9
+ //# sourceMappingURL=angular-rspack-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angular-rspack-plugin.d.ts","sourceRoot":"","sources":["../../../src/lib/plugins/angular-rspack-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EAGR,oBAAoB,EACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAGL,KAAK,oCAAoC,EAC1C,MAAM,WAAW,CAAC;AAiBnB,qBAAa,mBAAoB,YAAW,oBAAoB;;gBAWlD,OAAO,EAAE,oCAAoC;IAqBzD,KAAK,CAAC,QAAQ,EAAE,QAAQ;YAgJV,gBAAgB;CA0B/B"}
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AngularRspackPlugin = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const core_1 = require("@rspack/core");
6
+ const models_1 = require("../models");
7
+ const angular_rspack_compiler_1 = require("@nx/angular-rspack-compiler");
8
+ const path_1 = require("path");
9
+ const fs_2 = tslib_1.__importDefault(require("fs"));
10
+ const PLUGIN_NAME = 'AngularRspackPlugin';
11
+ class AngularRspackPlugin {
12
+ #_options;
13
+ #typescriptFileCache;
14
+ #javascriptTransformer;
15
+ // This will be defined in the apply method correctly
16
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
17
+ // @ts-expect-error
18
+ #angularCompilation;
19
+ constructor(options) {
20
+ this.#_options = options;
21
+ this.#typescriptFileCache = new Map();
22
+ this.#javascriptTransformer = new angular_rspack_compiler_1.JavaScriptTransformer({
23
+ /**
24
+ * Matches https://github.com/angular/angular-cli/blob/33ed6e875e509ebbaa0cbdb57be9e932f9915dff/packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts#L89
25
+ * where pluginOptions.sourcemap is set https://github.com/angular/angular-cli/blob/61d98fde122468978de9b17bd79761befdbf2fac/packages/angular/build/src/tools/esbuild/compiler-plugin-options.ts#L34
26
+ */
27
+ sourcemap: !!(this.#_options.sourceMap.scripts &&
28
+ (this.#_options.sourceMap.hidden ? 'external' : true)),
29
+ thirdPartySourcemaps: this.#_options.sourceMap.vendor,
30
+ advancedOptimizations: this.#_options.advancedOptimizations,
31
+ jit: !this.#_options.aot,
32
+ }, (0, angular_rspack_compiler_1.maxWorkers)());
33
+ }
34
+ apply(compiler) {
35
+ const root = this.#_options.root;
36
+ // Both of these are exclusive to each other - only one of them can be used at a time
37
+ // But they will happen before the compiler is created - so we can use them to set up the parallel compilation once
38
+ compiler.hooks.beforeRun.tapAsync(PLUGIN_NAME, async (compiler, callback) => {
39
+ await this.setupCompilation(root, compiler.options.resolve.tsConfig);
40
+ compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
41
+ await (0, angular_rspack_compiler_1.buildAndAnalyzeWithParallelCompilation)(this.#angularCompilation, this.#typescriptFileCache, this.#javascriptTransformer);
42
+ callback();
43
+ });
44
+ compiler.hooks.done.tap(PLUGIN_NAME, (stats) => {
45
+ if (stats.hasErrors() || stats.hasWarnings()) {
46
+ setTimeout(() => {
47
+ process.exit(stats.hasErrors() ? 1 : 0);
48
+ }, 1000);
49
+ }
50
+ });
51
+ callback();
52
+ });
53
+ compiler.hooks.watchRun.tapAsync(PLUGIN_NAME, async (compiler, callback) => {
54
+ if (!compiler.hooks.beforeCompile.taps.some((tap) => tap.name === PLUGIN_NAME)) {
55
+ compiler.hooks.beforeCompile.tapAsync(PLUGIN_NAME, async (params, callback) => {
56
+ const watchingModifiedFiles = compiler.watching?.compiler
57
+ ?.modifiedFiles
58
+ ? new Set(compiler.watching.compiler.modifiedFiles)
59
+ : new Set();
60
+ await this.setupCompilation(root, compiler.options.resolve.tsConfig);
61
+ await this.#angularCompilation.update(watchingModifiedFiles);
62
+ await (0, angular_rspack_compiler_1.buildAndAnalyzeWithParallelCompilation)(this.#angularCompilation, this.#typescriptFileCache, this.#javascriptTransformer);
63
+ compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
64
+ watchingModifiedFiles.forEach((file) => {
65
+ compilation.fileDependencies.add(file);
66
+ });
67
+ });
68
+ callback();
69
+ });
70
+ }
71
+ callback();
72
+ });
73
+ compiler.hooks.emit.tapAsync(PLUGIN_NAME, async (compilation, callback) => {
74
+ if (!this.#_options.skipTypeChecking) {
75
+ const { errors, warnings } = await this.#angularCompilation.diagnoseFiles(angular_rspack_compiler_1.DiagnosticModes.All);
76
+ for (const error of errors ?? []) {
77
+ compilation.errors.push({
78
+ name: PLUGIN_NAME,
79
+ message: error.text || '',
80
+ file: error.location?.file,
81
+ loc: `${error.location?.line}:${error.location?.column}`,
82
+ moduleIdentifier: error.location?.file,
83
+ stack: error.text,
84
+ });
85
+ }
86
+ for (const warning of warnings ?? []) {
87
+ compilation.warnings.push({
88
+ name: PLUGIN_NAME,
89
+ message: warning.text || '',
90
+ file: warning.location?.file,
91
+ loc: `${warning.location?.line}:${warning.location?.column}`,
92
+ stack: warning.text,
93
+ moduleIdentifier: warning.location?.file,
94
+ });
95
+ }
96
+ }
97
+ await this.#angularCompilation.close();
98
+ await this.#javascriptTransformer.close();
99
+ callback();
100
+ });
101
+ compiler.hooks.normalModuleFactory.tap(PLUGIN_NAME, (normalModuleFactory) => {
102
+ normalModuleFactory.hooks.beforeResolve.tap(PLUGIN_NAME, (data) => {
103
+ if (data.request.startsWith('angular:jit:')) {
104
+ const path = data.request.split(';')[1];
105
+ data.request = `${(0, path_1.normalize)((0, path_1.resolve)((0, path_1.dirname)(data.contextInfo.issuer), path))}?raw`;
106
+ }
107
+ });
108
+ });
109
+ compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
110
+ compilation[models_1.NG_RSPACK_SYMBOL_NAME] = () => ({
111
+ javascriptTransformer: this
112
+ .#javascriptTransformer,
113
+ typescriptFileCache: this.#typescriptFileCache,
114
+ });
115
+ });
116
+ compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
117
+ const htmlRspackPluginHooks = core_1.HtmlRspackPlugin.getCompilationHooks(compilation);
118
+ htmlRspackPluginHooks.beforeEmit.tap(PLUGIN_NAME, (data) => {
119
+ const ngJsDispatchEvent = `<script type="text/javascript" id="ng-event-dispatch-contract">
120
+ ${fs_2.default.readFileSync(require.resolve('@angular/core/event-dispatch-contract.min.js'), 'utf-8')}
121
+ </script>`;
122
+ data.html = data.html.replace('</body>', `${ngJsDispatchEvent}</body>`);
123
+ return data;
124
+ });
125
+ });
126
+ }
127
+ async setupCompilation(root, tsConfig) {
128
+ const tsconfigPath = tsConfig
129
+ ? typeof tsConfig === 'string'
130
+ ? tsConfig
131
+ : tsConfig.configFile
132
+ : this.#_options.tsConfig;
133
+ this.#angularCompilation = await (0, angular_rspack_compiler_1.setupCompilationWithParallelCompilation)({
134
+ source: {
135
+ tsconfigPath: tsconfigPath,
136
+ },
137
+ }, {
138
+ root,
139
+ aot: this.#_options.aot,
140
+ tsConfig: tsconfigPath,
141
+ inlineStyleLanguage: this.#_options.inlineStyleLanguage,
142
+ fileReplacements: this.#_options.fileReplacements,
143
+ useTsProjectReferences: this.#_options.useTsProjectReferences,
144
+ hasServer: this.#_options.hasServer,
145
+ });
146
+ }
147
+ }
148
+ exports.AngularRspackPlugin = AngularRspackPlugin;
@@ -0,0 +1,8 @@
1
+ import { Compiler, RspackPluginInstance } from '@rspack/core';
2
+ import { OutputPath } from '../models';
3
+ export declare class AngularSsrDevServer implements RspackPluginInstance {
4
+ #private;
5
+ constructor(outputPath: OutputPath);
6
+ apply(compiler: Compiler): void;
7
+ }
8
+ //# sourceMappingURL=angular-ssr-dev-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angular-ssr-dev-server.d.ts","sourceRoot":"","sources":["../../../src/lib/plugins/angular-ssr-dev-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAG9D,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAKvC,qBAAa,mBAAoB,YAAW,oBAAoB;;gBAKlD,UAAU,EAAE,UAAU;IAKlC,KAAK,CAAC,QAAQ,EAAE,QAAQ;CAkCzB"}
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AngularSsrDevServer = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const ssr_reload_server_1 = require("./server/ssr-reload-server");
6
+ const node_path_1 = require("node:path");
7
+ const node_fs_1 = require("node:fs");
8
+ const PLUGIN_NAME = 'AngularSsrDevServer';
9
+ class AngularSsrDevServer {
10
+ #devServerProcess;
11
+ #wsServer;
12
+ #outputPath;
13
+ constructor(outputPath) {
14
+ this.#outputPath = outputPath;
15
+ this.#wsServer = new ssr_reload_server_1.SsrReloadServer();
16
+ }
17
+ apply(compiler) {
18
+ compiler.hooks.entryOption.tap(PLUGIN_NAME, (context, entry) => {
19
+ const keys = Object.keys(entry);
20
+ for (const key of keys) {
21
+ const entryValue = entry[key];
22
+ entryValue.import = [
23
+ ...entryValue.import,
24
+ require.resolve(`${__dirname}/client/ssr-reload-client.js`),
25
+ ];
26
+ }
27
+ });
28
+ compiler.hooks.watchRun.tapAsync(PLUGIN_NAME, async (compiler, callback) => {
29
+ compiler.hooks.afterEmit.tapAsync(PLUGIN_NAME, async (_, callback) => {
30
+ const serverPath = (0, node_path_1.join)(this.#outputPath.server, 'server.js');
31
+ if (this.#devServerProcess) {
32
+ this.#devServerProcess.kill();
33
+ this.#devServerProcess = undefined;
34
+ await new Promise((res) => setTimeout(res, 50));
35
+ }
36
+ if (!(0, node_fs_1.existsSync)(serverPath)) {
37
+ await new Promise((res) => setTimeout(res, 50));
38
+ }
39
+ this.#devServerProcess = (0, child_process_1.fork)(serverPath);
40
+ this.#devServerProcess.on('spawn', () => {
41
+ this.#wsServer.sendReload();
42
+ });
43
+ callback();
44
+ });
45
+ callback();
46
+ });
47
+ }
48
+ }
49
+ exports.AngularSsrDevServer = AngularSsrDevServer;
@@ -0,0 +1,2 @@
1
+ declare const socket: any;
2
+ //# sourceMappingURL=ssr-reload-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssr-reload-client.d.ts","sourceRoot":"","sources":["../../../../src/lib/plugins/client/ssr-reload-client.ts"],"names":[],"mappings":"AACA,QAAA,MAAM,MAAM,KAAwC,CAAC"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ // @ts-expect-error: This is a client-side file
3
+ const socket = new WebSocket(`ws://localhost:60000`);
4
+ socket.addEventListener('message', (event) => {
5
+ if (event.data === 'ssr-reload') {
6
+ console.log('[AngularSSRDevServer] Reloading the page...');
7
+ // @ts-expect-error: This is a client-side file
8
+ window.location.reload();
9
+ }
10
+ });
11
+ socket.addEventListener('open', () => {
12
+ console.log('[AngularSSRDevServer] WebSocket connection established.');
13
+ });
14
+ socket.addEventListener('close', () => {
15
+ console.warn('[AngularSSRDevServer] WebSocket connection closed.');
16
+ });
@@ -0,0 +1,3 @@
1
+ import { LoaderContext } from '@rspack/core';
2
+ export default function loader(this: LoaderContext<unknown>, content: string): void;
3
+ //# sourceMappingURL=angular-partial-transform.loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angular-partial-transform.loader.d.ts","sourceRoot":"","sources":["../../../../src/lib/plugins/loaders/angular-partial-transform.loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,QAuC3E"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = loader;
4
+ const models_1 = require("../../models");
5
+ function loader(content) {
6
+ const callback = this.async();
7
+ if (this._compilation[models_1.NG_RSPACK_SYMBOL_NAME] ===
8
+ undefined) {
9
+ callback(null, content);
10
+ }
11
+ else {
12
+ const { javascriptTransformer, typescriptFileCache } = this._compilation[models_1.NG_RSPACK_SYMBOL_NAME]();
13
+ const request = this.resourcePath;
14
+ if (request.startsWith('data:text/javascript') &&
15
+ request.includes('__module_federation_bundler_runtime__')) {
16
+ callback(null, content);
17
+ return;
18
+ }
19
+ if (!content.includes('@angular')) {
20
+ callback(null, content);
21
+ return;
22
+ }
23
+ const existingTransform = typescriptFileCache.get(request);
24
+ if (existingTransform) {
25
+ callback(null, existingTransform);
26
+ return;
27
+ }
28
+ javascriptTransformer
29
+ .transformFile(request, false, false)
30
+ .then((contents) => {
31
+ const transformedCode = Buffer.from(contents).toString('utf8');
32
+ typescriptFileCache.set(request, transformedCode);
33
+ callback(null, transformedCode);
34
+ });
35
+ }
36
+ }
@@ -0,0 +1,3 @@
1
+ import type { LoaderContext } from '@rspack/core';
2
+ export default function loader(this: LoaderContext<unknown>, content: string): void;
3
+ //# sourceMappingURL=angular-transform.loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angular-transform.loader.d.ts","sourceRoot":"","sources":["../../../../src/lib/plugins/loaders/angular-transform.loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAWlD,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,QAqC3E"}