inventive-ui 0.0.9 → 0.0.11
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 +6 -6
- package/dist/index.js +369 -1087
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/assets.config.defaults.json +0 -28
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 path26 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.11" : "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 path27 = parsed.pathname.replace(/\/+$/, "");
|
|
377
|
+
if (path27 && !/^\/[a-zA-Z0-9._/-]+$/.test(path27)) {
|
|
378
378
|
throw new CLIError(
|
|
379
379
|
"IUI_API_URL path contains invalid characters.",
|
|
380
380
|
"Use a simple path prefix such as /v1"
|
|
@@ -434,7 +434,7 @@ var COMPONENTS_PACKAGE = "@inventive-ui/components";
|
|
|
434
434
|
var NPM_SCOPE = "@inventive-ui";
|
|
435
435
|
var IUI_DIR = ".iui";
|
|
436
436
|
var GLOBAL_CONFIG_DIR = ".iui";
|
|
437
|
-
var PROJECT_CONFIG_FILE = "
|
|
437
|
+
var PROJECT_CONFIG_FILE = "theme.config.ts";
|
|
438
438
|
var REQUIRED_REACT_MAJOR = 19;
|
|
439
439
|
var REACT_SAFE_VERSION = "^19.0.0";
|
|
440
440
|
var REQUIRED_VITE_MAJOR = 6;
|
|
@@ -596,7 +596,7 @@ var EMOJI_FAMILIES = [
|
|
|
596
596
|
"twitter",
|
|
597
597
|
"native"
|
|
598
598
|
];
|
|
599
|
-
var DEFAULT_EMOJI_SKIN_TONE = "
|
|
599
|
+
var DEFAULT_EMOJI_SKIN_TONE = "mediumLight";
|
|
600
600
|
var EMOJI_FAMILY_LABELS = {
|
|
601
601
|
apple: "Apple",
|
|
602
602
|
google: "Google",
|
|
@@ -1428,7 +1428,7 @@ function resolveFrameworkScriptsDir(startCwd) {
|
|
|
1428
1428
|
if (existsSync(loader)) return scriptsDir;
|
|
1429
1429
|
}
|
|
1430
1430
|
throw new CLIError(
|
|
1431
|
-
`Cannot scaffold
|
|
1431
|
+
`Cannot scaffold theme.config.ts: ${FRAMEWORK_PACKAGE} is not installed or is missing scripts/load-framework-theme-defaults.mjs.`
|
|
1432
1432
|
);
|
|
1433
1433
|
}
|
|
1434
1434
|
function buildProjectConfigSource(cwd = process.cwd()) {
|
|
@@ -1443,42 +1443,6 @@ function buildProjectConfigSource(cwd = process.cwd()) {
|
|
|
1443
1443
|
});
|
|
1444
1444
|
}
|
|
1445
1445
|
|
|
1446
|
-
// src/utils/security/identifiers.ts
|
|
1447
|
-
var SLUG_RE = /^[a-z][a-z0-9-]*$/;
|
|
1448
|
-
var JS_IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
1449
|
-
var NPM_SCOPE_IMPORT_RE = /^@inventive-ui\/[a-z0-9][a-z0-9._-]*$/;
|
|
1450
|
-
var NPM_COMPONENT_SUBPATH_RE = /^@inventive-ui\/components\/[A-Za-z][A-Za-z0-9-]*$/;
|
|
1451
|
-
function assertComponentSlug(slug) {
|
|
1452
|
-
if (!SLUG_RE.test(slug)) {
|
|
1453
|
-
throw new CLIError(
|
|
1454
|
-
`Invalid component slug: "${slug}"`,
|
|
1455
|
-
"Use lowercase letters, numbers, and hyphens (e.g. button, input)."
|
|
1456
|
-
);
|
|
1457
|
-
}
|
|
1458
|
-
}
|
|
1459
|
-
function assertJsIdentifier(name, label) {
|
|
1460
|
-
if (!JS_IDENTIFIER_RE.test(name)) {
|
|
1461
|
-
throw new CLIError(`Invalid ${label}: "${name}"`);
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
function assertImportSpecifier(specifier) {
|
|
1465
|
-
if (NPM_SCOPE_IMPORT_RE.test(specifier)) return;
|
|
1466
|
-
if (NPM_COMPONENT_SUBPATH_RE.test(specifier)) return;
|
|
1467
|
-
if (/^@inventive-ui\/[a-z0-9][a-z0-9-]*$/.test(specifier)) return;
|
|
1468
|
-
throw new CLIError(`Unsafe import specifier: "${specifier}"`);
|
|
1469
|
-
}
|
|
1470
|
-
function escapeTsStringLiteral(value) {
|
|
1471
|
-
return JSON.stringify(value);
|
|
1472
|
-
}
|
|
1473
|
-
function sanitizePackageVersionHeader(value) {
|
|
1474
|
-
if (!value) return null;
|
|
1475
|
-
const trimmed = value.trim();
|
|
1476
|
-
if (!/^[0-9A-Za-z.+~^<>= -]+$/.test(trimmed) || trimmed.length > 64) {
|
|
1477
|
-
throw new CLIError("Server returned an invalid package version header.");
|
|
1478
|
-
}
|
|
1479
|
-
return trimmed;
|
|
1480
|
-
}
|
|
1481
|
-
|
|
1482
1446
|
// src/utils/config-patch/vite-config.ts
|
|
1483
1447
|
import ts from "typescript";
|
|
1484
1448
|
var IUI_MANAGED_MARKER = "@iui-managed";
|
|
@@ -1969,393 +1933,40 @@ function patchProjectConfigBuildBlock(content) {
|
|
|
1969
1933
|
// src/utils/config-patch/component-config.ts
|
|
1970
1934
|
import ts2 from "typescript";
|
|
1971
1935
|
|
|
1972
|
-
// src/utils/
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
const packageRoot = resolvePackageDir("@inventive-ui/components", cwd);
|
|
1984
|
-
if (!packageRoot) return null;
|
|
1985
|
-
const pkgPath = path7.join(packageRoot, "package.json");
|
|
1986
|
-
if (!fs6.existsSync(pkgPath)) return null;
|
|
1987
|
-
try {
|
|
1988
|
-
const pkg = fs6.readJsonSync(pkgPath);
|
|
1989
|
-
const exportsField = toRecord(pkg.exports) ?? {};
|
|
1990
|
-
const rootExport = toRecord(exportsField["."]);
|
|
1991
|
-
const rootTypes = resolveTypesPathFromExportEntry(rootExport) ?? (typeof pkg.types === "string" ? pkg.types : null);
|
|
1992
|
-
return {
|
|
1993
|
-
packageRoot,
|
|
1994
|
-
exportsField,
|
|
1995
|
-
rootTypesPath: rootTypes ? path7.join(packageRoot, rootTypes) : null
|
|
1996
|
-
};
|
|
1997
|
-
} catch {
|
|
1998
|
-
return null;
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
function resolveTypesPathFromExportEntry(entry) {
|
|
2002
|
-
if (!entry) return null;
|
|
2003
|
-
if (typeof entry === "string") return null;
|
|
2004
|
-
const obj = toRecord(entry);
|
|
2005
|
-
if (!obj) return null;
|
|
2006
|
-
if (typeof obj.types === "string") return obj.types;
|
|
2007
|
-
for (const key of ["import", "require", "default", "node", "browser"]) {
|
|
2008
|
-
const nested = toRecord(obj[key]);
|
|
2009
|
-
if (!nested) continue;
|
|
2010
|
-
if (typeof nested.types === "string") return nested.types;
|
|
2011
|
-
}
|
|
2012
|
-
return null;
|
|
2013
|
-
}
|
|
2014
|
-
function parseNamedExportClause(clause, parsed) {
|
|
2015
|
-
const parts = clause.split(",").map((p) => p.trim()).filter(Boolean);
|
|
2016
|
-
for (const rawPart of parts) {
|
|
2017
|
-
let part = rawPart;
|
|
2018
|
-
let isTypeOnly = false;
|
|
2019
|
-
if (part.startsWith("type ")) {
|
|
2020
|
-
isTypeOnly = true;
|
|
2021
|
-
part = part.slice("type ".length).trim();
|
|
2022
|
-
}
|
|
2023
|
-
const asMatch = part.match(/^([A-Za-z_][A-Za-z0-9_]*)\s+as\s+([A-Za-z_][A-Za-z0-9_]*)$/);
|
|
2024
|
-
const symbol = asMatch ? asMatch[2] : part;
|
|
2025
|
-
if (!symbol) continue;
|
|
2026
|
-
if (isTypeOnly) parsed.typeExports.add(symbol);
|
|
2027
|
-
else parsed.valueExports.add(symbol);
|
|
2028
|
-
}
|
|
2029
|
-
}
|
|
2030
|
-
function mergeParsedExports(target, source) {
|
|
2031
|
-
for (const sym of source.valueExports) target.valueExports.add(sym);
|
|
2032
|
-
for (const sym of source.typeExports) target.typeExports.add(sym);
|
|
2033
|
-
}
|
|
2034
|
-
function resolveRelativeTypesPath(fromFile, rel) {
|
|
2035
|
-
const base = path7.dirname(fromFile);
|
|
2036
|
-
const noExt = path7.join(base, rel);
|
|
2037
|
-
const candidates = [`${noExt}.d.ts`, path7.join(noExt, "index.d.ts")];
|
|
2038
|
-
for (const candidate of candidates) {
|
|
2039
|
-
if (fs6.existsSync(candidate)) return candidate;
|
|
2040
|
-
}
|
|
2041
|
-
return null;
|
|
2042
|
-
}
|
|
2043
|
-
function parseTypeExports(typesFilePath, visited = /* @__PURE__ */ new Set()) {
|
|
2044
|
-
const parsed = {
|
|
2045
|
-
valueExports: /* @__PURE__ */ new Set(),
|
|
2046
|
-
typeExports: /* @__PURE__ */ new Set()
|
|
2047
|
-
};
|
|
2048
|
-
const abs = path7.resolve(typesFilePath);
|
|
2049
|
-
if (visited.has(abs)) return parsed;
|
|
2050
|
-
visited.add(abs);
|
|
2051
|
-
if (!fs6.existsSync(abs)) return parsed;
|
|
2052
|
-
let text = "";
|
|
2053
|
-
try {
|
|
2054
|
-
text = fs6.readFileSync(abs, "utf-8");
|
|
2055
|
-
} catch {
|
|
2056
|
-
return parsed;
|
|
2057
|
-
}
|
|
2058
|
-
applyTypeExportPatterns(text, parsed);
|
|
2059
|
-
const reexportFrom = text.matchAll(
|
|
2060
|
-
/export\s+(?:type\s+)?(?:\{[^}]*\}|\*)\s+from\s+["'](\.[^"']+)["']/g
|
|
2061
|
-
);
|
|
2062
|
-
for (const m of reexportFrom) {
|
|
2063
|
-
const refPath = resolveRelativeTypesPath(abs, m[1]);
|
|
2064
|
-
if (refPath) mergeParsedExports(parsed, parseTypeExports(refPath, visited));
|
|
2065
|
-
}
|
|
2066
|
-
return parsed;
|
|
2067
|
-
}
|
|
2068
|
-
function parseTypeExportsLocal(typesFilePath) {
|
|
2069
|
-
const parsed = {
|
|
2070
|
-
valueExports: /* @__PURE__ */ new Set(),
|
|
2071
|
-
typeExports: /* @__PURE__ */ new Set()
|
|
2072
|
-
};
|
|
2073
|
-
const abs = path7.resolve(typesFilePath);
|
|
2074
|
-
if (!fs6.existsSync(abs)) return parsed;
|
|
2075
|
-
let text = "";
|
|
2076
|
-
try {
|
|
2077
|
-
text = fs6.readFileSync(abs, "utf-8");
|
|
2078
|
-
} catch {
|
|
2079
|
-
return parsed;
|
|
2080
|
-
}
|
|
2081
|
-
applyTypeExportPatterns(text, parsed);
|
|
2082
|
-
return parsed;
|
|
2083
|
-
}
|
|
2084
|
-
function applyTypeExportPatterns(text, parsed) {
|
|
2085
|
-
const valueDecl = /export\s+(?:declare\s+)?(?:const|let|var|function|class)\s+([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
2086
|
-
const typeDecl = /export\s+(?:declare\s+)?(?:type|interface)\s+([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
2087
|
-
const namedClause = /export\s+(?!type\s*\{)\{([^}]+)\}/g;
|
|
2088
|
-
const typeNamedClause = /export\s+type\s*\{([^}]+)\}/g;
|
|
2089
|
-
for (const m of text.matchAll(valueDecl)) {
|
|
2090
|
-
parsed.valueExports.add(m[1]);
|
|
2091
|
-
}
|
|
2092
|
-
for (const m of text.matchAll(typeDecl)) {
|
|
2093
|
-
parsed.typeExports.add(m[1]);
|
|
2094
|
-
}
|
|
2095
|
-
for (const m of text.matchAll(namedClause)) {
|
|
2096
|
-
parseNamedExportClause(m[1], parsed);
|
|
2097
|
-
}
|
|
2098
|
-
for (const m of text.matchAll(typeNamedClause)) {
|
|
2099
|
-
parseNamedExportClause(m[1], parsed);
|
|
2100
|
-
}
|
|
2101
|
-
}
|
|
2102
|
-
function pickComponentName(item, parsed) {
|
|
2103
|
-
const expected = [toPascalCase(item.dirName), toPascalCase(item.name)];
|
|
2104
|
-
for (const name of expected) {
|
|
2105
|
-
if (parsed.valueExports.has(name)) return name;
|
|
2106
|
-
}
|
|
2107
|
-
const lowered = new Set(expected.map((n) => n.toLowerCase()));
|
|
2108
|
-
for (const exp of parsed.valueExports) {
|
|
2109
|
-
if (lowered.has(exp.toLowerCase())) return exp;
|
|
2110
|
-
}
|
|
2111
|
-
return null;
|
|
2112
|
-
}
|
|
2113
|
-
function pickPropsName(componentName, parsed) {
|
|
2114
|
-
const direct = `${componentName}Props`;
|
|
2115
|
-
if (parsed.typeExports.has(direct) || parsed.valueExports.has(direct)) return direct;
|
|
2116
|
-
for (const sym of parsed.typeExports) {
|
|
2117
|
-
if (sym.toLowerCase() === direct.toLowerCase()) return sym;
|
|
2118
|
-
}
|
|
2119
|
-
for (const sym of parsed.valueExports) {
|
|
2120
|
-
if (sym.toLowerCase() === direct.toLowerCase()) return sym;
|
|
2121
|
-
}
|
|
2122
|
-
return null;
|
|
2123
|
-
}
|
|
2124
|
-
function pickDefaultExportComponent(item, typesIndexPath) {
|
|
2125
|
-
const expected = [toPascalCase(item.dirName), toPascalCase(item.name)];
|
|
2126
|
-
for (const name of expected) {
|
|
2127
|
-
const mainTypesPath = findMainComponentTypesPath(typesIndexPath, name);
|
|
2128
|
-
if (!mainTypesPath) continue;
|
|
2129
|
-
const mainText = readTypesFileText(mainTypesPath);
|
|
2130
|
-
const defaultExportMatch = mainText.match(/export\s+default\s+([A-Za-z_][A-Za-z0-9_]*)/);
|
|
2131
|
-
if (!defaultExportMatch) continue;
|
|
2132
|
-
const symbol = defaultExportMatch[1];
|
|
2133
|
-
if (expected.some((candidate) => candidate.toLowerCase() === symbol.toLowerCase())) {
|
|
2134
|
-
return symbol;
|
|
2135
|
-
}
|
|
2136
|
-
}
|
|
2137
|
-
return null;
|
|
2138
|
-
}
|
|
2139
|
-
function readTypesFileText(typesFilePath) {
|
|
2140
|
-
try {
|
|
2141
|
-
return fs6.readFileSync(typesFilePath, "utf-8");
|
|
2142
|
-
} catch {
|
|
2143
|
-
return "";
|
|
2144
|
-
}
|
|
2145
|
-
}
|
|
2146
|
-
function findMainComponentTypesPath(typesIndexPath, componentName) {
|
|
2147
|
-
const dir = path7.dirname(typesIndexPath);
|
|
2148
|
-
const indexText = readTypesFileText(typesIndexPath);
|
|
2149
|
-
const fromMatches = indexText.matchAll(/from\s+["']\.\/([^"']+)["']/g);
|
|
2150
|
-
for (const match of fromMatches) {
|
|
2151
|
-
const candidate = path7.join(dir, `${match[1]}.d.ts`);
|
|
2152
|
-
if (fs6.existsSync(candidate)) return candidate;
|
|
2153
|
-
}
|
|
2154
|
-
const byName = path7.join(dir, `${componentName}.d.ts`);
|
|
2155
|
-
return fs6.existsSync(byName) ? byName : null;
|
|
2156
|
-
}
|
|
2157
|
-
function isNonCallableCompoundExport(typesText, symbolName) {
|
|
2158
|
-
const objectDecl = new RegExp(
|
|
2159
|
-
`(?:declare\\s+const|const)\\s+${symbolName}\\s*:\\s*\\{`
|
|
2160
|
-
);
|
|
2161
|
-
return objectDecl.test(typesText);
|
|
2162
|
-
}
|
|
2163
|
-
function pickCompoundRenderMember(typesText) {
|
|
2164
|
-
if (/\bText\s*:\s*React\./.test(typesText)) return "Text";
|
|
2165
|
-
const memberMatch = typesText.match(
|
|
2166
|
-
/^\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*React\.(?:ForwardRefExoticComponent|NamedExoticComponent|FC)/m
|
|
2167
|
-
);
|
|
2168
|
-
return memberMatch?.[1] ?? "Text";
|
|
2169
|
-
}
|
|
2170
|
-
function resolveLazyAccess(typesIndexPath, componentName) {
|
|
2171
|
-
const indexText = readTypesFileText(typesIndexPath);
|
|
2172
|
-
const mainTypesPath = findMainComponentTypesPath(typesIndexPath, componentName);
|
|
2173
|
-
const mainText = mainTypesPath ? readTypesFileText(mainTypesPath) : "";
|
|
2174
|
-
const defaultAsMatch = indexText.match(
|
|
2175
|
-
new RegExp(`export\\s*\\{[^}]*\\bdefault\\s+as\\s+${componentName}\\b[^}]*\\}`)
|
|
2176
|
-
);
|
|
2177
|
-
const namedExportMatch = indexText.match(
|
|
2178
|
-
new RegExp(`export\\s*\\{[^}]*\\b${componentName}\\b[^}]*\\}`)
|
|
2179
|
-
);
|
|
2180
|
-
const defaultExportMatch = mainText.match(/export\s+default\s+([A-Za-z_][A-Za-z0-9_]*)/);
|
|
2181
|
-
const defaultSymbol = defaultExportMatch?.[1];
|
|
2182
|
-
const compoundSymbol = defaultSymbol && isNonCallableCompoundExport(mainText, defaultSymbol) ? defaultSymbol : isNonCallableCompoundExport(mainText, componentName) ? componentName : null;
|
|
2183
|
-
if (compoundSymbol) {
|
|
2184
|
-
const member = pickCompoundRenderMember(mainText);
|
|
2185
|
-
if (defaultAsMatch || namedExportMatch) {
|
|
2186
|
-
return `.${componentName}.${member}`;
|
|
2187
|
-
}
|
|
2188
|
-
return `.default.${member}`;
|
|
2189
|
-
}
|
|
2190
|
-
if (defaultAsMatch || namedExportMatch) return `.${componentName}`;
|
|
2191
|
-
if (defaultSymbol && defaultSymbol === componentName) {
|
|
2192
|
-
return `.default`;
|
|
2193
|
-
}
|
|
2194
|
-
return `.${componentName}`;
|
|
2195
|
-
}
|
|
2196
|
-
function subpathExposesLazyBinding(typesIndexPath, componentName) {
|
|
2197
|
-
const indexText = readTypesFileText(typesIndexPath);
|
|
2198
|
-
if (new RegExp(`export\\s*\\{[^}]*\\bdefault\\s+as\\s+${componentName}\\b[^}]*\\}`).test(
|
|
2199
|
-
indexText
|
|
2200
|
-
)) {
|
|
2201
|
-
return true;
|
|
2202
|
-
}
|
|
2203
|
-
if (new RegExp(`export\\s*\\{[^}]*\\b${componentName}\\b[^}]*\\}`).test(indexText)) {
|
|
2204
|
-
return true;
|
|
2205
|
-
}
|
|
2206
|
-
if (/export\s+default\b/.test(indexText)) return true;
|
|
2207
|
-
return pickComponentName(
|
|
2208
|
-
{ name: componentName, dirName: componentName },
|
|
2209
|
-
parseTypeExportsLocal(typesIndexPath)
|
|
2210
|
-
) !== null;
|
|
2211
|
-
}
|
|
2212
|
-
function resolveLazyImport(pkgInfo, importSpecifier, typesFilePath, componentName) {
|
|
2213
|
-
let lazyImportSpecifier = importSpecifier;
|
|
2214
|
-
let lazyAccess = resolveLazyAccess(typesFilePath, componentName);
|
|
2215
|
-
if (importSpecifier !== "@inventive-ui/components" && !subpathExposesLazyBinding(typesFilePath, componentName) && pkgInfo.rootTypesPath) {
|
|
2216
|
-
lazyImportSpecifier = "@inventive-ui/components";
|
|
2217
|
-
lazyAccess = `.${componentName}`;
|
|
2218
|
-
}
|
|
2219
|
-
return { lazyImportSpecifier, lazyAccess };
|
|
2220
|
-
}
|
|
2221
|
-
function describeExpected(item) {
|
|
2222
|
-
return `${toPascalCase(item.dirName)} / ${toPascalCase(item.name)}`;
|
|
2223
|
-
}
|
|
2224
|
-
function resolveFromTypesFile(item, importSpecifier, typesFilePath, pkgInfo) {
|
|
2225
|
-
const parsed = parseTypeExports(typesFilePath);
|
|
2226
|
-
const indexParsed = parseTypeExportsLocal(typesFilePath);
|
|
2227
|
-
const componentName = pickComponentName(item, parsed) ?? pickDefaultExportComponent(item, typesFilePath);
|
|
2228
|
-
if (!componentName) {
|
|
2229
|
-
return {
|
|
2230
|
-
ok: false,
|
|
2231
|
-
reason: `No matching component export in ${importSpecifier}. Expected ${describeExpected(item)}.`
|
|
2232
|
-
};
|
|
1936
|
+
// src/utils/security/identifiers.ts
|
|
1937
|
+
var SLUG_RE = /^[a-z][a-z0-9-]*$/;
|
|
1938
|
+
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
|
+
);
|
|
2233
1947
|
}
|
|
2234
|
-
const propsName = pickPropsName(componentName, indexParsed) ?? pickPropsName(componentName, parsed) ?? (() => {
|
|
2235
|
-
const typesPath = path7.join(path7.dirname(typesFilePath), "types.d.ts");
|
|
2236
|
-
if (!fs6.existsSync(typesPath)) return null;
|
|
2237
|
-
return pickPropsName(componentName, parseTypeExports(typesPath));
|
|
2238
|
-
})();
|
|
2239
|
-
const lazyImport = resolveLazyImport(
|
|
2240
|
-
pkgInfo,
|
|
2241
|
-
importSpecifier,
|
|
2242
|
-
typesFilePath,
|
|
2243
|
-
componentName
|
|
2244
|
-
);
|
|
2245
|
-
return {
|
|
2246
|
-
ok: true,
|
|
2247
|
-
importSpecifier,
|
|
2248
|
-
lazyImportSpecifier: lazyImport.lazyImportSpecifier,
|
|
2249
|
-
componentName,
|
|
2250
|
-
propsName: propsName ?? void 0,
|
|
2251
|
-
lazyAccess: lazyImport.lazyAccess
|
|
2252
|
-
};
|
|
2253
1948
|
}
|
|
2254
|
-
function
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
`./${item.name.toLowerCase()}`,
|
|
2258
|
-
`./${item.dirName}`,
|
|
2259
|
-
`./${item.dirName.toLowerCase()}`
|
|
2260
|
-
];
|
|
2261
|
-
return [...new Set(candidates)];
|
|
2262
|
-
}
|
|
2263
|
-
function componentFolderCandidates(item) {
|
|
2264
|
-
return [
|
|
2265
|
-
.../* @__PURE__ */ new Set([
|
|
2266
|
-
item.dirName,
|
|
2267
|
-
item.name,
|
|
2268
|
-
toPascalCase(item.dirName),
|
|
2269
|
-
toPascalCase(item.name)
|
|
2270
|
-
])
|
|
2271
|
-
];
|
|
2272
|
-
}
|
|
2273
|
-
function resolveWildcardTypesPath(pkgInfo, segment) {
|
|
2274
|
-
const wildcardEntry = pkgInfo.exportsField["./*"];
|
|
2275
|
-
if (!wildcardEntry) return null;
|
|
2276
|
-
const typesRel = resolveTypesPathFromExportEntry(wildcardEntry);
|
|
2277
|
-
if (!typesRel || !typesRel.includes("*")) return null;
|
|
2278
|
-
const resolvedRel = typesRel.replace(/\*/g, segment);
|
|
2279
|
-
const fullPath = path7.join(pkgInfo.packageRoot, resolvedRel);
|
|
2280
|
-
return fs6.existsSync(fullPath) ? fullPath : null;
|
|
2281
|
-
}
|
|
2282
|
-
function resolveTypesPathForExportCandidate(pkgInfo, candidate) {
|
|
2283
|
-
const entry = pkgInfo.exportsField[candidate];
|
|
2284
|
-
if (entry) {
|
|
2285
|
-
const typesRel = resolveTypesPathFromExportEntry(entry);
|
|
2286
|
-
return typesRel ? path7.join(pkgInfo.packageRoot, typesRel) : null;
|
|
2287
|
-
}
|
|
2288
|
-
const segment = candidate.replace(/^\.\//, "");
|
|
2289
|
-
return resolveWildcardTypesPath(pkgInfo, segment);
|
|
2290
|
-
}
|
|
2291
|
-
function resolveFromComponentFolders(item, pkgInfo) {
|
|
2292
|
-
for (const folder of componentFolderCandidates(item)) {
|
|
2293
|
-
const typesPath = resolveWildcardTypesPath(pkgInfo, folder) ?? (() => {
|
|
2294
|
-
const directPath = path7.join(
|
|
2295
|
-
pkgInfo.packageRoot,
|
|
2296
|
-
"dist",
|
|
2297
|
-
"components",
|
|
2298
|
-
folder,
|
|
2299
|
-
"index.d.ts"
|
|
2300
|
-
);
|
|
2301
|
-
return fs6.existsSync(directPath) ? directPath : null;
|
|
2302
|
-
})();
|
|
2303
|
-
if (!typesPath) continue;
|
|
2304
|
-
const importSpecifier = `@inventive-ui/components/${folder}`;
|
|
2305
|
-
try {
|
|
2306
|
-
assertImportSpecifier(importSpecifier);
|
|
2307
|
-
} catch {
|
|
2308
|
-
continue;
|
|
2309
|
-
}
|
|
2310
|
-
const resolved = resolveFromTypesFile(item, importSpecifier, typesPath, pkgInfo);
|
|
2311
|
-
if (resolved.ok) return resolved;
|
|
1949
|
+
function assertJsIdentifier(name, label) {
|
|
1950
|
+
if (!JS_IDENTIFIER_RE.test(name)) {
|
|
1951
|
+
throw new CLIError(`Invalid ${label}: "${name}"`);
|
|
2312
1952
|
}
|
|
2313
|
-
return null;
|
|
2314
1953
|
}
|
|
2315
|
-
function
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
);
|
|
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}"`);
|
|
2319
1959
|
}
|
|
2320
|
-
function
|
|
2321
|
-
return
|
|
1960
|
+
function escapeTsStringLiteral(value) {
|
|
1961
|
+
return JSON.stringify(value);
|
|
2322
1962
|
}
|
|
2323
|
-
function
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
reason: "@inventive-ui/components is not installed in node_modules."
|
|
2329
|
-
};
|
|
2330
|
-
}
|
|
2331
|
-
const fromFolders = resolveFromComponentFolders(item, pkgInfo);
|
|
2332
|
-
if (fromFolders?.ok) return fromFolders;
|
|
2333
|
-
for (const candidate of exportCandidatesForItem(item)) {
|
|
2334
|
-
const typesPath = resolveTypesPathForExportCandidate(pkgInfo, candidate);
|
|
2335
|
-
if (!typesPath) continue;
|
|
2336
|
-
const importSpecifier = `@inventive-ui/components/${candidate.replace(/^\.\//, "")}`;
|
|
2337
|
-
try {
|
|
2338
|
-
assertImportSpecifier(importSpecifier);
|
|
2339
|
-
} catch {
|
|
2340
|
-
continue;
|
|
2341
|
-
}
|
|
2342
|
-
const resolved = resolveFromTypesFile(item, importSpecifier, typesPath, pkgInfo);
|
|
2343
|
-
if (resolved.ok) return resolved;
|
|
2344
|
-
}
|
|
2345
|
-
if (pkgInfo.rootTypesPath) {
|
|
2346
|
-
const fromRoot = resolveFromTypesFile(item, "@inventive-ui/components", pkgInfo.rootTypesPath, pkgInfo);
|
|
2347
|
-
if (fromRoot.ok) return fromRoot;
|
|
2348
|
-
}
|
|
2349
|
-
if (!componentBuildExists(item, pkgInfo)) {
|
|
2350
|
-
return {
|
|
2351
|
-
ok: false,
|
|
2352
|
-
reason: buildMissingComponentReason(item)
|
|
2353
|
-
};
|
|
1963
|
+
function sanitizePackageVersionHeader(value) {
|
|
1964
|
+
if (!value) return null;
|
|
1965
|
+
const trimmed = value.trim();
|
|
1966
|
+
if (!/^[0-9A-Za-z.+~^<>= -]+$/.test(trimmed) || trimmed.length > 64) {
|
|
1967
|
+
throw new CLIError("Server returned an invalid package version header.");
|
|
2354
1968
|
}
|
|
2355
|
-
return
|
|
2356
|
-
ok: false,
|
|
2357
|
-
reason: `No matching component export for "${item.name}" in @inventive-ui/components. Expected a value export named ${describeExpected(item)}.`
|
|
2358
|
-
};
|
|
1969
|
+
return trimmed;
|
|
2359
1970
|
}
|
|
2360
1971
|
|
|
2361
1972
|
// src/utils/config-patch/component-config.ts
|
|
@@ -2376,19 +1987,6 @@ function findComponentConfigObject(sourceFile) {
|
|
|
2376
1987
|
visit(sourceFile);
|
|
2377
1988
|
return found;
|
|
2378
1989
|
}
|
|
2379
|
-
function findComponentConfigMapType(sourceFile) {
|
|
2380
|
-
let found;
|
|
2381
|
-
const visit = (node) => {
|
|
2382
|
-
if (found) return;
|
|
2383
|
-
if (ts2.isTypeAliasDeclaration(node) && ts2.isIdentifier(node.name) && node.name.text === "ComponentConfigMap" && node.type && ts2.isTypeLiteralNode(node.type)) {
|
|
2384
|
-
found = node.type;
|
|
2385
|
-
return;
|
|
2386
|
-
}
|
|
2387
|
-
ts2.forEachChild(node, visit);
|
|
2388
|
-
};
|
|
2389
|
-
visit(sourceFile);
|
|
2390
|
-
return found;
|
|
2391
|
-
}
|
|
2392
1990
|
function existingComponentKeys(obj) {
|
|
2393
1991
|
const keys = /* @__PURE__ */ new Set();
|
|
2394
1992
|
for (const prop of obj.properties) {
|
|
@@ -2398,33 +1996,14 @@ function existingComponentKeys(obj) {
|
|
|
2398
1996
|
}
|
|
2399
1997
|
return keys;
|
|
2400
1998
|
}
|
|
2401
|
-
function formatDefaultConfig(cfg) {
|
|
2402
|
-
return JSON.stringify(cfg, null, 6).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n");
|
|
2403
|
-
}
|
|
2404
1999
|
function buildComponentEntry(item) {
|
|
2405
2000
|
assertJsIdentifier(item.dirName, "component dirName");
|
|
2406
|
-
const cfg = item.meta?.defaultConfig ?? {};
|
|
2407
|
-
const cfgStr = formatDefaultConfig(cfg);
|
|
2408
2001
|
return ` ${item.dirName}: {
|
|
2409
|
-
default:
|
|
2002
|
+
default: {},
|
|
2410
2003
|
},
|
|
2411
2004
|
|
|
2412
2005
|
`;
|
|
2413
2006
|
}
|
|
2414
|
-
function buildTypeEntry(item, cwd) {
|
|
2415
|
-
const resolved = resolveComponentExport(item, cwd);
|
|
2416
|
-
if (resolved.ok && resolved.propsName) {
|
|
2417
|
-
return ` ${item.dirName}: { default: Partial<${resolved.propsName}> };`;
|
|
2418
|
-
}
|
|
2419
|
-
return ` ${item.dirName}: { default: Record<string, unknown> };`;
|
|
2420
|
-
}
|
|
2421
|
-
function buildTypeImport(item, cwd) {
|
|
2422
|
-
const resolved = resolveComponentExport(item, cwd);
|
|
2423
|
-
if (resolved.ok && resolved.propsName && resolved.importSpecifier) {
|
|
2424
|
-
return `import type { ${resolved.propsName} } from "${resolved.importSpecifier}";`;
|
|
2425
|
-
}
|
|
2426
|
-
return null;
|
|
2427
|
-
}
|
|
2428
2007
|
function insertBeforeClosingBrace(source, objectEnd, insertion) {
|
|
2429
2008
|
let pos = objectEnd - 1;
|
|
2430
2009
|
while (pos >= 0 && /\s/.test(source[pos] ?? "")) pos--;
|
|
@@ -2436,7 +2015,7 @@ function insertBeforeClosingBrace(source, objectEnd, insertion) {
|
|
|
2436
2015
|
}
|
|
2437
2016
|
return source;
|
|
2438
2017
|
}
|
|
2439
|
-
function mergeComponentConfigContent(source, manifest
|
|
2018
|
+
function mergeComponentConfigContent(source, manifest) {
|
|
2440
2019
|
if (!manifest || manifest.items.length === 0) {
|
|
2441
2020
|
return { content: source, changed: false };
|
|
2442
2021
|
}
|
|
@@ -2452,33 +2031,78 @@ function mergeComponentConfigContent(source, manifest, cwd) {
|
|
|
2452
2031
|
const existing = existingComponentKeys(configObject);
|
|
2453
2032
|
const missing = manifest.items.filter((item) => !existing.has(item.dirName));
|
|
2454
2033
|
if (missing.length === 0) return { content: source, changed: false };
|
|
2455
|
-
let next = source;
|
|
2456
2034
|
const newEntries = missing.map((item) => buildComponentEntry(item)).join("");
|
|
2457
|
-
next = insertBeforeClosingBrace(
|
|
2458
|
-
|
|
2459
|
-
|
|
2035
|
+
const next = insertBeforeClosingBrace(
|
|
2036
|
+
source,
|
|
2037
|
+
configObject.getEnd(),
|
|
2038
|
+
newEntries
|
|
2460
2039
|
);
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
`;
|
|
2464
|
-
next = insertBeforeClosingBrace(next, typeLiteral.getEnd(), typeLines);
|
|
2465
|
-
}
|
|
2466
|
-
const existingImportLines = new Set(next.match(/^import\s.+;$/gm) ?? []);
|
|
2467
|
-
const newImports = missing.map((item) => buildTypeImport(item, cwd)).filter((line) => line !== null && !existingImportLines.has(line));
|
|
2468
|
-
if (newImports.length > 0) {
|
|
2469
|
-
const importMatches = [...next.matchAll(/^import\s.+;$/gm)];
|
|
2470
|
-
const lastImport = importMatches.at(-1);
|
|
2471
|
-
if (lastImport?.index !== void 0) {
|
|
2472
|
-
const insertAt = lastImport.index + lastImport[0].length;
|
|
2473
|
-
next = `${next.slice(0, insertAt)}
|
|
2474
|
-
${[...new Set(newImports)].join("\n")}${next.slice(insertAt)}`;
|
|
2475
|
-
} else {
|
|
2476
|
-
next = `${[...new Set(newImports)].join("\n")}
|
|
2040
|
+
return { content: next, changed: true };
|
|
2041
|
+
}
|
|
2477
2042
|
|
|
2478
|
-
|
|
2043
|
+
// src/utils/config-patch/tsconfig-iui.ts
|
|
2044
|
+
import path7 from "path";
|
|
2045
|
+
import fs6 from "fs-extra";
|
|
2046
|
+
function isSolutionStyleTsconfig(config) {
|
|
2047
|
+
const refs = config.references;
|
|
2048
|
+
return Array.isArray(refs) && refs.length > 0;
|
|
2049
|
+
}
|
|
2050
|
+
function patchJsonInclude(filePath, extra) {
|
|
2051
|
+
if (!fs6.existsSync(filePath)) return false;
|
|
2052
|
+
const raw = fs6.readJsonSync(filePath);
|
|
2053
|
+
const include = Array.isArray(raw.include) ? [...raw.include.map(String)] : [];
|
|
2054
|
+
let changed = false;
|
|
2055
|
+
for (const item of extra) {
|
|
2056
|
+
if (!include.includes(item)) {
|
|
2057
|
+
include.push(item);
|
|
2058
|
+
changed = true;
|
|
2479
2059
|
}
|
|
2480
2060
|
}
|
|
2481
|
-
|
|
2061
|
+
if (!changed) return false;
|
|
2062
|
+
atomicWriteJson(filePath, { ...raw, include });
|
|
2063
|
+
return true;
|
|
2064
|
+
}
|
|
2065
|
+
function resolveAppTsconfigPath(cwd, root) {
|
|
2066
|
+
const refs = root.references;
|
|
2067
|
+
if (!refs) return null;
|
|
2068
|
+
for (const ref of refs) {
|
|
2069
|
+
const p = ref.path?.replace(/^\.\//, "") ?? "";
|
|
2070
|
+
const base = p.replace(/\.json$/i, "");
|
|
2071
|
+
if (/app/i.test(base)) {
|
|
2072
|
+
return path7.join(cwd, p.endsWith(".json") ? p : `${p}.json`);
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
for (const ref of refs) {
|
|
2076
|
+
const p = ref.path?.replace(/^\.\//, "") ?? "";
|
|
2077
|
+
if (!/node/i.test(p)) {
|
|
2078
|
+
return path7.join(cwd, p.endsWith(".json") ? p : `${p}.json`);
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
return null;
|
|
2082
|
+
}
|
|
2083
|
+
function repairSolutionStyleRootTsconfig(cwd) {
|
|
2084
|
+
const rootPath = path7.join(cwd, "tsconfig.json");
|
|
2085
|
+
if (!fs6.existsSync(rootPath)) return false;
|
|
2086
|
+
const existing = fs6.readJsonSync(rootPath);
|
|
2087
|
+
if (!isSolutionStyleTsconfig(existing)) return false;
|
|
2088
|
+
const polluted = existing.compilerOptions !== void 0 || Array.isArray(existing.include) && existing.include.length > 0 || Array.isArray(existing.exclude) && existing.exclude.length > 0;
|
|
2089
|
+
if (!polluted) return false;
|
|
2090
|
+
atomicWriteJson(rootPath, {
|
|
2091
|
+
files: Array.isArray(existing.files) ? existing.files : [],
|
|
2092
|
+
references: existing.references
|
|
2093
|
+
});
|
|
2094
|
+
return true;
|
|
2095
|
+
}
|
|
2096
|
+
function patchSolutionStyleTsconfigForIui(cwd) {
|
|
2097
|
+
const rootPath = path7.join(cwd, "tsconfig.json");
|
|
2098
|
+
if (!fs6.existsSync(rootPath)) return false;
|
|
2099
|
+
const existing = fs6.readJsonSync(rootPath);
|
|
2100
|
+
if (!isSolutionStyleTsconfig(existing)) return false;
|
|
2101
|
+
const repairedRoot = repairSolutionStyleRootTsconfig(cwd);
|
|
2102
|
+
const appPath = resolveAppTsconfigPath(cwd, existing);
|
|
2103
|
+
const themeFile = fs6.existsSync(path7.join(cwd, "iui.config.ts")) && !fs6.existsSync(path7.join(cwd, "theme.config.ts")) ? "iui.config.ts" : "theme.config.ts";
|
|
2104
|
+
const patchedApp = appPath ? patchJsonInclude(appPath, [themeFile, "component.config.ts"]) : false;
|
|
2105
|
+
return repairedRoot || patchedApp;
|
|
2482
2106
|
}
|
|
2483
2107
|
|
|
2484
2108
|
// src/validation/configTierChecks.ts
|
|
@@ -2495,10 +2119,9 @@ var iuiThemeConfigSchema = z2.object({
|
|
|
2495
2119
|
}).strict();
|
|
2496
2120
|
var IuiThemeConfigSchema = iuiThemeConfigSchema.refine(
|
|
2497
2121
|
(data) => !("assets" in data),
|
|
2498
|
-
{ message: "
|
|
2122
|
+
{ message: "theme.config must not contain an assets key \u2014 use assets.config.json" }
|
|
2499
2123
|
);
|
|
2500
2124
|
var AssetsConfigSchema = z2.object({
|
|
2501
|
-
binding: z2.enum(["lazy", "scanned"]).optional(),
|
|
2502
2125
|
preload: z2.enum(["none", "configured", "scanned"]).optional(),
|
|
2503
2126
|
icon: z2.object({
|
|
2504
2127
|
library: z2.string().optional(),
|
|
@@ -2571,11 +2194,14 @@ function stripAssetsFromIuiConfig(content) {
|
|
|
2571
2194
|
return next;
|
|
2572
2195
|
}
|
|
2573
2196
|
function checkIuiConfigTierBleed(cwd = process.cwd(), options = {}) {
|
|
2574
|
-
const configPath = path8.join(
|
|
2197
|
+
const configPath = path8.join(
|
|
2198
|
+
cwd,
|
|
2199
|
+
fs7.existsSync(path8.join(cwd, PROJECT_CONFIG_FILE)) || !fs7.existsSync(path8.join(cwd, "iui.config.ts")) ? PROJECT_CONFIG_FILE : "iui.config.ts"
|
|
2200
|
+
);
|
|
2575
2201
|
if (!fs7.existsSync(configPath)) {
|
|
2576
2202
|
return {
|
|
2577
2203
|
ok: false,
|
|
2578
|
-
summary: "
|
|
2204
|
+
summary: "theme.config.ts not found",
|
|
2579
2205
|
details: "Run iui init to scaffold project config."
|
|
2580
2206
|
};
|
|
2581
2207
|
}
|
|
@@ -2590,7 +2216,7 @@ function checkIuiConfigTierBleed(cwd = process.cwd(), options = {}) {
|
|
|
2590
2216
|
}
|
|
2591
2217
|
}
|
|
2592
2218
|
if (issues.length === 0) {
|
|
2593
|
-
return { ok: true, summary: "
|
|
2219
|
+
return { ok: true, summary: "theme.config.ts tier boundaries are valid" };
|
|
2594
2220
|
}
|
|
2595
2221
|
if (options.autoFix) {
|
|
2596
2222
|
const fixed = stripAssetsFromIuiConfig(content);
|
|
@@ -2603,14 +2229,14 @@ function checkIuiConfigTierBleed(cwd = process.cwd(), options = {}) {
|
|
|
2603
2229
|
if (remaining.length === 0 && /\bbuild\s*:\s*\{/.test(content)) {
|
|
2604
2230
|
return {
|
|
2605
2231
|
ok: true,
|
|
2606
|
-
summary: "
|
|
2232
|
+
summary: "theme.config.ts repaired (removed assets tier bleed)"
|
|
2607
2233
|
};
|
|
2608
2234
|
}
|
|
2609
2235
|
}
|
|
2610
2236
|
}
|
|
2611
2237
|
return {
|
|
2612
2238
|
ok: false,
|
|
2613
|
-
summary: "
|
|
2239
|
+
summary: "theme.config.ts violates three-config tier boundaries",
|
|
2614
2240
|
details: issues.map((i) => `- ${i}`).join("\n")
|
|
2615
2241
|
};
|
|
2616
2242
|
}
|
|
@@ -2877,15 +2503,6 @@ function loadAssetsConfigTemplate() {
|
|
|
2877
2503
|
return {};
|
|
2878
2504
|
}
|
|
2879
2505
|
}
|
|
2880
|
-
function loadComponentConfigPresetsTemplate() {
|
|
2881
|
-
const templatePath = path10.join(getCliTemplatesDir(), "component.config.presets.json");
|
|
2882
|
-
if (!fs8.existsSync(templatePath)) return {};
|
|
2883
|
-
try {
|
|
2884
|
-
return fs8.readJsonSync(templatePath);
|
|
2885
|
-
} catch {
|
|
2886
|
-
return {};
|
|
2887
|
-
}
|
|
2888
|
-
}
|
|
2889
2506
|
function mergeAssetSlotWithTemplate(slot, templateSlot) {
|
|
2890
2507
|
if (!templateSlot) return slot ?? {};
|
|
2891
2508
|
const out = { ...templateSlot, ...slot ?? {} };
|
|
@@ -2913,12 +2530,6 @@ function mergeAssetSlotWithTemplate(slot, templateSlot) {
|
|
|
2913
2530
|
function seedAssetsOutputFromTemplate(output) {
|
|
2914
2531
|
const template = loadAssetsConfigTemplate();
|
|
2915
2532
|
for (const [key, tplVal] of Object.entries(template)) {
|
|
2916
|
-
if (key === "binding") {
|
|
2917
|
-
if (output.binding === void 0 && tplVal !== void 0) {
|
|
2918
|
-
output.binding = tplVal;
|
|
2919
|
-
}
|
|
2920
|
-
continue;
|
|
2921
|
-
}
|
|
2922
2533
|
if (typeof tplVal === "object" && tplVal !== null && !Array.isArray(tplVal)) {
|
|
2923
2534
|
output[key] = mergeAssetSlotWithTemplate(
|
|
2924
2535
|
output[key],
|
|
@@ -2926,13 +2537,6 @@ function seedAssetsOutputFromTemplate(output) {
|
|
|
2926
2537
|
);
|
|
2927
2538
|
}
|
|
2928
2539
|
}
|
|
2929
|
-
if (output.binding === "scanned") {
|
|
2930
|
-
output.preload = output.preload ?? "scanned";
|
|
2931
|
-
const icon = output.icon;
|
|
2932
|
-
if (icon && typeof icon === "object" && !Array.isArray(icon)) {
|
|
2933
|
-
icon.preload = icon.preload ?? "scanned";
|
|
2934
|
-
}
|
|
2935
|
-
}
|
|
2936
2540
|
}
|
|
2937
2541
|
function assetsConfigPath(cwd) {
|
|
2938
2542
|
return path10.join(resolveIuiProjectRoot(cwd ?? process.cwd()), ASSETS_CONFIG_FILE);
|
|
@@ -3092,9 +2696,6 @@ function writeAssetsConfig(cwd = process.cwd()) {
|
|
|
3092
2696
|
delete output[legacyKey];
|
|
3093
2697
|
}
|
|
3094
2698
|
}
|
|
3095
|
-
if (output.binding === void 0 && Object.keys(assets2).length > 0 && projectHasViteTooling(cwd)) {
|
|
3096
|
-
output.binding = "scanned";
|
|
3097
|
-
}
|
|
3098
2699
|
seedAssetsOutputFromTemplate(output);
|
|
3099
2700
|
writeJson(assetsConfigPath(cwd), output);
|
|
3100
2701
|
try {
|
|
@@ -3147,12 +2748,19 @@ function registryItemsMap(manifest) {
|
|
|
3147
2748
|
}
|
|
3148
2749
|
return map;
|
|
3149
2750
|
}
|
|
2751
|
+
function resolveProjectConfigPath(root) {
|
|
2752
|
+
const current = path10.join(root, PROJECT_CONFIG_FILE);
|
|
2753
|
+
if (fs8.existsSync(current)) return current;
|
|
2754
|
+
const previous = path10.join(root, "iui.config.ts");
|
|
2755
|
+
if (fs8.existsSync(previous)) return previous;
|
|
2756
|
+
return current;
|
|
2757
|
+
}
|
|
3150
2758
|
function writeProjectConfig(cwd = process.cwd()) {
|
|
3151
2759
|
const configPath = path10.join(cwd, PROJECT_CONFIG_FILE);
|
|
3152
2760
|
atomicWriteFile(configPath, buildProjectConfigSource(cwd));
|
|
3153
2761
|
}
|
|
3154
2762
|
function ensureProjectConfigBuildBlock(cwd = process.cwd()) {
|
|
3155
|
-
const configPath =
|
|
2763
|
+
const configPath = resolveProjectConfigPath(resolveIuiProjectRoot(cwd));
|
|
3156
2764
|
if (!fs8.existsSync(configPath)) return false;
|
|
3157
2765
|
const before = fs8.readFileSync(configPath, "utf-8");
|
|
3158
2766
|
const result = patchProjectConfigBuildBlock(before);
|
|
@@ -3162,7 +2770,7 @@ function ensureProjectConfigBuildBlock(cwd = process.cwd()) {
|
|
|
3162
2770
|
}
|
|
3163
2771
|
function ensureProjectConfig(cwd = process.cwd()) {
|
|
3164
2772
|
const root = resolveIuiProjectRoot(cwd);
|
|
3165
|
-
const configPath =
|
|
2773
|
+
const configPath = resolveProjectConfigPath(root);
|
|
3166
2774
|
if (!fs8.existsSync(configPath)) {
|
|
3167
2775
|
writeProjectConfig(root);
|
|
3168
2776
|
return "scaffolded";
|
|
@@ -3232,7 +2840,24 @@ function writeTsConfigNode(cwd = process.cwd()) {
|
|
|
3232
2840
|
};
|
|
3233
2841
|
atomicWriteJson(nodeTsPath, content);
|
|
3234
2842
|
}
|
|
3235
|
-
function
|
|
2843
|
+
function ensureTsConfigForIui(framework, cwd = process.cwd()) {
|
|
2844
|
+
const tsconfigPath = path10.join(cwd, "tsconfig.json");
|
|
2845
|
+
let existing = {};
|
|
2846
|
+
if (fs8.existsSync(tsconfigPath)) {
|
|
2847
|
+
try {
|
|
2848
|
+
existing = fs8.readJsonSync(tsconfigPath);
|
|
2849
|
+
} catch {
|
|
2850
|
+
existing = {};
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
if (framework === "vite" && isSolutionStyleTsconfig(existing)) {
|
|
2854
|
+
patchSolutionStyleTsconfigForIui(cwd);
|
|
2855
|
+
writeTsConfigNode(cwd);
|
|
2856
|
+
return;
|
|
2857
|
+
}
|
|
2858
|
+
writeFlatProjectTsConfig(framework, cwd);
|
|
2859
|
+
}
|
|
2860
|
+
function writeFlatProjectTsConfig(framework, cwd = process.cwd()) {
|
|
3236
2861
|
const tsconfigPath = path10.join(cwd, "tsconfig.json");
|
|
3237
2862
|
let existing = {};
|
|
3238
2863
|
if (fs8.existsSync(tsconfigPath)) {
|
|
@@ -3275,7 +2900,8 @@ function writeTsConfig(framework, cwd = process.cwd()) {
|
|
|
3275
2900
|
}
|
|
3276
2901
|
const include = Array.isArray(existing.include) ? [...existing.include.map(String)] : [];
|
|
3277
2902
|
if (!include.includes("src")) include.push("src");
|
|
3278
|
-
const
|
|
2903
|
+
const themeConfigFile = fs8.existsSync(path10.join(cwd, "iui.config.ts")) && !fs8.existsSync(path10.join(cwd, PROJECT_CONFIG_FILE)) ? "iui.config.ts" : PROJECT_CONFIG_FILE;
|
|
2904
|
+
const rootConfigFiles = [themeConfigFile, "component.config.ts"];
|
|
3279
2905
|
for (const rootFile of rootConfigFiles) {
|
|
3280
2906
|
if (!include.includes(rootFile)) include.push(rootFile);
|
|
3281
2907
|
}
|
|
@@ -3300,56 +2926,22 @@ function writeTsConfig(framework, cwd = process.cwd()) {
|
|
|
3300
2926
|
};
|
|
3301
2927
|
atomicWriteJson(tsconfigPath, output);
|
|
3302
2928
|
}
|
|
3303
|
-
function writeComponentConfig(
|
|
2929
|
+
function writeComponentConfig(_manifest, cwd = process.cwd()) {
|
|
3304
2930
|
const configPath = path10.join(cwd, COMPONENT_CONFIG_FILE);
|
|
3305
|
-
let entries = "";
|
|
3306
|
-
const typedEntries = [];
|
|
3307
|
-
const typeImports = [];
|
|
3308
|
-
const presetsTemplate = loadComponentConfigPresetsTemplate();
|
|
3309
|
-
if (manifest) {
|
|
3310
|
-
for (const item of manifest.items) {
|
|
3311
|
-
assertJsIdentifier(item.dirName, "component dirName");
|
|
3312
|
-
const cfg = item.meta?.defaultConfig ?? {};
|
|
3313
|
-
const presetBlock = presetsTemplate[item.dirName];
|
|
3314
|
-
const cfgStr = JSON.stringify(cfg, null, 6).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n");
|
|
3315
|
-
let extraBlocks = "";
|
|
3316
|
-
if (presetBlock?.presets) {
|
|
3317
|
-
const presetsStr = JSON.stringify(presetBlock.presets, null, 6).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n");
|
|
3318
|
-
extraBlocks += `
|
|
3319
|
-
presets: ${presetsStr},`;
|
|
3320
|
-
}
|
|
3321
|
-
entries += ` ${item.dirName}: {
|
|
3322
|
-
default: ${cfgStr},${extraBlocks}
|
|
3323
|
-
},
|
|
3324
|
-
|
|
3325
|
-
`;
|
|
3326
|
-
const resolved = resolveComponentExport(item, cwd);
|
|
3327
|
-
if (resolved.ok && resolved.propsName && resolved.importSpecifier) {
|
|
3328
|
-
typeImports.push(`import type { ${resolved.propsName} } from "${resolved.importSpecifier}";`);
|
|
3329
|
-
typedEntries.push(` ${item.dirName}: { default: Partial<${resolved.propsName}> };`);
|
|
3330
|
-
} else {
|
|
3331
|
-
typedEntries.push(` ${item.dirName}: { default: Record<string, unknown> };`);
|
|
3332
|
-
}
|
|
3333
|
-
}
|
|
3334
|
-
}
|
|
3335
|
-
const imports = [...new Set(typeImports)].join("\n");
|
|
3336
|
-
const componentConfigType = typedEntries.length > 0 ? `type ComponentConfigMap = {
|
|
3337
|
-
${typedEntries.join("\n")}
|
|
3338
|
-
};` : `type ComponentConfigMap = Record<string, { default: Record<string, unknown> }>;`;
|
|
3339
2931
|
const content = `// \u2500\u2500\u2500 Component Configuration \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3340
2932
|
//
|
|
3341
|
-
//
|
|
3342
|
-
//
|
|
3343
|
-
//
|
|
2933
|
+
// Optional per-component defaults (variant, appearance, presets, cTags).
|
|
2934
|
+
// Only add entries you want to override \u2014 omit components you do not customize.
|
|
2935
|
+
// \`iui update\` may append new registry keys; edit or remove them as needed.
|
|
3344
2936
|
//
|
|
3345
2937
|
// Docs: https://inventiveui.com/docs/configuration
|
|
3346
2938
|
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
${componentConfigType}
|
|
2939
|
+
import type { ComponentConfig } from "@inventive-ui/components/config";
|
|
3350
2940
|
|
|
3351
|
-
export const componentConfig
|
|
3352
|
-
|
|
2941
|
+
export const componentConfig = {
|
|
2942
|
+
// Example:
|
|
2943
|
+
// Button: { default: { variant: "solid", appearance: "soft" } },
|
|
2944
|
+
} satisfies ComponentConfig;
|
|
3353
2945
|
`;
|
|
3354
2946
|
atomicWriteFile(configPath, content);
|
|
3355
2947
|
}
|
|
@@ -3361,7 +2953,7 @@ function ensureComponentConfig(manifest, cwd = process.cwd(), options = {}) {
|
|
|
3361
2953
|
return existed && options.force ? "replaced" : "scaffolded";
|
|
3362
2954
|
}
|
|
3363
2955
|
const before = fs8.readFileSync(configPath, "utf-8");
|
|
3364
|
-
const result = mergeComponentConfigContent(before, manifest
|
|
2956
|
+
const result = mergeComponentConfigContent(before, manifest);
|
|
3365
2957
|
if (!result.changed) return "noop";
|
|
3366
2958
|
atomicWriteFile(configPath, result.content);
|
|
3367
2959
|
return "merged";
|
|
@@ -3773,13 +3365,13 @@ function ensureInventiveUiViteConfig(cwd = process.cwd()) {
|
|
|
3773
3365
|
}
|
|
3774
3366
|
|
|
3775
3367
|
// src/services/auth.ts
|
|
3776
|
-
async function api(
|
|
3777
|
-
const res = await fetch(`${API_BASE_URL}${
|
|
3368
|
+
async function api(path27, opts) {
|
|
3369
|
+
const res = await fetch(`${API_BASE_URL}${path27}`, {
|
|
3778
3370
|
...opts,
|
|
3779
3371
|
signal: opts?.signal ?? AbortSignal.timeout(API_REQUEST_TIMEOUT_MS),
|
|
3780
3372
|
headers: { "Content-Type": "application/json", ...opts?.headers }
|
|
3781
3373
|
});
|
|
3782
|
-
throwIfRateLimited(res, `calling ${
|
|
3374
|
+
throwIfRateLimited(res, `calling ${path27}`);
|
|
3783
3375
|
if (!res.ok) {
|
|
3784
3376
|
const body = await res.text().catch(() => "");
|
|
3785
3377
|
throw new CLIError(`API error ${res.status}: ${body || res.statusText}`);
|
|
@@ -4031,10 +3623,12 @@ async function promptAssetSelection(installedPackages = []) {
|
|
|
4031
3623
|
const choices = [];
|
|
4032
3624
|
for (const cat of categories) {
|
|
4033
3625
|
const inCategory = catalogue.filter((p) => p.category === cat);
|
|
3626
|
+
if (choices.length > 0) {
|
|
3627
|
+
choices.push(new inquirer.Separator(" "));
|
|
3628
|
+
}
|
|
4034
3629
|
choices.push(
|
|
4035
3630
|
new inquirer.Separator(
|
|
4036
|
-
`
|
|
4037
|
-
${brand.bold(ASSET_CATEGORY_LABELS[cat])} ${dim(`(${inCategory.length})`)}`
|
|
3631
|
+
` ${brand.bold(ASSET_CATEGORY_LABELS[cat])} ${dim(`(${inCategory.length})`)}`
|
|
4038
3632
|
)
|
|
4039
3633
|
);
|
|
4040
3634
|
for (const pkg of inCategory) {
|
|
@@ -4046,6 +3640,8 @@ async function promptAssetSelection(installedPackages = []) {
|
|
|
4046
3640
|
}
|
|
4047
3641
|
}
|
|
4048
3642
|
console.log();
|
|
3643
|
+
const terminalRows = process.stdout.rows ?? 0;
|
|
3644
|
+
const pageSize = terminalRows > 0 ? Math.max(10, Math.min(choices.length, terminalRows - 4)) : choices.length;
|
|
4049
3645
|
const { selected } = await inquirer.prompt([
|
|
4050
3646
|
{
|
|
4051
3647
|
type: "checkbox",
|
|
@@ -4053,7 +3649,7 @@ async function promptAssetSelection(installedPackages = []) {
|
|
|
4053
3649
|
message: chalk2.dim("Toggle packages to install"),
|
|
4054
3650
|
prefix: PROMPT_PREFIX,
|
|
4055
3651
|
choices,
|
|
4056
|
-
pageSize
|
|
3652
|
+
pageSize,
|
|
4057
3653
|
loop: false
|
|
4058
3654
|
}
|
|
4059
3655
|
]);
|
|
@@ -4135,7 +3731,7 @@ async function promptChooseEmojiFamily(fallbackCurrent) {
|
|
|
4135
3731
|
assertInteractivePrompt("emoji family choice");
|
|
4136
3732
|
inputBox(
|
|
4137
3733
|
"Emoji Family",
|
|
4138
|
-
"Choose the default CDN style for emoji slots. Skin tone defaults to medium-light."
|
|
3734
|
+
"Choose the default CDN style for emoji slots. Skin tone defaults to medium-light (`mediumLight`)."
|
|
4139
3735
|
);
|
|
4140
3736
|
const { chosen } = await inquirer.prompt([
|
|
4141
3737
|
{
|
|
@@ -4227,7 +3823,7 @@ async function promptText(title, hint2, placeholder, validate) {
|
|
|
4227
3823
|
}
|
|
4228
3824
|
|
|
4229
3825
|
// src/commands/init.ts
|
|
4230
|
-
import
|
|
3826
|
+
import path22 from "path";
|
|
4231
3827
|
import ora3 from "ora";
|
|
4232
3828
|
|
|
4233
3829
|
// src/services/license.ts
|
|
@@ -5194,8 +4790,8 @@ function getMajorFromVersion(version) {
|
|
|
5194
4790
|
import ora2 from "ora";
|
|
5195
4791
|
|
|
5196
4792
|
// src/services/slot-registry.ts
|
|
5197
|
-
import
|
|
5198
|
-
import
|
|
4793
|
+
import fs17 from "fs-extra";
|
|
4794
|
+
import path21 from "path";
|
|
5199
4795
|
|
|
5200
4796
|
// src/services/registry-lock.ts
|
|
5201
4797
|
import fs11 from "fs";
|
|
@@ -5282,8 +4878,8 @@ async function withRegistryLock(cwd, operation) {
|
|
|
5282
4878
|
}
|
|
5283
4879
|
|
|
5284
4880
|
// src/services/slots.ts
|
|
5285
|
-
import
|
|
5286
|
-
import
|
|
4881
|
+
import fs14 from "fs-extra";
|
|
4882
|
+
import path18 from "path";
|
|
5287
4883
|
|
|
5288
4884
|
// src/utils/public-slot-contract.ts
|
|
5289
4885
|
import path15 from "path";
|
|
@@ -5413,11 +5009,6 @@ function safeWriteFile(filePath, content) {
|
|
|
5413
5009
|
atomicWriteFile(filePath, content);
|
|
5414
5010
|
}
|
|
5415
5011
|
|
|
5416
|
-
// src/services/asset-bound.ts
|
|
5417
|
-
import fs14 from "fs-extra";
|
|
5418
|
-
import path18 from "path";
|
|
5419
|
-
import { pathToFileURL } from "url";
|
|
5420
|
-
|
|
5421
5012
|
// src/services/generated-paths.ts
|
|
5422
5013
|
import path17 from "path";
|
|
5423
5014
|
function iuiProjectRoot2(cwd) {
|
|
@@ -5429,367 +5020,26 @@ function generatedIuiDir(cwd) {
|
|
|
5429
5020
|
function generatedSlotsDir(cwd) {
|
|
5430
5021
|
return path17.join(generatedIuiDir(cwd), "slots");
|
|
5431
5022
|
}
|
|
5432
|
-
function generatedAssetsDir(cwd) {
|
|
5433
|
-
return path17.join(generatedIuiDir(cwd), "assets");
|
|
5434
|
-
}
|
|
5435
|
-
|
|
5436
|
-
// src/services/asset-bound.ts
|
|
5437
|
-
var LIBRARY_TO_PKG = {
|
|
5438
|
-
lucide: "icons-lucide",
|
|
5439
|
-
phosphor: "icons-phosphor",
|
|
5440
|
-
material: "icons-material",
|
|
5441
|
-
"material-icons": "icons-material",
|
|
5442
|
-
materialSymbols: "material-symbols",
|
|
5443
|
-
"material-symbols": "material-symbols"
|
|
5444
|
-
};
|
|
5445
|
-
var PKG_LOOKUP_PREFIX = {
|
|
5446
|
-
"icons-lucide": "icons/",
|
|
5447
|
-
"icons-phosphor": "icons/",
|
|
5448
|
-
"icons-material": "icons/",
|
|
5449
|
-
"material-symbols": "icons/",
|
|
5450
|
-
logos: "logos/",
|
|
5451
|
-
"color-logos": "logos/",
|
|
5452
|
-
flags: "flags/",
|
|
5453
|
-
"file-types": "types/",
|
|
5454
|
-
loaders: "loaders/",
|
|
5455
|
-
illustrations: ""
|
|
5456
|
-
};
|
|
5457
|
-
var BOUND_SPECS = [
|
|
5458
|
-
{
|
|
5459
|
-
slotType: "icon",
|
|
5460
|
-
fileName: "icons.bound.ts",
|
|
5461
|
-
exportName: "BOUND_ICONS",
|
|
5462
|
-
packages: /* @__PURE__ */ new Set([
|
|
5463
|
-
"material-symbols",
|
|
5464
|
-
"icons-lucide",
|
|
5465
|
-
"icons-phosphor",
|
|
5466
|
-
"icons-material"
|
|
5467
|
-
]),
|
|
5468
|
-
filterByDefaultIconLibrary: true
|
|
5469
|
-
},
|
|
5470
|
-
{
|
|
5471
|
-
slotType: "logo",
|
|
5472
|
-
fileName: "logos.bound.ts",
|
|
5473
|
-
exportName: "BOUND_LOGOS",
|
|
5474
|
-
packages: /* @__PURE__ */ new Set(["logos"])
|
|
5475
|
-
},
|
|
5476
|
-
{
|
|
5477
|
-
slotType: "color-logo",
|
|
5478
|
-
fileName: "color-logos.bound.ts",
|
|
5479
|
-
exportName: "BOUND_COLOR_LOGOS",
|
|
5480
|
-
packages: /* @__PURE__ */ new Set(["color-logos"])
|
|
5481
|
-
},
|
|
5482
|
-
{
|
|
5483
|
-
slotType: "flag",
|
|
5484
|
-
fileName: "flags.bound.ts",
|
|
5485
|
-
exportName: "BOUND_FLAGS",
|
|
5486
|
-
packages: /* @__PURE__ */ new Set(["flags"])
|
|
5487
|
-
},
|
|
5488
|
-
{
|
|
5489
|
-
slotType: "file-type",
|
|
5490
|
-
fileName: "file-types.bound.ts",
|
|
5491
|
-
exportName: "BOUND_FILE_TYPES",
|
|
5492
|
-
packages: /* @__PURE__ */ new Set(["file-types"])
|
|
5493
|
-
},
|
|
5494
|
-
{
|
|
5495
|
-
slotType: "loader",
|
|
5496
|
-
fileName: "loaders.bound.ts",
|
|
5497
|
-
exportName: "BOUND_LOADERS",
|
|
5498
|
-
packages: /* @__PURE__ */ new Set(["loaders"])
|
|
5499
|
-
},
|
|
5500
|
-
{
|
|
5501
|
-
slotType: "illustration",
|
|
5502
|
-
fileName: "illustrations.bound.ts",
|
|
5503
|
-
exportName: "BOUND_ILLUSTRATIONS",
|
|
5504
|
-
packages: /* @__PURE__ */ new Set(["illustrations"])
|
|
5505
|
-
}
|
|
5506
|
-
];
|
|
5507
|
-
function isAssetPackageInstalled(cwd, pkgId) {
|
|
5508
|
-
return resolvePackageDir(`@inventive-ui/${pkgId}`, cwd) !== null;
|
|
5509
|
-
}
|
|
5510
|
-
var DEFAULT_SCAN = {
|
|
5511
|
-
scanDirs: ["src", ".storybook", "stories", ".iui"],
|
|
5512
|
-
include: [
|
|
5513
|
-
"**/*.stories.*",
|
|
5514
|
-
"**/*.mdx",
|
|
5515
|
-
"**/src/**/*.tsx",
|
|
5516
|
-
"**/src/**/*.ts",
|
|
5517
|
-
"**/src/**/*.jsx",
|
|
5518
|
-
"**/src/**/*.js",
|
|
5519
|
-
"**/.storybook/**/*.tsx",
|
|
5520
|
-
"**/.storybook/**/*.ts",
|
|
5521
|
-
"**/.storybook/**/*.jsx",
|
|
5522
|
-
"**/.storybook/**/*.js"
|
|
5523
|
-
],
|
|
5524
|
-
exclude: ["**/*.test.*", "**/*.spec.*"]
|
|
5525
|
-
};
|
|
5526
|
-
function resolveFrameworkModule(cwd, relativePath) {
|
|
5527
|
-
const searchRoots = /* @__PURE__ */ new Set();
|
|
5528
|
-
for (const candidate of [
|
|
5529
|
-
resolveDependencyInstallRoot(cwd),
|
|
5530
|
-
path18.resolve(cwd),
|
|
5531
|
-
iuiProjectRoot2(cwd)
|
|
5532
|
-
]) {
|
|
5533
|
-
searchRoots.add(path18.resolve(candidate));
|
|
5534
|
-
}
|
|
5535
|
-
for (const start of searchRoots) {
|
|
5536
|
-
const frameworkDir = resolvePackageDir("@inventive-ui/framework", start);
|
|
5537
|
-
if (!frameworkDir) continue;
|
|
5538
|
-
const installed = path18.join(frameworkDir, relativePath);
|
|
5539
|
-
if (fs14.existsSync(installed)) return installed;
|
|
5540
|
-
}
|
|
5541
|
-
const root = iuiProjectRoot2(cwd);
|
|
5542
|
-
for (const candidate of [
|
|
5543
|
-
path18.join(root, "..", "Framework", relativePath),
|
|
5544
|
-
path18.join(root, "..", "..", "Framework", relativePath)
|
|
5545
|
-
]) {
|
|
5546
|
-
if (fs14.existsSync(candidate)) return candidate;
|
|
5547
|
-
}
|
|
5548
|
-
return null;
|
|
5549
|
-
}
|
|
5550
|
-
async function loadScanUtils(cwd) {
|
|
5551
|
-
const scanPath = resolveFrameworkModule(
|
|
5552
|
-
cwd,
|
|
5553
|
-
"integrations/vite/scan-used-slot-assets.mjs"
|
|
5554
|
-
);
|
|
5555
|
-
const resolvePath = resolveFrameworkModule(
|
|
5556
|
-
cwd,
|
|
5557
|
-
"integrations/shared/resolve-scanned-icon-name.mjs"
|
|
5558
|
-
);
|
|
5559
|
-
if (!scanPath || !resolvePath) {
|
|
5560
|
-
const installRoot = resolveDependencyInstallRoot(cwd);
|
|
5561
|
-
const frameworkDir = resolvePackageDir("@inventive-ui/framework", installRoot);
|
|
5562
|
-
const hint2 = frameworkDir && !scanPath ? "Update @inventive-ui/framework to the latest version (iui update) \u2014 scan utilities require a current Framework release." : "Install @inventive-ui/framework and run iui doctor again.";
|
|
5563
|
-
throw new CLIError("Could not load Framework scan utilities.", hint2);
|
|
5564
|
-
}
|
|
5565
|
-
const scanMod = await import(pathToFileURL(scanPath).href);
|
|
5566
|
-
const resolveMod = await import(pathToFileURL(resolvePath).href);
|
|
5567
|
-
return { ...scanMod, ...resolveMod };
|
|
5568
|
-
}
|
|
5569
|
-
function lookupKeyToGlyphKey(pkg, lookupKey) {
|
|
5570
|
-
let subpath = lookupKey.replace(/^\.\//, "").replace(/\.js$/, "");
|
|
5571
|
-
if (pkg === "illustrations") {
|
|
5572
|
-
return subpath;
|
|
5573
|
-
}
|
|
5574
|
-
const prefix = PKG_LOOKUP_PREFIX[pkg];
|
|
5575
|
-
if (prefix && subpath.startsWith(prefix)) {
|
|
5576
|
-
subpath = subpath.slice(prefix.length);
|
|
5577
|
-
}
|
|
5578
|
-
return subpath;
|
|
5579
|
-
}
|
|
5580
|
-
function glyphToIdentifier(name, used) {
|
|
5581
|
-
let base = name.split(/[^a-zA-Z0-9]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
5582
|
-
if (!base || !/^[A-Za-z_$]/.test(base)) {
|
|
5583
|
-
base = `Glyph${base}`;
|
|
5584
|
-
}
|
|
5585
|
-
let id = base;
|
|
5586
|
-
let suffix = 2;
|
|
5587
|
-
while (used.has(id)) {
|
|
5588
|
-
id = `${base}${suffix++}`;
|
|
5589
|
-
}
|
|
5590
|
-
used.add(id);
|
|
5591
|
-
return id;
|
|
5592
|
-
}
|
|
5593
|
-
function resolveIconPkg(library) {
|
|
5594
|
-
return LIBRARY_TO_PKG[library] ?? library;
|
|
5595
|
-
}
|
|
5596
|
-
function buildBoundFileContent(exportName, entries) {
|
|
5597
|
-
const lines = [
|
|
5598
|
-
"// Managed by iui. Do not edit manually.",
|
|
5599
|
-
'// Static glyph bindings for scanned assets (`binding: "scanned"`).',
|
|
5600
|
-
"",
|
|
5601
|
-
'import type { ComponentType } from "react";'
|
|
5602
|
-
];
|
|
5603
|
-
for (const entry of entries) {
|
|
5604
|
-
lines.push(`import ${entry.identifier} from "${entry.moduleId}";`);
|
|
5605
|
-
}
|
|
5606
|
-
lines.push("");
|
|
5607
|
-
lines.push(
|
|
5608
|
-
`export const ${exportName}: Record<string, ComponentType<Record<string, unknown>>> = {`
|
|
5609
|
-
);
|
|
5610
|
-
for (const entry of entries) {
|
|
5611
|
-
lines.push(` ${JSON.stringify(entry.key)}: ${entry.identifier},`);
|
|
5612
|
-
}
|
|
5613
|
-
lines.push("};");
|
|
5614
|
-
lines.push("");
|
|
5615
|
-
return lines.join("\n");
|
|
5616
|
-
}
|
|
5617
|
-
function cleanupAssetBoundFiles(cwd) {
|
|
5618
|
-
const assetsDir = generatedAssetsDir(cwd);
|
|
5619
|
-
if (!fs14.existsSync(assetsDir)) return;
|
|
5620
|
-
for (const file of fs14.readdirSync(assetsDir)) {
|
|
5621
|
-
if (file.endsWith(".bound.ts") || file === "register-bound.ts") {
|
|
5622
|
-
fs14.removeSync(path18.join(assetsDir, file));
|
|
5623
|
-
}
|
|
5624
|
-
}
|
|
5625
|
-
const remaining = fs14.readdirSync(assetsDir);
|
|
5626
|
-
if (remaining.length === 0) {
|
|
5627
|
-
fs14.removeSync(assetsDir);
|
|
5628
|
-
}
|
|
5629
|
-
}
|
|
5630
|
-
function hasAssetBoundRegistration(cwd) {
|
|
5631
|
-
return fs14.existsSync(path18.join(generatedAssetsDir(cwd), "register-bound.ts"));
|
|
5632
|
-
}
|
|
5633
|
-
async function writeAssetBoundFiles(cwd = process.cwd()) {
|
|
5634
|
-
const root = iuiProjectRoot2(cwd);
|
|
5635
|
-
const scanUtils = await loadScanUtils(cwd);
|
|
5636
|
-
const activeSpecs = BOUND_SPECS.filter(
|
|
5637
|
-
(spec) => scanUtils.isScannedAssetBindingEnabled(root, spec.slotType)
|
|
5638
|
-
);
|
|
5639
|
-
if (activeSpecs.length === 0) {
|
|
5640
|
-
cleanupAssetBoundFiles(root);
|
|
5641
|
-
return;
|
|
5642
|
-
}
|
|
5643
|
-
const registry = scanUtils.scanUsedSlotAssets(root, DEFAULT_SCAN);
|
|
5644
|
-
const defaultIconLibrary = scanUtils.readDefaultIconLibraryFromConfig(root);
|
|
5645
|
-
const defaultIconPkg = resolveIconPkg(defaultIconLibrary);
|
|
5646
|
-
const assetsDir = generatedAssetsDir(root);
|
|
5647
|
-
fs14.ensureDirSync(assetsDir);
|
|
5648
|
-
const generatedFiles = /* @__PURE__ */ new Set();
|
|
5649
|
-
const registrationSpecs = [];
|
|
5650
|
-
for (const spec of activeSpecs) {
|
|
5651
|
-
const entries = [];
|
|
5652
|
-
const usedIdentifiers = /* @__PURE__ */ new Set();
|
|
5653
|
-
for (const [pkg, keys] of registry.entries()) {
|
|
5654
|
-
if (!spec.packages.has(pkg)) continue;
|
|
5655
|
-
if ("filterByDefaultIconLibrary" in spec && spec.filterByDefaultIconLibrary && pkg !== defaultIconPkg) {
|
|
5656
|
-
continue;
|
|
5657
|
-
}
|
|
5658
|
-
if (!isAssetPackageInstalled(cwd, pkg)) continue;
|
|
5659
|
-
for (const lookupKey of keys) {
|
|
5660
|
-
const key = lookupKeyToGlyphKey(pkg, lookupKey);
|
|
5661
|
-
const moduleId = scanUtils.lookupKeyToModuleId(pkg, lookupKey);
|
|
5662
|
-
const identifier = glyphToIdentifier(key, usedIdentifiers);
|
|
5663
|
-
if (entries.some((entry) => entry.key === key)) continue;
|
|
5664
|
-
entries.push({ key, moduleId, identifier });
|
|
5665
|
-
}
|
|
5666
|
-
}
|
|
5667
|
-
entries.sort((a, b) => a.key.localeCompare(b.key));
|
|
5668
|
-
if (entries.length === 0) {
|
|
5669
|
-
continue;
|
|
5670
|
-
}
|
|
5671
|
-
const content = buildBoundFileContent(spec.exportName, entries);
|
|
5672
|
-
const outPath = resolveWithinRoot(
|
|
5673
|
-
root,
|
|
5674
|
-
".iui",
|
|
5675
|
-
"generated",
|
|
5676
|
-
"assets",
|
|
5677
|
-
spec.fileName
|
|
5678
|
-
);
|
|
5679
|
-
safeWriteFile(outPath, content);
|
|
5680
|
-
generatedFiles.add(spec.fileName);
|
|
5681
|
-
registrationSpecs.push({
|
|
5682
|
-
slotType: spec.slotType,
|
|
5683
|
-
exportName: spec.exportName,
|
|
5684
|
-
fileName: spec.fileName
|
|
5685
|
-
});
|
|
5686
|
-
}
|
|
5687
|
-
const existing = fs14.existsSync(assetsDir) ? fs14.readdirSync(assetsDir).filter((f) => f.endsWith(".bound.ts")) : [];
|
|
5688
|
-
for (const file of existing) {
|
|
5689
|
-
if (!generatedFiles.has(file)) {
|
|
5690
|
-
fs14.removeSync(path18.join(assetsDir, file));
|
|
5691
|
-
}
|
|
5692
|
-
}
|
|
5693
|
-
if (registrationSpecs.length === 0) {
|
|
5694
|
-
cleanupAssetBoundFiles(root);
|
|
5695
|
-
return;
|
|
5696
|
-
}
|
|
5697
|
-
const registerLines = [
|
|
5698
|
-
"// Managed by iui. Do not edit manually.",
|
|
5699
|
-
"",
|
|
5700
|
-
'import { registerBoundAssetComponents } from "@inventive-ui/framework/slots";'
|
|
5701
|
-
];
|
|
5702
|
-
for (const spec of registrationSpecs) {
|
|
5703
|
-
registerLines.push(
|
|
5704
|
-
`import { ${spec.exportName} } from "./${spec.fileName.replace(/\.ts$/, "")}";`
|
|
5705
|
-
);
|
|
5706
|
-
}
|
|
5707
|
-
registerLines.push("");
|
|
5708
|
-
for (const spec of registrationSpecs) {
|
|
5709
|
-
registerLines.push(
|
|
5710
|
-
`registerBoundAssetComponents(${JSON.stringify(spec.slotType)}, ${spec.exportName});`
|
|
5711
|
-
);
|
|
5712
|
-
}
|
|
5713
|
-
registerLines.push("");
|
|
5714
|
-
safeWriteFile(
|
|
5715
|
-
resolveWithinRoot(root, ".iui", "generated", "assets", "register-bound.ts"),
|
|
5716
|
-
registerLines.join("\n")
|
|
5717
|
-
);
|
|
5718
|
-
}
|
|
5719
|
-
function assetModuleCandidates(pkgRoot, moduleId) {
|
|
5720
|
-
const pkgName = moduleId.split("/").slice(0, 2).join("/");
|
|
5721
|
-
const subpath = moduleId.slice(pkgName.length + 1);
|
|
5722
|
-
const pkgId = pkgName.replace("@inventive-ui/", "");
|
|
5723
|
-
if (!subpath || subpath.includes("..")) return [];
|
|
5724
|
-
if (pkgId === "loaders") {
|
|
5725
|
-
return [path18.join(pkgRoot, "dist", "loaders", `${subpath}.js`)];
|
|
5726
|
-
}
|
|
5727
|
-
if (pkgId === "illustrations") {
|
|
5728
|
-
const [family, scene] = subpath.split("/");
|
|
5729
|
-
if (family && scene) {
|
|
5730
|
-
return [path18.join(pkgRoot, "dist", family, `${scene}.js`)];
|
|
5731
|
-
}
|
|
5732
|
-
return [path18.join(pkgRoot, "dist", `${subpath}.js`)];
|
|
5733
|
-
}
|
|
5734
|
-
const prefix = PKG_LOOKUP_PREFIX[pkgId];
|
|
5735
|
-
if (prefix) {
|
|
5736
|
-
const dir = prefix.replace(/\/$/, "");
|
|
5737
|
-
return [
|
|
5738
|
-
path18.join(pkgRoot, "dist", dir, `${subpath}.js`),
|
|
5739
|
-
path18.join(pkgRoot, "dist", `${subpath}.js`),
|
|
5740
|
-
path18.join(pkgRoot, "dist", subpath, "index.js")
|
|
5741
|
-
];
|
|
5742
|
-
}
|
|
5743
|
-
return [
|
|
5744
|
-
path18.join(pkgRoot, "dist", `${subpath}.js`),
|
|
5745
|
-
path18.join(pkgRoot, "dist", subpath, "index.js")
|
|
5746
|
-
];
|
|
5747
|
-
}
|
|
5748
|
-
function validateGeneratedAssetBoundImports(cwd = process.cwd()) {
|
|
5749
|
-
const assetsDir = generatedAssetsDir(cwd);
|
|
5750
|
-
if (!fs14.existsSync(assetsDir)) return [];
|
|
5751
|
-
const issues = [];
|
|
5752
|
-
const boundFiles = fs14.readdirSync(assetsDir).filter((file) => file.endsWith(".bound.ts"));
|
|
5753
|
-
for (const file of boundFiles) {
|
|
5754
|
-
const content = fs14.readFileSync(path18.join(assetsDir, file), "utf8");
|
|
5755
|
-
const importRe = /from\s+["'](@inventive-ui\/[^"']+)["']/g;
|
|
5756
|
-
let match;
|
|
5757
|
-
while ((match = importRe.exec(content)) !== null) {
|
|
5758
|
-
const moduleId = match[1];
|
|
5759
|
-
const pkgName = moduleId.split("/").slice(0, 2).join("/");
|
|
5760
|
-
const pkgRoot = resolvePackageDir(pkgName, cwd);
|
|
5761
|
-
if (!pkgRoot) {
|
|
5762
|
-
issues.push(`${file}: missing asset package ${pkgName}`);
|
|
5763
|
-
continue;
|
|
5764
|
-
}
|
|
5765
|
-
const candidates = assetModuleCandidates(pkgRoot, moduleId);
|
|
5766
|
-
if (!candidates.some((candidate) => fs14.existsSync(candidate))) {
|
|
5767
|
-
issues.push(`${file}: missing asset module ${moduleId}`);
|
|
5768
|
-
}
|
|
5769
|
-
}
|
|
5770
|
-
}
|
|
5771
|
-
return issues;
|
|
5772
|
-
}
|
|
5773
5023
|
|
|
5774
5024
|
// src/services/slots.ts
|
|
5775
5025
|
var SLOT_GROUP_CORE_FILE = "slot-core.generated.tsx";
|
|
5776
5026
|
var SLOT_GROUP_OPTIONAL_FILE = "slot-optional.generated.tsx";
|
|
5777
5027
|
function bridgeSlotFilePath(cwd) {
|
|
5778
|
-
return
|
|
5028
|
+
return path18.join(cwd, "src", "iui", "slot.tsx");
|
|
5779
5029
|
}
|
|
5780
5030
|
function cleanupLegacySourceSlotFiles(cwd) {
|
|
5781
|
-
const legacySlotsDir =
|
|
5782
|
-
if (!
|
|
5031
|
+
const legacySlotsDir = path18.join(cwd, "src", "iui", "slots");
|
|
5032
|
+
if (!fs14.existsSync(legacySlotsDir)) return;
|
|
5783
5033
|
try {
|
|
5784
|
-
const files =
|
|
5034
|
+
const files = fs14.readdirSync(legacySlotsDir);
|
|
5785
5035
|
for (const file of files) {
|
|
5786
5036
|
if (file.endsWith(".slot.tsx")) {
|
|
5787
|
-
|
|
5037
|
+
fs14.removeSync(path18.join(legacySlotsDir, file));
|
|
5788
5038
|
}
|
|
5789
5039
|
}
|
|
5790
|
-
const remaining =
|
|
5040
|
+
const remaining = fs14.readdirSync(legacySlotsDir);
|
|
5791
5041
|
if (remaining.length === 0) {
|
|
5792
|
-
|
|
5042
|
+
fs14.removeSync(legacySlotsDir);
|
|
5793
5043
|
}
|
|
5794
5044
|
} catch {
|
|
5795
5045
|
}
|
|
@@ -5853,18 +5103,18 @@ function writeComponentSlotFiles(cwd = process.cwd()) {
|
|
|
5853
5103
|
const generationIssues = [];
|
|
5854
5104
|
cleanupLegacySourceSlotFiles(cwd);
|
|
5855
5105
|
if (Object.keys(components).length === 0) {
|
|
5856
|
-
if (
|
|
5857
|
-
const existingSlots2 =
|
|
5106
|
+
if (fs14.existsSync(slotsDir)) {
|
|
5107
|
+
const existingSlots2 = fs14.readdirSync(slotsDir).filter((f) => f.endsWith(".slot.tsx"));
|
|
5858
5108
|
for (const file of existingSlots2) {
|
|
5859
5109
|
try {
|
|
5860
|
-
|
|
5110
|
+
fs14.removeSync(path18.join(slotsDir, file));
|
|
5861
5111
|
} catch {
|
|
5862
5112
|
}
|
|
5863
5113
|
}
|
|
5864
5114
|
}
|
|
5865
5115
|
return;
|
|
5866
5116
|
}
|
|
5867
|
-
|
|
5117
|
+
fs14.ensureDirSync(slotsDir);
|
|
5868
5118
|
if (!pkgManifest) return;
|
|
5869
5119
|
const itemsLookup = registryItemsMap(pkgManifest);
|
|
5870
5120
|
const installedItems = Object.entries(components).map(([slug]) => itemsLookup[slug]).filter((item) => Boolean(item));
|
|
@@ -5905,7 +5155,7 @@ function writeComponentSlotFiles(cwd = process.cwd()) {
|
|
|
5905
5155
|
for (const group of renderedGroups) {
|
|
5906
5156
|
const outPath = resolveWithinRoot(root, ".iui", "generated", "slots", group.fileName);
|
|
5907
5157
|
if (group.emitters.length === 0) {
|
|
5908
|
-
if (
|
|
5158
|
+
if (fs14.existsSync(outPath)) fs14.removeSync(outPath);
|
|
5909
5159
|
continue;
|
|
5910
5160
|
}
|
|
5911
5161
|
safeWriteFile(
|
|
@@ -5915,19 +5165,19 @@ function writeComponentSlotFiles(cwd = process.cwd()) {
|
|
|
5915
5165
|
})
|
|
5916
5166
|
);
|
|
5917
5167
|
}
|
|
5918
|
-
const existingSlots =
|
|
5168
|
+
const existingSlots = fs14.existsSync(slotsDir) ? fs14.readdirSync(slotsDir).filter((f) => f.endsWith(".slot.tsx") || f.endsWith(".generated.tsx")) : [];
|
|
5919
5169
|
for (const file of existingSlots) {
|
|
5920
5170
|
if (file === SLOT_GROUP_CORE_FILE || file === SLOT_GROUP_OPTIONAL_FILE) continue;
|
|
5921
5171
|
if (file.endsWith(".slot.tsx")) {
|
|
5922
5172
|
try {
|
|
5923
|
-
|
|
5173
|
+
fs14.removeSync(path18.join(slotsDir, file));
|
|
5924
5174
|
} catch {
|
|
5925
5175
|
}
|
|
5926
5176
|
continue;
|
|
5927
5177
|
}
|
|
5928
5178
|
if (file.endsWith(".generated.tsx")) {
|
|
5929
5179
|
try {
|
|
5930
|
-
|
|
5180
|
+
fs14.removeSync(path18.join(slotsDir, file));
|
|
5931
5181
|
} catch {
|
|
5932
5182
|
}
|
|
5933
5183
|
}
|
|
@@ -6031,24 +5281,18 @@ function writeSlotHelperFile(cwd = process.cwd()) {
|
|
|
6031
5281
|
}
|
|
6032
5282
|
const typesArray = Array.from(slotTypes).sort();
|
|
6033
5283
|
const slotImports = [];
|
|
6034
|
-
const coreSlotsPath =
|
|
6035
|
-
const optionalSlotsPath =
|
|
6036
|
-
if (
|
|
6037
|
-
if (
|
|
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$/, "")}";`);
|
|
6038
5288
|
const componentSlotImports = slotImports.join("\n");
|
|
6039
|
-
const includeAssetBindings = hasAssetBoundRegistration(cwd);
|
|
6040
5289
|
const outDir = generatedIuiDir(cwd);
|
|
6041
|
-
|
|
6042
|
-
const outPath =
|
|
5290
|
+
fs14.ensureDirSync(outDir);
|
|
5291
|
+
const outPath = path18.join(outDir, "slot.generated.tsx");
|
|
6043
5292
|
const sections = [
|
|
6044
5293
|
`// Managed by iui. Do not edit manually.`,
|
|
6045
5294
|
`// Rebuilt automatically when the CLI validates the project.`
|
|
6046
5295
|
];
|
|
6047
|
-
if (includeAssetBindings) {
|
|
6048
|
-
sections.push("");
|
|
6049
|
-
sections.push("// Scanned asset bindings (static glyph imports)");
|
|
6050
|
-
sections.push(`import "./assets/register-bound";`);
|
|
6051
|
-
}
|
|
6052
5296
|
if (componentSlotImports) {
|
|
6053
5297
|
sections.push("");
|
|
6054
5298
|
sections.push("// Component slot registrations");
|
|
@@ -6074,11 +5318,11 @@ ${typesArray.map((t) => ` | "${t}"`).join("\n")};` : `export type IUISlotType =
|
|
|
6074
5318
|
}
|
|
6075
5319
|
function writeSlotBridge(packageDir, iuiRoot2) {
|
|
6076
5320
|
const bridgePath = bridgeSlotFilePath(packageDir);
|
|
6077
|
-
const generatedFile =
|
|
6078
|
-
const importBase = relativeImportPath(
|
|
6079
|
-
|
|
6080
|
-
if (
|
|
6081
|
-
const existing =
|
|
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");
|
|
6082
5326
|
if (existing.length > 0 && !/@iui-managed/.test(existing)) {
|
|
6083
5327
|
return;
|
|
6084
5328
|
}
|
|
@@ -6095,18 +5339,18 @@ export type { IUISlotType } from "${importBase}";
|
|
|
6095
5339
|
}
|
|
6096
5340
|
|
|
6097
5341
|
// src/services/workspace-bootstrap.ts
|
|
6098
|
-
import
|
|
6099
|
-
import
|
|
5342
|
+
import path20 from "path";
|
|
5343
|
+
import fs16 from "fs-extra";
|
|
6100
5344
|
|
|
6101
5345
|
// src/services/bootstrap.ts
|
|
6102
|
-
import
|
|
6103
|
-
import
|
|
5346
|
+
import fs15 from "fs-extra";
|
|
5347
|
+
import path19 from "path";
|
|
6104
5348
|
var BOOTSTRAP_GENERATED_FILE = "bootstrap.generated.tsx";
|
|
6105
5349
|
function bridgeBootstrapFilePath(cwd) {
|
|
6106
|
-
return
|
|
5350
|
+
return path19.join(cwd, "src", "iui", "bootstrap.ts");
|
|
6107
5351
|
}
|
|
6108
5352
|
function bootstrapGeneratedPath(cwd = process.cwd()) {
|
|
6109
|
-
return
|
|
5353
|
+
return path19.join(generatedIuiDir(cwd), BOOTSTRAP_GENERATED_FILE);
|
|
6110
5354
|
}
|
|
6111
5355
|
function resolveProjectConfigPaths(cwd) {
|
|
6112
5356
|
const meta = readProjectMeta(cwd);
|
|
@@ -6121,8 +5365,8 @@ function resolveProjectConfigPaths(cwd) {
|
|
|
6121
5365
|
};
|
|
6122
5366
|
}
|
|
6123
5367
|
function configImportFromGenerated(cwd, configRel) {
|
|
6124
|
-
const generatedDir =
|
|
6125
|
-
const abs =
|
|
5368
|
+
const generatedDir = path19.dirname(bootstrapGeneratedPath(cwd));
|
|
5369
|
+
const abs = path19.resolve(cwd, configRel.replace(/^\.\//, ""));
|
|
6126
5370
|
return relativeImportPath(generatedDir, abs);
|
|
6127
5371
|
}
|
|
6128
5372
|
function expectedBootstrapImportPaths(cwd) {
|
|
@@ -6135,13 +5379,13 @@ function expectedBootstrapImportPaths(cwd) {
|
|
|
6135
5379
|
}
|
|
6136
5380
|
function writeBootstrapGenerated(cwd = process.cwd()) {
|
|
6137
5381
|
const outPath = bootstrapGeneratedPath(cwd);
|
|
6138
|
-
|
|
5382
|
+
fs15.ensureDirSync(path19.dirname(outPath));
|
|
6139
5383
|
const imports = expectedBootstrapImportPaths(cwd);
|
|
6140
5384
|
const content = `// @iui-managed
|
|
6141
5385
|
|
|
6142
5386
|
// Generated by iui CLI \u2014 do not edit manually.
|
|
6143
5387
|
|
|
6144
|
-
// Connects
|
|
5388
|
+
// Connects theme.config.ts + assets.config.json + component.config.ts for standard bootstrap.
|
|
6145
5389
|
|
|
6146
5390
|
|
|
6147
5391
|
|
|
@@ -6161,7 +5405,7 @@ import {
|
|
|
6161
5405
|
|
|
6162
5406
|
} from "@inventive-ui/framework";
|
|
6163
5407
|
|
|
6164
|
-
import { initConfig as
|
|
5408
|
+
import { initConfig as initAssetsConfig } from "@inventive-ui/framework/assets";
|
|
6165
5409
|
|
|
6166
5410
|
import type { IUIAssetsConfig } from "@inventive-ui/framework/config";
|
|
6167
5411
|
|
|
@@ -6197,7 +5441,7 @@ registerBootstrapState({
|
|
|
6197
5441
|
|
|
6198
5442
|
initFramework(frameworkConfig);
|
|
6199
5443
|
|
|
6200
|
-
|
|
5444
|
+
initAssetsConfig(frameworkConfig);
|
|
6201
5445
|
|
|
6202
5446
|
|
|
6203
5447
|
|
|
@@ -6209,10 +5453,10 @@ export { projectComponentConfig as componentConfig };
|
|
|
6209
5453
|
function writeBootstrapBridge(packageDir, iuiRoot2) {
|
|
6210
5454
|
const bridgePath = bridgeBootstrapFilePath(packageDir);
|
|
6211
5455
|
const generatedFile = bootstrapGeneratedPath(iuiRoot2);
|
|
6212
|
-
const importBase = relativeImportPath(
|
|
6213
|
-
|
|
6214
|
-
if (
|
|
6215
|
-
const existing =
|
|
5456
|
+
const importBase = relativeImportPath(path19.dirname(bridgePath), generatedFile);
|
|
5457
|
+
fs15.ensureDirSync(path19.dirname(bridgePath));
|
|
5458
|
+
if (fs15.existsSync(bridgePath)) {
|
|
5459
|
+
const existing = fs15.readFileSync(bridgePath, "utf-8");
|
|
6216
5460
|
if (existing.length > 0 && !/@iui-managed/.test(existing)) {
|
|
6217
5461
|
return;
|
|
6218
5462
|
}
|
|
@@ -6237,13 +5481,13 @@ function writeProjectBootstrapArtifacts(packageDir, iuiRoot2) {
|
|
|
6237
5481
|
|
|
6238
5482
|
// src/services/workspace-bootstrap.ts
|
|
6239
5483
|
function workspaceManifestPath(iuiRoot2) {
|
|
6240
|
-
return
|
|
5484
|
+
return path20.join(iuiRoot2, IUI_DIR, "workspace.json");
|
|
6241
5485
|
}
|
|
6242
5486
|
function readWorkspaceManifest(iuiRoot2) {
|
|
6243
5487
|
const p = workspaceManifestPath(iuiRoot2);
|
|
6244
|
-
if (!
|
|
5488
|
+
if (!fs16.existsSync(p)) return null;
|
|
6245
5489
|
try {
|
|
6246
|
-
const raw =
|
|
5490
|
+
const raw = fs16.readJsonSync(p);
|
|
6247
5491
|
if (!Array.isArray(raw.packages)) return null;
|
|
6248
5492
|
return {
|
|
6249
5493
|
iuiRoot: raw.iuiRoot ?? iuiRoot2,
|
|
@@ -6255,40 +5499,40 @@ function readWorkspaceManifest(iuiRoot2) {
|
|
|
6255
5499
|
}
|
|
6256
5500
|
}
|
|
6257
5501
|
function writeWorkspaceManifest(iuiRoot2, packageDirs) {
|
|
6258
|
-
const unique = [...new Set(packageDirs.map((dir) =>
|
|
5502
|
+
const unique = [...new Set(packageDirs.map((dir) => path20.resolve(dir)))];
|
|
6259
5503
|
atomicWriteJson(workspaceManifestPath(iuiRoot2), {
|
|
6260
|
-
packages: unique.map((dir) =>
|
|
5504
|
+
packages: unique.map((dir) => path20.relative(iuiRoot2, dir) || "."),
|
|
6261
5505
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6262
5506
|
});
|
|
6263
5507
|
}
|
|
6264
5508
|
function resolveRegisteredPackageDirs(iuiRoot2) {
|
|
6265
|
-
const resolvedRoot =
|
|
5509
|
+
const resolvedRoot = path20.resolve(iuiRoot2);
|
|
6266
5510
|
const manifest = readWorkspaceManifest(resolvedRoot);
|
|
6267
5511
|
if (!manifest) return [resolvedRoot];
|
|
6268
5512
|
const dirs = manifest.packages.map(
|
|
6269
|
-
(rel) =>
|
|
5513
|
+
(rel) => path20.resolve(resolvedRoot, rel === "." ? "" : rel)
|
|
6270
5514
|
);
|
|
6271
|
-
if (!dirs.some((dir) =>
|
|
5515
|
+
if (!dirs.some((dir) => path20.resolve(dir) === resolvedRoot)) {
|
|
6272
5516
|
dirs.unshift(resolvedRoot);
|
|
6273
5517
|
}
|
|
6274
5518
|
return dirs;
|
|
6275
5519
|
}
|
|
6276
5520
|
function registerWorkspacePackage(iuiRoot2, packageDir) {
|
|
6277
|
-
const resolvedRoot =
|
|
6278
|
-
const resolvedPackage =
|
|
5521
|
+
const resolvedRoot = path20.resolve(iuiRoot2);
|
|
5522
|
+
const resolvedPackage = path20.resolve(packageDir);
|
|
6279
5523
|
const existing = resolveRegisteredPackageDirs(resolvedRoot);
|
|
6280
|
-
if (!existing.some((dir) =>
|
|
5524
|
+
if (!existing.some((dir) => path20.resolve(dir) === resolvedPackage)) {
|
|
6281
5525
|
existing.push(resolvedPackage);
|
|
6282
5526
|
}
|
|
6283
5527
|
writeWorkspaceManifest(resolvedRoot, existing);
|
|
6284
5528
|
}
|
|
6285
5529
|
function registerAllWorkspacePackages(iuiRoot2) {
|
|
6286
|
-
const resolvedRoot =
|
|
5530
|
+
const resolvedRoot = path20.resolve(iuiRoot2);
|
|
6287
5531
|
const workspaceRoot = findWorkspaceRoot(resolvedRoot);
|
|
6288
5532
|
const targets = /* @__PURE__ */ new Set([resolvedRoot]);
|
|
6289
5533
|
if (workspaceRoot) {
|
|
6290
5534
|
for (const pkgDir of listWorkspacePackageDirs(workspaceRoot)) {
|
|
6291
|
-
targets.add(
|
|
5535
|
+
targets.add(path20.resolve(pkgDir));
|
|
6292
5536
|
}
|
|
6293
5537
|
}
|
|
6294
5538
|
const dirs = [...targets];
|
|
@@ -6299,7 +5543,7 @@ function bootstrapRegisteredPackages(iuiRoot2) {
|
|
|
6299
5543
|
const resolvedRoot = resolveIuiProjectRoot(iuiRoot2);
|
|
6300
5544
|
const bootstrapped = [];
|
|
6301
5545
|
for (const packageDir of resolveRegisteredPackageDirs(resolvedRoot)) {
|
|
6302
|
-
if (!
|
|
5546
|
+
if (!fs16.existsSync(path20.join(packageDir, "package.json"))) continue;
|
|
6303
5547
|
ensureProjectNpmrc(packageDir);
|
|
6304
5548
|
writeSlotBridge(packageDir, resolvedRoot);
|
|
6305
5549
|
writeProjectBootstrapArtifacts(packageDir, resolvedRoot);
|
|
@@ -6308,9 +5552,9 @@ function bootstrapRegisteredPackages(iuiRoot2) {
|
|
|
6308
5552
|
return bootstrapped;
|
|
6309
5553
|
}
|
|
6310
5554
|
async function bootstrapWorkspacePackage(packageDir, iuiRoot2) {
|
|
6311
|
-
const resolvedPackage =
|
|
5555
|
+
const resolvedPackage = path20.resolve(packageDir);
|
|
6312
5556
|
const resolvedIuiRoot = resolveIuiProjectRoot(iuiRoot2);
|
|
6313
|
-
if (!
|
|
5557
|
+
if (!fs16.existsSync(path20.join(resolvedPackage, "package.json"))) {
|
|
6314
5558
|
throw new CLIError(
|
|
6315
5559
|
`No package.json found in ${resolvedPackage}.`,
|
|
6316
5560
|
"Run iui init from a workspace app directory that contains package.json."
|
|
@@ -6346,17 +5590,17 @@ function checksumFor(components, slots) {
|
|
|
6346
5590
|
return sha256(JSON.stringify({ components, slots }));
|
|
6347
5591
|
}
|
|
6348
5592
|
function backupCorruptFile(filePath) {
|
|
6349
|
-
if (!
|
|
5593
|
+
if (!fs17.existsSync(filePath)) return;
|
|
6350
5594
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
6351
5595
|
try {
|
|
6352
|
-
|
|
5596
|
+
fs17.moveSync(filePath, `${filePath}.corrupt-${stamp}`, { overwrite: false });
|
|
6353
5597
|
} catch {
|
|
6354
5598
|
}
|
|
6355
5599
|
}
|
|
6356
5600
|
function readJsonObject(filePath, fallback, issues, label) {
|
|
6357
|
-
if (!
|
|
5601
|
+
if (!fs17.existsSync(filePath)) return fallback;
|
|
6358
5602
|
try {
|
|
6359
|
-
const value =
|
|
5603
|
+
const value = fs17.readJsonSync(filePath);
|
|
6360
5604
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
6361
5605
|
return value;
|
|
6362
5606
|
}
|
|
@@ -6368,9 +5612,9 @@ function readJsonObject(filePath, fallback, issues, label) {
|
|
|
6368
5612
|
}
|
|
6369
5613
|
function readState(cwd, issues) {
|
|
6370
5614
|
const filePath = statePath(cwd);
|
|
6371
|
-
if (!
|
|
5615
|
+
if (!fs17.existsSync(filePath)) return null;
|
|
6372
5616
|
try {
|
|
6373
|
-
const raw =
|
|
5617
|
+
const raw = fs17.readJsonSync(filePath);
|
|
6374
5618
|
if (raw.schemaVersion !== STATE_SCHEMA_VERSION) {
|
|
6375
5619
|
issues.push("registration state schema was upgraded");
|
|
6376
5620
|
return null;
|
|
@@ -6474,7 +5718,7 @@ async function ensureSlotRegistry(options = {}) {
|
|
|
6474
5718
|
}
|
|
6475
5719
|
const iuiRoot2 = resolveIuiProjectRoot(cwd);
|
|
6476
5720
|
return withRegistryLock(iuiRoot2, async () => {
|
|
6477
|
-
const iuiPath =
|
|
5721
|
+
const iuiPath = path21.join(iuiRoot2, IUI_DIR);
|
|
6478
5722
|
const issues = [];
|
|
6479
5723
|
cleanupTempFiles(iuiPath);
|
|
6480
5724
|
const registry = ensureInstalledManifest(
|
|
@@ -6528,9 +5772,7 @@ async function ensureSlotRegistry(options = {}) {
|
|
|
6528
5772
|
if (driftDetected) {
|
|
6529
5773
|
issues.push("slot manifests drifted");
|
|
6530
5774
|
}
|
|
6531
|
-
const
|
|
6532
|
-
const assetBoundIssues = validateGeneratedAssetBoundImports(iuiRoot2);
|
|
6533
|
-
const integrityIssues = [...generationIssues, ...assetBoundIssues];
|
|
5775
|
+
const integrityIssues = validateGeneratedSlotImports(iuiRoot2);
|
|
6534
5776
|
if (shouldSkipWritesFastPath({
|
|
6535
5777
|
mode,
|
|
6536
5778
|
previousState,
|
|
@@ -6584,7 +5826,6 @@ async function ensureSlotRegistry(options = {}) {
|
|
|
6584
5826
|
writeComponentSlotFiles(iuiRoot2);
|
|
6585
5827
|
writeAssetsConfig(iuiRoot2);
|
|
6586
5828
|
ensureProjectConfig(iuiRoot2);
|
|
6587
|
-
await writeAssetBoundFiles(iuiRoot2);
|
|
6588
5829
|
writeSlotHelperFile(iuiRoot2);
|
|
6589
5830
|
if (projectHasViteTooling(cwd)) {
|
|
6590
5831
|
ensureInventiveUiViteConfig(cwd);
|
|
@@ -6769,7 +6010,7 @@ async function initCommand(opts) {
|
|
|
6769
6010
|
try {
|
|
6770
6011
|
heading("Initialize Project");
|
|
6771
6012
|
const existingIuiRoot = findIuiProjectRoot(invocationCwd);
|
|
6772
|
-
if (existingIuiRoot &&
|
|
6013
|
+
if (existingIuiRoot && path22.resolve(existingIuiRoot) !== path22.resolve(invocationCwd)) {
|
|
6773
6014
|
await bootstrapWorkspacePackage(invocationCwd, existingIuiRoot);
|
|
6774
6015
|
return;
|
|
6775
6016
|
}
|
|
@@ -6788,10 +6029,10 @@ async function initCommand(opts) {
|
|
|
6788
6029
|
return;
|
|
6789
6030
|
}
|
|
6790
6031
|
const originalCwd = process.cwd();
|
|
6791
|
-
if (
|
|
6032
|
+
if (path22.resolve(initRoot) !== path22.resolve(originalCwd)) {
|
|
6792
6033
|
process.chdir(initRoot);
|
|
6793
6034
|
hint(
|
|
6794
|
-
`Monorepo --workspace: initializing at ${
|
|
6035
|
+
`Monorepo --workspace: initializing at ${path22.relative(invocationCwd, initRoot) || initRoot}`
|
|
6795
6036
|
);
|
|
6796
6037
|
} else if (!sharedWorkspace && findIuiProjectRoot(initRoot) === null) {
|
|
6797
6038
|
hint("Initializing this package only \u2014 other monorepo apps are untouched.");
|
|
@@ -6852,7 +6093,7 @@ async function initCommand(opts) {
|
|
|
6852
6093
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6853
6094
|
initScope: sharedWorkspace ? "workspace" : "package",
|
|
6854
6095
|
configs: {
|
|
6855
|
-
theme: "./
|
|
6096
|
+
theme: "./theme.config.ts",
|
|
6856
6097
|
assets: "./assets.config.json",
|
|
6857
6098
|
components: "./component.config.ts"
|
|
6858
6099
|
}
|
|
@@ -6913,17 +6154,17 @@ async function initCommand(opts) {
|
|
|
6913
6154
|
step("Generating config files\u2026");
|
|
6914
6155
|
writeAssetsConfig(initRoot);
|
|
6915
6156
|
ensureProjectConfig(initRoot);
|
|
6916
|
-
|
|
6157
|
+
ensureTsConfigForIui(framework.framework, initRoot);
|
|
6917
6158
|
if (framework.framework === "vite") {
|
|
6918
6159
|
ensureInventiveUiViteConfig(initRoot);
|
|
6919
|
-
ok("Config files ready (
|
|
6160
|
+
ok("Config files ready (theme.config.ts, tsconfig.json, tsconfig.node.json, vite.config.ts)");
|
|
6920
6161
|
} else {
|
|
6921
6162
|
if (removeStaleIuiViteConfig(initRoot)) {
|
|
6922
6163
|
hint("Removed vite.config.ts (React-only preset \u2014 no Vite tooling required).");
|
|
6923
6164
|
}
|
|
6924
|
-
ok("Config files ready (
|
|
6165
|
+
ok("Config files ready (theme.config.ts, tsconfig.json)");
|
|
6925
6166
|
}
|
|
6926
|
-
step("
|
|
6167
|
+
step("Scaffolding component.config.ts\u2026");
|
|
6927
6168
|
const fetchedRegistry = await fetchComponentRegistry(auth.token);
|
|
6928
6169
|
if (!fetchedRegistry.registry && fetchedRegistry.apiFailure) {
|
|
6929
6170
|
warn(`Component registry API: ${fetchedRegistry.apiFailure}`);
|
|
@@ -7674,17 +6915,17 @@ async function deployTokenRevokeCommand(tokenId) {
|
|
|
7674
6915
|
}
|
|
7675
6916
|
|
|
7676
6917
|
// src/commands/setup.ts
|
|
7677
|
-
import
|
|
7678
|
-
import
|
|
6918
|
+
import path25 from "path";
|
|
6919
|
+
import fs19 from "fs-extra";
|
|
7679
6920
|
import ora6 from "ora";
|
|
7680
6921
|
|
|
7681
6922
|
// src/commands/doctor.ts
|
|
7682
|
-
import
|
|
6923
|
+
import path24 from "path";
|
|
7683
6924
|
|
|
7684
6925
|
// src/services/health.ts
|
|
7685
6926
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
7686
|
-
import
|
|
7687
|
-
import
|
|
6927
|
+
import path23 from "path";
|
|
6928
|
+
import fs18 from "fs-extra";
|
|
7688
6929
|
function installDevTypeScript(cwd) {
|
|
7689
6930
|
const pm = detectPackageManager(cwd);
|
|
7690
6931
|
try {
|
|
@@ -7727,8 +6968,8 @@ function checkGeneratedSlotValidity(cwd = process.cwd()) {
|
|
|
7727
6968
|
};
|
|
7728
6969
|
}
|
|
7729
6970
|
function checkComponentConfigValidity(cwd = process.cwd(), options = {}) {
|
|
7730
|
-
const configPath =
|
|
7731
|
-
if (!
|
|
6971
|
+
const configPath = path23.join(cwd, COMPONENT_CONFIG_FILE);
|
|
6972
|
+
if (!fs18.existsSync(configPath)) {
|
|
7732
6973
|
return {
|
|
7733
6974
|
ok: false,
|
|
7734
6975
|
summary: "component.config.ts not found",
|
|
@@ -7736,8 +6977,8 @@ function checkComponentConfigValidity(cwd = process.cwd(), options = {}) {
|
|
|
7736
6977
|
};
|
|
7737
6978
|
}
|
|
7738
6979
|
const tsPkgDir = resolvePackageDir("typescript", cwd);
|
|
7739
|
-
const tscPath = tsPkgDir ?
|
|
7740
|
-
if (!
|
|
6980
|
+
const tscPath = tsPkgDir ? path23.join(tsPkgDir, "bin", "tsc") : path23.join(cwd, "node_modules", "typescript", "bin", "tsc");
|
|
6981
|
+
if (!fs18.existsSync(tscPath)) {
|
|
7741
6982
|
if (!options.autoFix) {
|
|
7742
6983
|
return {
|
|
7743
6984
|
ok: false,
|
|
@@ -7805,33 +7046,36 @@ ${stderr}`.trim() };
|
|
|
7805
7046
|
function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
|
|
7806
7047
|
const warnings = [];
|
|
7807
7048
|
const hints = [];
|
|
7808
|
-
const configPath =
|
|
7809
|
-
|
|
7810
|
-
|
|
7049
|
+
const configPath = path23.join(
|
|
7050
|
+
cwd,
|
|
7051
|
+
fs18.existsSync(path23.join(cwd, PROJECT_CONFIG_FILE)) || !fs18.existsSync(path23.join(cwd, "iui.config.ts")) ? PROJECT_CONFIG_FILE : "iui.config.ts"
|
|
7052
|
+
);
|
|
7053
|
+
if (fs18.existsSync(configPath)) {
|
|
7054
|
+
const configContent = fs18.readFileSync(configPath, "utf-8");
|
|
7811
7055
|
if (/packageSafelist\s*:\s*false/.test(configContent)) {
|
|
7812
7056
|
warnings.push(
|
|
7813
|
-
"Deprecated
|
|
7057
|
+
"Deprecated theme.config build.packageSafelist \u2014 remove it; Framework always merges IUI package compile contracts"
|
|
7814
7058
|
);
|
|
7815
7059
|
}
|
|
7816
7060
|
if (/includeShadeMatrix\s*:/.test(configContent)) {
|
|
7817
7061
|
warnings.push(
|
|
7818
|
-
"Deprecated compiler flags in
|
|
7062
|
+
"Deprecated compiler flags in theme.config build.* \u2014 remove them; compile policy is Framework-internal"
|
|
7819
7063
|
);
|
|
7820
7064
|
hints.push("Use theme + optional scan.dirs only. See Framework docs/01-compile-first-guide.md");
|
|
7821
7065
|
}
|
|
7822
7066
|
if (/scanPackages\s*:/.test(configContent) || /scan\.packages\s*:/.test(configContent)) {
|
|
7823
7067
|
warnings.push(
|
|
7824
|
-
"Deprecated scanPackages in
|
|
7068
|
+
"Deprecated scanPackages in theme.config \u2014 IUI packages are discovered from package.json dependencies"
|
|
7825
7069
|
);
|
|
7826
7070
|
}
|
|
7827
7071
|
}
|
|
7828
7072
|
if (projectHasViteTooling(cwd)) {
|
|
7829
7073
|
const viteCandidates = ["vite.config.ts", "vite.config.mjs", "vite.config.js"];
|
|
7830
|
-
const vitePath = viteCandidates.map((name) =>
|
|
7074
|
+
const vitePath = viteCandidates.map((name) => path23.join(cwd, name)).find((p) => fs18.existsSync(p));
|
|
7831
7075
|
if (!vitePath) {
|
|
7832
7076
|
warnings.push("Vite tooling detected but no vite.config.* found");
|
|
7833
7077
|
} else {
|
|
7834
|
-
const viteContent =
|
|
7078
|
+
const viteContent = fs18.readFileSync(vitePath, "utf-8");
|
|
7835
7079
|
if (!/inventiveUiVite\s*\(/.test(viteContent)) {
|
|
7836
7080
|
warnings.push("vite.config is missing inventiveUiVite() \u2014 compile-first CSS will not generate");
|
|
7837
7081
|
hints.push("Wire plugins: [...inventiveUiVite({ root: import.meta.dirname }), react()]");
|
|
@@ -7845,11 +7089,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
|
|
|
7845
7089
|
"webpack.config.mjs",
|
|
7846
7090
|
"webpack.config.ts"
|
|
7847
7091
|
];
|
|
7848
|
-
const webpackPath = webpackCandidates.map((name) =>
|
|
7092
|
+
const webpackPath = webpackCandidates.map((name) => path23.join(cwd, name)).find((p) => fs18.existsSync(p));
|
|
7849
7093
|
if (!webpackPath) {
|
|
7850
7094
|
warnings.push("Webpack tooling detected but no webpack.config.* found");
|
|
7851
7095
|
} else {
|
|
7852
|
-
const webpackContent =
|
|
7096
|
+
const webpackContent = fs18.readFileSync(webpackPath, "utf-8");
|
|
7853
7097
|
if (!/inventiveUiWebpack\s*\(/.test(webpackContent)) {
|
|
7854
7098
|
warnings.push("webpack.config is missing inventiveUiWebpack() \u2014 compile-first CSS will not generate");
|
|
7855
7099
|
hints.push('Wire plugins: [...inventiveUiWebpack()] from "@inventive-ui/framework/webpack"');
|
|
@@ -7859,11 +7103,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
|
|
|
7859
7103
|
}
|
|
7860
7104
|
if (projectHasNextTooling(cwd)) {
|
|
7861
7105
|
const nextCandidates = ["next.config.ts", "next.config.mjs", "next.config.js", "next.config.cjs"];
|
|
7862
|
-
const nextPath = nextCandidates.map((name) =>
|
|
7106
|
+
const nextPath = nextCandidates.map((name) => path23.join(cwd, name)).find((p) => fs18.existsSync(p));
|
|
7863
7107
|
if (!nextPath) {
|
|
7864
7108
|
warnings.push("Next.js detected but no next.config.* found");
|
|
7865
7109
|
} else {
|
|
7866
|
-
const nextContent =
|
|
7110
|
+
const nextContent = fs18.readFileSync(nextPath, "utf-8");
|
|
7867
7111
|
if (!/withIUI\s*\(/.test(nextContent)) {
|
|
7868
7112
|
warnings.push("next.config is missing withIUI() \u2014 compile-first CSS will not generate");
|
|
7869
7113
|
hints.push('Wrap config: export default withIUI({ ... }) from "@inventive-ui/framework/next"');
|
|
@@ -7876,18 +7120,18 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
|
|
|
7876
7120
|
"src/app/layout.jsx",
|
|
7877
7121
|
"app/providers.tsx",
|
|
7878
7122
|
"src/app/providers.tsx"
|
|
7879
|
-
].map((rel) =>
|
|
7880
|
-
const readableLayouts = layoutCandidates.filter((file) =>
|
|
7123
|
+
].map((rel) => path23.join(cwd, rel));
|
|
7124
|
+
const readableLayouts = layoutCandidates.filter((file) => fs18.existsSync(file));
|
|
7881
7125
|
const hasRegistry = readableLayouts.some((file) => {
|
|
7882
7126
|
try {
|
|
7883
|
-
return /\bIUIRegistry\b/.test(
|
|
7127
|
+
return /\bIUIRegistry\b/.test(fs18.readFileSync(file, "utf-8"));
|
|
7884
7128
|
} catch {
|
|
7885
7129
|
return false;
|
|
7886
7130
|
}
|
|
7887
7131
|
});
|
|
7888
7132
|
const hasBootstrapImport = readableLayouts.some((file) => {
|
|
7889
7133
|
try {
|
|
7890
|
-
const content =
|
|
7134
|
+
const content = fs18.readFileSync(file, "utf-8");
|
|
7891
7135
|
return /next\/bootstrap/.test(content) || /["']iui-bootstrap["']/.test(content) || /iui\/bootstrap/.test(content);
|
|
7892
7136
|
} catch {
|
|
7893
7137
|
return false;
|
|
@@ -7895,7 +7139,7 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
|
|
|
7895
7139
|
});
|
|
7896
7140
|
const hasProvider = readableLayouts.some((file) => {
|
|
7897
7141
|
try {
|
|
7898
|
-
return /\bIUIProvider\b/.test(
|
|
7142
|
+
return /\bIUIProvider\b/.test(fs18.readFileSync(file, "utf-8"));
|
|
7899
7143
|
} catch {
|
|
7900
7144
|
return false;
|
|
7901
7145
|
}
|
|
@@ -7926,14 +7170,14 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
|
|
|
7926
7170
|
"src/app/providers.tsx",
|
|
7927
7171
|
"app/layout.tsx",
|
|
7928
7172
|
"src/app/layout.tsx"
|
|
7929
|
-
].map((rel) =>
|
|
7173
|
+
].map((rel) => path23.join(cwd, rel));
|
|
7930
7174
|
for (const file of entryCandidates) {
|
|
7931
|
-
if (!
|
|
7175
|
+
if (!fs18.existsSync(file)) continue;
|
|
7932
7176
|
try {
|
|
7933
|
-
const content =
|
|
7177
|
+
const content = fs18.readFileSync(file, "utf-8");
|
|
7934
7178
|
if (/from\s+['"][^'"]*\.generated['"]/.test(content) || /import\s+['"][^'"]*\.generated['"]/.test(content)) {
|
|
7935
7179
|
warnings.push(
|
|
7936
|
-
`Do not import .generated style-map files into the browser (${
|
|
7180
|
+
`Do not import .generated style-map files into the browser (${path23.relative(cwd, file)})`
|
|
7937
7181
|
);
|
|
7938
7182
|
hints.push(
|
|
7939
7183
|
"Keep style maps on the scanner path (default src + .iui/generated, or override build.scanDirs) \u2014 see Framework compile-first docs"
|
|
@@ -7953,9 +7197,9 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
|
|
|
7953
7197
|
hints.push(
|
|
7954
7198
|
"Compile-first: avoid dynamic utility templates like `p-${n}` \u2014 use static strings, style maps, or safelist (ESLint: customPlugin/no-dynamic-utility-class)"
|
|
7955
7199
|
);
|
|
7956
|
-
const giPath =
|
|
7957
|
-
if (
|
|
7958
|
-
const gi =
|
|
7200
|
+
const giPath = path23.join(cwd, ".gitignore");
|
|
7201
|
+
if (fs18.existsSync(giPath)) {
|
|
7202
|
+
const gi = fs18.readFileSync(giPath, "utf-8");
|
|
7959
7203
|
if (!gi.includes(".iui/cache/")) {
|
|
7960
7204
|
warnings.push(".gitignore missing IUI cache directory (.iui/cache/)");
|
|
7961
7205
|
hints.push("Run iui init or append .iui/cache/ from the IUI docs");
|
|
@@ -7966,11 +7210,11 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
|
|
|
7966
7210
|
function checkMetadataPortability(cwd = process.cwd()) {
|
|
7967
7211
|
const warnings = [];
|
|
7968
7212
|
const hints = [];
|
|
7969
|
-
const iuiPath =
|
|
7970
|
-
const projectPath =
|
|
7971
|
-
if (
|
|
7213
|
+
const iuiPath = path23.join(cwd, IUI_DIR);
|
|
7214
|
+
const projectPath = path23.join(iuiPath, "project.json");
|
|
7215
|
+
if (fs18.existsSync(projectPath)) {
|
|
7972
7216
|
try {
|
|
7973
|
-
const meta =
|
|
7217
|
+
const meta = fs18.readJsonSync(projectPath);
|
|
7974
7218
|
const repoUrl = meta.repoUrl ?? "";
|
|
7975
7219
|
if (/^[A-Za-z]:[\\/]/.test(repoUrl) || repoUrl.startsWith("/") && !repoUrl.startsWith("//") || repoUrl.startsWith("file:")) {
|
|
7976
7220
|
warnings.push("project.json repoUrl is a local filesystem path \u2014 use a git remote URL");
|
|
@@ -7979,15 +7223,15 @@ function checkMetadataPortability(cwd = process.cwd()) {
|
|
|
7979
7223
|
} catch {
|
|
7980
7224
|
}
|
|
7981
7225
|
}
|
|
7982
|
-
const workspacePath =
|
|
7983
|
-
if (
|
|
7226
|
+
const workspacePath = path23.join(iuiPath, "workspace.json");
|
|
7227
|
+
if (fs18.existsSync(workspacePath)) {
|
|
7984
7228
|
try {
|
|
7985
|
-
const ws =
|
|
7229
|
+
const ws = fs18.readJsonSync(workspacePath);
|
|
7986
7230
|
if (ws.iuiRoot) {
|
|
7987
7231
|
warnings.push("workspace.json contains deprecated iuiRoot \u2014 remove it (root is implicit)");
|
|
7988
7232
|
}
|
|
7989
7233
|
for (const pkg of ws.packages ?? []) {
|
|
7990
|
-
if (/^[A-Za-z]:[\\/]/.test(pkg) ||
|
|
7234
|
+
if (/^[A-Za-z]:[\\/]/.test(pkg) || path23.isAbsolute(pkg)) {
|
|
7991
7235
|
warnings.push(`workspace.json packages entry is absolute: ${pkg}`);
|
|
7992
7236
|
hints.push("packages should be relative paths from the IUI root");
|
|
7993
7237
|
}
|
|
@@ -7996,9 +7240,9 @@ function checkMetadataPortability(cwd = process.cwd()) {
|
|
|
7996
7240
|
}
|
|
7997
7241
|
}
|
|
7998
7242
|
const scanCachePath = iuiCacheFile(cwd, "scan");
|
|
7999
|
-
if (
|
|
7243
|
+
if (fs18.existsSync(scanCachePath)) {
|
|
8000
7244
|
try {
|
|
8001
|
-
const cache =
|
|
7245
|
+
const cache = fs18.readJsonSync(scanCachePath);
|
|
8002
7246
|
const absoluteKeys = Object.keys(cache.files ?? {}).filter(
|
|
8003
7247
|
(key) => /^[A-Za-z]:[\\/]/.test(key) || key.startsWith("/") && !key.startsWith("//")
|
|
8004
7248
|
);
|
|
@@ -8015,38 +7259,70 @@ function checkMetadataPortability(cwd = process.cwd()) {
|
|
|
8015
7259
|
}
|
|
8016
7260
|
return { warnings, hints };
|
|
8017
7261
|
}
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
7262
|
+
var ICON_LIBRARY_PACKAGES = {
|
|
7263
|
+
"material-symbols": "material-symbols",
|
|
7264
|
+
materialSymbols: "material-symbols",
|
|
7265
|
+
"material-icons": "icons-material",
|
|
7266
|
+
lucide: "icons-lucide",
|
|
7267
|
+
phosphor: "icons-phosphor"
|
|
7268
|
+
};
|
|
7269
|
+
function checkAssetPipeline(cwd = process.cwd()) {
|
|
7270
|
+
const assetsPath = path23.join(cwd, ASSETS_CONFIG_FILE);
|
|
7271
|
+
if (!fs18.existsSync(assetsPath)) {
|
|
7272
|
+
return { ok: true, summary: "Asset check skipped (no assets.config.json)" };
|
|
8022
7273
|
}
|
|
8023
7274
|
let assets2;
|
|
8024
7275
|
try {
|
|
8025
|
-
assets2 =
|
|
7276
|
+
assets2 = fs18.readJsonSync(assetsPath);
|
|
8026
7277
|
} catch {
|
|
8027
7278
|
return { ok: false, summary: "assets.config.json is not valid JSON" };
|
|
8028
7279
|
}
|
|
8029
|
-
|
|
8030
|
-
|
|
7280
|
+
const packagesDir = path23.join(cwd, "node_modules", "@inventive-ui");
|
|
7281
|
+
const frameworkPkg = path23.join(packagesDir, "framework", "package.json");
|
|
7282
|
+
if (fs18.existsSync(frameworkPkg)) {
|
|
7283
|
+
const framework = fs18.readJsonSync(frameworkPkg);
|
|
7284
|
+
if (!framework.exports?.["./assets"]) {
|
|
7285
|
+
return {
|
|
7286
|
+
ok: false,
|
|
7287
|
+
summary: "Installed @inventive-ui/framework has no asset pipeline",
|
|
7288
|
+
details: "Update it: iui update"
|
|
7289
|
+
};
|
|
7290
|
+
}
|
|
7291
|
+
}
|
|
7292
|
+
const library = assets2.icon?.library;
|
|
7293
|
+
const pkg = library ? ICON_LIBRARY_PACKAGES[library] : void 0;
|
|
7294
|
+
if (!pkg) return { ok: true, summary: "Asset config valid" };
|
|
7295
|
+
const iconsDir = path23.join(packagesDir, pkg, "dist", "icons");
|
|
7296
|
+
if (!fs18.existsSync(iconsDir)) {
|
|
7297
|
+
return {
|
|
7298
|
+
ok: false,
|
|
7299
|
+
summary: `Icon library "${library}" is configured but @inventive-ui/${pkg} is not installed`,
|
|
7300
|
+
details: `Install it: iui install assets @inventive-ui/${pkg}`
|
|
7301
|
+
};
|
|
8031
7302
|
}
|
|
8032
|
-
const
|
|
8033
|
-
|
|
7303
|
+
const glyphs = [
|
|
7304
|
+
...Object.entries(assets2.icon?.globalIcons ?? {}).map(([alias, glyph]) => [`@${alias}`, glyph]),
|
|
7305
|
+
["placeholder", assets2.icon?.placeholder?.name],
|
|
7306
|
+
["fallback", assets2.icon?.fallback]
|
|
7307
|
+
].filter((entry) => typeof entry[1] === "string" && entry[1].length > 0);
|
|
7308
|
+
const missing = glyphs.filter(([, glyph]) => !fs18.existsSync(path23.join(iconsDir, `${glyph}.js`)));
|
|
7309
|
+
if (missing.length > 0) {
|
|
8034
7310
|
return {
|
|
8035
7311
|
ok: false,
|
|
8036
|
-
summary:
|
|
8037
|
-
details:
|
|
7312
|
+
summary: `${missing.length} icon alias${missing.length === 1 ? "" : "es"} point at glyphs "${library}" does not have`,
|
|
7313
|
+
details: missing.slice(0, 8).map(([name, glyph]) => `${name} \u2192 ${glyph}`).join(", ")
|
|
8038
7314
|
};
|
|
8039
7315
|
}
|
|
8040
|
-
return { ok: true, summary:
|
|
7316
|
+
return { ok: true, summary: `Asset config valid (${glyphs.length} icon names checked in ${library})` };
|
|
8041
7317
|
}
|
|
8042
7318
|
function checkBootstrapSync(cwd = process.cwd(), options = {}) {
|
|
8043
7319
|
const iuiRoot2 = resolveIuiProjectRoot(cwd);
|
|
8044
7320
|
const generatedPath = bootstrapGeneratedPath(iuiRoot2);
|
|
8045
|
-
const bridgePath =
|
|
8046
|
-
if (!
|
|
7321
|
+
const bridgePath = path23.join(cwd, "src", "iui", "bootstrap.ts");
|
|
7322
|
+
if (!fs18.existsSync(generatedPath)) {
|
|
8047
7323
|
if (options.autoFix) {
|
|
8048
7324
|
writeProjectBootstrapArtifacts(cwd, iuiRoot2);
|
|
8049
|
-
if (
|
|
7325
|
+
if (fs18.existsSync(generatedPath)) {
|
|
8050
7326
|
return { ok: true, summary: "Generated bootstrap artifacts repaired" };
|
|
8051
7327
|
}
|
|
8052
7328
|
}
|
|
@@ -8056,10 +7332,10 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
|
|
|
8056
7332
|
details: "Expected .iui/generated/bootstrap.generated.tsx \u2014 run iui doctor --fix."
|
|
8057
7333
|
};
|
|
8058
7334
|
}
|
|
8059
|
-
if (!
|
|
7335
|
+
if (!fs18.existsSync(bridgePath)) {
|
|
8060
7336
|
if (options.autoFix) {
|
|
8061
7337
|
writeProjectBootstrapArtifacts(cwd, iuiRoot2);
|
|
8062
|
-
if (
|
|
7338
|
+
if (fs18.existsSync(bridgePath)) {
|
|
8063
7339
|
return { ok: true, summary: "Bootstrap bridge repaired" };
|
|
8064
7340
|
}
|
|
8065
7341
|
}
|
|
@@ -8072,8 +7348,8 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
|
|
|
8072
7348
|
const configs = resolveProjectConfigPaths(iuiRoot2);
|
|
8073
7349
|
const missing = [];
|
|
8074
7350
|
for (const [key, rel] of Object.entries(configs)) {
|
|
8075
|
-
const abs =
|
|
8076
|
-
if (!
|
|
7351
|
+
const abs = path23.resolve(iuiRoot2, rel.replace(/^\.\//, ""));
|
|
7352
|
+
if (!fs18.existsSync(abs)) missing.push(`${key}: ${rel}`);
|
|
8077
7353
|
}
|
|
8078
7354
|
if (missing.length > 0) {
|
|
8079
7355
|
return {
|
|
@@ -8083,7 +7359,7 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
|
|
|
8083
7359
|
};
|
|
8084
7360
|
}
|
|
8085
7361
|
const expected = expectedBootstrapImportPaths(iuiRoot2);
|
|
8086
|
-
const generated =
|
|
7362
|
+
const generated = fs18.readFileSync(generatedPath, "utf8");
|
|
8087
7363
|
const stale = [];
|
|
8088
7364
|
for (const [key, importPath] of Object.entries(expected)) {
|
|
8089
7365
|
if (!generated.includes(`"${importPath}"`)) {
|
|
@@ -8093,7 +7369,7 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
|
|
|
8093
7369
|
if (stale.length > 0) {
|
|
8094
7370
|
if (options.autoFix) {
|
|
8095
7371
|
writeProjectBootstrapArtifacts(cwd, iuiRoot2);
|
|
8096
|
-
const refreshed =
|
|
7372
|
+
const refreshed = fs18.readFileSync(bootstrapGeneratedPath(iuiRoot2), "utf8");
|
|
8097
7373
|
const stillStale = Object.entries(expected).filter(
|
|
8098
7374
|
([, importPath]) => !refreshed.includes(`"${importPath}"`)
|
|
8099
7375
|
);
|
|
@@ -8111,7 +7387,7 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
|
|
|
8111
7387
|
}
|
|
8112
7388
|
|
|
8113
7389
|
// src/commands/doctor.ts
|
|
8114
|
-
function runConfigTierDiagnostics(targetCwd, opts, counters, options = {}) {
|
|
7390
|
+
async function runConfigTierDiagnostics(targetCwd, opts, counters, options = {}) {
|
|
8115
7391
|
const pass = (label) => {
|
|
8116
7392
|
checkPass(label);
|
|
8117
7393
|
counters.passed++;
|
|
@@ -8129,10 +7405,13 @@ function runConfigTierDiagnostics(targetCwd, opts, counters, options = {}) {
|
|
|
8129
7405
|
if (opts?.fix === true && includePackageJson) {
|
|
8130
7406
|
ensureProjectConfig(targetCwd);
|
|
8131
7407
|
ensureGitignoreHasIuiBuildCache(targetCwd);
|
|
8132
|
-
|
|
7408
|
+
const vite = projectHasViteTooling(targetCwd);
|
|
7409
|
+
ensureTsConfigForIui(vite ? "vite" : "react", targetCwd);
|
|
7410
|
+
if (vite) {
|
|
8133
7411
|
ensureInventiveUiViteConfig(targetCwd);
|
|
8134
7412
|
}
|
|
8135
7413
|
ensureComponentConfig(readComponentPackageManifest(targetCwd), targetCwd);
|
|
7414
|
+
await ensureSlotRegistry({ cwd: targetCwd, quiet: true, mode: "repair" });
|
|
8136
7415
|
}
|
|
8137
7416
|
if (includeSlotCheck && isInsideProject(targetCwd) && getInstalledPackageVersion(COMPONENTS_PACKAGE, targetCwd)) {
|
|
8138
7417
|
const slotValidity = checkGeneratedSlotValidity(targetCwd);
|
|
@@ -8216,12 +7495,12 @@ function runConfigTierDiagnostics(targetCwd, opts, counters, options = {}) {
|
|
|
8216
7495
|
hint(hint2);
|
|
8217
7496
|
}
|
|
8218
7497
|
}
|
|
8219
|
-
const
|
|
8220
|
-
if (
|
|
8221
|
-
pass(
|
|
7498
|
+
const assetPipeline = checkAssetPipeline(targetCwd);
|
|
7499
|
+
if (assetPipeline.ok) {
|
|
7500
|
+
pass(assetPipeline.summary);
|
|
8222
7501
|
} else {
|
|
8223
|
-
warn(
|
|
8224
|
-
if (
|
|
7502
|
+
warn(assetPipeline.summary);
|
|
7503
|
+
if (assetPipeline.details) hint(assetPipeline.details);
|
|
8225
7504
|
}
|
|
8226
7505
|
}
|
|
8227
7506
|
async function runPackageDiagnostics(targetCwd, opts, counters) {
|
|
@@ -8234,7 +7513,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
|
|
|
8234
7513
|
counters.failed++;
|
|
8235
7514
|
};
|
|
8236
7515
|
if (opts?.configOnly) {
|
|
8237
|
-
runConfigTierDiagnostics(targetCwd, opts, counters, {
|
|
7516
|
+
await runConfigTierDiagnostics(targetCwd, opts, counters, {
|
|
8238
7517
|
includePackageJson: true,
|
|
8239
7518
|
includeSlotCheck: true
|
|
8240
7519
|
});
|
|
@@ -8244,10 +7523,13 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
|
|
|
8244
7523
|
else fail2("package.json missing");
|
|
8245
7524
|
if (opts?.fix === true) {
|
|
8246
7525
|
ensureProjectConfig(targetCwd);
|
|
8247
|
-
|
|
7526
|
+
const vite2 = projectHasViteTooling(targetCwd);
|
|
7527
|
+
ensureTsConfigForIui(vite2 ? "vite" : "react", targetCwd);
|
|
7528
|
+
if (vite2) {
|
|
8248
7529
|
ensureInventiveUiViteConfig(targetCwd);
|
|
8249
7530
|
}
|
|
8250
7531
|
ensureComponentConfig(readComponentPackageManifest(targetCwd), targetCwd);
|
|
7532
|
+
await ensureSlotRegistry({ cwd: targetCwd, quiet: true, mode: "repair" });
|
|
8251
7533
|
}
|
|
8252
7534
|
if (isInsideProject(targetCwd)) {
|
|
8253
7535
|
pass("Inventive UI project initialized");
|
|
@@ -8366,7 +7648,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
|
|
|
8366
7648
|
hint("Fix: run iui doctor --fix to regenerate bootstrap artifacts");
|
|
8367
7649
|
}
|
|
8368
7650
|
}
|
|
8369
|
-
runConfigTierDiagnostics(targetCwd, opts, counters, {
|
|
7651
|
+
await runConfigTierDiagnostics(targetCwd, opts, counters, {
|
|
8370
7652
|
includePackageJson: false,
|
|
8371
7653
|
includeSlotCheck: false
|
|
8372
7654
|
});
|
|
@@ -8374,7 +7656,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
|
|
|
8374
7656
|
async function doctorCommand(opts) {
|
|
8375
7657
|
try {
|
|
8376
7658
|
const invocationCwd = process.cwd();
|
|
8377
|
-
const targets = opts?.cwd ? [
|
|
7659
|
+
const targets = opts?.cwd ? [path24.resolve(opts.cwd)] : resolveSetupDoctorTargets(invocationCwd);
|
|
8378
7660
|
const installRoot = resolveDependencyInstallRoot(invocationCwd);
|
|
8379
7661
|
const multiPackage = targets.length > 1;
|
|
8380
7662
|
heading("Diagnostics");
|
|
@@ -8417,7 +7699,7 @@ async function doctorCommand(opts) {
|
|
|
8417
7699
|
for (const targetCwd of targets) {
|
|
8418
7700
|
if (multiPackage) {
|
|
8419
7701
|
newline();
|
|
8420
|
-
const label =
|
|
7702
|
+
const label = path24.relative(installRoot, targetCwd) || path24.basename(targetCwd);
|
|
8421
7703
|
kv("Package", label);
|
|
8422
7704
|
}
|
|
8423
7705
|
await runPackageDiagnostics(targetCwd, opts, counters);
|
|
@@ -8445,9 +7727,9 @@ async function doctorCommand(opts) {
|
|
|
8445
7727
|
|
|
8446
7728
|
// src/commands/setup.ts
|
|
8447
7729
|
function detectDevScript(cwd) {
|
|
8448
|
-
const pkgPath =
|
|
7730
|
+
const pkgPath = path25.join(cwd, "package.json");
|
|
8449
7731
|
try {
|
|
8450
|
-
const pkg =
|
|
7732
|
+
const pkg = fs19.readJsonSync(pkgPath);
|
|
8451
7733
|
if (pkg.scripts?.dev) return "npm run dev";
|
|
8452
7734
|
if (pkg.scripts?.start) return "npm run start";
|
|
8453
7735
|
} catch {
|
|
@@ -8456,8 +7738,8 @@ function detectDevScript(cwd) {
|
|
|
8456
7738
|
return null;
|
|
8457
7739
|
}
|
|
8458
7740
|
function relativePackageLabel(installRoot, packageDir) {
|
|
8459
|
-
const rel =
|
|
8460
|
-
return rel && rel !== "." ? rel :
|
|
7741
|
+
const rel = path25.relative(installRoot, packageDir);
|
|
7742
|
+
return rel && rel !== "." ? rel : path25.basename(packageDir);
|
|
8461
7743
|
}
|
|
8462
7744
|
async function setupCommand(opts) {
|
|
8463
7745
|
try {
|
|
@@ -8466,7 +7748,7 @@ async function setupCommand(opts) {
|
|
|
8466
7748
|
const installRoot = resolveDependencyInstallRoot(cwd);
|
|
8467
7749
|
const workspaceRoot = findWorkspaceRoot(cwd);
|
|
8468
7750
|
const inMonorepo = workspaceRoot !== null;
|
|
8469
|
-
const installFromChild = inMonorepo &&
|
|
7751
|
+
const installFromChild = inMonorepo && path25.resolve(installRoot) !== path25.resolve(cwd);
|
|
8470
7752
|
if (!hasPackageJson(cwd) && !hasPackageJson(installRoot)) {
|
|
8471
7753
|
throw new CLIError(
|
|
8472
7754
|
"No package.json found in the current directory.",
|
|
@@ -8500,7 +7782,7 @@ async function setupCommand(opts) {
|
|
|
8500
7782
|
for (const w of warnings) warn(w);
|
|
8501
7783
|
kv("Package manager", `${pm} (${source})`);
|
|
8502
7784
|
if (installFromChild) {
|
|
8503
|
-
const rel =
|
|
7785
|
+
const rel = path25.relative(cwd, installRoot) || ".";
|
|
8504
7786
|
kv("Install directory", rel === ".." || rel.includes("..") ? installRoot : rel);
|
|
8505
7787
|
}
|
|
8506
7788
|
const installCmd2 = syncInstallCommand(pm);
|
|
@@ -8514,7 +7796,7 @@ async function setupCommand(opts) {
|
|
|
8514
7796
|
} catch (err) {
|
|
8515
7797
|
installSpinner.fail("Dependency install failed");
|
|
8516
7798
|
const detail = formatExecSyncError(err);
|
|
8517
|
-
const manual =
|
|
7799
|
+
const manual = path25.resolve(installRoot) === path25.resolve(cwd) ? installCmd2 : `cd ${JSON.stringify(installRoot)} && ${installCmd2}`;
|
|
8518
7800
|
throw new CLIError(
|
|
8519
7801
|
detail ? `Could not install project dependencies.
|
|
8520
7802
|
${detail}` : "Could not install project dependencies.",
|
|
@@ -8672,7 +7954,7 @@ async function updateCommand(opts = {}) {
|
|
|
8672
7954
|
const auth = await ensureAuthSession();
|
|
8673
7955
|
await ensureLicenseSession();
|
|
8674
7956
|
const inProject = isInsideProject();
|
|
8675
|
-
const currentCliVersion = true ? "0.0.
|
|
7957
|
+
const currentCliVersion = true ? "0.0.11" : "unknown";
|
|
8676
7958
|
const latestCliVersion = await fetchLatestCliVersion(auth.token);
|
|
8677
7959
|
const cliUpdateAvailable = latestCliVersion !== null && isVersionGreater(latestCliVersion, currentCliVersion);
|
|
8678
7960
|
if (latestCliVersion && cliUpdateAvailable) {
|
|
@@ -8954,7 +8236,7 @@ var AUTH_EXEMPT_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
8954
8236
|
"doctor",
|
|
8955
8237
|
"list"
|
|
8956
8238
|
]);
|
|
8957
|
-
program.name("iui").description("The official CLI for the Inventive UI Design System").version(true ? "0.0.
|
|
8239
|
+
program.name("iui").description("The official CLI for the Inventive UI Design System").version(true ? "0.0.11" : "1.0.0").option("-C, --cwd <dir>", "Run as if started in the given directory").option("-q, --quiet", "Minimal output (also respects IUI_QUIET=1)").option("--no-color", "Disable ANSI colors");
|
|
8958
8240
|
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));
|
|
8959
8241
|
program.command("logout").description("Remove stored credentials").action(logoutCommand);
|
|
8960
8242
|
program.command("whoami").description("Show authenticated identity and license details").action(whoamiCommand);
|
|
@@ -9037,7 +8319,7 @@ program.command("update").description("Check for and apply framework, component,
|
|
|
9037
8319
|
var assets = program.command("assets").description("Manage asset packages (icons, illustrations, logos, etc.)");
|
|
9038
8320
|
assets.command("remove <package>").description("Remove an installed asset package").action((pkg) => assetsRemoveCommand(pkg));
|
|
9039
8321
|
assets.command("list").description("Show all available and installed asset packages").action(assetsListCommand);
|
|
9040
|
-
program.command("doctor").description("Run project health diagnostics (read-only by default)").option("--fix", "Apply safe config patches (
|
|
8322
|
+
program.command("doctor").description("Run project health diagnostics (read-only by default)").option("--fix", "Apply safe config patches (theme.config, vite.config, component.config)").option("--config-only", "Validate project config tiers only (no auth/registry)").action((opts) => doctorCommand(opts));
|
|
9041
8323
|
if (shouldShowBanner()) {
|
|
9042
8324
|
printBanner();
|
|
9043
8325
|
}
|
|
@@ -9052,7 +8334,7 @@ program.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
9052
8334
|
const root = topLevelCommandName(actionCommand);
|
|
9053
8335
|
const globalOpts = program.opts();
|
|
9054
8336
|
if (globalOpts.cwd) {
|
|
9055
|
-
process.chdir(
|
|
8337
|
+
process.chdir(path26.resolve(globalOpts.cwd));
|
|
9056
8338
|
}
|
|
9057
8339
|
if (isInsideProject()) {
|
|
9058
8340
|
try {
|