@typestyles/build-runner 0.0.0-unstable.439960c19a5a → 0.0.0-unstable.4b1f40dade83

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/dist/index.js CHANGED
@@ -1,7 +1,521 @@
1
- // src/index.ts
2
- import { build as esbuildBuild } from "esbuild";
3
- import { existsSync, unlinkSync, writeFileSync } from "fs";
1
+ // src/discover.ts
2
+ import { existsSync } from "fs";
3
+ import { resolve as resolvePath } from "path";
4
+ var DEFAULT_EXTRACT_MODULE_BASES = [
5
+ "src/typestyles-entry",
6
+ "src/typestyles",
7
+ "src/styles/index",
8
+ "src/styles",
9
+ "styles/typestyles-entry",
10
+ "styles/typestyles"
11
+ ];
12
+ var DISCOVERY_EXTENSIONS = [".ts", ".tsx", ".js", ".mjs"];
13
+ var DEFAULT_EXTRACT_MODULE_CANDIDATES = DEFAULT_EXTRACT_MODULE_BASES.map(
14
+ (base) => `${base}.ts`
15
+ );
16
+ function discoverDefaultExtractModules(root) {
17
+ const absRoot = resolvePath(root);
18
+ for (const base of DEFAULT_EXTRACT_MODULE_BASES) {
19
+ for (const ext of DISCOVERY_EXTENSIONS) {
20
+ const rel = `${base}${ext}`;
21
+ if (existsSync(resolvePath(absRoot, rel))) {
22
+ return [rel.replace(/\\/g, "/")];
23
+ }
24
+ }
25
+ }
26
+ return [];
27
+ }
28
+
29
+ // src/namespaces.ts
30
+ var STYLES_COMPONENT_RE = /styles\.component\(\s*['"]([^'"]+)['"]/g;
31
+ var STYLES_CLASS_RE = /styles\.class\(\s*['"]([^'"]+)['"]/g;
32
+ var TOKENS_CREATE_RE = /tokens\.create\(\s*['"]([^'"]+)['"]/g;
33
+ var CREATE_THEME_RE = /(?:tokens\.)?createTheme\(\s*['"]([^'"]+)['"]/g;
34
+ var KEYFRAMES_CREATE_RE = /keyframes\.create\(\s*['"]([^'"]+)['"]/g;
35
+ var GLOBAL_STYLE_RE = /global\.style\(\s*['"]([^'"]+)['"]/g;
36
+ var GLOBAL_FONT_FACE_RE = /global\.fontFace\(\s*['"]([^'"]+)['"]/g;
37
+ var OVERRIDE_HMR_EXPORT_NAMES = /* @__PURE__ */ new Set(["createDesignTheme", "overrideComponent"]);
38
+ var TYPESTYLES_IMPORT_RE = /(?:from\s+|import\s+|require\s*\(\s*)['"]typestyles['"]/;
39
+ function stripCommentsForHmrScan(code) {
40
+ return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:])\/\/.*$/gm, "$1");
41
+ }
42
+ function collectOverrideHmrCallTargets(code) {
43
+ const locals = new Set(OVERRIDE_HMR_EXPORT_NAMES);
44
+ const namespaces = /* @__PURE__ */ new Set();
45
+ for (const match of code.matchAll(/import\s*{([^}]+)}\s*from\s*['"][^'"]+['"]/g)) {
46
+ for (const rawPart of match[1].split(",")) {
47
+ const part = rawPart.trim();
48
+ if (!part || part.startsWith("type ")) continue;
49
+ const asMatch = part.match(/^(\w+)\s+as\s+(\w+)$/);
50
+ if (asMatch) {
51
+ if (OVERRIDE_HMR_EXPORT_NAMES.has(asMatch[1])) {
52
+ locals.add(asMatch[2]);
53
+ }
54
+ continue;
55
+ }
56
+ const name = part.match(/^(\w+)$/)?.[1];
57
+ if (name && OVERRIDE_HMR_EXPORT_NAMES.has(name)) {
58
+ locals.add(name);
59
+ }
60
+ }
61
+ }
62
+ for (const match of code.matchAll(/import\s*\*\s*as\s+(\w+)\s*from\s*['"][^'"]+['"]/g)) {
63
+ namespaces.add(match[1]);
64
+ }
65
+ return { locals, namespaces };
66
+ }
67
+ function moduleNeedsOverrideHmr(code) {
68
+ const scan = stripCommentsForHmrScan(code);
69
+ if (/\bstyles\.override\s*\(/.test(scan)) return true;
70
+ const { locals, namespaces } = collectOverrideHmrCallTargets(scan);
71
+ for (const name of locals) {
72
+ if (new RegExp(`\\b${name}\\s*\\(`).test(scan)) return true;
73
+ }
74
+ for (const ns of namespaces) {
75
+ if (new RegExp(`\\b${ns}\\.(?:createDesignTheme|overrideComponent)\\s*\\(`).test(scan)) {
76
+ return true;
77
+ }
78
+ }
79
+ return false;
80
+ }
81
+ function extractNamespaces(code) {
82
+ const keys = [];
83
+ const prefixes = [];
84
+ for (const match of code.matchAll(STYLES_COMPONENT_RE)) {
85
+ prefixes.push(`.${match[1]}-`);
86
+ }
87
+ for (const match of code.matchAll(STYLES_CLASS_RE)) {
88
+ prefixes.push(`.${match[1]}-`);
89
+ }
90
+ for (const match of code.matchAll(TOKENS_CREATE_RE)) {
91
+ keys.push(`tokens:${match[1]}`);
92
+ }
93
+ for (const match of code.matchAll(CREATE_THEME_RE)) {
94
+ keys.push(`theme:${match[1]}`);
95
+ }
96
+ for (const match of code.matchAll(KEYFRAMES_CREATE_RE)) {
97
+ keys.push(`keyframes:${match[1]}`);
98
+ }
99
+ for (const match of code.matchAll(GLOBAL_STYLE_RE)) {
100
+ prefixes.push(match[1]);
101
+ }
102
+ for (const match of code.matchAll(GLOBAL_FONT_FACE_RE)) {
103
+ prefixes.push(`font-face:${match[1]}`);
104
+ }
105
+ return { keys, prefixes };
106
+ }
107
+ function reportDuplicateNamespaces(moduleNamespaces, id, prefixes, reporter) {
108
+ for (const [otherId, other] of moduleNamespaces) {
109
+ if (otherId === id) continue;
110
+ for (const prefix of prefixes) {
111
+ if (other.prefixes.includes(prefix)) {
112
+ const ns = prefix.slice(1, -1);
113
+ reporter.error(
114
+ `[typestyles] Style namespace "${ns}" is also used in ${otherId}. Duplicate namespaces cause class name collisions. Use a distinct name or isolate with createStyles({ scopeId: fileScopeId(import.meta) }).`
115
+ );
116
+ }
117
+ }
118
+ }
119
+ }
120
+
121
+ // src/resolve-extract.ts
122
+ function resolveExtractModules(root, extract) {
123
+ if (extract?.modules !== void 0) {
124
+ return extract.modules;
125
+ }
126
+ return discoverDefaultExtractModules(root);
127
+ }
128
+ function resolveExtractMode(explicitMode, resolvedModules) {
129
+ return explicitMode ?? (resolvedModules.length > 0 ? "build" : "runtime");
130
+ }
131
+
132
+ // src/verify.ts
133
+ import { existsSync as existsSync2, readFileSync } from "fs";
4
134
  import { resolve } from "path";
135
+
136
+ // src/manifest.ts
137
+ function isManifestV2(manifest) {
138
+ return manifest.version === 2;
139
+ }
140
+ function normalizeRoutePath(routePath) {
141
+ if (!routePath || routePath === "/") return "/";
142
+ const trimmed = routePath.replace(/\/+$/, "");
143
+ return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
144
+ }
145
+
146
+ // src/verify.ts
147
+ var VerifyTypestylesBuildError = class extends Error {
148
+ constructor(message, code) {
149
+ super(`[typestyles:verify] ${message}`);
150
+ this.name = "VerifyTypestylesBuildError";
151
+ this.code = code;
152
+ }
153
+ };
154
+ function fail(message, code) {
155
+ throw new VerifyTypestylesBuildError(message, code);
156
+ }
157
+ function readManifest(path) {
158
+ let parsed;
159
+ try {
160
+ parsed = JSON.parse(readFileSync(path, "utf8"));
161
+ } catch {
162
+ fail(`Invalid JSON in ${path}.`, "manifest-invalid-json");
163
+ }
164
+ if (typeof parsed !== "object" || parsed === null || !("version" in parsed) || !("css" in parsed)) {
165
+ fail(`Manifest at ${path} is missing required fields.`, "manifest-invalid-shape");
166
+ }
167
+ const version = parsed.version;
168
+ if (version !== 1 && version !== 2) {
169
+ fail(`Unsupported manifest version ${String(version)}.`, "manifest-version-unsupported");
170
+ }
171
+ const manifest = parsed;
172
+ if (isManifestV2(manifest) && typeof manifest.routes !== "object") {
173
+ fail(`Manifest v2 at ${path} is missing routes.`, "manifest-invalid-shape");
174
+ }
175
+ return manifest;
176
+ }
177
+ function verifyTypestylesBuild(options) {
178
+ const {
179
+ root,
180
+ cssFile,
181
+ manifestFile,
182
+ manifestCssPath,
183
+ manifestVersion = 1,
184
+ minBytes,
185
+ requiredCssSubstrings = [],
186
+ minRouteEntries
187
+ } = options;
188
+ const cssPath = resolve(root, cssFile);
189
+ if (!existsSync2(cssPath)) {
190
+ fail(`Missing ${cssPath} \u2014 run your TypeStyles build step first.`, "css-missing");
191
+ }
192
+ const css = readFileSync(cssPath, "utf8");
193
+ const cssBytes = Buffer.byteLength(css, "utf8");
194
+ const min = minBytes ?? 1;
195
+ if (cssBytes < min) {
196
+ fail(
197
+ `CSS file unexpectedly small (${cssBytes} bytes, expected at least ${min}).`,
198
+ "css-too-small"
199
+ );
200
+ }
201
+ for (const substring of requiredCssSubstrings) {
202
+ if (!css.includes(substring)) {
203
+ fail(`Expected CSS to contain ${JSON.stringify(substring)}.`, "css-missing-substring");
204
+ }
205
+ }
206
+ const manifestRel = manifestFile === false ? void 0 : manifestFile;
207
+ if (!manifestRel) {
208
+ return { cssPath, cssBytes };
209
+ }
210
+ const manifestPath = resolve(root, manifestRel);
211
+ if (!existsSync2(manifestPath)) {
212
+ fail(`Missing ${manifestPath}.`, "manifest-missing");
213
+ }
214
+ const manifest = readManifest(manifestPath);
215
+ if (manifest.version !== manifestVersion) {
216
+ fail(
217
+ `Expected manifest version ${manifestVersion}, got ${manifest.version}.`,
218
+ "manifest-version-mismatch"
219
+ );
220
+ }
221
+ const expectedCssPath = manifestCssPath ?? cssFile;
222
+ if (manifest.css !== expectedCssPath) {
223
+ fail(
224
+ `Expected manifest.css ${JSON.stringify(expectedCssPath)}, got ${JSON.stringify(manifest.css)}.`,
225
+ "manifest-css-mismatch"
226
+ );
227
+ }
228
+ if (isManifestV2(manifest)) {
229
+ const routeCount = Object.keys(manifest.routes).length;
230
+ if (minRouteEntries !== void 0 && routeCount < minRouteEntries) {
231
+ fail(
232
+ `Expected at least ${minRouteEntries} route CSS entries, got ${routeCount}.`,
233
+ "manifest-routes-too-few"
234
+ );
235
+ }
236
+ for (const [routePath, entry] of Object.entries(manifest.routes)) {
237
+ const routeCssPath = resolve(root, entry.css);
238
+ if (!existsSync2(routeCssPath)) {
239
+ fail(`Missing route CSS for ${routePath} at ${routeCssPath}.`, "route-css-missing");
240
+ }
241
+ if (Buffer.byteLength(readFileSync(routeCssPath, "utf8"), "utf8") < 1) {
242
+ fail(`Route CSS for ${routePath} is empty.`, "route-css-empty");
243
+ }
244
+ }
245
+ }
246
+ return {
247
+ cssPath,
248
+ cssBytes,
249
+ manifestPath,
250
+ manifestVersion: manifest.version
251
+ };
252
+ }
253
+
254
+ // src/next-routes.ts
255
+ import { existsSync as existsSync3, readdirSync, statSync } from "fs";
256
+ import { dirname, join, relative, resolve as resolve2 } from "path";
257
+ var PAGE_BASENAMES = /* @__PURE__ */ new Set(["page.tsx", "page.ts", "page.jsx", "page.js"]);
258
+ var LAYOUT_BASENAMES = /* @__PURE__ */ new Set(["layout.tsx", "layout.ts", "layout.jsx", "layout.js"]);
259
+ function normalizeRelPath(root, absPath) {
260
+ return relative(root, absPath).replace(/\\/g, "/");
261
+ }
262
+ function isRouteGroupSegment(segment) {
263
+ return segment.startsWith("(") && segment.endsWith(")");
264
+ }
265
+ function pageRelPathToRoutePath(pageRelPath) {
266
+ const dir = dirname(pageRelPath).replace(/\\/g, "/");
267
+ if (dir === "." || dir === "") return "/";
268
+ const segments = dir.split("/").filter((segment) => segment.length > 0 && !isRouteGroupSegment(segment));
269
+ return segments.length === 0 ? "/" : `/${segments.join("/")}`;
270
+ }
271
+ function walkForPages(appAbs, currentRel, pages) {
272
+ const currentAbs = join(appAbs, currentRel);
273
+ let entries;
274
+ try {
275
+ entries = readdirSync(currentAbs);
276
+ } catch {
277
+ return;
278
+ }
279
+ for (const entry of entries) {
280
+ const entryRel = currentRel ? join(currentRel, entry) : entry;
281
+ const entryAbs = join(appAbs, entryRel);
282
+ let stat;
283
+ try {
284
+ stat = statSync(entryAbs);
285
+ } catch {
286
+ continue;
287
+ }
288
+ if (stat.isDirectory()) {
289
+ walkForPages(appAbs, entryRel, pages);
290
+ continue;
291
+ }
292
+ if (PAGE_BASENAMES.has(entry)) {
293
+ pages.push(entryRel.replace(/\\/g, "/"));
294
+ }
295
+ }
296
+ }
297
+ function collectLayoutChain(appAbs, pageRelPath) {
298
+ const layouts = [];
299
+ const segments = dirname(pageRelPath).replace(/\\/g, "/").split("/");
300
+ const chainDirs = [""];
301
+ for (const segment of segments) {
302
+ if (!segment || segment === ".") continue;
303
+ const parent = chainDirs[chainDirs.length - 1];
304
+ chainDirs.push(parent ? `${parent}/${segment}` : segment);
305
+ }
306
+ for (const dir of chainDirs) {
307
+ const dirAbs = dir ? join(appAbs, dir) : appAbs;
308
+ for (const layoutName of LAYOUT_BASENAMES) {
309
+ const layoutAbs = join(dirAbs, layoutName);
310
+ if (existsSync3(layoutAbs)) {
311
+ layouts.push(join(dir, layoutName).replace(/\\/g, "/"));
312
+ break;
313
+ }
314
+ }
315
+ }
316
+ return layouts;
317
+ }
318
+ function discoverNextAppRoutes(root, appDir = "app") {
319
+ const appAbs = resolve2(root, appDir);
320
+ if (!existsSync3(appAbs)) return [];
321
+ const pageRelPaths = [];
322
+ walkForPages(appAbs, "", pageRelPaths);
323
+ return pageRelPaths.map((pageRelPath) => {
324
+ const pageFile = normalizeRelPath(root, join(appAbs, pageRelPath));
325
+ const layoutFiles = collectLayoutChain(appAbs, pageRelPath).map(
326
+ (layoutRel) => normalizeRelPath(root, join(appAbs, layoutRel))
327
+ );
328
+ return {
329
+ routePath: pageRelPathToRoutePath(pageRelPath),
330
+ pageFile,
331
+ layoutFiles
332
+ };
333
+ }).sort((a, b) => a.routePath.localeCompare(b.routePath));
334
+ }
335
+
336
+ // src/trace-imports.ts
337
+ import { build as esbuildBuild } from "esbuild";
338
+ import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
339
+ import { join as join2, resolve as resolve3 } from "path";
340
+ import { pathToFileURL } from "url";
341
+ var EXTERNAL_PREFIXES = [
342
+ "react",
343
+ "react-dom",
344
+ "react/",
345
+ "react-dom/",
346
+ "next",
347
+ "next/",
348
+ "server-only",
349
+ "client-only",
350
+ "typestyles",
351
+ "typestyles/"
352
+ ];
353
+ function isExternalBareImport(specifier) {
354
+ if (specifier.startsWith("node:")) return true;
355
+ return EXTERNAL_PREFIXES.some(
356
+ (prefix) => specifier === prefix || specifier.startsWith(`${prefix}/`)
357
+ );
358
+ }
359
+ function isExternalAssetPath(path, importer, namespace) {
360
+ if (path.endsWith(".css")) return true;
361
+ const fromCss = namespace === "css" || importer.endsWith(".css");
362
+ if (fromCss && path.startsWith("/") && !path.startsWith("//")) {
363
+ return true;
364
+ }
365
+ return false;
366
+ }
367
+ function fileImportsTypestyles(absPath) {
368
+ if (!existsSync4(absPath)) return false;
369
+ try {
370
+ return TYPESTYLES_IMPORT_RE.test(readFileSync2(absPath, "utf8"));
371
+ } catch {
372
+ return false;
373
+ }
374
+ }
375
+ async function traceTypestylesModules(root, entryFiles) {
376
+ const absEntries = entryFiles.map((file) => resolve3(root, file));
377
+ const missing = absEntries.filter((file) => !existsSync4(file));
378
+ if (missing.length > 0) {
379
+ throw new Error(
380
+ `[typestyles] Cannot trace imports; missing entry file(s): ${missing.join(", ")}`
381
+ );
382
+ }
383
+ const tsconfigPath = join2(root, "tsconfig.json");
384
+ const result = await esbuildBuild({
385
+ entryPoints: absEntries,
386
+ bundle: true,
387
+ write: false,
388
+ outdir: root,
389
+ metafile: true,
390
+ platform: "neutral",
391
+ format: "esm",
392
+ logLevel: "silent",
393
+ absWorkingDir: root,
394
+ ...existsSync4(tsconfigPath) ? { tsconfig: tsconfigPath } : {},
395
+ plugins: [
396
+ {
397
+ name: "typestyles-trace-imports",
398
+ setup(build) {
399
+ build.onResolve({ filter: /.*/ }, (args) => {
400
+ if (isExternalAssetPath(args.path, args.importer, args.namespace)) {
401
+ return { path: args.path, external: true };
402
+ }
403
+ if (args.path.startsWith(".")) {
404
+ return null;
405
+ }
406
+ if (isExternalBareImport(args.path)) {
407
+ return { path: args.path, external: true };
408
+ }
409
+ return null;
410
+ });
411
+ }
412
+ }
413
+ ]
414
+ });
415
+ const inputs = result.metafile?.inputs ?? {};
416
+ const traced = /* @__PURE__ */ new Set();
417
+ for (const inputPath of Object.keys(inputs)) {
418
+ const absPath = resolve3(root, inputPath);
419
+ if (!fileImportsTypestyles(absPath)) continue;
420
+ traced.add(inputPath.replace(/\\/g, "/"));
421
+ }
422
+ return [...traced].sort();
423
+ }
424
+ function createModuleLoader(root, modulePath) {
425
+ const abs = resolve3(root, modulePath);
426
+ const href = pathToFileURL(abs).href;
427
+ return () => import(href);
428
+ }
429
+
430
+ // src/route-css.ts
431
+ import { mkdir, writeFile } from "fs/promises";
432
+ import { dirname as dirname2, resolve as resolve4 } from "path";
433
+ function routePathToCssFile(routePath) {
434
+ if (routePath === "/") return "index.css";
435
+ const slug = routePath.slice(1).replace(/^\[|\]$/g, "").replace(/[^\w.-]+/g, "-");
436
+ return `${slug || "route"}.css`;
437
+ }
438
+ function uniqueModules(...groups) {
439
+ return [...new Set(groups.flat())].sort();
440
+ }
441
+ async function collectAndWriteRouteCss(options) {
442
+ const {
443
+ root,
444
+ sharedModules,
445
+ appDir = "app",
446
+ routeCssOutDir = "app/_typestyles/routes",
447
+ collectCss
448
+ } = options;
449
+ const routes = discoverNextAppRoutes(root, appDir);
450
+ if (routes.length === 0) {
451
+ return { routes: {} };
452
+ }
453
+ const manifestRoutes = {};
454
+ for (const route of routes) {
455
+ const entryFiles = uniqueModules(route.layoutFiles, [route.pageFile]);
456
+ const routeModules = await traceTypestylesModules(root, entryFiles);
457
+ const modules = uniqueModules(sharedModules, routeModules);
458
+ const loaders = modules.map((mod) => createModuleLoader(root, mod));
459
+ const css = await collectCss(loaders);
460
+ const cssFileName = routePathToCssFile(route.routePath);
461
+ const cssRel = `${routeCssOutDir.replace(/\\/g, "/")}/${cssFileName}`;
462
+ const cssAbs = resolve4(root, cssRel);
463
+ await mkdir(dirname2(cssAbs), { recursive: true });
464
+ await writeFile(cssAbs, css, "utf8");
465
+ manifestRoutes[route.routePath] = { css: cssRel };
466
+ }
467
+ return { routes: manifestRoutes };
468
+ }
469
+ function buildManifestV2(cssOutFile, routeEntries) {
470
+ return {
471
+ version: 2,
472
+ css: cssOutFile,
473
+ routes: routeEntries
474
+ };
475
+ }
476
+
477
+ // src/route-css-read.ts
478
+ import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
479
+ import { resolve as resolve5 } from "path";
480
+ function readTypestylesManifest(root, manifestFile = "app/typestyles.manifest.json") {
481
+ const manifestPath = resolve5(root, manifestFile);
482
+ if (!existsSync5(manifestPath)) {
483
+ throw new Error(`[typestyles] Missing manifest at ${manifestPath}.`);
484
+ }
485
+ let parsed;
486
+ try {
487
+ parsed = JSON.parse(readFileSync3(manifestPath, "utf8"));
488
+ } catch {
489
+ throw new Error(`[typestyles] Invalid JSON in ${manifestPath}.`);
490
+ }
491
+ if (typeof parsed !== "object" || parsed === null || !("version" in parsed) || !("css" in parsed)) {
492
+ throw new Error(`[typestyles] Manifest at ${manifestPath} is missing required fields.`);
493
+ }
494
+ return parsed;
495
+ }
496
+ function readCssFile(root, cssRelPath) {
497
+ const cssPath = resolve5(root, cssRelPath);
498
+ if (!existsSync5(cssPath)) {
499
+ throw new Error(`[typestyles] Missing CSS file at ${cssPath}.`);
500
+ }
501
+ return readFileSync3(cssPath, "utf8");
502
+ }
503
+ function getRouteCss(routePath, options) {
504
+ const manifest = readTypestylesManifest(options.root, options.manifestFile);
505
+ const normalized = normalizeRoutePath(routePath);
506
+ if (isManifestV2(manifest)) {
507
+ const routeEntry = manifest.routes[normalized];
508
+ if (routeEntry) {
509
+ return readCssFile(options.root, routeEntry.css);
510
+ }
511
+ }
512
+ return readCssFile(options.root, manifest.css);
513
+ }
514
+
515
+ // src/index.ts
516
+ import { build as esbuildBuild2 } from "esbuild";
517
+ import { existsSync as existsSync6, unlinkSync, writeFileSync } from "fs";
518
+ import { resolve as resolve6 } from "path";
5
519
  import { spawnSync } from "child_process";
6
520
  function toImportPath(modulePath) {
7
521
  const normalized = modulePath.replace(/\\/g, "/");
@@ -16,13 +530,32 @@ async function runTypestylesBuild({
16
530
  }) {
17
531
  if (!modules.length) return "";
18
532
  const importLines = modules.map((mod) => `import ${JSON.stringify(toImportPath(mod))};`).join("\n");
19
- const bundleResult = await esbuildBuild({
533
+ const bundleResult = await esbuildBuild2({
20
534
  write: false,
21
535
  bundle: true,
22
536
  platform: "node",
23
537
  format: "cjs",
24
538
  target: "node18",
25
539
  external: ["typestyles"],
540
+ // Style registration calls (styles.component/class, createTypeStyles) are
541
+ // side-effect-only: the CSS they register into the global registry is the
542
+ // point, regardless of whether the returned classname function is ever
543
+ // read. esbuild's default tree shaking doesn't know that, so any
544
+ // consumer module reached only through an unread namespace/barrel import
545
+ // (or a package marked "sideEffects": false) can have its registration
546
+ // calls silently dropped as "unused". Disable tree shaking here so every
547
+ // registration in the extraction graph survives.
548
+ treeShaking: false,
549
+ // `treeShaking: false` only stops esbuild from pruning declarations
550
+ // *within* an already-included module. It's a separate esbuild behavior
551
+ // by the treeShaking option — that drops a plain bare import entirely
552
+ // (`import './some-lib'` with no binding at all) when it resolves to a
553
+ // module/package marked "sideEffects": false, before that module is ever
554
+ // considered for inclusion. A real extraction entry is exactly this
555
+ // shape: several side-effect-only imports, any one of which may point at
556
+ // a (correctly) tree-shakeable component library. Ignore both kinds of
557
+ // annotation so every import in the extraction graph is included.
558
+ ignoreAnnotations: true,
26
559
  stdin: {
27
560
  contents: importLines,
28
561
  resolveDir: root,
@@ -34,7 +567,7 @@ async function runTypestylesBuild({
34
567
  if (!bundledCode) {
35
568
  throw new Error("[typestyles] Failed to produce extraction bundle.");
36
569
  }
37
- const scriptPath = resolve(root, `.typestyles-extract-${process.pid}.cjs`);
570
+ const scriptPath = resolve6(root, `.typestyles-extract-${process.pid}.cjs`);
38
571
  const script = `${bundledCode}
39
572
  process.stdout.write(require('typestyles').getRegisteredCss());
40
573
  `;
@@ -56,7 +589,7 @@ ${result.stderr || result.stdout || "unknown error"}`
56
589
  }
57
590
  return result.stdout ?? "";
58
591
  } finally {
59
- if (existsSync(scriptPath)) {
592
+ if (existsSync6(scriptPath)) {
60
593
  try {
61
594
  unlinkSync(scriptPath);
62
595
  } catch {
@@ -65,5 +598,26 @@ ${result.stderr || result.stdout || "unknown error"}`
65
598
  }
66
599
  }
67
600
  export {
68
- runTypestylesBuild
601
+ DEFAULT_EXTRACT_MODULE_CANDIDATES,
602
+ TYPESTYLES_IMPORT_RE,
603
+ VerifyTypestylesBuildError,
604
+ buildManifestV2,
605
+ collectAndWriteRouteCss,
606
+ createModuleLoader,
607
+ discoverDefaultExtractModules,
608
+ discoverNextAppRoutes,
609
+ extractNamespaces,
610
+ getRouteCss,
611
+ isManifestV2,
612
+ moduleNeedsOverrideHmr,
613
+ normalizeRoutePath,
614
+ pageRelPathToRoutePath,
615
+ readCssFile,
616
+ readTypestylesManifest,
617
+ reportDuplicateNamespaces,
618
+ resolveExtractMode,
619
+ resolveExtractModules,
620
+ runTypestylesBuild,
621
+ traceTypestylesModules,
622
+ verifyTypestylesBuild
69
623
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typestyles/build-runner",
3
- "version": "0.0.0-unstable.439960c19a5a",
3
+ "version": "0.0.0-unstable.4b1f40dade83",
4
4
  "description": "Shared module execution utilities for typestyles build integrations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -28,16 +28,19 @@
28
28
  "@types/node": "^25.2.1",
29
29
  "eslint": "^9.39.2",
30
30
  "tsup": "^8.0.0",
31
- "typescript": "^5.4.0"
31
+ "typescript": "^5.4.0",
32
+ "typestyles": "0.0.0-unstable.4b1f40dade83",
33
+ "vitest": "^3.0.0"
32
34
  },
33
35
  "license": "Apache-2.0",
34
36
  "repository": {
35
37
  "type": "git",
36
- "url": "https://github.com/dbanksdesign/typestyles",
38
+ "url": "https://github.com/type-styles/typestyles",
37
39
  "directory": "packages/build-runner"
38
40
  },
39
41
  "scripts": {
40
42
  "build": "tsup src/index.ts --format esm,cjs --dts --clean",
43
+ "test": "vitest run",
41
44
  "lint": "eslint .",
42
45
  "typecheck": "tsc --noEmit"
43
46
  }