inventive-ui 0.0.11 → 0.0.12

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,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.ts
4
- import path26 from "path";
4
+ import path25 from "path";
5
5
  import { Command } from "commander";
6
6
 
7
7
  // src/utils/ui.ts
@@ -190,7 +190,7 @@ var BANNER_COMPACT = [
190
190
  var FULL_BANNER_WIDTH = 101;
191
191
  function resolveCliVersion() {
192
192
  try {
193
- return true ? "0.0.11" : "1.0.0";
193
+ return true ? "0.0.12" : "1.0.0";
194
194
  } catch {
195
195
  return "1.0.0";
196
196
  }
@@ -373,8 +373,8 @@ function resolveApiBaseUrl() {
373
373
  );
374
374
  }
375
375
  if (parsed.pathname && parsed.pathname !== "/" && parsed.pathname !== "") {
376
- const path27 = parsed.pathname.replace(/\/+$/, "");
377
- if (path27 && !/^\/[a-zA-Z0-9._/-]+$/.test(path27)) {
376
+ const path26 = parsed.pathname.replace(/\/+$/, "");
377
+ if (path26 && !/^\/[a-zA-Z0-9._/-]+$/.test(path26)) {
378
378
  throw new CLIError(
379
379
  "IUI_API_URL path contains invalid characters.",
380
380
  "Use a simple path prefix such as /v1"
@@ -763,22 +763,6 @@ function writeJsonRestricted(filePath, data) {
763
763
 
764
764
  // src/utils/security/paths.ts
765
765
  import path4 from "path";
766
- function assertWithinRoot(rootDir, targetPath, label) {
767
- const root = path4.resolve(rootDir);
768
- const target = path4.resolve(targetPath);
769
- const rel = path4.relative(root, target);
770
- if (rel.startsWith("..") || path4.isAbsolute(rel)) {
771
- throw new CLIError(
772
- `Unsafe ${label} path: ${targetPath}`,
773
- `Path must stay within ${rootDir}`
774
- );
775
- }
776
- }
777
- function resolveWithinRoot(rootDir, ...segments) {
778
- const joined = path4.join(rootDir, ...segments);
779
- assertWithinRoot(rootDir, joined, "file");
780
- return joined;
781
- }
782
766
 
783
767
  // src/utils/security/process.ts
784
768
  import fs5 from "fs-extra";
@@ -1934,32 +1918,12 @@ function patchProjectConfigBuildBlock(content) {
1934
1918
  import ts2 from "typescript";
1935
1919
 
1936
1920
  // src/utils/security/identifiers.ts
1937
- var SLUG_RE = /^[a-z][a-z0-9-]*$/;
1938
1921
  var JS_IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
1939
- var NPM_SCOPE_IMPORT_RE = /^@inventive-ui\/[a-z0-9][a-z0-9._-]*$/;
1940
- var NPM_COMPONENT_SUBPATH_RE = /^@inventive-ui\/components\/[A-Za-z][A-Za-z0-9-]*$/;
1941
- function assertComponentSlug(slug) {
1942
- if (!SLUG_RE.test(slug)) {
1943
- throw new CLIError(
1944
- `Invalid component slug: "${slug}"`,
1945
- "Use lowercase letters, numbers, and hyphens (e.g. button, input)."
1946
- );
1947
- }
1948
- }
1949
1922
  function assertJsIdentifier(name, label) {
1950
1923
  if (!JS_IDENTIFIER_RE.test(name)) {
1951
1924
  throw new CLIError(`Invalid ${label}: "${name}"`);
1952
1925
  }
1953
1926
  }
1954
- function assertImportSpecifier(specifier) {
1955
- if (NPM_SCOPE_IMPORT_RE.test(specifier)) return;
1956
- if (NPM_COMPONENT_SUBPATH_RE.test(specifier)) return;
1957
- if (/^@inventive-ui\/[a-z0-9][a-z0-9-]*$/.test(specifier)) return;
1958
- throw new CLIError(`Unsafe import specifier: "${specifier}"`);
1959
- }
1960
- function escapeTsStringLiteral(value) {
1961
- return JSON.stringify(value);
1962
- }
1963
1927
  function sanitizePackageVersionHeader(value) {
1964
1928
  if (!value) return null;
1965
1929
  const trimmed = value.trim();
@@ -2443,9 +2407,6 @@ function componentManifestPath(cwd) {
2443
2407
  function packageManifestPath(cwd) {
2444
2408
  return metaPath("packages.json", cwd);
2445
2409
  }
2446
- function slotManifestPath(cwd) {
2447
- return metaPath("slots.json", cwd);
2448
- }
2449
2410
  function readProjectJsonStrict(p, label) {
2450
2411
  if (!fs8.existsSync(p)) {
2451
2412
  throw new CLIError(`Missing ${label}.`, "Run iui init to initialize the project.");
@@ -2704,14 +2665,6 @@ function writeAssetsConfig(cwd = process.cwd()) {
2704
2665
  } catch {
2705
2666
  }
2706
2667
  }
2707
- function readSlotManifest(cwd) {
2708
- const p = slotManifestPath(cwd);
2709
- if (!fs8.existsSync(p)) return {};
2710
- return readProjectJsonStrict(p, ".iui/slots.json");
2711
- }
2712
- function writeSlotManifest(manifest, cwd) {
2713
- writeJson(slotManifestPath(cwd), manifest);
2714
- }
2715
2668
  function readComponentPackageManifest(cwd = process.cwd()) {
2716
2669
  const pkgDir = resolvePackageDir("@inventive-ui/components", cwd);
2717
2670
  if (!pkgDir) return null;
@@ -3365,13 +3318,13 @@ function ensureInventiveUiViteConfig(cwd = process.cwd()) {
3365
3318
  }
3366
3319
 
3367
3320
  // src/services/auth.ts
3368
- async function api(path27, opts) {
3369
- const res = await fetch(`${API_BASE_URL}${path27}`, {
3321
+ async function api(path26, opts) {
3322
+ const res = await fetch(`${API_BASE_URL}${path26}`, {
3370
3323
  ...opts,
3371
3324
  signal: opts?.signal ?? AbortSignal.timeout(API_REQUEST_TIMEOUT_MS),
3372
3325
  headers: { "Content-Type": "application/json", ...opts?.headers }
3373
3326
  });
3374
- throwIfRateLimited(res, `calling ${path27}`);
3327
+ throwIfRateLimited(res, `calling ${path26}`);
3375
3328
  if (!res.ok) {
3376
3329
  const body = await res.text().catch(() => "");
3377
3330
  throw new CLIError(`API error ${res.status}: ${body || res.statusText}`);
@@ -3823,7 +3776,7 @@ async function promptText(title, hint2, placeholder, validate) {
3823
3776
  }
3824
3777
 
3825
3778
  // src/commands/init.ts
3826
- import path22 from "path";
3779
+ import path21 from "path";
3827
3780
  import ora3 from "ora";
3828
3781
 
3829
3782
  // src/services/license.ts
@@ -4790,8 +4743,8 @@ function getMajorFromVersion(version) {
4790
4743
  import ora2 from "ora";
4791
4744
 
4792
4745
  // src/services/slot-registry.ts
4793
- import fs17 from "fs-extra";
4794
- import path21 from "path";
4746
+ import fs16 from "fs-extra";
4747
+ import path20 from "path";
4795
4748
 
4796
4749
  // src/services/registry-lock.ts
4797
4750
  import fs11 from "fs";
@@ -4877,113 +4830,107 @@ async function withRegistryLock(cwd, operation) {
4877
4830
  }
4878
4831
  }
4879
4832
 
4880
- // src/services/slots.ts
4881
- import fs14 from "fs-extra";
4882
- import path18 from "path";
4833
+ // src/services/legacy-slot-cleanup.ts
4834
+ import fs12 from "fs-extra";
4835
+ import path16 from "path";
4883
4836
 
4884
- // src/utils/public-slot-contract.ts
4837
+ // src/services/generated-paths.ts
4885
4838
  import path15 from "path";
4886
- import fs12 from "fs-extra";
4887
- var CONTRACT_FILENAME = "public-slot-contract.json";
4888
- function loadPublicSlotContract(cwd = process.cwd()) {
4889
- const pkgRoot = resolvePackageDir("@inventive-ui/components", cwd);
4890
- if (!pkgRoot) return null;
4891
- const contractPath = path15.join(pkgRoot, CONTRACT_FILENAME);
4892
- if (!fs12.existsSync(contractPath)) return null;
4839
+ function iuiProjectRoot2(cwd) {
4840
+ return resolveIuiProjectRoot(cwd);
4841
+ }
4842
+ function generatedIuiDir(cwd) {
4843
+ return path15.join(iuiProjectRoot2(cwd), ".iui", "generated");
4844
+ }
4845
+
4846
+ // src/services/legacy-slot-cleanup.ts
4847
+ var MANAGED_MARKER = /@iui-managed|Managed by iui/;
4848
+ function isManagedFile(filePath) {
4893
4849
  try {
4894
- return fs12.readJsonSync(contractPath);
4850
+ return MANAGED_MARKER.test(fs12.readFileSync(filePath, "utf-8"));
4895
4851
  } catch {
4896
- return null;
4852
+ return false;
4897
4853
  }
4898
4854
  }
4899
- function slotRequiresPrefetch(entry) {
4900
- if (entry.prefetch === true) return true;
4901
- if (entry.prefetch === false) return false;
4902
- if (entry.bootstrap === "sync") return true;
4903
- return Array.isArray(entry.profile) && entry.profile.includes("critical");
4904
- }
4905
- function contractEntryToBootstrapPolicy(entry) {
4906
- return slotRequiresPrefetch(entry) ? "core" : "optional";
4907
- }
4908
- function validateSlotPrefetchPolicy(entry) {
4909
- const type = entry.type ?? "?";
4910
- const requires = slotRequiresPrefetch(entry);
4911
- if (requires && entry.prefetch === false) {
4912
- return `slot "${type}" is core/critical but prefetch is false`;
4913
- }
4914
- if ((entry.bootstrap === "sync" || Array.isArray(entry.profile) && entry.profile.includes("critical")) && entry.prefetch !== true) {
4915
- return `slot "${type}" must declare prefetch: true (sync/critical peer hub)`;
4916
- }
4917
- if (!requires && entry.prefetch === true) {
4918
- return `slot "${type}" declares prefetch: true but is not sync/critical`;
4855
+ function listFiles(dir, match) {
4856
+ if (!fs12.existsSync(dir)) return [];
4857
+ try {
4858
+ return fs12.readdirSync(dir).filter(match).map((file) => path16.join(dir, file));
4859
+ } catch {
4860
+ return [];
4919
4861
  }
4920
- return null;
4921
4862
  }
4922
-
4923
- // src/utils/slot-emitters.ts
4924
- function contractEntryToEmitter(entry) {
4925
- const lazyAccess = entry.lazyAccess.startsWith(".") ? entry.lazyAccess : `.${entry.lazyAccess}`;
4926
- return {
4927
- type: entry.type,
4928
- parentSlug: entry.parent,
4929
- componentName: entry.component ?? entry.type,
4930
- propsName: entry.props,
4931
- importSpecifier: entry.import,
4932
- lazyImportSpecifier: entry.lazyImport ?? entry.import,
4933
- lazyAccess
4934
- };
4935
- }
4936
- function isContractEntryInstalled(entry, installedSlugs) {
4937
- if (!entry.public) return false;
4938
- if (installedSlugs.has(entry.type)) return true;
4939
- if (installedSlugs.has(entry.parent)) return true;
4940
- return false;
4863
+ function ownedDirs(iuiRoot2, packageDirs) {
4864
+ const generated = generatedIuiDir(iuiRoot2);
4865
+ return [
4866
+ path16.join(generated, "slots"),
4867
+ path16.join(generated, "assets"),
4868
+ ...packageDirs.map((dir) => path16.join(dir, "src", "iui", "slots"))
4869
+ ];
4941
4870
  }
4942
- function collectInstalledSlotEmitters(items, installedSlugs, cwd = process.cwd()) {
4943
- const contract = loadPublicSlotContract(cwd);
4944
- if (!contract) {
4945
- return {
4946
- emitters: [],
4947
- issues: [
4948
- "@inventive-ui/components/public-slot-contract.json is missing from node_modules."
4949
- ]
4950
- };
4951
- }
4952
- const issues = [];
4953
- const emitters = [];
4954
- const registrySlugs = new Set(items.map((item) => item.name));
4955
- for (const slug of installedSlugs) {
4956
- if (!registrySlugs.has(slug)) continue;
4957
- const hasPrimary = contract.slots.some(
4958
- (entry) => entry.public && entry.type === slug
4871
+ function findStaleComponentSlotOutput(cwd, packageDirs = []) {
4872
+ const iuiRoot2 = iuiProjectRoot2(cwd);
4873
+ const generated = generatedIuiDir(iuiRoot2);
4874
+ const packages = [...new Set([iuiRoot2, ...packageDirs].map((dir) => path16.resolve(dir)))];
4875
+ const stale = [];
4876
+ stale.push(
4877
+ ...listFiles(
4878
+ path16.join(generated, "slots"),
4879
+ (file) => file.endsWith(".generated.tsx") || file.endsWith(".slot.tsx")
4880
+ )
4881
+ );
4882
+ const helper = path16.join(generated, "slot.generated.tsx");
4883
+ if (fs12.existsSync(helper) && isManagedFile(helper)) stale.push(helper);
4884
+ stale.push(
4885
+ ...listFiles(
4886
+ path16.join(generated, "assets"),
4887
+ (file) => file.endsWith(".bound.ts") || file === "register-bound.ts"
4888
+ )
4889
+ );
4890
+ const manifest = path16.join(iuiRoot2, ".iui", "slots.json");
4891
+ if (fs12.existsSync(manifest)) stale.push(manifest);
4892
+ for (const packageDir of packages) {
4893
+ const bridge = path16.join(packageDir, "src", "iui", "slot.tsx");
4894
+ if (fs12.existsSync(bridge) && isManagedFile(bridge)) stale.push(bridge);
4895
+ stale.push(
4896
+ ...listFiles(
4897
+ path16.join(packageDir, "src", "iui", "slots"),
4898
+ (file) => file.endsWith(".slot.tsx")
4899
+ )
4959
4900
  );
4960
- if (!hasPrimary) {
4961
- issues.push(`${slug}: no public slot contract entry for primary type "${slug}"`);
4962
- }
4963
4901
  }
4964
- for (const entry of contract.slots) {
4965
- if (!isContractEntryInstalled(entry, installedSlugs)) continue;
4966
- if (!entry.props || !entry.lazyAccess || !entry.import) {
4967
- issues.push(`${entry.type}: incomplete public slot contract entry`);
4968
- continue;
4902
+ return stale;
4903
+ }
4904
+ function removeStaleComponentSlotOutput(cwd, packageDirs = []) {
4905
+ const iuiRoot2 = iuiProjectRoot2(cwd);
4906
+ const removed = [];
4907
+ for (const file of findStaleComponentSlotOutput(iuiRoot2, packageDirs)) {
4908
+ try {
4909
+ fs12.removeSync(file);
4910
+ removed.push(file);
4911
+ } catch {
4969
4912
  }
4970
- emitters.push(contractEntryToEmitter(entry));
4971
4913
  }
4972
- const deduped = /* @__PURE__ */ new Map();
4973
- for (const emitter of emitters) {
4974
- if (!deduped.has(emitter.type)) {
4975
- deduped.set(emitter.type, emitter);
4914
+ for (const dir of ownedDirs(iuiRoot2, [iuiRoot2, ...packageDirs])) {
4915
+ try {
4916
+ if (fs12.existsSync(dir) && fs12.readdirSync(dir).length === 0) fs12.removeSync(dir);
4917
+ } catch {
4976
4918
  }
4977
4919
  }
4978
- return {
4979
- emitters: [...deduped.values()].sort((a, b) => a.type.localeCompare(b.type)),
4980
- issues
4981
- };
4920
+ return removed;
4982
4921
  }
4983
4922
 
4923
+ // src/services/workspace-bootstrap.ts
4924
+ import path19 from "path";
4925
+ import fs15 from "fs-extra";
4926
+
4927
+ // src/services/bootstrap.ts
4928
+ import fs14 from "fs-extra";
4929
+ import path18 from "path";
4930
+
4984
4931
  // src/utils/security/fsSafe.ts
4985
4932
  import fs13 from "fs";
4986
- import path16 from "path";
4933
+ import path17 from "path";
4987
4934
  function assertNotSymlink(filePath, label) {
4988
4935
  try {
4989
4936
  const stat = fs13.lstatSync(filePath);
@@ -4997,11 +4944,11 @@ function assertNotSymlink(filePath, label) {
4997
4944
  }
4998
4945
  }
4999
4946
  function safeWriteFile(filePath, content) {
5000
- const dir = path16.dirname(filePath);
4947
+ const dir = path17.dirname(filePath);
5001
4948
  if (fs13.existsSync(dir)) {
5002
4949
  assertNotSymlink(dir, "directory");
5003
4950
  }
5004
- const parent = path16.dirname(filePath);
4951
+ const parent = path17.dirname(filePath);
5005
4952
  fs13.mkdirSync(parent, { recursive: true });
5006
4953
  if (fs13.existsSync(filePath)) {
5007
4954
  assertNotSymlink(filePath, "file");
@@ -5009,348 +4956,13 @@ function safeWriteFile(filePath, content) {
5009
4956
  atomicWriteFile(filePath, content);
5010
4957
  }
5011
4958
 
5012
- // src/services/generated-paths.ts
5013
- import path17 from "path";
5014
- function iuiProjectRoot2(cwd) {
5015
- return resolveIuiProjectRoot(cwd);
5016
- }
5017
- function generatedIuiDir(cwd) {
5018
- return path17.join(iuiProjectRoot2(cwd), ".iui", "generated");
5019
- }
5020
- function generatedSlotsDir(cwd) {
5021
- return path17.join(generatedIuiDir(cwd), "slots");
5022
- }
5023
-
5024
- // src/services/slots.ts
5025
- var SLOT_GROUP_CORE_FILE = "slot-core.generated.tsx";
5026
- var SLOT_GROUP_OPTIONAL_FILE = "slot-optional.generated.tsx";
5027
- function bridgeSlotFilePath(cwd) {
5028
- return path18.join(cwd, "src", "iui", "slot.tsx");
5029
- }
5030
- function cleanupLegacySourceSlotFiles(cwd) {
5031
- const legacySlotsDir = path18.join(cwd, "src", "iui", "slots");
5032
- if (!fs14.existsSync(legacySlotsDir)) return;
5033
- try {
5034
- const files = fs14.readdirSync(legacySlotsDir);
5035
- for (const file of files) {
5036
- if (file.endsWith(".slot.tsx")) {
5037
- fs14.removeSync(path18.join(legacySlotsDir, file));
5038
- }
5039
- }
5040
- const remaining = fs14.readdirSync(legacySlotsDir);
5041
- if (remaining.length === 0) {
5042
- fs14.removeSync(legacySlotsDir);
5043
- }
5044
- } catch {
5045
- }
5046
- }
5047
- function loadSlotBootstrapPolicy(cwd) {
5048
- const policy = /* @__PURE__ */ new Map();
5049
- const contract = loadPublicSlotContract(cwd);
5050
- if (!contract) return policy;
5051
- for (const entry of contract.slots ?? []) {
5052
- if (!entry?.type || !entry.public) continue;
5053
- policy.set(entry.type, contractEntryToBootstrapPolicy(entry));
5054
- }
5055
- return policy;
5056
- }
5057
- function validateGeneratedSlotImports(cwd = process.cwd()) {
5058
- const components = readComponentManifest(cwd);
5059
- const pkgManifest = readComponentPackageManifest(cwd);
5060
- if (!pkgManifest) {
5061
- return ["@inventive-ui/components manifest is missing from node_modules."];
5062
- }
5063
- const itemsLookup = registryItemsMap(pkgManifest);
5064
- const installedItems = Object.keys(components).map((slug) => itemsLookup[slug]).filter((item) => Boolean(item));
5065
- const { issues } = collectInstalledSlotEmitters(
5066
- installedItems,
5067
- new Set(Object.keys(components)),
5068
- cwd
5069
- );
5070
- return issues.map((issue) => issue);
5071
- }
5072
- function renderGetComponentExpr(emitter, _slotPropsType = "unknown") {
5073
- const access = emitter.lazyAccess.replace(/^\./, "").trim();
5074
- const parts = access.split(".").filter(Boolean);
5075
- const compName = emitter.componentName;
5076
- if (parts.length === 0) {
5077
- assertJsIdentifier(compName, "component export");
5078
- return `resolveComponentExport(mod, ${JSON.stringify(compName)})`;
5079
- }
5080
- if (parts.length === 1) {
5081
- const name = parts[0] === "default" ? compName : parts[0];
5082
- assertJsIdentifier(name, "component export");
5083
- return `resolveComponentExport(mod, ${JSON.stringify(name)})`;
5084
- }
5085
- const [root, ...rest] = parts;
5086
- if (root !== "default") {
5087
- assertJsIdentifier(root, "component export");
5088
- }
5089
- for (const part of rest) {
5090
- assertJsIdentifier(part, "component export member");
5091
- }
5092
- const rootName = root === "default" ? compName : root;
5093
- if (rest.length === 1) {
5094
- return `resolveComponentExport(mod, ${JSON.stringify(rootName)}, ${JSON.stringify(rest[0])})`;
5095
- }
5096
- const rootExpr = `resolveComponentExport(mod, ${JSON.stringify(rootName)})`;
5097
- return `${rootExpr}?.${rest.join(".")}`;
5098
- }
5099
- function writeComponentSlotFiles(cwd = process.cwd()) {
5100
- const components = readComponentManifest(cwd);
5101
- const pkgManifest = readComponentPackageManifest(cwd);
5102
- const slotsDir = generatedSlotsDir(cwd);
5103
- const generationIssues = [];
5104
- cleanupLegacySourceSlotFiles(cwd);
5105
- if (Object.keys(components).length === 0) {
5106
- if (fs14.existsSync(slotsDir)) {
5107
- const existingSlots2 = fs14.readdirSync(slotsDir).filter((f) => f.endsWith(".slot.tsx"));
5108
- for (const file of existingSlots2) {
5109
- try {
5110
- fs14.removeSync(path18.join(slotsDir, file));
5111
- } catch {
5112
- }
5113
- }
5114
- }
5115
- return;
5116
- }
5117
- fs14.ensureDirSync(slotsDir);
5118
- if (!pkgManifest) return;
5119
- const itemsLookup = registryItemsMap(pkgManifest);
5120
- const installedItems = Object.entries(components).map(([slug]) => itemsLookup[slug]).filter((item) => Boolean(item));
5121
- const { emitters, issues: emitterIssues } = collectInstalledSlotEmitters(
5122
- installedItems,
5123
- new Set(Object.keys(components)),
5124
- cwd
5125
- );
5126
- generationIssues.push(...emitterIssues.map((issue) => `- ${issue}`));
5127
- const contract = loadPublicSlotContract(cwd);
5128
- if (contract) {
5129
- for (const entry of contract.slots ?? []) {
5130
- if (!entry.public) continue;
5131
- const prefetchError = validateSlotPrefetchPolicy(entry);
5132
- if (prefetchError) {
5133
- generationIssues.push(prefetchError);
5134
- }
5135
- }
5136
- }
5137
- const slotPolicy = loadSlotBootstrapPolicy(cwd);
5138
- const coreEmitters = [];
5139
- const optionalEmitters = [];
5140
- for (const emitter of emitters) {
5141
- assertComponentSlug(emitter.type);
5142
- assertJsIdentifier(emitter.componentName, "component export");
5143
- if (emitter.propsName !== "Props") assertJsIdentifier(emitter.propsName, "props type");
5144
- assertImportSpecifier(emitter.importSpecifier);
5145
- assertImportSpecifier(emitter.lazyImportSpecifier);
5146
- const policy = slotPolicy.get(emitter.type) ?? "optional";
5147
- if (policy === "core") coreEmitters.push(emitter);
5148
- else optionalEmitters.push(emitter);
5149
- }
5150
- const root = iuiProjectRoot2(cwd);
5151
- const renderedGroups = [
5152
- { fileName: SLOT_GROUP_CORE_FILE, emitters: coreEmitters },
5153
- { fileName: SLOT_GROUP_OPTIONAL_FILE, emitters: optionalEmitters }
5154
- ];
5155
- for (const group of renderedGroups) {
5156
- const outPath = resolveWithinRoot(root, ".iui", "generated", "slots", group.fileName);
5157
- if (group.emitters.length === 0) {
5158
- if (fs14.existsSync(outPath)) fs14.removeSync(outPath);
5159
- continue;
5160
- }
5161
- safeWriteFile(
5162
- outPath,
5163
- renderGroupedSlotFileContent(group.emitters, {
5164
- prefetch: group.fileName === SLOT_GROUP_CORE_FILE
5165
- })
5166
- );
5167
- }
5168
- const existingSlots = fs14.existsSync(slotsDir) ? fs14.readdirSync(slotsDir).filter((f) => f.endsWith(".slot.tsx") || f.endsWith(".generated.tsx")) : [];
5169
- for (const file of existingSlots) {
5170
- if (file === SLOT_GROUP_CORE_FILE || file === SLOT_GROUP_OPTIONAL_FILE) continue;
5171
- if (file.endsWith(".slot.tsx")) {
5172
- try {
5173
- fs14.removeSync(path18.join(slotsDir, file));
5174
- } catch {
5175
- }
5176
- continue;
5177
- }
5178
- if (file.endsWith(".generated.tsx")) {
5179
- try {
5180
- fs14.removeSync(path18.join(slotsDir, file));
5181
- } catch {
5182
- }
5183
- }
5184
- }
5185
- if (generationIssues.length > 0) {
5186
- throw new CLIError(
5187
- [
5188
- "Component public slot contract mismatch while generating slot files:",
5189
- ...generationIssues
5190
- ].join("\n"),
5191
- "Reinstall @inventive-ui/components and run iui doctor to repair the slot registry."
5192
- );
5193
- }
5194
- }
5195
- function renderGroupedSlotFileContent(emitters, options = {}) {
5196
- const needsComponentProps = emitters.some((emitter) => emitter.propsName === "Props");
5197
- const lines = [
5198
- "// Managed by iui. Do not edit manually.",
5199
- 'import React from "react";',
5200
- 'import { registerSlot, createEagerComponent, resolveComponentExport } from "@inventive-ui/framework/slots";'
5201
- ];
5202
- if (needsComponentProps) {
5203
- lines.push('import type { ComponentProps } from "react";');
5204
- }
5205
- lines.push("");
5206
- const imports = /* @__PURE__ */ new Set();
5207
- let idx = 0;
5208
- for (const emitter of emitters) {
5209
- idx += 1;
5210
- const alias = `Comp${idx}`;
5211
- if (emitter.propsName === "Props") {
5212
- imports.add(
5213
- `import type { ${emitter.componentName} as ${alias}Type } from "${emitter.importSpecifier}";`
5214
- );
5215
- } else {
5216
- imports.add(`import type { ${emitter.propsName} } from "${emitter.importSpecifier}";`);
5217
- }
5218
- }
5219
- lines.push(...[...imports].sort(), "");
5220
- idx = 0;
5221
- for (const emitter of emitters) {
5222
- idx += 1;
5223
- const alias = `Comp${idx}`;
5224
- const slotType = emitter.propsName === "Props" ? `ComponentProps<typeof ${alias}Type>` : emitter.propsName;
5225
- lines.push(`type ${alias}Slot = { type: "${emitter.type}" } & Omit<${slotType}, "type">;`);
5226
- lines.push(`type ${alias}SlotProps = Omit<${alias}Slot, "type">;`);
5227
- }
5228
- lines.push("", 'declare module "@inventive-ui/framework/slots" {', " interface SlotMap {");
5229
- idx = 0;
5230
- for (const emitter of emitters) {
5231
- idx += 1;
5232
- lines.push(` "${emitter.type}": Comp${idx}Slot;`);
5233
- }
5234
- lines.push(" }", "}", "");
5235
- idx = 0;
5236
- for (const emitter of emitters) {
5237
- idx += 1;
5238
- const alias = `Comp${idx}`;
5239
- const renderer = `${alias}Renderer`;
5240
- lines.push(`const ${renderer} = createEagerComponent<${alias}SlotProps>(`);
5241
- lines.push(` () => import(${escapeTsStringLiteral(emitter.lazyImportSpecifier)}),`);
5242
- lines.push(` (mod) => ${renderGetComponentExpr(emitter, `${alias}SlotProps`)} as React.ComponentType<${alias}SlotProps>,`);
5243
- if (options.prefetch) {
5244
- lines.push(" { prefetch: true },");
5245
- }
5246
- lines.push(");", "");
5247
- lines.push(`registerSlot(${escapeTsStringLiteral(emitter.type)}, (slot) => {`);
5248
- lines.push(" const { type, ...props } = slot;");
5249
- lines.push(` return <${renderer} {...props} />;`);
5250
- lines.push("});", "");
5251
- }
5252
- return `${lines.join("\n")}
5253
- `;
5254
- }
5255
- function writeSlotHelperFile(cwd = process.cwd()) {
5256
- const manifest = readSlotManifest(cwd);
5257
- const components = readComponentManifest(cwd);
5258
- const pkgManifest = readComponentPackageManifest(cwd);
5259
- const slotTypes = /* @__PURE__ */ new Set();
5260
- for (const record of Object.values(manifest)) {
5261
- if (record.slotType && record.slotType !== "component") {
5262
- slotTypes.add(record.slotType);
5263
- }
5264
- if (Array.isArray(record.supportedSlots)) {
5265
- for (const t of record.supportedSlots) slotTypes.add(t);
5266
- }
5267
- }
5268
- let emitterSlotTypes = [];
5269
- if (pkgManifest) {
5270
- const itemsLookup = registryItemsMap(pkgManifest);
5271
- const installedItems = Object.keys(components).map((slug) => itemsLookup[slug]).filter((item) => Boolean(item));
5272
- const { emitters } = collectInstalledSlotEmitters(
5273
- installedItems,
5274
- new Set(Object.keys(components)),
5275
- cwd
5276
- );
5277
- emitterSlotTypes = emitters.map((emitter) => emitter.type);
5278
- for (const type of emitterSlotTypes) slotTypes.add(type);
5279
- } else {
5280
- for (const slug of Object.keys(components)) slotTypes.add(slug);
5281
- }
5282
- const typesArray = Array.from(slotTypes).sort();
5283
- const slotImports = [];
5284
- const coreSlotsPath = path18.join(generatedSlotsDir(cwd), SLOT_GROUP_CORE_FILE);
5285
- const optionalSlotsPath = path18.join(generatedSlotsDir(cwd), SLOT_GROUP_OPTIONAL_FILE);
5286
- if (fs14.existsSync(coreSlotsPath)) slotImports.push(`import "./slots/${SLOT_GROUP_CORE_FILE.replace(/\.tsx$/, "")}";`);
5287
- if (fs14.existsSync(optionalSlotsPath)) slotImports.push(`import "./slots/${SLOT_GROUP_OPTIONAL_FILE.replace(/\.tsx$/, "")}";`);
5288
- const componentSlotImports = slotImports.join("\n");
5289
- const outDir = generatedIuiDir(cwd);
5290
- fs14.ensureDirSync(outDir);
5291
- const outPath = path18.join(outDir, "slot.generated.tsx");
5292
- const sections = [
5293
- `// Managed by iui. Do not edit manually.`,
5294
- `// Rebuilt automatically when the CLI validates the project.`
5295
- ];
5296
- if (componentSlotImports) {
5297
- sections.push("");
5298
- sections.push("// Component slot registrations");
5299
- sections.push(componentSlotImports);
5300
- }
5301
- sections.push("");
5302
- sections.push(`// Framework slot system \u2014 flag, icon, loader, etc. registrations run as side effects`);
5303
- sections.push(`// when @inventive-ui/framework is first imported. No explicit registration needed here.`);
5304
- sections.push(`import { SlotRenderer, useSlotRenderer } from "@inventive-ui/framework/slots";`);
5305
- sections.push(`import slotManifest from "../slots.json";`);
5306
- sections.push("");
5307
- sections.push(
5308
- typesArray.length > 0 ? `export type IUISlotType =
5309
- ${typesArray.map((t) => ` | "${t}"`).join("\n")};` : `export type IUISlotType = never;`
5310
- );
5311
- sections.push("");
5312
- sections.push(`export { SlotRenderer, useSlotRenderer };`);
5313
- sections.push("");
5314
- sections.push(`export const slots = slotManifest;`);
5315
- sections.push("");
5316
- const content = sections.join("\n");
5317
- safeWriteFile(outPath, content);
5318
- }
5319
- function writeSlotBridge(packageDir, iuiRoot2) {
5320
- const bridgePath = bridgeSlotFilePath(packageDir);
5321
- const generatedFile = path18.join(iuiRoot2, ".iui", "generated", "slot.generated.tsx");
5322
- const importBase = relativeImportPath(path18.dirname(bridgePath), generatedFile);
5323
- fs14.ensureDirSync(path18.dirname(bridgePath));
5324
- if (fs14.existsSync(bridgePath)) {
5325
- const existing = fs14.readFileSync(bridgePath, "utf-8");
5326
- if (existing.length > 0 && !/@iui-managed/.test(existing)) {
5327
- return;
5328
- }
5329
- }
5330
- const bridgeContent = `// Managed by iui. Do not edit manually.
5331
- // @iui-managed
5332
- // Compatibility bridge: keep project imports stable at src/iui/slot.tsx.
5333
-
5334
- export { SlotRenderer, useSlotRenderer, slots } from "${importBase}";
5335
- export type { IUISlotType } from "${importBase}";
5336
- `;
5337
- safeWriteFile(bridgePath, bridgeContent);
5338
- cleanupLegacySourceSlotFiles(packageDir);
5339
- }
5340
-
5341
- // src/services/workspace-bootstrap.ts
5342
- import path20 from "path";
5343
- import fs16 from "fs-extra";
5344
-
5345
4959
  // src/services/bootstrap.ts
5346
- import fs15 from "fs-extra";
5347
- import path19 from "path";
5348
4960
  var BOOTSTRAP_GENERATED_FILE = "bootstrap.generated.tsx";
5349
4961
  function bridgeBootstrapFilePath(cwd) {
5350
- return path19.join(cwd, "src", "iui", "bootstrap.ts");
4962
+ return path18.join(cwd, "src", "iui", "bootstrap.ts");
5351
4963
  }
5352
4964
  function bootstrapGeneratedPath(cwd = process.cwd()) {
5353
- return path19.join(generatedIuiDir(cwd), BOOTSTRAP_GENERATED_FILE);
4965
+ return path18.join(generatedIuiDir(cwd), BOOTSTRAP_GENERATED_FILE);
5354
4966
  }
5355
4967
  function resolveProjectConfigPaths(cwd) {
5356
4968
  const meta = readProjectMeta(cwd);
@@ -5365,8 +4977,8 @@ function resolveProjectConfigPaths(cwd) {
5365
4977
  };
5366
4978
  }
5367
4979
  function configImportFromGenerated(cwd, configRel) {
5368
- const generatedDir = path19.dirname(bootstrapGeneratedPath(cwd));
5369
- const abs = path19.resolve(cwd, configRel.replace(/^\.\//, ""));
4980
+ const generatedDir = path18.dirname(bootstrapGeneratedPath(cwd));
4981
+ const abs = path18.resolve(cwd, configRel.replace(/^\.\//, ""));
5370
4982
  return relativeImportPath(generatedDir, abs);
5371
4983
  }
5372
4984
  function expectedBootstrapImportPaths(cwd) {
@@ -5379,7 +4991,7 @@ function expectedBootstrapImportPaths(cwd) {
5379
4991
  }
5380
4992
  function writeBootstrapGenerated(cwd = process.cwd()) {
5381
4993
  const outPath = bootstrapGeneratedPath(cwd);
5382
- fs15.ensureDirSync(path19.dirname(outPath));
4994
+ fs14.ensureDirSync(path18.dirname(outPath));
5383
4995
  const imports = expectedBootstrapImportPaths(cwd);
5384
4996
  const content = `// @iui-managed
5385
4997
 
@@ -5411,10 +5023,6 @@ import type { IUIAssetsConfig } from "@inventive-ui/framework/config";
5411
5023
 
5412
5024
 
5413
5025
 
5414
- import "./slot.generated";
5415
-
5416
-
5417
-
5418
5026
  const themeConfig = (theme as { default?: typeof theme }).default ?? theme;
5419
5027
 
5420
5028
 
@@ -5453,10 +5061,10 @@ export { projectComponentConfig as componentConfig };
5453
5061
  function writeBootstrapBridge(packageDir, iuiRoot2) {
5454
5062
  const bridgePath = bridgeBootstrapFilePath(packageDir);
5455
5063
  const generatedFile = bootstrapGeneratedPath(iuiRoot2);
5456
- const importBase = relativeImportPath(path19.dirname(bridgePath), generatedFile);
5457
- fs15.ensureDirSync(path19.dirname(bridgePath));
5458
- if (fs15.existsSync(bridgePath)) {
5459
- const existing = fs15.readFileSync(bridgePath, "utf-8");
5064
+ const importBase = relativeImportPath(path18.dirname(bridgePath), generatedFile);
5065
+ fs14.ensureDirSync(path18.dirname(bridgePath));
5066
+ if (fs14.existsSync(bridgePath)) {
5067
+ const existing = fs14.readFileSync(bridgePath, "utf-8");
5460
5068
  if (existing.length > 0 && !/@iui-managed/.test(existing)) {
5461
5069
  return;
5462
5070
  }
@@ -5477,17 +5085,18 @@ import "${importBase}";
5477
5085
  function writeProjectBootstrapArtifacts(packageDir, iuiRoot2) {
5478
5086
  writeBootstrapGenerated(iuiRoot2);
5479
5087
  writeBootstrapBridge(packageDir, iuiRoot2);
5088
+ removeStaleComponentSlotOutput(iuiRoot2, [packageDir]);
5480
5089
  }
5481
5090
 
5482
5091
  // src/services/workspace-bootstrap.ts
5483
5092
  function workspaceManifestPath(iuiRoot2) {
5484
- return path20.join(iuiRoot2, IUI_DIR, "workspace.json");
5093
+ return path19.join(iuiRoot2, IUI_DIR, "workspace.json");
5485
5094
  }
5486
5095
  function readWorkspaceManifest(iuiRoot2) {
5487
5096
  const p = workspaceManifestPath(iuiRoot2);
5488
- if (!fs16.existsSync(p)) return null;
5097
+ if (!fs15.existsSync(p)) return null;
5489
5098
  try {
5490
- const raw = fs16.readJsonSync(p);
5099
+ const raw = fs15.readJsonSync(p);
5491
5100
  if (!Array.isArray(raw.packages)) return null;
5492
5101
  return {
5493
5102
  iuiRoot: raw.iuiRoot ?? iuiRoot2,
@@ -5499,40 +5108,45 @@ function readWorkspaceManifest(iuiRoot2) {
5499
5108
  }
5500
5109
  }
5501
5110
  function writeWorkspaceManifest(iuiRoot2, packageDirs) {
5502
- const unique = [...new Set(packageDirs.map((dir) => path20.resolve(dir)))];
5111
+ const unique = [...new Set(packageDirs.map((dir) => path19.resolve(dir)))];
5503
5112
  atomicWriteJson(workspaceManifestPath(iuiRoot2), {
5504
- packages: unique.map((dir) => path20.relative(iuiRoot2, dir) || "."),
5113
+ packages: unique.map((dir) => path19.relative(iuiRoot2, dir) || "."),
5505
5114
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
5506
5115
  });
5507
5116
  }
5508
5117
  function resolveRegisteredPackageDirs(iuiRoot2) {
5509
- const resolvedRoot = path20.resolve(iuiRoot2);
5118
+ const resolvedRoot = path19.resolve(iuiRoot2);
5510
5119
  const manifest = readWorkspaceManifest(resolvedRoot);
5511
5120
  if (!manifest) return [resolvedRoot];
5512
5121
  const dirs = manifest.packages.map(
5513
- (rel) => path20.resolve(resolvedRoot, rel === "." ? "" : rel)
5122
+ (rel) => path19.resolve(resolvedRoot, rel === "." ? "" : rel)
5514
5123
  );
5515
- if (!dirs.some((dir) => path20.resolve(dir) === resolvedRoot)) {
5124
+ if (!dirs.some((dir) => path19.resolve(dir) === resolvedRoot)) {
5516
5125
  dirs.unshift(resolvedRoot);
5517
5126
  }
5518
5127
  return dirs;
5519
5128
  }
5129
+ function registeredPackageDirs(iuiRoot2) {
5130
+ return resolveRegisteredPackageDirs(resolveIuiProjectRoot(iuiRoot2)).filter(
5131
+ (dir) => fs15.existsSync(path19.join(dir, "package.json"))
5132
+ );
5133
+ }
5520
5134
  function registerWorkspacePackage(iuiRoot2, packageDir) {
5521
- const resolvedRoot = path20.resolve(iuiRoot2);
5522
- const resolvedPackage = path20.resolve(packageDir);
5135
+ const resolvedRoot = path19.resolve(iuiRoot2);
5136
+ const resolvedPackage = path19.resolve(packageDir);
5523
5137
  const existing = resolveRegisteredPackageDirs(resolvedRoot);
5524
- if (!existing.some((dir) => path20.resolve(dir) === resolvedPackage)) {
5138
+ if (!existing.some((dir) => path19.resolve(dir) === resolvedPackage)) {
5525
5139
  existing.push(resolvedPackage);
5526
5140
  }
5527
5141
  writeWorkspaceManifest(resolvedRoot, existing);
5528
5142
  }
5529
5143
  function registerAllWorkspacePackages(iuiRoot2) {
5530
- const resolvedRoot = path20.resolve(iuiRoot2);
5144
+ const resolvedRoot = path19.resolve(iuiRoot2);
5531
5145
  const workspaceRoot = findWorkspaceRoot(resolvedRoot);
5532
5146
  const targets = /* @__PURE__ */ new Set([resolvedRoot]);
5533
5147
  if (workspaceRoot) {
5534
5148
  for (const pkgDir of listWorkspacePackageDirs(workspaceRoot)) {
5535
- targets.add(path20.resolve(pkgDir));
5149
+ targets.add(path19.resolve(pkgDir));
5536
5150
  }
5537
5151
  }
5538
5152
  const dirs = [...targets];
@@ -5543,18 +5157,17 @@ function bootstrapRegisteredPackages(iuiRoot2) {
5543
5157
  const resolvedRoot = resolveIuiProjectRoot(iuiRoot2);
5544
5158
  const bootstrapped = [];
5545
5159
  for (const packageDir of resolveRegisteredPackageDirs(resolvedRoot)) {
5546
- if (!fs16.existsSync(path20.join(packageDir, "package.json"))) continue;
5160
+ if (!fs15.existsSync(path19.join(packageDir, "package.json"))) continue;
5547
5161
  ensureProjectNpmrc(packageDir);
5548
- writeSlotBridge(packageDir, resolvedRoot);
5549
5162
  writeProjectBootstrapArtifacts(packageDir, resolvedRoot);
5550
5163
  bootstrapped.push(packageDir);
5551
5164
  }
5552
5165
  return bootstrapped;
5553
5166
  }
5554
5167
  async function bootstrapWorkspacePackage(packageDir, iuiRoot2) {
5555
- const resolvedPackage = path20.resolve(packageDir);
5168
+ const resolvedPackage = path19.resolve(packageDir);
5556
5169
  const resolvedIuiRoot = resolveIuiProjectRoot(iuiRoot2);
5557
- if (!fs16.existsSync(path20.join(resolvedPackage, "package.json"))) {
5170
+ if (!fs15.existsSync(path19.join(resolvedPackage, "package.json"))) {
5558
5171
  throw new CLIError(
5559
5172
  `No package.json found in ${resolvedPackage}.`,
5560
5173
  "Run iui init from a workspace app directory that contains package.json."
@@ -5567,7 +5180,7 @@ async function bootstrapWorkspacePackage(packageDir, iuiRoot2) {
5567
5180
  }
5568
5181
  registerWorkspacePackage(resolvedIuiRoot, resolvedPackage);
5569
5182
  bootstrapRegisteredPackages(resolvedIuiRoot);
5570
- ok("Slot bridge ready");
5183
+ ok("Bootstrap bridge ready");
5571
5184
  hint(
5572
5185
  "This app is linked to an existing IUI setup \u2014 packages and configs stay at the IUI root."
5573
5186
  );
@@ -5579,28 +5192,28 @@ async function bootstrapWorkspacePackage(packageDir, iuiRoot2) {
5579
5192
  }
5580
5193
 
5581
5194
  // src/services/slot-registry.ts
5582
- var STATE_SCHEMA_VERSION = 1;
5195
+ var STATE_SCHEMA_VERSION = 2;
5583
5196
  function statePath(cwd) {
5584
5197
  return iuiCacheFile(cwd, "slotState");
5585
5198
  }
5586
5199
  function now() {
5587
5200
  return (/* @__PURE__ */ new Date()).toISOString();
5588
5201
  }
5589
- function checksumFor(components, slots) {
5590
- return sha256(JSON.stringify({ components, slots }));
5202
+ function checksumFor(components, packages) {
5203
+ return sha256(JSON.stringify({ components, packages }));
5591
5204
  }
5592
5205
  function backupCorruptFile(filePath) {
5593
- if (!fs17.existsSync(filePath)) return;
5206
+ if (!fs16.existsSync(filePath)) return;
5594
5207
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
5595
5208
  try {
5596
- fs17.moveSync(filePath, `${filePath}.corrupt-${stamp}`, { overwrite: false });
5209
+ fs16.moveSync(filePath, `${filePath}.corrupt-${stamp}`, { overwrite: false });
5597
5210
  } catch {
5598
5211
  }
5599
5212
  }
5600
5213
  function readJsonObject(filePath, fallback, issues, label) {
5601
- if (!fs17.existsSync(filePath)) return fallback;
5214
+ if (!fs16.existsSync(filePath)) return fallback;
5602
5215
  try {
5603
- const value = fs17.readJsonSync(filePath);
5216
+ const value = fs16.readJsonSync(filePath);
5604
5217
  if (value && typeof value === "object" && !Array.isArray(value)) {
5605
5218
  return value;
5606
5219
  }
@@ -5612,9 +5225,9 @@ function readJsonObject(filePath, fallback, issues, label) {
5612
5225
  }
5613
5226
  function readState(cwd, issues) {
5614
5227
  const filePath = statePath(cwd);
5615
- if (!fs17.existsSync(filePath)) return null;
5228
+ if (!fs16.existsSync(filePath)) return null;
5616
5229
  try {
5617
- const raw = fs17.readJsonSync(filePath);
5230
+ const raw = fs16.readJsonSync(filePath);
5618
5231
  if (raw.schemaVersion !== STATE_SCHEMA_VERSION) {
5619
5232
  issues.push("registration state schema was upgraded");
5620
5233
  return null;
@@ -5643,37 +5256,15 @@ function updateState(cwd, state, phase, patch = {}) {
5643
5256
  writeState(cwd, next);
5644
5257
  return next;
5645
5258
  }
5646
- function buildDesiredState(registry, packageVersion, currentSlots, packages) {
5259
+ function buildDesiredComponents(registry, packageVersion) {
5647
5260
  const components = {};
5648
- const slots = {};
5649
- const timestamp = now();
5650
5261
  for (const item of registry.items) {
5651
5262
  components[item.name] = packageVersion;
5652
- slots[item.name] = {
5653
- component: item.name,
5654
- slotType: "component",
5655
- registeredAt: currentSlots[item.name]?.registeredAt ?? timestamp,
5656
- version: packageVersion
5657
- };
5658
- if (item.slots.length > 0) {
5659
- slots[item.name].supportedSlots = [...item.slots].sort();
5660
- }
5661
- }
5662
- for (const [packageId, meta] of Object.entries(packages)) {
5663
- const def = ASSET_PACKAGES_MAP[packageId];
5664
- if (!def) continue;
5665
- const key = `asset:${packageId}`;
5666
- slots[key] = {
5667
- component: packageId,
5668
- slotType: def.slotType,
5669
- registeredAt: currentSlots[key]?.registeredAt ?? timestamp,
5670
- version: meta.version
5671
- };
5672
5263
  }
5673
- return { components, slots };
5264
+ return components;
5674
5265
  }
5675
- function hasManifestDrift(currentComponents, currentSlots, desiredComponents, desiredSlots) {
5676
- return JSON.stringify(currentComponents) !== JSON.stringify(desiredComponents) || JSON.stringify(currentSlots) !== JSON.stringify(desiredSlots);
5266
+ function hasManifestDrift(currentComponents, desiredComponents) {
5267
+ return JSON.stringify(currentComponents) !== JSON.stringify(desiredComponents);
5677
5268
  }
5678
5269
  function shouldSkipWritesFastPath(params) {
5679
5270
  const {
@@ -5718,7 +5309,7 @@ async function ensureSlotRegistry(options = {}) {
5718
5309
  }
5719
5310
  const iuiRoot2 = resolveIuiProjectRoot(cwd);
5720
5311
  return withRegistryLock(iuiRoot2, async () => {
5721
- const iuiPath = path21.join(iuiRoot2, IUI_DIR);
5312
+ const iuiPath = path20.join(iuiRoot2, IUI_DIR);
5722
5313
  const issues = [];
5723
5314
  cleanupTempFiles(iuiPath);
5724
5315
  const registry = ensureInstalledManifest(
@@ -5744,35 +5335,25 @@ async function ensureSlotRegistry(options = {}) {
5744
5335
  issues,
5745
5336
  ".iui/packages.json"
5746
5337
  );
5747
- const currentSlots = readJsonObject(
5748
- slotManifestPath(iuiRoot2),
5749
- {},
5750
- issues,
5751
- ".iui/slots.json"
5752
- );
5753
- const desired = buildDesiredState(
5754
- registry,
5755
- packageVersion,
5756
- currentSlots,
5757
- currentPackages
5758
- );
5759
- const checksum = checksumFor(desired.components, desired.slots);
5338
+ const desiredComponents = buildDesiredComponents(registry, packageVersion);
5339
+ const checksum = checksumFor(desiredComponents, currentPackages);
5760
5340
  if (previousState?.status === "running" || previousState?.status === "failed") {
5761
5341
  issues.push("interrupted registration was resumed");
5762
5342
  }
5763
5343
  if (previousState?.checksum && previousState.checksum !== checksum) {
5764
- issues.push("slot registry checksum changed");
5344
+ issues.push("registry checksum changed");
5765
5345
  }
5766
- const driftDetected = hasManifestDrift(
5767
- currentComponents,
5768
- currentSlots,
5769
- desired.components,
5770
- desired.slots
5771
- );
5346
+ const driftDetected = hasManifestDrift(currentComponents, desiredComponents);
5772
5347
  if (driftDetected) {
5773
- issues.push("slot manifests drifted");
5348
+ issues.push("component manifest drifted");
5774
5349
  }
5775
- const integrityIssues = validateGeneratedSlotImports(iuiRoot2);
5350
+ const staleSlotOutput = findStaleComponentSlotOutput(
5351
+ iuiRoot2,
5352
+ registeredPackageDirs(iuiRoot2)
5353
+ );
5354
+ const integrityIssues = staleSlotOutput.map(
5355
+ (file) => `stale component-slot output: ${path20.relative(iuiRoot2, file) || file}`
5356
+ );
5776
5357
  if (shouldSkipWritesFastPath({
5777
5358
  mode,
5778
5359
  previousState,
@@ -5790,8 +5371,8 @@ async function ensureSlotRegistry(options = {}) {
5790
5371
  if (mode === "validate") {
5791
5372
  if (integrityIssues.length > 0) {
5792
5373
  throw new CLIError(
5793
- "Slot registry integrity check failed.",
5794
- integrityIssues.map((issue) => `- ${issue}`).join("\n")
5374
+ "Stale component-slot files from an older iui version were found.",
5375
+ "Run iui doctor --fix (or iui update) to regenerate .iui/generated and remove them."
5795
5376
  );
5796
5377
  }
5797
5378
  return {
@@ -5814,31 +5395,32 @@ async function ensureSlotRegistry(options = {}) {
5814
5395
  writeState(iuiRoot2, state);
5815
5396
  updateState(iuiRoot2, state, "state-loaded");
5816
5397
  await retry(() => {
5817
- writeComponentManifest(desired.components, iuiRoot2);
5398
+ writeComponentManifest(desiredComponents, iuiRoot2);
5818
5399
  writePackageManifest(currentPackages, iuiRoot2);
5819
- writeSlotManifest(desired.slots, iuiRoot2);
5820
5400
  });
5821
5401
  let next = updateState(iuiRoot2, state, "manifests-written", {
5822
5402
  checksum,
5823
5403
  repairedIssues: issues
5824
5404
  });
5825
5405
  await retry(async () => {
5826
- writeComponentSlotFiles(iuiRoot2);
5827
5406
  writeAssetsConfig(iuiRoot2);
5828
5407
  ensureProjectConfig(iuiRoot2);
5829
- writeSlotHelperFile(iuiRoot2);
5830
5408
  if (projectHasViteTooling(cwd)) {
5831
5409
  ensureInventiveUiViteConfig(cwd);
5832
5410
  }
5833
5411
  });
5834
5412
  bootstrapRegisteredPackages(iuiRoot2);
5835
- next = updateState(iuiRoot2, next, "slot-files-written", { repairedIssues: issues });
5836
- if (integrityIssues.length > 0) {
5413
+ next = updateState(iuiRoot2, next, "generated-files-written", { repairedIssues: issues });
5414
+ const leftover = findStaleComponentSlotOutput(iuiRoot2, registeredPackageDirs(iuiRoot2));
5415
+ if (leftover.length > 0) {
5837
5416
  throw new CLIError(
5838
- "Slot registry integrity check failed.",
5839
- integrityIssues.map((issue) => `- ${issue}`).join("\n")
5417
+ "Could not remove stale component-slot output.",
5418
+ leftover.map((file) => `- ${path20.relative(iuiRoot2, file) || file}`).join("\n")
5840
5419
  );
5841
5420
  }
5421
+ if (integrityIssues.length > 0) {
5422
+ issues.push(...integrityIssues.map((issue) => `removed ${issue}`));
5423
+ }
5842
5424
  next = updateState(iuiRoot2, next, "integrity-verified", { repairedIssues: issues });
5843
5425
  updateState(iuiRoot2, next, "complete", {
5844
5426
  status: "complete",
@@ -5847,7 +5429,7 @@ async function ensureSlotRegistry(options = {}) {
5847
5429
  repairedIssues: issues
5848
5430
  });
5849
5431
  if (!options.quiet && issues.length > 0) {
5850
- ok("Slot registry repaired");
5432
+ ok("Project registry repaired");
5851
5433
  }
5852
5434
  return {
5853
5435
  status: issues.length > 0 ? "repaired" : "valid",
@@ -5855,7 +5437,7 @@ async function ensureSlotRegistry(options = {}) {
5855
5437
  repairedIssues: issues
5856
5438
  };
5857
5439
  } catch (error) {
5858
- const message = error instanceof Error ? error.message : "Slot registry update failed";
5440
+ const message = error instanceof Error ? error.message : "Project registry update failed";
5859
5441
  if (state) {
5860
5442
  updateState(iuiRoot2, state, "state-loaded", {
5861
5443
  status: "failed",
@@ -5929,15 +5511,15 @@ async function installComponentsPackage(opts) {
5929
5511
  mode: "repair"
5930
5512
  });
5931
5513
  if (result.status === "skipped") {
5932
- warn("Component slot registry was not generated.");
5514
+ warn("Component registry was not generated.");
5933
5515
  hint(
5934
5516
  "Run iui init in this package (or iui doctor). Hoisted node_modules are supported \u2014 a root-level install is not required."
5935
5517
  );
5936
5518
  } else {
5937
5519
  ok(
5938
- result.status === "repaired" ? `Component slots repaired for ${COMPONENTS_PACKAGE} ${dim(`v${pkgVersion}`)}` : `Component slots ready for ${COMPONENTS_PACKAGE} ${dim(`v${pkgVersion}`)}`
5520
+ result.status === "repaired" ? `Components registry repaired for ${COMPONENTS_PACKAGE} ${dim(`v${pkgVersion}`)}` : `Components ready for ${COMPONENTS_PACKAGE} ${dim(`v${pkgVersion}`)}`
5939
5521
  );
5940
- hint('Import components from "@inventive-ui/components"; slots are available automatically.');
5522
+ hint('Import components from "@inventive-ui/components".');
5941
5523
  }
5942
5524
  return { previousVersion, version: pkgVersion };
5943
5525
  }
@@ -6010,7 +5592,7 @@ async function initCommand(opts) {
6010
5592
  try {
6011
5593
  heading("Initialize Project");
6012
5594
  const existingIuiRoot = findIuiProjectRoot(invocationCwd);
6013
- if (existingIuiRoot && path22.resolve(existingIuiRoot) !== path22.resolve(invocationCwd)) {
5595
+ if (existingIuiRoot && path21.resolve(existingIuiRoot) !== path21.resolve(invocationCwd)) {
6014
5596
  await bootstrapWorkspacePackage(invocationCwd, existingIuiRoot);
6015
5597
  return;
6016
5598
  }
@@ -6029,10 +5611,10 @@ async function initCommand(opts) {
6029
5611
  return;
6030
5612
  }
6031
5613
  const originalCwd = process.cwd();
6032
- if (path22.resolve(initRoot) !== path22.resolve(originalCwd)) {
5614
+ if (path21.resolve(initRoot) !== path21.resolve(originalCwd)) {
6033
5615
  process.chdir(initRoot);
6034
5616
  hint(
6035
- `Monorepo --workspace: initializing at ${path22.relative(invocationCwd, initRoot) || initRoot}`
5617
+ `Monorepo --workspace: initializing at ${path21.relative(invocationCwd, initRoot) || initRoot}`
6036
5618
  );
6037
5619
  } else if (!sharedWorkspace && findIuiProjectRoot(initRoot) === null) {
6038
5620
  hint("Initializing this package only \u2014 other monorepo apps are untouched.");
@@ -6915,17 +6497,17 @@ async function deployTokenRevokeCommand(tokenId) {
6915
6497
  }
6916
6498
 
6917
6499
  // src/commands/setup.ts
6918
- import path25 from "path";
6919
- import fs19 from "fs-extra";
6500
+ import path24 from "path";
6501
+ import fs18 from "fs-extra";
6920
6502
  import ora6 from "ora";
6921
6503
 
6922
6504
  // src/commands/doctor.ts
6923
- import path24 from "path";
6505
+ import path23 from "path";
6924
6506
 
6925
6507
  // src/services/health.ts
6926
6508
  import { execFileSync as execFileSync2 } from "child_process";
6927
- import path23 from "path";
6928
- import fs18 from "fs-extra";
6509
+ import path22 from "path";
6510
+ import fs17 from "fs-extra";
6929
6511
  function installDevTypeScript(cwd) {
6930
6512
  const pm = detectPackageManager(cwd);
6931
6513
  try {
@@ -6953,23 +6535,24 @@ function checkPackageCompatibility(cwd = process.cwd()) {
6953
6535
  summary: `Core packages installed (framework ${frameworkVersion}, components ${componentsVersion})`
6954
6536
  };
6955
6537
  }
6956
- function checkGeneratedSlotValidity(cwd = process.cwd()) {
6957
- const issues = validateGeneratedSlotImports(cwd);
6958
- if (issues.length > 0) {
6538
+ function checkStaleComponentSlotOutput(cwd = process.cwd()) {
6539
+ const iuiRoot2 = resolveIuiProjectRoot(cwd);
6540
+ const stale = findStaleComponentSlotOutput(iuiRoot2, [cwd]);
6541
+ if (stale.length > 0) {
6959
6542
  return {
6960
6543
  ok: false,
6961
- summary: "Managed slot imports are invalid",
6962
- details: issues.map((i) => `- ${i}`).join("\n")
6544
+ summary: `${stale.length} stale component-slot file${stale.length === 1 ? "" : "s"} from an older iui version`,
6545
+ details: stale.slice(0, 8).map((file) => `- ${path22.relative(iuiRoot2, file) || file}`).join("\n")
6963
6546
  };
6964
6547
  }
6965
6548
  return {
6966
6549
  ok: true,
6967
- summary: "Managed slot imports are valid"
6550
+ summary: "No stale component-slot output"
6968
6551
  };
6969
6552
  }
6970
6553
  function checkComponentConfigValidity(cwd = process.cwd(), options = {}) {
6971
- const configPath = path23.join(cwd, COMPONENT_CONFIG_FILE);
6972
- if (!fs18.existsSync(configPath)) {
6554
+ const configPath = path22.join(cwd, COMPONENT_CONFIG_FILE);
6555
+ if (!fs17.existsSync(configPath)) {
6973
6556
  return {
6974
6557
  ok: false,
6975
6558
  summary: "component.config.ts not found",
@@ -6977,8 +6560,8 @@ function checkComponentConfigValidity(cwd = process.cwd(), options = {}) {
6977
6560
  };
6978
6561
  }
6979
6562
  const tsPkgDir = resolvePackageDir("typescript", cwd);
6980
- const tscPath = tsPkgDir ? path23.join(tsPkgDir, "bin", "tsc") : path23.join(cwd, "node_modules", "typescript", "bin", "tsc");
6981
- if (!fs18.existsSync(tscPath)) {
6563
+ const tscPath = tsPkgDir ? path22.join(tsPkgDir, "bin", "tsc") : path22.join(cwd, "node_modules", "typescript", "bin", "tsc");
6564
+ if (!fs17.existsSync(tscPath)) {
6982
6565
  if (!options.autoFix) {
6983
6566
  return {
6984
6567
  ok: false,
@@ -7046,12 +6629,12 @@ ${stderr}`.trim() };
7046
6629
  function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7047
6630
  const warnings = [];
7048
6631
  const hints = [];
7049
- const configPath = path23.join(
6632
+ const configPath = path22.join(
7050
6633
  cwd,
7051
- fs18.existsSync(path23.join(cwd, PROJECT_CONFIG_FILE)) || !fs18.existsSync(path23.join(cwd, "iui.config.ts")) ? PROJECT_CONFIG_FILE : "iui.config.ts"
6634
+ fs17.existsSync(path22.join(cwd, PROJECT_CONFIG_FILE)) || !fs17.existsSync(path22.join(cwd, "iui.config.ts")) ? PROJECT_CONFIG_FILE : "iui.config.ts"
7052
6635
  );
7053
- if (fs18.existsSync(configPath)) {
7054
- const configContent = fs18.readFileSync(configPath, "utf-8");
6636
+ if (fs17.existsSync(configPath)) {
6637
+ const configContent = fs17.readFileSync(configPath, "utf-8");
7055
6638
  if (/packageSafelist\s*:\s*false/.test(configContent)) {
7056
6639
  warnings.push(
7057
6640
  "Deprecated theme.config build.packageSafelist \u2014 remove it; Framework always merges IUI package compile contracts"
@@ -7071,11 +6654,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7071
6654
  }
7072
6655
  if (projectHasViteTooling(cwd)) {
7073
6656
  const viteCandidates = ["vite.config.ts", "vite.config.mjs", "vite.config.js"];
7074
- const vitePath = viteCandidates.map((name) => path23.join(cwd, name)).find((p) => fs18.existsSync(p));
6657
+ const vitePath = viteCandidates.map((name) => path22.join(cwd, name)).find((p) => fs17.existsSync(p));
7075
6658
  if (!vitePath) {
7076
6659
  warnings.push("Vite tooling detected but no vite.config.* found");
7077
6660
  } else {
7078
- const viteContent = fs18.readFileSync(vitePath, "utf-8");
6661
+ const viteContent = fs17.readFileSync(vitePath, "utf-8");
7079
6662
  if (!/inventiveUiVite\s*\(/.test(viteContent)) {
7080
6663
  warnings.push("vite.config is missing inventiveUiVite() \u2014 compile-first CSS will not generate");
7081
6664
  hints.push("Wire plugins: [...inventiveUiVite({ root: import.meta.dirname }), react()]");
@@ -7089,11 +6672,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7089
6672
  "webpack.config.mjs",
7090
6673
  "webpack.config.ts"
7091
6674
  ];
7092
- const webpackPath = webpackCandidates.map((name) => path23.join(cwd, name)).find((p) => fs18.existsSync(p));
6675
+ const webpackPath = webpackCandidates.map((name) => path22.join(cwd, name)).find((p) => fs17.existsSync(p));
7093
6676
  if (!webpackPath) {
7094
6677
  warnings.push("Webpack tooling detected but no webpack.config.* found");
7095
6678
  } else {
7096
- const webpackContent = fs18.readFileSync(webpackPath, "utf-8");
6679
+ const webpackContent = fs17.readFileSync(webpackPath, "utf-8");
7097
6680
  if (!/inventiveUiWebpack\s*\(/.test(webpackContent)) {
7098
6681
  warnings.push("webpack.config is missing inventiveUiWebpack() \u2014 compile-first CSS will not generate");
7099
6682
  hints.push('Wire plugins: [...inventiveUiWebpack()] from "@inventive-ui/framework/webpack"');
@@ -7103,11 +6686,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7103
6686
  }
7104
6687
  if (projectHasNextTooling(cwd)) {
7105
6688
  const nextCandidates = ["next.config.ts", "next.config.mjs", "next.config.js", "next.config.cjs"];
7106
- const nextPath = nextCandidates.map((name) => path23.join(cwd, name)).find((p) => fs18.existsSync(p));
6689
+ const nextPath = nextCandidates.map((name) => path22.join(cwd, name)).find((p) => fs17.existsSync(p));
7107
6690
  if (!nextPath) {
7108
6691
  warnings.push("Next.js detected but no next.config.* found");
7109
6692
  } else {
7110
- const nextContent = fs18.readFileSync(nextPath, "utf-8");
6693
+ const nextContent = fs17.readFileSync(nextPath, "utf-8");
7111
6694
  if (!/withIUI\s*\(/.test(nextContent)) {
7112
6695
  warnings.push("next.config is missing withIUI() \u2014 compile-first CSS will not generate");
7113
6696
  hints.push('Wrap config: export default withIUI({ ... }) from "@inventive-ui/framework/next"');
@@ -7120,18 +6703,18 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7120
6703
  "src/app/layout.jsx",
7121
6704
  "app/providers.tsx",
7122
6705
  "src/app/providers.tsx"
7123
- ].map((rel) => path23.join(cwd, rel));
7124
- const readableLayouts = layoutCandidates.filter((file) => fs18.existsSync(file));
6706
+ ].map((rel) => path22.join(cwd, rel));
6707
+ const readableLayouts = layoutCandidates.filter((file) => fs17.existsSync(file));
7125
6708
  const hasRegistry = readableLayouts.some((file) => {
7126
6709
  try {
7127
- return /\bIUIRegistry\b/.test(fs18.readFileSync(file, "utf-8"));
6710
+ return /\bIUIRegistry\b/.test(fs17.readFileSync(file, "utf-8"));
7128
6711
  } catch {
7129
6712
  return false;
7130
6713
  }
7131
6714
  });
7132
6715
  const hasBootstrapImport = readableLayouts.some((file) => {
7133
6716
  try {
7134
- const content = fs18.readFileSync(file, "utf-8");
6717
+ const content = fs17.readFileSync(file, "utf-8");
7135
6718
  return /next\/bootstrap/.test(content) || /["']iui-bootstrap["']/.test(content) || /iui\/bootstrap/.test(content);
7136
6719
  } catch {
7137
6720
  return false;
@@ -7139,7 +6722,7 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7139
6722
  });
7140
6723
  const hasProvider = readableLayouts.some((file) => {
7141
6724
  try {
7142
- return /\bIUIProvider\b/.test(fs18.readFileSync(file, "utf-8"));
6725
+ return /\bIUIProvider\b/.test(fs17.readFileSync(file, "utf-8"));
7143
6726
  } catch {
7144
6727
  return false;
7145
6728
  }
@@ -7170,14 +6753,14 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7170
6753
  "src/app/providers.tsx",
7171
6754
  "app/layout.tsx",
7172
6755
  "src/app/layout.tsx"
7173
- ].map((rel) => path23.join(cwd, rel));
6756
+ ].map((rel) => path22.join(cwd, rel));
7174
6757
  for (const file of entryCandidates) {
7175
- if (!fs18.existsSync(file)) continue;
6758
+ if (!fs17.existsSync(file)) continue;
7176
6759
  try {
7177
- const content = fs18.readFileSync(file, "utf-8");
6760
+ const content = fs17.readFileSync(file, "utf-8");
7178
6761
  if (/from\s+['"][^'"]*\.generated['"]/.test(content) || /import\s+['"][^'"]*\.generated['"]/.test(content)) {
7179
6762
  warnings.push(
7180
- `Do not import .generated style-map files into the browser (${path23.relative(cwd, file)})`
6763
+ `Do not import .generated style-map files into the browser (${path22.relative(cwd, file)})`
7181
6764
  );
7182
6765
  hints.push(
7183
6766
  "Keep style maps on the scanner path (default src + .iui/generated, or override build.scanDirs) \u2014 see Framework compile-first docs"
@@ -7197,9 +6780,9 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7197
6780
  hints.push(
7198
6781
  "Compile-first: avoid dynamic utility templates like `p-${n}` \u2014 use static strings, style maps, or safelist (ESLint: customPlugin/no-dynamic-utility-class)"
7199
6782
  );
7200
- const giPath = path23.join(cwd, ".gitignore");
7201
- if (fs18.existsSync(giPath)) {
7202
- const gi = fs18.readFileSync(giPath, "utf-8");
6783
+ const giPath = path22.join(cwd, ".gitignore");
6784
+ if (fs17.existsSync(giPath)) {
6785
+ const gi = fs17.readFileSync(giPath, "utf-8");
7203
6786
  if (!gi.includes(".iui/cache/")) {
7204
6787
  warnings.push(".gitignore missing IUI cache directory (.iui/cache/)");
7205
6788
  hints.push("Run iui init or append .iui/cache/ from the IUI docs");
@@ -7210,11 +6793,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7210
6793
  function checkMetadataPortability(cwd = process.cwd()) {
7211
6794
  const warnings = [];
7212
6795
  const hints = [];
7213
- const iuiPath = path23.join(cwd, IUI_DIR);
7214
- const projectPath = path23.join(iuiPath, "project.json");
7215
- if (fs18.existsSync(projectPath)) {
6796
+ const iuiPath = path22.join(cwd, IUI_DIR);
6797
+ const projectPath = path22.join(iuiPath, "project.json");
6798
+ if (fs17.existsSync(projectPath)) {
7216
6799
  try {
7217
- const meta = fs18.readJsonSync(projectPath);
6800
+ const meta = fs17.readJsonSync(projectPath);
7218
6801
  const repoUrl = meta.repoUrl ?? "";
7219
6802
  if (/^[A-Za-z]:[\\/]/.test(repoUrl) || repoUrl.startsWith("/") && !repoUrl.startsWith("//") || repoUrl.startsWith("file:")) {
7220
6803
  warnings.push("project.json repoUrl is a local filesystem path \u2014 use a git remote URL");
@@ -7223,15 +6806,15 @@ function checkMetadataPortability(cwd = process.cwd()) {
7223
6806
  } catch {
7224
6807
  }
7225
6808
  }
7226
- const workspacePath = path23.join(iuiPath, "workspace.json");
7227
- if (fs18.existsSync(workspacePath)) {
6809
+ const workspacePath = path22.join(iuiPath, "workspace.json");
6810
+ if (fs17.existsSync(workspacePath)) {
7228
6811
  try {
7229
- const ws = fs18.readJsonSync(workspacePath);
6812
+ const ws = fs17.readJsonSync(workspacePath);
7230
6813
  if (ws.iuiRoot) {
7231
6814
  warnings.push("workspace.json contains deprecated iuiRoot \u2014 remove it (root is implicit)");
7232
6815
  }
7233
6816
  for (const pkg of ws.packages ?? []) {
7234
- if (/^[A-Za-z]:[\\/]/.test(pkg) || path23.isAbsolute(pkg)) {
6817
+ if (/^[A-Za-z]:[\\/]/.test(pkg) || path22.isAbsolute(pkg)) {
7235
6818
  warnings.push(`workspace.json packages entry is absolute: ${pkg}`);
7236
6819
  hints.push("packages should be relative paths from the IUI root");
7237
6820
  }
@@ -7240,9 +6823,9 @@ function checkMetadataPortability(cwd = process.cwd()) {
7240
6823
  }
7241
6824
  }
7242
6825
  const scanCachePath = iuiCacheFile(cwd, "scan");
7243
- if (fs18.existsSync(scanCachePath)) {
6826
+ if (fs17.existsSync(scanCachePath)) {
7244
6827
  try {
7245
- const cache = fs18.readJsonSync(scanCachePath);
6828
+ const cache = fs17.readJsonSync(scanCachePath);
7246
6829
  const absoluteKeys = Object.keys(cache.files ?? {}).filter(
7247
6830
  (key) => /^[A-Za-z]:[\\/]/.test(key) || key.startsWith("/") && !key.startsWith("//")
7248
6831
  );
@@ -7267,20 +6850,20 @@ var ICON_LIBRARY_PACKAGES = {
7267
6850
  phosphor: "icons-phosphor"
7268
6851
  };
7269
6852
  function checkAssetPipeline(cwd = process.cwd()) {
7270
- const assetsPath = path23.join(cwd, ASSETS_CONFIG_FILE);
7271
- if (!fs18.existsSync(assetsPath)) {
6853
+ const assetsPath = path22.join(cwd, ASSETS_CONFIG_FILE);
6854
+ if (!fs17.existsSync(assetsPath)) {
7272
6855
  return { ok: true, summary: "Asset check skipped (no assets.config.json)" };
7273
6856
  }
7274
6857
  let assets2;
7275
6858
  try {
7276
- assets2 = fs18.readJsonSync(assetsPath);
6859
+ assets2 = fs17.readJsonSync(assetsPath);
7277
6860
  } catch {
7278
6861
  return { ok: false, summary: "assets.config.json is not valid JSON" };
7279
6862
  }
7280
- const packagesDir = path23.join(cwd, "node_modules", "@inventive-ui");
7281
- const frameworkPkg = path23.join(packagesDir, "framework", "package.json");
7282
- if (fs18.existsSync(frameworkPkg)) {
7283
- const framework = fs18.readJsonSync(frameworkPkg);
6863
+ const packagesDir = path22.join(cwd, "node_modules", "@inventive-ui");
6864
+ const frameworkPkg = path22.join(packagesDir, "framework", "package.json");
6865
+ if (fs17.existsSync(frameworkPkg)) {
6866
+ const framework = fs17.readJsonSync(frameworkPkg);
7284
6867
  if (!framework.exports?.["./assets"]) {
7285
6868
  return {
7286
6869
  ok: false,
@@ -7292,8 +6875,8 @@ function checkAssetPipeline(cwd = process.cwd()) {
7292
6875
  const library = assets2.icon?.library;
7293
6876
  const pkg = library ? ICON_LIBRARY_PACKAGES[library] : void 0;
7294
6877
  if (!pkg) return { ok: true, summary: "Asset config valid" };
7295
- const iconsDir = path23.join(packagesDir, pkg, "dist", "icons");
7296
- if (!fs18.existsSync(iconsDir)) {
6878
+ const iconsDir = path22.join(packagesDir, pkg, "dist", "icons");
6879
+ if (!fs17.existsSync(iconsDir)) {
7297
6880
  return {
7298
6881
  ok: false,
7299
6882
  summary: `Icon library "${library}" is configured but @inventive-ui/${pkg} is not installed`,
@@ -7305,7 +6888,7 @@ function checkAssetPipeline(cwd = process.cwd()) {
7305
6888
  ["placeholder", assets2.icon?.placeholder?.name],
7306
6889
  ["fallback", assets2.icon?.fallback]
7307
6890
  ].filter((entry) => typeof entry[1] === "string" && entry[1].length > 0);
7308
- const missing = glyphs.filter(([, glyph]) => !fs18.existsSync(path23.join(iconsDir, `${glyph}.js`)));
6891
+ const missing = glyphs.filter(([, glyph]) => !fs17.existsSync(path22.join(iconsDir, `${glyph}.js`)));
7309
6892
  if (missing.length > 0) {
7310
6893
  return {
7311
6894
  ok: false,
@@ -7318,11 +6901,11 @@ function checkAssetPipeline(cwd = process.cwd()) {
7318
6901
  function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7319
6902
  const iuiRoot2 = resolveIuiProjectRoot(cwd);
7320
6903
  const generatedPath = bootstrapGeneratedPath(iuiRoot2);
7321
- const bridgePath = path23.join(cwd, "src", "iui", "bootstrap.ts");
7322
- if (!fs18.existsSync(generatedPath)) {
6904
+ const bridgePath = path22.join(cwd, "src", "iui", "bootstrap.ts");
6905
+ if (!fs17.existsSync(generatedPath)) {
7323
6906
  if (options.autoFix) {
7324
6907
  writeProjectBootstrapArtifacts(cwd, iuiRoot2);
7325
- if (fs18.existsSync(generatedPath)) {
6908
+ if (fs17.existsSync(generatedPath)) {
7326
6909
  return { ok: true, summary: "Generated bootstrap artifacts repaired" };
7327
6910
  }
7328
6911
  }
@@ -7332,10 +6915,10 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7332
6915
  details: "Expected .iui/generated/bootstrap.generated.tsx \u2014 run iui doctor --fix."
7333
6916
  };
7334
6917
  }
7335
- if (!fs18.existsSync(bridgePath)) {
6918
+ if (!fs17.existsSync(bridgePath)) {
7336
6919
  if (options.autoFix) {
7337
6920
  writeProjectBootstrapArtifacts(cwd, iuiRoot2);
7338
- if (fs18.existsSync(bridgePath)) {
6921
+ if (fs17.existsSync(bridgePath)) {
7339
6922
  return { ok: true, summary: "Bootstrap bridge repaired" };
7340
6923
  }
7341
6924
  }
@@ -7348,8 +6931,8 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7348
6931
  const configs = resolveProjectConfigPaths(iuiRoot2);
7349
6932
  const missing = [];
7350
6933
  for (const [key, rel] of Object.entries(configs)) {
7351
- const abs = path23.resolve(iuiRoot2, rel.replace(/^\.\//, ""));
7352
- if (!fs18.existsSync(abs)) missing.push(`${key}: ${rel}`);
6934
+ const abs = path22.resolve(iuiRoot2, rel.replace(/^\.\//, ""));
6935
+ if (!fs17.existsSync(abs)) missing.push(`${key}: ${rel}`);
7353
6936
  }
7354
6937
  if (missing.length > 0) {
7355
6938
  return {
@@ -7359,8 +6942,11 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7359
6942
  };
7360
6943
  }
7361
6944
  const expected = expectedBootstrapImportPaths(iuiRoot2);
7362
- const generated = fs18.readFileSync(generatedPath, "utf8");
6945
+ const generated = fs17.readFileSync(generatedPath, "utf8");
7363
6946
  const stale = [];
6947
+ if (/["']\.\/slot\.generated["']|@inventive-ui\/framework\/slots/.test(generated)) {
6948
+ stale.push("bootstrap still imports removed component-slot output");
6949
+ }
7364
6950
  for (const [key, importPath] of Object.entries(expected)) {
7365
6951
  if (!generated.includes(`"${importPath}"`)) {
7366
6952
  stale.push(`${key} import should be "${importPath}"`);
@@ -7369,11 +6955,11 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7369
6955
  if (stale.length > 0) {
7370
6956
  if (options.autoFix) {
7371
6957
  writeProjectBootstrapArtifacts(cwd, iuiRoot2);
7372
- const refreshed = fs18.readFileSync(bootstrapGeneratedPath(iuiRoot2), "utf8");
6958
+ const refreshed = fs17.readFileSync(bootstrapGeneratedPath(iuiRoot2), "utf8");
7373
6959
  const stillStale = Object.entries(expected).filter(
7374
6960
  ([, importPath]) => !refreshed.includes(`"${importPath}"`)
7375
6961
  );
7376
- if (stillStale.length === 0) {
6962
+ if (stillStale.length === 0 && !/slot\.generated/.test(refreshed)) {
7377
6963
  return { ok: true, summary: "Generated bootstrap refreshed from project.json" };
7378
6964
  }
7379
6965
  }
@@ -7387,6 +6973,24 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7387
6973
  }
7388
6974
 
7389
6975
  // src/commands/doctor.ts
6976
+ function repairStaleSlotOutput(targetCwd) {
6977
+ if (!isInsideProject(targetCwd)) return;
6978
+ writeProjectBootstrapArtifacts(targetCwd, resolveIuiProjectRoot(targetCwd));
6979
+ }
6980
+ function reportStaleSlotOutput(targetCwd, pass, fail2) {
6981
+ const staleSlots = checkStaleComponentSlotOutput(targetCwd);
6982
+ if (staleSlots.ok) {
6983
+ pass(staleSlots.summary);
6984
+ return;
6985
+ }
6986
+ fail2(staleSlots.summary);
6987
+ if (staleSlots.details) {
6988
+ for (const line of staleSlots.details.split("\n")) {
6989
+ hint(line);
6990
+ }
6991
+ }
6992
+ hint("Fix: run iui doctor --fix to remove it and regenerate bootstrap");
6993
+ }
7390
6994
  async function runConfigTierDiagnostics(targetCwd, opts, counters, options = {}) {
7391
6995
  const pass = (label) => {
7392
6996
  checkPass(label);
@@ -7397,7 +7001,7 @@ async function runConfigTierDiagnostics(targetCwd, opts, counters, options = {})
7397
7001
  counters.failed++;
7398
7002
  };
7399
7003
  const includePackageJson = options.includePackageJson !== false;
7400
- const includeSlotCheck = options.includeSlotCheck === true;
7004
+ const includeStaleSlotCheck = options.includeStaleSlotCheck === true;
7401
7005
  if (includePackageJson) {
7402
7006
  if (hasPackageJson(targetCwd)) pass("package.json found");
7403
7007
  else fail2("package.json missing");
@@ -7412,20 +7016,10 @@ async function runConfigTierDiagnostics(targetCwd, opts, counters, options = {})
7412
7016
  }
7413
7017
  ensureComponentConfig(readComponentPackageManifest(targetCwd), targetCwd);
7414
7018
  await ensureSlotRegistry({ cwd: targetCwd, quiet: true, mode: "repair" });
7019
+ repairStaleSlotOutput(targetCwd);
7415
7020
  }
7416
- if (includeSlotCheck && isInsideProject(targetCwd) && getInstalledPackageVersion(COMPONENTS_PACKAGE, targetCwd)) {
7417
- const slotValidity = checkGeneratedSlotValidity(targetCwd);
7418
- if (slotValidity.ok) {
7419
- pass(slotValidity.summary);
7420
- } else {
7421
- fail2(slotValidity.summary);
7422
- if (slotValidity.details) {
7423
- for (const line of slotValidity.details.split("\n")) {
7424
- hint(line);
7425
- }
7426
- }
7427
- hint("Fix: reinstall @inventive-ui/components and rerun iui doctor");
7428
- }
7021
+ if (includeStaleSlotCheck && isInsideProject(targetCwd)) {
7022
+ reportStaleSlotOutput(targetCwd, pass, fail2);
7429
7023
  }
7430
7024
  const configValidity = checkComponentConfigValidity(targetCwd, {
7431
7025
  autoFix: opts?.fix === true
@@ -7515,7 +7109,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
7515
7109
  if (opts?.configOnly) {
7516
7110
  await runConfigTierDiagnostics(targetCwd, opts, counters, {
7517
7111
  includePackageJson: true,
7518
- includeSlotCheck: true
7112
+ includeStaleSlotCheck: true
7519
7113
  });
7520
7114
  return;
7521
7115
  }
@@ -7530,6 +7124,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
7530
7124
  }
7531
7125
  ensureComponentConfig(readComponentPackageManifest(targetCwd), targetCwd);
7532
7126
  await ensureSlotRegistry({ cwd: targetCwd, quiet: true, mode: "repair" });
7127
+ repairStaleSlotOutput(targetCwd);
7533
7128
  }
7534
7129
  if (isInsideProject(targetCwd)) {
7535
7130
  pass("Inventive UI project initialized");
@@ -7577,9 +7172,6 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
7577
7172
  const packages = readPackageManifest(targetCwd);
7578
7173
  const pkgCount = Object.keys(packages).length;
7579
7174
  pass(`${pkgCount} asset package${pkgCount !== 1 ? "s" : ""} installed`);
7580
- const slots = readSlotManifest(targetCwd);
7581
- const slotCount = Object.keys(slots).length;
7582
- pass(`${slotCount} slot${slotCount !== 1 ? "s" : ""} registered`);
7583
7175
  const compatibility = checkPackageCompatibility(targetCwd);
7584
7176
  if (compatibility.ok) {
7585
7177
  pass(compatibility.summary);
@@ -7620,18 +7212,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
7620
7212
  pass("Inventive UI packages are on the latest version");
7621
7213
  }
7622
7214
  }
7623
- const slotValidity = checkGeneratedSlotValidity(targetCwd);
7624
- if (slotValidity.ok) {
7625
- pass(slotValidity.summary);
7626
- } else {
7627
- fail2(slotValidity.summary);
7628
- if (slotValidity.details) {
7629
- for (const line of slotValidity.details.split("\n")) {
7630
- hint(line);
7631
- }
7632
- }
7633
- hint("Fix: reinstall @inventive-ui/components and rerun iui doctor");
7634
- }
7215
+ reportStaleSlotOutput(targetCwd, pass, fail2);
7635
7216
  const bootstrapSync = checkBootstrapSync(targetCwd, {
7636
7217
  autoFix: opts?.fix === true
7637
7218
  });
@@ -7650,13 +7231,13 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
7650
7231
  }
7651
7232
  await runConfigTierDiagnostics(targetCwd, opts, counters, {
7652
7233
  includePackageJson: false,
7653
- includeSlotCheck: false
7234
+ includeStaleSlotCheck: false
7654
7235
  });
7655
7236
  }
7656
7237
  async function doctorCommand(opts) {
7657
7238
  try {
7658
7239
  const invocationCwd = process.cwd();
7659
- const targets = opts?.cwd ? [path24.resolve(opts.cwd)] : resolveSetupDoctorTargets(invocationCwd);
7240
+ const targets = opts?.cwd ? [path23.resolve(opts.cwd)] : resolveSetupDoctorTargets(invocationCwd);
7660
7241
  const installRoot = resolveDependencyInstallRoot(invocationCwd);
7661
7242
  const multiPackage = targets.length > 1;
7662
7243
  heading("Diagnostics");
@@ -7699,7 +7280,7 @@ async function doctorCommand(opts) {
7699
7280
  for (const targetCwd of targets) {
7700
7281
  if (multiPackage) {
7701
7282
  newline();
7702
- const label = path24.relative(installRoot, targetCwd) || path24.basename(targetCwd);
7283
+ const label = path23.relative(installRoot, targetCwd) || path23.basename(targetCwd);
7703
7284
  kv("Package", label);
7704
7285
  }
7705
7286
  await runPackageDiagnostics(targetCwd, opts, counters);
@@ -7712,7 +7293,7 @@ async function doctorCommand(opts) {
7712
7293
  } else {
7713
7294
  fail(`${counters.failed} issue${counters.failed > 1 ? "s" : ""} found`);
7714
7295
  hint("Resolve the issues above and re-run iui doctor");
7715
- hint("Checklist: compatibility, managed slots, config validity, required types");
7296
+ hint("Checklist: compatibility, generated bootstrap, config validity, required types");
7716
7297
  if (!opts?.fix) {
7717
7298
  hint("Use iui doctor --fix to apply safe automatic repairs");
7718
7299
  }
@@ -7727,9 +7308,9 @@ async function doctorCommand(opts) {
7727
7308
 
7728
7309
  // src/commands/setup.ts
7729
7310
  function detectDevScript(cwd) {
7730
- const pkgPath = path25.join(cwd, "package.json");
7311
+ const pkgPath = path24.join(cwd, "package.json");
7731
7312
  try {
7732
- const pkg = fs19.readJsonSync(pkgPath);
7313
+ const pkg = fs18.readJsonSync(pkgPath);
7733
7314
  if (pkg.scripts?.dev) return "npm run dev";
7734
7315
  if (pkg.scripts?.start) return "npm run start";
7735
7316
  } catch {
@@ -7738,8 +7319,8 @@ function detectDevScript(cwd) {
7738
7319
  return null;
7739
7320
  }
7740
7321
  function relativePackageLabel(installRoot, packageDir) {
7741
- const rel = path25.relative(installRoot, packageDir);
7742
- return rel && rel !== "." ? rel : path25.basename(packageDir);
7322
+ const rel = path24.relative(installRoot, packageDir);
7323
+ return rel && rel !== "." ? rel : path24.basename(packageDir);
7743
7324
  }
7744
7325
  async function setupCommand(opts) {
7745
7326
  try {
@@ -7748,7 +7329,7 @@ async function setupCommand(opts) {
7748
7329
  const installRoot = resolveDependencyInstallRoot(cwd);
7749
7330
  const workspaceRoot = findWorkspaceRoot(cwd);
7750
7331
  const inMonorepo = workspaceRoot !== null;
7751
- const installFromChild = inMonorepo && path25.resolve(installRoot) !== path25.resolve(cwd);
7332
+ const installFromChild = inMonorepo && path24.resolve(installRoot) !== path24.resolve(cwd);
7752
7333
  if (!hasPackageJson(cwd) && !hasPackageJson(installRoot)) {
7753
7334
  throw new CLIError(
7754
7335
  "No package.json found in the current directory.",
@@ -7782,7 +7363,7 @@ async function setupCommand(opts) {
7782
7363
  for (const w of warnings) warn(w);
7783
7364
  kv("Package manager", `${pm} (${source})`);
7784
7365
  if (installFromChild) {
7785
- const rel = path25.relative(cwd, installRoot) || ".";
7366
+ const rel = path24.relative(cwd, installRoot) || ".";
7786
7367
  kv("Install directory", rel === ".." || rel.includes("..") ? installRoot : rel);
7787
7368
  }
7788
7369
  const installCmd2 = syncInstallCommand(pm);
@@ -7796,7 +7377,7 @@ async function setupCommand(opts) {
7796
7377
  } catch (err) {
7797
7378
  installSpinner.fail("Dependency install failed");
7798
7379
  const detail = formatExecSyncError(err);
7799
- const manual = path25.resolve(installRoot) === path25.resolve(cwd) ? installCmd2 : `cd ${JSON.stringify(installRoot)} && ${installCmd2}`;
7380
+ const manual = path24.resolve(installRoot) === path24.resolve(cwd) ? installCmd2 : `cd ${JSON.stringify(installRoot)} && ${installCmd2}`;
7800
7381
  throw new CLIError(
7801
7382
  detail ? `Could not install project dependencies.
7802
7383
  ${detail}` : "Could not install project dependencies.",
@@ -7923,23 +7504,6 @@ async function listCommand(opts) {
7923
7504
  newline();
7924
7505
  info(`${pkgKeys.length} asset package${pkgKeys.length !== 1 ? "s" : ""} installed`);
7925
7506
  }
7926
- heading("Slot Registry");
7927
- const slots = readSlotManifest();
7928
- const slotKeys = Object.keys(slots);
7929
- if (slotKeys.length === 0) {
7930
- info("No component slots available yet.");
7931
- } else {
7932
- for (const [key, record] of Object.entries(slots)) {
7933
- const displayName = itemsLookup[key]?.title ?? key;
7934
- const slotInfo = record.supportedSlots?.length ? `${record.slotType} \xB7 slots: ${record.supportedSlots.join(", ")}` : `${record.slotType}`;
7935
- bulletItem(
7936
- displayName.padEnd(26),
7937
- `${slotInfo} \xB7 v${record.version}`
7938
- );
7939
- }
7940
- newline();
7941
- info(`${slotKeys.length} slot${slotKeys.length !== 1 ? "s" : ""} registered`);
7942
- }
7943
7507
  newline();
7944
7508
  } catch (error) {
7945
7509
  handleError(error);
@@ -7954,7 +7518,7 @@ async function updateCommand(opts = {}) {
7954
7518
  const auth = await ensureAuthSession();
7955
7519
  await ensureLicenseSession();
7956
7520
  const inProject = isInsideProject();
7957
- const currentCliVersion = true ? "0.0.11" : "unknown";
7521
+ const currentCliVersion = true ? "0.0.12" : "unknown";
7958
7522
  const latestCliVersion = await fetchLatestCliVersion(auth.token);
7959
7523
  const cliUpdateAvailable = latestCliVersion !== null && isVersionGreater(latestCliVersion, currentCliVersion);
7960
7524
  if (latestCliVersion && cliUpdateAvailable) {
@@ -8236,7 +7800,7 @@ var AUTH_EXEMPT_COMMANDS = /* @__PURE__ */ new Set([
8236
7800
  "doctor",
8237
7801
  "list"
8238
7802
  ]);
8239
- program.name("iui").description("The official CLI for the Inventive UI Design System").version(true ? "0.0.11" : "1.0.0").option("-C, --cwd <dir>", "Run as if started in the given directory").option("-q, --quiet", "Minimal output (also respects IUI_QUIET=1)").option("--no-color", "Disable ANSI colors");
7803
+ program.name("iui").description("The official CLI for the Inventive UI Design System").version(true ? "0.0.12" : "1.0.0").option("-C, --cwd <dir>", "Run as if started in the given directory").option("-q, --quiet", "Minimal output (also respects IUI_QUIET=1)").option("--no-color", "Disable ANSI colors");
8240
7804
  program.command("login").description("Authenticate with GitHub and link your license").option("-f, --force", "Force re-authentication and register this device").option("--bootstrap", "After login, run optional setup prompts").action((opts) => loginCommand(opts));
8241
7805
  program.command("logout").description("Remove stored credentials").action(logoutCommand);
8242
7806
  program.command("whoami").description("Show authenticated identity and license details").action(whoamiCommand);
@@ -8334,7 +7898,7 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
8334
7898
  const root = topLevelCommandName(actionCommand);
8335
7899
  const globalOpts = program.opts();
8336
7900
  if (globalOpts.cwd) {
8337
- process.chdir(path26.resolve(globalOpts.cwd));
7901
+ process.chdir(path25.resolve(globalOpts.cwd));
8338
7902
  }
8339
7903
  if (isInsideProject()) {
8340
7904
  try {
@@ -8348,14 +7912,14 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
8348
7912
  mode: slotPolicy.mode
8349
7913
  });
8350
7914
  if (result.status === "repaired") {
8351
- info("Slot registry repaired");
7915
+ info("Project registry repaired");
8352
7916
  }
8353
7917
  } catch (error) {
8354
7918
  if (error instanceof CLIError) {
8355
7919
  warn(error.message);
8356
7920
  if (error.hint) hint(error.hint);
8357
7921
  } else {
8358
- warn("Slot registry validation failed; run iui doctor for diagnostics.");
7922
+ warn("Project registry validation failed; run iui doctor for diagnostics.");
8359
7923
  }
8360
7924
  }
8361
7925
  }