inventive-ui 0.0.8 → 0.0.10
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 +1 -1
- package/dist/index.js +159 -619
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/assets.config.defaults.json +5 -4
package/dist/index.js
CHANGED
|
@@ -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.10" : "1.0.0";
|
|
194
194
|
} catch {
|
|
195
195
|
return "1.0.0";
|
|
196
196
|
}
|
|
@@ -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";
|
|
@@ -1955,452 +1919,54 @@ function patchViteConfigContent(source) {
|
|
|
1955
1919
|
}
|
|
1956
1920
|
|
|
1957
1921
|
// src/utils/config-patch/iui-config.ts
|
|
1958
|
-
var
|
|
1959
|
-
* Compile-first CSS \u2014 scanned at build time by the Vite/Webpack/Next plugin.
|
|
1960
|
-
* Do not import style-map ".generated" files into the browser graph.
|
|
1961
|
-
* scanDirs / scanPackages default in Framework \u2014 override only when needed.
|
|
1962
|
-
* See Framework docs/01-compile-first-guide.md for all build options.
|
|
1963
|
-
*/
|
|
1964
|
-
build: {
|
|
1965
|
-
safelist: [],
|
|
1966
|
-
includeShadeMatrix: false,
|
|
1967
|
-
includeThemePresets: true,
|
|
1968
|
-
includeThemeGrayScale: true,
|
|
1969
|
-
resolvePalettePatterns: true,
|
|
1970
|
-
includeArbitraryScan: true,
|
|
1971
|
-
writeFiles: false,
|
|
1972
|
-
minify: true,
|
|
1973
|
-
useAst: true,
|
|
1974
|
-
},
|
|
1975
|
-
`;
|
|
1976
|
-
var BUILD_DEFAULT_ENTRIES = [
|
|
1977
|
-
["safelist", "[]"],
|
|
1978
|
-
["includeShadeMatrix", "false"],
|
|
1979
|
-
["includeThemePresets", "true"],
|
|
1980
|
-
["includeThemeGrayScale", "true"],
|
|
1981
|
-
["resolvePalettePatterns", "true"],
|
|
1982
|
-
["includeArbitraryScan", "true"],
|
|
1983
|
-
["writeFiles", "false"],
|
|
1984
|
-
["minify", "true"],
|
|
1985
|
-
["useAst", "true"]
|
|
1986
|
-
];
|
|
1922
|
+
var DEPRECATED_BUILD_FLAG = /\b(includeShadeMatrix|includeThemePresets|includeThemeGrayScale|resolvePalettePatterns|includeArbitraryScan|packageSafelist|useAst|writeFiles)\s*:/;
|
|
1987
1923
|
function patchProjectConfigBuildBlock(content) {
|
|
1988
|
-
if (
|
|
1989
|
-
const updated = content.replace(
|
|
1990
|
-
/(\n)(};)\s*\n(\s*export default config;)/,
|
|
1991
|
-
`$1${BUILD_BLOCK}$1$2
|
|
1992
|
-
$3`
|
|
1993
|
-
);
|
|
1994
|
-
if (updated === content) return { content, changed: false };
|
|
1995
|
-
return { content: updated, changed: true };
|
|
1996
|
-
}
|
|
1997
|
-
let next = content;
|
|
1998
|
-
let changed = false;
|
|
1999
|
-
if (!/\bbuild\s*:\s*\{/.test(next)) {
|
|
1924
|
+
if (DEPRECATED_BUILD_FLAG.test(content)) {
|
|
2000
1925
|
return { content, changed: false };
|
|
2001
1926
|
}
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
const replaced = next.replace(/(\bbuild\s*:\s*\{\n)/, `$1 ${key}: ${value},
|
|
2005
|
-
`);
|
|
2006
|
-
if (replaced !== next) {
|
|
2007
|
-
next = replaced;
|
|
2008
|
-
changed = true;
|
|
2009
|
-
}
|
|
1927
|
+
if (/\bscan\s*:\s*\{/.test(content)) {
|
|
1928
|
+
return { content, changed: false };
|
|
2010
1929
|
}
|
|
2011
|
-
return { content
|
|
1930
|
+
return { content, changed: false };
|
|
2012
1931
|
}
|
|
2013
1932
|
|
|
2014
1933
|
// src/utils/config-patch/component-config.ts
|
|
2015
1934
|
import ts2 from "typescript";
|
|
2016
1935
|
|
|
2017
|
-
// src/utils/
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
const packageRoot = resolvePackageDir("@inventive-ui/components", cwd);
|
|
2029
|
-
if (!packageRoot) return null;
|
|
2030
|
-
const pkgPath = path7.join(packageRoot, "package.json");
|
|
2031
|
-
if (!fs6.existsSync(pkgPath)) return null;
|
|
2032
|
-
try {
|
|
2033
|
-
const pkg = fs6.readJsonSync(pkgPath);
|
|
2034
|
-
const exportsField = toRecord(pkg.exports) ?? {};
|
|
2035
|
-
const rootExport = toRecord(exportsField["."]);
|
|
2036
|
-
const rootTypes = resolveTypesPathFromExportEntry(rootExport) ?? (typeof pkg.types === "string" ? pkg.types : null);
|
|
2037
|
-
return {
|
|
2038
|
-
packageRoot,
|
|
2039
|
-
exportsField,
|
|
2040
|
-
rootTypesPath: rootTypes ? path7.join(packageRoot, rootTypes) : null
|
|
2041
|
-
};
|
|
2042
|
-
} catch {
|
|
2043
|
-
return null;
|
|
2044
|
-
}
|
|
2045
|
-
}
|
|
2046
|
-
function resolveTypesPathFromExportEntry(entry) {
|
|
2047
|
-
if (!entry) return null;
|
|
2048
|
-
if (typeof entry === "string") return null;
|
|
2049
|
-
const obj = toRecord(entry);
|
|
2050
|
-
if (!obj) return null;
|
|
2051
|
-
if (typeof obj.types === "string") return obj.types;
|
|
2052
|
-
for (const key of ["import", "require", "default", "node", "browser"]) {
|
|
2053
|
-
const nested = toRecord(obj[key]);
|
|
2054
|
-
if (!nested) continue;
|
|
2055
|
-
if (typeof nested.types === "string") return nested.types;
|
|
2056
|
-
}
|
|
2057
|
-
return null;
|
|
2058
|
-
}
|
|
2059
|
-
function parseNamedExportClause(clause, parsed) {
|
|
2060
|
-
const parts = clause.split(",").map((p) => p.trim()).filter(Boolean);
|
|
2061
|
-
for (const rawPart of parts) {
|
|
2062
|
-
let part = rawPart;
|
|
2063
|
-
let isTypeOnly = false;
|
|
2064
|
-
if (part.startsWith("type ")) {
|
|
2065
|
-
isTypeOnly = true;
|
|
2066
|
-
part = part.slice("type ".length).trim();
|
|
2067
|
-
}
|
|
2068
|
-
const asMatch = part.match(/^([A-Za-z_][A-Za-z0-9_]*)\s+as\s+([A-Za-z_][A-Za-z0-9_]*)$/);
|
|
2069
|
-
const symbol = asMatch ? asMatch[2] : part;
|
|
2070
|
-
if (!symbol) continue;
|
|
2071
|
-
if (isTypeOnly) parsed.typeExports.add(symbol);
|
|
2072
|
-
else parsed.valueExports.add(symbol);
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
|
-
function mergeParsedExports(target, source) {
|
|
2076
|
-
for (const sym of source.valueExports) target.valueExports.add(sym);
|
|
2077
|
-
for (const sym of source.typeExports) target.typeExports.add(sym);
|
|
2078
|
-
}
|
|
2079
|
-
function resolveRelativeTypesPath(fromFile, rel) {
|
|
2080
|
-
const base = path7.dirname(fromFile);
|
|
2081
|
-
const noExt = path7.join(base, rel);
|
|
2082
|
-
const candidates = [`${noExt}.d.ts`, path7.join(noExt, "index.d.ts")];
|
|
2083
|
-
for (const candidate of candidates) {
|
|
2084
|
-
if (fs6.existsSync(candidate)) return candidate;
|
|
2085
|
-
}
|
|
2086
|
-
return null;
|
|
2087
|
-
}
|
|
2088
|
-
function parseTypeExports(typesFilePath, visited = /* @__PURE__ */ new Set()) {
|
|
2089
|
-
const parsed = {
|
|
2090
|
-
valueExports: /* @__PURE__ */ new Set(),
|
|
2091
|
-
typeExports: /* @__PURE__ */ new Set()
|
|
2092
|
-
};
|
|
2093
|
-
const abs = path7.resolve(typesFilePath);
|
|
2094
|
-
if (visited.has(abs)) return parsed;
|
|
2095
|
-
visited.add(abs);
|
|
2096
|
-
if (!fs6.existsSync(abs)) return parsed;
|
|
2097
|
-
let text = "";
|
|
2098
|
-
try {
|
|
2099
|
-
text = fs6.readFileSync(abs, "utf-8");
|
|
2100
|
-
} catch {
|
|
2101
|
-
return parsed;
|
|
2102
|
-
}
|
|
2103
|
-
applyTypeExportPatterns(text, parsed);
|
|
2104
|
-
const reexportFrom = text.matchAll(
|
|
2105
|
-
/export\s+(?:type\s+)?(?:\{[^}]*\}|\*)\s+from\s+["'](\.[^"']+)["']/g
|
|
2106
|
-
);
|
|
2107
|
-
for (const m of reexportFrom) {
|
|
2108
|
-
const refPath = resolveRelativeTypesPath(abs, m[1]);
|
|
2109
|
-
if (refPath) mergeParsedExports(parsed, parseTypeExports(refPath, visited));
|
|
2110
|
-
}
|
|
2111
|
-
return parsed;
|
|
2112
|
-
}
|
|
2113
|
-
function parseTypeExportsLocal(typesFilePath) {
|
|
2114
|
-
const parsed = {
|
|
2115
|
-
valueExports: /* @__PURE__ */ new Set(),
|
|
2116
|
-
typeExports: /* @__PURE__ */ new Set()
|
|
2117
|
-
};
|
|
2118
|
-
const abs = path7.resolve(typesFilePath);
|
|
2119
|
-
if (!fs6.existsSync(abs)) return parsed;
|
|
2120
|
-
let text = "";
|
|
2121
|
-
try {
|
|
2122
|
-
text = fs6.readFileSync(abs, "utf-8");
|
|
2123
|
-
} catch {
|
|
2124
|
-
return parsed;
|
|
2125
|
-
}
|
|
2126
|
-
applyTypeExportPatterns(text, parsed);
|
|
2127
|
-
return parsed;
|
|
2128
|
-
}
|
|
2129
|
-
function applyTypeExportPatterns(text, parsed) {
|
|
2130
|
-
const valueDecl = /export\s+(?:declare\s+)?(?:const|let|var|function|class)\s+([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
2131
|
-
const typeDecl = /export\s+(?:declare\s+)?(?:type|interface)\s+([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
2132
|
-
const namedClause = /export\s+(?!type\s*\{)\{([^}]+)\}/g;
|
|
2133
|
-
const typeNamedClause = /export\s+type\s*\{([^}]+)\}/g;
|
|
2134
|
-
for (const m of text.matchAll(valueDecl)) {
|
|
2135
|
-
parsed.valueExports.add(m[1]);
|
|
2136
|
-
}
|
|
2137
|
-
for (const m of text.matchAll(typeDecl)) {
|
|
2138
|
-
parsed.typeExports.add(m[1]);
|
|
2139
|
-
}
|
|
2140
|
-
for (const m of text.matchAll(namedClause)) {
|
|
2141
|
-
parseNamedExportClause(m[1], parsed);
|
|
2142
|
-
}
|
|
2143
|
-
for (const m of text.matchAll(typeNamedClause)) {
|
|
2144
|
-
parseNamedExportClause(m[1], parsed);
|
|
2145
|
-
}
|
|
2146
|
-
}
|
|
2147
|
-
function pickComponentName(item, parsed) {
|
|
2148
|
-
const expected = [toPascalCase(item.dirName), toPascalCase(item.name)];
|
|
2149
|
-
for (const name of expected) {
|
|
2150
|
-
if (parsed.valueExports.has(name)) return name;
|
|
2151
|
-
}
|
|
2152
|
-
const lowered = new Set(expected.map((n) => n.toLowerCase()));
|
|
2153
|
-
for (const exp of parsed.valueExports) {
|
|
2154
|
-
if (lowered.has(exp.toLowerCase())) return exp;
|
|
2155
|
-
}
|
|
2156
|
-
return null;
|
|
2157
|
-
}
|
|
2158
|
-
function pickPropsName(componentName, parsed) {
|
|
2159
|
-
const direct = `${componentName}Props`;
|
|
2160
|
-
if (parsed.typeExports.has(direct) || parsed.valueExports.has(direct)) return direct;
|
|
2161
|
-
for (const sym of parsed.typeExports) {
|
|
2162
|
-
if (sym.toLowerCase() === direct.toLowerCase()) return sym;
|
|
2163
|
-
}
|
|
2164
|
-
for (const sym of parsed.valueExports) {
|
|
2165
|
-
if (sym.toLowerCase() === direct.toLowerCase()) return sym;
|
|
2166
|
-
}
|
|
2167
|
-
return null;
|
|
2168
|
-
}
|
|
2169
|
-
function pickDefaultExportComponent(item, typesIndexPath) {
|
|
2170
|
-
const expected = [toPascalCase(item.dirName), toPascalCase(item.name)];
|
|
2171
|
-
for (const name of expected) {
|
|
2172
|
-
const mainTypesPath = findMainComponentTypesPath(typesIndexPath, name);
|
|
2173
|
-
if (!mainTypesPath) continue;
|
|
2174
|
-
const mainText = readTypesFileText(mainTypesPath);
|
|
2175
|
-
const defaultExportMatch = mainText.match(/export\s+default\s+([A-Za-z_][A-Za-z0-9_]*)/);
|
|
2176
|
-
if (!defaultExportMatch) continue;
|
|
2177
|
-
const symbol = defaultExportMatch[1];
|
|
2178
|
-
if (expected.some((candidate) => candidate.toLowerCase() === symbol.toLowerCase())) {
|
|
2179
|
-
return symbol;
|
|
2180
|
-
}
|
|
2181
|
-
}
|
|
2182
|
-
return null;
|
|
2183
|
-
}
|
|
2184
|
-
function readTypesFileText(typesFilePath) {
|
|
2185
|
-
try {
|
|
2186
|
-
return fs6.readFileSync(typesFilePath, "utf-8");
|
|
2187
|
-
} catch {
|
|
2188
|
-
return "";
|
|
2189
|
-
}
|
|
2190
|
-
}
|
|
2191
|
-
function findMainComponentTypesPath(typesIndexPath, componentName) {
|
|
2192
|
-
const dir = path7.dirname(typesIndexPath);
|
|
2193
|
-
const indexText = readTypesFileText(typesIndexPath);
|
|
2194
|
-
const fromMatches = indexText.matchAll(/from\s+["']\.\/([^"']+)["']/g);
|
|
2195
|
-
for (const match of fromMatches) {
|
|
2196
|
-
const candidate = path7.join(dir, `${match[1]}.d.ts`);
|
|
2197
|
-
if (fs6.existsSync(candidate)) return candidate;
|
|
2198
|
-
}
|
|
2199
|
-
const byName = path7.join(dir, `${componentName}.d.ts`);
|
|
2200
|
-
return fs6.existsSync(byName) ? byName : null;
|
|
2201
|
-
}
|
|
2202
|
-
function isNonCallableCompoundExport(typesText, symbolName) {
|
|
2203
|
-
const objectDecl = new RegExp(
|
|
2204
|
-
`(?:declare\\s+const|const)\\s+${symbolName}\\s*:\\s*\\{`
|
|
2205
|
-
);
|
|
2206
|
-
return objectDecl.test(typesText);
|
|
2207
|
-
}
|
|
2208
|
-
function pickCompoundRenderMember(typesText) {
|
|
2209
|
-
if (/\bText\s*:\s*React\./.test(typesText)) return "Text";
|
|
2210
|
-
const memberMatch = typesText.match(
|
|
2211
|
-
/^\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*React\.(?:ForwardRefExoticComponent|NamedExoticComponent|FC)/m
|
|
2212
|
-
);
|
|
2213
|
-
return memberMatch?.[1] ?? "Text";
|
|
2214
|
-
}
|
|
2215
|
-
function resolveLazyAccess(typesIndexPath, componentName) {
|
|
2216
|
-
const indexText = readTypesFileText(typesIndexPath);
|
|
2217
|
-
const mainTypesPath = findMainComponentTypesPath(typesIndexPath, componentName);
|
|
2218
|
-
const mainText = mainTypesPath ? readTypesFileText(mainTypesPath) : "";
|
|
2219
|
-
const defaultAsMatch = indexText.match(
|
|
2220
|
-
new RegExp(`export\\s*\\{[^}]*\\bdefault\\s+as\\s+${componentName}\\b[^}]*\\}`)
|
|
2221
|
-
);
|
|
2222
|
-
const namedExportMatch = indexText.match(
|
|
2223
|
-
new RegExp(`export\\s*\\{[^}]*\\b${componentName}\\b[^}]*\\}`)
|
|
2224
|
-
);
|
|
2225
|
-
const defaultExportMatch = mainText.match(/export\s+default\s+([A-Za-z_][A-Za-z0-9_]*)/);
|
|
2226
|
-
const defaultSymbol = defaultExportMatch?.[1];
|
|
2227
|
-
const compoundSymbol = defaultSymbol && isNonCallableCompoundExport(mainText, defaultSymbol) ? defaultSymbol : isNonCallableCompoundExport(mainText, componentName) ? componentName : null;
|
|
2228
|
-
if (compoundSymbol) {
|
|
2229
|
-
const member = pickCompoundRenderMember(mainText);
|
|
2230
|
-
if (defaultAsMatch || namedExportMatch) {
|
|
2231
|
-
return `.${componentName}.${member}`;
|
|
2232
|
-
}
|
|
2233
|
-
return `.default.${member}`;
|
|
2234
|
-
}
|
|
2235
|
-
if (defaultAsMatch || namedExportMatch) return `.${componentName}`;
|
|
2236
|
-
if (defaultSymbol && defaultSymbol === componentName) {
|
|
2237
|
-
return `.default`;
|
|
2238
|
-
}
|
|
2239
|
-
return `.${componentName}`;
|
|
2240
|
-
}
|
|
2241
|
-
function subpathExposesLazyBinding(typesIndexPath, componentName) {
|
|
2242
|
-
const indexText = readTypesFileText(typesIndexPath);
|
|
2243
|
-
if (new RegExp(`export\\s*\\{[^}]*\\bdefault\\s+as\\s+${componentName}\\b[^}]*\\}`).test(
|
|
2244
|
-
indexText
|
|
2245
|
-
)) {
|
|
2246
|
-
return true;
|
|
2247
|
-
}
|
|
2248
|
-
if (new RegExp(`export\\s*\\{[^}]*\\b${componentName}\\b[^}]*\\}`).test(indexText)) {
|
|
2249
|
-
return true;
|
|
2250
|
-
}
|
|
2251
|
-
if (/export\s+default\b/.test(indexText)) return true;
|
|
2252
|
-
return pickComponentName(
|
|
2253
|
-
{ name: componentName, dirName: componentName },
|
|
2254
|
-
parseTypeExportsLocal(typesIndexPath)
|
|
2255
|
-
) !== null;
|
|
2256
|
-
}
|
|
2257
|
-
function resolveLazyImport(pkgInfo, importSpecifier, typesFilePath, componentName) {
|
|
2258
|
-
let lazyImportSpecifier = importSpecifier;
|
|
2259
|
-
let lazyAccess = resolveLazyAccess(typesFilePath, componentName);
|
|
2260
|
-
if (importSpecifier !== "@inventive-ui/components" && !subpathExposesLazyBinding(typesFilePath, componentName) && pkgInfo.rootTypesPath) {
|
|
2261
|
-
lazyImportSpecifier = "@inventive-ui/components";
|
|
2262
|
-
lazyAccess = `.${componentName}`;
|
|
2263
|
-
}
|
|
2264
|
-
return { lazyImportSpecifier, lazyAccess };
|
|
2265
|
-
}
|
|
2266
|
-
function describeExpected(item) {
|
|
2267
|
-
return `${toPascalCase(item.dirName)} / ${toPascalCase(item.name)}`;
|
|
2268
|
-
}
|
|
2269
|
-
function resolveFromTypesFile(item, importSpecifier, typesFilePath, pkgInfo) {
|
|
2270
|
-
const parsed = parseTypeExports(typesFilePath);
|
|
2271
|
-
const indexParsed = parseTypeExportsLocal(typesFilePath);
|
|
2272
|
-
const componentName = pickComponentName(item, parsed) ?? pickDefaultExportComponent(item, typesFilePath);
|
|
2273
|
-
if (!componentName) {
|
|
2274
|
-
return {
|
|
2275
|
-
ok: false,
|
|
2276
|
-
reason: `No matching component export in ${importSpecifier}. Expected ${describeExpected(item)}.`
|
|
2277
|
-
};
|
|
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
|
+
);
|
|
2278
1947
|
}
|
|
2279
|
-
const propsName = pickPropsName(componentName, indexParsed) ?? pickPropsName(componentName, parsed) ?? (() => {
|
|
2280
|
-
const typesPath = path7.join(path7.dirname(typesFilePath), "types.d.ts");
|
|
2281
|
-
if (!fs6.existsSync(typesPath)) return null;
|
|
2282
|
-
return pickPropsName(componentName, parseTypeExports(typesPath));
|
|
2283
|
-
})();
|
|
2284
|
-
const lazyImport = resolveLazyImport(
|
|
2285
|
-
pkgInfo,
|
|
2286
|
-
importSpecifier,
|
|
2287
|
-
typesFilePath,
|
|
2288
|
-
componentName
|
|
2289
|
-
);
|
|
2290
|
-
return {
|
|
2291
|
-
ok: true,
|
|
2292
|
-
importSpecifier,
|
|
2293
|
-
lazyImportSpecifier: lazyImport.lazyImportSpecifier,
|
|
2294
|
-
componentName,
|
|
2295
|
-
propsName: propsName ?? void 0,
|
|
2296
|
-
lazyAccess: lazyImport.lazyAccess
|
|
2297
|
-
};
|
|
2298
|
-
}
|
|
2299
|
-
function exportCandidatesForItem(item) {
|
|
2300
|
-
const candidates = [
|
|
2301
|
-
`./${item.name}`,
|
|
2302
|
-
`./${item.name.toLowerCase()}`,
|
|
2303
|
-
`./${item.dirName}`,
|
|
2304
|
-
`./${item.dirName.toLowerCase()}`
|
|
2305
|
-
];
|
|
2306
|
-
return [...new Set(candidates)];
|
|
2307
1948
|
}
|
|
2308
|
-
function
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
item.dirName,
|
|
2312
|
-
item.name,
|
|
2313
|
-
toPascalCase(item.dirName),
|
|
2314
|
-
toPascalCase(item.name)
|
|
2315
|
-
])
|
|
2316
|
-
];
|
|
2317
|
-
}
|
|
2318
|
-
function resolveWildcardTypesPath(pkgInfo, segment) {
|
|
2319
|
-
const wildcardEntry = pkgInfo.exportsField["./*"];
|
|
2320
|
-
if (!wildcardEntry) return null;
|
|
2321
|
-
const typesRel = resolveTypesPathFromExportEntry(wildcardEntry);
|
|
2322
|
-
if (!typesRel || !typesRel.includes("*")) return null;
|
|
2323
|
-
const resolvedRel = typesRel.replace(/\*/g, segment);
|
|
2324
|
-
const fullPath = path7.join(pkgInfo.packageRoot, resolvedRel);
|
|
2325
|
-
return fs6.existsSync(fullPath) ? fullPath : null;
|
|
2326
|
-
}
|
|
2327
|
-
function resolveTypesPathForExportCandidate(pkgInfo, candidate) {
|
|
2328
|
-
const entry = pkgInfo.exportsField[candidate];
|
|
2329
|
-
if (entry) {
|
|
2330
|
-
const typesRel = resolveTypesPathFromExportEntry(entry);
|
|
2331
|
-
return typesRel ? path7.join(pkgInfo.packageRoot, typesRel) : null;
|
|
2332
|
-
}
|
|
2333
|
-
const segment = candidate.replace(/^\.\//, "");
|
|
2334
|
-
return resolveWildcardTypesPath(pkgInfo, segment);
|
|
2335
|
-
}
|
|
2336
|
-
function resolveFromComponentFolders(item, pkgInfo) {
|
|
2337
|
-
for (const folder of componentFolderCandidates(item)) {
|
|
2338
|
-
const typesPath = resolveWildcardTypesPath(pkgInfo, folder) ?? (() => {
|
|
2339
|
-
const directPath = path7.join(
|
|
2340
|
-
pkgInfo.packageRoot,
|
|
2341
|
-
"dist",
|
|
2342
|
-
"components",
|
|
2343
|
-
folder,
|
|
2344
|
-
"index.d.ts"
|
|
2345
|
-
);
|
|
2346
|
-
return fs6.existsSync(directPath) ? directPath : null;
|
|
2347
|
-
})();
|
|
2348
|
-
if (!typesPath) continue;
|
|
2349
|
-
const importSpecifier = `@inventive-ui/components/${folder}`;
|
|
2350
|
-
try {
|
|
2351
|
-
assertImportSpecifier(importSpecifier);
|
|
2352
|
-
} catch {
|
|
2353
|
-
continue;
|
|
2354
|
-
}
|
|
2355
|
-
const resolved = resolveFromTypesFile(item, importSpecifier, typesPath, pkgInfo);
|
|
2356
|
-
if (resolved.ok) return resolved;
|
|
1949
|
+
function assertJsIdentifier(name, label) {
|
|
1950
|
+
if (!JS_IDENTIFIER_RE.test(name)) {
|
|
1951
|
+
throw new CLIError(`Invalid ${label}: "${name}"`);
|
|
2357
1952
|
}
|
|
2358
|
-
return null;
|
|
2359
1953
|
}
|
|
2360
|
-
function
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
);
|
|
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}"`);
|
|
2364
1959
|
}
|
|
2365
|
-
function
|
|
2366
|
-
return
|
|
1960
|
+
function escapeTsStringLiteral(value) {
|
|
1961
|
+
return JSON.stringify(value);
|
|
2367
1962
|
}
|
|
2368
|
-
function
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
reason: "@inventive-ui/components is not installed in node_modules."
|
|
2374
|
-
};
|
|
2375
|
-
}
|
|
2376
|
-
const fromFolders = resolveFromComponentFolders(item, pkgInfo);
|
|
2377
|
-
if (fromFolders?.ok) return fromFolders;
|
|
2378
|
-
for (const candidate of exportCandidatesForItem(item)) {
|
|
2379
|
-
const typesPath = resolveTypesPathForExportCandidate(pkgInfo, candidate);
|
|
2380
|
-
if (!typesPath) continue;
|
|
2381
|
-
const importSpecifier = `@inventive-ui/components/${candidate.replace(/^\.\//, "")}`;
|
|
2382
|
-
try {
|
|
2383
|
-
assertImportSpecifier(importSpecifier);
|
|
2384
|
-
} catch {
|
|
2385
|
-
continue;
|
|
2386
|
-
}
|
|
2387
|
-
const resolved = resolveFromTypesFile(item, importSpecifier, typesPath, pkgInfo);
|
|
2388
|
-
if (resolved.ok) return resolved;
|
|
2389
|
-
}
|
|
2390
|
-
if (pkgInfo.rootTypesPath) {
|
|
2391
|
-
const fromRoot = resolveFromTypesFile(item, "@inventive-ui/components", pkgInfo.rootTypesPath, pkgInfo);
|
|
2392
|
-
if (fromRoot.ok) return fromRoot;
|
|
2393
|
-
}
|
|
2394
|
-
if (!componentBuildExists(item, pkgInfo)) {
|
|
2395
|
-
return {
|
|
2396
|
-
ok: false,
|
|
2397
|
-
reason: buildMissingComponentReason(item)
|
|
2398
|
-
};
|
|
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.");
|
|
2399
1968
|
}
|
|
2400
|
-
return
|
|
2401
|
-
ok: false,
|
|
2402
|
-
reason: `No matching component export for "${item.name}" in @inventive-ui/components. Expected a value export named ${describeExpected(item)}.`
|
|
2403
|
-
};
|
|
1969
|
+
return trimmed;
|
|
2404
1970
|
}
|
|
2405
1971
|
|
|
2406
1972
|
// src/utils/config-patch/component-config.ts
|
|
@@ -2421,19 +1987,6 @@ function findComponentConfigObject(sourceFile) {
|
|
|
2421
1987
|
visit(sourceFile);
|
|
2422
1988
|
return found;
|
|
2423
1989
|
}
|
|
2424
|
-
function findComponentConfigMapType(sourceFile) {
|
|
2425
|
-
let found;
|
|
2426
|
-
const visit = (node) => {
|
|
2427
|
-
if (found) return;
|
|
2428
|
-
if (ts2.isTypeAliasDeclaration(node) && ts2.isIdentifier(node.name) && node.name.text === "ComponentConfigMap" && node.type && ts2.isTypeLiteralNode(node.type)) {
|
|
2429
|
-
found = node.type;
|
|
2430
|
-
return;
|
|
2431
|
-
}
|
|
2432
|
-
ts2.forEachChild(node, visit);
|
|
2433
|
-
};
|
|
2434
|
-
visit(sourceFile);
|
|
2435
|
-
return found;
|
|
2436
|
-
}
|
|
2437
1990
|
function existingComponentKeys(obj) {
|
|
2438
1991
|
const keys = /* @__PURE__ */ new Set();
|
|
2439
1992
|
for (const prop of obj.properties) {
|
|
@@ -2443,33 +1996,14 @@ function existingComponentKeys(obj) {
|
|
|
2443
1996
|
}
|
|
2444
1997
|
return keys;
|
|
2445
1998
|
}
|
|
2446
|
-
function formatDefaultConfig(cfg) {
|
|
2447
|
-
return JSON.stringify(cfg, null, 6).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n");
|
|
2448
|
-
}
|
|
2449
1999
|
function buildComponentEntry(item) {
|
|
2450
2000
|
assertJsIdentifier(item.dirName, "component dirName");
|
|
2451
|
-
const cfg = item.meta?.defaultConfig ?? {};
|
|
2452
|
-
const cfgStr = formatDefaultConfig(cfg);
|
|
2453
2001
|
return ` ${item.dirName}: {
|
|
2454
|
-
default:
|
|
2002
|
+
default: {},
|
|
2455
2003
|
},
|
|
2456
2004
|
|
|
2457
2005
|
`;
|
|
2458
2006
|
}
|
|
2459
|
-
function buildTypeEntry(item, cwd) {
|
|
2460
|
-
const resolved = resolveComponentExport(item, cwd);
|
|
2461
|
-
if (resolved.ok && resolved.propsName) {
|
|
2462
|
-
return ` ${item.dirName}: { default: Partial<${resolved.propsName}> };`;
|
|
2463
|
-
}
|
|
2464
|
-
return ` ${item.dirName}: { default: Record<string, unknown> };`;
|
|
2465
|
-
}
|
|
2466
|
-
function buildTypeImport(item, cwd) {
|
|
2467
|
-
const resolved = resolveComponentExport(item, cwd);
|
|
2468
|
-
if (resolved.ok && resolved.propsName && resolved.importSpecifier) {
|
|
2469
|
-
return `import type { ${resolved.propsName} } from "${resolved.importSpecifier}";`;
|
|
2470
|
-
}
|
|
2471
|
-
return null;
|
|
2472
|
-
}
|
|
2473
2007
|
function insertBeforeClosingBrace(source, objectEnd, insertion) {
|
|
2474
2008
|
let pos = objectEnd - 1;
|
|
2475
2009
|
while (pos >= 0 && /\s/.test(source[pos] ?? "")) pos--;
|
|
@@ -2481,7 +2015,7 @@ function insertBeforeClosingBrace(source, objectEnd, insertion) {
|
|
|
2481
2015
|
}
|
|
2482
2016
|
return source;
|
|
2483
2017
|
}
|
|
2484
|
-
function mergeComponentConfigContent(source, manifest
|
|
2018
|
+
function mergeComponentConfigContent(source, manifest) {
|
|
2485
2019
|
if (!manifest || manifest.items.length === 0) {
|
|
2486
2020
|
return { content: source, changed: false };
|
|
2487
2021
|
}
|
|
@@ -2497,33 +2031,78 @@ function mergeComponentConfigContent(source, manifest, cwd) {
|
|
|
2497
2031
|
const existing = existingComponentKeys(configObject);
|
|
2498
2032
|
const missing = manifest.items.filter((item) => !existing.has(item.dirName));
|
|
2499
2033
|
if (missing.length === 0) return { content: source, changed: false };
|
|
2500
|
-
let next = source;
|
|
2501
2034
|
const newEntries = missing.map((item) => buildComponentEntry(item)).join("");
|
|
2502
|
-
next = insertBeforeClosingBrace(
|
|
2503
|
-
|
|
2504
|
-
|
|
2035
|
+
const next = insertBeforeClosingBrace(
|
|
2036
|
+
source,
|
|
2037
|
+
configObject.getEnd(),
|
|
2038
|
+
newEntries
|
|
2505
2039
|
);
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
`;
|
|
2509
|
-
next = insertBeforeClosingBrace(next, typeLiteral.getEnd(), typeLines);
|
|
2510
|
-
}
|
|
2511
|
-
const existingImportLines = new Set(next.match(/^import\s.+;$/gm) ?? []);
|
|
2512
|
-
const newImports = missing.map((item) => buildTypeImport(item, cwd)).filter((line) => line !== null && !existingImportLines.has(line));
|
|
2513
|
-
if (newImports.length > 0) {
|
|
2514
|
-
const importMatches = [...next.matchAll(/^import\s.+;$/gm)];
|
|
2515
|
-
const lastImport = importMatches.at(-1);
|
|
2516
|
-
if (lastImport?.index !== void 0) {
|
|
2517
|
-
const insertAt = lastImport.index + lastImport[0].length;
|
|
2518
|
-
next = `${next.slice(0, insertAt)}
|
|
2519
|
-
${[...new Set(newImports)].join("\n")}${next.slice(insertAt)}`;
|
|
2520
|
-
} else {
|
|
2521
|
-
next = `${[...new Set(newImports)].join("\n")}
|
|
2040
|
+
return { content: next, changed: true };
|
|
2041
|
+
}
|
|
2522
2042
|
|
|
2523
|
-
|
|
2043
|
+
// src/utils/config-patch/tsconfig-iui.ts
|
|
2044
|
+
import path7 from "path";
|
|
2045
|
+
import fs6 from "fs-extra";
|
|
2046
|
+
var IUI_TS_ROOT_FILES = ["iui.config.ts", "component.config.ts"];
|
|
2047
|
+
function isSolutionStyleTsconfig(config) {
|
|
2048
|
+
const refs = config.references;
|
|
2049
|
+
return Array.isArray(refs) && refs.length > 0;
|
|
2050
|
+
}
|
|
2051
|
+
function patchJsonInclude(filePath, extra) {
|
|
2052
|
+
if (!fs6.existsSync(filePath)) return false;
|
|
2053
|
+
const raw = fs6.readJsonSync(filePath);
|
|
2054
|
+
const include = Array.isArray(raw.include) ? [...raw.include.map(String)] : [];
|
|
2055
|
+
let changed = false;
|
|
2056
|
+
for (const item of extra) {
|
|
2057
|
+
if (!include.includes(item)) {
|
|
2058
|
+
include.push(item);
|
|
2059
|
+
changed = true;
|
|
2524
2060
|
}
|
|
2525
2061
|
}
|
|
2526
|
-
|
|
2062
|
+
if (!changed) return false;
|
|
2063
|
+
atomicWriteJson(filePath, { ...raw, include });
|
|
2064
|
+
return true;
|
|
2065
|
+
}
|
|
2066
|
+
function resolveAppTsconfigPath(cwd, root) {
|
|
2067
|
+
const refs = root.references;
|
|
2068
|
+
if (!refs) return null;
|
|
2069
|
+
for (const ref of refs) {
|
|
2070
|
+
const p = ref.path?.replace(/^\.\//, "") ?? "";
|
|
2071
|
+
const base = p.replace(/\.json$/i, "");
|
|
2072
|
+
if (/app/i.test(base)) {
|
|
2073
|
+
return path7.join(cwd, p.endsWith(".json") ? p : `${p}.json`);
|
|
2074
|
+
}
|
|
2075
|
+
}
|
|
2076
|
+
for (const ref of refs) {
|
|
2077
|
+
const p = ref.path?.replace(/^\.\//, "") ?? "";
|
|
2078
|
+
if (!/node/i.test(p)) {
|
|
2079
|
+
return path7.join(cwd, p.endsWith(".json") ? p : `${p}.json`);
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
return null;
|
|
2083
|
+
}
|
|
2084
|
+
function repairSolutionStyleRootTsconfig(cwd) {
|
|
2085
|
+
const rootPath = path7.join(cwd, "tsconfig.json");
|
|
2086
|
+
if (!fs6.existsSync(rootPath)) return false;
|
|
2087
|
+
const existing = fs6.readJsonSync(rootPath);
|
|
2088
|
+
if (!isSolutionStyleTsconfig(existing)) return false;
|
|
2089
|
+
const polluted = existing.compilerOptions !== void 0 || Array.isArray(existing.include) && existing.include.length > 0 || Array.isArray(existing.exclude) && existing.exclude.length > 0;
|
|
2090
|
+
if (!polluted) return false;
|
|
2091
|
+
atomicWriteJson(rootPath, {
|
|
2092
|
+
files: Array.isArray(existing.files) ? existing.files : [],
|
|
2093
|
+
references: existing.references
|
|
2094
|
+
});
|
|
2095
|
+
return true;
|
|
2096
|
+
}
|
|
2097
|
+
function patchSolutionStyleTsconfigForIui(cwd) {
|
|
2098
|
+
const rootPath = path7.join(cwd, "tsconfig.json");
|
|
2099
|
+
if (!fs6.existsSync(rootPath)) return false;
|
|
2100
|
+
const existing = fs6.readJsonSync(rootPath);
|
|
2101
|
+
if (!isSolutionStyleTsconfig(existing)) return false;
|
|
2102
|
+
const repairedRoot = repairSolutionStyleRootTsconfig(cwd);
|
|
2103
|
+
const appPath = resolveAppTsconfigPath(cwd, existing);
|
|
2104
|
+
const patchedApp = appPath ? patchJsonInclude(appPath, IUI_TS_ROOT_FILES) : false;
|
|
2105
|
+
return repairedRoot || patchedApp;
|
|
2527
2106
|
}
|
|
2528
2107
|
|
|
2529
2108
|
// src/validation/configTierChecks.ts
|
|
@@ -2922,15 +2501,6 @@ function loadAssetsConfigTemplate() {
|
|
|
2922
2501
|
return {};
|
|
2923
2502
|
}
|
|
2924
2503
|
}
|
|
2925
|
-
function loadComponentConfigPresetsTemplate() {
|
|
2926
|
-
const templatePath = path10.join(getCliTemplatesDir(), "component.config.presets.json");
|
|
2927
|
-
if (!fs8.existsSync(templatePath)) return {};
|
|
2928
|
-
try {
|
|
2929
|
-
return fs8.readJsonSync(templatePath);
|
|
2930
|
-
} catch {
|
|
2931
|
-
return {};
|
|
2932
|
-
}
|
|
2933
|
-
}
|
|
2934
2504
|
function mergeAssetSlotWithTemplate(slot, templateSlot) {
|
|
2935
2505
|
if (!templateSlot) return slot ?? {};
|
|
2936
2506
|
const out = { ...templateSlot, ...slot ?? {} };
|
|
@@ -3277,7 +2847,24 @@ function writeTsConfigNode(cwd = process.cwd()) {
|
|
|
3277
2847
|
};
|
|
3278
2848
|
atomicWriteJson(nodeTsPath, content);
|
|
3279
2849
|
}
|
|
3280
|
-
function
|
|
2850
|
+
function ensureTsConfigForIui(framework, cwd = process.cwd()) {
|
|
2851
|
+
const tsconfigPath = path10.join(cwd, "tsconfig.json");
|
|
2852
|
+
let existing = {};
|
|
2853
|
+
if (fs8.existsSync(tsconfigPath)) {
|
|
2854
|
+
try {
|
|
2855
|
+
existing = fs8.readJsonSync(tsconfigPath);
|
|
2856
|
+
} catch {
|
|
2857
|
+
existing = {};
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
if (framework === "vite" && isSolutionStyleTsconfig(existing)) {
|
|
2861
|
+
patchSolutionStyleTsconfigForIui(cwd);
|
|
2862
|
+
writeTsConfigNode(cwd);
|
|
2863
|
+
return;
|
|
2864
|
+
}
|
|
2865
|
+
writeFlatProjectTsConfig(framework, cwd);
|
|
2866
|
+
}
|
|
2867
|
+
function writeFlatProjectTsConfig(framework, cwd = process.cwd()) {
|
|
3281
2868
|
const tsconfigPath = path10.join(cwd, "tsconfig.json");
|
|
3282
2869
|
let existing = {};
|
|
3283
2870
|
if (fs8.existsSync(tsconfigPath)) {
|
|
@@ -3345,56 +2932,22 @@ function writeTsConfig(framework, cwd = process.cwd()) {
|
|
|
3345
2932
|
};
|
|
3346
2933
|
atomicWriteJson(tsconfigPath, output);
|
|
3347
2934
|
}
|
|
3348
|
-
function writeComponentConfig(
|
|
2935
|
+
function writeComponentConfig(_manifest, cwd = process.cwd()) {
|
|
3349
2936
|
const configPath = path10.join(cwd, COMPONENT_CONFIG_FILE);
|
|
3350
|
-
let entries = "";
|
|
3351
|
-
const typedEntries = [];
|
|
3352
|
-
const typeImports = [];
|
|
3353
|
-
const presetsTemplate = loadComponentConfigPresetsTemplate();
|
|
3354
|
-
if (manifest) {
|
|
3355
|
-
for (const item of manifest.items) {
|
|
3356
|
-
assertJsIdentifier(item.dirName, "component dirName");
|
|
3357
|
-
const cfg = item.meta?.defaultConfig ?? {};
|
|
3358
|
-
const presetBlock = presetsTemplate[item.dirName];
|
|
3359
|
-
const cfgStr = JSON.stringify(cfg, null, 6).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n");
|
|
3360
|
-
let extraBlocks = "";
|
|
3361
|
-
if (presetBlock?.presets) {
|
|
3362
|
-
const presetsStr = JSON.stringify(presetBlock.presets, null, 6).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n");
|
|
3363
|
-
extraBlocks += `
|
|
3364
|
-
presets: ${presetsStr},`;
|
|
3365
|
-
}
|
|
3366
|
-
entries += ` ${item.dirName}: {
|
|
3367
|
-
default: ${cfgStr},${extraBlocks}
|
|
3368
|
-
},
|
|
3369
|
-
|
|
3370
|
-
`;
|
|
3371
|
-
const resolved = resolveComponentExport(item, cwd);
|
|
3372
|
-
if (resolved.ok && resolved.propsName && resolved.importSpecifier) {
|
|
3373
|
-
typeImports.push(`import type { ${resolved.propsName} } from "${resolved.importSpecifier}";`);
|
|
3374
|
-
typedEntries.push(` ${item.dirName}: { default: Partial<${resolved.propsName}> };`);
|
|
3375
|
-
} else {
|
|
3376
|
-
typedEntries.push(` ${item.dirName}: { default: Record<string, unknown> };`);
|
|
3377
|
-
}
|
|
3378
|
-
}
|
|
3379
|
-
}
|
|
3380
|
-
const imports = [...new Set(typeImports)].join("\n");
|
|
3381
|
-
const componentConfigType = typedEntries.length > 0 ? `type ComponentConfigMap = {
|
|
3382
|
-
${typedEntries.join("\n")}
|
|
3383
|
-
};` : `type ComponentConfigMap = Record<string, { default: Record<string, unknown> }>;`;
|
|
3384
2937
|
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
|
|
3385
2938
|
//
|
|
3386
|
-
//
|
|
3387
|
-
//
|
|
3388
|
-
//
|
|
2939
|
+
// Optional per-component defaults (variant, appearance, presets, cTags).
|
|
2940
|
+
// Only add entries you want to override \u2014 omit components you do not customize.
|
|
2941
|
+
// \`iui update\` may append new registry keys; edit or remove them as needed.
|
|
3389
2942
|
//
|
|
3390
2943
|
// Docs: https://inventiveui.com/docs/configuration
|
|
3391
2944
|
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
${componentConfigType}
|
|
2945
|
+
import type { ComponentConfig } from "@inventive-ui/components/config";
|
|
3395
2946
|
|
|
3396
|
-
export const componentConfig
|
|
3397
|
-
|
|
2947
|
+
export const componentConfig = {
|
|
2948
|
+
// Example:
|
|
2949
|
+
// Button: { default: { variant: "solid", appearance: "soft" } },
|
|
2950
|
+
} satisfies ComponentConfig;
|
|
3398
2951
|
`;
|
|
3399
2952
|
atomicWriteFile(configPath, content);
|
|
3400
2953
|
}
|
|
@@ -3406,7 +2959,7 @@ function ensureComponentConfig(manifest, cwd = process.cwd(), options = {}) {
|
|
|
3406
2959
|
return existed && options.force ? "replaced" : "scaffolded";
|
|
3407
2960
|
}
|
|
3408
2961
|
const before = fs8.readFileSync(configPath, "utf-8");
|
|
3409
|
-
const result = mergeComponentConfigContent(before, manifest
|
|
2962
|
+
const result = mergeComponentConfigContent(before, manifest);
|
|
3410
2963
|
if (!result.changed) return "noop";
|
|
3411
2964
|
atomicWriteFile(configPath, result.content);
|
|
3412
2965
|
return "merged";
|
|
@@ -6958,7 +6511,7 @@ async function initCommand(opts) {
|
|
|
6958
6511
|
step("Generating config files\u2026");
|
|
6959
6512
|
writeAssetsConfig(initRoot);
|
|
6960
6513
|
ensureProjectConfig(initRoot);
|
|
6961
|
-
|
|
6514
|
+
ensureTsConfigForIui(framework.framework, initRoot);
|
|
6962
6515
|
if (framework.framework === "vite") {
|
|
6963
6516
|
ensureInventiveUiViteConfig(initRoot);
|
|
6964
6517
|
ok("Config files ready (iui.config.ts, tsconfig.json, tsconfig.node.json, vite.config.ts)");
|
|
@@ -6968,7 +6521,7 @@ async function initCommand(opts) {
|
|
|
6968
6521
|
}
|
|
6969
6522
|
ok("Config files ready (iui.config.ts, tsconfig.json)");
|
|
6970
6523
|
}
|
|
6971
|
-
step("
|
|
6524
|
+
step("Scaffolding component.config.ts\u2026");
|
|
6972
6525
|
const fetchedRegistry = await fetchComponentRegistry(auth.token);
|
|
6973
6526
|
if (!fetchedRegistry.registry && fetchedRegistry.apiFailure) {
|
|
6974
6527
|
warn(`Component registry API: ${fetchedRegistry.apiFailure}`);
|
|
@@ -7853,40 +7406,21 @@ function checkCompileFirstReadiness(cwd = process.cwd(), _options = {}) {
|
|
|
7853
7406
|
const configPath = path24.join(cwd, PROJECT_CONFIG_FILE);
|
|
7854
7407
|
if (fs19.existsSync(configPath)) {
|
|
7855
7408
|
const configContent = fs19.readFileSync(configPath, "utf-8");
|
|
7856
|
-
if (
|
|
7857
|
-
warnings.push(
|
|
7858
|
-
|
|
7859
|
-
|
|
7409
|
+
if (/packageSafelist\s*:\s*false/.test(configContent)) {
|
|
7410
|
+
warnings.push(
|
|
7411
|
+
"Deprecated iui.config build.packageSafelist \u2014 remove it; Framework always merges IUI package compile contracts"
|
|
7412
|
+
);
|
|
7413
|
+
}
|
|
7414
|
+
if (/includeShadeMatrix\s*:/.test(configContent)) {
|
|
7415
|
+
warnings.push(
|
|
7416
|
+
"Deprecated compiler flags in iui.config build.* \u2014 remove them; compile policy is Framework-internal"
|
|
7417
|
+
);
|
|
7418
|
+
hints.push("Use theme + optional scan.dirs only. See Framework docs/01-compile-first-guide.md");
|
|
7419
|
+
}
|
|
7420
|
+
if (/scanPackages\s*:/.test(configContent) || /scan\.packages\s*:/.test(configContent)) {
|
|
7421
|
+
warnings.push(
|
|
7422
|
+
"Deprecated scanPackages in iui.config \u2014 IUI packages are discovered from package.json dependencies"
|
|
7860
7423
|
);
|
|
7861
|
-
} else {
|
|
7862
|
-
if (/packageSafelist\s*:\s*false/.test(configContent)) {
|
|
7863
|
-
warnings.push(
|
|
7864
|
-
"iui.config.ts build.packageSafelist is false \u2014 package compile.safelist contracts from scanPackages will not merge"
|
|
7865
|
-
);
|
|
7866
|
-
hints.push(
|
|
7867
|
-
"Remove packageSafelist: false to use Framework default (true) so @inventive-ui/components compile.safelist is included"
|
|
7868
|
-
);
|
|
7869
|
-
}
|
|
7870
|
-
if (!/includeShadeMatrix\s*:\s*false/.test(configContent)) {
|
|
7871
|
-
warnings.push("iui.config.ts build.includeShadeMatrix should be false unless you need the full compose() matrix");
|
|
7872
|
-
}
|
|
7873
|
-
if (!/includeThemePresets\s*:\s*true/.test(configContent)) {
|
|
7874
|
-
warnings.push("iui.config.ts build.includeThemePresets should be true");
|
|
7875
|
-
}
|
|
7876
|
-
if (!/includeThemeGrayScale\s*:\s*true/.test(configContent)) {
|
|
7877
|
-
warnings.push(
|
|
7878
|
-
"iui.config.ts build.includeThemeGrayScale should be true (pre-expand theme gray gray-2\u202698 utilities)"
|
|
7879
|
-
);
|
|
7880
|
-
}
|
|
7881
|
-
if (!/resolvePalettePatterns\s*:\s*true/.test(configContent)) {
|
|
7882
|
-
warnings.push("iui.config.ts build.resolvePalettePatterns should be true");
|
|
7883
|
-
}
|
|
7884
|
-
if (!/includeArbitraryScan\s*:\s*true/.test(configContent)) {
|
|
7885
|
-
warnings.push("iui.config.ts build.includeArbitraryScan should be true");
|
|
7886
|
-
}
|
|
7887
|
-
if (!/useAst\s*:\s*true/.test(configContent)) {
|
|
7888
|
-
warnings.push("iui.config.ts build.useAst should be true");
|
|
7889
|
-
}
|
|
7890
7424
|
}
|
|
7891
7425
|
}
|
|
7892
7426
|
if (projectHasViteTooling(cwd)) {
|
|
@@ -8175,7 +7709,7 @@ function checkBootstrapSync(cwd = process.cwd(), options = {}) {
|
|
|
8175
7709
|
}
|
|
8176
7710
|
|
|
8177
7711
|
// src/commands/doctor.ts
|
|
8178
|
-
function runConfigTierDiagnostics(targetCwd, opts, counters, options = {}) {
|
|
7712
|
+
async function runConfigTierDiagnostics(targetCwd, opts, counters, options = {}) {
|
|
8179
7713
|
const pass = (label) => {
|
|
8180
7714
|
checkPass(label);
|
|
8181
7715
|
counters.passed++;
|
|
@@ -8193,10 +7727,13 @@ function runConfigTierDiagnostics(targetCwd, opts, counters, options = {}) {
|
|
|
8193
7727
|
if (opts?.fix === true && includePackageJson) {
|
|
8194
7728
|
ensureProjectConfig(targetCwd);
|
|
8195
7729
|
ensureGitignoreHasIuiBuildCache(targetCwd);
|
|
8196
|
-
|
|
7730
|
+
const vite = projectHasViteTooling(targetCwd);
|
|
7731
|
+
ensureTsConfigForIui(vite ? "vite" : "react", targetCwd);
|
|
7732
|
+
if (vite) {
|
|
8197
7733
|
ensureInventiveUiViteConfig(targetCwd);
|
|
8198
7734
|
}
|
|
8199
7735
|
ensureComponentConfig(readComponentPackageManifest(targetCwd), targetCwd);
|
|
7736
|
+
await ensureSlotRegistry({ cwd: targetCwd, quiet: true, mode: "repair" });
|
|
8200
7737
|
}
|
|
8201
7738
|
if (includeSlotCheck && isInsideProject(targetCwd) && getInstalledPackageVersion(COMPONENTS_PACKAGE, targetCwd)) {
|
|
8202
7739
|
const slotValidity = checkGeneratedSlotValidity(targetCwd);
|
|
@@ -8298,7 +7835,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
|
|
|
8298
7835
|
counters.failed++;
|
|
8299
7836
|
};
|
|
8300
7837
|
if (opts?.configOnly) {
|
|
8301
|
-
runConfigTierDiagnostics(targetCwd, opts, counters, {
|
|
7838
|
+
await runConfigTierDiagnostics(targetCwd, opts, counters, {
|
|
8302
7839
|
includePackageJson: true,
|
|
8303
7840
|
includeSlotCheck: true
|
|
8304
7841
|
});
|
|
@@ -8308,10 +7845,13 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
|
|
|
8308
7845
|
else fail2("package.json missing");
|
|
8309
7846
|
if (opts?.fix === true) {
|
|
8310
7847
|
ensureProjectConfig(targetCwd);
|
|
8311
|
-
|
|
7848
|
+
const vite2 = projectHasViteTooling(targetCwd);
|
|
7849
|
+
ensureTsConfigForIui(vite2 ? "vite" : "react", targetCwd);
|
|
7850
|
+
if (vite2) {
|
|
8312
7851
|
ensureInventiveUiViteConfig(targetCwd);
|
|
8313
7852
|
}
|
|
8314
7853
|
ensureComponentConfig(readComponentPackageManifest(targetCwd), targetCwd);
|
|
7854
|
+
await ensureSlotRegistry({ cwd: targetCwd, quiet: true, mode: "repair" });
|
|
8315
7855
|
}
|
|
8316
7856
|
if (isInsideProject(targetCwd)) {
|
|
8317
7857
|
pass("Inventive UI project initialized");
|
|
@@ -8430,7 +7970,7 @@ async function runPackageDiagnostics(targetCwd, opts, counters) {
|
|
|
8430
7970
|
hint("Fix: run iui doctor --fix to regenerate bootstrap artifacts");
|
|
8431
7971
|
}
|
|
8432
7972
|
}
|
|
8433
|
-
runConfigTierDiagnostics(targetCwd, opts, counters, {
|
|
7973
|
+
await runConfigTierDiagnostics(targetCwd, opts, counters, {
|
|
8434
7974
|
includePackageJson: false,
|
|
8435
7975
|
includeSlotCheck: false
|
|
8436
7976
|
});
|
|
@@ -8736,7 +8276,7 @@ async function updateCommand(opts = {}) {
|
|
|
8736
8276
|
const auth = await ensureAuthSession();
|
|
8737
8277
|
await ensureLicenseSession();
|
|
8738
8278
|
const inProject = isInsideProject();
|
|
8739
|
-
const currentCliVersion = true ? "0.0.
|
|
8279
|
+
const currentCliVersion = true ? "0.0.10" : "unknown";
|
|
8740
8280
|
const latestCliVersion = await fetchLatestCliVersion(auth.token);
|
|
8741
8281
|
const cliUpdateAvailable = latestCliVersion !== null && isVersionGreater(latestCliVersion, currentCliVersion);
|
|
8742
8282
|
if (latestCliVersion && cliUpdateAvailable) {
|
|
@@ -9018,7 +8558,7 @@ var AUTH_EXEMPT_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
9018
8558
|
"doctor",
|
|
9019
8559
|
"list"
|
|
9020
8560
|
]);
|
|
9021
|
-
program.name("iui").description("The official CLI for the Inventive UI Design System").version(true ? "0.0.
|
|
8561
|
+
program.name("iui").description("The official CLI for the Inventive UI Design System").version(true ? "0.0.10" : "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");
|
|
9022
8562
|
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));
|
|
9023
8563
|
program.command("logout").description("Remove stored credentials").action(logoutCommand);
|
|
9024
8564
|
program.command("whoami").description("Show authenticated identity and license details").action(whoamiCommand);
|