@pandacss/config 2.0.0-beta.5 → 2.0.0-beta.7

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.
@@ -2,12 +2,26 @@
2
2
  var PandaError = class extends Error {
3
3
  code;
4
4
  hint;
5
+ diagnostics;
5
6
  constructor(code, message, opts) {
6
7
  super(message, { cause: opts?.cause });
7
8
  this.code = `ERR_PANDA_${code}`;
8
9
  this.hint = opts?.hint;
10
+ this.diagnostics = opts?.diagnostics;
9
11
  }
10
12
  };
13
+ function createConfigError(message, diagnostics) {
14
+ return new PandaError("CONFIG_ERROR", `\u{1F4A5} ${message}`, { diagnostics });
15
+ }
16
+ function createConfigDiagnostic(code, message, help) {
17
+ return {
18
+ code,
19
+ message,
20
+ severity: "error",
21
+ category: "config",
22
+ ...help ? { help } : {}
23
+ };
24
+ }
11
25
 
12
26
  // src/sources.ts
13
27
  var sectionKeySet = /* @__PURE__ */ new Set([
@@ -125,6 +139,13 @@ function clone(value) {
125
139
  }
126
140
  return value;
127
141
  }
142
+ function ensureConfigObject(config, name) {
143
+ if (isPlainObject2(config)) return config;
144
+ throw new PandaError("CONFIG_ERROR", `\u{1F4A5} Preset ${JSON.stringify(name)} must resolve to an object.`);
145
+ }
146
+ function errorMessage(error) {
147
+ return error instanceof Error ? error.message : String(error);
148
+ }
128
149
 
129
150
  // src/merge.ts
130
151
  var sectionKeys = [
@@ -244,7 +265,11 @@ function isValidToken(token) {
244
265
 
245
266
  export {
246
267
  PandaError,
268
+ createConfigError,
269
+ createConfigDiagnostic,
247
270
  isPlainObject2 as isPlainObject,
271
+ ensureConfigObject,
272
+ errorMessage,
248
273
  mergeConfigsWithSources,
249
274
  mergeConfigs
250
275
  };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { SerializedConfig, ProjectCallbacks, ProjectHooks, ConfigSnapshot, DiffConfigResult } from '@pandacss/compiler-shared';
1
+ import { DesignSystemManifest, SerializedConfig, ProjectCallbacks, ProjectHooks, ConfigSnapshot, DiffConfigResult, DesignSystemManifestImportMap } from '@pandacss/compiler-shared';
2
2
  export { DiffConfigResult } from '@pandacss/compiler-shared';
3
- import { HookRegistry, Config } from '@pandacss/types';
4
- import { C as ConfigSources } from './merge-Bt4BM1CH.js';
5
- export { a as ConfigSourceEntry, m as mergeConfigs } from './merge-Bt4BM1CH.js';
3
+ import { HookRegistry, Config, UserConfig } from '@pandacss/types';
4
+ import { C as ConfigSources } from './merge-DiBpncUC.js';
5
+ export { a as ConfigSourceEntry, m as mergeConfigs } from './merge-DiBpncUC.js';
6
6
  export { ConfigSnapshot, createConfigSnapshot } from './serialize.js';
7
7
 
8
8
  interface PluginHookEntry<Name extends keyof HookRegistry> {
@@ -15,6 +15,17 @@ type HostHooks = {
15
15
  'codegen:done'?: Array<PluginHookEntry<'codegen:done'>>;
16
16
  };
17
17
 
18
+ interface ResolvedDesignSystem {
19
+ name: string;
20
+ specifier: string;
21
+ manifest: DesignSystemManifest;
22
+ manifestPath: string;
23
+ buildInfoPath: string;
24
+ files: string[];
25
+ tokenPaths: string[];
26
+ importMap?: DesignSystemManifest['importMap'];
27
+ }
28
+
18
29
  interface LoadConfigOptions {
19
30
  cwd: string;
20
31
  /** Explicit config file path (relative to `cwd`); otherwise discovered upward. */
@@ -37,6 +48,8 @@ interface LoadConfigResult {
37
48
  dependencies: string[];
38
49
  metadata?: {
39
50
  sources?: ConfigSources;
51
+ designSystem?: ResolvedDesignSystem[];
52
+ userTokenPaths?: string[];
40
53
  };
41
54
  }
42
55
 
@@ -81,4 +94,47 @@ interface BundleConfigResult<T = Config> {
81
94
  */
82
95
  declare function bundleConfig<T extends Config = Config>(filepath: string, cwd: string): Promise<BundleConfigResult<T>>;
83
96
 
84
- export { type BundleConfigResult, ConfigSources, type HostHooks, type LoadConfigOptions, type LoadConfigResult, bundleConfig, diffConfig, findConfig, loadConfig };
97
+ interface SmartIncludeResult {
98
+ include: string[];
99
+ excludes: string[];
100
+ changed: boolean;
101
+ }
102
+ declare function resolveSmartInclude(include: string[], cwd: string, deps: Set<string>): SmartIncludeResult;
103
+ declare function mergeExcludes(existing: string[] | undefined, additions: string[]): string[];
104
+
105
+ declare function readPandaVersion(): string | undefined;
106
+
107
+ interface CompilePresetResult {
108
+ code: string;
109
+ dependencies: string[];
110
+ }
111
+ interface CompilePresetOptions {
112
+ configPath: string;
113
+ cwd: string;
114
+ }
115
+ declare function compilePreset(options: CompilePresetOptions): Promise<CompilePresetResult>;
116
+
117
+ interface PackageIdentity {
118
+ name: string;
119
+ version?: string;
120
+ pandaPeer?: string;
121
+ packagePath: string;
122
+ }
123
+ declare function readPackageIdentity(cwd: string): PackageIdentity;
124
+ declare function defaultImportMap(name: string): DesignSystemManifestImportMap;
125
+ interface SyncExportsResult {
126
+ changed: boolean;
127
+ json: string;
128
+ }
129
+ interface SyncExportsOptions {
130
+ packageJson: string;
131
+ entries: Record<string, string>;
132
+ }
133
+ declare function syncExports(options: SyncExportsOptions): SyncExportsResult;
134
+ declare function toPosixPath(path: string): string;
135
+ declare function toPosixRelative(from: string, to: string): string;
136
+ declare function toRelativeKey(key: string, cwd: string): string;
137
+
138
+ declare function collectTokenPaths(config: Pick<UserConfig, 'theme'> | undefined): string[];
139
+
140
+ export { type BundleConfigResult, type CompilePresetOptions, type CompilePresetResult, ConfigSources, type HostHooks, type LoadConfigOptions, type LoadConfigResult, type PackageIdentity, type SyncExportsOptions, type SyncExportsResult, bundleConfig, collectTokenPaths, compilePreset, defaultImportMap, diffConfig, findConfig, loadConfig, mergeExcludes, readPackageIdentity, readPandaVersion, resolveSmartInclude, syncExports, toPosixPath, toPosixRelative, toRelativeKey };
package/dist/index.js CHANGED
@@ -1,9 +1,13 @@
1
1
  import {
2
2
  PandaError,
3
+ createConfigDiagnostic,
4
+ createConfigError,
5
+ ensureConfigObject,
6
+ errorMessage,
3
7
  isPlainObject,
4
8
  mergeConfigs,
5
9
  mergeConfigsWithSources
6
- } from "./chunk-LUSBBUHX.js";
10
+ } from "./chunk-YKIDLZNO.js";
7
11
  import {
8
12
  collectPluginHookHandlers,
9
13
  createConfigSnapshot,
@@ -307,9 +311,317 @@ function traverseValue(value, callback, options, parent, key, path = "", depth =
307
311
  function joinPath(parent, key, separator) {
308
312
  return parent ? `${parent}${separator}${key}` : key;
309
313
  }
314
+ function attachRuntimeHooks(config, configs) {
315
+ const plugins = configs.flatMap((item) => {
316
+ if ("hooks" in item && item.hooks != null) {
317
+ const message = '`config.hooks` was removed in v2. Use `plugins: [{ name: "local", hooks: { ... } }]` instead.';
318
+ throw createConfigError(message, [
319
+ createConfigDiagnostic("config_hooks_removed", message, [
320
+ 'Move root `hooks` into `plugins: [{ name: "local", hooks: { ... } }]`.'
321
+ ])
322
+ ]);
323
+ }
324
+ return [...item.plugins ?? [], ...item.extend?.plugins ?? []];
325
+ });
326
+ for (const plugin of plugins) {
327
+ if (!isPlainObject(plugin) || typeof plugin.name !== "string" || plugin.name.length === 0) {
328
+ throw new PandaError(
329
+ "CONFIG_ERROR",
330
+ "\u{1F4A5} Every plugin in `config.plugins` must be an object with a non-empty `name`."
331
+ );
332
+ }
333
+ }
334
+ if (plugins.length > 0) {
335
+ config.plugins = plugins;
336
+ }
337
+ return config;
338
+ }
339
+
340
+ // src/preset.ts
341
+ import { normalize as normalize2, relative as relative3 } from "path";
342
+
343
+ // src/design-system.ts
344
+ import {
345
+ outdirBasename
346
+ } from "@pandacss/compiler-shared";
347
+ import { readFileSync, statSync } from "fs";
348
+ import { dirname as dirname3, resolve as resolve3 } from "path";
349
+ import { pathToFileURL as pathToFileURL3 } from "url";
350
+
351
+ // src/resolve.ts
352
+ import { createRequire } from "module";
353
+ import { resolve as resolve2 } from "path";
354
+ function tryResolveFrom(request, fromDir) {
355
+ try {
356
+ return createRequire(resolve2(fromDir, "noop.js")).resolve(request, { paths: [fromDir] });
357
+ } catch (error) {
358
+ if (isResolveMiss(error)) return void 0;
359
+ throw error;
360
+ }
361
+ }
362
+ function isResolveMiss(error) {
363
+ const code = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
364
+ return code === "MODULE_NOT_FOUND" || code === "ERR_PACKAGE_PATH_NOT_EXPORTED";
365
+ }
366
+
367
+ // src/design-system.ts
368
+ async function loadDesignSystemChain(spec, cwd, deps) {
369
+ const levels = [];
370
+ const seenAt = /* @__PURE__ */ new Map();
371
+ let currentSpec = spec;
372
+ let fromDir = cwd;
373
+ let declaredBy;
374
+ while (true) {
375
+ const manifestPath = resolveManifestPath(currentSpec, fromDir);
376
+ if (manifestPath === void 0) {
377
+ throw declaredBy === void 0 ? notResolvedError(currentSpec) : parentNotResolvedError(declaredBy, currentSpec);
378
+ }
379
+ const seen = seenAt.get(manifestPath);
380
+ if (seen !== void 0) {
381
+ throw cycleError([...levels.slice(seen).map((level2) => level2.info.name), levels[seen].info.name]);
382
+ }
383
+ seenAt.set(manifestPath, levels.length);
384
+ deps.add(manifestPath);
385
+ const { level, parent } = await loadManifestLevel(currentSpec, manifestPath, deps);
386
+ levels.push(level);
387
+ if (parent === void 0) break;
388
+ declaredBy = level.info.name;
389
+ fromDir = dirname3(manifestPath);
390
+ currentSpec = parent;
391
+ }
392
+ return levels.reverse();
393
+ }
394
+ function withDesignSystemImportMap(config, infos) {
395
+ const existing = config.importMap === void 0 ? [] : Array.isArray(config.importMap) ? config.importMap : [config.importMap];
396
+ const roots = infos.map(
397
+ (info) => info.importMap ? designSystemImportMap(info.importMap, info.specifier) : info.specifier
398
+ );
399
+ return { ...config, importMap: [...roots, outdirBasename(config.outdir ?? "styled-system"), ...existing] };
400
+ }
401
+ function resolveManifestPath(spec, fromDir) {
402
+ try {
403
+ return tryResolveFrom(`${spec}/panda.lib.json`, fromDir);
404
+ } catch (error) {
405
+ const message = `Failed to resolve designSystem ${JSON.stringify(spec)} from ${JSON.stringify(fromDir)}: ${errorMessage(error)}`;
406
+ throw createConfigError(message, [createConfigDiagnostic("design_system_resolve_failed", message)]);
407
+ }
408
+ }
409
+ async function loadManifestLevel(spec, manifestPath, deps) {
410
+ let manifest;
411
+ try {
412
+ manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
413
+ } catch (error) {
414
+ throw new PandaError("CONFIG_ERROR", `\u{1F4A5} Failed to read ${JSON.stringify(manifestPath)}: ${errorMessage(error)}`);
415
+ }
416
+ if (typeof manifest.preset !== "string") {
417
+ throw invalidManifestError(spec, "preset");
418
+ }
419
+ if (typeof manifest.buildInfo !== "string") {
420
+ throw invalidManifestError(spec, "buildInfo");
421
+ }
422
+ const presetPath = resolve3(dirname3(manifestPath), manifest.preset);
423
+ const buildInfoPath = resolve3(dirname3(manifestPath), manifest.buildInfo);
424
+ deps.add(presetPath);
425
+ deps.add(buildInfoPath);
426
+ let preset;
427
+ try {
428
+ const mod = await import(presetImportUrl(presetPath));
429
+ preset = ensureConfigObject(mod.default ?? mod, manifest.name ?? spec);
430
+ } catch (error) {
431
+ if (error instanceof PandaError) throw error;
432
+ throw new PandaError(
433
+ "CONFIG_ERROR",
434
+ `\u{1F4A5} Failed to load preset for designSystem ${JSON.stringify(spec)}: ${errorMessage(error)}`
435
+ );
436
+ }
437
+ const parent = typeof manifest.designSystem === "string" && manifest.designSystem.length > 0 ? manifest.designSystem : void 0;
438
+ return {
439
+ parent,
440
+ level: {
441
+ preset,
442
+ info: {
443
+ name: manifest.name ?? spec,
444
+ specifier: spec,
445
+ manifest,
446
+ manifestPath,
447
+ buildInfoPath,
448
+ files: manifest.files ?? [],
449
+ tokenPaths: [],
450
+ ...manifest.importMap ? { importMap: manifest.importMap } : {}
451
+ }
452
+ }
453
+ };
454
+ }
455
+ function presetImportUrl(path) {
456
+ const url = pathToFileURL3(path);
457
+ url.searchParams.set("mtime", String(statSync(path).mtimeMs));
458
+ return url.href;
459
+ }
460
+ function designSystemImportMap(map, spec) {
461
+ return {
462
+ css: map.css ?? `${spec}/css`,
463
+ recipes: map.recipes ?? `${spec}/recipes`,
464
+ patterns: map.patterns ?? `${spec}/patterns`,
465
+ jsx: map.jsx ?? `${spec}/jsx`,
466
+ tokens: map.tokens ?? `${spec}/tokens`
467
+ };
468
+ }
469
+ function notResolvedError(spec) {
470
+ const message = `designSystem ${JSON.stringify(spec)} could not be resolved. Install it, or \u2014 if it isn't a Panda design system \u2014 build it with \`panda lib\`.`;
471
+ return createConfigError(message, [
472
+ createConfigDiagnostic("design_system_manifest_not_found", message, [
473
+ `Install ${JSON.stringify(spec)}, or build it with \`panda lib\` if it is a Panda design system.`
474
+ ])
475
+ ]);
476
+ }
477
+ function parentNotResolvedError(child, parent) {
478
+ const message = `designSystem ${JSON.stringify(child)} extends ${JSON.stringify(parent)}, which isn't installed alongside it. Install it where ${JSON.stringify(child)} can resolve it, or rebuild that library with \`panda lib\`.`;
479
+ return createConfigError(message, [
480
+ createConfigDiagnostic("design_system_parent_not_found", message, [
481
+ `Install ${JSON.stringify(parent)} where ${JSON.stringify(child)} can resolve it, or rebuild ${JSON.stringify(child)} with \`panda lib\`.`
482
+ ])
483
+ ]);
484
+ }
485
+ function cycleError(cycle) {
486
+ const message = `Design-system cycle: ${cycle.join(" \u2192 ")}. A design system can't depend on itself.`;
487
+ return createConfigError(message, [createConfigDiagnostic("design_system_cycle", message)]);
488
+ }
489
+ function invalidManifestError(spec, field) {
490
+ const message = `${JSON.stringify(spec)} manifest is missing a "${field}" entry.`;
491
+ return createConfigError(message, [
492
+ createConfigDiagnostic("design_system_manifest_invalid", message, [
493
+ `Rebuild ${JSON.stringify(spec)} with \`panda lib\`.`
494
+ ])
495
+ ]);
496
+ }
497
+
498
+ // src/smart-include.ts
499
+ import { existsSync as existsSync2 } from "fs";
500
+ import { dirname as dirname4, isAbsolute as isAbsolute3, join as join2, relative as relative2, resolve as resolve4, sep } from "path";
501
+ var SMART_INCLUDE_EXTENSIONS = ["js", "mjs", "cjs", "jsx", "ts", "cts", "mts", "tsx", "vue", "svelte", "astro"];
502
+ var MANIFEST = "panda.lib.json";
503
+ var PACKAGE_SPECIFIER = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/i;
504
+ var PATH_SEPARATOR = /[\\/]/;
505
+ function resolveSmartInclude(include, cwd, deps) {
506
+ const offenders = [];
507
+ const next = [];
508
+ const excludes = [];
509
+ let changed = false;
510
+ for (const entry of include) {
511
+ if (!PACKAGE_SPECIFIER.test(entry)) {
512
+ next.push(entry);
513
+ continue;
514
+ }
515
+ if (isLocalPath(entry, cwd)) {
516
+ next.push(entry);
517
+ continue;
518
+ }
519
+ if (tryResolveFrom(`${entry}/${MANIFEST}`, cwd) !== void 0) {
520
+ offenders.push(entry);
521
+ continue;
522
+ }
523
+ const packageDir = resolvePackageDir(entry, cwd);
524
+ if (packageDir === void 0) {
525
+ next.push(entry);
526
+ continue;
527
+ }
528
+ if (existsSync2(join2(packageDir, MANIFEST))) {
529
+ offenders.push(entry);
530
+ continue;
531
+ }
532
+ deps.add(join2(packageDir, "package.json"));
533
+ const base = globBase(packageDir, cwd);
534
+ next.push(`${base}/**/*.{${SMART_INCLUDE_EXTENSIONS.join(",")}}`);
535
+ excludes.push(`${base}/**/node_modules/**`);
536
+ changed = true;
537
+ }
538
+ if (offenders.length > 0) throw inIncludeError(offenders);
539
+ return { include: changed ? next : include, excludes, changed };
540
+ }
541
+ function expandSmartInclude(config, cwd, deps) {
542
+ if (!config.include || config.include.length === 0) return config;
543
+ const resolved = resolveSmartInclude(config.include, cwd, deps);
544
+ if (!resolved.changed) return config;
545
+ return { ...config, include: resolved.include, exclude: mergeExcludes(config.exclude, resolved.excludes) };
546
+ }
547
+ function mergeExcludes(existing, additions) {
548
+ return [...existing ?? [], ...additions];
549
+ }
550
+ function isLocalPath(entry, cwd) {
551
+ return existsSync2(isAbsolute3(entry) ? entry : resolve4(cwd, entry));
552
+ }
553
+ function resolvePackageDir(spec, cwd) {
554
+ const fromPackageJson = tryResolve(`${spec}/package.json`, cwd);
555
+ if (fromPackageJson !== void 0) return dirname4(fromPackageJson);
556
+ const fromEntry = tryResolve(spec, cwd);
557
+ return fromEntry === void 0 ? void 0 : nearestPackageDir(fromEntry);
558
+ }
559
+ function tryResolve(request, cwd) {
560
+ try {
561
+ return tryResolveFrom(request, cwd);
562
+ } catch (error) {
563
+ const message = `Failed to resolve include package ${JSON.stringify(request)} from ${JSON.stringify(cwd)}: ${errorMessage(error)}`;
564
+ throw createConfigError(message, [createConfigDiagnostic("include_package_resolution_failed", message)]);
565
+ }
566
+ }
567
+ function isInsideCwd(relativePath) {
568
+ if (relativePath === "" || relativePath === "..") return false;
569
+ if (isAbsolute3(relativePath)) return false;
570
+ return !relativePath.startsWith(`..${sep}`);
571
+ }
572
+ function nearestPackageDir(from) {
573
+ let dir = dirname4(from);
574
+ while (true) {
575
+ if (existsSync2(join2(dir, "package.json"))) return dir;
576
+ const parent = dirname4(dir);
577
+ if (parent === dir) return void 0;
578
+ dir = parent;
579
+ }
580
+ }
581
+ function globBase(packageDir, cwd) {
582
+ const rel = relative2(cwd, packageDir);
583
+ const base = isInsideCwd(rel) ? rel : packageDir;
584
+ return toPosix(base);
585
+ }
586
+ function toPosix(path) {
587
+ return path.split(PATH_SEPARATOR).join("/");
588
+ }
589
+ function inIncludeError(specs) {
590
+ const list = specs.map((spec) => JSON.stringify(spec)).join(", ");
591
+ const plural = specs.length > 1;
592
+ const message = `Design system${plural ? "s" : ""} in \`include\`: ${list}. ${plural ? "They each ship" : "It ships"} a ${MANIFEST}, so ${plural ? "they belong" : "it belongs"} in \`designSystem\`, not \`include\`. \`include\` is for files, not design systems.`;
593
+ return createConfigError(
594
+ message,
595
+ specs.map(
596
+ (spec) => createConfigDiagnostic(
597
+ "design_system_in_include",
598
+ `Design system ${JSON.stringify(spec)} is listed in \`include\`. Move it to \`designSystem\`; \`include\` is for files, not design systems.`,
599
+ [`Move ${JSON.stringify(spec)} to \`designSystem\`.`]
600
+ )
601
+ )
602
+ );
603
+ }
604
+
605
+ // src/token-paths.ts
606
+ function collectTokenPaths(config) {
607
+ if (!isPlainObject(config?.theme)) return [];
608
+ const paths = /* @__PURE__ */ new Set();
609
+ collect(config.theme.tokens, [], paths);
610
+ collect(config.theme.semanticTokens, [], paths);
611
+ return [...paths].sort();
612
+ }
613
+ function collect(node, trail, out) {
614
+ if (!isPlainObject(node)) return;
615
+ if ("value" in node) {
616
+ if (trail.length > 0) out.add(trail.join("."));
617
+ return;
618
+ }
619
+ for (const [key, child] of Object.entries(node)) {
620
+ collect(child, [...trail, key], out);
621
+ }
622
+ }
310
623
 
311
624
  // src/preset.ts
312
- import { normalize as normalize2, relative as relative2 } from "path";
313
625
  async function resolveAuthoredPresets(config, cwd, options = {}) {
314
626
  const ctx = {
315
627
  cwd,
@@ -319,44 +631,68 @@ async function resolveAuthoredPresets(config, cwd, options = {}) {
319
631
  ...options.trackSources ? { sourcedConfigs: [] } : {}
320
632
  };
321
633
  const rootSource = { kind: "config" };
322
- if (options.configFile) rootSource.file = normalize2(relative2(cwd, options.configFile));
323
- await collectConfigs(config, rootSource, ctx, /* @__PURE__ */ new WeakSet());
634
+ if (options.configFile) rootSource.file = normalize2(relative3(cwd, options.configFile));
635
+ const designSystem = config.designSystem;
636
+ let dsChain = [];
637
+ if (typeof designSystem === "string" && designSystem.length > 0) {
638
+ dsChain = await loadDesignSystemChain(designSystem, cwd, ctx.dependencies);
639
+ for (const level of dsChain) {
640
+ const block = await collectConfigBlock(
641
+ level.preset,
642
+ { kind: "preset", specifier: level.info.name },
643
+ cwd,
644
+ ctx.dependencies,
645
+ options.trackSources
646
+ );
647
+ level.info.tokenPaths = collectTokenPaths(block.resolved);
648
+ appendConfigBlock(ctx, block);
649
+ }
650
+ }
651
+ const rootBlock = await collectConfigBlock(config, rootSource, cwd, ctx.dependencies, options.trackSources);
652
+ appendConfigBlock(ctx, rootBlock);
653
+ const dsInfos = dsChain.map((level) => level.info);
654
+ const finalize = (resolved) => {
655
+ const withImportMap = dsInfos.length > 0 ? withDesignSystemImportMap(resolved, dsInfos) : resolved;
656
+ return expandSmartInclude(withImportMap, cwd, ctx.dependencies);
657
+ };
658
+ const dsMetadata = dsInfos.length > 0 ? { designSystem: dsInfos, userTokenPaths: collectTokenPaths(rootBlock.resolved) } : void 0;
324
659
  if (ctx.sourcedConfigs) {
325
660
  const merged = mergeConfigsWithSources(ctx.sourcedConfigs);
326
661
  if (options.preserveRuntimeHooks) attachRuntimeHooks(merged.config, ctx.configs);
327
662
  return {
328
- config: merged.config,
663
+ config: finalize(merged.config),
329
664
  dependencies: Array.from(ctx.dependencies),
330
- metadata: { sources: merged.sources }
665
+ metadata: { sources: merged.sources, ...dsMetadata }
331
666
  };
332
667
  }
333
668
  return {
334
- config: options.preserveRuntimeHooks ? attachRuntimeHooks(mergeConfigs(ctx.configs), ctx.configs) : mergeConfigs(ctx.configs),
335
- dependencies: Array.from(ctx.dependencies)
669
+ config: finalize(
670
+ options.preserveRuntimeHooks ? attachRuntimeHooks(mergeConfigs(ctx.configs), ctx.configs) : mergeConfigs(ctx.configs)
671
+ ),
672
+ dependencies: Array.from(ctx.dependencies),
673
+ ...dsMetadata ? { metadata: dsMetadata } : {}
336
674
  };
337
675
  }
338
- function attachRuntimeHooks(config, configs) {
339
- const plugins = configs.flatMap((item) => {
340
- if ("hooks" in item && item.hooks != null) {
341
- throw new PandaError(
342
- "CONFIG_ERROR",
343
- '\u{1F4A5} `config.hooks` was removed in v2. Use `plugins: [{ name: "local", hooks: { ... } }]` instead.'
344
- );
345
- }
346
- return [...item.plugins ?? [], ...item.extend?.plugins ?? []];
347
- });
348
- for (const plugin of plugins) {
349
- if (!isPlainObject(plugin) || typeof plugin.name !== "string" || plugin.name.length === 0) {
350
- throw new PandaError(
351
- "CONFIG_ERROR",
352
- "\u{1F4A5} Every plugin in `config.plugins` must be an object with a non-empty `name`."
353
- );
354
- }
355
- }
356
- if (plugins.length > 0) {
357
- config.plugins = plugins;
676
+ async function collectConfigBlock(config, source, cwd, dependencies, trackSources) {
677
+ const ctx = {
678
+ cwd,
679
+ configs: [],
680
+ dependencies,
681
+ presetResolvedHooks: [],
682
+ ...trackSources ? { sourcedConfigs: [] } : {}
683
+ };
684
+ await collectConfigs(config, source, ctx, /* @__PURE__ */ new WeakSet());
685
+ return {
686
+ configs: ctx.configs,
687
+ ...ctx.sourcedConfigs ? { sourcedConfigs: ctx.sourcedConfigs } : {},
688
+ resolved: mergeConfigs(ctx.configs)
689
+ };
690
+ }
691
+ function appendConfigBlock(ctx, block) {
692
+ ctx.configs.push(...block.configs);
693
+ if (ctx.sourcedConfigs && block.sourcedConfigs) {
694
+ ctx.sourcedConfigs.push(...block.sourcedConfigs);
358
695
  }
359
- return config;
360
696
  }
361
697
  async function collectConfigs(config, source, ctx, active) {
362
698
  if (active.has(config)) {
@@ -402,10 +738,7 @@ async function resolvePreset(preset, cwd) {
402
738
  };
403
739
  } catch (error) {
404
740
  if (error instanceof PandaError) throw error;
405
- throw new PandaError(
406
- "CONFIG_ERROR",
407
- `\u{1F4A5} Failed to resolve preset ${JSON.stringify(preset)}: ${errorMessage(error)}`
408
- );
741
+ throw presetResolutionError(JSON.stringify(preset), error);
409
742
  }
410
743
  }
411
744
  try {
@@ -417,12 +750,12 @@ async function resolvePreset(preset, cwd) {
417
750
  };
418
751
  } catch (error) {
419
752
  if (error instanceof PandaError) throw error;
420
- throw new PandaError("CONFIG_ERROR", `\u{1F4A5} Failed to resolve preset "unknown-preset": ${errorMessage(error)}`);
753
+ throw presetResolutionError('"unknown-preset"', error);
421
754
  }
422
755
  }
423
- function ensureConfigObject(config, name) {
424
- if (isPlainObject(config)) return config;
425
- throw new PandaError("CONFIG_ERROR", `\u{1F4A5} Preset ${JSON.stringify(name)} must resolve to an object.`);
756
+ function presetResolutionError(name, error) {
757
+ const message = `Failed to resolve preset ${name}: ${errorMessage(error)}`;
758
+ return createConfigError(message, [createConfigDiagnostic("preset_resolution_failed", message)]);
426
759
  }
427
760
  function presetName(config) {
428
761
  return isPlainObject(config) && typeof config.name === "string" ? config.name : void 0;
@@ -435,9 +768,6 @@ function presetSource(config, specifier, file) {
435
768
  if (file) source.file = file;
436
769
  return source;
437
770
  }
438
- function errorMessage(error) {
439
- return error instanceof Error ? error.message : String(error);
440
- }
441
771
 
442
772
  // src/load.ts
443
773
  async function loadConfig(options) {
@@ -593,11 +923,176 @@ function diffInput(input) {
593
923
  function isConfigSnapshot(input) {
594
924
  return !!input && typeof input === "object" && !Array.isArray(input) && ("callbacks" in input || "hooks" in input) && "config" in input && !!input.config && typeof input.config === "object" && !Array.isArray(input.config);
595
925
  }
926
+
927
+ // src/version.ts
928
+ import { readFileSync as readFileSync2 } from "fs";
929
+ import { dirname as dirname5, join as join3 } from "path";
930
+ import { fileURLToPath } from "url";
931
+ function readPandaVersion() {
932
+ try {
933
+ const pkgPath = join3(dirname5(fileURLToPath(import.meta.url)), "../package.json");
934
+ return JSON.parse(readFileSync2(pkgPath, "utf8")).version;
935
+ } catch {
936
+ return void 0;
937
+ }
938
+ }
939
+
940
+ // src/lib-preset.ts
941
+ import { builtinModules as builtinModules2 } from "module";
942
+ import { rolldown as rolldown2 } from "rolldown";
943
+ var APP_FIELDS = ["designSystem", "include", "exclude", "outdir", "cwd", "watch", "clean", "gitignore", "importMap"];
944
+ var VIRTUAL_ENTRY = "\0panda-lib-preset-entry";
945
+ var nodeBuiltins2 = /* @__PURE__ */ new Set([...builtinModules2, ...builtinModules2.map((mod) => `node:${mod}`)]);
946
+ async function compilePreset(options) {
947
+ const { configPath, cwd } = options;
948
+ const build = await rolldown2({
949
+ input: VIRTUAL_ENTRY,
950
+ cwd,
951
+ platform: "node",
952
+ external: (id) => nodeBuiltins2.has(id),
953
+ treeshake: true,
954
+ plugins: [importMetaUrlPlugin(), presetEntryPlugin(configPath)]
955
+ });
956
+ let chunks;
957
+ try {
958
+ chunks = await build.generate({ format: "esm", exports: "named", codeSplitting: false });
959
+ } finally {
960
+ await build.close?.();
961
+ }
962
+ const output = chunks.output.find((item) => item.type === "chunk");
963
+ if (!output || output.type !== "chunk") {
964
+ throw new PandaError("CONFIG_ERROR", "\u{1F4A5} Preset bundle did not produce an executable module.");
965
+ }
966
+ await validatePreset(output.code);
967
+ const dependencies = Object.keys(output.modules ?? {}).filter((id) => id !== VIRTUAL_ENTRY);
968
+ return { code: output.code, dependencies };
969
+ }
970
+ function presetEntryPlugin(configPath) {
971
+ return {
972
+ name: "panda-lib-preset-entry",
973
+ resolveId(id) {
974
+ return id === VIRTUAL_ENTRY ? VIRTUAL_ENTRY : null;
975
+ },
976
+ load(id) {
977
+ if (id !== VIRTUAL_ENTRY) return null;
978
+ const fields = APP_FIELDS.join(", ");
979
+ return `import __panda_lib_config from ${JSON.stringify(configPath)}
980
+ const __panda_lib_resolved = await __panda_lib_config
981
+ if (!${isPlainObjectSource()}(__panda_lib_resolved)) throw new Error('Config must export or return an object.')
982
+ const { ${fields}, ...preset } = __panda_lib_resolved
983
+ export default preset
984
+ `;
985
+ }
986
+ };
987
+ }
988
+ function isPlainObjectSource() {
989
+ return `((value) => {
990
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false
991
+ const proto = Object.getPrototypeOf(value)
992
+ return proto === Object.prototype || proto === null
993
+ })`;
994
+ }
995
+ async function validatePreset(code) {
996
+ try {
997
+ await import(`data:text/javascript;base64,${Buffer.from(code).toString("base64")}`);
998
+ } catch (error) {
999
+ throw new PandaError("CONFIG_ERROR", `\u{1F4A5} Failed to compile design system preset: ${errorMessage2(error)}`);
1000
+ }
1001
+ }
1002
+ function errorMessage2(error) {
1003
+ return error instanceof Error ? error.message : String(error);
1004
+ }
1005
+
1006
+ // src/lib-manifest.ts
1007
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
1008
+ import { dirname as dirname6, isAbsolute as isAbsolute4, join as join4, relative as relative4 } from "path";
1009
+ function readPackageIdentity(cwd) {
1010
+ const packagePath = nearestPackageJson(cwd);
1011
+ if (packagePath === void 0) {
1012
+ throw new Error(`Could not find a package.json from ${JSON.stringify(cwd)} to build the design system manifest.`);
1013
+ }
1014
+ const pkg = JSON.parse(readFileSync3(packagePath, "utf8"));
1015
+ const name = pkg.name;
1016
+ if (typeof name !== "string" || name.length === 0) {
1017
+ throw new Error(`${JSON.stringify(packagePath)} has no "name"; a design system must be a named package.`);
1018
+ }
1019
+ const peer = pkg.peerDependencies?.["@pandacss/dev"];
1020
+ return {
1021
+ name,
1022
+ version: typeof pkg.version === "string" ? pkg.version : void 0,
1023
+ pandaPeer: typeof peer === "string" ? peer : void 0,
1024
+ packagePath
1025
+ };
1026
+ }
1027
+ function defaultImportMap(name) {
1028
+ return {
1029
+ css: `${name}/css`,
1030
+ recipes: `${name}/recipes`,
1031
+ patterns: `${name}/patterns`,
1032
+ jsx: `${name}/jsx`,
1033
+ tokens: `${name}/tokens`
1034
+ };
1035
+ }
1036
+ function syncExports(options) {
1037
+ const { packageJson, entries } = options;
1038
+ const pkg = JSON.parse(packageJson);
1039
+ const existing = normalizeExports(pkg.exports);
1040
+ const merged = { ...existing };
1041
+ for (const [key, value] of Object.entries(entries)) merged[key] = value;
1042
+ const changed = JSON.stringify(pkg.exports) !== JSON.stringify(merged);
1043
+ const out = { ...pkg, exports: merged };
1044
+ return { changed, json: `${JSON.stringify(out, null, 2)}
1045
+ ` };
1046
+ }
1047
+ function toPosixPath(path) {
1048
+ return path.split("\\").join("/");
1049
+ }
1050
+ function toPosixRelative(from, to) {
1051
+ const rel = toPosixPath(relative4(from, to));
1052
+ return rel.startsWith(".") ? rel : `./${rel}`;
1053
+ }
1054
+ function toRelativeKey(key, cwd) {
1055
+ return toPosixPath(isAbsolute4(key) ? relative4(cwd, key) : key);
1056
+ }
1057
+ function isPlainObject2(value) {
1058
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1059
+ }
1060
+ function normalizeExports(exports) {
1061
+ if (exports === void 0) return {};
1062
+ if (typeof exports === "string") return { ".": exports };
1063
+ if (!isPlainObject2(exports)) return {};
1064
+ if (isSubpathExportMap(exports)) return exports;
1065
+ return { ".": exports };
1066
+ }
1067
+ function isSubpathExportMap(exports) {
1068
+ return Object.keys(exports).some((key) => key === "." || key.startsWith("./"));
1069
+ }
1070
+ function nearestPackageJson(start) {
1071
+ let current = start;
1072
+ while (true) {
1073
+ const candidate = join4(current, "package.json");
1074
+ if (existsSync3(candidate)) return candidate;
1075
+ const parent = dirname6(current);
1076
+ if (parent === current) return void 0;
1077
+ current = parent;
1078
+ }
1079
+ }
596
1080
  export {
597
1081
  bundleConfig,
1082
+ collectTokenPaths,
1083
+ compilePreset,
598
1084
  createConfigSnapshot,
1085
+ defaultImportMap,
599
1086
  diffConfig,
600
1087
  findConfig,
601
1088
  loadConfig,
602
- mergeConfigs
1089
+ mergeConfigs,
1090
+ mergeExcludes,
1091
+ readPackageIdentity,
1092
+ readPandaVersion,
1093
+ resolveSmartInclude,
1094
+ syncExports,
1095
+ toPosixPath,
1096
+ toPosixRelative,
1097
+ toRelativeKey
603
1098
  };
package/dist/merge.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { S as SourcedConfig, m as mergeConfigs, b as mergeConfigsWithSources } from './merge-Bt4BM1CH.js';
1
+ export { S as SourcedConfig, m as mergeConfigs, b as mergeConfigsWithSources } from './merge-DiBpncUC.js';
2
2
  import '@pandacss/types';
package/dist/merge.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  mergeConfigs,
3
3
  mergeConfigsWithSources
4
- } from "./chunk-LUSBBUHX.js";
4
+ } from "./chunk-YKIDLZNO.js";
5
5
  export {
6
6
  mergeConfigs,
7
7
  mergeConfigsWithSources
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pandacss/config",
3
- "version": "2.0.0-beta.5",
3
+ "version": "2.0.0-beta.7",
4
4
  "description": "Self-contained loader that bundles and serializes a Panda config for the Rust compiler",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -45,8 +45,8 @@
45
45
  "magic-string": "^0.30.21",
46
46
  "microdiff": "1.5.0",
47
47
  "rolldown": "1.0.0-rc.17",
48
- "@pandacss/compiler-shared": "2.0.0-beta.5",
49
- "@pandacss/types": "2.0.0-beta.5"
48
+ "@pandacss/compiler-shared": "2.0.0-beta.7",
49
+ "@pandacss/types": "2.0.0-beta.7"
50
50
  },
51
51
  "engines": {
52
52
  "node": ">=22"
@@ -1,5 +1,11 @@
1
1
  import { Config } from '@pandacss/types';
2
2
 
3
+ type Dict = Record<string, any>;
4
+ type Extendable<T> = T & {
5
+ extend?: T;
6
+ };
7
+ type ExtendableConfig = Extendable<Config>;
8
+
3
9
  interface ConfigSourceEntry {
4
10
  kind: 'config' | 'preset';
5
11
  name?: string;
@@ -19,12 +25,6 @@ declare class SourceTracker {
19
25
  delete(path: string[]): void;
20
26
  }
21
27
 
22
- type Dict = Record<string, any>;
23
- type Extendable<T> = T & {
24
- extend?: T;
25
- };
26
- type ExtendableConfig = Extendable<Config>;
27
-
28
28
  interface SourcedConfig {
29
29
  config: ExtendableConfig;
30
30
  source: ConfigSourceEntry;