ng-packagr 22.2.0-next.3 → 22.2.0-next.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ng-packagr",
3
- "version": "22.2.0-next.3",
3
+ "version": "22.2.0-next.4",
4
4
  "description": "Compile and package Angular libraries in Angular Package Format (APF)",
5
5
  "keywords": [
6
6
  "apf",
@@ -34,8 +34,9 @@ export declare class BundlerContext {
34
34
  #private;
35
35
  private workspaceRoot;
36
36
  private incremental;
37
+ private useContext;
37
38
  readonly watchFiles: Set<string>;
38
- constructor(workspaceRoot: string, incremental: boolean, options: BuildOptions | BundlerOptionsFactory);
39
+ constructor(workspaceRoot: string, incremental: boolean, options: BuildOptions | BundlerOptionsFactory, useContext?: boolean, initialFilter?: ((initial: Readonly<InitialFileRecord>) => boolean) | LoadResultCache, sharedLoadCache?: LoadResultCache);
39
40
  /**
40
41
  * Executes the esbuild build function and normalizes the build result in the event of a
41
42
  * build failure that results in no output being generated.
@@ -53,7 +54,7 @@ export declare class BundlerContext {
53
54
  * to be stored.
54
55
  * @returns True, if the result was invalidated; False, otherwise.
55
56
  */
56
- invalidate(files: Iterable<string>): boolean;
57
+ invalidate(files: Iterable<string> | ReadonlySet<string>): boolean;
57
58
  /**
58
59
  * Disposes incremental build resources present in the context.
59
60
  *
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BundlerContext = exports.BuildOutputFileType = void 0;
4
4
  const esbuild_1 = require("esbuild");
5
5
  const node_path_1 = require("node:path");
6
+ const path_1 = require("../utils/path");
6
7
  const load_result_cache_1 = require("./load-result-cache");
7
8
  var BuildOutputFileType;
8
9
  (function (BuildOutputFileType) {
@@ -23,6 +24,7 @@ function isEsBuildFailure(value) {
23
24
  class BundlerContext {
24
25
  workspaceRoot;
25
26
  incremental;
27
+ useContext;
26
28
  #esbuildContext;
27
29
  #esbuildOptions;
28
30
  #esbuildResult;
@@ -32,9 +34,16 @@ class BundlerContext {
32
34
  #shouldCacheResult;
33
35
  #loadCache;
34
36
  watchFiles = new Set();
35
- constructor(workspaceRoot, incremental, options) {
37
+ constructor(workspaceRoot, incremental, options, useContext = incremental, initialFilter, sharedLoadCache) {
36
38
  this.workspaceRoot = workspaceRoot;
37
39
  this.incremental = incremental;
40
+ this.useContext = useContext;
41
+ if (initialFilter && typeof initialFilter !== 'function') {
42
+ this.#loadCache = initialFilter;
43
+ }
44
+ else {
45
+ this.#loadCache = sharedLoadCache;
46
+ }
38
47
  // To cache the results an option factory is needed to capture the full set of dependencies
39
48
  this.#shouldCacheResult = incremental && typeof options === 'function';
40
49
  this.#optionsFactory = (...args) => {
@@ -78,7 +87,7 @@ class BundlerContext {
78
87
  async #performBundle() {
79
88
  // Create esbuild options if not present
80
89
  if (this.#esbuildOptions === undefined) {
81
- if (this.incremental) {
90
+ if (this.incremental && !this.#loadCache) {
82
91
  this.#loadCache = new load_result_cache_1.MemoryLoadResultCache();
83
92
  }
84
93
  this.#esbuildOptions = this.#optionsFactory(this.#loadCache);
@@ -92,7 +101,7 @@ class BundlerContext {
92
101
  // Rebuild using the existing incremental build context
93
102
  result = await this.#esbuildContext.rebuild();
94
103
  }
95
- else if (this.incremental) {
104
+ else if (this.useContext) {
96
105
  // Create an incremental build context and perform the first build.
97
106
  // Context creation does not perform a build.
98
107
  const esbuildContext = await (0, esbuild_1.context)(this.#esbuildOptions);
@@ -105,47 +114,58 @@ class BundlerContext {
105
114
  }
106
115
  else {
107
116
  // For non-incremental builds, perform a single build
117
+ if (this.#disposed) {
118
+ throw new Error('BundlerContext was disposed during build.');
119
+ }
108
120
  result = await (0, esbuild_1.build)(this.#esbuildOptions);
121
+ if (this.#disposed) {
122
+ throw new Error('BundlerContext was disposed during build.');
123
+ }
109
124
  }
110
125
  }
111
126
  catch (failure) {
112
127
  // Build failures will throw an exception which contains errors/warnings
113
128
  if (isEsBuildFailure(failure)) {
114
129
  this.#addErrorsToWatch(failure);
130
+ this.#addLoadCacheFilesToWatch();
115
131
  return failure;
116
132
  }
117
133
  else {
118
134
  throw failure;
119
135
  }
120
136
  }
121
- finally {
122
- if (this.incremental) {
123
- // When incremental always add any files from the load result cache
124
- if (this.#loadCache) {
125
- for (const file of this.#loadCache.watchFiles) {
126
- if (!isInternalAngularFile(file)) {
127
- // watch files are fully resolved paths
128
- this.watchFiles.add(file);
129
- }
130
- }
131
- }
132
- }
133
- }
134
137
  // Update files that should be watched.
135
138
  // While this should technically not be linked to incremental mode, incremental is only
136
139
  // currently enabled with watch mode where watch files are needed.
137
140
  if (this.incremental) {
138
141
  // Add input files except virtual angular files which do not exist on disk
139
142
  for (const input of Object.keys(result.metafile.inputs)) {
140
- if (!isInternalAngularFile(input)) {
141
- // input file paths are always relative to the workspace root
142
- this.watchFiles.add((0, node_path_1.join)(this.workspaceRoot, input));
143
+ const isInternal = isInternalAngularFile(input) || isInternalBundlerFile(input);
144
+ // Input file paths are always relative to the workspace root unless already absolute
145
+ const normalizedAbsoluteInput = (0, node_path_1.isAbsolute)(input)
146
+ ? (0, path_1.ensureUnixPath)(input)
147
+ : (0, path_1.ensureUnixPath)((0, node_path_1.join)(this.workspaceRoot, input));
148
+ if (!isInternal) {
149
+ this.watchFiles.add(normalizedAbsoluteInput);
150
+ }
151
+ if (this.#loadCache) {
152
+ const cachedLoad = await (this.#loadCache.get(input) ??
153
+ this.#loadCache.get(input.replace(';', ':')) ??
154
+ this.#loadCache.get('file:' + normalizedAbsoluteInput));
155
+ if (cachedLoad?.watchFiles) {
156
+ for (const file of cachedLoad.watchFiles) {
157
+ if (!isInternalAngularFile(file)) {
158
+ this.watchFiles.add((0, node_path_1.isAbsolute)(file) ? (0, path_1.ensureUnixPath)(file) : (0, path_1.ensureUnixPath)((0, node_path_1.join)(this.workspaceRoot, file)));
159
+ }
160
+ }
161
+ }
143
162
  }
144
163
  }
145
164
  }
146
165
  // Return if the build encountered any errors
147
166
  if (result.errors.length) {
148
167
  this.#addErrorsToWatch(result);
168
+ this.#addLoadCacheFilesToWatch();
149
169
  return {
150
170
  errors: result.errors,
151
171
  warnings: result.warnings,
@@ -161,14 +181,23 @@ class BundlerContext {
161
181
  }
162
182
  #addErrorsToWatch(result) {
163
183
  for (const error of result.errors) {
164
- let file = error.location?.file;
184
+ const file = error.location?.file;
165
185
  if (file && !isInternalAngularFile(file)) {
166
- this.watchFiles.add((0, node_path_1.join)(this.workspaceRoot, file));
186
+ this.watchFiles.add((0, node_path_1.isAbsolute)(file) ? (0, path_1.ensureUnixPath)(file) : (0, path_1.ensureUnixPath)((0, node_path_1.join)(this.workspaceRoot, file)));
187
+ }
188
+ for (const note of error.notes ?? []) {
189
+ const noteFile = note.location?.file;
190
+ if (noteFile && !isInternalAngularFile(noteFile)) {
191
+ this.watchFiles.add((0, node_path_1.isAbsolute)(noteFile) ? (0, path_1.ensureUnixPath)(noteFile) : (0, path_1.ensureUnixPath)((0, node_path_1.join)(this.workspaceRoot, noteFile)));
192
+ }
167
193
  }
168
- for (const note of error.notes) {
169
- file = note.location?.file;
170
- if (file && !isInternalAngularFile(file)) {
171
- this.watchFiles.add((0, node_path_1.join)(this.workspaceRoot, file));
194
+ }
195
+ }
196
+ #addLoadCacheFilesToWatch() {
197
+ if (this.incremental && this.#loadCache) {
198
+ for (const file of this.#loadCache.watchFiles) {
199
+ if (!isInternalAngularFile(file)) {
200
+ this.watchFiles.add((0, node_path_1.isAbsolute)(file) ? (0, path_1.ensureUnixPath)(file) : (0, path_1.ensureUnixPath)((0, node_path_1.join)(this.workspaceRoot, file)));
172
201
  }
173
202
  }
174
203
  }
@@ -184,13 +213,65 @@ class BundlerContext {
184
213
  if (!this.incremental) {
185
214
  return false;
186
215
  }
216
+ let candidateFiles;
217
+ if (files instanceof Set) {
218
+ let isCandidateReady = true;
219
+ for (const file of files) {
220
+ if (file !== (0, path_1.ensureUnixPath)(file) ||
221
+ (!(0, node_path_1.isAbsolute)(file) && !files.has((0, path_1.ensureUnixPath)((0, node_path_1.join)(this.workspaceRoot, file))))) {
222
+ isCandidateReady = false;
223
+ break;
224
+ }
225
+ }
226
+ if (isCandidateReady) {
227
+ candidateFiles = files;
228
+ }
229
+ else {
230
+ const normalizedFiles = new Set();
231
+ for (const file of files) {
232
+ const normalized = (0, path_1.ensureUnixPath)(file);
233
+ normalizedFiles.add(normalized);
234
+ if (!(0, node_path_1.isAbsolute)(normalized)) {
235
+ normalizedFiles.add((0, path_1.ensureUnixPath)((0, node_path_1.join)(this.workspaceRoot, normalized)));
236
+ }
237
+ }
238
+ candidateFiles = normalizedFiles;
239
+ }
240
+ }
241
+ else {
242
+ const normalizedFiles = new Set();
243
+ for (const file of files) {
244
+ const normalized = (0, path_1.ensureUnixPath)(file);
245
+ normalizedFiles.add(normalized);
246
+ if (!(0, node_path_1.isAbsolute)(normalized)) {
247
+ normalizedFiles.add((0, path_1.ensureUnixPath)((0, node_path_1.join)(this.workspaceRoot, normalized)));
248
+ }
249
+ }
250
+ candidateFiles = normalizedFiles;
251
+ }
187
252
  let invalid = false;
188
- for (const file of files) {
253
+ for (const file of candidateFiles) {
189
254
  if (this.#loadCache?.invalidate(file)) {
190
255
  invalid = true;
191
- continue;
192
256
  }
193
- invalid ||= this.watchFiles.has(file);
257
+ }
258
+ if (!invalid) {
259
+ if (this.watchFiles.size < candidateFiles.size) {
260
+ for (const file of this.watchFiles) {
261
+ if (candidateFiles.has(file)) {
262
+ invalid = true;
263
+ break;
264
+ }
265
+ }
266
+ }
267
+ else {
268
+ for (const file of candidateFiles) {
269
+ if (this.watchFiles.has(file)) {
270
+ invalid = true;
271
+ break;
272
+ }
273
+ }
274
+ }
194
275
  }
195
276
  if (invalid) {
196
277
  this.#esbuildResult = undefined;
@@ -220,4 +301,15 @@ exports.BundlerContext = BundlerContext;
220
301
  function isInternalAngularFile(file) {
221
302
  return file.startsWith('angular:');
222
303
  }
304
+ function isInternalBundlerFile(file) {
305
+ // Bundler virtual files such as "<define:???>" or "<runtime>"
306
+ if (file[0] === '<' && file.at(-1) === '>') {
307
+ return true;
308
+ }
309
+ // Any (disabled): path is a virtual esbuild entry that doesn't exist on disk
310
+ if (file.includes('(disabled):')) {
311
+ return true;
312
+ }
313
+ return false;
314
+ }
223
315
  //# sourceMappingURL=bundler-context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bundler-context.js","sourceRoot":"","sources":["../../../../src/lib/styles/bundler-context.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BuildContext,\n BuildFailure,\n BuildOptions,\n BuildResult,\n Message,\n Metafile,\n OutputFile,\n build,\n context,\n} from 'esbuild';\nimport { join } from 'node:path';\nimport { LoadResultCache, MemoryLoadResultCache } from './load-result-cache';\n\nexport type BundleContextResult =\n | { errors: Message[]; warnings: Message[] }\n | {\n errors: undefined;\n warnings: Message[];\n metafile: Metafile;\n outputFiles: BuildOutputFile[];\n };\n\nexport interface InitialFileRecord {\n entrypoint: boolean;\n name?: string;\n type: 'script' | 'style';\n external?: boolean;\n serverFile: boolean;\n depth: number;\n}\n\nexport enum BuildOutputFileType {\n Browser,\n Media,\n ServerApplication,\n ServerRoot,\n Root,\n}\n\nexport interface BuildOutputFile extends OutputFile {\n type: BuildOutputFileType;\n readonly size: number;\n clone: () => BuildOutputFile;\n}\n\nexport type BundlerOptionsFactory<T extends BuildOptions = BuildOptions> = (\n loadCache: LoadResultCache | undefined,\n) => T;\n\n/**\n * Determines if an unknown value is an esbuild BuildFailure error object thrown by esbuild.\n * @param value A potential esbuild BuildFailure error object.\n * @returns `true` if the object is determined to be a BuildFailure object; otherwise, `false`.\n */\nfunction isEsBuildFailure(value: unknown): value is BuildFailure {\n return !!value && typeof value === 'object' && 'errors' in value && 'warnings' in value;\n}\n\nexport class BundlerContext {\n #esbuildContext?: BuildContext<{ metafile: true; write: false }>;\n #esbuildOptions?: BuildOptions & { metafile: true; write: false };\n #esbuildResult?: BundleContextResult;\n #activeBundlePromise?: Promise<BundleContextResult>;\n #disposed = false;\n #optionsFactory: BundlerOptionsFactory<BuildOptions & { metafile: true; write: false }>;\n #shouldCacheResult: boolean;\n #loadCache?: MemoryLoadResultCache;\n readonly watchFiles: Set<string> = new Set<string>();\n\n constructor(\n private workspaceRoot: string,\n private incremental: boolean,\n options: BuildOptions | BundlerOptionsFactory,\n ) {\n // To cache the results an option factory is needed to capture the full set of dependencies\n this.#shouldCacheResult = incremental && typeof options === 'function';\n this.#optionsFactory = (...args) => {\n const baseOptions = typeof options === 'function' ? options(...args) : options;\n\n return {\n ...baseOptions,\n metafile: true,\n write: false,\n };\n };\n }\n\n /**\n * Executes the esbuild build function and normalizes the build result in the event of a\n * build failure that results in no output being generated.\n * All builds use the `write` option with a value of `false` to allow for the output files\n * build result array to be populated.\n *\n * @returns If output files are generated, the full esbuild BuildResult; if not, the\n * warnings and errors for the attempted build.\n */\n async bundle(force = false): Promise<BundleContextResult> {\n // Return existing result if present\n if (this.#esbuildResult) {\n return this.#esbuildResult;\n }\n\n if (!force && this.#activeBundlePromise !== undefined) {\n return this.#activeBundlePromise;\n }\n\n const bundlePromise = this.#performBundle().finally(() => {\n if (this.#activeBundlePromise === bundlePromise) {\n this.#activeBundlePromise = undefined;\n }\n });\n this.#activeBundlePromise = bundlePromise;\n\n const result = await bundlePromise;\n if (this.#shouldCacheResult) {\n this.#esbuildResult = result;\n }\n\n return result;\n }\n\n async #performBundle(): Promise<BundleContextResult> {\n // Create esbuild options if not present\n if (this.#esbuildOptions === undefined) {\n if (this.incremental) {\n this.#loadCache = new MemoryLoadResultCache();\n }\n this.#esbuildOptions = this.#optionsFactory(this.#loadCache);\n }\n\n if (this.incremental) {\n this.watchFiles.clear();\n }\n\n let result: BuildResult<{ metafile: true; write: false }>;\n try {\n if (this.#esbuildContext) {\n // Rebuild using the existing incremental build context\n result = await this.#esbuildContext.rebuild();\n } else if (this.incremental) {\n // Create an incremental build context and perform the first build.\n // Context creation does not perform a build.\n const esbuildContext = await context(this.#esbuildOptions);\n if (this.#disposed) {\n await esbuildContext.dispose();\n throw new Error('BundlerContext was disposed during build.');\n }\n this.#esbuildContext = esbuildContext;\n result = await this.#esbuildContext.rebuild();\n } else {\n // For non-incremental builds, perform a single build\n result = await build(this.#esbuildOptions);\n }\n } catch (failure) {\n // Build failures will throw an exception which contains errors/warnings\n if (isEsBuildFailure(failure)) {\n this.#addErrorsToWatch(failure);\n\n return failure;\n } else {\n throw failure;\n }\n } finally {\n if (this.incremental) {\n // When incremental always add any files from the load result cache\n if (this.#loadCache) {\n for (const file of this.#loadCache.watchFiles) {\n if (!isInternalAngularFile(file)) {\n // watch files are fully resolved paths\n this.watchFiles.add(file);\n }\n }\n }\n }\n }\n\n // Update files that should be watched.\n // While this should technically not be linked to incremental mode, incremental is only\n // currently enabled with watch mode where watch files are needed.\n if (this.incremental) {\n // Add input files except virtual angular files which do not exist on disk\n for (const input of Object.keys(result.metafile.inputs)) {\n if (!isInternalAngularFile(input)) {\n // input file paths are always relative to the workspace root\n this.watchFiles.add(join(this.workspaceRoot, input));\n }\n }\n }\n\n // Return if the build encountered any errors\n if (result.errors.length) {\n this.#addErrorsToWatch(result);\n\n return {\n errors: result.errors,\n warnings: result.warnings,\n };\n }\n\n // Return the successful build results\n return {\n errors: undefined,\n warnings: result.warnings,\n metafile: result.metafile,\n outputFiles: result.outputFiles as BuildOutputFile[],\n };\n }\n\n #addErrorsToWatch(result: BuildFailure | BuildResult): void {\n for (const error of result.errors) {\n let file = error.location?.file;\n if (file && !isInternalAngularFile(file)) {\n this.watchFiles.add(join(this.workspaceRoot, file));\n }\n for (const note of error.notes) {\n file = note.location?.file;\n if (file && !isInternalAngularFile(file)) {\n this.watchFiles.add(join(this.workspaceRoot, file));\n }\n }\n }\n }\n\n /**\n * Invalidate a stored bundler result based on the previous watch files\n * and a list of changed files.\n * The context must be created with incremental mode enabled for results\n * to be stored.\n * @returns True, if the result was invalidated; False, otherwise.\n */\n invalidate(files: Iterable<string>): boolean {\n if (!this.incremental) {\n return false;\n }\n\n let invalid = false;\n for (const file of files) {\n if (this.#loadCache?.invalidate(file)) {\n invalid = true;\n continue;\n }\n\n invalid ||= this.watchFiles.has(file);\n }\n\n if (invalid) {\n this.#esbuildResult = undefined;\n }\n\n return invalid;\n }\n\n /**\n * Disposes incremental build resources present in the context.\n *\n * @returns A promise that resolves when disposal is complete.\n */\n async dispose(): Promise<void> {\n this.#disposed = true;\n try {\n this.#esbuildOptions = undefined;\n this.#esbuildResult = undefined;\n this.#activeBundlePromise = undefined;\n this.#loadCache = undefined;\n await this.#esbuildContext?.dispose();\n } finally {\n this.#esbuildContext = undefined;\n }\n }\n}\n\nfunction isInternalAngularFile(file: string) {\n return file.startsWith('angular:');\n}\n"]}
1
+ {"version":3,"file":"bundler-context.js","sourceRoot":"","sources":["../../../../src/lib/styles/bundler-context.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BuildContext,\n BuildFailure,\n BuildOptions,\n BuildResult,\n Message,\n Metafile,\n OutputFile,\n build,\n context,\n} from 'esbuild';\nimport { isAbsolute, join } from 'node:path';\nimport { ensureUnixPath } from '../utils/path';\nimport { LoadResultCache, MemoryLoadResultCache } from './load-result-cache';\n\nexport type BundleContextResult =\n | { errors: Message[]; warnings: Message[] }\n | {\n errors: undefined;\n warnings: Message[];\n metafile: Metafile;\n outputFiles: BuildOutputFile[];\n };\n\nexport interface InitialFileRecord {\n entrypoint: boolean;\n name?: string;\n type: 'script' | 'style';\n external?: boolean;\n serverFile: boolean;\n depth: number;\n}\n\nexport enum BuildOutputFileType {\n Browser,\n Media,\n ServerApplication,\n ServerRoot,\n Root,\n}\n\nexport interface BuildOutputFile extends OutputFile {\n type: BuildOutputFileType;\n readonly size: number;\n clone: () => BuildOutputFile;\n}\n\nexport type BundlerOptionsFactory<T extends BuildOptions = BuildOptions> = (\n loadCache: LoadResultCache | undefined,\n) => T;\n\n/**\n * Determines if an unknown value is an esbuild BuildFailure error object thrown by esbuild.\n * @param value A potential esbuild BuildFailure error object.\n * @returns `true` if the object is determined to be a BuildFailure object; otherwise, `false`.\n */\nfunction isEsBuildFailure(value: unknown): value is BuildFailure {\n return !!value && typeof value === 'object' && 'errors' in value && 'warnings' in value;\n}\n\nexport class BundlerContext {\n #esbuildContext?: BuildContext<{ metafile: true; write: false }>;\n #esbuildOptions?: BuildOptions & { metafile: true; write: false };\n #esbuildResult?: BundleContextResult;\n #activeBundlePromise?: Promise<BundleContextResult>;\n #disposed = false;\n #optionsFactory: BundlerOptionsFactory<BuildOptions & { metafile: true; write: false }>;\n #shouldCacheResult: boolean;\n #loadCache?: LoadResultCache;\n readonly watchFiles: Set<string> = new Set<string>();\n\n constructor(\n private workspaceRoot: string,\n private incremental: boolean,\n options: BuildOptions | BundlerOptionsFactory,\n private useContext = incremental,\n initialFilter?: ((initial: Readonly<InitialFileRecord>) => boolean) | LoadResultCache,\n sharedLoadCache?: LoadResultCache,\n ) {\n if (initialFilter && typeof initialFilter !== 'function') {\n this.#loadCache = initialFilter;\n } else {\n this.#loadCache = sharedLoadCache;\n }\n // To cache the results an option factory is needed to capture the full set of dependencies\n this.#shouldCacheResult = incremental && typeof options === 'function';\n this.#optionsFactory = (...args) => {\n const baseOptions = typeof options === 'function' ? options(...args) : options;\n\n return {\n ...baseOptions,\n metafile: true,\n write: false,\n };\n };\n }\n\n /**\n * Executes the esbuild build function and normalizes the build result in the event of a\n * build failure that results in no output being generated.\n * All builds use the `write` option with a value of `false` to allow for the output files\n * build result array to be populated.\n *\n * @returns If output files are generated, the full esbuild BuildResult; if not, the\n * warnings and errors for the attempted build.\n */\n async bundle(force = false): Promise<BundleContextResult> {\n // Return existing result if present\n if (this.#esbuildResult) {\n return this.#esbuildResult;\n }\n\n if (!force && this.#activeBundlePromise !== undefined) {\n return this.#activeBundlePromise;\n }\n\n const bundlePromise = this.#performBundle().finally(() => {\n if (this.#activeBundlePromise === bundlePromise) {\n this.#activeBundlePromise = undefined;\n }\n });\n this.#activeBundlePromise = bundlePromise;\n\n const result = await bundlePromise;\n if (this.#shouldCacheResult) {\n this.#esbuildResult = result;\n }\n\n return result;\n }\n\n async #performBundle(): Promise<BundleContextResult> {\n // Create esbuild options if not present\n if (this.#esbuildOptions === undefined) {\n if (this.incremental && !this.#loadCache) {\n this.#loadCache = new MemoryLoadResultCache();\n }\n this.#esbuildOptions = this.#optionsFactory(this.#loadCache);\n }\n\n if (this.incremental) {\n this.watchFiles.clear();\n }\n\n let result: BuildResult<{ metafile: true; write: false }>;\n try {\n if (this.#esbuildContext) {\n // Rebuild using the existing incremental build context\n result = await this.#esbuildContext.rebuild();\n } else if (this.useContext) {\n // Create an incremental build context and perform the first build.\n // Context creation does not perform a build.\n const esbuildContext = await context(this.#esbuildOptions);\n if (this.#disposed) {\n await esbuildContext.dispose();\n throw new Error('BundlerContext was disposed during build.');\n }\n this.#esbuildContext = esbuildContext;\n result = await this.#esbuildContext.rebuild();\n } else {\n // For non-incremental builds, perform a single build\n if (this.#disposed) {\n throw new Error('BundlerContext was disposed during build.');\n }\n result = await build(this.#esbuildOptions);\n if (this.#disposed) {\n throw new Error('BundlerContext was disposed during build.');\n }\n }\n } catch (failure) {\n // Build failures will throw an exception which contains errors/warnings\n if (isEsBuildFailure(failure)) {\n this.#addErrorsToWatch(failure);\n this.#addLoadCacheFilesToWatch();\n\n return failure;\n } else {\n throw failure;\n }\n }\n\n // Update files that should be watched.\n // While this should technically not be linked to incremental mode, incremental is only\n // currently enabled with watch mode where watch files are needed.\n if (this.incremental) {\n // Add input files except virtual angular files which do not exist on disk\n for (const input of Object.keys(result.metafile.inputs)) {\n const isInternal = isInternalAngularFile(input) || isInternalBundlerFile(input);\n\n // Input file paths are always relative to the workspace root unless already absolute\n const normalizedAbsoluteInput = isAbsolute(input)\n ? ensureUnixPath(input)\n : ensureUnixPath(join(this.workspaceRoot, input));\n\n if (!isInternal) {\n this.watchFiles.add(normalizedAbsoluteInput);\n }\n\n if (this.#loadCache) {\n const cachedLoad = await (this.#loadCache.get(input) ??\n this.#loadCache.get(input.replace(';', ':')) ??\n this.#loadCache.get('file:' + normalizedAbsoluteInput));\n if (cachedLoad?.watchFiles) {\n for (const file of cachedLoad.watchFiles) {\n if (!isInternalAngularFile(file)) {\n this.watchFiles.add(\n isAbsolute(file) ? ensureUnixPath(file) : ensureUnixPath(join(this.workspaceRoot, file)),\n );\n }\n }\n }\n }\n }\n }\n\n // Return if the build encountered any errors\n if (result.errors.length) {\n this.#addErrorsToWatch(result);\n this.#addLoadCacheFilesToWatch();\n\n return {\n errors: result.errors,\n warnings: result.warnings,\n };\n }\n\n // Return the successful build results\n return {\n errors: undefined,\n warnings: result.warnings,\n metafile: result.metafile,\n outputFiles: result.outputFiles as BuildOutputFile[],\n };\n }\n\n #addErrorsToWatch(result: BuildFailure | BuildResult): void {\n for (const error of result.errors) {\n const file = error.location?.file;\n if (file && !isInternalAngularFile(file)) {\n this.watchFiles.add(isAbsolute(file) ? ensureUnixPath(file) : ensureUnixPath(join(this.workspaceRoot, file)));\n }\n for (const note of error.notes ?? []) {\n const noteFile = note.location?.file;\n if (noteFile && !isInternalAngularFile(noteFile)) {\n this.watchFiles.add(\n isAbsolute(noteFile) ? ensureUnixPath(noteFile) : ensureUnixPath(join(this.workspaceRoot, noteFile)),\n );\n }\n }\n }\n }\n\n #addLoadCacheFilesToWatch(): void {\n if (this.incremental && this.#loadCache) {\n for (const file of this.#loadCache.watchFiles) {\n if (!isInternalAngularFile(file)) {\n this.watchFiles.add(isAbsolute(file) ? ensureUnixPath(file) : ensureUnixPath(join(this.workspaceRoot, file)));\n }\n }\n }\n }\n\n /**\n * Invalidate a stored bundler result based on the previous watch files\n * and a list of changed files.\n * The context must be created with incremental mode enabled for results\n * to be stored.\n * @returns True, if the result was invalidated; False, otherwise.\n */\n invalidate(files: Iterable<string> | ReadonlySet<string>): boolean {\n if (!this.incremental) {\n return false;\n }\n\n let candidateFiles: ReadonlySet<string>;\n if (files instanceof Set) {\n let isCandidateReady = true;\n for (const file of files) {\n if (\n file !== ensureUnixPath(file) ||\n (!isAbsolute(file) && !files.has(ensureUnixPath(join(this.workspaceRoot, file))))\n ) {\n isCandidateReady = false;\n break;\n }\n }\n\n if (isCandidateReady) {\n candidateFiles = files;\n } else {\n const normalizedFiles = new Set<string>();\n for (const file of files) {\n const normalized = ensureUnixPath(file);\n normalizedFiles.add(normalized);\n if (!isAbsolute(normalized)) {\n normalizedFiles.add(ensureUnixPath(join(this.workspaceRoot, normalized)));\n }\n }\n candidateFiles = normalizedFiles;\n }\n } else {\n const normalizedFiles = new Set<string>();\n for (const file of files) {\n const normalized = ensureUnixPath(file);\n normalizedFiles.add(normalized);\n if (!isAbsolute(normalized)) {\n normalizedFiles.add(ensureUnixPath(join(this.workspaceRoot, normalized)));\n }\n }\n candidateFiles = normalizedFiles;\n }\n\n let invalid = false;\n for (const file of candidateFiles) {\n if (this.#loadCache?.invalidate(file)) {\n invalid = true;\n }\n }\n\n if (!invalid) {\n if (this.watchFiles.size < candidateFiles.size) {\n for (const file of this.watchFiles) {\n if (candidateFiles.has(file)) {\n invalid = true;\n break;\n }\n }\n } else {\n for (const file of candidateFiles) {\n if (this.watchFiles.has(file)) {\n invalid = true;\n break;\n }\n }\n }\n }\n\n if (invalid) {\n this.#esbuildResult = undefined;\n }\n\n return invalid;\n }\n\n /**\n * Disposes incremental build resources present in the context.\n *\n * @returns A promise that resolves when disposal is complete.\n */\n async dispose(): Promise<void> {\n this.#disposed = true;\n try {\n this.#esbuildOptions = undefined;\n this.#esbuildResult = undefined;\n this.#activeBundlePromise = undefined;\n this.#loadCache = undefined;\n await this.#esbuildContext?.dispose();\n } finally {\n this.#esbuildContext = undefined;\n }\n }\n}\n\nfunction isInternalAngularFile(file: string): boolean {\n return file.startsWith('angular:');\n}\n\nfunction isInternalBundlerFile(file: string): boolean {\n // Bundler virtual files such as \"<define:???>\" or \"<runtime>\"\n if (file[0] === '<' && file.at(-1) === '>') {\n return true;\n }\n\n // Any (disabled): path is a virtual esbuild entry that doesn't exist on disk\n if (file.includes('(disabled):')) {\n return true;\n }\n\n return false;\n}\n"]}
@@ -60,6 +60,10 @@ export declare class Cache<V, S extends CacheStore<V> = CacheStore<V>> {
60
60
  * @param value A value to put in the cache.
61
61
  */
62
62
  put(key: string, value: V): Promise<void>;
63
+ /**
64
+ * Clears internal state for a specific namespaced key (requests, write counts, and pending gets).
65
+ */
66
+ protected deleteInternal(namespacedKey: string): void;
63
67
  /**
64
68
  * Clears the base class internal state (requests, write counts, and pending gets).
65
69
  */
@@ -70,6 +74,12 @@ export declare class Cache<V, S extends CacheStore<V> = CacheStore<V>> {
70
74
  */
71
75
  export declare class MemoryCache<V> extends Cache<V, Map<string, V>> {
72
76
  constructor();
77
+ /**
78
+ * Removes the specified key from the cache instance.
79
+ * @param key The key to remove.
80
+ * @returns True if an element in the Map existed and has been removed, or false if the element does not exist.
81
+ */
82
+ delete(key: string): boolean;
73
83
  /**
74
84
  * Removes all entries from the cache instance.
75
85
  */
@@ -126,6 +126,14 @@ class Cache {
126
126
  this.#incrementWrite(namespacedKey);
127
127
  await this.store.set(namespacedKey, value);
128
128
  }
129
+ /**
130
+ * Clears internal state for a specific namespaced key (requests, write counts, and pending gets).
131
+ */
132
+ deleteInternal(namespacedKey) {
133
+ this.#requests.delete(namespacedKey);
134
+ this.#writeCounts.delete(namespacedKey);
135
+ this.#pendingGets.delete(namespacedKey);
136
+ }
129
137
  /**
130
138
  * Clears the base class internal state (requests, write counts, and pending gets).
131
139
  */
@@ -143,6 +151,16 @@ class MemoryCache extends Cache {
143
151
  constructor() {
144
152
  super(new Map());
145
153
  }
154
+ /**
155
+ * Removes the specified key from the cache instance.
156
+ * @param key The key to remove.
157
+ * @returns True if an element in the Map existed and has been removed, or false if the element does not exist.
158
+ */
159
+ delete(key) {
160
+ const namespacedKey = this.withNamespace(key);
161
+ this.deleteInternal(namespacedKey);
162
+ return this.store.delete(namespacedKey);
163
+ }
146
164
  /**
147
165
  * Removes all entries from the cache instance.
148
166
  */
@@ -1 +1 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../../src/lib/styles/cache.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A backing data store for one or more Cache instances.\n * The interface is intentionally designed to support using a JavaScript\n * Map instance as a potential cache store.\n */\nexport interface CacheStore<V> {\n /**\n * Returns the specified value from the cache store or `undefined` if not found.\n * @param key The key to retrieve from the store.\n */\n get(key: string): V | undefined | Promise<V | undefined>;\n\n /**\n * Returns whether the provided key is present in the cache store.\n * @param key The key to check from the store.\n */\n has(key: string): boolean | Promise<boolean>;\n\n /**\n * Adds a new value to the cache store if the key is not present.\n * Updates the value for the key if already present.\n * @param key The key to associate with the value in the cache store.\n * @param value The value to add to the cache store.\n */\n set(key: string, value: V): this | Promise<this>;\n}\n\n/**\n * A cache object that allows accessing and storing key/value pairs in\n * an underlying CacheStore. This class is the primary method for consumers\n * to use a cache.\n */\nexport class Cache<V, S extends CacheStore<V> = CacheStore<V>> {\n // In-flight creator promises to deduplicate concurrent requests for the same key.\n readonly #requests = new Map<string, Promise<V>>();\n // Track how many writes occurred for a key to detect mutations during await gaps.\n readonly #writeCounts = new Map<string, number>();\n // Count the number of active, pending getOrCreate operations per key to avoid memory leaks.\n readonly #pendingGets = new Map<string, number>();\n\n constructor(\n protected readonly store: S,\n readonly namespace?: string,\n ) {}\n\n #incrementWrite(key: string) {\n // Only track write counts if there is a pending getOrCreate operation active for the key.\n // This ensures that write counts are not leaked when no concurrent gets are running.\n if (this.#pendingGets.has(key)) {\n this.#writeCounts.set(key, (this.#writeCounts.get(key) || 0) + 1);\n }\n }\n\n /**\n * Prefixes a key with the cache namespace if present.\n * @param key A key string to prefix.\n * @returns A prefixed key if a namespace is present. Otherwise the provided key.\n */\n protected withNamespace(key: string): string {\n if (this.namespace) {\n return `${this.namespace}:${key}`;\n }\n\n return key;\n }\n\n /**\n * Gets the value associated with a provided key if available.\n * Otherwise, creates a value using the factory creator function, puts the value\n * in the cache, and returns the new value.\n * @param key A key associated with the value.\n * @param creator A factory function for the value if no value is present.\n * @returns A value associated with the provided key.\n */\n async getOrCreate(key: string, creator: () => V | Promise<V>): Promise<V> {\n const namespacedKey = this.withNamespace(key);\n\n // 1. If another call is already running the creator for this key, share its promise.\n let activeRequest = this.#requests.get(namespacedKey);\n if (activeRequest !== undefined) {\n return activeRequest;\n }\n\n // Increment pending gets count to enable write-tracking for this key.\n const currentPending = this.#pendingGets.get(namespacedKey) || 0;\n this.#pendingGets.set(namespacedKey, currentPending + 1);\n\n try {\n const startWriteCount = this.#writeCounts.get(namespacedKey) || 0;\n\n // 2. Query the backing store. Since store.get can be async, we yield to the event loop.\n const value = await this.store.get(namespacedKey);\n\n // If a write (e.g. put) occurred during the store.get await gap, we must abort\n // the current execution and restart to ensure we return the newly written value.\n if ((this.#writeCounts.get(namespacedKey) || 0) !== startWriteCount) {\n return this.getOrCreate(key, creator);\n }\n\n if (value !== undefined) {\n return value;\n }\n\n // 3. Recheck active request after the await gap in case another concurrent call\n // initiated a creator during the store.get wait.\n activeRequest = this.#requests.get(namespacedKey);\n if (activeRequest !== undefined) {\n return activeRequest;\n }\n\n // 4. Run the creator to produce the new value, and store its promise in #requests.\n activeRequest = Promise.resolve(creator()).then(\n async newValue => {\n // Ensure this request is still the active one before writing back to the store\n // (prevents overwriting newer data if put() was called before resolution).\n if (this.#requests.get(namespacedKey) === activeRequest) {\n this.#incrementWrite(namespacedKey);\n await this.store.set(namespacedKey, newValue);\n this.#requests.delete(namespacedKey);\n }\n\n return newValue;\n },\n error => {\n // Clean up the active request if the creator fails.\n if (this.#requests.get(namespacedKey) === activeRequest) {\n this.#requests.delete(namespacedKey);\n }\n throw error;\n },\n );\n\n this.#requests.set(namespacedKey, activeRequest);\n\n return activeRequest;\n } finally {\n // Clean up write counts and pending gets once all concurrent gets for this key finish.\n const current = this.#pendingGets.get(namespacedKey) || 0;\n if (current <= 1) {\n this.#pendingGets.delete(namespacedKey);\n this.#writeCounts.delete(namespacedKey);\n } else {\n this.#pendingGets.set(namespacedKey, current - 1);\n }\n }\n }\n\n /**\n * Gets the value associated with a provided key if available.\n * @param key A key associated with the value.\n * @returns A value associated with the provided key if present. Otherwise, `undefined`.\n */\n async get(key: string): Promise<V | undefined> {\n const value = await this.store.get(this.withNamespace(key));\n\n return value;\n }\n\n /**\n * Puts a value in the cache and associates it with the provided key.\n * If the key is already present, the value is updated instead.\n * @param key A key associated with the value.\n * @param value A value to put in the cache.\n */\n async put(key: string, value: V): Promise<void> {\n const namespacedKey = this.withNamespace(key);\n this.#requests.delete(namespacedKey);\n this.#incrementWrite(namespacedKey);\n await this.store.set(namespacedKey, value);\n }\n\n /**\n * Clears the base class internal state (requests, write counts, and pending gets).\n */\n protected clearInternal(): void {\n this.#requests.clear();\n this.#writeCounts.clear();\n this.#pendingGets.clear();\n }\n}\n\n/**\n * A lightweight in-memory cache implementation based on a JavaScript Map object.\n */\nexport class MemoryCache<V> extends Cache<V, Map<string, V>> {\n constructor() {\n super(new Map());\n }\n\n /**\n * Removes all entries from the cache instance.\n */\n clear() {\n this.clearInternal();\n this.store.clear();\n }\n\n /**\n * Provides all the values currently present in the cache instance.\n * @returns An iterable of all values in the cache.\n */\n values() {\n return this.store.values();\n }\n\n /**\n * Provides all the keys/values currently present in the cache instance.\n * @returns An iterable of all key/value pairs in the cache.\n */\n entries() {\n return this.store.entries();\n }\n}\n"]}
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../../src/lib/styles/cache.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A backing data store for one or more Cache instances.\n * The interface is intentionally designed to support using a JavaScript\n * Map instance as a potential cache store.\n */\nexport interface CacheStore<V> {\n /**\n * Returns the specified value from the cache store or `undefined` if not found.\n * @param key The key to retrieve from the store.\n */\n get(key: string): V | undefined | Promise<V | undefined>;\n\n /**\n * Returns whether the provided key is present in the cache store.\n * @param key The key to check from the store.\n */\n has(key: string): boolean | Promise<boolean>;\n\n /**\n * Adds a new value to the cache store if the key is not present.\n * Updates the value for the key if already present.\n * @param key The key to associate with the value in the cache store.\n * @param value The value to add to the cache store.\n */\n set(key: string, value: V): this | Promise<this>;\n}\n\n/**\n * A cache object that allows accessing and storing key/value pairs in\n * an underlying CacheStore. This class is the primary method for consumers\n * to use a cache.\n */\nexport class Cache<V, S extends CacheStore<V> = CacheStore<V>> {\n // In-flight creator promises to deduplicate concurrent requests for the same key.\n readonly #requests = new Map<string, Promise<V>>();\n // Track how many writes occurred for a key to detect mutations during await gaps.\n readonly #writeCounts = new Map<string, number>();\n // Count the number of active, pending getOrCreate operations per key to avoid memory leaks.\n readonly #pendingGets = new Map<string, number>();\n\n constructor(\n protected readonly store: S,\n readonly namespace?: string,\n ) {}\n\n #incrementWrite(key: string) {\n // Only track write counts if there is a pending getOrCreate operation active for the key.\n // This ensures that write counts are not leaked when no concurrent gets are running.\n if (this.#pendingGets.has(key)) {\n this.#writeCounts.set(key, (this.#writeCounts.get(key) || 0) + 1);\n }\n }\n\n /**\n * Prefixes a key with the cache namespace if present.\n * @param key A key string to prefix.\n * @returns A prefixed key if a namespace is present. Otherwise the provided key.\n */\n protected withNamespace(key: string): string {\n if (this.namespace) {\n return `${this.namespace}:${key}`;\n }\n\n return key;\n }\n\n /**\n * Gets the value associated with a provided key if available.\n * Otherwise, creates a value using the factory creator function, puts the value\n * in the cache, and returns the new value.\n * @param key A key associated with the value.\n * @param creator A factory function for the value if no value is present.\n * @returns A value associated with the provided key.\n */\n async getOrCreate(key: string, creator: () => V | Promise<V>): Promise<V> {\n const namespacedKey = this.withNamespace(key);\n\n // 1. If another call is already running the creator for this key, share its promise.\n let activeRequest = this.#requests.get(namespacedKey);\n if (activeRequest !== undefined) {\n return activeRequest;\n }\n\n // Increment pending gets count to enable write-tracking for this key.\n const currentPending = this.#pendingGets.get(namespacedKey) || 0;\n this.#pendingGets.set(namespacedKey, currentPending + 1);\n\n try {\n const startWriteCount = this.#writeCounts.get(namespacedKey) || 0;\n\n // 2. Query the backing store. Since store.get can be async, we yield to the event loop.\n const value = await this.store.get(namespacedKey);\n\n // If a write (e.g. put) occurred during the store.get await gap, we must abort\n // the current execution and restart to ensure we return the newly written value.\n if ((this.#writeCounts.get(namespacedKey) || 0) !== startWriteCount) {\n return this.getOrCreate(key, creator);\n }\n\n if (value !== undefined) {\n return value;\n }\n\n // 3. Recheck active request after the await gap in case another concurrent call\n // initiated a creator during the store.get wait.\n activeRequest = this.#requests.get(namespacedKey);\n if (activeRequest !== undefined) {\n return activeRequest;\n }\n\n // 4. Run the creator to produce the new value, and store its promise in #requests.\n activeRequest = Promise.resolve(creator()).then(\n async newValue => {\n // Ensure this request is still the active one before writing back to the store\n // (prevents overwriting newer data if put() was called before resolution).\n if (this.#requests.get(namespacedKey) === activeRequest) {\n this.#incrementWrite(namespacedKey);\n await this.store.set(namespacedKey, newValue);\n this.#requests.delete(namespacedKey);\n }\n\n return newValue;\n },\n error => {\n // Clean up the active request if the creator fails.\n if (this.#requests.get(namespacedKey) === activeRequest) {\n this.#requests.delete(namespacedKey);\n }\n throw error;\n },\n );\n\n this.#requests.set(namespacedKey, activeRequest);\n\n return activeRequest;\n } finally {\n // Clean up write counts and pending gets once all concurrent gets for this key finish.\n const current = this.#pendingGets.get(namespacedKey) || 0;\n if (current <= 1) {\n this.#pendingGets.delete(namespacedKey);\n this.#writeCounts.delete(namespacedKey);\n } else {\n this.#pendingGets.set(namespacedKey, current - 1);\n }\n }\n }\n\n /**\n * Gets the value associated with a provided key if available.\n * @param key A key associated with the value.\n * @returns A value associated with the provided key if present. Otherwise, `undefined`.\n */\n async get(key: string): Promise<V | undefined> {\n const value = await this.store.get(this.withNamespace(key));\n\n return value;\n }\n\n /**\n * Puts a value in the cache and associates it with the provided key.\n * If the key is already present, the value is updated instead.\n * @param key A key associated with the value.\n * @param value A value to put in the cache.\n */\n async put(key: string, value: V): Promise<void> {\n const namespacedKey = this.withNamespace(key);\n this.#requests.delete(namespacedKey);\n this.#incrementWrite(namespacedKey);\n await this.store.set(namespacedKey, value);\n }\n\n /**\n * Clears internal state for a specific namespaced key (requests, write counts, and pending gets).\n */\n protected deleteInternal(namespacedKey: string): void {\n this.#requests.delete(namespacedKey);\n this.#writeCounts.delete(namespacedKey);\n this.#pendingGets.delete(namespacedKey);\n }\n\n /**\n * Clears the base class internal state (requests, write counts, and pending gets).\n */\n protected clearInternal(): void {\n this.#requests.clear();\n this.#writeCounts.clear();\n this.#pendingGets.clear();\n }\n}\n\n/**\n * A lightweight in-memory cache implementation based on a JavaScript Map object.\n */\nexport class MemoryCache<V> extends Cache<V, Map<string, V>> {\n constructor() {\n super(new Map());\n }\n\n /**\n * Removes the specified key from the cache instance.\n * @param key The key to remove.\n * @returns True if an element in the Map existed and has been removed, or false if the element does not exist.\n */\n delete(key: string): boolean {\n const namespacedKey = this.withNamespace(key);\n this.deleteInternal(namespacedKey);\n\n return this.store.delete(namespacedKey);\n }\n\n /**\n * Removes all entries from the cache instance.\n */\n clear() {\n this.clearInternal();\n this.store.clear();\n }\n\n /**\n * Provides all the values currently present in the cache instance.\n * @returns An iterable of all values in the cache.\n */\n values() {\n return this.store.values();\n }\n\n /**\n * Provides all the keys/values currently present in the cache instance.\n * @returns An iterable of all key/value pairs in the cache.\n */\n entries() {\n return this.store.entries();\n }\n}\n"]}
@@ -19,9 +19,9 @@ export declare class ComponentStylesheetBundler {
19
19
  private readonly defaultInlineLanguage;
20
20
  private readonly incremental;
21
21
  /**
22
- *
23
22
  * @param options An object containing the stylesheet bundling options.
24
- * @param cache A load result cache to use when bundling.
23
+ * @param defaultInlineLanguage The default language to use for inline component styles.
24
+ * @param incremental True if incremental watch mode is enabled.
25
25
  */
26
26
  constructor(options: BundleStylesheetOptions, defaultInlineLanguage: string, incremental: boolean);
27
27
  bundleFile(entry: string): Promise<ComponentStylesheetResult>;
@@ -31,7 +31,7 @@ export declare class ComponentStylesheetBundler {
31
31
  * @param files The group of files that have been modified
32
32
  * @returns An array of file based stylesheet entries if any were invalidated; otherwise, undefined.
33
33
  */
34
- invalidate(files: Iterable<string>): string[] | undefined;
34
+ invalidate(files: Iterable<string> | ReadonlySet<string>): string[] | undefined;
35
35
  dispose(): Promise<void>;
36
36
  private extractResult;
37
37
  }
@@ -6,8 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.ComponentStylesheetBundler = void 0;
7
7
  const node_crypto_1 = require("node:crypto");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
+ const path_1 = require("../utils/path");
9
10
  const bundler_context_1 = require("./bundler-context");
10
11
  const cache_1 = require("./cache");
12
+ const load_result_cache_1 = require("./load-result-cache");
11
13
  const bundle_options_1 = require("./stylesheets/bundle-options");
12
14
  const sass_language_1 = require("./stylesheets/sass-language");
13
15
  /**
@@ -21,10 +23,11 @@ class ComponentStylesheetBundler {
21
23
  incremental;
22
24
  #fileContexts = new cache_1.MemoryCache();
23
25
  #inlineContexts = new cache_1.MemoryCache();
26
+ #loadCache = new load_result_cache_1.MemoryLoadResultCache();
24
27
  /**
25
- *
26
28
  * @param options An object containing the stylesheet bundling options.
27
- * @param cache A load result cache to use when bundling.
29
+ * @param defaultInlineLanguage The default language to use for inline component styles.
30
+ * @param incremental True if incremental watch mode is enabled.
28
31
  */
29
32
  constructor(options, defaultInlineLanguage, incremental) {
30
33
  this.options = options;
@@ -32,16 +35,20 @@ class ComponentStylesheetBundler {
32
35
  this.incremental = incremental;
33
36
  }
34
37
  async bundleFile(entry) {
38
+ entry = (0, path_1.ensureUnixPath)(entry);
35
39
  const bundlerContext = await this.#fileContexts.getOrCreate(entry, () => {
36
40
  return new bundler_context_1.BundlerContext(this.options.workspaceRoot, this.incremental, loadCache => {
37
41
  const buildOptions = (0, bundle_options_1.createStylesheetBundleOptions)(this.options, loadCache);
38
42
  buildOptions.entryPoints = [entry];
39
43
  return buildOptions;
40
- });
44
+ },
45
+ /* useContext */ false,
46
+ /* initialFilter */ undefined, this.#loadCache);
41
47
  });
42
48
  return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);
43
49
  }
44
50
  async bundleInline(data, filename, language = this.defaultInlineLanguage) {
51
+ filename = (0, path_1.ensureUnixPath)(filename);
45
52
  // Use a hash of the inline stylesheet content to ensure a consistent identifier. External stylesheets will resolve
46
53
  // to the actual stylesheet file path.
47
54
  // TODO: Consider xxhash instead for hashing
@@ -76,7 +83,9 @@ class ComponentStylesheetBundler {
76
83
  },
77
84
  });
78
85
  return buildOptions;
79
- });
86
+ },
87
+ /* useContext */ false,
88
+ /* initialFilter */ undefined, this.#loadCache);
80
89
  });
81
90
  // Extract the result of the bundling from the output files
82
91
  return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);
