inventive-ui 0.0.1 → 0.0.3

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 path25 from "path";
4
+ import path27 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.1" : "1.0.0";
193
+ return true ? "0.0.3" : "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 path26 = parsed.pathname.replace(/\/+$/, "");
377
- if (path26 && !/^\/[a-zA-Z0-9._/-]+$/.test(path26)) {
376
+ const path28 = parsed.pathname.replace(/\/+$/, "");
377
+ if (path28 && !/^\/[a-zA-Z0-9._/-]+$/.test(path28)) {
378
378
  throw new CLIError(
379
379
  "IUI_API_URL path contains invalid characters.",
380
380
  "Use a simple path prefix such as /v1"
@@ -633,8 +633,8 @@ var ASSET_CATEGORY_LABELS = {
633
633
  };
634
634
 
635
635
  // src/utils/filesystem.ts
636
- import path9 from "path";
637
- import { fileURLToPath } from "url";
636
+ import path10 from "path";
637
+ import { fileURLToPath as fileURLToPath2 } from "url";
638
638
  import os3 from "os";
639
639
  import fs8 from "fs-extra";
640
640
 
@@ -1046,8 +1046,8 @@ function listIuiInitializedPackages(startCwd) {
1046
1046
  );
1047
1047
  if (initialized.length > 0) return initialized;
1048
1048
  }
1049
- const iuiRoot = findIuiProjectRoot(startCwd);
1050
- return iuiRoot ? [iuiRoot] : [];
1049
+ const iuiRoot2 = findIuiProjectRoot(startCwd);
1050
+ return iuiRoot2 ? [iuiRoot2] : [];
1051
1051
  }
1052
1052
  function resolveSetupDoctorTargets(cwd) {
1053
1053
  const resolved = path5.resolve(cwd);
@@ -1412,6 +1412,37 @@ function parseAndValidateRegistryManifest(raw, source) {
1412
1412
  return result.data;
1413
1413
  }
1414
1414
 
1415
+ // src/utils/theme-config-scaffold.ts
1416
+ import { existsSync } from "fs";
1417
+ import { dirname, join } from "path";
1418
+ import { fileURLToPath } from "url";
1419
+ import { createJiti } from "jiti";
1420
+ var __dirname2 = dirname(fileURLToPath(import.meta.url));
1421
+ function resolveFrameworkScriptsDir(startCwd) {
1422
+ const searchRoots = [startCwd, process.cwd(), join(__dirname2, "../..")];
1423
+ for (const root of searchRoots) {
1424
+ const frameworkDir = resolvePackageDir(FRAMEWORK_PACKAGE, root);
1425
+ if (!frameworkDir) continue;
1426
+ const scriptsDir = join(frameworkDir, "scripts");
1427
+ const loader = join(scriptsDir, "load-framework-theme-defaults.mjs");
1428
+ if (existsSync(loader)) return scriptsDir;
1429
+ }
1430
+ throw new CLIError(
1431
+ `Cannot scaffold iui.config.ts: ${FRAMEWORK_PACKAGE} is not installed or is missing scripts/load-framework-theme-defaults.mjs.`
1432
+ );
1433
+ }
1434
+ function buildProjectConfigSource(cwd = process.cwd()) {
1435
+ const scriptsDir = resolveFrameworkScriptsDir(cwd);
1436
+ const jiti = createJiti(import.meta.url, { interopDefault: true });
1437
+ const loader = jiti(
1438
+ join(scriptsDir, "load-framework-theme-defaults.mjs")
1439
+ );
1440
+ const defaults = loader.loadFrameworkThemeDefaults(scriptsDir);
1441
+ return loader.buildThemeScaffoldConfig(defaults, {
1442
+ configType: "IUIThemeConfig"
1443
+ });
1444
+ }
1445
+
1415
1446
  // src/utils/security/identifiers.ts
1416
1447
  var SLUG_RE = /^[a-z][a-z0-9-]*$/;
1417
1448
  var JS_IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
@@ -2527,6 +2558,19 @@ var ComponentConfigEntrySchema = z2.object({
2527
2558
  presets: z2.record(z2.unknown()).optional()
2528
2559
  }).catchall(z2.unknown());
2529
2560
  var ComponentConfigSchema = z2.record(ComponentConfigEntrySchema);
2561
+ var ProjectMetaSchema = z2.object({
2562
+ projectId: z2.string().min(1),
2563
+ repoUrl: z2.string().min(1),
2564
+ createdAt: z2.string().min(1),
2565
+ initScope: z2.enum(["package", "workspace"]).optional(),
2566
+ configs: z2.object({
2567
+ theme: z2.string().min(1),
2568
+ assets: z2.string().min(1),
2569
+ components: z2.string().min(1)
2570
+ }).strict().optional()
2571
+ }).strict().refine((data) => !("theme" in data) && !("assets" in data), {
2572
+ message: "project.json must not contain config values \u2014 use configs paths only"
2573
+ });
2530
2574
  function formatZodIssues(error) {
2531
2575
  return error.issues.slice(0, 8).map((i) => `${i.path.join(".") || "(root)"}: ${i.message}`).join("\n");
2532
2576
  }
@@ -2647,6 +2691,30 @@ function checkAssetsConfigValidity(cwd = process.cwd()) {
2647
2691
  details: "Run iui init or merge CLI defaults so @alias icons resolve."
2648
2692
  };
2649
2693
  }
2694
+ const logo = assets2.logo;
2695
+ if (assets2.logo && (!logo?.globalLogos || Object.keys(logo.globalLogos).length === 0)) {
2696
+ return {
2697
+ ok: false,
2698
+ summary: "assets.config.json is missing logo.globalLogos",
2699
+ details: "Run iui init or merge CLI defaults so @alias logos resolve."
2700
+ };
2701
+ }
2702
+ const emoji = assets2.emoji;
2703
+ if (assets2.emoji && (!emoji?.globalEmojis || Object.keys(emoji.globalEmojis).length === 0)) {
2704
+ return {
2705
+ ok: false,
2706
+ summary: "assets.config.json is missing emoji.globalEmojis",
2707
+ details: "Run iui init or merge CLI defaults so @alias emojis resolve."
2708
+ };
2709
+ }
2710
+ const colorLogo = assets2.colorLogo;
2711
+ if (assets2.colorLogo && (!colorLogo?.globalColorLogos || Object.keys(colorLogo.globalColorLogos).length === 0)) {
2712
+ return {
2713
+ ok: false,
2714
+ summary: "assets.config.json is missing colorLogo.globalColorLogos",
2715
+ details: "Run iui init or merge CLI defaults so @alias color logos resolve."
2716
+ };
2717
+ }
2650
2718
  return { ok: true, summary: "assets.config.json is valid" };
2651
2719
  }
2652
2720
  function checkComponentConfigTierBleed(cwd = process.cwd()) {
@@ -2671,12 +2739,59 @@ function checkComponentConfigTierBleed(cwd = process.cwd()) {
2671
2739
  };
2672
2740
  }
2673
2741
 
2742
+ // src/services/iui-paths.ts
2743
+ import path9 from "path";
2744
+ var IUI_CACHE_SEGMENT = "cache";
2745
+ var IUI_CACHE_FILES = {
2746
+ scan: "scan.cache.json",
2747
+ styles: "styles.css",
2748
+ manifest: "manifest.js",
2749
+ stylesInject: "styles.inject.js",
2750
+ stylesInline: "styles.inline.js",
2751
+ slotState: "slot-state.json",
2752
+ slotLock: "slot.lock",
2753
+ utilities: "utilities.css",
2754
+ manifestJson: "manifest.json",
2755
+ slotWarmup: "slot-warmup.mjs"
2756
+ };
2757
+ function iuiProjectRoot(cwd = process.cwd()) {
2758
+ return resolveIuiProjectRoot(cwd);
2759
+ }
2760
+ function iuiRoot(cwd = process.cwd()) {
2761
+ return path9.join(iuiProjectRoot(cwd), IUI_DIR);
2762
+ }
2763
+ function iuiCacheDir(cwd = process.cwd()) {
2764
+ return path9.join(iuiRoot(cwd), IUI_CACHE_SEGMENT);
2765
+ }
2766
+ function iuiCacheFile(cwd, name) {
2767
+ return path9.join(iuiCacheDir(cwd), IUI_CACHE_FILES[name]);
2768
+ }
2769
+ var IUI_CACHE_GITIGNORE_LINES = [
2770
+ "",
2771
+ "# IUI disposable cache (.iui/generated/ stays committed)",
2772
+ `${IUI_DIR}/${IUI_CACHE_SEGMENT}/`,
2773
+ `${IUI_DIR}/slot-registration-state.json`,
2774
+ `${IUI_DIR}/slot-registration.lock`,
2775
+ `${IUI_DIR}/classes.cache.json`,
2776
+ `${IUI_DIR}/utilities.css`,
2777
+ `${IUI_DIR}/build-styles.generated.css`,
2778
+ `${IUI_DIR}/build-styles.generated.js`,
2779
+ `${IUI_DIR}/build-manifest.generated.js`,
2780
+ `${IUI_DIR}/build-css-inline.js`,
2781
+ `${IUI_DIR}/build-manifest.json`,
2782
+ `${IUI_DIR}/slot-warmup.generated.mjs`,
2783
+ ".iui-bootstrap-client.js",
2784
+ ".iui-bootstrap-server.js",
2785
+ ".iui-bootstrap.js",
2786
+ "public/iui/"
2787
+ ];
2788
+
2674
2789
  // src/utils/filesystem.ts
2675
2790
  function globalConfigPath() {
2676
- return path9.join(os3.homedir(), GLOBAL_CONFIG_DIR, "config.json");
2791
+ return path10.join(os3.homedir(), GLOBAL_CONFIG_DIR, "config.json");
2677
2792
  }
2678
2793
  function globalSecretsPath() {
2679
- return path9.join(os3.homedir(), GLOBAL_CONFIG_DIR, "secrets.json");
2794
+ return path10.join(os3.homedir(), GLOBAL_CONFIG_DIR, "secrets.json");
2680
2795
  }
