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