@@ -90,7 +99,14 @@ class ComponentStylesheetBundler {
90
99
  if (!this.incremental) {
91
100
  return;
92
101
  }
93
- const normalizedFiles = [...files].map(node_path_1.default.normalize);
102
+ const normalizedFiles = new Set();
103
+ for (const file of files) {
104
+ const normalized = (0, path_1.ensureUnixPath)(file);
105
+ normalizedFiles.add(normalized);
106
+ if (!node_path_1.default.isAbsolute(normalized)) {
107
+ normalizedFiles.add((0, path_1.ensureUnixPath)(node_path_1.default.join(this.options.workspaceRoot, normalized)));
108
+ }
109
+ }
94
110
  let entries;
95
111
  for (const [entry, bundler] of this.#fileContexts.entries()) {
96
112
  if (bundler.invalidate(normalizedFiles)) {
@@ -98,8 +114,18 @@ class ComponentStylesheetBundler {
98
114
  entries.push(entry);
99
115
  }
100
116
  }
101
- for (const bundler of this.#inlineContexts.values()) {
102
- bundler.invalidate(normalizedFiles);
117
+ for (const [entry, bundler] of this.#inlineContexts.entries()) {
118
+ // Entry is format: [language, id, filename].join(';')
119
+ const firstSemi = entry.indexOf(';');
120
+ const secondSemi = firstSemi !== -1 ? entry.indexOf(';', firstSemi + 1) : -1;
121
+ const filename = secondSemi !== -1 ? entry.slice(secondSemi + 1) : '';
122
+ if (filename && normalizedFiles.has((0, path_1.ensureUnixPath)(filename))) {
123
+ this.#inlineContexts.delete(entry);
124
+ void bundler.dispose();
125
+ }
126
+ else {
127
+ bundler.invalidate(normalizedFiles);
128
+ }
103
129
  }
104
130
  return entries;
105
131
  }
@@ -107,6 +133,7 @@ class ComponentStylesheetBundler {
107
133
  const contexts = [...this.#fileContexts.values(), ...this.#inlineContexts.values()];
108
134
  this.#fileContexts.clear();
109
135
  this.#inlineContexts.clear();
136
+ this.#loadCache.clear();
110
137
  await Promise.allSettled([(0, sass_language_1.shutdownSassWorkerPool)(), ...contexts.map(context => context.dispose())]);
111
138
  }
112
139
  extractResult(result, referencedFiles) {
@@ -1 +1 @@
1
- {"version":3,"file":"component-stylesheets.js","sourceRoot":"","sources":["../../../../src/lib/styles/component-stylesheets.ts"],"names":[],"mappings":"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","sourcesContent":["import { Message, Metafile, OutputFile } from 'esbuild';\nimport { createHash } from 'node:crypto';\nimport path from 'node:path';\nimport { BuildOutputFileType, BundleContextResult, BundlerContext } from './bundler-context';\nimport { MemoryCache } from './cache';\nimport { BundleStylesheetOptions, createStylesheetBundleOptions } from './stylesheets/bundle-options';\nimport { shutdownSassWorkerPool } from './stylesheets/sass-language';\n\nexport interface ComponentStylesheetResult {\n errors: Message[] | undefined;\n warnings: Message[];\n contents: string;\n outputFiles: OutputFile[];\n metafile: Metafile | undefined;\n referencedFiles: Set<string> | undefined;\n}\n\n/**\n * Bundles component stylesheets. A stylesheet can be either an inline stylesheet that\n * is contained within the Component's metadata definition or an external file referenced\n * from the Component's metadata definition.\n */\nexport class ComponentStylesheetBundler {\n readonly #fileContexts = new MemoryCache<BundlerContext>();\n readonly #inlineContexts = new MemoryCache<BundlerContext>();\n\n /**\n *\n * @param options An object containing the stylesheet bundling options.\n * @param cache A load result cache to use when bundling.\n */\n constructor(\n private readonly options: BundleStylesheetOptions,\n private readonly defaultInlineLanguage: string,\n private readonly incremental: boolean,\n ) {}\n\n async bundleFile(entry: string): Promise<ComponentStylesheetResult> {\n const bundlerContext = await this.#fileContexts.getOrCreate(entry, () => {\n return new BundlerContext(this.options.workspaceRoot, this.incremental, loadCache => {\n const buildOptions = createStylesheetBundleOptions(this.options, loadCache);\n\n buildOptions.entryPoints = [entry];\n\n return buildOptions;\n });\n });\n\n return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);\n }\n\n async bundleInline(data: string, filename: string, language: string = this.defaultInlineLanguage): Promise<ComponentStylesheetResult> {\n // Use a hash of the inline stylesheet content to ensure a consistent identifier. External stylesheets will resolve\n // to the actual stylesheet file path.\n // TODO: Consider xxhash instead for hashing\n const id = createHash('sha256').update(data).digest('hex');\n const entry = [language, id, filename].join(';');\n\n const bundlerContext = await this.#inlineContexts.getOrCreate(entry, () => {\n const namespace = 'angular:styles/component';\n\n return new BundlerContext(this.options.workspaceRoot, this.incremental, loadCache => {\n const buildOptions = createStylesheetBundleOptions(this.options, loadCache, {\n [entry]: data,\n });\n buildOptions.entryPoints = [`${namespace};${entry}`];\n\n buildOptions.plugins.push({\n name: 'angular-component-styles',\n setup(build) {\n build.onResolve({ filter: /^angular:styles\\/component;/ }, args => {\n if (args.kind !== 'entry-point') {\n return null;\n }\n\n return {\n path: entry,\n namespace,\n };\n });\n build.onLoad({ filter: /^css;/, namespace }, () => {\n return {\n contents: data,\n loader: 'css',\n resolveDir: path.dirname(filename),\n };\n });\n },\n });\n\n return buildOptions;\n });\n });\n\n // Extract the result of the bundling from the output files\n return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);\n }\n\n /**\n * Invalidates both file and inline based component style bundling state for a set of modified files.\n * @param files The group of files that have been modified\n * @returns An array of file based stylesheet entries if any were invalidated; otherwise, undefined.\n */\n invalidate(files: Iterable<string>): string[] | undefined {\n if (!this.incremental) {\n return;\n }\n\n const normalizedFiles = [...files].map(path.normalize);\n let entries: string[] | undefined;\n\n for (const [entry, bundler] of this.#fileContexts.entries()) {\n if (bundler.invalidate(normalizedFiles)) {\n entries ??= [];\n entries.push(entry);\n }\n }\n for (const bundler of this.#inlineContexts.values()) {\n bundler.invalidate(normalizedFiles);\n }\n\n return entries;\n }\n\n async dispose(): Promise<void> {\n const contexts = [...this.#fileContexts.values(), ...this.#inlineContexts.values()];\n this.#fileContexts.clear();\n this.#inlineContexts.clear();\n\n await Promise.allSettled([shutdownSassWorkerPool(), ...contexts.map(context => context.dispose())]);\n }\n\n private extractResult(result: BundleContextResult, referencedFiles: Set<string> | undefined): ComponentStylesheetResult {\n let contents = '';\n let metafile;\n const outputFiles: OutputFile[] = [];\n\n if ('outputFiles' in result) {\n for (const outputFile of result.outputFiles) {\n const filename = path.basename(outputFile.path);\n\n if (outputFile.type === BuildOutputFileType.Media || filename.endsWith('.css.map')) {\n // The output files could also contain resources (images/fonts/etc.) that were referenced and the map files.\n\n // Clone the output file to avoid amending the original path which would causes problems during rebuild.\n const clonedOutputFile = outputFile.clone();\n\n // Needed for Bazel as otherwise the files will not be written in the correct place,\n // this is because esbuild will resolve the output file from the outdir which is currently set to `workspaceRoot` twice,\n // once in the stylesheet and the other in the application code bundler.\n // Ex: `../../../../../app.component.css.map`.\n clonedOutputFile.path = path.join(this.options.workspaceRoot, outputFile.path);\n\n outputFiles.push(clonedOutputFile);\n } else if (filename.endsWith('.css')) {\n contents = outputFile.text;\n } else {\n throw new Error(\n `Unexpected non CSS/Media file \"${filename}\" outputted during component stylesheet processing.`,\n );\n }\n }\n\n metafile = result.metafile;\n }\n\n return {\n errors: result.errors,\n warnings: result.warnings,\n contents,\n outputFiles,\n metafile,\n referencedFiles,\n };\n }\n}\n"]}
1
+ {"version":3,"file":"component-stylesheets.js","sourceRoot":"","sources":["../../../../src/lib/styles/component-stylesheets.ts"],"names":[],"mappings":"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","sourcesContent":["import { Message, Metafile, OutputFile } from 'esbuild';\nimport { createHash } from 'node:crypto';\nimport path from 'node:path';\nimport { ensureUnixPath } from '../utils/path';\nimport { BuildOutputFileType, BundleContextResult, BundlerContext } from './bundler-context';\nimport { MemoryCache } from './cache';\nimport { MemoryLoadResultCache } from './load-result-cache';\nimport { BundleStylesheetOptions, createStylesheetBundleOptions } from './stylesheets/bundle-options';\nimport { shutdownSassWorkerPool } from './stylesheets/sass-language';\n\nexport interface ComponentStylesheetResult {\n errors: Message[] | undefined;\n warnings: Message[];\n contents: string;\n outputFiles: OutputFile[];\n metafile: Metafile | undefined;\n referencedFiles: Set<string> | undefined;\n}\n\n/**\n * Bundles component stylesheets. A stylesheet can be either an inline stylesheet that\n * is contained within the Component's metadata definition or an external file referenced\n * from the Component's metadata definition.\n */\nexport class ComponentStylesheetBundler {\n readonly #fileContexts = new MemoryCache<BundlerContext>();\n readonly #inlineContexts = new MemoryCache<BundlerContext>();\n readonly #loadCache = new MemoryLoadResultCache();\n\n /**\n * @param options An object containing the stylesheet bundling options.\n * @param defaultInlineLanguage The default language to use for inline component styles.\n * @param incremental True if incremental watch mode is enabled.\n */\n constructor(\n private readonly options: BundleStylesheetOptions,\n private readonly defaultInlineLanguage: string,\n private readonly incremental: boolean,\n ) {}\n\n async bundleFile(entry: string): Promise<ComponentStylesheetResult> {\n entry = ensureUnixPath(entry);\n\n const bundlerContext = await this.#fileContexts.getOrCreate(entry, () => {\n return new BundlerContext(\n this.options.workspaceRoot,\n this.incremental,\n loadCache => {\n const buildOptions = createStylesheetBundleOptions(this.options, loadCache);\n\n buildOptions.entryPoints = [entry];\n\n return buildOptions;\n },\n /* useContext */ false,\n /* initialFilter */ undefined,\n this.#loadCache,\n );\n });\n\n return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);\n }\n\n async bundleInline(\n data: string,\n filename: string,\n language: string = this.defaultInlineLanguage,\n ): Promise<ComponentStylesheetResult> {\n filename = ensureUnixPath(filename);\n\n // Use a hash of the inline stylesheet content to ensure a consistent identifier. External stylesheets will resolve\n // to the actual stylesheet file path.\n // TODO: Consider xxhash instead for hashing\n const id = createHash('sha256').update(data).digest('hex');\n const entry = [language, id, filename].join(';');\n\n const bundlerContext = await this.#inlineContexts.getOrCreate(entry, () => {\n const namespace = 'angular:styles/component';\n\n return new BundlerContext(\n this.options.workspaceRoot,\n this.incremental,\n loadCache => {\n const buildOptions = createStylesheetBundleOptions(this.options, loadCache, {\n [entry]: data,\n });\n buildOptions.entryPoints = [`${namespace};${entry}`];\n\n buildOptions.plugins.push({\n name: 'angular-component-styles',\n setup(build) {\n build.onResolve({ filter: /^angular:styles\\/component;/ }, args => {\n if (args.kind !== 'entry-point') {\n return null;\n }\n\n return {\n path: entry,\n namespace,\n };\n });\n build.onLoad({ filter: /^css;/, namespace }, () => {\n return {\n contents: data,\n loader: 'css',\n resolveDir: path.dirname(filename),\n };\n });\n },\n });\n\n return buildOptions;\n },\n /* useContext */ false,\n /* initialFilter */ undefined,\n this.#loadCache,\n );\n });\n\n // Extract the result of the bundling from the output files\n return this.extractResult(await bundlerContext.bundle(), bundlerContext.watchFiles);\n }\n\n /**\n * Invalidates both file and inline based component style bundling state for a set of modified files.\n * @param files The group of files that have been modified\n * @returns An array of file based stylesheet entries if any were invalidated; otherwise, undefined.\n */\n invalidate(files: Iterable<string> | ReadonlySet<string>): string[] | undefined {\n if (!this.incremental) {\n return;\n }\n\n const normalizedFiles = new Set<string>();\n for (const file of files) {\n const normalized = ensureUnixPath(file);\n normalizedFiles.add(normalized);\n if (!path.isAbsolute(normalized)) {\n normalizedFiles.add(ensureUnixPath(path.join(this.options.workspaceRoot, normalized)));\n }\n }\n\n let entries: string[] | undefined;\n\n for (const [entry, bundler] of this.#fileContexts.entries()) {\n if (bundler.invalidate(normalizedFiles)) {\n entries ??= [];\n entries.push(entry);\n }\n }\n for (const [entry, bundler] of this.#inlineContexts.entries()) {\n // Entry is format: [language, id, filename].join(';')\n const firstSemi = entry.indexOf(';');\n const secondSemi = firstSemi !== -1 ? entry.indexOf(';', firstSemi + 1) : -1;\n const filename = secondSemi !== -1 ? entry.slice(secondSemi + 1) : '';\n if (filename && normalizedFiles.has(ensureUnixPath(filename))) {\n this.#inlineContexts.delete(entry);\n void bundler.dispose();\n } else {\n bundler.invalidate(normalizedFiles);\n }\n }\n\n return entries;\n }\n\n async dispose(): Promise<void> {\n const contexts = [...this.#fileContexts.values(), ...this.#inlineContexts.values()];\n this.#fileContexts.clear();\n this.#inlineContexts.clear();\n this.#loadCache.clear();\n\n await Promise.allSettled([shutdownSassWorkerPool(), ...contexts.map(context => context.dispose())]);\n }\n\n private extractResult(\n result: BundleContextResult,\n referencedFiles: Set<string> | undefined,\n ): ComponentStylesheetResult {\n let contents = '';\n let metafile;\n const outputFiles: OutputFile[] = [];\n\n if ('outputFiles' in result) {\n for (const outputFile of result.outputFiles) {\n const filename = path.basename(outputFile.path);\n\n if (outputFile.type === BuildOutputFileType.Media || filename.endsWith('.css.map')) {\n // The output files could also contain resources (images/fonts/etc.) that were referenced and the map files.\n\n // Clone the output file to avoid amending the original path which would causes problems during rebuild.\n const clonedOutputFile = outputFile.clone();\n\n // Needed for Bazel as otherwise the files will not be written in the correct place,\n // this is because esbuild will resolve the output file from the outdir which is currently set to `workspaceRoot` twice,\n // once in the stylesheet and the other in the application code bundler.\n // Ex: `../../../../../app.component.css.map`.\n clonedOutputFile.path = path.join(this.options.workspaceRoot, outputFile.path);\n\n outputFiles.push(clonedOutputFile);\n } else if (filename.endsWith('.css')) {\n contents = outputFile.text;\n } else {\n throw new Error(\n `Unexpected non CSS/Media file \"${filename}\" outputted during component stylesheet processing.`,\n );\n }\n }\n\n metafile = result.metafile;\n }\n\n return {\n errors: result.errors,\n warnings: result.warnings,\n contents,\n outputFiles,\n metafile,\n referencedFiles,\n };\n }\n}\n"]}
@@ -2,6 +2,7 @@ import type { OnLoadResult, PluginBuild } from 'esbuild';
2
2
  export interface LoadResultCache {
3
3
  get(path: string): OnLoadResult | undefined;
4
4
  put(path: string, result: OnLoadResult): Promise<void>;
5
+ invalidate(path: string): boolean;
5
6
  readonly watchFiles: ReadonlyArray<string>;
6
7
  }
7
8
  export declare function createCachedLoad(cache: LoadResultCache | undefined, callback: Parameters<PluginBuild['onLoad']>[1]): Parameters<PluginBuild['onLoad']>[1];
@@ -11,4 +12,5 @@ export declare class MemoryLoadResultCache implements LoadResultCache {
11
12
  put(path: string, result: OnLoadResult): Promise<void>;
12
13
  invalidate(path: string): boolean;
13
14
  get watchFiles(): string[];
15
+ clear(): void;
14
16
  }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MemoryLoadResultCache = void 0;
4
4
  exports.createCachedLoad = createCachedLoad;
5
- const node_path_1 = require("node:path");
5
+ const path_1 = require("../utils/path");
6
6
  function createCachedLoad(cache, callback) {
7
7
  if (cache === undefined) {
8
8
  return callback;
@@ -36,7 +36,7 @@ class MemoryLoadResultCache {
36
36
  if (result.watchFiles) {
37
37
  for (const watchFile of result.watchFiles) {
38
38
  // Normalize the watch file path to ensure OS consistent paths
39
- const normalizedWatchFile = (0, node_path_1.normalize)(watchFile);
39
+ const normalizedWatchFile = (0, path_1.ensureUnixPath)(watchFile);
40
40
  let affected = this.#fileDependencies.get(normalizedWatchFile);
41
41
  if (affected === undefined) {
42
42
  affected = new Set();
@@ -47,7 +47,7 @@ class MemoryLoadResultCache {
47
47
  }
48
48
  }
49
49
  invalidate(path) {
50
- const affectedPaths = this.#fileDependencies.get(path);
50
+ const affectedPaths = this.#fileDependencies.get((0, path_1.ensureUnixPath)(path));
51
51
  let found = false;
52
52
  if (affectedPaths) {
53
53
  for (const affected of affectedPaths) {
@@ -64,6 +64,10 @@ class MemoryLoadResultCache {
64
64
  // are namespaced request paths and not disk-based file paths.
65
65
  return [...this.#fileDependencies.keys()];
66
66
  }
67
+ clear() {
68
+ this.#loadResults.clear();
69
+ this.#fileDependencies.clear();
70
+ }
67
71
  }
68
72
  exports.MemoryLoadResultCache = MemoryLoadResultCache;
69
73
  //# sourceMappingURL=load-result-cache.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"load-result-cache.js","sourceRoot":"","sources":["../../../../src/lib/styles/load-result-cache.ts"],"names":[],"mappings":";;;AASA,4CA4BC;AApCD,yCAAsC;AAQtC,SAAgB,gBAAgB,CAC9B,KAAkC,EAClC,QAA8C;IAE9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,KAAK,EAAE,IAAI,EAAE,EAAE;QACpB,MAAM,YAAY,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACtD,IAAI,MAAM,GAAoC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAEtE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;YAE9B,iCAAiC;YACjC,IAAI,MAAM,EAAE,CAAC;gBACX,8DAA8D;gBAC9D,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM,EAAE,CAAC;oBAC9B,MAAM,CAAC,UAAU,KAAK,EAAE,CAAC;oBACzB,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACpC,CAAC;gBACD,MAAM,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC;AAED,MAAa,qBAAqB;IAChC,YAAY,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC/C,iBAAiB,GAAG,IAAI,GAAG,EAAuB,CAAC;IAEnD,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,IAAY,EAAE,MAAoB;QAC1C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpC,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;YACtB,KAAK,MAAM,SAAS,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBAC1C,8DAA8D;gBAC9D,MAAM,mBAAmB,GAAG,IAAA,qBAAS,EAAC,SAAS,CAAC,CAAC;gBACjD,IAAI,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBAC/D,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;oBACrB,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC;gBAC5D,CAAC;gBACD,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;IACH,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,MAAM,aAAa,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,KAAK,GAAG,KAAK,CAAC;QAElB,IAAI,aAAa,EAAE,CAAC;YAClB,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,CAAC;gBACrC,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACvC,KAAK,GAAG,IAAI,CAAC;gBACf,CAAC;YACH,CAAC;YACD,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,UAAU;QACZ,iEAAiE;QACjE,8DAA8D;QAC9D,OAAO,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;CACF;AA7CD,sDA6CC","sourcesContent":["import type { OnLoadResult, PluginBuild } from 'esbuild';\nimport { normalize } from 'node:path';\n\nexport interface LoadResultCache {\n get(path: string): OnLoadResult | undefined;\n put(path: string, result: OnLoadResult): Promise<void>;\n readonly watchFiles: ReadonlyArray<string>;\n}\n\nexport function createCachedLoad(\n cache: LoadResultCache | undefined,\n callback: Parameters<PluginBuild['onLoad']>[1],\n): Parameters<PluginBuild['onLoad']>[1] {\n if (cache === undefined) {\n return callback;\n }\n\n return async (args) => {\n const loadCacheKey = `${args.namespace}:${args.path}`;\n let result: OnLoadResult | null | undefined = cache.get(loadCacheKey);\n\n if (result === undefined) {\n result = await callback(args);\n\n // Do not cache null or undefined\n if (result) {\n // Ensure requested path is included if it was a resolved file\n if (args.namespace === 'file') {\n result.watchFiles ??= [];\n result.watchFiles.push(args.path);\n }\n await cache.put(loadCacheKey, result);\n }\n }\n\n return result;\n };\n}\n\nexport class MemoryLoadResultCache implements LoadResultCache {\n #loadResults = new Map<string, OnLoadResult>();\n #fileDependencies = new Map<string, Set<string>>();\n\n get(path: string): OnLoadResult | undefined {\n return this.#loadResults.get(path);\n }\n\n async put(path: string, result: OnLoadResult): Promise<void> {\n this.#loadResults.set(path, result);\n if (result.watchFiles) {\n for (const watchFile of result.watchFiles) {\n // Normalize the watch file path to ensure OS consistent paths\n const normalizedWatchFile = normalize(watchFile);\n let affected = this.#fileDependencies.get(normalizedWatchFile);\n if (affected === undefined) {\n affected = new Set();\n this.#fileDependencies.set(normalizedWatchFile, affected);\n }\n affected.add(path);\n }\n }\n }\n\n invalidate(path: string): boolean {\n const affectedPaths = this.#fileDependencies.get(path);\n let found = false;\n\n if (affectedPaths) {\n for (const affected of affectedPaths) {\n if (this.#loadResults.delete(affected)) {\n found = true;\n }\n }\n this.#fileDependencies.delete(path);\n }\n\n return found;\n }\n\n get watchFiles(): string[] {\n // this.#loadResults.keys() is not included here because the keys\n // are namespaced request paths and not disk-based file paths.\n return [...this.#fileDependencies.keys()];\n }\n}\n"]}
1
+ {"version":3,"file":"load-result-cache.js","sourceRoot":"","sources":["../../../../src/lib/styles/load-result-cache.ts"],"names":[],"mappings":"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","sourcesContent":["import type { OnLoadResult, PluginBuild } from 'esbuild';\nimport { ensureUnixPath } from '../utils/path';\n\nexport interface LoadResultCache {\n get(path: string): OnLoadResult | undefined;\n put(path: string, result: OnLoadResult): Promise<void>;\n invalidate(path: string): boolean;\n readonly watchFiles: ReadonlyArray<string>;\n}\n\nexport function createCachedLoad(\n cache: LoadResultCache | undefined,\n callback: Parameters<PluginBuild['onLoad']>[1],\n): Parameters<PluginBuild['onLoad']>[1] {\n if (cache === undefined) {\n return callback;\n }\n\n return async args => {\n const loadCacheKey = `${args.namespace}:${args.path}`;\n let result: OnLoadResult | null | undefined = cache.get(loadCacheKey);\n\n if (result === undefined) {\n result = await callback(args);\n\n // Do not cache null or undefined\n if (result) {\n // Ensure requested path is included if it was a resolved file\n if (args.namespace === 'file') {\n result.watchFiles ??= [];\n result.watchFiles.push(args.path);\n }\n await cache.put(loadCacheKey, result);\n }\n }\n\n return result;\n };\n}\n\nexport class MemoryLoadResultCache implements LoadResultCache {\n #loadResults = new Map<string, OnLoadResult>();\n #fileDependencies = new Map<string, Set<string>>();\n\n get(path: string): OnLoadResult | undefined {\n return this.#loadResults.get(path);\n }\n\n async put(path: string, result: OnLoadResult): Promise<void> {\n this.#loadResults.set(path, result);\n if (result.watchFiles) {\n for (const watchFile of result.watchFiles) {\n // Normalize the watch file path to ensure OS consistent paths\n const normalizedWatchFile = ensureUnixPath(watchFile);\n let affected = this.#fileDependencies.get(normalizedWatchFile);\n if (affected === undefined) {\n affected = new Set();\n this.#fileDependencies.set(normalizedWatchFile, affected);\n }\n affected.add(path);\n }\n }\n }\n\n invalidate(path: string): boolean {\n const affectedPaths = this.#fileDependencies.get(ensureUnixPath(path));\n let found = false;\n\n if (affectedPaths) {\n for (const affected of affectedPaths) {\n if (this.#loadResults.delete(affected)) {\n found = true;\n }\n }\n this.#fileDependencies.delete(path);\n }\n\n return found;\n }\n\n get watchFiles(): string[] {\n // this.#loadResults.keys() is not included here because the keys\n // are namespaced request paths and not disk-based file paths.\n return [...this.#fileDependencies.keys()];\n }\n\n clear(): void {\n this.#loadResults.clear();\n this.#fileDependencies.clear();\n }\n}\n"]}