@typestyles/build-runner 0.0.0-unstable.de79e3a17eb1 → 0.0.0-unstable.df708abe489f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -164,7 +164,7 @@ Parses a file for typestyles registration calls. Returns `{ keys, prefixes }` fo
164
164
  import { extractNamespaces } from '@typestyles/build-runner';
165
165
 
166
166
  const { prefixes } = extractNamespaces(source);
167
- // styles.component('button', ...) → prefixes includes '.button-'
167
+ // recipe('button', ...) → prefixes includes '.button-'
168
168
  ```
169
169
 
170
170
  ### `reportDuplicateNamespaces(map, fileId, prefixes, reporter)`
package/dist/index.cjs CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  DEFAULT_EXTRACT_MODULE_CANDIDATES: () => DEFAULT_EXTRACT_MODULE_CANDIDATES,
24
+ DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES: () => DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES,
24
25
  TYPESTYLES_IMPORT_RE: () => TYPESTYLES_IMPORT_RE,
25
26
  VerifyTypestylesBuildError: () => VerifyTypestylesBuildError,
26
27
  buildManifestV2: () => buildManifestV2,
@@ -28,9 +29,11 @@ __export(index_exports, {
28
29
  createModuleLoader: () => createModuleLoader,
29
30
  discoverDefaultExtractModules: () => discoverDefaultExtractModules,
30
31
  discoverNextAppRoutes: () => discoverNextAppRoutes,
32
+ discoverRegisteredComponentsModule: () => discoverRegisteredComponentsModule,
31
33
  extractNamespaces: () => extractNamespaces,
32
34
  getRouteCss: () => getRouteCss,
33
35
  isManifestV2: () => isManifestV2,
36
+ moduleNeedsOverrideHmr: () => moduleNeedsOverrideHmr,
34
37
  normalizeRoutePath: () => normalizeRoutePath,
35
38
  pageRelPathToRoutePath: () => pageRelPathToRoutePath,
36
39
  readCssFile: () => readCssFile,
@@ -59,6 +62,12 @@ var DISCOVERY_EXTENSIONS = [".ts", ".tsx", ".js", ".mjs"];
59
62
  var DEFAULT_EXTRACT_MODULE_CANDIDATES = DEFAULT_EXTRACT_MODULE_BASES.map(
60
63
  (base) => `${base}.ts`
61
64
  );
65
+ var DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES = [
66
+ "src/themeable-refs",
67
+ "src/typestyles/themeable-refs",
68
+ "src/typestyles-registry",
69
+ "styles/themeable-refs"
70
+ ];
62
71
  function discoverDefaultExtractModules(root) {
63
72
  const absRoot = (0, import_node_path.resolve)(root);
64
73
  for (const base of DEFAULT_EXTRACT_MODULE_BASES) {
@@ -71,16 +80,88 @@ function discoverDefaultExtractModules(root) {
71
80
  }
72
81
  return [];
73
82
  }
83
+ function discoverRegisteredComponentsModule(root) {
84
+ const absRoot = (0, import_node_path.resolve)(root);
85
+ for (const base of DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES) {
86
+ for (const ext of DISCOVERY_EXTENSIONS) {
87
+ const rel = `${base}${ext}`;
88
+ if ((0, import_node_fs.existsSync)((0, import_node_path.resolve)(absRoot, rel))) {
89
+ return rel.replace(/\\/g, "/");
90
+ }
91
+ }
92
+ }
93
+ return void 0;
94
+ }
74
95
 
75
96
  // src/namespaces.ts
76
- var STYLES_COMPONENT_RE = /styles\.component\(\s*['"]([^'"]+)['"]/g;
77
- var STYLES_CLASS_RE = /styles\.class\(\s*['"]([^'"]+)['"]/g;
97
+ var STYLES_COMPONENT_RE = /(?:styles\.component|(?<![\w.])recipe)\(\s*['"]([^'"]+)['"]/g;
98
+ var STYLES_CLASS_RE = /(?:styles\.class|(?<![\w.])style)\(\s*['"]([^'"]+)['"]/g;
78
99
  var TOKENS_CREATE_RE = /tokens\.create\(\s*['"]([^'"]+)['"]/g;
79
- var CREATE_THEME_RE = /(?:tokens\.)?createTheme\(\s*['"]([^'"]+)['"]/g;
100
+ var CREATE_THEME_CALL_RE = /(?:tokens\.)?createTheme\s*\(/g;
80
101
  var KEYFRAMES_CREATE_RE = /keyframes\.create\(\s*['"]([^'"]+)['"]/g;
81
- var GLOBAL_STYLE_RE = /global\.style\(\s*['"]([^'"]+)['"]/g;
102
+ var GLOBAL_STYLE_RE = /global\.(?:rule|style)\(\s*['"]([^'"]+)['"]/g;
82
103
  var GLOBAL_FONT_FACE_RE = /global\.fontFace\(\s*['"]([^'"]+)['"]/g;
104
+ var CREATE_THEME_ARG_SCAN = 4e3;
105
+ function extractCreateThemeNames(code) {
106
+ const names = [];
107
+ for (const match of code.matchAll(CREATE_THEME_CALL_RE)) {
108
+ const start = (match.index ?? 0) + match[0].length;
109
+ const args = code.slice(start, start + CREATE_THEME_ARG_SCAN);
110
+ const positional = args.match(/^\s*['"]([^'"]+)['"]/);
111
+ if (positional) {
112
+ names.push(positional[1]);
113
+ continue;
114
+ }
115
+ if (!/^\s*\{/.test(args)) continue;
116
+ const named = args.match(/\bname\s*:\s*['"]([^'"]+)['"]/);
117
+ if (named) names.push(named[1]);
118
+ }
119
+ return names;
120
+ }
121
+ var OVERRIDE_HMR_EXPORT_NAMES = /* @__PURE__ */ new Set(["createDesignTheme", "overrideComponent"]);
83
122
  var TYPESTYLES_IMPORT_RE = /(?:from\s+|import\s+|require\s*\(\s*)['"]typestyles['"]/;
123
+ function stripCommentsForHmrScan(code) {
124
+ return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
125
+ }
126
+ function collectOverrideHmrCallTargets(code) {
127
+ const locals = new Set(OVERRIDE_HMR_EXPORT_NAMES);
128
+ const namespaces = /* @__PURE__ */ new Set();
129
+ for (const match of code.matchAll(/import\s*{([^}]+)}\s*from\s*['"][^'"]+['"]/g)) {
130
+ for (const rawPart of match[1].split(",")) {
131
+ const part = rawPart.trim();
132
+ if (!part || part.startsWith("type ")) continue;
133
+ const asMatch = part.match(/^(\w+)\s+as\s+(\w+)$/);
134
+ if (asMatch) {
135
+ if (OVERRIDE_HMR_EXPORT_NAMES.has(asMatch[1])) {
136
+ locals.add(asMatch[2]);
137
+ }
138
+ continue;
139
+ }
140
+ const name = part.match(/^(\w+)$/)?.[1];
141
+ if (name && OVERRIDE_HMR_EXPORT_NAMES.has(name)) {
142
+ locals.add(name);
143
+ }
144
+ }
145
+ }
146
+ for (const match of code.matchAll(/import\s*\*\s*as\s+(\w+)\s*from\s*['"][^'"]+['"]/g)) {
147
+ namespaces.add(match[1]);
148
+ }
149
+ return { locals, namespaces };
150
+ }
151
+ function moduleNeedsOverrideHmr(code) {
152
+ const scan = stripCommentsForHmrScan(code);
153
+ if (/\b(?:styles\.)?override\s*\(/.test(scan)) return true;
154
+ const { locals, namespaces } = collectOverrideHmrCallTargets(scan);
155
+ for (const name of locals) {
156
+ if (new RegExp(`\\b${name}\\s*\\(`).test(scan)) return true;
157
+ }
158
+ for (const ns of namespaces) {
159
+ if (new RegExp(`\\b${ns}\\.(?:createDesignTheme|overrideComponent)\\s*\\(`).test(scan)) {
160
+ return true;
161
+ }
162
+ }
163
+ return false;
164
+ }
84
165
  function extractNamespaces(code) {
85
166
  const keys = [];
86
167
  const prefixes = [];
@@ -93,8 +174,8 @@ function extractNamespaces(code) {
93
174
  for (const match of code.matchAll(TOKENS_CREATE_RE)) {
94
175
  keys.push(`tokens:${match[1]}`);
95
176
  }
96
- for (const match of code.matchAll(CREATE_THEME_RE)) {
97
- keys.push(`theme:${match[1]}`);
177
+ for (const themeName of extractCreateThemeNames(code)) {
178
+ keys.push(`theme:${themeName}`);
98
179
  }
99
180
  for (const match of code.matchAll(KEYFRAMES_CREATE_RE)) {
100
181
  keys.push(`keyframes:${match[1]}`);
@@ -123,10 +204,20 @@ function reportDuplicateNamespaces(moduleNamespaces, id, prefixes, reporter) {
123
204
 
124
205
  // src/resolve-extract.ts
125
206
  function resolveExtractModules(root, extract) {
207
+ let modules;
126
208
  if (extract?.modules !== void 0) {
127
- return extract.modules;
209
+ modules = [...extract.modules];
210
+ } else {
211
+ modules = discoverDefaultExtractModules(root);
212
+ }
213
+ let registeredModule = extract?.registeredComponentsModule;
214
+ if (!registeredModule && extract?.include === "allRegisteredComponents") {
215
+ registeredModule = discoverRegisteredComponentsModule(root);
216
+ }
217
+ if (registeredModule && !modules.includes(registeredModule)) {
218
+ modules.push(registeredModule);
128
219
  }
129
- return discoverDefaultExtractModules(root);
220
+ return modules;
130
221
  }
131
222
  function resolveExtractMode(explicitMode, resolvedModules) {
132
223
  return explicitMode ?? (resolvedModules.length > 0 ? "build" : "runtime");
@@ -424,10 +515,11 @@ async function traceTypestylesModules(root, entryFiles) {
424
515
  }
425
516
  return [...traced].sort();
426
517
  }
518
+ var moduleLoadNonce = 0;
427
519
  function createModuleLoader(root, modulePath) {
428
520
  const abs = (0, import_node_path4.resolve)(root, modulePath);
429
521
  const href = (0, import_node_url.pathToFileURL)(abs).href;
430
- return () => import(href);
522
+ return () => import(`${href}?typestyles-extract=${++moduleLoadNonce}`);
431
523
  }
432
524
 
433
525
  // src/route-css.ts
@@ -549,6 +641,16 @@ async function runTypestylesBuild({
549
641
  // calls silently dropped as "unused". Disable tree shaking here so every
550
642
  // registration in the extraction graph survives.
551
643
  treeShaking: false,
644
+ // `treeShaking: false` only stops esbuild from pruning declarations
645
+ // *within* an already-included module. It's a separate esbuild behavior
646
+ // by the treeShaking option — that drops a plain bare import entirely
647
+ // (`import './some-lib'` with no binding at all) when it resolves to a
648
+ // module/package marked "sideEffects": false, before that module is ever
649
+ // considered for inclusion. A real extraction entry is exactly this
650
+ // shape: several side-effect-only imports, any one of which may point at
651
+ // a (correctly) tree-shakeable component library. Ignore both kinds of
652
+ // annotation so every import in the extraction graph is included.
653
+ ignoreAnnotations: true,
552
654
  stdin: {
553
655
  contents: importLines,
554
656
  resolveDir: root,
@@ -593,6 +695,7 @@ ${result.stderr || result.stdout || "unknown error"}`
593
695
  // Annotate the CommonJS export names for ESM import in node:
594
696
  0 && (module.exports = {
595
697
  DEFAULT_EXTRACT_MODULE_CANDIDATES,
698
+ DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES,
596
699
  TYPESTYLES_IMPORT_RE,
597
700
  VerifyTypestylesBuildError,
598
701
  buildManifestV2,
@@ -600,9 +703,11 @@ ${result.stderr || result.stdout || "unknown error"}`
600
703
  createModuleLoader,
601
704
  discoverDefaultExtractModules,
602
705
  discoverNextAppRoutes,
706
+ discoverRegisteredComponentsModule,
603
707
  extractNamespaces,
604
708
  getRouteCss,
605
709
  isManifestV2,
710
+ moduleNeedsOverrideHmr,
606
711
  normalizeRoutePath,
607
712
  pageRelPathToRoutePath,
608
713
  readCssFile,
package/dist/index.d.cts CHANGED
@@ -3,13 +3,33 @@
3
3
  * Shared by bundler integrations and `@typestyles/next/build`.
4
4
  */
5
5
  declare const DEFAULT_EXTRACT_MODULE_CANDIDATES: readonly string[];
6
+ /**
7
+ * Side-effect modules that import every recipe and export `getRegisteredComponentRefs(styles)`.
8
+ * Used when `extract.include` is `"allRegisteredComponents"`.
9
+ */
10
+ declare const DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES: readonly ["src/themeable-refs", "src/typestyles/themeable-refs", "src/typestyles-registry", "styles/themeable-refs"];
6
11
  /**
7
12
  * Resolve the default extraction module when the user did not pass explicit `modules`.
8
13
  * Returns at most one path using `/` separators, relative to `root`.
9
14
  */
10
15
  declare function discoverDefaultExtractModules(root: string): string[];
16
+ /**
17
+ * Convention registry module for `extract.include: 'allRegisteredComponents'`.
18
+ * The file should import all recipe modules and
19
+ * export `getRegisteredComponentRefs(styles)` from your `createTypeStyles` entry.
20
+ */
21
+ declare function discoverRegisteredComponentsModule(root: string): string | undefined;
11
22
 
12
23
  declare const TYPESTYLES_IMPORT_RE: RegExp;
24
+ /**
25
+ * True when this module may register `styles.override` rules and needs Vite HMR
26
+ * dispose tracking — including Var UI sugar (`createDesignTheme` / `overrideComponent`)
27
+ * that never spells `styles.override` in source.
28
+ *
29
+ * Detects renamed imports (`createDesignTheme as cdt`) and namespace imports
30
+ * (`Core.createDesignTheme(`), not only the canonical identifier spelling.
31
+ */
32
+ declare function moduleNeedsOverrideHmr(code: string): boolean;
13
33
  /**
14
34
  * Extract namespace information from source code for invalidation and duplicate checks.
15
35
  */
@@ -39,6 +59,19 @@ interface TypestylesExtractOptions {
39
59
  * Output CSS filename. Defaults to `typestyles.css`.
40
60
  */
41
61
  fileName?: string;
62
+ /**
63
+ * Additional module that re-exports {@link getRegisteredComponentRefs} (or an
64
+ * equivalent object of every themeable recipe handle) so extract bundles retain
65
+ * full design-system CSS without a hand-maintained registry object.
66
+ */
67
+ registeredComponentsModule?: string;
68
+ /**
69
+ * When `"allRegisteredComponents"`, appends a convention registry module if present
70
+ * ({@link discoverRegisteredComponentsModule}) or {@link registeredComponentsModule}
71
+ * when set. That file must side-effect-import every recipe and reference
72
+ * `getRegisteredComponentRefs(styles)` — the extract entry alone is not enough.
73
+ */
74
+ include?: 'allRegisteredComponents';
42
75
  }
43
76
  /**
44
77
  * Resolve extraction modules from explicit config or convention entry discovery.
@@ -134,7 +167,7 @@ declare function discoverNextAppRoutes(root: string, appDir?: string): NextAppRo
134
167
  * Paths are relative to `root` with `/` separators.
135
168
  */
136
169
  declare function traceTypestylesModules(root: string, entryFiles: string[]): Promise<string[]>;
137
- /** Load a traced module for style extraction. */
170
+ /** Load a traced module for style extraction (cache-busted so re-runs re-register styles). */
138
171
  declare function createModuleLoader(root: string, modulePath: string): () => Promise<unknown>;
139
172
 
140
173
  interface CollectRouteCssOptions {
@@ -194,4 +227,4 @@ interface RunTypestylesBuildOptions {
194
227
  */
195
228
  declare function runTypestylesBuild({ root, modules, }: RunTypestylesBuildOptions): Promise<string>;
196
229
 
197
- export { type CollectRouteCssOptions, type CollectRouteCssResult, DEFAULT_EXTRACT_MODULE_CANDIDATES, type DuplicateNamespaceReporter, type GetRouteCssOptions, type NextAppRoute, type RunTypestylesBuildOptions, TYPESTYLES_IMPORT_RE, type TypestylesExtractManifest, type TypestylesExtractManifestV1, type TypestylesExtractManifestV2, type TypestylesExtractOptions, type TypestylesIntegrationMode, type TypestylesRouteCssEntry, VerifyTypestylesBuildError, type VerifyTypestylesBuildOptions, type VerifyTypestylesBuildResult, buildManifestV2, collectAndWriteRouteCss, createModuleLoader, discoverDefaultExtractModules, discoverNextAppRoutes, extractNamespaces, getRouteCss, isManifestV2, normalizeRoutePath, pageRelPathToRoutePath, readCssFile, readTypestylesManifest, reportDuplicateNamespaces, resolveExtractMode, resolveExtractModules, runTypestylesBuild, traceTypestylesModules, verifyTypestylesBuild };
230
+ export { type CollectRouteCssOptions, type CollectRouteCssResult, DEFAULT_EXTRACT_MODULE_CANDIDATES, DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES, type DuplicateNamespaceReporter, type GetRouteCssOptions, type NextAppRoute, type RunTypestylesBuildOptions, TYPESTYLES_IMPORT_RE, type TypestylesExtractManifest, type TypestylesExtractManifestV1, type TypestylesExtractManifestV2, type TypestylesExtractOptions, type TypestylesIntegrationMode, type TypestylesRouteCssEntry, VerifyTypestylesBuildError, type VerifyTypestylesBuildOptions, type VerifyTypestylesBuildResult, buildManifestV2, collectAndWriteRouteCss, createModuleLoader, discoverDefaultExtractModules, discoverNextAppRoutes, discoverRegisteredComponentsModule, extractNamespaces, getRouteCss, isManifestV2, moduleNeedsOverrideHmr, normalizeRoutePath, pageRelPathToRoutePath, readCssFile, readTypestylesManifest, reportDuplicateNamespaces, resolveExtractMode, resolveExtractModules, runTypestylesBuild, traceTypestylesModules, verifyTypestylesBuild };
package/dist/index.d.ts CHANGED
@@ -3,13 +3,33 @@
3
3
  * Shared by bundler integrations and `@typestyles/next/build`.
4
4
  */
5
5
  declare const DEFAULT_EXTRACT_MODULE_CANDIDATES: readonly string[];
6
+ /**
7
+ * Side-effect modules that import every recipe and export `getRegisteredComponentRefs(styles)`.
8
+ * Used when `extract.include` is `"allRegisteredComponents"`.
9
+ */
10
+ declare const DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES: readonly ["src/themeable-refs", "src/typestyles/themeable-refs", "src/typestyles-registry", "styles/themeable-refs"];
6
11
  /**
7
12
  * Resolve the default extraction module when the user did not pass explicit `modules`.
8
13
  * Returns at most one path using `/` separators, relative to `root`.
9
14
  */
10
15
  declare function discoverDefaultExtractModules(root: string): string[];
16
+ /**
17
+ * Convention registry module for `extract.include: 'allRegisteredComponents'`.
18
+ * The file should import all recipe modules and
19
+ * export `getRegisteredComponentRefs(styles)` from your `createTypeStyles` entry.
20
+ */
21
+ declare function discoverRegisteredComponentsModule(root: string): string | undefined;
11
22
 
12
23
  declare const TYPESTYLES_IMPORT_RE: RegExp;
24
+ /**
25
+ * True when this module may register `styles.override` rules and needs Vite HMR
26
+ * dispose tracking — including Var UI sugar (`createDesignTheme` / `overrideComponent`)
27
+ * that never spells `styles.override` in source.
28
+ *
29
+ * Detects renamed imports (`createDesignTheme as cdt`) and namespace imports
30
+ * (`Core.createDesignTheme(`), not only the canonical identifier spelling.
31
+ */
32
+ declare function moduleNeedsOverrideHmr(code: string): boolean;
13
33
  /**
14
34
  * Extract namespace information from source code for invalidation and duplicate checks.
15
35
  */
@@ -39,6 +59,19 @@ interface TypestylesExtractOptions {
39
59
  * Output CSS filename. Defaults to `typestyles.css`.
40
60
  */
41
61
  fileName?: string;
62
+ /**
63
+ * Additional module that re-exports {@link getRegisteredComponentRefs} (or an
64
+ * equivalent object of every themeable recipe handle) so extract bundles retain
65
+ * full design-system CSS without a hand-maintained registry object.
66
+ */
67
+ registeredComponentsModule?: string;
68
+ /**
69
+ * When `"allRegisteredComponents"`, appends a convention registry module if present
70
+ * ({@link discoverRegisteredComponentsModule}) or {@link registeredComponentsModule}
71
+ * when set. That file must side-effect-import every recipe and reference
72
+ * `getRegisteredComponentRefs(styles)` — the extract entry alone is not enough.
73
+ */
74
+ include?: 'allRegisteredComponents';
42
75
  }
43
76
  /**
44
77
  * Resolve extraction modules from explicit config or convention entry discovery.
@@ -134,7 +167,7 @@ declare function discoverNextAppRoutes(root: string, appDir?: string): NextAppRo
134
167
  * Paths are relative to `root` with `/` separators.
135
168
  */
136
169
  declare function traceTypestylesModules(root: string, entryFiles: string[]): Promise<string[]>;
137
- /** Load a traced module for style extraction. */
170
+ /** Load a traced module for style extraction (cache-busted so re-runs re-register styles). */
138
171
  declare function createModuleLoader(root: string, modulePath: string): () => Promise<unknown>;
139
172
 
140
173
  interface CollectRouteCssOptions {
@@ -194,4 +227,4 @@ interface RunTypestylesBuildOptions {
194
227
  */
195
228
  declare function runTypestylesBuild({ root, modules, }: RunTypestylesBuildOptions): Promise<string>;
196
229
 
197
- export { type CollectRouteCssOptions, type CollectRouteCssResult, DEFAULT_EXTRACT_MODULE_CANDIDATES, type DuplicateNamespaceReporter, type GetRouteCssOptions, type NextAppRoute, type RunTypestylesBuildOptions, TYPESTYLES_IMPORT_RE, type TypestylesExtractManifest, type TypestylesExtractManifestV1, type TypestylesExtractManifestV2, type TypestylesExtractOptions, type TypestylesIntegrationMode, type TypestylesRouteCssEntry, VerifyTypestylesBuildError, type VerifyTypestylesBuildOptions, type VerifyTypestylesBuildResult, buildManifestV2, collectAndWriteRouteCss, createModuleLoader, discoverDefaultExtractModules, discoverNextAppRoutes, extractNamespaces, getRouteCss, isManifestV2, normalizeRoutePath, pageRelPathToRoutePath, readCssFile, readTypestylesManifest, reportDuplicateNamespaces, resolveExtractMode, resolveExtractModules, runTypestylesBuild, traceTypestylesModules, verifyTypestylesBuild };
230
+ export { type CollectRouteCssOptions, type CollectRouteCssResult, DEFAULT_EXTRACT_MODULE_CANDIDATES, DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES, type DuplicateNamespaceReporter, type GetRouteCssOptions, type NextAppRoute, type RunTypestylesBuildOptions, TYPESTYLES_IMPORT_RE, type TypestylesExtractManifest, type TypestylesExtractManifestV1, type TypestylesExtractManifestV2, type TypestylesExtractOptions, type TypestylesIntegrationMode, type TypestylesRouteCssEntry, VerifyTypestylesBuildError, type VerifyTypestylesBuildOptions, type VerifyTypestylesBuildResult, buildManifestV2, collectAndWriteRouteCss, createModuleLoader, discoverDefaultExtractModules, discoverNextAppRoutes, discoverRegisteredComponentsModule, extractNamespaces, getRouteCss, isManifestV2, moduleNeedsOverrideHmr, normalizeRoutePath, pageRelPathToRoutePath, readCssFile, readTypestylesManifest, reportDuplicateNamespaces, resolveExtractMode, resolveExtractModules, runTypestylesBuild, traceTypestylesModules, verifyTypestylesBuild };
package/dist/index.js CHANGED
@@ -13,6 +13,12 @@ var DISCOVERY_EXTENSIONS = [".ts", ".tsx", ".js", ".mjs"];
13
13
  var DEFAULT_EXTRACT_MODULE_CANDIDATES = DEFAULT_EXTRACT_MODULE_BASES.map(
14
14
  (base) => `${base}.ts`
15
15
  );
16
+ var DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES = [
17
+ "src/themeable-refs",
18
+ "src/typestyles/themeable-refs",
19
+ "src/typestyles-registry",
20
+ "styles/themeable-refs"
21
+ ];
16
22
  function discoverDefaultExtractModules(root) {
17
23
  const absRoot = resolvePath(root);
18
24
  for (const base of DEFAULT_EXTRACT_MODULE_BASES) {
@@ -25,16 +31,88 @@ function discoverDefaultExtractModules(root) {
25
31
  }
26
32
  return [];
27
33
  }
34
+ function discoverRegisteredComponentsModule(root) {
35
+ const absRoot = resolvePath(root);
36
+ for (const base of DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES) {
37
+ for (const ext of DISCOVERY_EXTENSIONS) {
38
+ const rel = `${base}${ext}`;
39
+ if (existsSync(resolvePath(absRoot, rel))) {
40
+ return rel.replace(/\\/g, "/");
41
+ }
42
+ }
43
+ }
44
+ return void 0;
45
+ }
28
46
 
29
47
  // src/namespaces.ts
30
- var STYLES_COMPONENT_RE = /styles\.component\(\s*['"]([^'"]+)['"]/g;
31
- var STYLES_CLASS_RE = /styles\.class\(\s*['"]([^'"]+)['"]/g;
48
+ var STYLES_COMPONENT_RE = /(?:styles\.component|(?<![\w.])recipe)\(\s*['"]([^'"]+)['"]/g;
49
+ var STYLES_CLASS_RE = /(?:styles\.class|(?<![\w.])style)\(\s*['"]([^'"]+)['"]/g;
32
50
  var TOKENS_CREATE_RE = /tokens\.create\(\s*['"]([^'"]+)['"]/g;
33
- var CREATE_THEME_RE = /(?:tokens\.)?createTheme\(\s*['"]([^'"]+)['"]/g;
51
+ var CREATE_THEME_CALL_RE = /(?:tokens\.)?createTheme\s*\(/g;
34
52
  var KEYFRAMES_CREATE_RE = /keyframes\.create\(\s*['"]([^'"]+)['"]/g;
35
- var GLOBAL_STYLE_RE = /global\.style\(\s*['"]([^'"]+)['"]/g;
53
+ var GLOBAL_STYLE_RE = /global\.(?:rule|style)\(\s*['"]([^'"]+)['"]/g;
36
54
  var GLOBAL_FONT_FACE_RE = /global\.fontFace\(\s*['"]([^'"]+)['"]/g;
55
+ var CREATE_THEME_ARG_SCAN = 4e3;
56
+ function extractCreateThemeNames(code) {
57
+ const names = [];
58
+ for (const match of code.matchAll(CREATE_THEME_CALL_RE)) {
59
+ const start = (match.index ?? 0) + match[0].length;
60
+ const args = code.slice(start, start + CREATE_THEME_ARG_SCAN);
61
+ const positional = args.match(/^\s*['"]([^'"]+)['"]/);
62
+ if (positional) {
63
+ names.push(positional[1]);
64
+ continue;
65
+ }
66
+ if (!/^\s*\{/.test(args)) continue;
67
+ const named = args.match(/\bname\s*:\s*['"]([^'"]+)['"]/);
68
+ if (named) names.push(named[1]);
69
+ }
70
+ return names;
71
+ }
72
+ var OVERRIDE_HMR_EXPORT_NAMES = /* @__PURE__ */ new Set(["createDesignTheme", "overrideComponent"]);
37
73
  var TYPESTYLES_IMPORT_RE = /(?:from\s+|import\s+|require\s*\(\s*)['"]typestyles['"]/;
74
+ function stripCommentsForHmrScan(code) {
75
+ return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
76
+ }
77
+ function collectOverrideHmrCallTargets(code) {
78
+ const locals = new Set(OVERRIDE_HMR_EXPORT_NAMES);
79
+ const namespaces = /* @__PURE__ */ new Set();
80
+ for (const match of code.matchAll(/import\s*{([^}]+)}\s*from\s*['"][^'"]+['"]/g)) {
81
+ for (const rawPart of match[1].split(",")) {
82
+ const part = rawPart.trim();
83
+ if (!part || part.startsWith("type ")) continue;
84
+ const asMatch = part.match(/^(\w+)\s+as\s+(\w+)$/);
85
+ if (asMatch) {
86
+ if (OVERRIDE_HMR_EXPORT_NAMES.has(asMatch[1])) {
87
+ locals.add(asMatch[2]);
88
+ }
89
+ continue;
90
+ }
91
+ const name = part.match(/^(\w+)$/)?.[1];
92
+ if (name && OVERRIDE_HMR_EXPORT_NAMES.has(name)) {
93
+ locals.add(name);
94
+ }
95
+ }
96
+ }
97
+ for (const match of code.matchAll(/import\s*\*\s*as\s+(\w+)\s*from\s*['"][^'"]+['"]/g)) {
98
+ namespaces.add(match[1]);
99
+ }
100
+ return { locals, namespaces };
101
+ }
102
+ function moduleNeedsOverrideHmr(code) {
103
+ const scan = stripCommentsForHmrScan(code);
104
+ if (/\b(?:styles\.)?override\s*\(/.test(scan)) return true;
105
+ const { locals, namespaces } = collectOverrideHmrCallTargets(scan);
106
+ for (const name of locals) {
107
+ if (new RegExp(`\\b${name}\\s*\\(`).test(scan)) return true;
108
+ }
109
+ for (const ns of namespaces) {
110
+ if (new RegExp(`\\b${ns}\\.(?:createDesignTheme|overrideComponent)\\s*\\(`).test(scan)) {
111
+ return true;
112
+ }
113
+ }
114
+ return false;
115
+ }
38
116
  function extractNamespaces(code) {
39
117
  const keys = [];
40
118
  const prefixes = [];
@@ -47,8 +125,8 @@ function extractNamespaces(code) {
47
125
  for (const match of code.matchAll(TOKENS_CREATE_RE)) {
48
126
  keys.push(`tokens:${match[1]}`);
49
127
  }
50
- for (const match of code.matchAll(CREATE_THEME_RE)) {
51
- keys.push(`theme:${match[1]}`);
128
+ for (const themeName of extractCreateThemeNames(code)) {
129
+ keys.push(`theme:${themeName}`);
52
130
  }
53
131
  for (const match of code.matchAll(KEYFRAMES_CREATE_RE)) {
54
132
  keys.push(`keyframes:${match[1]}`);
@@ -77,10 +155,20 @@ function reportDuplicateNamespaces(moduleNamespaces, id, prefixes, reporter) {
77
155
 
78
156
  // src/resolve-extract.ts
79
157
  function resolveExtractModules(root, extract) {
158
+ let modules;
80
159
  if (extract?.modules !== void 0) {
81
- return extract.modules;
160
+ modules = [...extract.modules];
161
+ } else {
162
+ modules = discoverDefaultExtractModules(root);
163
+ }
164
+ let registeredModule = extract?.registeredComponentsModule;
165
+ if (!registeredModule && extract?.include === "allRegisteredComponents") {
166
+ registeredModule = discoverRegisteredComponentsModule(root);
167
+ }
168
+ if (registeredModule && !modules.includes(registeredModule)) {
169
+ modules.push(registeredModule);
82
170
  }
83
- return discoverDefaultExtractModules(root);
171
+ return modules;
84
172
  }
85
173
  function resolveExtractMode(explicitMode, resolvedModules) {
86
174
  return explicitMode ?? (resolvedModules.length > 0 ? "build" : "runtime");
@@ -378,10 +466,11 @@ async function traceTypestylesModules(root, entryFiles) {
378
466
  }
379
467
  return [...traced].sort();
380
468
  }
469
+ var moduleLoadNonce = 0;
381
470
  function createModuleLoader(root, modulePath) {
382
471
  const abs = resolve3(root, modulePath);
383
472
  const href = pathToFileURL(abs).href;
384
- return () => import(href);
473
+ return () => import(`${href}?typestyles-extract=${++moduleLoadNonce}`);
385
474
  }
386
475
 
387
476
  // src/route-css.ts
@@ -503,6 +592,16 @@ async function runTypestylesBuild({
503
592
  // calls silently dropped as "unused". Disable tree shaking here so every
504
593
  // registration in the extraction graph survives.
505
594
  treeShaking: false,
595
+ // `treeShaking: false` only stops esbuild from pruning declarations
596
+ // *within* an already-included module. It's a separate esbuild behavior
597
+ // by the treeShaking option — that drops a plain bare import entirely
598
+ // (`import './some-lib'` with no binding at all) when it resolves to a
599
+ // module/package marked "sideEffects": false, before that module is ever
600
+ // considered for inclusion. A real extraction entry is exactly this
601
+ // shape: several side-effect-only imports, any one of which may point at
602
+ // a (correctly) tree-shakeable component library. Ignore both kinds of
603
+ // annotation so every import in the extraction graph is included.
604
+ ignoreAnnotations: true,
506
605
  stdin: {
507
606
  contents: importLines,
508
607
  resolveDir: root,
@@ -546,6 +645,7 @@ ${result.stderr || result.stdout || "unknown error"}`
546
645
  }
547
646
  export {
548
647
  DEFAULT_EXTRACT_MODULE_CANDIDATES,
648
+ DEFAULT_REGISTERED_COMPONENTS_MODULE_BASES,
549
649
  TYPESTYLES_IMPORT_RE,
550
650
  VerifyTypestylesBuildError,
551
651
  buildManifestV2,
@@ -553,9 +653,11 @@ export {
553
653
  createModuleLoader,
554
654
  discoverDefaultExtractModules,
555
655
  discoverNextAppRoutes,
656
+ discoverRegisteredComponentsModule,
556
657
  extractNamespaces,
557
658
  getRouteCss,
558
659
  isManifestV2,
660
+ moduleNeedsOverrideHmr,
559
661
  normalizeRoutePath,
560
662
  pageRelPathToRoutePath,
561
663
  readCssFile,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typestyles/build-runner",
3
- "version": "0.0.0-unstable.de79e3a17eb1",
3
+ "version": "0.0.0-unstable.df708abe489f",
4
4
  "description": "Shared module execution utilities for typestyles build integrations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -29,7 +29,7 @@
29
29
  "eslint": "^9.39.2",
30
30
  "tsup": "^8.0.0",
31
31
  "typescript": "^5.4.0",
32
- "typestyles": "0.0.0-unstable.de79e3a17eb1",
32
+ "typestyles": "0.0.0-unstable.df708abe489f",
33
33
  "vitest": "^3.0.0"
34
34
  },
35
35
  "license": "Apache-2.0",