2681
2796
  function readSecretsFile() {
2682
2797
  const p = globalSecretsPath();
@@ -2731,10 +2846,10 @@ function removeGlobalConfig() {
2731
2846
  if (fs8.existsSync(s)) fs8.removeSync(s);
2732
2847
  }
2733
2848
  function iuiDir(cwd = process.cwd()) {
2734
- return path9.join(resolveIuiProjectRoot(cwd), IUI_DIR);
2849
+ return path10.join(resolveIuiProjectRoot(cwd), IUI_DIR);
2735
2850
  }
2736
2851
  function metaPath(file, cwd) {
2737
- return path9.join(iuiDir(cwd ?? process.cwd()), file);
2852
+ return path10.join(iuiDir(cwd ?? process.cwd()), file);
2738
2853
  }
2739
2854
  function projectMetaPath(cwd) {
2740
2855
  return metaPath("project.json", cwd);
@@ -2794,10 +2909,10 @@ function writePackageManifest(manifest, cwd) {
2794
2909
  writeJson(packageManifestPath(cwd), manifest);
2795
2910
  }
2796
2911
  function getCliTemplatesDir() {
2797
- return path9.join(path9.dirname(fileURLToPath(import.meta.url)), "..", "templates");
2912
+ return path10.join(path10.dirname(fileURLToPath2(import.meta.url)), "..", "templates");
2798
2913
  }
2799
2914
  function loadAssetsConfigTemplate() {
2800
- const templatePath = path9.join(getCliTemplatesDir(), "assets.config.defaults.json");
2915
+ const templatePath = path10.join(getCliTemplatesDir(), "assets.config.defaults.json");
2801
2916
  if (!fs8.existsSync(templatePath)) return {};
2802
2917
  try {
2803
2918
  return fs8.readJsonSync(templatePath);
@@ -2806,7 +2921,7 @@ function loadAssetsConfigTemplate() {
2806
2921
  }
2807
2922
  }
2808
2923
  function loadComponentConfigPresetsTemplate() {
2809
- const templatePath = path9.join(getCliTemplatesDir(), "component.config.presets.json");
2924
+ const templatePath = path10.join(getCliTemplatesDir(), "component.config.presets.json");
2810
2925
  if (!fs8.existsSync(templatePath)) return {};
2811
2926
  try {
2812
2927
  return fs8.readJsonSync(templatePath);
@@ -2821,12 +2936,19 @@ function mergeAssetSlotWithTemplate(slot, templateSlot) {
2821
2936
  "globalIcons",
2822
2937
  "globalEmojis",
2823
2938
  "globalLogos",
2824
- "globalColorLogos"
2939
+ "globalColorLogos",
2940
+ "globalLoaders",
2941
+ "globalIllustrations",
2942
+ "globalFlags",
2943
+ "globalFileTypes"
2825
2944
  ]) {
2826
2945
  const tplMap = templateSlot[mapKey];
2827
2946
  const userMap = slot?.[mapKey];
2828
- if (tplMap && typeof tplMap === "object" && (!userMap || Object.keys(userMap).length === 0)) {
2829
- out[mapKey] = tplMap;
2947
+ if (tplMap && typeof tplMap === "object") {
2948
+ out[mapKey] = {
2949
+ ...tplMap,
2950
+ ...userMap ?? {}
2951
+ };
2830
2952
  }
2831
2953
  }
2832
2954
  return out;
@@ -2856,7 +2978,7 @@ function seedAssetsOutputFromTemplate(output) {
2856
2978
  }
2857
2979
  }
2858
2980
  function assetsConfigPath(cwd) {
2859
- return path9.join(resolveIuiProjectRoot(cwd ?? process.cwd()), ASSETS_CONFIG_FILE);
2981
+ return path10.join(resolveIuiProjectRoot(cwd ?? process.cwd()), ASSETS_CONFIG_FILE);
2860
2982
  }
2861
2983
  function readExistingAssetsConfigRaw(cwd) {
2862
2984
  const p = assetsConfigPath(cwd);
@@ -3019,7 +3141,7 @@ function writeAssetsConfig(cwd = process.cwd()) {
3019
3141
  seedAssetsOutputFromTemplate(output);
3020
3142
  writeJson(assetsConfigPath(cwd), output);
3021
3143
  try {
3022
- const legacyIconDefaults = path9.join(cwd ?? process.cwd(), IUI_DIR, "icon-defaults.json");
3144
+ const legacyIconDefaults = path10.join(cwd ?? process.cwd(), IUI_DIR, "icon-defaults.json");
3023
3145
  if (fs8.existsSync(legacyIconDefaults)) fs8.removeSync(legacyIconDefaults);
3024
3146
  } catch {
3025
3147
  }
@@ -3035,7 +3157,7 @@ function writeSlotManifest(manifest, cwd) {
3035
3157
  function readComponentPackageManifest(cwd = process.cwd()) {
3036
3158
  const pkgDir = resolvePackageDir("@inventive-ui/components", cwd);
3037
3159
  if (!pkgDir) return null;
3038
- const p = path9.join(pkgDir, "iui-manifest.json");
3160
+ const p = path10.join(pkgDir, "iui-manifest.json");
3039
3161
  if (!fs8.existsSync(p)) return null;
3040
3162
  try {
3041
3163
  const raw = fs8.readJsonSync(p);
@@ -3051,7 +3173,7 @@ function readComponentPackageManifest(cwd = process.cwd()) {
3051
3173
  function getInstalledPackageVersion(packageName, cwd = process.cwd()) {
3052
3174
  const pkgDir = resolvePackageDir(packageName, cwd);
3053
3175
  if (!pkgDir) return null;
3054
- const pkgPath = path9.join(pkgDir, "package.json");
3176
+ const pkgPath = path10.join(pkgDir, "package.json");
3055
3177
  if (!fs8.existsSync(pkgPath)) return null;
3056
3178
  try {
3057
3179
  const pkg = fs8.readJsonSync(pkgPath);
@@ -3069,121 +3191,11 @@ function registryItemsMap(manifest) {
3069
3191
  return map;
3070
3192
  }
3071
3193
  function writeProjectConfig(cwd = process.cwd()) {
3072
- const configPath = path9.join(cwd, PROJECT_CONFIG_FILE);
3073
- const content = `import type { IUIThemeConfig } from "@inventive-ui/framework/config";
3074
-
3075
- const config: IUIThemeConfig = {
3076
- theme: {
3077
- mode: {
3078
- default: "light",
3079
- allowSystem: true,
3080
- },
3081
-
3082
- direction: "ltr",
3083
-
3084
- colors: {
3085
- semantic: {
3086
- success: "green",
3087
- warning: "amber",
3088
- danger: "red",
3089
- info: "blue",
3090
- },
3091
-
3092
- neutral: {
3093
- base: "gray",
3094
- warm: "stone",
3095
- cool: "slate",
3096
- },
3097
-
3098
- brand: {
3099
- set: "indigo",
3100
- },
3101
-
3102
- accent: {
3103
- "accent-1": "fuchsia",
3104
- },
3105
-
3106
- gradients: {
3107
- sunset: {
3108
- from: "success",
3109
- to: "blue",
3110
- direction: "to end",
3111
- },
3112
- glass: {
3113
- from: "red",
3114
- to: "yellow",
3115
- direction: "to end",
3116
- },
3117
- },
3118
- },
3119
-
3120
- typography: {
3121
- provider: "system",
3122
- set: "inter",
3123
- },
3124
-
3125
- spacing: {
3126
- set: "compact",
3127
- },
3128
-
3129
- radius: {
3130
- set: "none",
3131
- },
3132
- },
3133
-
3134
- states: {
3135
- focused: {
3136
- mode: "native",
3137
- shades: { light: "600", dark: "400" },
3138
- style: {
3139
- width: 2,
3140
- offset: 2,
3141
- offsetColor: { light: "white", dark: "black" },
3142
- },
3143
- accessibility: { minContrast: 3, highContrastSupport: false },
3144
- },
3145
- disabled: {
3146
- style: "fade",
3147
- opacity: 0.5,
3148
- },
3149
- loading: {
3150
- style: "fade",
3151
- opacity: 0.5,
3152
- spinner: true,
3153
- cursor: "wait",
3154
- label: "Loading",
3155
- },
3156
- },
3157
-
3158
- core: {
3159
- important: false,
3160
- },
3161
-
3162
- /**
3163
- * Compile-first CSS \u2014 scanned at build time by the Vite/Webpack/Next plugin.
3164
- * Do not import style-map ".generated" files into the browser graph.
3165
- * scanDirs / scanPackages default in Framework \u2014 override only when needed.
3166
- * See Framework docs/01-compile-first-guide.md for all build options.
3167
- */
3168
- build: {
3169
- safelist: [],
3170
- packageSafelist: false,
3171
- includeShadeMatrix: false,
3172
- includeThemePresets: true,
3173
- resolvePalettePatterns: true,
3174
- includeArbitraryScan: true,
3175
- writeFiles: false,
3176
- minify: true,
3177
- useAst: true,
3178
- },
3179
- };
3180
-
3181
- export default config;
3182
- `;
3183
- atomicWriteFile(configPath, content);
3194
+ const configPath = path10.join(cwd, PROJECT_CONFIG_FILE);
3195
+ atomicWriteFile(configPath, buildProjectConfigSource(cwd));
3184
3196
  }
3185
3197
  function ensureProjectConfigBuildBlock(cwd = process.cwd()) {
3186
- const configPath = path9.join(resolveIuiProjectRoot(cwd), PROJECT_CONFIG_FILE);
3198
+ const configPath = path10.join(resolveIuiProjectRoot(cwd), PROJECT_CONFIG_FILE);
3187
3199
  if (!fs8.existsSync(configPath)) return false;
3188
3200
  const before = fs8.readFileSync(configPath, "utf-8");
3189
3201
  const result = patchProjectConfigBuildBlock(before);
@@ -3193,7 +3205,7 @@ function ensureProjectConfigBuildBlock(cwd = process.cwd()) {
3193
3205
  }
3194
3206
  function ensureProjectConfig(cwd = process.cwd()) {
3195
3207
  const root = resolveIuiProjectRoot(cwd);
3196
- const configPath = path9.join(root, PROJECT_CONFIG_FILE);
3208
+ const configPath = path10.join(root, PROJECT_CONFIG_FILE);
3197
3209
  if (!fs8.existsSync(configPath)) {
3198
3210
  writeProjectConfig(root);
3199
3211
  return "scaffolded";
@@ -3221,7 +3233,7 @@ function isIuiManagedOrMinimalScaffold(content) {
3221
3233
  function removeStaleIuiViteConfig(cwd = process.cwd()) {
3222
3234
  if (projectHasViteTooling(cwd)) return false;
3223
3235
  let removed = false;
3224
- const configPath = path9.join(cwd, "vite.config.ts");
3236
+ const configPath = path10.join(cwd, "vite.config.ts");
3225
3237
  if (fs8.existsSync(configPath)) {
3226
3238
  const existing = fs8.readFileSync(configPath, "utf-8");
3227
3239
  if (isIuiManagedOrMinimalScaffold(existing)) {
@@ -3229,7 +3241,7 @@ function removeStaleIuiViteConfig(cwd = process.cwd()) {
3229
3241
  removed = true;
3230
3242
  }
3231
3243
  }
3232
- const nodeTsPath = path9.join(cwd, "tsconfig.node.json");
3244
+ const nodeTsPath = path10.join(cwd, "tsconfig.node.json");
3233
3245
  if (fs8.existsSync(nodeTsPath)) {
3234
3246
  try {
3235
3247
  const nodeTs = fs8.readJsonSync(nodeTsPath);
@@ -3244,7 +3256,7 @@ function removeStaleIuiViteConfig(cwd = process.cwd()) {
3244
3256
  return removed;
3245
3257
  }
3246
3258
  function writeTsConfigNode(cwd = process.cwd()) {
3247
- const nodeTsPath = path9.join(cwd, "tsconfig.node.json");
3259
+ const nodeTsPath = path10.join(cwd, "tsconfig.node.json");
3248
3260
  const content = {
3249
3261
  compilerOptions: {
3250
3262
  target: "ES2022",
@@ -3264,7 +3276,7 @@ function writeTsConfigNode(cwd = process.cwd()) {
3264
3276
  atomicWriteJson(nodeTsPath, content);
3265
3277
  }
3266
3278
  function writeTsConfig(framework, cwd = process.cwd()) {
3267
- const tsconfigPath = path9.join(cwd, "tsconfig.json");
3279
+ const tsconfigPath = path10.join(cwd, "tsconfig.json");
3268
3280
  let existing = {};
3269
3281
  if (fs8.existsSync(tsconfigPath)) {
3270
3282
  try {
@@ -3332,7 +3344,7 @@ function writeTsConfig(framework, cwd = process.cwd()) {
3332
3344
  atomicWriteJson(tsconfigPath, output);
3333
3345
  }
3334
3346
  function writeComponentConfig(manifest, cwd = process.cwd()) {
3335
- const configPath = path9.join(cwd, COMPONENT_CONFIG_FILE);
3347
+ const configPath = path10.join(cwd, COMPONENT_CONFIG_FILE);
3336
3348
  let entries = "";
3337
3349
  const typedEntries = [];
3338
3350
  const typeImports = [];
@@ -3385,7 +3397,7 @@ ${entries}};
3385
3397
  atomicWriteFile(configPath, content);
3386
3398
  }
3387
3399
  function ensureComponentConfig(manifest, cwd = process.cwd(), options = {}) {
3388
- const configPath = path9.join(cwd, COMPONENT_CONFIG_FILE);
3400
+ const configPath = path10.join(cwd, COMPONENT_CONFIG_FILE);
3389
3401
  if (options.force || !fs8.existsSync(configPath)) {
3390
3402
  const existed = fs8.existsSync(configPath);
3391
3403
  writeComponentConfig(manifest, cwd);
@@ -3402,7 +3414,7 @@ function isInsideProject(cwd = process.cwd()) {
3402
3414
  }
3403
3415
  function detectRepoUrl(cwd = process.cwd()) {
3404
3416
  try {
3405
- const gitConfigPath = path9.join(cwd, ".git", "config");
3417
+ const gitConfigPath = path10.join(cwd, ".git", "config");
3406
3418
  if (!fs8.existsSync(gitConfigPath)) return cwd;
3407
3419
  const gitConfig = fs8.readFileSync(gitConfigPath, "utf-8");
3408
3420
  const match = gitConfig.match(/url\s*=\s*(.+)/);
@@ -3412,11 +3424,11 @@ function detectRepoUrl(cwd = process.cwd()) {
3412
3424
  }
3413
3425
  }
3414
3426
  function hasPackageJson(cwd = process.cwd()) {
3415
- return fs8.existsSync(path9.join(cwd, "package.json"));
3427
+ return fs8.existsSync(path10.join(cwd, "package.json"));
3416
3428
  }
3417
3429
  function cleanupLegacyFrameworkMeta(cwd = process.cwd()) {
3418
3430
  try {
3419
- const legacyPath = path9.join(cwd, IUI_DIR, "framework.json");
3431
+ const legacyPath = path10.join(cwd, IUI_DIR, "framework.json");
3420
3432
  if (fs8.existsSync(legacyPath)) fs8.removeSync(legacyPath);
3421
3433
  } catch {
3422
3434
  }
@@ -3433,7 +3445,7 @@ var LOCKFILES = [
3433
3445
  ];
3434
3446
  var PM_PRIORITY = ["bun", "pnpm", "yarn", "npm"];
3435
3447
  function readPackageManagerField(cwd) {
3436
- const pkgPath = path9.join(cwd, "package.json");
3448
+ const pkgPath = path10.join(cwd, "package.json");
3437
3449
  if (!fs8.existsSync(pkgPath)) return null;
3438
3450
  try {
3439
3451
  const pkg = fs8.readJsonSync(pkgPath);
@@ -3449,11 +3461,11 @@ function readPackageManagerField(cwd) {
3449
3461
  }
3450
3462
  function detectPackageManagerWithMeta(cwd = process.cwd()) {
3451
3463
  const warnings = [];
3452
- const root = findWorkspaceRoot(cwd) ?? path9.resolve(cwd);
3464
+ const root = findWorkspaceRoot(cwd) ?? path10.resolve(cwd);
3453
3465
  const declared = readPackageManagerField(root);
3454
3466
  const presentLockPms = [
3455
3467
  ...new Set(
3456
- LOCKFILES.filter(({ file }) => fs8.existsSync(path9.join(root, file))).map(
3468
+ LOCKFILES.filter(({ file }) => fs8.existsSync(path10.join(root, file))).map(
3457
3469
  ({ pm }) => pm
3458
3470
  )
3459
3471
  )
@@ -3497,7 +3509,7 @@ function installCmd(pm, pkg, cwd) {
3497
3509
  if (cwd) {
3498
3510
  const { commandCwd, workspaceName } = resolveWorkspaceInstallRouting(cwd);
3499
3511
  if (workspaceName) {
3500
- const fromRoot = path9.resolve(commandCwd) !== path9.resolve(cwd) ? ` (run from ${commandCwd})` : "";
3512
+ const fromRoot = path10.resolve(commandCwd) !== path10.resolve(cwd) ? ` (run from ${commandCwd})` : "";
3501
3513
  switch (pm) {
3502
3514
  case "yarn":
3503
3515
  return `yarn workspace ${workspaceName} add ${pkg}${fromRoot}`;
@@ -3534,7 +3546,7 @@ function installDevCmd(pm, pkg) {
3534
3546
  }
3535
3547
  }
3536
3548
  function runTarballInstall(pm, tarballPath, cwd) {
3537
- const resolvedTarball = path9.resolve(tarballPath);
3549
+ const resolvedTarball = path10.resolve(tarballPath);
3538
3550
  if (!fs8.existsSync(resolvedTarball)) {
3539
3551
  throw new CLIError(`Tarball not found: ${resolvedTarball}`);
3540
3552
  }
@@ -3549,7 +3561,7 @@ function runSyncInstall2(pm, cwd) {
3549
3561
  runSyncInstall(pm, resolveDependencyInstallRoot(cwd));
3550
3562
  }
3551
3563
  function fixTarballDep(packageName, version, cwd = process.cwd()) {
3552
- const pkgPath = path9.join(cwd, "package.json");
3564
+ const pkgPath = path10.join(cwd, "package.json");
3553
3565
  if (!fs8.existsSync(pkgPath)) return;
3554
3566
  try {
3555
3567
  const pkg = fs8.readJsonSync(pkgPath);
@@ -3571,7 +3583,7 @@ function npmrcAuthLine(token) {
3571
3583
  }
3572
3584
  function ensureProjectNpmrc(cwd = process.cwd()) {
3573
3585
  const configRoot = resolveProjectConfigRoot(cwd);
3574
- const npmrcPath = path9.join(configRoot, ".npmrc");
3586
+ const npmrcPath = path10.join(configRoot, ".npmrc");
3575
3587
  let content = "";
3576
3588
  if (fs8.existsSync(npmrcPath)) {
3577
3589
  content = fs8.readFileSync(npmrcPath, "utf-8");
@@ -3590,7 +3602,7 @@ function ensureProjectNpmrc(cwd = process.cwd()) {
3590
3602
  atomicWriteFile(npmrcPath, result);
3591
3603
  }
3592
3604
  function writeGlobalNpmrcAuth(token) {
3593
- const globalNpmrc = path9.join(os3.homedir(), ".npmrc");
3605
+ const globalNpmrc = path10.join(os3.homedir(), ".npmrc");
3594
3606
  let content = "";
3595
3607
  if (fs8.existsSync(globalNpmrc)) {
3596
3608
  content = fs8.readFileSync(globalNpmrc, "utf-8");
@@ -3606,7 +3618,7 @@ function writeGlobalNpmrcAuth(token) {
3606
3618
  writeFileRestricted(globalNpmrc, result);
3607
3619
  }
3608
3620
  function removeGlobalNpmrcAuth() {
3609
- const globalNpmrc = path9.join(os3.homedir(), ".npmrc");
3621
+ const globalNpmrc = path10.join(os3.homedir(), ".npmrc");
3610
3622
  if (!fs8.existsSync(globalNpmrc)) return;
3611
3623
  const content = fs8.readFileSync(globalNpmrc, "utf-8");
3612
3624
  const url = new URL(`${API_BASE_URL}/registry/npm`);
@@ -3624,7 +3636,7 @@ function removeGlobalNpmrcAuth() {
3624
3636
  }
3625
3637
  function ensureGitignoreHasNpmrc(cwd = process.cwd()) {
3626
3638
  const configRoot = resolveProjectConfigRoot(cwd);
3627
- const giPath = path9.join(configRoot, ".gitignore");
3639
+ const giPath = path10.join(configRoot, ".gitignore");
3628
3640
  if (!fs8.existsSync(giPath)) return;
3629
3641
  const content = fs8.readFileSync(giPath, "utf-8");
3630
3642
  if (content.split("\n").some((l) => l.trim() === ".npmrc")) return;
@@ -3633,25 +3645,10 @@ function ensureGitignoreHasNpmrc(cwd = process.cwd()) {
3633
3645
  .npmrc
3634
3646
  `);
3635
3647
  }
3636
- var IUI_BUILD_CACHE_GITIGNORE_LINES = [
3637
- "",
3638
- "# IUI compile-first build cache (generated slot files under .iui/generated/ stay committed)",
3639
- ".iui/slot-registration-state.json",
3640
- ".iui/slot-registration.lock",
3641
- ".iui/classes.cache.json",
3642
- ".iui/utilities.css",
3643
- ".iui/build-styles.generated.css",
3644
- ".iui/build-styles.generated.js",
3645
- ".iui/build-manifest.generated.js",
3646
- ".iui/build-css-inline.js",
3647
- ".iui/build-manifest.json",
3648
- ".iui-bootstrap-client.js",
3649
- ".iui-bootstrap-server.js",
3650
- "public/iui/"
3651
- ];
3648
+ var IUI_BUILD_CACHE_GITIGNORE_LINES = IUI_CACHE_GITIGNORE_LINES;
3652
3649
  function ensureGitignoreHasIuiBuildCache(cwd = process.cwd()) {
3653
3650
  const configRoot = resolveProjectConfigRoot(cwd);
3654
- const giPath = path9.join(configRoot, ".gitignore");
3651
+ const giPath = path10.join(configRoot, ".gitignore");
3655
3652
  if (!fs8.existsSync(giPath)) return;
3656
3653
  const content = fs8.readFileSync(giPath, "utf-8");
3657
3654
  const lines = content.split("\n");
@@ -3665,7 +3662,7 @@ function ensureGitignoreHasIuiBuildCache(cwd = process.cwd()) {
3665
3662
  `);
3666
3663
  }
3667
3664
  function detectReactVersion(cwd = process.cwd()) {
3668
- const pkgPath = path9.join(cwd, "package.json");
3665
+ const pkgPath = path10.join(cwd, "package.json");
3669
3666
  if (!fs8.existsSync(pkgPath)) return { status: "not-installed" };
3670
3667
  try {
3671
3668
  const pkg = fs8.readJsonSync(pkgPath);
@@ -3683,7 +3680,7 @@ function detectReactVersion(cwd = process.cwd()) {
3683
3680
  }
3684
3681
  function getInstalledReactVersion(cwd) {
3685
3682
  try {
3686
- const reactPkgPath = path9.join(cwd, "node_modules", "react", "package.json");
3683
+ const reactPkgPath = path10.join(cwd, "node_modules", "react", "package.json");
3687
3684
  if (!fs8.existsSync(reactPkgPath)) return null;
3688
3685
  const reactPkg = fs8.readJsonSync(reactPkgPath);
3689
3686
  return reactPkg.version ?? null;
@@ -3697,7 +3694,7 @@ function isReact19(version) {
3697
3694
  return major === 19;
3698
3695
  }
3699
3696
  function detectReactDomVersion(cwd = process.cwd()) {
3700
- const pkgPath = path9.join(cwd, "package.json");
3697
+ const pkgPath = path10.join(cwd, "package.json");
3701
3698
  if (!fs8.existsSync(pkgPath)) return { status: "not-installed" };
3702
3699
  try {
3703
3700
  const pkg = fs8.readJsonSync(pkgPath);
@@ -3715,7 +3712,7 @@ function detectReactDomVersion(cwd = process.cwd()) {
3715
3712
  }
3716
3713
  function getInstalledReactDomVersion(cwd) {
3717
3714
  try {
3718
- const reactDomPkgPath = path9.join(cwd, "node_modules", "react-dom", "package.json");
3715
+ const reactDomPkgPath = path10.join(cwd, "node_modules", "react-dom", "package.json");
3719
3716
  if (!fs8.existsSync(reactDomPkgPath)) return null;
3720
3717
  const reactDomPkg = fs8.readJsonSync(reactDomPkgPath);
3721
3718
  return reactDomPkg.version ?? null;
@@ -3724,7 +3721,7 @@ function getInstalledReactDomVersion(cwd) {
3724
3721
  }
3725
3722
  }
3726
3723
  function detectViteVersion(cwd = process.cwd()) {
3727
- const pkgPath = path9.join(cwd, "package.json");
3724
+ const pkgPath = path10.join(cwd, "package.json");
3728
3725
  if (!fs8.existsSync(pkgPath)) return { status: "not-installed" };
3729
3726
  try {
3730
3727
  const pkg = fs8.readJsonSync(pkgPath);
@@ -3742,7 +3739,7 @@ function detectViteVersion(cwd = process.cwd()) {
3742
3739
  }
3743
3740
  function getInstalledViteVersion(cwd) {
3744
3741
  try {
3745
- const vitePkgPath = path9.join(cwd, "node_modules", "vite", "package.json");
3742
+ const vitePkgPath = path10.join(cwd, "node_modules", "vite", "package.json");
3746
3743
  if (!fs8.existsSync(vitePkgPath)) return null;
3747
3744
  const vitePkg = fs8.readJsonSync(vitePkgPath);
3748
3745
  return vitePkg.version ?? null;
@@ -3765,7 +3762,7 @@ function isViteSupported(version) {
3765
3762
  }
3766
3763
  function ensureInventiveUiViteConfig(cwd = process.cwd()) {
3767
3764
  if (!projectHasViteTooling(cwd)) return "skipped";
3768
- const configPath = path9.join(cwd, "vite.config.ts");
3765
+ const configPath = path10.join(cwd, "vite.config.ts");
3769
3766
  if (!fs8.existsSync(configPath)) {
3770
3767
  atomicWriteFile(configPath, MINIMAL_VITE_SCAFFOLD);
3771
3768
  return "scaffolded";
@@ -3779,13 +3776,13 @@ function ensureInventiveUiViteConfig(cwd = process.cwd()) {
3779
3776
  }
3780
3777
 
3781
3778
  // src/services/auth.ts
3782
- async function api(path26, opts) {
3783
- const res = await fetch(`${API_BASE_URL}${path26}`, {
3779
+ async function api(path28, opts) {
3780
+ const res = await fetch(`${API_BASE_URL}${path28}`, {
3784
3781
  ...opts,
3785
3782
  signal: opts?.signal ?? AbortSignal.timeout(API_REQUEST_TIMEOUT_MS),
3786
3783
  headers: { "Content-Type": "application/json", ...opts?.headers }
3787
3784
  });
3788
- throwIfRateLimited(res, `calling ${path26}`);
3785
+ throwIfRateLimited(res, `calling ${path28}`);
3789
3786
  if (!res.ok) {
3790
3787
  const body = await res.text().catch(() => "");
3791
3788
  throw new CLIError(`API error ${res.status}: ${body || res.statusText}`);
@@ -4233,7 +4230,7 @@ async function promptText(title, hint2, placeholder, validate) {
4233
4230
  }
4234
4231
 
4235
4232
  // src/commands/init.ts
4236
- import path21 from "path";
4233
+ import path23 from "path";
4237
4234
  import ora3 from "ora";
4238
4235
 
4239
4236
  // src/services/license.ts
@@ -4571,7 +4568,7 @@ async function fetchLatestCliVersion(token) {
4571
4568
  }
4572
4569
 
4573
4570
  // src/services/framework.ts
4574
- import path12 from "path";
4571
+ import path13 from "path";
4575
4572
  import fs10 from "fs-extra";
4576
4573
  import ora from "ora";
4577
4574
 
@@ -4580,7 +4577,7 @@ import { createWriteStream, mkdtempSync, unlinkSync, rmSync } from "fs";
4580
4577
  import { pipeline } from "stream/promises";
4581
4578
  import { Readable, Transform } from "stream";
4582
4579
  import os4 from "os";
4583
- import path10 from "path";
4580
+ import path11 from "path";
4584
4581
  var MAX_TARBALL_BYTES = 250 * 1024 * 1024;
4585
4582
  async function downloadPackageTarball(token, packageShortName) {
4586
4583
  if (!/^[a-z0-9][a-z0-9._-]*$/.test(packageShortName)) {
@@ -4624,8 +4621,8 @@ async function downloadPackageTarball(token, packageShortName) {
4624
4621
  );
4625
4622
  }
4626
4623
  }
4627
- const tmpDir = mkdtempSync(path10.join(os4.tmpdir(), "iui-dl-"));
4628
- const tempPath = path10.join(tmpDir, `${packageShortName}.tgz`);
4624
+ const tmpDir = mkdtempSync(path11.join(os4.tmpdir(), "iui-dl-"));
4625
+ const tempPath = path11.join(tmpDir, `${packageShortName}.tgz`);
4629
4626
  const fileStream = createWriteStream(tempPath, { flags: "wx" });
4630
4627
  let bytesWritten = 0;
4631
4628
  const limiter = new Transform({
@@ -4655,7 +4652,7 @@ async function downloadPackageTarball(token, packageShortName) {
4655
4652
  return { path: tempPath, version };
4656
4653
  }
4657
4654
  function cleanupTempFile(filePath) {
4658
- const parent = path10.dirname(filePath);
4655
+ const parent = path11.dirname(filePath);
4659
4656
  try {
4660
4657
  unlinkSync(filePath);
4661
4658
  } catch {
@@ -4669,7 +4666,7 @@ function cleanupTempFile(filePath) {
4669
4666
  }
4670
4667
 
4671
4668
  // src/utils/declared-deps.ts
4672
- import path11 from "path";
4669
+ import path12 from "path";
4673
4670
  import fs9 from "fs-extra";
4674
4671
  function shouldSyncDeclaredDependency(declared, installed) {
4675
4672
  const desired = `^${installed}`;
@@ -4687,7 +4684,7 @@ function readDepField(pkg, packageName) {
4687
4684
  return { field, declared };
4688
4685
  }
4689
4686
  function syncDeclaredDependencyVersion(packageName, cwd = process.cwd()) {
4690
- const pkgPath = path11.join(cwd, "package.json");
4687
+ const pkgPath = path12.join(cwd, "package.json");
4691
4688
  if (!fs9.existsSync(pkgPath)) return false;
4692
4689
  const installed = getInstalledPackageVersion(packageName, cwd);
4693
4690
  if (!installed) return false;
@@ -4701,8 +4698,14 @@ function syncDeclaredDependencyVersion(packageName, cwd = process.cwd()) {
4701
4698
  atomicWriteJson(pkgPath, pkg);
4702
4699
  return true;
4703
4700
  }
4701
+ function getDirectDeclaredVersionFloor(packageName, cwd = process.cwd()) {
4702
+ const declared = isPackageInDirectDeps(packageName, cwd);
4703
+ if (!declared) return null;
4704
+ const floor = cleanVersionString(declared);
4705
+ return floor || null;
4706
+ }
4704
4707
  function syncInventiveUiDeclaredDependencies(cwd = process.cwd()) {
4705
- const pkgPath = path11.join(cwd, "package.json");
4708
+ const pkgPath = path12.join(cwd, "package.json");
4706
4709
  if (!fs9.existsSync(pkgPath)) return [];
4707
4710
  const pkg = fs9.readJsonSync(pkgPath);
4708
4711
  const names = /* @__PURE__ */ new Set();
@@ -4869,7 +4872,10 @@ async function notifyIfUpdateAvailable(token, shortName, currentVersion, label)
4869
4872
  // src/services/framework.ts
4870
4873
  var FRAMEWORK_PACKAGE2 = "@inventive-ui/framework";
4871
4874
  function hasYarnPnP(cwd) {
4872
- return fs10.existsSync(path12.join(cwd, ".pnp.cjs")) || fs10.existsSync(path12.join(cwd, ".pnp.js"));
4875
+ return fs10.existsSync(path13.join(cwd, ".pnp.cjs")) || fs10.existsSync(path13.join(cwd, ".pnp.js"));
4876
+ }
4877
+ function getFrameworkUpdateBaselineVersion(cwd = process.cwd()) {
4878
+ return getDirectDeclaredVersionFloor(FRAMEWORK_PACKAGE2, cwd) ?? getInstalledPackageVersion(FRAMEWORK_PACKAGE2, cwd);
4873
4879
  }
4874
4880
  function getFrameworkInstallStatus(cwd = process.cwd()) {
4875
4881
  cleanupLegacyFrameworkMeta(cwd);
@@ -5083,7 +5089,7 @@ function normalizeFrameworkChoice(choice) {
5083
5089
  return null;
5084
5090
  }
5085
5091
  function hasViteConfig(cwd) {
5086
- return fs10.existsSync(path12.join(cwd, "vite.config.ts")) || fs10.existsSync(path12.join(cwd, "vite.config.mts")) || fs10.existsSync(path12.join(cwd, "vite.config.js")) || fs10.existsSync(path12.join(cwd, "vite.config.mjs")) || fs10.existsSync(path12.join(cwd, "vite.config.cjs"));
5092
+ return fs10.existsSync(path13.join(cwd, "vite.config.ts")) || fs10.existsSync(path13.join(cwd, "vite.config.mts")) || fs10.existsSync(path13.join(cwd, "vite.config.js")) || fs10.existsSync(path13.join(cwd, "vite.config.mjs")) || fs10.existsSync(path13.join(cwd, "vite.config.cjs"));
5087
5093
  }
5088
5094
  async function ensureReactRuntime(pm, cwd, autoApprove, react, reactDom) {
5089
5095
  if (react.status === "ok" && reactDom.status === "ok") {
@@ -5191,12 +5197,12 @@ function getMajorFromVersion(version) {
5191
5197
  import ora2 from "ora";
5192
5198
 
5193
5199
  // src/services/slot-registry.ts
5194
- import fs17 from "fs-extra";
5195
- import path20 from "path";
5200
+ import fs18 from "fs-extra";
5201
+ import path22 from "path";
5196
5202
 
5197
5203
  // src/services/registry-lock.ts
5198
5204
  import fs11 from "fs";
5199
- import path13 from "path";
5205
+ import path14 from "path";
5200
5206
  var LOCK_STALE_MS = 2 * 60 * 1e3;
5201
5207
  var LOCK_RETRY_MS = 80;
5202
5208
  var LOCK_TIMEOUT_MS = 1e4;
@@ -5204,7 +5210,7 @@ function sleep(ms) {
5204
5210
  return new Promise((resolve) => setTimeout(resolve, ms));
5205
5211
  }
5206
5212
  function lockPath(cwd) {
5207
- return path13.join(cwd, IUI_DIR, "slot-registration.lock");
5213
+ return iuiCacheFile(cwd, "slotLock");
5208
5214
  }
5209
5215
  function readLockAge(filePath) {
5210
5216
  try {
@@ -5224,7 +5230,7 @@ function removeStaleLock(filePath) {
5224
5230
  }
5225
5231
  async function acquireRegistryLock(cwd) {
5226
5232
  const filePath = lockPath(cwd);
5227
- fs11.mkdirSync(path13.dirname(filePath), { recursive: true });
5233
+ fs11.mkdirSync(path14.dirname(filePath), { recursive: true });
5228
5234
  const started = Date.now();
5229
5235
  while (Date.now() - started < LOCK_TIMEOUT_MS) {
5230
5236
  removeStaleLock(filePath);
@@ -5280,16 +5286,16 @@ async function withRegistryLock(cwd, operation) {
5280
5286
 
5281
5287
  // src/services/slots.ts
5282
5288
  import fs15 from "fs-extra";
5283
- import path18 from "path";
5289
+ import path19 from "path";
5284
5290
 
5285
5291
  // src/utils/public-slot-contract.ts
5286
- import path14 from "path";
5292
+ import path15 from "path";
5287
5293
  import fs12 from "fs-extra";
5288
5294
  var CONTRACT_FILENAME = "public-slot-contract.json";
5289
5295
  function loadPublicSlotContract(cwd = process.cwd()) {
5290
5296
  const pkgRoot = resolvePackageDir("@inventive-ui/components", cwd);
5291
5297
  if (!pkgRoot) return null;
5292
- const contractPath = path14.join(pkgRoot, CONTRACT_FILENAME);
5298
+ const contractPath = path15.join(pkgRoot, CONTRACT_FILENAME);
5293
5299
  if (!fs12.existsSync(contractPath)) return null;
5294
5300
  try {
5295
5301
  return fs12.readJsonSync(contractPath);
@@ -5367,7 +5373,7 @@ function collectInstalledSlotEmitters(items, installedSlugs, cwd = process.cwd()
5367
5373
 
5368
5374
  // src/utils/security/fsSafe.ts
5369
5375
  import fs13 from "fs";
5370
- import path15 from "path";
5376
+ import path16 from "path";
5371
5377
  function assertNotSymlink(filePath, label) {
5372
5378
  try {
5373
5379
  const stat = fs13.lstatSync(filePath);
@@ -5381,11 +5387,11 @@ function assertNotSymlink(filePath, label) {
5381
5387
  }
5382
5388
  }
5383
5389
  function safeWriteFile(filePath, content) {
5384
- const dir = path15.dirname(filePath);
5390
+ const dir = path16.dirname(filePath);
5385
5391
  if (fs13.existsSync(dir)) {
5386
5392
  assertNotSymlink(dir, "directory");
5387
5393
  }
5388
- const parent = path15.dirname(filePath);
5394
+ const parent = path16.dirname(filePath);
5389
5395
  fs13.mkdirSync(parent, { recursive: true });
5390
5396
  if (fs13.existsSync(filePath)) {
5391
5397
  assertNotSymlink(filePath, "file");
@@ -5395,22 +5401,22 @@ function safeWriteFile(filePath, content) {
5395
5401
 
5396
5402
  // src/services/asset-bound.ts
5397
5403
  import fs14 from "fs-extra";
5398
- import path17 from "path";
5404
+ import path18 from "path";
5399
5405
  import { pathToFileURL } from "url";
5400
5406
 
5401
5407
  // src/services/generated-paths.ts
5402
- import path16 from "path";
5403
- function iuiProjectRoot(cwd) {
5408
+ import path17 from "path";
5409
+ function iuiProjectRoot2(cwd) {
5404
5410
  return resolveIuiProjectRoot(cwd);
5405
5411
  }
5406
5412
  function generatedIuiDir(cwd) {
5407
- return path16.join(iuiProjectRoot(cwd), ".iui", "generated");
5413
+ return path17.join(iuiProjectRoot2(cwd), ".iui", "generated");
5408
5414
  }
5409
5415
  function generatedSlotsDir(cwd) {
5410
- return path16.join(generatedIuiDir(cwd), "slots");
5416
+ return path17.join(generatedIuiDir(cwd), "slots");
5411
5417
  }
5412
5418
  function generatedAssetsDir(cwd) {
5413
- return path16.join(generatedIuiDir(cwd), "assets");
5419
+ return path17.join(generatedIuiDir(cwd), "assets");
5414
5420
  }
5415
5421
 
5416
5422
  // src/services/asset-bound.ts
@@ -5507,21 +5513,21 @@ function resolveFrameworkModule(cwd, relativePath) {
5507
5513
  const searchRoots = /* @__PURE__ */ new Set();
5508
5514
  for (const candidate of [
5509
5515
  resolveDependencyInstallRoot(cwd),
5510
- path17.resolve(cwd),
5511
- iuiProjectRoot(cwd)
5516
+ path18.resolve(cwd),
5517
+ iuiProjectRoot2(cwd)
5512
5518
  ]) {
5513
- searchRoots.add(path17.resolve(candidate));
5519
+ searchRoots.add(path18.resolve(candidate));
5514
5520
  }
5515
5521
  for (const start of searchRoots) {
5516
5522
  const frameworkDir = resolvePackageDir("@inventive-ui/framework", start);
5517
5523
  if (!frameworkDir) continue;
5518
- const installed = path17.join(frameworkDir, relativePath);
5524
+ const installed = path18.join(frameworkDir, relativePath);
5519
5525
  if (fs14.existsSync(installed)) return installed;
5520
5526
  }
5521
- const root = iuiProjectRoot(cwd);
5527
+ const root = iuiProjectRoot2(cwd);
5522
5528
  for (const candidate of [
5523
- path17.join(root, "..", "Framework", relativePath),
5524
- path17.join(root, "..", "..", "Framework", relativePath)
5529
+ path18.join(root, "..", "Framework", relativePath),
5530
+ path18.join(root, "..", "..", "Framework", relativePath)
5525
5531
  ]) {
5526
5532
  if (fs14.existsSync(candidate)) return candidate;
5527
5533
  }
@@ -5599,7 +5605,7 @@ function cleanupAssetBoundFiles(cwd) {
5599
5605
  if (!fs14.existsSync(assetsDir)) return;
5600
5606
  for (const file of fs14.readdirSync(assetsDir)) {
5601
5607
  if (file.endsWith(".bound.ts") || file === "register-bound.ts") {
5602
- fs14.removeSync(path17.join(assetsDir, file));
5608
+ fs14.removeSync(path18.join(assetsDir, file));
5603
5609
  }
5604
5610
  }
5605
5611
  const remaining = fs14.readdirSync(assetsDir);
@@ -5608,10 +5614,10 @@ function cleanupAssetBoundFiles(cwd) {
5608
5614
  }
5609
5615
  }
5610
5616
  function hasAssetBoundRegistration(cwd) {
5611
- return fs14.existsSync(path17.join(generatedAssetsDir(cwd), "register-bound.ts"));
5617
+ return fs14.existsSync(path18.join(generatedAssetsDir(cwd), "register-bound.ts"));
5612
5618
  }
5613
5619
  async function writeAssetBoundFiles(cwd = process.cwd()) {
5614
- const root = iuiProjectRoot(cwd);
5620
+ const root = iuiProjectRoot2(cwd);
5615
5621
  const scanUtils = await loadScanUtils(cwd);
5616
5622
  const activeSpecs = BOUND_SPECS.filter(
5617
5623
  (spec) => scanUtils.isScannedAssetBindingEnabled(root, spec.slotType)
@@ -5667,7 +5673,7 @@ async function writeAssetBoundFiles(cwd = process.cwd()) {
5667
5673
  const existing = fs14.existsSync(assetsDir) ? fs14.readdirSync(assetsDir).filter((f) => f.endsWith(".bound.ts")) : [];
5668
5674
  for (const file of existing) {
5669
5675
  if (!generatedFiles.has(file)) {
5670
- fs14.removeSync(path17.join(assetsDir, file));
5676
+ fs14.removeSync(path18.join(assetsDir, file));
5671
5677
  }
5672
5678
  }
5673
5679
  if (registrationSpecs.length === 0) {
@@ -5702,27 +5708,27 @@ function assetModuleCandidates(pkgRoot, moduleId) {
5702
5708
  const pkgId = pkgName.replace("@inventive-ui/", "");
5703
5709
  if (!subpath || subpath.includes("..")) return [];
5704
5710
  if (pkgId === "loaders") {
5705
- return [path17.join(pkgRoot, "dist", "loaders", `${subpath}.js`)];
5711
+ return [path18.join(pkgRoot, "dist", "loaders", `${subpath}.js`)];
5706
5712
  }
5707
5713
  if (pkgId === "illustrations") {
5708
5714
  const [family, scene] = subpath.split("/");
5709
5715
  if (family && scene) {
5710
- return [path17.join(pkgRoot, "dist", family, `${scene}.js`)];
5716
+ return [path18.join(pkgRoot, "dist", family, `${scene}.js`)];
5711
5717
  }
5712
- return [path17.join(pkgRoot, "dist", `${subpath}.js`)];
5718
+ return [path18.join(pkgRoot, "dist", `${subpath}.js`)];
5713
5719
  }
5714
5720
  const prefix = PKG_LOOKUP_PREFIX[pkgId];
5715
5721
  if (prefix) {
5716
5722
  const dir = prefix.replace(/\/$/, "");
5717
5723
  return [
5718
- path17.join(pkgRoot, "dist", dir, `${subpath}.js`),
5719
- path17.join(pkgRoot, "dist", `${subpath}.js`),
5720
- path17.join(pkgRoot, "dist", subpath, "index.js")
5724
+ path18.join(pkgRoot, "dist", dir, `${subpath}.js`),
5725
+ path18.join(pkgRoot, "dist", `${subpath}.js`),
5726
+ path18.join(pkgRoot, "dist", subpath, "index.js")
5721
5727
  ];
5722
5728
  }
5723
5729
  return [
5724
- path17.join(pkgRoot, "dist", `${subpath}.js`),
5725
- path17.join(pkgRoot, "dist", subpath, "index.js")
5730
+ path18.join(pkgRoot, "dist", `${subpath}.js`),
5731
+ path18.join(pkgRoot, "dist", subpath, "index.js")
5726
5732
  ];
5727
5733
  }
5728
5734
  function validateGeneratedAssetBoundImports(cwd = process.cwd()) {
@@ -5731,7 +5737,7 @@ function validateGeneratedAssetBoundImports(cwd = process.cwd()) {
5731
5737
  const issues = [];
5732
5738
  const boundFiles = fs14.readdirSync(assetsDir).filter((file) => file.endsWith(".bound.ts"));
5733
5739
  for (const file of boundFiles) {
5734
- const content = fs14.readFileSync(path17.join(assetsDir, file), "utf8");
5740
+ const content = fs14.readFileSync(path18.join(assetsDir, file), "utf8");
5735
5741
  const importRe = /from\s+["'](@inventive-ui\/[^"']+)["']/g;
5736
5742
  let match;
5737
5743
  while ((match = importRe.exec(content)) !== null) {
@@ -5755,16 +5761,16 @@ function validateGeneratedAssetBoundImports(cwd = process.cwd()) {
5755
5761
  var SLOT_GROUP_CORE_FILE = "slot-core.generated.tsx";
5756
5762
  var SLOT_GROUP_OPTIONAL_FILE = "slot-optional.generated.tsx";
5757
5763
  function bridgeSlotFilePath(cwd) {
5758
- return path18.join(cwd, "src", "iui", "slot.tsx");
5764
+ return path19.join(cwd, "src", "iui", "slot.tsx");
5759
5765
  }
5760
5766
  function cleanupLegacySourceSlotFiles(cwd) {
5761
- const legacySlotsDir = path18.join(cwd, "src", "iui", "slots");
5767
+ const legacySlotsDir = path19.join(cwd, "src", "iui", "slots");
5762
5768
  if (!fs15.existsSync(legacySlotsDir)) return;
5763
5769
  try {
5764
5770
  const files = fs15.readdirSync(legacySlotsDir);
5765
5771
  for (const file of files) {
5766
5772
  if (file.endsWith(".slot.tsx")) {
5767
- fs15.removeSync(path18.join(legacySlotsDir, file));
5773
+ fs15.removeSync(path19.join(legacySlotsDir, file));
5768
5774
  }
5769
5775
  }
5770
5776
  const remaining = fs15.readdirSync(legacySlotsDir);
@@ -5832,7 +5838,7 @@ function writeComponentSlotFiles(cwd = process.cwd()) {
5832
5838
  const existingSlots2 = fs15.readdirSync(slotsDir).filter((f) => f.endsWith(".slot.tsx"));
5833
5839
  for (const file of existingSlots2) {
5834
5840
  try {
5835
- fs15.removeSync(path18.join(slotsDir, file));
5841
+ fs15.removeSync(path19.join(slotsDir, file));
5836
5842
  } catch {
5837
5843
  }
5838
5844
  }
@@ -5862,7 +5868,7 @@ function writeComponentSlotFiles(cwd = process.cwd()) {
5862
5868
  if (policy === "core") coreEmitters.push(emitter);
5863
5869
  else optionalEmitters.push(emitter);
5864
5870
  }
5865
- const root = iuiProjectRoot(cwd);
5871
+ const root = iuiProjectRoot2(cwd);
5866
5872
  const renderedGroups = [
5867
5873
  { fileName: SLOT_GROUP_CORE_FILE, emitters: coreEmitters },
5868
5874
  { fileName: SLOT_GROUP_OPTIONAL_FILE, emitters: optionalEmitters }
@@ -5880,14 +5886,14 @@ function writeComponentSlotFiles(cwd = process.cwd()) {
5880
5886
  if (file === SLOT_GROUP_CORE_FILE || file === SLOT_GROUP_OPTIONAL_FILE) continue;
5881
5887
  if (file.endsWith(".slot.tsx")) {
5882
5888
  try {
5883
- fs15.removeSync(path18.join(slotsDir, file));
5889
+ fs15.removeSync(path19.join(slotsDir, file));
5884
5890
  } catch {
5885
5891
  }
5886
5892
  continue;
5887
5893
  }
5888
5894
  if (file.endsWith(".generated.tsx")) {
5889
5895
  try {
5890
- fs15.removeSync(path18.join(slotsDir, file));
5896
+ fs15.removeSync(path19.join(slotsDir, file));
5891
5897
  } catch {
5892
5898
  }
5893
5899
  }
@@ -5988,15 +5994,15 @@ function writeSlotHelperFile(cwd = process.cwd()) {
5988
5994
  }
5989
5995
  const typesArray = Array.from(slotTypes).sort();
5990
5996
  const slotImports = [];
5991
- const coreSlotsPath = path18.join(generatedSlotsDir(cwd), SLOT_GROUP_CORE_FILE);
5992
- const optionalSlotsPath = path18.join(generatedSlotsDir(cwd), SLOT_GROUP_OPTIONAL_FILE);
5997
+ const coreSlotsPath = path19.join(generatedSlotsDir(cwd), SLOT_GROUP_CORE_FILE);
5998
+ const optionalSlotsPath = path19.join(generatedSlotsDir(cwd), SLOT_GROUP_OPTIONAL_FILE);
5993
5999
  if (fs15.existsSync(coreSlotsPath)) slotImports.push(`import "./slots/${SLOT_GROUP_CORE_FILE.replace(/\.tsx$/, "")}";`);
5994
6000
  if (fs15.existsSync(optionalSlotsPath)) slotImports.push(`import "./slots/${SLOT_GROUP_OPTIONAL_FILE.replace(/\.tsx$/, "")}";`);
5995
6001
  const componentSlotImports = slotImports.join("\n");
5996
6002
  const includeAssetBindings = hasAssetBoundRegistration(cwd);
5997
6003
  const outDir = generatedIuiDir(cwd);
5998
6004
  fs15.ensureDirSync(outDir);
5999
- const outPath = path18.join(outDir, "slot.generated.tsx");
6005
+ const outPath = path19.join(outDir, "slot.generated.tsx");
6000
6006
  const sections = [
6001
6007
  `// Managed by iui. Do not edit manually.`,
6002
6008
  `// Rebuilt automatically when the CLI validates the project.`
@@ -6029,11 +6035,11 @@ ${typesArray.map((t) => ` | "${t}"`).join("\n")};` : `export type IUISlotType =
6029
6035
  const content = sections.join("\n");
6030
6036
  safeWriteFile(outPath, content);
6031
6037
  }
6032
- function writeSlotBridge(packageDir, iuiRoot) {
6038
+ function writeSlotBridge(packageDir, iuiRoot2) {
6033
6039
  const bridgePath = bridgeSlotFilePath(packageDir);
6034
- const generatedFile = path18.join(iuiRoot, ".iui", "generated", "slot.generated.tsx");
6035
- const importBase = relativeImportPath(path18.dirname(bridgePath), generatedFile);
6036
- fs15.ensureDirSync(path18.dirname(bridgePath));
6040
+ const generatedFile = path19.join(iuiRoot2, ".iui", "generated", "slot.generated.tsx");
6041
+ const importBase = relativeImportPath(path19.dirname(bridgePath), generatedFile);
6042
+ fs15.ensureDirSync(path19.dirname(bridgePath));
6037
6043
  if (fs15.existsSync(bridgePath)) {
6038
6044
  const existing = fs15.readFileSync(bridgePath, "utf-8");
6039
6045
  if (existing.length > 0 && !/@iui-managed/.test(existing)) {
@@ -6052,19 +6058,158 @@ export type { IUISlotType } from "${importBase}";
6052
6058
  }
6053
6059
 
6054
6060
  // src/services/workspace-bootstrap.ts
6055
- import path19 from "path";
6061
+ import path21 from "path";
6062
+ import fs17 from "fs-extra";
6063
+
6064
+ // src/services/bootstrap.ts
6056
6065
  import fs16 from "fs-extra";
6057
- function workspaceManifestPath(iuiRoot) {
6058
- return path19.join(iuiRoot, IUI_DIR, "workspace.json");
6066
+ import path20 from "path";
6067
+ var BOOTSTRAP_GENERATED_FILE = "bootstrap.generated.tsx";
6068
+ function bridgeBootstrapFilePath(cwd) {
6069
+ return path20.join(cwd, "src", "iui", "bootstrap.ts");
6070
+ }
6071
+ function bootstrapGeneratedPath(cwd = process.cwd()) {
6072
+ return path20.join(generatedIuiDir(cwd), BOOTSTRAP_GENERATED_FILE);
6073
+ }
6074
+ function resolveProjectConfigPaths(cwd) {
6075
+ const meta = readProjectMeta(cwd);
6076
+ const configs = meta?.configs;
6077
+ if (configs?.theme && configs?.assets && configs?.components) {
6078
+ return configs;
6079
+ }
6080
+ return {
6081
+ theme: PROJECT_CONFIG_FILE,
6082
+ assets: ASSETS_CONFIG_FILE,
6083
+ components: COMPONENT_CONFIG_FILE
6084
+ };
6085
+ }
6086
+ function configImportFromGenerated(cwd, configRel) {
6087
+ const generatedDir = path20.dirname(bootstrapGeneratedPath(cwd));
6088
+ const abs = path20.resolve(cwd, configRel.replace(/^\.\//, ""));
6089
+ return relativeImportPath(generatedDir, abs);
6059
6090
  }
6060
- function readWorkspaceManifest(iuiRoot) {
6061
- const p = workspaceManifestPath(iuiRoot);
6062
- if (!fs16.existsSync(p)) return null;
6091
+ function expectedBootstrapImportPaths(cwd) {
6092
+ const configs = resolveProjectConfigPaths(cwd);
6093
+ return {
6094
+ theme: configImportFromGenerated(cwd, configs.theme),
6095
+ assets: configImportFromGenerated(cwd, configs.assets),
6096
+ components: configImportFromGenerated(cwd, configs.components)
6097
+ };
6098
+ }
6099
+ function writeBootstrapGenerated(cwd = process.cwd()) {
6100
+ const outPath = bootstrapGeneratedPath(cwd);
6101
+ fs16.ensureDirSync(path20.dirname(outPath));
6102
+ const imports = expectedBootstrapImportPaths(cwd);
6103
+ const content = `// @iui-managed
6104
+
6105
+ // Generated by iui CLI \u2014 do not edit manually.
6106
+
6107
+ // Connects iui.config.ts + assets.config.json + component.config.ts for standard bootstrap.
6108
+
6109
+
6110
+
6111
+ import theme from "${imports.theme}";
6112
+
6113
+ import assets from "${imports.assets}";
6114
+
6115
+ import { componentConfig as projectComponentConfig } from "${imports.components}";
6116
+
6117
+ import {
6118
+
6119
+ mergeProjectConfig,
6120
+
6121
+ initFramework,
6122
+
6123
+ registerBootstrapState,
6124
+
6125
+ } from "@inventive-ui/framework";
6126
+
6127
+ import { initConfig as initSlotsConfig } from "@inventive-ui/framework/slots";
6128
+
6129
+ import type { IUIAssetsConfig } from "@inventive-ui/framework/config";
6130
+
6131
+
6132
+
6133
+ import "./slot.generated";
6134
+
6135
+
6136
+
6137
+ const themeConfig = (theme as { default?: typeof theme }).default ?? theme;
6138
+
6139
+
6140
+
6141
+ export const frameworkConfig = mergeProjectConfig(
6142
+
6143
+ themeConfig,
6144
+
6145
+ assets as IUIAssetsConfig,
6146
+
6147
+ );
6148
+
6149
+
6150
+
6151
+ registerBootstrapState({
6152
+
6153
+ frameworkConfig,
6154
+
6155
+ componentConfig: projectComponentConfig,
6156
+
6157
+ });
6158
+
6159
+
6160
+
6161
+ initFramework(frameworkConfig);
6162
+
6163
+ initSlotsConfig(frameworkConfig);
6164
+
6165
+
6166
+
6167
+ export { projectComponentConfig as componentConfig };
6168
+
6169
+ `;
6170
+ safeWriteFile(outPath, content);
6171
+ }
6172
+ function writeBootstrapBridge(packageDir, iuiRoot2) {
6173
+ const bridgePath = bridgeBootstrapFilePath(packageDir);
6174
+ const generatedFile = bootstrapGeneratedPath(iuiRoot2);
6175
+ const importBase = relativeImportPath(path20.dirname(bridgePath), generatedFile);
6176
+ fs16.ensureDirSync(path20.dirname(bridgePath));
6177
+ if (fs16.existsSync(bridgePath)) {
6178
+ const existing = fs16.readFileSync(bridgePath, "utf-8");
6179
+ if (existing.length > 0 && !/@iui-managed/.test(existing)) {
6180
+ return;
6181
+ }
6182
+ }
6183
+ const bridgeContent = `// Managed by iui. Do not edit manually.
6184
+
6185
+ // @iui-managed
6186
+
6187
+ // Standard bootstrap: wires theme + assets + component configs before IUIProvider.
6188
+
6189
+
6190
+
6191
+ import "${importBase}";
6192
+
6193
+ `;
6194
+ safeWriteFile(bridgePath, bridgeContent);
6195
+ }
6196
+ function writeProjectBootstrapArtifacts(packageDir, iuiRoot2) {
6197
+ writeBootstrapGenerated(iuiRoot2);
6198
+ writeBootstrapBridge(packageDir, iuiRoot2);
6199
+ }
6200
+
6201
+ // src/services/workspace-bootstrap.ts
6202
+ function workspaceManifestPath(iuiRoot2) {
6203
+ return path21.join(iuiRoot2, IUI_DIR, "workspace.json");
6204
+ }
6205
+ function readWorkspaceManifest(iuiRoot2) {
6206
+ const p = workspaceManifestPath(iuiRoot2);
6207
+ if (!fs17.existsSync(p)) return null;
6063
6208
  try {
6064
- const raw = fs16.readJsonSync(p);
6209
+ const raw = fs17.readJsonSync(p);
6065
6210
  if (!Array.isArray(raw.packages)) return null;
6066
6211
  return {
6067
- iuiRoot: raw.iuiRoot ?? iuiRoot,
6212
+ iuiRoot: raw.iuiRoot ?? iuiRoot2,
6068
6213
  packages: raw.packages.map(String),
6069
6214
  updatedAt: raw.updatedAt ?? ""
6070
6215
  };
@@ -6072,63 +6217,64 @@ function readWorkspaceManifest(iuiRoot) {
6072
6217
  return null;
6073
6218
  }
6074
6219
  }
6075
- function writeWorkspaceManifest(iuiRoot, packageDirs) {
6076
- const unique = [...new Set(packageDirs.map((dir) => path19.resolve(dir)))];
6077
- atomicWriteJson(workspaceManifestPath(iuiRoot), {
6078
- iuiRoot,
6079
- packages: unique.map((dir) => path19.relative(iuiRoot, dir) || "."),
6220
+ function writeWorkspaceManifest(iuiRoot2, packageDirs) {
6221
+ const unique = [...new Set(packageDirs.map((dir) => path21.resolve(dir)))];
6222
+ atomicWriteJson(workspaceManifestPath(iuiRoot2), {
6223
+ iuiRoot: iuiRoot2,
6224
+ packages: unique.map((dir) => path21.relative(iuiRoot2, dir) || "."),
6080
6225
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
6081
6226
  });
6082
6227
  }
6083
- function resolveRegisteredPackageDirs(iuiRoot) {
6084
- const resolvedRoot = path19.resolve(iuiRoot);
6228
+ function resolveRegisteredPackageDirs(iuiRoot2) {
6229
+ const resolvedRoot = path21.resolve(iuiRoot2);
6085
6230
  const manifest = readWorkspaceManifest(resolvedRoot);
6086
6231
  if (!manifest) return [resolvedRoot];
6087
6232
  const dirs = manifest.packages.map(
6088
- (rel) => path19.resolve(resolvedRoot, rel === "." ? "" : rel)
6233
+ (rel) => path21.resolve(resolvedRoot, rel === "." ? "" : rel)
6089
6234
  );
6090
- if (!dirs.some((dir) => path19.resolve(dir) === resolvedRoot)) {
6235
+ if (!dirs.some((dir) => path21.resolve(dir) === resolvedRoot)) {
6091
6236
  dirs.unshift(resolvedRoot);
6092
6237
  }
6093
6238
  return dirs;
6094
6239
  }
6095
- function registerWorkspacePackage(iuiRoot, packageDir) {
6096
- const resolvedRoot = path19.resolve(iuiRoot);
6097
- const resolvedPackage = path19.resolve(packageDir);
6240
+ function registerWorkspacePackage(iuiRoot2, packageDir) {
6241
+ const resolvedRoot = path21.resolve(iuiRoot2);
6242
+ const resolvedPackage = path21.resolve(packageDir);
6098
6243
  const existing = resolveRegisteredPackageDirs(resolvedRoot);
6099
- if (!existing.some((dir) => path19.resolve(dir) === resolvedPackage)) {
6244
+ if (!existing.some((dir) => path21.resolve(dir) === resolvedPackage)) {
6100
6245
  existing.push(resolvedPackage);
6101
6246
  }
6102
6247
  writeWorkspaceManifest(resolvedRoot, existing);
6103
6248
  }
6104
- function registerAllWorkspacePackages(iuiRoot) {
6105
- const resolvedRoot = path19.resolve(iuiRoot);
6249
+ function registerAllWorkspacePackages(iuiRoot2) {
6250
+ const resolvedRoot = path21.resolve(iuiRoot2);
6106
6251
  const workspaceRoot = findWorkspaceRoot(resolvedRoot);
6107
6252
  const targets = /* @__PURE__ */ new Set([resolvedRoot]);
6108
6253
  if (workspaceRoot) {
6109
6254
  for (const pkgDir of listWorkspacePackageDirs(workspaceRoot)) {
6110
- targets.add(path19.resolve(pkgDir));
6255
+ targets.add(path21.resolve(pkgDir));
6111
6256
  }
6112
6257
  }
6113
6258
  const dirs = [...targets];
6114
6259
  writeWorkspaceManifest(resolvedRoot, dirs);
6115
6260
  return dirs;
6116
6261
  }
6117
- function bootstrapRegisteredPackages(iuiRoot) {
6118
- const resolvedRoot = resolveIuiProjectRoot(iuiRoot);
6262
+ function bootstrapRegisteredPackages(iuiRoot2) {
6263
+ const resolvedRoot = resolveIuiProjectRoot(iuiRoot2);
6119
6264
  const bootstrapped = [];
6120
6265
  for (const packageDir of resolveRegisteredPackageDirs(resolvedRoot)) {
6121
- if (!fs16.existsSync(path19.join(packageDir, "package.json"))) continue;
6266
+ if (!fs17.existsSync(path21.join(packageDir, "package.json"))) continue;
6122
6267
  ensureProjectNpmrc(packageDir);
6123
6268
  writeSlotBridge(packageDir, resolvedRoot);
6269
+ writeProjectBootstrapArtifacts(packageDir, resolvedRoot);
6124
6270
  bootstrapped.push(packageDir);
6125
6271
  }
6126
6272
  return bootstrapped;
6127
6273
  }
6128
- async function bootstrapWorkspacePackage(packageDir, iuiRoot) {
6129
- const resolvedPackage = path19.resolve(packageDir);
6130
- const resolvedIuiRoot = resolveIuiProjectRoot(iuiRoot);
6131
- if (!fs16.existsSync(path19.join(resolvedPackage, "package.json"))) {
6274
+ async function bootstrapWorkspacePackage(packageDir, iuiRoot2) {
6275
+ const resolvedPackage = path21.resolve(packageDir);
6276
+ const resolvedIuiRoot = resolveIuiProjectRoot(iuiRoot2);
6277
+ if (!fs17.existsSync(path21.join(resolvedPackage, "package.json"))) {
6132
6278
  throw new CLIError(
6133
6279
  `No package.json found in ${resolvedPackage}.`,
6134
6280
  "Run iui init from a workspace app directory that contains package.json."
@@ -6146,7 +6292,7 @@ async function bootstrapWorkspacePackage(packageDir, iuiRoot) {
6146
6292
  "This app is linked to an existing IUI setup \u2014 packages and configs stay at the IUI root."
6147
6293
  );
6148
6294
  nextSteps([
6149
- 'import "./iui/slot" in your app entry',
6295
+ 'import "./iui/bootstrap" in your app entry (or rely on Vite auto-wiring)',
6150
6296
  "iui doctor \u2014 Verify project health",
6151
6297
  "iui list \u2014 View installed components"
6152
6298
  ]);
@@ -6154,9 +6300,8 @@ async function bootstrapWorkspacePackage(packageDir, iuiRoot) {
6154
6300
 
6155
6301
  // src/services/slot-registry.ts
6156
6302
  var STATE_SCHEMA_VERSION = 1;
6157
- var STATE_FILE = "slot-registration-state.json";
6158
6303
  function statePath(cwd) {
6159
- return path20.join(cwd, IUI_DIR, STATE_FILE);
6304
+ return iuiCacheFile(cwd, "slotState");
6160
6305
  }
6161
6306
  function now() {
6162
6307
  return (/* @__PURE__ */ new Date()).toISOString();
@@ -6165,17 +6310,17 @@ function checksumFor(components, slots) {
6165
6310
  return sha256(JSON.stringify({ components, slots }));
6166
6311
  }
6167
6312
  function backupCorruptFile(filePath) {
6168
- if (!fs17.existsSync(filePath)) return;
6313
+ if (!fs18.existsSync(filePath)) return;
6169
6314
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
6170
6315
  try {
6171
- fs17.moveSync(filePath, `${filePath}.corrupt-${stamp}`, { overwrite: false });
6316
+ fs18.moveSync(filePath, `${filePath}.corrupt-${stamp}`, { overwrite: false });
6172
6317
  } catch {
6173
6318
  }
6174
6319
  }
6175
6320
  function readJsonObject(filePath, fallback, issues, label) {
6176
- if (!fs17.existsSync(filePath)) return fallback;
6321
+ if (!fs18.existsSync(filePath)) return fallback;
6177
6322
  try {
6178
- const value = fs17.readJsonSync(filePath);
6323
+ const value = fs18.readJsonSync(filePath);
6179
6324
  if (value && typeof value === "object" && !Array.isArray(value)) {
6180
6325
  return value;
6181
6326
  }
@@ -6187,9 +6332,9 @@ function readJsonObject(filePath, fallback, issues, label) {
6187
6332
  }
6188
6333
  function readState(cwd, issues) {
6189
6334
  const filePath = statePath(cwd);
6190
- if (!fs17.existsSync(filePath)) return null;
6335
+ if (!fs18.existsSync(filePath)) return null;
6191
6336
  try {
6192
- const raw = fs17.readJsonSync(filePath);
6337
+ const raw = fs18.readJsonSync(filePath);
6193
6338
  if (raw.schemaVersion !== STATE_SCHEMA_VERSION) {
6194
6339
  issues.push("registration state schema was upgraded");
6195
6340
  return null;
@@ -6291,9 +6436,9 @@ async function ensureSlotRegistry(options = {}) {
6291
6436
  if (!isInsideProject(cwd)) {
6292
6437
  return { status: "skipped", packageVersion: null, repairedIssues: [] };
6293
6438
  }
6294
- const iuiRoot = resolveIuiProjectRoot(cwd);
6295
- return withRegistryLock(iuiRoot, async () => {
6296
- const iuiPath = path20.join(iuiRoot, IUI_DIR);
6439
+ const iuiRoot2 = resolveIuiProjectRoot(cwd);
6440
+ return withRegistryLock(iuiRoot2, async () => {
6441
+ const iuiPath = path22.join(iuiRoot2, IUI_DIR);
6297
6442
  const issues = [];
6298
6443
  cleanupTempFiles(iuiPath);
6299
6444
  const registry = ensureInstalledManifest(
@@ -6304,23 +6449,23 @@ async function ensureSlotRegistry(options = {}) {
6304
6449
  return { status: "skipped", packageVersion: null, repairedIssues: [] };
6305
6450
  }
6306
6451
  const packageVersion = getInstalledPackageVersion(COMPONENTS_PACKAGE, cwd) ?? registry.version;
6307
- const previousState = readState(iuiRoot, issues);
6452
+ const previousState = readState(iuiRoot2, issues);
6308
6453
  let state = null;
6309
6454
  try {
6310
6455
  const currentComponents = readJsonObject(
6311
- componentManifestPath(iuiRoot),
6456
+ componentManifestPath(iuiRoot2),
6312
6457
  {},
6313
6458
  issues,
6314
6459
  ".iui/components.json"
6315
6460
  );
6316
6461
  const currentPackages = readJsonObject(
6317
- packageManifestPath(iuiRoot),
6462
+ packageManifestPath(iuiRoot2),
6318
6463
  {},
6319
6464
  issues,
6320
6465
  ".iui/packages.json"
6321
6466
  );
6322
6467
  const currentSlots = readJsonObject(
6323
- slotManifestPath(iuiRoot),
6468
+ slotManifestPath(iuiRoot2),
6324
6469
  {},
6325
6470
  issues,
6326
6471
  ".iui/slots.json"
@@ -6347,8 +6492,8 @@ async function ensureSlotRegistry(options = {}) {
6347
6492
  if (driftDetected) {
6348
6493
  issues.push("slot manifests drifted");
6349
6494
  }
6350
- const generationIssues = validateGeneratedSlotImports(iuiRoot);
6351
- const assetBoundIssues = validateGeneratedAssetBoundImports(iuiRoot);
6495
+ const generationIssues = validateGeneratedSlotImports(iuiRoot2);
6496
+ const assetBoundIssues = validateGeneratedAssetBoundImports(iuiRoot2);
6352
6497
  const integrityIssues = [...generationIssues, ...assetBoundIssues];
6353
6498
  if (shouldSkipWritesFastPath({
6354
6499
  mode,
@@ -6388,37 +6533,37 @@ async function ensureSlotRegistry(options = {}) {
6388
6533
  attempts: (previousState?.attempts ?? 0) + 1,
6389
6534
  repairedIssues: issues
6390
6535
  };
6391
- writeState(iuiRoot, state);
6392
- updateState(iuiRoot, state, "state-loaded");
6536
+ writeState(iuiRoot2, state);
6537
+ updateState(iuiRoot2, state, "state-loaded");
6393
6538
  await retry(() => {
6394
- writeComponentManifest(desired.components, iuiRoot);
6395
- writePackageManifest(currentPackages, iuiRoot);
6396
- writeSlotManifest(desired.slots, iuiRoot);
6539
+ writeComponentManifest(desired.components, iuiRoot2);
6540
+ writePackageManifest(currentPackages, iuiRoot2);
6541
+ writeSlotManifest(desired.slots, iuiRoot2);
6397
6542
  });
6398
- let next = updateState(iuiRoot, state, "manifests-written", {
6543
+ let next = updateState(iuiRoot2, state, "manifests-written", {
6399
6544
  checksum,
6400
6545
  repairedIssues: issues
6401
6546
  });
6402
6547
  await retry(async () => {
6403
- writeComponentSlotFiles(iuiRoot);
6404
- writeAssetsConfig(iuiRoot);
6405
- ensureProjectConfig(iuiRoot);
6406
- await writeAssetBoundFiles(iuiRoot);
6407
- writeSlotHelperFile(iuiRoot);
6548
+ writeComponentSlotFiles(iuiRoot2);
6549
+ writeAssetsConfig(iuiRoot2);
6550
+ ensureProjectConfig(iuiRoot2);
6551
+ await writeAssetBoundFiles(iuiRoot2);
6552
+ writeSlotHelperFile(iuiRoot2);
6408
6553
  if (projectHasViteTooling(cwd)) {
6409
6554
  ensureInventiveUiViteConfig(cwd);
6410
6555
  }
6411
6556
  });
6412
- bootstrapRegisteredPackages(iuiRoot);
6413
- next = updateState(iuiRoot, next, "slot-files-written", { repairedIssues: issues });
6557
+ bootstrapRegisteredPackages(iuiRoot2);
6558
+ next = updateState(iuiRoot2, next, "slot-files-written", { repairedIssues: issues });
6414
6559
  if (integrityIssues.length > 0) {
6415
6560
  throw new CLIError(
6416
6561
  "Slot registry integrity check failed.",
6417
6562
  integrityIssues.map((issue) => `- ${issue}`).join("\n")
6418
6563
  );
6419
6564
  }
6420
- next = updateState(iuiRoot, next, "integrity-verified", { repairedIssues: issues });
6421
- updateState(iuiRoot, next, "complete", {
6565
+ next = updateState(iuiRoot2, next, "integrity-verified", { repairedIssues: issues });
6566
+ updateState(iuiRoot2, next, "complete", {
6422
6567
  status: "complete",
6423
6568
  completedAt: now(),
6424
6569
  lastError: void 0,
@@ -6435,7 +6580,7 @@ async function ensureSlotRegistry(options = {}) {
6435
6580
  } catch (error) {
6436
6581
  const message = error instanceof Error ? error.message : "Slot registry update failed";
6437
6582
  if (state) {
6438
- updateState(iuiRoot, state, "state-loaded", {
6583
+ updateState(iuiRoot2, state, "state-loaded", {
6439
6584
  status: "failed",
6440
6585
  lastError: message,
6441
6586
  repairedIssues: issues
@@ -6588,7 +6733,7 @@ async function initCommand(opts) {
6588
6733
  try {
6589
6734
  heading("Initialize Project");
6590
6735
  const existingIuiRoot = findIuiProjectRoot(invocationCwd);
6591
- if (existingIuiRoot && path21.resolve(existingIuiRoot) !== path21.resolve(invocationCwd)) {
6736
+ if (existingIuiRoot && path23.resolve(existingIuiRoot) !== path23.resolve(invocationCwd)) {
6592
6737
  await bootstrapWorkspacePackage(invocationCwd, existingIuiRoot);
6593
6738
  return;
6594
6739
  }
@@ -6607,10 +6752,10 @@ async function initCommand(opts) {
6607
6752
  return;
6608
6753
  }
6609
6754
  const originalCwd = process.cwd();
6610
- if (path21.resolve(initRoot) !== path21.resolve(originalCwd)) {
6755
+ if (path23.resolve(initRoot) !== path23.resolve(originalCwd)) {
6611
6756
  process.chdir(initRoot);
6612
6757
  hint(
6613
- `Monorepo --workspace: initializing at ${path21.relative(invocationCwd, initRoot) || initRoot}`
6758
+ `Monorepo --workspace: initializing at ${path23.relative(invocationCwd, initRoot) || initRoot}`
6614
6759
  );
6615
6760
  } else if (!sharedWorkspace && findIuiProjectRoot(initRoot) === null) {
6616
6761
  hint("Initializing this package only \u2014 other monorepo apps are untouched.");
@@ -6669,7 +6814,12 @@ async function initCommand(opts) {
6669
6814
  projectId: project.project_id,
6670
6815
  repoUrl,
6671
6816
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
6672
- initScope: sharedWorkspace ? "workspace" : "package"
6817
+ initScope: sharedWorkspace ? "workspace" : "package",
6818
+ configs: {
6819
+ theme: "./iui.config.ts",
6820
+ assets: "./assets.config.json",
6821
+ components: "./component.config.ts"
6822
+ }
6673
6823
  };
6674
6824
  writeProjectMeta(meta, initRoot);
6675
6825
  step("Configuring npm registry\u2026");
@@ -7488,17 +7638,17 @@ async function deployTokenRevokeCommand(tokenId) {
7488
7638
  }
7489
7639
 
7490
7640
  // src/commands/setup.ts
7491
- import path24 from "path";
7492
- import fs19 from "fs-extra";
7641
+ import path26 from "path";
7642
+ import fs20 from "fs-extra";
7493
7643
  import ora6 from "ora";
7494
7644
 
7495
7645
  // src/commands/doctor.ts
7496
- import path23 from "path";
7646
+ import path25 from "path";
7497
7647
 
7498
7648
  // src/services/health.ts
7499
7649
  import { execFileSync as execFileSync2 } from "child_process";
7500
- import path22 from "path";
7501
- import fs18 from "fs-extra";
7650
+ import path24 from "path";
7651
+ import fs19 from "fs-extra";
7502
7652
  function installDevTypeScript(cwd) {
7503
7653
  const pm = detectPackageManager(cwd);
7504
7654
  try {
@@ -7541,8 +7691,8 @@ function checkGeneratedSlotValidity(cwd = process.cwd()) {
7541
7691
  };
7542
7692
  }
7543
7693
  function checkComponentConfigValidity(cwd = process.cwd(), options = {}) {
7544
- const configPath = path22.join(cwd, COMPONENT_CONFIG_FILE);
7545
- if (!fs18.existsSync(configPath)) {
7694
+ const configPath = path24.join(cwd, COMPONENT_CONFIG_FILE);
7695
+ if (!fs19.existsSync(configPath)) {
7546
7696
  return {
7547
7697
  ok: false,
7548
7698
  summary: "component.config.ts not found",
@@ -7550,8 +7700,8 @@ function checkComponentConfigValidity(cwd = process.cwd(), options = {}) {
7550
7700
  };
7551
7701
  }
7552
7702
  const tsPkgDir = resolvePackageDir("typescript", cwd);
7553
- const tscPath = tsPkgDir ? path22.join(tsPkgDir, "bin", "tsc") : path22.join(cwd, "node_modules", "typescript", "bin", "tsc");
7554
- if (!fs18.existsSync(tscPath)) {
7703
+ const tscPath = tsPkgDir ? path24.join(tsPkgDir, "bin", "tsc") : path24.join(cwd, "node_modules", "typescript", "bin", "tsc");
7704
+ if (!fs19.existsSync(tscPath)) {
7555
7705
  if (!options.autoFix) {
7556
7706
  return {
7557
7707
  ok: false,
@@ -7619,9 +7769,9 @@ ${stderr}`.trim() };
7619
7769
  function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7620
7770
  const warnings = [];
7621
7771
  const hints = [];
7622
- const configPath = path22.join(cwd, PROJECT_CONFIG_FILE);
7623
- if (fs18.existsSync(configPath)) {
7624
- const configContent = fs18.readFileSync(configPath, "utf-8");
7772
+ const configPath = path24.join(cwd, PROJECT_CONFIG_FILE);
7773
+ if (fs19.existsSync(configPath)) {
7774
+ const configContent = fs19.readFileSync(configPath, "utf-8");
7625
7775
  if (!/\bbuild\s*:\s*\{/.test(configContent)) {
7626
7776
  warnings.push("iui.config.ts is missing a compile-first `build` block");
7627
7777
  hints.push(
@@ -7650,11 +7800,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7650
7800
  }
7651
7801
  if (projectHasViteTooling(cwd)) {
7652
7802
  const viteCandidates = ["vite.config.ts", "vite.config.mjs", "vite.config.js"];
7653
- const vitePath = viteCandidates.map((name) => path22.join(cwd, name)).find((p) => fs18.existsSync(p));
7803
+ const vitePath = viteCandidates.map((name) => path24.join(cwd, name)).find((p) => fs19.existsSync(p));
7654
7804
  if (!vitePath) {
7655
7805
  warnings.push("Vite tooling detected but no vite.config.* found");
7656
7806
  } else {
7657
- const viteContent = fs18.readFileSync(vitePath, "utf-8");
7807
+ const viteContent = fs19.readFileSync(vitePath, "utf-8");
7658
7808
  if (!/inventiveUiVite\s*\(/.test(viteContent)) {
7659
7809
  warnings.push("vite.config is missing inventiveUiVite() \u2014 compile-first CSS will not generate");
7660
7810
  hints.push("Wire plugins: [...inventiveUiVite({ root: import.meta.dirname }), react()]");
@@ -7668,11 +7818,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7668
7818
  "webpack.config.mjs",
7669
7819
  "webpack.config.ts"
7670
7820
  ];
7671
- const webpackPath = webpackCandidates.map((name) => path22.join(cwd, name)).find((p) => fs18.existsSync(p));
7821
+ const webpackPath = webpackCandidates.map((name) => path24.join(cwd, name)).find((p) => fs19.existsSync(p));
7672
7822
  if (!webpackPath) {
7673
7823
  warnings.push("Webpack tooling detected but no webpack.config.* found");
7674
7824
  } else {
7675
- const webpackContent = fs18.readFileSync(webpackPath, "utf-8");
7825
+ const webpackContent = fs19.readFileSync(webpackPath, "utf-8");
7676
7826
  if (!/inventiveUiWebpack\s*\(/.test(webpackContent)) {
7677
7827
  warnings.push("webpack.config is missing inventiveUiWebpack() \u2014 compile-first CSS will not generate");
7678
7828
  hints.push('Wire plugins: [...inventiveUiWebpack()] from "@inventive-ui/framework/webpack"');
@@ -7682,11 +7832,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7682
7832
  }
7683
7833
  if (projectHasNextTooling(cwd)) {
7684
7834
  const nextCandidates = ["next.config.ts", "next.config.mjs", "next.config.js", "next.config.cjs"];
7685
- const nextPath = nextCandidates.map((name) => path22.join(cwd, name)).find((p) => fs18.existsSync(p));
7835
+ const nextPath = nextCandidates.map((name) => path24.join(cwd, name)).find((p) => fs19.existsSync(p));
7686
7836
  if (!nextPath) {
7687
7837
  warnings.push("Next.js detected but no next.config.* found");
7688
7838
  } else {
7689
- const nextContent = fs18.readFileSync(nextPath, "utf-8");
7839
+ const nextContent = fs19.readFileSync(nextPath, "utf-8");
7690
7840
  if (!/withIUI\s*\(/.test(nextContent)) {
7691
7841
  warnings.push("next.config is missing withIUI() \u2014 compile-first CSS will not generate");
7692
7842
  hints.push('Wrap config: export default withIUI({ ... }) from "@inventive-ui/framework/next"');
@@ -7699,11 +7849,26 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7699
7849
  "src/app/layout.jsx",
7700
7850
  "app/providers.tsx",
7701
7851
  "src/app/providers.tsx"
7702
- ].map((rel) => path22.join(cwd, rel));
7703
- const hasRegistry = layoutCandidates.some((file) => {
7704
- if (!fs18.existsSync(file)) return false;
7852
+ ].map((rel) => path24.join(cwd, rel));
7853
+ const readableLayouts = layoutCandidates.filter((file) => fs19.existsSync(file));
7854
+ const hasRegistry = readableLayouts.some((file) => {
7855
+ try {
7856
+ return /\bIUIRegistry\b/.test(fs19.readFileSync(file, "utf-8"));
7857
+ } catch {
7858
+ return false;
7859
+ }
7860
+ });
7861
+ const hasBootstrapImport = readableLayouts.some((file) => {
7862
+ try {
7863
+ const content = fs19.readFileSync(file, "utf-8");
7864
+ return /next\/bootstrap/.test(content) || /["']iui-bootstrap["']/.test(content) || /iui\/bootstrap/.test(content);
7865
+ } catch {
7866
+ return false;
7867
+ }
7868
+ });
7869
+ const hasProvider = readableLayouts.some((file) => {
7705
7870
  try {
7706
- return /\bIUIRegistry\b/.test(fs18.readFileSync(file, "utf-8"));
7871
+ return /\bIUIProvider\b/.test(fs19.readFileSync(file, "utf-8"));
7707
7872
  } catch {
7708
7873
  return false;
7709
7874
  }
@@ -7712,6 +7877,16 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7712
7877
  warnings.push("Next.js app should wrap the root layout with <IUIRegistry>");
7713
7878
  hints.push('Import IUIRegistry from "@inventive-ui/framework/next/registry" in the root layout');
7714
7879
  }
7880
+ if (!hasBootstrapImport) {
7881
+ warnings.push("Next.js root layout should import bootstrap before render");
7882
+ hints.push(
7883
+ 'Add `import "@inventive-ui/framework/next/bootstrap"` to the root layout (server) and client providers'
7884
+ );
7885
+ }
7886
+ if (!hasProvider) {
7887
+ warnings.push("Next.js app should use <IUIProvider> for bootstrap-state runtime");
7888
+ hints.push('Wrap children with <IUIProvider> from "@inventive-ui/framework" inside IUIRegistry');
7889
+ }
7715
7890
  }
7716
7891
  const entryCandidates = [
7717
7892
  "src/main.tsx",
@@ -7724,14 +7899,14 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7724
7899
  "src/app/providers.tsx",
7725
7900
  "app/layout.tsx",
7726
7901
  "src/app/layout.tsx"
7727
- ].map((rel) => path22.join(cwd, rel));
7902
+ ].map((rel) => path24.join(cwd, rel));
7728
7903
  for (const file of entryCandidates) {
7729
- if (!fs18.existsSync(file)) continue;
7904
+ if (!fs19.existsSync(file)) continue;
7730
7905
  try {
7731
- const content = fs18.readFileSync(file, "utf-8");
7906
+ const content = fs19.readFileSync(file, "utf-8");
7732
7907
  if (/from\s+['"][^'"]*\.generated['"]/.test(content) || /import\s+['"][^'"]*\.generated['"]/.test(content)) {
7733
7908
  warnings.push(
7734
- `Do not import .generated style-map files into the browser (${path22.relative(cwd, file)})`
7909
+ `Do not import .generated style-map files into the browser (${path24.relative(cwd, file)})`
7735
7910
  );
7736
7911
  hints.push(
7737
7912
  "Keep style maps on the scanner path (default src/.iui, or override build.scanDirs) \u2014 see Framework compile-first docs"
@@ -7751,32 +7926,32 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
7751
7926
  hints.push(
7752
7927
  "Compile-first: avoid dynamic utility templates like `p-${n}` \u2014 use static strings, style maps, or safelist (ESLint: customPlugin/no-dynamic-utility-class)"
7753
7928
  );
7754
- const giPath = path22.join(cwd, ".gitignore");
7755
- if (fs18.existsSync(giPath)) {
7756
- const gi = fs18.readFileSync(giPath, "utf-8");
7757
- if (!gi.includes(".iui/classes.cache.json")) {
7758
- warnings.push(".gitignore missing IUI compile cache entries (.iui/classes.cache.json)");
7759
- hints.push("Run iui init or append compile cache paths from the IUI docs");
7929
+ const giPath = path24.join(cwd, ".gitignore");
7930
+ if (fs19.existsSync(giPath)) {
7931
+ const gi = fs19.readFileSync(giPath, "utf-8");
7932
+ if (!gi.includes(".iui/cache/")) {
7933
+ warnings.push(".gitignore missing IUI cache directory (.iui/cache/)");
7934
+ hints.push("Run iui init or append .iui/cache/ from the IUI docs");
7760
7935
  }
7761
7936
  }
7762
7937
  return { warnings, hints };
7763
7938
  }
7764
7939
  function checkAssetBoundBindings(cwd = process.cwd()) {
7765
- const assetsPath = path22.join(cwd, ASSETS_CONFIG_FILE);
7766
- if (!fs18.existsSync(assetsPath)) {
7940
+ const assetsPath = path24.join(cwd, ASSETS_CONFIG_FILE);
7941
+ if (!fs19.existsSync(assetsPath)) {
7767
7942
  return { ok: true, summary: "Asset binding check skipped (no assets.config.json)" };
7768
7943
  }
7769
7944
  let assets2;
7770
7945
  try {
7771
- assets2 = fs18.readJsonSync(assetsPath);
7946
+ assets2 = fs19.readJsonSync(assetsPath);
7772
7947
  } catch {
7773
7948
  return { ok: false, summary: "assets.config.json is not valid JSON" };
7774
7949
  }
7775
7950
  if (assets2.binding !== "scanned") {
7776
7951
  return { ok: true, summary: "Asset slots use lazy binding (default)" };
7777
7952
  }
7778
- const registerBound = path22.join(generatedAssetsDir(cwd), "register-bound.ts");
7779
- if (!fs18.existsSync(registerBound)) {
7953
+ const registerBound = path24.join(generatedAssetsDir(cwd), "register-bound.ts");
7954
+ if (!fs19.existsSync(registerBound)) {
7780
7955
  return {
7781
7956
  ok: false,
7782
7957
  summary: 'binding is "scanned" but .iui/generated/assets/register-bound.ts is missing',
@@ -7785,6 +7960,76 @@ function checkAssetBoundBindings(cwd = process.cwd()) {
7785
7960
  }
7786
7961
  return { ok: true, summary: "Scanned asset bindings present" };
7787
7962
  }
7963
+ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
7964
+ const iuiRoot2 = resolveIuiProjectRoot(cwd);
7965
+ const generatedPath = bootstrapGeneratedPath(iuiRoot2);
7966
+ const bridgePath = path24.join(cwd, "src", "iui", "bootstrap.ts");
7967
+ if (!fs19.existsSync(generatedPath)) {
7968
+ if (options.autoFix) {
7969
+ writeProjectBootstrapArtifacts(cwd, iuiRoot2);
7970
+ if (fs19.existsSync(generatedPath)) {
7971
+ return { ok: true, summary: "Generated bootstrap artifacts repaired" };
7972
+ }
7973
+ }
7974
+ return {
7975
+ ok: false,
7976
+ summary: "Generated bootstrap missing",
7977
+ details: "Expected .iui/generated/bootstrap.generated.tsx \u2014 run iui doctor --fix."
7978
+ };
7979
+ }
7980
+ if (!fs19.existsSync(bridgePath)) {
7981
+ if (options.autoFix) {
7982
+ writeProjectBootstrapArtifacts(cwd, iuiRoot2);
7983
+ if (fs19.existsSync(bridgePath)) {
7984
+ return { ok: true, summary: "Bootstrap bridge repaired" };
7985
+ }
7986
+ }
7987
+ return {
7988
+ ok: false,
7989
+ summary: "Bootstrap bridge missing",
7990
+ details: "Expected src/iui/bootstrap.ts \u2014 run iui doctor --fix."
7991
+ };
7992
+ }
7993
+ const configs = resolveProjectConfigPaths(iuiRoot2);
7994
+ const missing = [];
7995
+ for (const [key, rel] of Object.entries(configs)) {
7996
+ const abs = path24.resolve(iuiRoot2, rel.replace(/^\.\//, ""));
7997
+ if (!fs19.existsSync(abs)) missing.push(`${key}: ${rel}`);
7998
+ }
7999
+ if (missing.length > 0) {
8000
+ return {
8001
+ ok: false,
8002
+ summary: "Bootstrap config paths from project.json are missing",
8003
+ details: missing.map((line) => `- ${line}`).join("\n")
8004
+ };
8005
+ }
8006
+ const expected = expectedBootstrapImportPaths(iuiRoot2);
8007
+ const generated = fs19.readFileSync(generatedPath, "utf8");
8008
+ const stale = [];
8009
+ for (const [key, importPath] of Object.entries(expected)) {
8010
+ if (!generated.includes(`"${importPath}"`)) {
8011
+ stale.push(`${key} import should be "${importPath}"`);
8012
+ }
8013
+ }
8014
+ if (stale.length > 0) {
8015
+ if (options.autoFix) {
8016
+ writeProjectBootstrapArtifacts(cwd, iuiRoot2);
8017
+ const refreshed = fs19.readFileSync(bootstrapGeneratedPath(iuiRoot2), "utf8");
8018
+ const stillStale = Object.entries(expected).filter(
8019
+ ([, importPath]) => !refreshed.includes(`"${importPath}"`)
8020
+ );
8021
+ if (stillStale.length === 0) {
8022
+ return { ok: true, summary: "Generated bootstrap refreshed from project.json" };
8023
+ }
8024
+ }
8025
+ return {
8026
+ ok: false,
8027
+ summary: "Generated bootstrap is stale",
8028
+ details: stale.map((line) => `- ${line}`).join("\n")
8029
+ };
8030
+ }
8031
+ return { ok: true, summary: "Generated bootstrap matches project.json config paths" };
8032
+ }
7788
8033
 
7789
8034
  // src/commands/doctor.ts
7790
8035
  function runConfigTierDiagnostics(targetCwd, opts, counters, options = {}) {
@@ -7981,16 +8226,16 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
7981
8226
  }
7982
8227
  const auth = getAuthConfig();
7983
8228
  if (auth?.token) {
7984
- const fwInstalled = getInstalledPackageVersion(FRAMEWORK_PACKAGE, targetCwd);
8229
+ const fwBaseline = getFrameworkUpdateBaselineVersion(targetCwd);
7985
8230
  const compInstalled = getInstalledPackageVersion(COMPONENTS_PACKAGE, targetCwd);
7986
8231
  const [latestFw, latestComp] = await Promise.all([
7987
- fwInstalled ? getLatestVersionSafe(auth.token, "framework") : Promise.resolve(null),
8232
+ fwBaseline ? getLatestVersionSafe(auth.token, "framework") : Promise.resolve(null),
7988
8233
  compInstalled ? getLatestVersionSafe(auth.token, "components") : Promise.resolve(null)
7989
8234
  ]);
7990
8235
  let behind = false;
7991
- if (fwInstalled && latestFw && isVersionGreater(latestFw, fwInstalled)) {
8236
+ if (fwBaseline && latestFw && isVersionGreater(latestFw, fwBaseline)) {
7992
8237
  behind = true;
7993
- warn(`Framework v${fwInstalled} is behind the latest v${latestFw}`);
8238
+ warn(`Framework v${fwBaseline} is behind the latest v${latestFw}`);
7994
8239
  }
7995
8240
  if (compInstalled && latestComp && isVersionGreater(latestComp, compInstalled)) {
7996
8241
  behind = true;
@@ -7998,7 +8243,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
7998
8243
  }
7999
8244
  if (behind) {
8000
8245
  hint("Run iui update to move to the latest versions.");
8001
- } else if (fwInstalled && latestFw || compInstalled && latestComp) {
8246
+ } else if (fwBaseline && latestFw || compInstalled && latestComp) {
8002
8247
  pass("Inventive UI packages are on the latest version");
8003
8248
  }
8004
8249
  }
@@ -8014,6 +8259,22 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
8014
8259
  }
8015
8260
  hint("Fix: reinstall @inventive-ui/components and rerun iui doctor");
8016
8261
  }
8262
+ const bootstrapSync = checkBootstrapSync(targetCwd, {
8263
+ autoFix: opts?.fix === true
8264
+ });
8265
+ if (bootstrapSync.ok) {
8266
+ pass(bootstrapSync.summary);
8267
+ } else {
8268
+ fail2(bootstrapSync.summary);
8269
+ if (bootstrapSync.details) {
8270
+ for (const line of bootstrapSync.details.split("\n")) {
8271
+ hint(line);
8272
+ }
8273
+ }
8274
+ if (!opts?.fix) {
8275
+ hint("Fix: run iui doctor --fix to regenerate bootstrap artifacts");
8276
+ }
8277
+ }
8017
8278
  runConfigTierDiagnostics(targetCwd, opts, counters, {
8018
8279
  includePackageJson: false,
8019
8280
  includeSlotCheck: false
@@ -8022,7 +8283,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
8022
8283
  async function doctorCommand(opts) {
8023
8284
  try {
8024
8285
  const invocationCwd = process.cwd();
8025
- const targets = opts?.cwd ? [path23.resolve(opts.cwd)] : resolveSetupDoctorTargets(invocationCwd);
8286
+ const targets = opts?.cwd ? [path25.resolve(opts.cwd)] : resolveSetupDoctorTargets(invocationCwd);
8026
8287
  const installRoot = resolveDependencyInstallRoot(invocationCwd);
8027
8288
  const multiPackage = targets.length > 1;
8028
8289
  heading("Diagnostics");
@@ -8065,7 +8326,7 @@ async function doctorCommand(opts) {
8065
8326
  for (const targetCwd of targets) {
8066
8327
  if (multiPackage) {
8067
8328
  newline();
8068
- const label = path23.relative(installRoot, targetCwd) || path23.basename(targetCwd);
8329
+ const label = path25.relative(installRoot, targetCwd) || path25.basename(targetCwd);
8069
8330
  kv("Package", label);
8070
8331
  }
8071
8332
  await runPackageDiagnostics(targetCwd, opts, counters);
@@ -8093,9 +8354,9 @@ async function doctorCommand(opts) {
8093
8354
 
8094
8355
  // src/commands/setup.ts
8095
8356
  function detectDevScript(cwd) {
8096
- const pkgPath = path24.join(cwd, "package.json");
8357
+ const pkgPath = path26.join(cwd, "package.json");
8097
8358
  try {
8098
- const pkg = fs19.readJsonSync(pkgPath);
8359
+ const pkg = fs20.readJsonSync(pkgPath);
8099
8360
  if (pkg.scripts?.dev) return "npm run dev";
8100
8361
  if (pkg.scripts?.start) return "npm run start";
8101
8362
  } catch {
@@ -8104,8 +8365,8 @@ function detectDevScript(cwd) {
8104
8365
  return null;
8105
8366
  }
8106
8367
  function relativePackageLabel(installRoot, packageDir) {
8107
- const rel = path24.relative(installRoot, packageDir);
8108
- return rel && rel !== "." ? rel : path24.basename(packageDir);
8368
+ const rel = path26.relative(installRoot, packageDir);
8369
+ return rel && rel !== "." ? rel : path26.basename(packageDir);
8109
8370
  }
8110
8371
  async function setupCommand(opts) {
8111
8372
  try {
@@ -8114,7 +8375,7 @@ async function setupCommand(opts) {
8114
8375
  const installRoot = resolveDependencyInstallRoot(cwd);
8115
8376
  const workspaceRoot = findWorkspaceRoot(cwd);
8116
8377
  const inMonorepo = workspaceRoot !== null;
8117
- const installFromChild = inMonorepo && path24.resolve(installRoot) !== path24.resolve(cwd);
8378
+ const installFromChild = inMonorepo && path26.resolve(installRoot) !== path26.resolve(cwd);
8118
8379
  if (!hasPackageJson(cwd) && !hasPackageJson(installRoot)) {
8119
8380
  throw new CLIError(
8120
8381
  "No package.json found in the current directory.",
@@ -8148,7 +8409,7 @@ async function setupCommand(opts) {
8148
8409
  for (const w of warnings) warn(w);
8149
8410
  kv("Package manager", `${pm} (${source})`);
8150
8411
  if (installFromChild) {
8151
- const rel = path24.relative(cwd, installRoot) || ".";
8412
+ const rel = path26.relative(cwd, installRoot) || ".";
8152
8413
  kv("Install directory", rel === ".." || rel.includes("..") ? installRoot : rel);
8153
8414
  }
8154
8415
  const installCmd2 = syncInstallCommand(pm);
@@ -8162,7 +8423,7 @@ async function setupCommand(opts) {
8162
8423
  } catch (err) {
8163
8424
  installSpinner.fail("Dependency install failed");
8164
8425
  const detail = formatExecSyncError(err);
8165
- const manual = path24.resolve(installRoot) === path24.resolve(cwd) ? installCmd2 : `cd ${JSON.stringify(installRoot)} && ${installCmd2}`;
8426
+ const manual = path26.resolve(installRoot) === path26.resolve(cwd) ? installCmd2 : `cd ${JSON.stringify(installRoot)} && ${installCmd2}`;
8166
8427
  throw new CLIError(
8167
8428
  detail ? `Could not install project dependencies.
8168
8429
  ${detail}` : "Could not install project dependencies.",
@@ -8320,7 +8581,7 @@ async function updateCommand(opts = {}) {
8320
8581
  const auth = await ensureAuthSession();
8321
8582
  await ensureLicenseSession();
8322
8583
  const inProject = isInsideProject();
8323
- const currentCliVersion = true ? "0.0.1" : "unknown";
8584
+ const currentCliVersion = true ? "0.0.3" : "unknown";
8324
8585
  const latestCliVersion = await fetchLatestCliVersion(auth.token);
8325
8586
  const cliUpdateAvailable = latestCliVersion !== null && isVersionGreater(latestCliVersion, currentCliVersion);
8326
8587
  if (latestCliVersion && cliUpdateAvailable) {
@@ -8385,15 +8646,16 @@ async function updateCommand(opts = {}) {
8385
8646
  }
8386
8647
  }
8387
8648
  const frameworkStatus = getFrameworkInstallStatus(installCwd);
8649
+ const frameworkBaselineVersion = getFrameworkUpdateBaselineVersion(installCwd);
8388
8650
  const latestFrameworkVersion = await fetchLatestScopedPackageVersion(auth.token, "framework");
8389
- const frameworkUpdateAvailable = frameworkStatus.installed && frameworkStatus.version && latestFrameworkVersion && isVersionGreater(latestFrameworkVersion, frameworkStatus.version);
8651
+ const frameworkUpdateAvailable = frameworkStatus.installed && frameworkBaselineVersion && latestFrameworkVersion && isVersionGreater(latestFrameworkVersion, frameworkBaselineVersion);
8390
8652
  let shouldUpdateFramework = false;
8391
8653
  if (frameworkUpdateAvailable) {
8392
8654
  subheading("Framework update");
8393
8655
  newline();
8394
8656
  updateRow(
8395
8657
  "Inventive UI Framework",
8396
- frameworkStatus.version ?? "unknown",
8658
+ frameworkBaselineVersion ?? "unknown",
8397
8659
  latestFrameworkVersion ?? "unknown",
8398
8660
  true
8399
8661
  );
@@ -8447,6 +8709,7 @@ async function updateCommand(opts = {}) {
8447
8709
  info("No asset package updates available.");
8448
8710
  }
8449
8711
  const hasAnyUpdates = cliUpdateAvailable || available.length > 0 || assetUpdates.length > 0 || Boolean(frameworkUpdateAvailable);
8712
+ const alignDeclaredDependencies = () => syncInventiveUiDeclaredDependencies(installCwd);
8450
8713
  if (opts.check === true) {
8451
8714
  if (hasAnyUpdates) {
8452
8715
  done("Updates are available.");
@@ -8457,6 +8720,14 @@ async function updateCommand(opts = {}) {
8457
8720
  return;
8458
8721
  }
8459
8722
  if (!hasAnyUpdates) {
8723
+ const synced2 = alignDeclaredDependencies();
8724
+ if (synced2.length > 0) {
8725
+ ok(
8726
+ `Aligned package.json with hoisted installs (${synced2.length} @inventive-ui package${synced2.length === 1 ? "" : "s"})`
8727
+ );
8728
+ done("Workspace dependency declarations are now in sync.");
8729
+ return;
8730
+ }
8460
8731
  done("Everything is up to date.");
8461
8732
  return;
8462
8733
  }
@@ -8509,6 +8780,12 @@ async function updateCommand(opts = {}) {
8509
8780
  updatedAssets += 1;
8510
8781
  }
8511
8782
  }
8783
+ const synced = alignDeclaredDependencies();
8784
+ if (synced.length > 0) {
8785
+ ok(
8786
+ `Aligned package.json with installed versions (${synced.length} @inventive-ui package${synced.length === 1 ? "" : "s"})`
8787
+ );
8788
+ }
8512
8789
  done(
8513
8790
  `Update complete: ${updatedFramework} framework, ${updatedComponents} component${updatedComponents === 1 ? "" : "s"}, ${updatedAssets} asset package${updatedAssets === 1 ? "" : "s"}.`
8514
8791
  );
@@ -8586,7 +8863,7 @@ var AUTH_EXEMPT_COMMANDS = /* @__PURE__ */ new Set([
8586
8863
  "doctor",
8587
8864
  "list"
8588
8865
  ]);
8589
- program.name("iui").description("The official CLI for the Inventive UI Design System").version(true ? "0.0.1" : "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");
8866
+ program.name("iui").description("The official CLI for the Inventive UI Design System").version(true ? "0.0.3" : "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");
8590
8867
  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));
8591
8868
  program.command("logout").description("Remove stored credentials").action(logoutCommand);
8592
8869
  program.command("whoami").description("Show authenticated identity and license details").action(whoamiCommand);
@@ -8684,7 +8961,7 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
8684
8961
  const root = topLevelCommandName(actionCommand);
8685
8962
  const globalOpts = program.opts();
8686
8963
  if (globalOpts.cwd) {
8687
- process.chdir(path25.resolve(globalOpts.cwd));
8964
+ process.chdir(path27.resolve(globalOpts.cwd));
8688
8965
  }
8689
8966
  if (isInsideProject()) {
8690
8967
  try {