auklet 0.3.3 → 0.3.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.
@@ -29,6 +29,8 @@ export declare class StylePackageContext {
29
29
  constructor(options: StylePackageContextOptions);
30
30
  getStyleFiles(files: Array<string>): string[];
31
31
  getModuleStyleImports(): Map<string, string[]>;
32
+ invalidateModuleStyleImports(): void;
33
+ invalidateStyleContentCaches(): void;
32
34
  getModuleStyleEntryPlanner(): StyleModuleEntryPlanner;
33
35
  getStyleEntryFiles(): string[];
34
36
  isSharedStyleFile(file: string): boolean;
@@ -59,6 +59,15 @@ export class StylePackageContext {
59
59
  this.moduleStyleImports ??= this.importCollector.collect(this.sourceFiles, this.normalizedConfig);
60
60
  return this.moduleStyleImports;
61
61
  }
62
+ invalidateModuleStyleImports() {
63
+ this.moduleStyleImports = undefined;
64
+ this.moduleStyleEntryPlanner = undefined;
65
+ }
66
+ invalidateStyleContentCaches() {
67
+ this.moduleStyleEntryPlanner = undefined;
68
+ this.hasValidatedSourceRootLocalStyleImports = false;
69
+ this.hasValidatedPreservedLocalStyleImports = false;
70
+ }
62
71
  getModuleStyleEntryPlanner() {
63
72
  this.moduleStyleEntryPlanner ??= new StyleModuleEntryPlanner(this);
64
73
  return this.moduleStyleEntryPlanner;
@@ -1,9 +1,13 @@
1
+ import { StylePackageContext } from '#auklet/css/core/stylePackageContext';
1
2
  import type { ModuleStyleBuildConfig, ModuleStyleBuildContext, ModuleStyleBuildOptions } from '#auklet/types';
3
+ type ModuleStyleBuildInternalOptions = ModuleStyleBuildOptions & {
4
+ packageContext?: StylePackageContext;
5
+ };
2
6
  export declare class ModuleStyleBuilder {
3
7
  private readonly config;
4
8
  private readonly context;
5
9
  constructor(context?: ModuleStyleBuildContext, config?: ModuleStyleBuildConfig);
6
- build(options?: ModuleStyleBuildOptions): Promise<{
10
+ build(options?: ModuleStyleBuildInternalOptions): Promise<{
7
11
  packageRoot: string;
8
12
  styleFiles: string[];
9
13
  outputs: {
@@ -11,6 +15,8 @@ export declare class ModuleStyleBuilder {
11
15
  size: number;
12
16
  }[];
13
17
  }>;
18
+ createPackageContext(options?: ModuleStyleBuildOptions): StylePackageContext;
14
19
  private createBuildContext;
15
- private createPackageContext;
20
+ private createStylePackageContext;
16
21
  }
22
+ export {};
@@ -20,7 +20,8 @@ export class ModuleStyleBuilder {
20
20
  const rawConfig = options.aukletConfig ?? this.context.aukletConfig ?? {};
21
21
  const normalizedConfig = normalizeAukletConfig(rawConfig);
22
22
  const context = this.createBuildContext(normalizedConfig);
23
- const packageContext = this.createPackageContext(context, normalizedConfig);
23
+ const packageContext = options.packageContext ??
24
+ this.createStylePackageContext(context, normalizedConfig);
24
25
  packageContext.assertNoSourceRootEscapingLocalStyleImports();
25
26
  const writerOptions = {
26
27
  config: this.config,
@@ -42,6 +43,12 @@ export class ModuleStyleBuilder {
42
43
  })),
43
44
  };
44
45
  }
46
+ createPackageContext(options = {}) {
47
+ const rawConfig = options.aukletConfig ?? this.context.aukletConfig ?? {};
48
+ const normalizedConfig = normalizeAukletConfig(rawConfig);
49
+ const context = this.createBuildContext(normalizedConfig);
50
+ return this.createStylePackageContext(context, normalizedConfig);
51
+ }
45
52
  createBuildContext(config) {
46
53
  return {
47
54
  packageRoot: this.context.packageRoot,
@@ -49,7 +56,7 @@ export class ModuleStyleBuilder {
49
56
  outputDir: this.context.output ?? config.output,
50
57
  };
51
58
  }
52
- createPackageContext(context, normalizedConfig) {
59
+ createStylePackageContext(context, normalizedConfig) {
53
60
  return new StylePackageContext({
54
61
  config: this.config,
55
62
  context,
@@ -37,7 +37,6 @@ export declare class AukletStyleHmr {
37
37
  private sameStyleLoadResult;
38
38
  private suppressFullReload;
39
39
  private shouldSuppressFullReload;
40
- private logDebug;
41
40
  private isDuplicateUpdate;
42
41
  }
43
42
  export {};
@@ -129,18 +129,12 @@ export class AukletStyleHmr {
129
129
  if (!graph.isStyleFile(context.file)) {
130
130
  return undefined;
131
131
  }
132
- const totalStartedAt = Date.now();
133
132
  const isSourceGraphFile = graph.isSourceGraphFile(context.file);
134
133
  const trackedEntries = this.getTrackedStyleFileEntries(context.file, context.server.moduleGraph);
135
- const debug = trackedEntries.length
136
- ? await graph.isDebugEnabled(trackedEntries[0].parsed)
137
- : false;
138
- this.logDebug(debug, `package css hmr start ${getRelativeFile(context.file)} tracked=${trackedEntries.length}`);
139
134
  if (!trackedEntries.length) {
140
135
  if (isSourceGraphFile) {
141
136
  graph.invalidateFile(context.file);
142
137
  }
143
- this.logDebug(debug, `package css hmr skip ${getRelativeFile(context.file)} total=${Date.now() - totalStartedAt}ms`);
144
138
  return undefined;
145
139
  }
146
140
  const entryEntries = isSourceGraphFile
@@ -153,7 +147,7 @@ export class AukletStyleHmr {
153
147
  ? this.createTrackedVirtualStyleResults(graph, entryEntries)
154
148
  : null;
155
149
  if (isSourceGraphFile) {
156
- graph.invalidateFile(context.file);
150
+ graph.invalidateFileLoadResults(context.file);
157
151
  }
158
152
  else {
159
153
  this.invalidateTrackedVirtualPackages(graph, dependencyEntries);
@@ -161,16 +155,14 @@ export class AukletStyleHmr {
161
155
  if (this.isDuplicateUpdate(context.file)) {
162
156
  return [];
163
157
  }
164
- const updates = [
165
- ...(dependencyEntries.length
166
- ? this.createTrackedVirtualStyleUpdates(context.server, dependencyEntries, context.timestamp)
167
- : []),
168
- ...(entryEntries.length
169
- ? await this.refreshTrackedVirtualStyleUpdates(context.server, entryEntries, previousResults, context.timestamp, debug)
170
- : []),
171
- ];
158
+ const dependencyUpdates = dependencyEntries.length
159
+ ? this.createTrackedVirtualStyleUpdates(context.server, dependencyEntries, context.timestamp)
160
+ : [];
161
+ const entryUpdates = entryEntries.length
162
+ ? await this.refreshTrackedVirtualStyleUpdates(context.server, entryEntries, previousResults, context.timestamp)
163
+ : [];
164
+ const updates = [...dependencyUpdates, ...entryUpdates];
172
165
  if (!updates.length) {
173
- this.logDebug(debug, `package css hmr no-update ${getRelativeFile(context.file)} total=${Date.now() - totalStartedAt}ms`);
174
166
  return undefined;
175
167
  }
176
168
  this.suppressFullReload();
@@ -179,7 +171,6 @@ export class AukletStyleHmr {
179
171
  updates,
180
172
  });
181
173
  logger.info(`package css hmr ${getRelativeFile(context.file)} tracked=${trackedEntries.length} updates=${updates.length}`);
182
- this.logDebug(debug, `package css hmr done ${getRelativeFile(context.file)} tracked=${trackedEntries.length} updates=${updates.length} total=${Date.now() - totalStartedAt}ms`);
183
174
  return [];
184
175
  }
185
176
  async handleSourceModuleChange(server, file) {
@@ -187,25 +178,20 @@ export class AukletStyleHmr {
187
178
  if (!graph.isSourceGraphFile(file) || !graph.isSourceModuleFile(file)) {
188
179
  return false;
189
180
  }
190
- const totalStartedAt = Date.now();
191
181
  const virtualIds = this.getDependencyVirtualIds(file, server.moduleGraph);
192
182
  if (!virtualIds.length) {
193
183
  graph.invalidateFile(file);
194
- this.logDebug(false, `package css source hmr skip ${getRelativeFile(file)} reason=untracked total=${Date.now() - totalStartedAt}ms`);
195
184
  return false;
196
185
  }
197
186
  const parsedVirtualIds = this.parseTrackedVirtualIds(graph, virtualIds);
198
187
  if (!parsedVirtualIds.length) {
199
188
  graph.invalidateFile(file);
200
- this.logDebug(false, `package css source hmr skip ${getRelativeFile(file)} reason=unparsed total=${Date.now() - totalStartedAt}ms`);
201
189
  return false;
202
190
  }
203
- const debug = await graph.isDebugEnabled(parsedVirtualIds[0].parsed);
204
191
  const previousResults = this.createTrackedVirtualStyleResults(graph, parsedVirtualIds);
205
192
  graph.invalidateFile(file);
206
- const updates = await this.refreshTrackedVirtualStyleUpdates(server, parsedVirtualIds, previousResults, Date.now(), debug);
193
+ const updates = await this.refreshTrackedVirtualStyleUpdates(server, parsedVirtualIds, previousResults, Date.now());
207
194
  if (!updates.length) {
208
- this.logDebug(debug, `package css source hmr no-update ${getRelativeFile(file)} tracked=${parsedVirtualIds.length} total=${Date.now() - totalStartedAt}ms`);
209
195
  return false;
210
196
  }
211
197
  this.suppressFullReload();
@@ -214,7 +200,6 @@ export class AukletStyleHmr {
214
200
  updates,
215
201
  });
216
202
  logger.info(`package css source hmr ${getRelativeFile(file)} tracked=${parsedVirtualIds.length} updates=${updates.length}`);
217
- this.logDebug(debug, `package css source hmr done ${getRelativeFile(file)} tracked=${parsedVirtualIds.length} updates=${updates.length} total=${Date.now() - totalStartedAt}ms`);
218
203
  return true;
219
204
  }
220
205
  parseTrackedVirtualIds(graph, virtualIds) {
@@ -309,13 +294,11 @@ export class AukletStyleHmr {
309
294
  kind,
310
295
  };
311
296
  }
312
- async refreshTrackedVirtualStyleUpdates(server, parsedVirtualIds, previousResults, timestamp, debug) {
297
+ async refreshTrackedVirtualStyleUpdates(server, parsedVirtualIds, previousResults, timestamp) {
313
298
  const graph = this.graph();
314
299
  const changedVirtualIds = [];
315
300
  for (const item of parsedVirtualIds) {
316
- const buildStartedAt = Date.now();
317
301
  const nextResult = await graph.createPackageStyleCode(item.parsed);
318
- this.logDebug(debug, `package css hmr rebuild ${item.id} took=${Date.now() - buildStartedAt}ms`);
319
302
  const previousResult = previousResults.get(item.id);
320
303
  if (!previousResult ||
321
304
  !this.sameStyleLoadResult(previousResult, nextResult)) {
@@ -339,11 +322,6 @@ export class AukletStyleHmr {
339
322
  shouldSuppressFullReload() {
340
323
  return Date.now() <= this.suppressFullReloadUntil;
341
324
  }
342
- logDebug(enabled, message) {
343
- if (!enabled)
344
- return;
345
- logger.info(message);
346
- }
347
325
  isDuplicateUpdate(file) {
348
326
  const now = Date.now();
349
327
  const normalizedFile = normalizeFileKey(file);
@@ -17,9 +17,10 @@ export declare class ModuleStyleGraph {
17
17
  getWatchRoots(): Promise<string[]>;
18
18
  createPackageStyleCode(parsed: PackageStyleId): Promise<import("#auklet/css/vite/moduleGraph/types").PackageStyleLoadResult>;
19
19
  peekPackageStyleCode(parsed: PackageStyleId): import("#auklet/css/vite/moduleGraph/types").PackageStyleLoadResult | null;
20
- isDebugEnabled(parsed: PackageStyleId): Promise<boolean>;
21
20
  invalidatePackage(packageName: string): void;
21
+ invalidateFileLoadResults(file: string): string | null;
22
22
  invalidateFile(file: string): string | null;
23
23
  isSourceModuleFile(file: string): boolean;
24
+ private getFilePackageName;
24
25
  private isPackageFile;
25
26
  }
@@ -63,26 +63,34 @@ export class ModuleStyleGraph {
63
63
  peekPackageStyleCode(parsed) {
64
64
  return this.requestCache.peekLoadResult(parsed);
65
65
  }
66
- isDebugEnabled(parsed) {
67
- return this.requestCache.isDebugEnabled(parsed);
68
- }
69
66
  invalidatePackage(packageName) {
70
67
  this.requestCache.invalidatePackage(packageName);
71
68
  }
69
+ invalidateFileLoadResults(file) {
70
+ const packageName = this.getFilePackageName(file);
71
+ if (!packageName)
72
+ return null;
73
+ this.requestCache.invalidatePackageLoadResults(packageName);
74
+ return packageName;
75
+ }
72
76
  invalidateFile(file) {
77
+ const packageName = this.getFilePackageName(file);
78
+ if (!packageName)
79
+ return null;
80
+ this.invalidatePackage(packageName);
81
+ return packageName;
82
+ }
83
+ isSourceModuleFile(file) {
84
+ return SOURCE_MODULE_RE.test(normalizeFileKey(file));
85
+ }
86
+ getFilePackageName(file) {
73
87
  if (!this.isSourceGraphFile(file))
74
88
  return null;
75
89
  const normalizedFile = normalizeFileKey(file);
76
90
  const stylePackage = this.packageSource
77
91
  .getPackages()
78
92
  .find((item) => this.isPackageFile(item.packageRoot, normalizedFile));
79
- if (!stylePackage)
80
- return null;
81
- this.invalidatePackage(stylePackage.packageName);
82
- return stylePackage.packageName;
83
- }
84
- isSourceModuleFile(file) {
85
- return SOURCE_MODULE_RE.test(normalizeFileKey(file));
93
+ return stylePackage?.packageName ?? null;
86
94
  }
87
95
  isPackageFile(packageRoot, file) {
88
96
  const normalizedPackageRoot = normalizeFileKey(packageRoot);
@@ -28,6 +28,7 @@ export type ModuleStyleGraphRequestCacheOptions = {
28
28
  export declare class ModuleStyleGraphRequestCache {
29
29
  private readonly options;
30
30
  private readonly contexts;
31
+ private readonly settledContexts;
31
32
  private readonly loadResults;
32
33
  private readonly settledLoadResults;
33
34
  private readonly loadResultsByPackage;
@@ -80,8 +81,8 @@ export declare class ModuleStyleGraphRequestCache {
80
81
  } | null>;
81
82
  getLoadResult(parsed: PackageStyleId, create: () => Promise<LoadResultEntry>): Promise<PackageStyleLoadResult>;
82
83
  invalidatePackage(packageName: string): void;
84
+ invalidatePackageLoadResults(packageName: string): void;
83
85
  readPersistentLoadResult(parsed: PackageStyleId, context: PackageStyleContext): PackageStyleLoadResult | null;
84
- isDebugEnabled(parsed: PackageStyleId): Promise<boolean>;
85
86
  writePersistentLoadResult(parsed: PackageStyleId, context: PackageStyleContext, result: PackageStyleLoadResult): {
86
87
  cacheInputFiles: string[];
87
88
  code: string;
@@ -7,6 +7,7 @@ import { normalizeFileKey, toPosixPath } from '#auklet/utils';
7
7
  export class ModuleStyleGraphRequestCache {
8
8
  options;
9
9
  contexts = new Map();
10
+ settledContexts = new Map();
10
11
  loadResults = new Map();
11
12
  settledLoadResults = new Map();
12
13
  loadResultsByPackage = new Map();
@@ -35,6 +36,20 @@ export class ModuleStyleGraphRequestCache {
35
36
  return cachedContext;
36
37
  const context = this.createContext(parsed);
37
38
  this.contexts.set(parsed.packageName, context);
39
+ context.then((resolvedContext) => {
40
+ if (this.contexts.get(parsed.packageName) !== context)
41
+ return;
42
+ if (resolvedContext) {
43
+ this.settledContexts.set(parsed.packageName, resolvedContext);
44
+ }
45
+ else {
46
+ this.settledContexts.delete(parsed.packageName);
47
+ }
48
+ }, () => {
49
+ if (this.contexts.get(parsed.packageName) !== context)
50
+ return;
51
+ this.settledContexts.delete(parsed.packageName);
52
+ });
38
53
  return context;
39
54
  }
40
55
  getLoadResult(parsed, create) {
@@ -91,15 +106,19 @@ export class ModuleStyleGraphRequestCache {
91
106
  invalidatePackage(packageName) {
92
107
  this.bumpGraphVersion();
93
108
  this.contexts.delete(packageName);
109
+ this.settledContexts.delete(packageName);
110
+ this.invalidateLoadResults(packageName);
111
+ }
112
+ invalidatePackageLoadResults(packageName) {
113
+ this.bumpGraphVersion();
114
+ this.settledContexts
115
+ .get(packageName)
116
+ ?.packageContext.invalidateStyleContentCaches();
94
117
  this.invalidateLoadResults(packageName);
95
118
  }
96
119
  readPersistentLoadResult(parsed, context) {
97
120
  return this.persistentCache.read(this.createPersistentKey(parsed, context));
98
121
  }
99
- async isDebugEnabled(parsed) {
100
- const context = await this.getContext(parsed);
101
- return context?.normalizedConfig.debug ?? false;
102
- }
103
122
  writePersistentLoadResult(parsed, context, result) {
104
123
  const cacheInputFiles = this.getPersistentInputFiles(context, result);
105
124
  const cacheResult = {
@@ -150,7 +150,8 @@ export function aukletStylePlugin(options = {}) {
150
150
  reloadStyleGraph(file);
151
151
  }
152
152
  else if (graph.isStyleFile(file)) {
153
- if (hmr.hasTrackedStyleDependency(file)) {
153
+ const tracked = hmr.hasTrackedStyleDependency(file);
154
+ if (tracked) {
154
155
  await hmr.handleStyleHotUpdate({
155
156
  file,
156
157
  modules: [],
@@ -161,7 +162,7 @@ export function aukletStylePlugin(options = {}) {
161
162
  });
162
163
  }
163
164
  else {
164
- graph.invalidateFile(file);
165
+ graph.invalidateFileLoadResults(file);
165
166
  }
166
167
  }
167
168
  else if (graph.isSourceModuleFile(file)) {
@@ -1,6 +1,6 @@
1
1
  import { type AukletLogger } from '#auklet/logger';
2
2
  import type { ModuleStyleBuildConfig, ModuleStyleBuildContext } from '#auklet/types';
3
- type ModuleStyleWatcherLogger = Pick<AukletLogger, 'error'> & Partial<Pick<AukletLogger, 'info'>>;
3
+ type ModuleStyleWatcherLogger = Pick<AukletLogger, 'error'>;
4
4
  export declare class ModuleStyleWatcher {
5
5
  private readonly context;
6
6
  private readonly config;
@@ -11,14 +11,16 @@ export declare class ModuleStyleWatcher {
11
11
  private shouldRebuild;
12
12
  private watcher;
13
13
  private readonly lastErrorLogTimes;
14
+ private packageContext;
14
15
  constructor(context?: ModuleStyleBuildContext, config?: ModuleStyleBuildConfig, logger?: ModuleStyleWatcherLogger | null);
15
16
  watch(): Promise<void>;
16
17
  private rebuild;
17
- private logDebug;
18
18
  private refreshWatcher;
19
19
  private logError;
20
20
  private scheduleBuild;
21
21
  private shouldRebuildForFile;
22
+ private handleFileEvent;
23
+ private invalidateBuildCache;
22
24
  close(): Promise<void>;
23
25
  }
24
26
  export {};
@@ -18,6 +18,7 @@ export class ModuleStyleWatcher {
18
18
  shouldRebuild = false;
19
19
  watcher = null;
20
20
  lastErrorLogTimes = new Map();
21
+ packageContext = null;
21
22
  constructor(context = {}, config = moduleStyleBuildConfig, logger = null) {
22
23
  this.context = {
23
24
  packageRoot: process.cwd(),
@@ -39,12 +40,16 @@ export class ModuleStyleWatcher {
39
40
  return;
40
41
  }
41
42
  this.isBuilding = true;
42
- const startedAt = Date.now();
43
43
  try {
44
44
  try {
45
45
  const builder = new ModuleStyleBuilder(this.context, this.config);
46
- await builder.build();
47
- this.logDebug(`CSS build finished in ${Date.now() - startedAt}ms`);
46
+ this.packageContext ??= builder.createPackageContext({
47
+ aukletConfig: this.context.aukletConfig,
48
+ });
49
+ await builder.build({
50
+ aukletConfig: this.context.aukletConfig,
51
+ packageContext: this.packageContext,
52
+ });
48
53
  }
49
54
  catch (error) {
50
55
  this.logError('build', 'CSS build failed; waiting for changes.', error);
@@ -66,11 +71,6 @@ export class ModuleStyleWatcher {
66
71
  }
67
72
  }
68
73
  }
69
- logDebug(message) {
70
- if (this.context.aukletConfig?.debug !== true)
71
- return;
72
- this.logger.info?.(message);
73
- }
74
74
  async refreshWatcher() {
75
75
  if (this.closed)
76
76
  return;
@@ -89,13 +89,8 @@ export class ModuleStyleWatcher {
89
89
  interval: 300,
90
90
  usePolling: true,
91
91
  });
92
- this.watcher.on('all', (_event, file) => {
93
- if (this.closed)
94
- return;
95
- if (isString(file) && !this.shouldRebuildForFile(file)) {
96
- return;
97
- }
98
- this.scheduleBuild();
92
+ this.watcher.on('all', (event, file) => {
93
+ this.handleFileEvent(event, file);
99
94
  });
100
95
  this.watcher.on('error', (error) => {
101
96
  if (this.closed)
@@ -130,6 +125,34 @@ export class ModuleStyleWatcher {
130
125
  return true;
131
126
  return this.config.styleExtensions.includes(path.extname(file));
132
127
  }
128
+ handleFileEvent(event, file) {
129
+ if (this.closed || !isString(file))
130
+ return;
131
+ if (!this.shouldRebuildForFile(file))
132
+ return;
133
+ this.invalidateBuildCache(event, file);
134
+ this.scheduleBuild();
135
+ }
136
+ invalidateBuildCache(event, file) {
137
+ if (isAukletConfigFile(path.basename(file))) {
138
+ this.packageContext = null;
139
+ return;
140
+ }
141
+ if (event === 'add' ||
142
+ event === 'unlink' ||
143
+ event === 'addDir' ||
144
+ event === 'unlinkDir') {
145
+ this.packageContext = null;
146
+ return;
147
+ }
148
+ if (SOURCE_MODULE_RE.test(file)) {
149
+ this.packageContext?.invalidateModuleStyleImports();
150
+ return;
151
+ }
152
+ if (this.config.styleExtensions.includes(path.extname(file))) {
153
+ this.packageContext?.invalidateStyleContentCaches();
154
+ }
155
+ }
133
156
  async close() {
134
157
  this.closed = true;
135
158
  this.shouldRebuild = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auklet",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "type": "module",
5
5
  "author": "chentao.arthur",
6
6
  "description": "Build utilities for TypeScript packages and module CSS output.",