uidex 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/cli.cjs +122 -41
- package/dist/cli/cli.cjs.map +1 -1
- package/dist/cloud/index.cjs +22 -2
- package/dist/cloud/index.cjs.map +1 -1
- package/dist/cloud/index.js +22 -2
- package/dist/cloud/index.js.map +1 -1
- package/dist/headless/index.cjs +909 -346
- package/dist/headless/index.cjs.map +1 -1
- package/dist/headless/index.d.cts +6 -0
- package/dist/headless/index.d.ts +6 -0
- package/dist/headless/index.js +914 -346
- package/dist/headless/index.js.map +1 -1
- package/dist/index.cjs +2887 -1167
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -16
- package/dist/index.d.ts +83 -16
- package/dist/index.js +2919 -1175
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +2850 -1155
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +55 -8
- package/dist/react/index.d.ts +55 -8
- package/dist/react/index.js +2879 -1159
- package/dist/react/index.js.map +1 -1
- package/dist/scan/index.cjs +121 -42
- package/dist/scan/index.cjs.map +1 -1
- package/dist/scan/index.d.cts +5 -0
- package/dist/scan/index.d.ts +5 -0
- package/dist/scan/index.js +121 -42
- package/dist/scan/index.js.map +1 -1
- package/package.json +18 -17
- package/templates/claude/audit.md +8 -2
- package/templates/claude/rules.md +15 -0
- package/dist/cloud/index.d.cts +0 -108
- package/dist/cloud/index.d.ts +0 -108
package/dist/scan/index.d.cts
CHANGED
|
@@ -31,11 +31,16 @@ interface Route {
|
|
|
31
31
|
path: string;
|
|
32
32
|
page: string;
|
|
33
33
|
}
|
|
34
|
+
interface FlowStep {
|
|
35
|
+
entityId: string;
|
|
36
|
+
action?: string;
|
|
37
|
+
}
|
|
34
38
|
interface Flow {
|
|
35
39
|
kind: "flow";
|
|
36
40
|
id: string;
|
|
37
41
|
loc: Location;
|
|
38
42
|
touches: string[];
|
|
43
|
+
steps: FlowStep[];
|
|
39
44
|
}
|
|
40
45
|
interface Page extends EntityWithMetaBase {
|
|
41
46
|
kind: "page";
|
package/dist/scan/index.d.ts
CHANGED
|
@@ -31,11 +31,16 @@ interface Route {
|
|
|
31
31
|
path: string;
|
|
32
32
|
page: string;
|
|
33
33
|
}
|
|
34
|
+
interface FlowStep {
|
|
35
|
+
entityId: string;
|
|
36
|
+
action?: string;
|
|
37
|
+
}
|
|
34
38
|
interface Flow {
|
|
35
39
|
kind: "flow";
|
|
36
40
|
id: string;
|
|
37
41
|
loc: Location;
|
|
38
42
|
touches: string[];
|
|
43
|
+
steps: FlowStep[];
|
|
39
44
|
}
|
|
40
45
|
interface Page extends EntityWithMetaBase {
|
|
41
46
|
kind: "page";
|
package/dist/scan/index.js
CHANGED
|
@@ -4,6 +4,10 @@ import * as path from "path";
|
|
|
4
4
|
|
|
5
5
|
// src/scan/config.ts
|
|
6
6
|
var DEFAULT_TYPE_MODE = "strict";
|
|
7
|
+
var WELL_KNOWN_FILES = {
|
|
8
|
+
page: "uidex.page.ts",
|
|
9
|
+
feature: "uidex.feature.ts"
|
|
10
|
+
};
|
|
7
11
|
var ConfigError = class extends Error {
|
|
8
12
|
constructor(message) {
|
|
9
13
|
super(message);
|
|
@@ -41,14 +45,14 @@ var ALLOWED_AUDIT_KEYS = /* @__PURE__ */ new Set(["scopeLeak", "coverage", "acce
|
|
|
41
45
|
function fail(msg) {
|
|
42
46
|
throw new ConfigError(`Invalid .uidex.json: ${msg}`);
|
|
43
47
|
}
|
|
44
|
-
function assertObject(value,
|
|
48
|
+
function assertObject(value, path10) {
|
|
45
49
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
46
|
-
fail(`${
|
|
50
|
+
fail(`${path10} must be an object`);
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
|
-
function assertStringArray(value,
|
|
53
|
+
function assertStringArray(value, path10) {
|
|
50
54
|
if (!Array.isArray(value) || !value.every((v) => typeof v === "string")) {
|
|
51
|
-
fail(`${
|
|
55
|
+
fail(`${path10} must be a string[]`);
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
function validateConfig(raw) {
|
|
@@ -1769,7 +1773,24 @@ function resolve2(ctx) {
|
|
|
1769
1773
|
const routes = conventions.pages === "auto" ? detectRoutes(ctx.extracted.map((e) => e.file)) : [];
|
|
1770
1774
|
const handledPageFiles = /* @__PURE__ */ new Set();
|
|
1771
1775
|
for (const route of routes) {
|
|
1772
|
-
const
|
|
1776
|
+
const routeDir = path3.posix.dirname(route.file);
|
|
1777
|
+
const wellKnownPath = `${routeDir}/${WELL_KNOWN_FILES.page}`;
|
|
1778
|
+
const wellKnownExp = exportFor(wellKnownPath, "page");
|
|
1779
|
+
const routeExp = exportFor(route.file, "page");
|
|
1780
|
+
const exp = wellKnownExp ?? routeExp;
|
|
1781
|
+
const locFile = wellKnownExp ? wellKnownPath : route.file;
|
|
1782
|
+
if (wellKnownExp) handledPageFiles.add(wellKnownPath);
|
|
1783
|
+
handledPageFiles.add(route.file);
|
|
1784
|
+
if (wellKnownExp && routeExp) {
|
|
1785
|
+
diagnostics.push({
|
|
1786
|
+
code: "competing-uidex-export",
|
|
1787
|
+
severity: "warning",
|
|
1788
|
+
message: `Page metadata declared in both ${wellKnownPath} and ${route.file}; ${wellKnownPath} takes precedence.`,
|
|
1789
|
+
file: route.file,
|
|
1790
|
+
line: routeExp.loc.line,
|
|
1791
|
+
hint: `Remove the export from ${route.file} or delete ${wellKnownPath}.`
|
|
1792
|
+
});
|
|
1793
|
+
}
|
|
1773
1794
|
if (exp && exp.id === false) continue;
|
|
1774
1795
|
const effectiveId = exp && typeof exp.id === "string" ? exp.id : route.id;
|
|
1775
1796
|
const meta = exp ? buildMetaFromExport(exp) : void 0;
|
|
@@ -1777,11 +1798,10 @@ function resolve2(ctx) {
|
|
|
1777
1798
|
const page = {
|
|
1778
1799
|
kind: "page",
|
|
1779
1800
|
id: effectiveId,
|
|
1780
|
-
loc: { file:
|
|
1801
|
+
loc: { file: locFile, line: exp?.loc.line },
|
|
1781
1802
|
...meta ? { meta } : {}
|
|
1782
1803
|
};
|
|
1783
1804
|
registry.add(page);
|
|
1784
|
-
handledPageFiles.add(route.file);
|
|
1785
1805
|
}
|
|
1786
1806
|
for (const ef of ctx.extracted) {
|
|
1787
1807
|
const exp = exportFor(ef.file.displayPath, "page");
|
|
@@ -1797,7 +1817,8 @@ function resolve2(ctx) {
|
|
|
1797
1817
|
}
|
|
1798
1818
|
const featureGlob = typeof conventions.features === "string" ? conventions.features : null;
|
|
1799
1819
|
const conventionalFeatureDirs = /* @__PURE__ */ new Set();
|
|
1800
|
-
const
|
|
1820
|
+
const featureExportFilesByDir = /* @__PURE__ */ new Map();
|
|
1821
|
+
const wellKnownFeatureFileByDir = /* @__PURE__ */ new Map();
|
|
1801
1822
|
const suppressedFeatureDirs = /* @__PURE__ */ new Set();
|
|
1802
1823
|
if (featureGlob) {
|
|
1803
1824
|
const re = globToRegExp(featureGlob + "/**");
|
|
@@ -1806,16 +1827,43 @@ function resolve2(ctx) {
|
|
|
1806
1827
|
const dir = extractFeatureDir(ef.file.displayPath, featureGlob);
|
|
1807
1828
|
if (!dir) continue;
|
|
1808
1829
|
conventionalFeatureDirs.add(dir);
|
|
1830
|
+
const isWellKnown = path3.posix.basename(ef.file.displayPath) === WELL_KNOWN_FILES.feature;
|
|
1831
|
+
if (isWellKnown) wellKnownFeatureFileByDir.set(dir, ef.file.displayPath);
|
|
1809
1832
|
const exp = exportFor(ef.file.displayPath, "feature");
|
|
1810
1833
|
if (exp) {
|
|
1811
1834
|
if (exp.id === false) suppressedFeatureDirs.add(dir);
|
|
1812
|
-
else
|
|
1813
|
-
|
|
1835
|
+
else {
|
|
1836
|
+
let arr = featureExportFilesByDir.get(dir);
|
|
1837
|
+
if (!arr) {
|
|
1838
|
+
arr = [];
|
|
1839
|
+
featureExportFilesByDir.set(dir, arr);
|
|
1840
|
+
}
|
|
1841
|
+
arr.push({ file: ef.file.displayPath, exp });
|
|
1842
|
+
}
|
|
1814
1843
|
}
|
|
1815
1844
|
}
|
|
1816
1845
|
for (const dir of conventionalFeatureDirs) {
|
|
1817
1846
|
if (suppressedFeatureDirs.has(dir)) continue;
|
|
1818
|
-
const
|
|
1847
|
+
const allExports = featureExportFilesByDir.get(dir) ?? [];
|
|
1848
|
+
const wellKnownPath = wellKnownFeatureFileByDir.get(dir);
|
|
1849
|
+
const wellKnownEntry = wellKnownPath ? allExports.find((e) => e.file === wellKnownPath) : void 0;
|
|
1850
|
+
let exp;
|
|
1851
|
+
if (wellKnownEntry) {
|
|
1852
|
+
exp = wellKnownEntry.exp;
|
|
1853
|
+
for (const other of allExports) {
|
|
1854
|
+
if (other.file === wellKnownEntry.file) continue;
|
|
1855
|
+
diagnostics.push({
|
|
1856
|
+
code: "competing-uidex-export",
|
|
1857
|
+
severity: "warning",
|
|
1858
|
+
message: `Feature metadata declared in both ${wellKnownEntry.file} and ${other.file}; ${wellKnownEntry.file} takes precedence.`,
|
|
1859
|
+
file: other.file,
|
|
1860
|
+
line: other.exp.loc.line,
|
|
1861
|
+
hint: `Remove the export from ${other.file} or delete ${wellKnownEntry.file}.`
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1864
|
+
} else if (allExports.length > 0) {
|
|
1865
|
+
exp = allExports[0].exp;
|
|
1866
|
+
}
|
|
1819
1867
|
const id = exp && typeof exp.id === "string" ? exp.id : path3.posix.basename(dir);
|
|
1820
1868
|
const meta = exp ? buildMetaFromExport(exp) : void 0;
|
|
1821
1869
|
const feature = {
|
|
@@ -1948,11 +1996,12 @@ function resolve2(ctx) {
|
|
|
1948
1996
|
exp.id,
|
|
1949
1997
|
buildMetaFromExport(exp)
|
|
1950
1998
|
);
|
|
1999
|
+
const scope = computeScope(file);
|
|
1951
2000
|
const primitive = {
|
|
1952
2001
|
kind: "primitive",
|
|
1953
2002
|
id: exp.id,
|
|
1954
2003
|
loc: { file, line: exp.loc.line },
|
|
1955
|
-
scopes: [
|
|
2004
|
+
...scope ? { scopes: [scope] } : {},
|
|
1956
2005
|
...meta ? { meta } : {}
|
|
1957
2006
|
};
|
|
1958
2007
|
registry.add(primitive);
|
|
@@ -1964,11 +2013,12 @@ function resolve2(ctx) {
|
|
|
1964
2013
|
if (domPrimitives.length > 0) {
|
|
1965
2014
|
for (const p2 of domPrimitives) {
|
|
1966
2015
|
const meta = metaWithComposes("primitive", p2.id);
|
|
2016
|
+
const domScope = computeScope(p2.file);
|
|
1967
2017
|
const primitive = {
|
|
1968
2018
|
kind: "primitive",
|
|
1969
2019
|
id: p2.id,
|
|
1970
2020
|
loc: { file: p2.file, line: p2.line },
|
|
1971
|
-
scopes: [
|
|
2021
|
+
...domScope ? { scopes: [domScope] } : {},
|
|
1972
2022
|
...meta ? { meta } : {}
|
|
1973
2023
|
};
|
|
1974
2024
|
registry.add(primitive);
|
|
@@ -1978,13 +2028,13 @@ function resolve2(ctx) {
|
|
|
1978
2028
|
if (primitiveConventions && fileMatchesAny(file, primitiveConventions)) {
|
|
1979
2029
|
const name = kebab(baseName(file));
|
|
1980
2030
|
if (!name) continue;
|
|
1981
|
-
const
|
|
2031
|
+
const convScope = computeScope(file);
|
|
1982
2032
|
const meta = metaWithComposes("primitive", name);
|
|
1983
2033
|
const primitive = {
|
|
1984
2034
|
kind: "primitive",
|
|
1985
2035
|
id: name,
|
|
1986
2036
|
loc: { file },
|
|
1987
|
-
scopes: [
|
|
2037
|
+
...convScope ? { scopes: [convScope] } : {},
|
|
1988
2038
|
...meta ? { meta } : {}
|
|
1989
2039
|
};
|
|
1990
2040
|
registry.add(primitive);
|
|
@@ -2014,7 +2064,8 @@ function resolve2(ctx) {
|
|
|
2014
2064
|
kind: "flow",
|
|
2015
2065
|
id: flowExport.id,
|
|
2016
2066
|
loc: base.loc,
|
|
2017
|
-
touches: base.touches
|
|
2067
|
+
touches: base.touches,
|
|
2068
|
+
steps: base.steps
|
|
2018
2069
|
};
|
|
2019
2070
|
registry.add(flow);
|
|
2020
2071
|
} else {
|
|
@@ -2059,7 +2110,7 @@ function computeScope(displayPath) {
|
|
|
2059
2110
|
if (pagesIdx !== -1 && parts[pagesIdx + 1]) {
|
|
2060
2111
|
return `page:${parts[pagesIdx + 1]}`;
|
|
2061
2112
|
}
|
|
2062
|
-
return
|
|
2113
|
+
return null;
|
|
2063
2114
|
}
|
|
2064
2115
|
function extractFlowsFromSource(file) {
|
|
2065
2116
|
const flows = [];
|
|
@@ -2093,17 +2144,18 @@ function extractFlowsFromSource(file) {
|
|
|
2093
2144
|
kind: "flow",
|
|
2094
2145
|
id,
|
|
2095
2146
|
loc: { file: file.displayPath, line },
|
|
2096
|
-
touches: dedupe(touches.map((t) => t.id))
|
|
2147
|
+
touches: dedupe(touches.map((t) => t.id)),
|
|
2148
|
+
steps: touches.filter((t) => t.action).map((t) => ({ entityId: t.id, action: t.action }))
|
|
2097
2149
|
});
|
|
2098
2150
|
}
|
|
2099
2151
|
return flows;
|
|
2100
2152
|
}
|
|
2101
2153
|
function captureUidexIds(body) {
|
|
2102
2154
|
const out2 = [];
|
|
2103
|
-
const re = /uidex\(\s*(?:'([^']+)'|"([^"]+)"|`([^`$]+)`)\s*\)
|
|
2155
|
+
const re = /uidex\(\s*(?:'([^']+)'|"([^"]+)"|`([^`$]+)`)\s*\)(?:\.(\w+)\s*\()?/g;
|
|
2104
2156
|
let m;
|
|
2105
2157
|
while ((m = re.exec(body)) !== null) {
|
|
2106
|
-
out2.push({ id: m[1] || m[2] || m[3] });
|
|
2158
|
+
out2.push({ id: m[1] || m[2] || m[3], action: m[4] });
|
|
2107
2159
|
}
|
|
2108
2160
|
return out2;
|
|
2109
2161
|
}
|
|
@@ -2112,6 +2164,7 @@ function dedupe(arr) {
|
|
|
2112
2164
|
}
|
|
2113
2165
|
|
|
2114
2166
|
// src/scan/audit.ts
|
|
2167
|
+
import * as path4 from "path";
|
|
2115
2168
|
var MARKER_FILENAMES = ["UIDEX_PAGE.md", "UIDEX_FEATURE.md"];
|
|
2116
2169
|
function audit(opts) {
|
|
2117
2170
|
const diagnostics = [];
|
|
@@ -2213,6 +2266,32 @@ function audit(opts) {
|
|
|
2213
2266
|
}
|
|
2214
2267
|
}
|
|
2215
2268
|
}
|
|
2269
|
+
if (lint) {
|
|
2270
|
+
const scannedPaths = new Set(files.map((f) => f.displayPath));
|
|
2271
|
+
for (const ef of extracted) {
|
|
2272
|
+
if (!ef.metadata) continue;
|
|
2273
|
+
for (const m of ef.metadata) {
|
|
2274
|
+
if (m.kind !== "page" && m.kind !== "feature") continue;
|
|
2275
|
+
if (typeof m.id !== "string") continue;
|
|
2276
|
+
const filePath = ef.file.displayPath;
|
|
2277
|
+
const wellKnownName = WELL_KNOWN_FILES[m.kind];
|
|
2278
|
+
if (path4.posix.basename(filePath) === wellKnownName) continue;
|
|
2279
|
+
const dir = path4.posix.dirname(filePath);
|
|
2280
|
+
const wellKnownPath = dir === "." ? wellKnownName : `${dir}/${wellKnownName}`;
|
|
2281
|
+
if (scannedPaths.has(wellKnownPath)) continue;
|
|
2282
|
+
const kindLabel = m.kind === "page" ? "Page" : "Feature";
|
|
2283
|
+
diagnostics.push({
|
|
2284
|
+
code: "prefer-well-known-file",
|
|
2285
|
+
severity: "info",
|
|
2286
|
+
message: `${kindLabel} "${m.id}" metadata lives on ${filePath}; prefer ${wellKnownPath}`,
|
|
2287
|
+
file: filePath,
|
|
2288
|
+
line: m.loc.line,
|
|
2289
|
+
entity: { kind: m.kind, id: m.id },
|
|
2290
|
+
hint: `Move the \`export const uidex\` block to ${wellKnownPath} and remove it from ${filePath}.`
|
|
2291
|
+
});
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
}
|
|
2216
2295
|
if (lint) {
|
|
2217
2296
|
for (const f of files) {
|
|
2218
2297
|
const lines = f.content.split("\n");
|
|
@@ -2249,8 +2328,8 @@ function audit(opts) {
|
|
|
2249
2328
|
baseName2.replace(/\.(tsx|ts|jsx|js|mjs|cjs)$/, "").replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase()
|
|
2250
2329
|
);
|
|
2251
2330
|
if (!primitive) continue;
|
|
2252
|
-
const scope = primitive.scopes?.[0]
|
|
2253
|
-
if (scope
|
|
2331
|
+
const scope = primitive.scopes?.[0];
|
|
2332
|
+
if (!scope) continue;
|
|
2254
2333
|
const [kind, id] = scope.split(":");
|
|
2255
2334
|
const importerSegments = f.displayPath.split("/");
|
|
2256
2335
|
if (!importerSegments.includes(id) || !importerSegments.includes(kind + "s")) {
|
|
@@ -2648,7 +2727,7 @@ function parseGitHubRef(ref) {
|
|
|
2648
2727
|
|
|
2649
2728
|
// src/scan/scaffold.ts
|
|
2650
2729
|
import * as fs3 from "fs";
|
|
2651
|
-
import * as
|
|
2730
|
+
import * as path5 from "path";
|
|
2652
2731
|
function scaffoldWidgetSpec(opts) {
|
|
2653
2732
|
const {
|
|
2654
2733
|
registry,
|
|
@@ -2663,7 +2742,7 @@ function scaffoldWidgetSpec(opts) {
|
|
|
2663
2742
|
}
|
|
2664
2743
|
const criteria = widget.meta?.acceptance ?? [];
|
|
2665
2744
|
const filename = `widget-${widgetId}.spec.ts`;
|
|
2666
|
-
const outputPath =
|
|
2745
|
+
const outputPath = path5.resolve(outDir, filename);
|
|
2667
2746
|
if (fs3.existsSync(outputPath) && !force) {
|
|
2668
2747
|
return {
|
|
2669
2748
|
outputPath,
|
|
@@ -2677,7 +2756,7 @@ function scaffoldWidgetSpec(opts) {
|
|
|
2677
2756
|
criteria,
|
|
2678
2757
|
fixtureImport
|
|
2679
2758
|
});
|
|
2680
|
-
fs3.mkdirSync(
|
|
2759
|
+
fs3.mkdirSync(path5.dirname(outputPath), { recursive: true });
|
|
2681
2760
|
fs3.writeFileSync(outputPath, content, "utf8");
|
|
2682
2761
|
return { outputPath, written: true, skipped: false };
|
|
2683
2762
|
}
|
|
@@ -2711,7 +2790,7 @@ function renderSpec(args) {
|
|
|
2711
2790
|
|
|
2712
2791
|
// src/scan/pipeline.ts
|
|
2713
2792
|
import * as fs4 from "fs";
|
|
2714
|
-
import * as
|
|
2793
|
+
import * as path6 from "path";
|
|
2715
2794
|
function runScan(opts = {}) {
|
|
2716
2795
|
const cwd = opts.cwd ?? process.cwd();
|
|
2717
2796
|
const configs = opts.configs ?? discover({ cwd });
|
|
@@ -2743,7 +2822,7 @@ function runOne(dc, opts) {
|
|
|
2743
2822
|
gitContext,
|
|
2744
2823
|
typeMode: config.typeMode
|
|
2745
2824
|
});
|
|
2746
|
-
const outputPath =
|
|
2825
|
+
const outputPath = path6.resolve(configDir, config.output);
|
|
2747
2826
|
const outputRel = config.output;
|
|
2748
2827
|
let existingOnDisk = null;
|
|
2749
2828
|
if (opts.check) {
|
|
@@ -2779,29 +2858,29 @@ function runOne(dc, opts) {
|
|
|
2779
2858
|
};
|
|
2780
2859
|
}
|
|
2781
2860
|
function writeScanResult(result) {
|
|
2782
|
-
fs4.mkdirSync(
|
|
2861
|
+
fs4.mkdirSync(path6.dirname(result.outputPath), { recursive: true });
|
|
2783
2862
|
fs4.writeFileSync(result.outputPath, result.generated, "utf8");
|
|
2784
2863
|
}
|
|
2785
2864
|
|
|
2786
2865
|
// src/scan/cli.ts
|
|
2787
2866
|
import * as fs7 from "fs";
|
|
2788
|
-
import * as
|
|
2867
|
+
import * as path9 from "path";
|
|
2789
2868
|
|
|
2790
2869
|
// src/scan/ai/index.ts
|
|
2791
2870
|
import * as p from "@clack/prompts";
|
|
2792
2871
|
|
|
2793
2872
|
// src/scan/ai/providers/claude.ts
|
|
2794
2873
|
import * as fs6 from "fs";
|
|
2795
|
-
import * as
|
|
2874
|
+
import * as path8 from "path";
|
|
2796
2875
|
|
|
2797
2876
|
// src/scan/ai/templates.ts
|
|
2798
2877
|
import * as fs5 from "fs";
|
|
2799
|
-
import * as
|
|
2878
|
+
import * as path7 from "path";
|
|
2800
2879
|
function templatePath(rel) {
|
|
2801
2880
|
const candidates = [
|
|
2802
|
-
|
|
2881
|
+
path7.resolve(__dirname, "../../templates", rel),
|
|
2803
2882
|
// dist/cli/cli.cjs → ../../templates
|
|
2804
|
-
|
|
2883
|
+
path7.resolve(__dirname, "../../../templates", rel)
|
|
2805
2884
|
// src/scan/ai/foo.ts → ../../../templates
|
|
2806
2885
|
];
|
|
2807
2886
|
for (const c of candidates) {
|
|
@@ -2833,7 +2912,7 @@ var claudeProvider = {
|
|
|
2833
2912
|
async install({ cwd, force }) {
|
|
2834
2913
|
const changes = [];
|
|
2835
2914
|
for (const file of CLAUDE_FILES) {
|
|
2836
|
-
const dest =
|
|
2915
|
+
const dest = path8.join(cwd, file.dest);
|
|
2837
2916
|
const exists = fs6.existsSync(dest);
|
|
2838
2917
|
if (exists && !force) {
|
|
2839
2918
|
changes.push({
|
|
@@ -2843,7 +2922,7 @@ var claudeProvider = {
|
|
|
2843
2922
|
});
|
|
2844
2923
|
continue;
|
|
2845
2924
|
}
|
|
2846
|
-
fs6.mkdirSync(
|
|
2925
|
+
fs6.mkdirSync(path8.dirname(dest), { recursive: true });
|
|
2847
2926
|
fs6.writeFileSync(dest, readTemplate(file.template));
|
|
2848
2927
|
changes.push({
|
|
2849
2928
|
path: file.dest,
|
|
@@ -2855,7 +2934,7 @@ var claudeProvider = {
|
|
|
2855
2934
|
async uninstall({ cwd }) {
|
|
2856
2935
|
const changes = [];
|
|
2857
2936
|
for (const file of CLAUDE_FILES) {
|
|
2858
|
-
const dest =
|
|
2937
|
+
const dest = path8.join(cwd, file.dest);
|
|
2859
2938
|
if (!fs6.existsSync(dest)) {
|
|
2860
2939
|
changes.push({ path: file.dest, action: "skipped", reason: "absent" });
|
|
2861
2940
|
continue;
|
|
@@ -2863,9 +2942,9 @@ var claudeProvider = {
|
|
|
2863
2942
|
fs6.unlinkSync(dest);
|
|
2864
2943
|
changes.push({ path: file.dest, action: "removed" });
|
|
2865
2944
|
}
|
|
2866
|
-
cleanupEmpty(
|
|
2867
|
-
cleanupEmpty(
|
|
2868
|
-
cleanupEmpty(
|
|
2945
|
+
cleanupEmpty(path8.join(cwd, ".claude/commands/uidex"));
|
|
2946
|
+
cleanupEmpty(path8.join(cwd, ".claude/commands"));
|
|
2947
|
+
cleanupEmpty(path8.join(cwd, ".claude/rules"));
|
|
2869
2948
|
return { changes };
|
|
2870
2949
|
}
|
|
2871
2950
|
};
|
|
@@ -3076,7 +3155,7 @@ function helpText2() {
|
|
|
3076
3155
|
].join("\n");
|
|
3077
3156
|
}
|
|
3078
3157
|
function runInit(cwd, w) {
|
|
3079
|
-
const configPath =
|
|
3158
|
+
const configPath = path9.join(cwd, CONFIG_FILENAME);
|
|
3080
3159
|
if (fs7.existsSync(configPath)) {
|
|
3081
3160
|
w.err(`.uidex.json already exists at ${configPath}`);
|
|
3082
3161
|
return w.result(1);
|
|
@@ -3088,7 +3167,7 @@ function runInit(cwd, w) {
|
|
|
3088
3167
|
};
|
|
3089
3168
|
fs7.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
3090
3169
|
w.out(`Created ${configPath}`);
|
|
3091
|
-
const gitignorePath =
|
|
3170
|
+
const gitignorePath = path9.join(cwd, ".gitignore");
|
|
3092
3171
|
const entry = "*.gen.ts";
|
|
3093
3172
|
if (fs7.existsSync(gitignorePath)) {
|
|
3094
3173
|
const existing = fs7.readFileSync(gitignorePath, "utf8");
|
|
@@ -3166,7 +3245,7 @@ function runScaffold(cwd, args, flags, w) {
|
|
|
3166
3245
|
for (const r of results) {
|
|
3167
3246
|
const widget = r.registry.get("widget", id);
|
|
3168
3247
|
if (!widget) continue;
|
|
3169
|
-
const outDir =
|
|
3248
|
+
const outDir = path9.resolve(r.configDir, "e2e");
|
|
3170
3249
|
const result = scaffoldWidgetSpec({
|
|
3171
3250
|
registry: r.registry,
|
|
3172
3251
|
widgetId: id,
|