auklet 0.1.7 → 0.1.9

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.
@@ -9,11 +9,11 @@ export async function resolveWorkspaceScriptTargets(cwd, filters, envContext, op
9
9
  excludeRoot: true,
10
10
  env: envContext.normalizedValues,
11
11
  scope: options.scope ?? 'workspace',
12
- emptyTargetMessage: options.emptyTargetMessage ?? '[workspace] no workspace package found.',
13
12
  includePrivate: options.includePrivate,
14
13
  readPackageJson: readWorkspaceScriptPackageJson,
15
14
  getDependencies: getWorkspaceScriptDependencies,
16
15
  includeDependencies: options.includeDependencies,
16
+ emptyTargetMessage: options.emptyTargetMessage ?? '[workspace] no workspace package found.',
17
17
  createTarget: (item, packageJson) => ({
18
18
  packageRoot: item.path,
19
19
  packageName: item.name,
@@ -1,8 +1,8 @@
1
1
  import type { StylePackageContext } from '#auklet/css/core/stylePackageContext';
2
2
  export type ModuleStyleEntryPlan = {
3
3
  sourceDir: string;
4
- moduleStyleImports: Array<string>;
5
4
  ownStyleFiles: Array<string>;
5
+ moduleStyleImports: Array<string>;
6
6
  };
7
7
  export declare class StyleModuleEntryPlanner {
8
8
  private readonly packageContext;
@@ -23,4 +23,7 @@ export declare class StyleModuleEntryPlanner {
23
23
  private getSourceModuleDirs;
24
24
  private getOwnStyleDirs;
25
25
  private getOwnStyleFiles;
26
+ private rejectCrossModuleStyleImports;
27
+ private getStyleFileModuleDir;
28
+ private toRelativeSourceFile;
26
29
  }
@@ -11,6 +11,7 @@ export class StyleModuleEntryPlanner {
11
11
  this.styleFilesByDir = groupStyleFilesByDir(this.packageContext.sourceRoot, this.packageContext.styleFiles);
12
12
  this.importedStyleFiles =
13
13
  this.packageContext.styleProcessor.collectImportedStyleFiles(this.packageContext.styleFiles);
14
+ this.rejectCrossModuleStyleImports();
14
15
  }
15
16
  createEntries(moduleStyleImports) {
16
17
  return this.getSourceDirs(moduleStyleImports).map((sourceDir) => this.createEntry(sourceDir, moduleStyleImports));
@@ -47,4 +48,38 @@ export class StyleModuleEntryPlanner {
47
48
  getOwnStyleFiles(sourceDir) {
48
49
  return (this.styleFilesByDir.get(sourceDir) ?? []).filter((styleFile) => !this.importedStyleFiles.has(path.resolve(styleFile)));
49
50
  }
51
+ rejectCrossModuleStyleImports() {
52
+ if (!this.packageContext.normalizedConfig.modules)
53
+ return;
54
+ const styleFileKeys = new Set(this.packageContext.styleFiles.map((file) => path.resolve(file)));
55
+ const imports = this.packageContext.styleProcessor.collectImportedStyleFileReferences(this.packageContext.styleFiles);
56
+ for (const item of imports) {
57
+ if (!styleFileKeys.has(item.imported))
58
+ continue;
59
+ const importerModuleDir = this.getStyleFileModuleDir(item.importer);
60
+ const importedModuleDir = this.getStyleFileModuleDir(item.imported);
61
+ if (!importerModuleDir ||
62
+ !importedModuleDir ||
63
+ importerModuleDir === importedModuleDir) {
64
+ continue;
65
+ }
66
+ const importer = this.toRelativeSourceFile(item.importer);
67
+ const imported = this.toRelativeSourceFile(item.imported);
68
+ throw new Error(`[css] cross-component CSS import detected: ${importer} imports ${imported}. ` +
69
+ 'Use TSX imports to express component dependencies so auklet can ' +
70
+ 'generate module CSS entries correctly.');
71
+ }
72
+ }
73
+ getStyleFileModuleDir(file) {
74
+ const sourceRelative = toPosixPath(path.relative(this.packageContext.sourceRoot, file));
75
+ const parts = sourceRelative.split('/');
76
+ if (parts.length < 2)
77
+ return null;
78
+ if (parts.length === 2)
79
+ return getSourceModuleDir(sourceRelative);
80
+ return parts.slice(0, 2).join('/');
81
+ }
82
+ toRelativeSourceFile(file) {
83
+ return toPosixPath(path.relative(this.packageContext.sourceRoot, file));
84
+ }
50
85
  }
@@ -1,6 +1,10 @@
1
1
  import postcss, { type Root } from 'postcss';
2
2
  import type { ModuleStyleBuildConfig } from '#auklet/types';
3
3
  import type { WorkspaceStyleResolver } from '#auklet/css/core/workspaceStyleResolver';
4
+ export type StyleFileImportReference = {
5
+ importer: string;
6
+ imported: string;
7
+ };
4
8
  export declare class StyleProcessor {
5
9
  private readonly config;
6
10
  private readonly resolver;
@@ -11,6 +15,7 @@ export declare class StyleProcessor {
11
15
  appendStyleContent(target: Root, content: string, from: string): void;
12
16
  readStyleFile(stylePath: string, seen?: Set<string>): string;
13
17
  collectImportedStyleFiles(styleFiles: Array<string>): Set<string>;
18
+ collectImportedStyleFileReferences(styleFiles: Array<string>): StyleFileImportReference[];
14
19
  collectStyleImportSpecifiers(styleFiles: Array<string>): Set<string>;
15
20
  private parse;
16
21
  private parseImportSpecifier;
@@ -62,7 +62,10 @@ export class StyleProcessor {
62
62
  return root.toString();
63
63
  }
64
64
  collectImportedStyleFiles(styleFiles) {
65
- const imported = new Set();
65
+ return new Set(this.collectImportedStyleFileReferences(styleFiles).map((item) => item.imported));
66
+ }
67
+ collectImportedStyleFileReferences(styleFiles) {
68
+ const imports = [];
66
69
  for (const styleFile of styleFiles) {
67
70
  const css = fs.readFileSync(styleFile, 'utf8');
68
71
  const root = this.parse(css, styleFile);
@@ -72,10 +75,13 @@ export class StyleProcessor {
72
75
  !this.config.styleExtensions.includes(path.extname(specifier))) {
73
76
  return;
74
77
  }
75
- imported.add(path.resolve(path.dirname(styleFile), specifier));
78
+ imports.push({
79
+ importer: path.resolve(styleFile),
80
+ imported: path.resolve(path.dirname(styleFile), specifier),
81
+ });
76
82
  });
77
83
  }
78
- return imported;
84
+ return imports;
79
85
  }
80
86
  collectStyleImportSpecifiers(styleFiles) {
81
87
  const specifiers = new Set();
@@ -11,19 +11,6 @@ const toBrowserVirtualPath = (id) => {
11
11
  const getRelativeFile = (file) => {
12
12
  return path.relative(process.cwd(), file);
13
13
  };
14
- const invalidateVirtualModules = (server, graph) => {
15
- const modules = [];
16
- for (const packageName of graph.getPackageNames()) {
17
- for (const entry of ['style.css', 'external.css', 'module.css']) {
18
- const module = server.moduleGraph.getModuleById(`\0auklet-css:${packageName}/${entry}`);
19
- if (!module)
20
- continue;
21
- server.moduleGraph.invalidateModule(module);
22
- modules.push(module);
23
- }
24
- }
25
- return modules;
26
- };
27
14
  const addVirtualStyleDependency = (virtualIdsByDependency, file, virtualId) => {
28
15
  const normalizedFile = normalizeFileKey(file);
29
16
  const values = virtualIdsByDependency.get(normalizedFile) ?? new Set();
@@ -72,16 +59,16 @@ export class AukletStyleHmr {
72
59
  !graph.isStyleFile(context.file)) {
73
60
  return;
74
61
  }
62
+ this.suppressFullReload();
63
+ graph.invalidateFile(context.file);
75
64
  if (this.isDuplicateUpdate(context.file)) {
76
65
  return [];
77
66
  }
78
- this.suppressFullReload();
79
67
  const virtualIds = getDependencyVirtualIds(this.virtualIdsByDependency, context.file);
80
68
  const modules = getDependencyVirtualModules(this.virtualIdsByDependency, context.server, context.file);
81
69
  for (const module of modules) {
82
70
  context.server.moduleGraph.invalidateModule(module);
83
71
  }
84
- invalidateVirtualModules(context.server, graph);
85
72
  const updates = virtualIds.map((id) => {
86
73
  const browserPath = toBrowserVirtualPath(id);
87
74
  return {
@@ -3,6 +3,7 @@ export declare class ModuleStyleGraph {
3
3
  private readonly config;
4
4
  private readonly packageSource;
5
5
  private readonly styleCodeFactory;
6
+ private readonly requestCache;
6
7
  private readonly loadAukletConfig;
7
8
  constructor(options: ModuleStyleGraphOptions);
8
9
  parsePackageStyleId(id: string): {
@@ -18,5 +19,8 @@ export declare class ModuleStyleGraph {
18
19
  code: string;
19
20
  watchFiles: string[];
20
21
  }>;
21
- private createRequestCache;
22
+ invalidatePackage(packageName: string): void;
23
+ invalidateFile(file: string): string | null;
24
+ isSourceModuleFile(file: string): boolean;
25
+ private isPackageFile;
22
26
  }
@@ -1,6 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import { isAukletConfigFile } from '#auklet/config';
3
3
  import { loadAukletConfig } from '#auklet/configLoader';
4
+ import { SOURCE_MODULE_RE } from '#auklet/css/constants';
4
5
  import { moduleStyleBuildConfig } from '#auklet/css/config';
5
6
  import { parsePackageStyleId } from '#auklet/css/vite/moduleGraph/styleId';
6
7
  import { StyleCodeFactory } from '#auklet/css/vite/moduleGraph/styleCodeFactory';
@@ -13,6 +14,7 @@ export class ModuleStyleGraph {
13
14
  config;
14
15
  packageSource;
15
16
  styleCodeFactory;
17
+ requestCache;
16
18
  loadAukletConfig;
17
19
  constructor(options) {
18
20
  this.config = options.config ?? moduleStyleBuildConfig;
@@ -29,6 +31,11 @@ export class ModuleStyleGraph {
29
31
  styleExtensions: this.config.styleExtensions,
30
32
  loadAukletConfig: this.loadAukletConfig,
31
33
  });
34
+ this.requestCache = new ModuleStyleGraphRequestCache({
35
+ packageSource: this.packageSource,
36
+ config: this.config,
37
+ loadAukletConfig: this.loadAukletConfig,
38
+ });
32
39
  }
33
40
  parsePackageStyleId(id) {
34
41
  return parsePackageStyleId(id, this.getPackageNames());
@@ -49,13 +56,29 @@ export class ModuleStyleGraph {
49
56
  return this.packageSource.getWatchRoots();
50
57
  }
51
58
  createPackageStyleCode(parsed) {
52
- return this.styleCodeFactory.createPackageStyleCode(parsed, this.createRequestCache());
59
+ return this.styleCodeFactory.createPackageStyleCode(parsed, this.requestCache);
53
60
  }
54
- createRequestCache() {
55
- return new ModuleStyleGraphRequestCache({
56
- packageSource: this.packageSource,
57
- config: this.config,
58
- loadAukletConfig: this.loadAukletConfig,
59
- });
61
+ invalidatePackage(packageName) {
62
+ this.requestCache.invalidatePackage(packageName);
63
+ }
64
+ invalidateFile(file) {
65
+ if (!this.isSourceGraphFile(file))
66
+ return null;
67
+ const normalizedFile = normalizeFileKey(file);
68
+ const stylePackage = this.packageSource
69
+ .getPackages()
70
+ .find((item) => this.isPackageFile(item.packageRoot, normalizedFile));
71
+ if (!stylePackage)
72
+ return null;
73
+ this.invalidatePackage(stylePackage.packageName);
74
+ return stylePackage.packageName;
75
+ }
76
+ isSourceModuleFile(file) {
77
+ return SOURCE_MODULE_RE.test(normalizeFileKey(file));
78
+ }
79
+ isPackageFile(packageRoot, file) {
80
+ const normalizedPackageRoot = normalizeFileKey(packageRoot);
81
+ return (file === normalizedPackageRoot ||
82
+ file.startsWith(`${normalizedPackageRoot}/`));
60
83
  }
61
84
  }
@@ -62,5 +62,6 @@ export declare class ModuleStyleGraphRequestCache {
62
62
  sourceRoot: string;
63
63
  styleProcessor: StyleProcessor;
64
64
  } | null>;
65
+ invalidatePackage(packageName: string): void;
65
66
  private createContext;
66
67
  }
@@ -24,6 +24,9 @@ export class ModuleStyleGraphRequestCache {
24
24
  this.contexts.set(parsed.packageName, context);
25
25
  return context;
26
26
  }
27
+ invalidatePackage(packageName) {
28
+ this.contexts.delete(packageName);
29
+ }
27
30
  async createContext(parsed) {
28
31
  const stylePackage = this.options.packageSource
29
32
  .getPackages()
@@ -106,6 +106,7 @@ export function aukletStylePlugin(options = {}) {
106
106
  const invalidateStyleGraph = (file) => {
107
107
  if (!graph.isSourceGraphFile(file))
108
108
  return false;
109
+ graph.invalidateFile(file);
109
110
  invalidateVirtualModules(server, graph);
110
111
  return true;
111
112
  };
@@ -116,7 +117,7 @@ export function aukletStylePlugin(options = {}) {
116
117
  };
117
118
  const handleSourceAddOrUnlink = (file) => {
118
119
  if (graph.isStyleFile(file)) {
119
- invalidateStyleGraph(file);
120
+ reloadStyleGraph(file);
120
121
  return;
121
122
  }
122
123
  reloadStyleGraph(file);
@@ -126,6 +127,10 @@ export function aukletStylePlugin(options = {}) {
126
127
  server.watcher.on('change', (file) => {
127
128
  if (graph.isStyleConfigFile(file)) {
128
129
  reloadStyleGraph(file);
130
+ return;
131
+ }
132
+ if (graph.isSourceModuleFile(file)) {
133
+ reloadStyleGraph(file);
129
134
  }
130
135
  });
131
136
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "auklet",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "author": "chentao.arthur",
6
6
  "description": "Build utilities for TypeScript packages and module CSS output.",