youiyoux 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{chunk-FUB7B3VK.js → chunk-74KBRI2H.js} +1 -1
- package/dist/chunks/{chunk-ZLRFD5JI.js → chunk-C3TSTYP7.js} +68 -7
- package/dist/chunks/{chunk-3ZHGONNA.js → chunk-L5BV4PI7.js} +399 -37
- package/dist/chunks/{src-7ENJHYG4.js → chunk-OIHNEGWH.js} +278 -78
- package/dist/chunks/{chunk-CLNMVQZJ.js → chunk-RTOTNSOV.js} +133 -13
- package/dist/chunks/{chunk-UHPK62Q5.js → chunk-UEB6MJDX.js} +75 -10
- package/dist/chunks/{src-VEHGMKYV.js → src-DS43LCRA.js} +2 -2
- package/dist/chunks/src-U5NTDPUX.js +148 -0
- package/dist/chunks/{src-WQWYJ6IQ.js → src-YGEZCUAO.js} +48 -6
- package/dist/chunks/{src-4KFNL3MY.js → src-YUC5PIDK.js} +6 -2
- package/dist/chunks/{src-B742AYFC.js → src-ZS76UD7E.js} +30 -2
- package/dist/schema/youi.request.schema.json +229 -0
- package/dist/youi.js +5 -5
- package/dist/youiyoux.js +5 -5
- package/package.json +4 -4
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
libraryOfPackage,
|
|
9
9
|
packageOf,
|
|
10
10
|
playwrightCli
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-74KBRI2H.js";
|
|
12
12
|
import {
|
|
13
13
|
candidateSource,
|
|
14
14
|
checkpointSqlite,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
showFromCatalog,
|
|
30
30
|
storeLocation,
|
|
31
31
|
syncIndex
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-UEB6MJDX.js";
|
|
33
33
|
import {
|
|
34
34
|
BASELINE_FILE,
|
|
35
35
|
DEFAULT_EXCLUDE,
|
|
@@ -41,6 +41,8 @@ import {
|
|
|
41
41
|
buildInventory,
|
|
42
42
|
buildTheme,
|
|
43
43
|
buildTokens,
|
|
44
|
+
captureScreens,
|
|
45
|
+
captureText,
|
|
44
46
|
checkCapabilities,
|
|
45
47
|
compareParity,
|
|
46
48
|
compareToBaseline,
|
|
@@ -76,7 +78,7 @@ import {
|
|
|
76
78
|
substituteVars,
|
|
77
79
|
vendoredPath,
|
|
78
80
|
whereUsed
|
|
79
|
-
} from "./chunk-
|
|
81
|
+
} from "./chunk-L5BV4PI7.js";
|
|
80
82
|
import {
|
|
81
83
|
within
|
|
82
84
|
} from "./chunk-S7UV34H5.js";
|
|
@@ -91,6 +93,7 @@ import {
|
|
|
91
93
|
OutputConfig,
|
|
92
94
|
ProjectConfig,
|
|
93
95
|
ScanReport,
|
|
96
|
+
copyleft,
|
|
94
97
|
executionLabel,
|
|
95
98
|
findFiles,
|
|
96
99
|
getSystem,
|
|
@@ -107,7 +110,7 @@ import {
|
|
|
107
110
|
sha256,
|
|
108
111
|
shortHash,
|
|
109
112
|
writeFileAtomic
|
|
110
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-C3TSTYP7.js";
|
|
111
114
|
import {
|
|
112
115
|
__toESM
|
|
113
116
|
} from "./chunk-E4HNK7VF.js";
|
|
@@ -140,7 +143,7 @@ var import_yaml3 = __toESM(require_dist(), 1);
|
|
|
140
143
|
import { execFile as execFile6 } from "node:child_process";
|
|
141
144
|
import { existsSync as existsSync4 } from "node:fs";
|
|
142
145
|
import { appendFile as appendFile2, readFile as readFile8 } from "node:fs/promises";
|
|
143
|
-
import { join as join22, relative as relative9, resolve as resolve12 } from "node:path";
|
|
146
|
+
import { basename as basename3, join as join22, relative as relative9, resolve as resolve12 } from "node:path";
|
|
144
147
|
import { parseArgs, promisify as promisify6 } from "node:util";
|
|
145
148
|
|
|
146
149
|
// ../cli/src/check.ts
|
|
@@ -158,7 +161,7 @@ import { join as join2, relative, resolve } from "node:path";
|
|
|
158
161
|
|
|
159
162
|
// ../cli/src/command.ts
|
|
160
163
|
var COMMAND = "youiyoux";
|
|
161
|
-
var SUBCOMMANDS = ["show", "where", "bom", "check", "baseline", "rules", "plan", "migrate", "init", "sync", "scan", "watch", "hooks", "agents", "mcp", "ui", "library", "discover", "index", "report", "render", "detect", "build", "parity", "schema", "inventory", "help"];
|
|
164
|
+
var SUBCOMMANDS = ["show", "where", "bom", "check", "baseline", "rules", "plan", "migrate", "init", "sync", "scan", "watch", "hooks", "agents", "mcp", "ui", "library", "discover", "index", "report", "render", "screens", "requests", "detect", "build", "parity", "schema", "inventory", "help"];
|
|
162
165
|
|
|
163
166
|
// ../cli/src/agents.ts
|
|
164
167
|
var import_yaml = __toESM(require_dist(), 1);
|
|
@@ -231,6 +234,7 @@ function agentsBlock(project2) {
|
|
|
231
234
|
`- Never edit files marked \`${GENERATED_MARK}\` (\`${config.outputs.dir}/*\`, ${config.agents.designMd}, the youiyoux skill). Change the design language and run \`youiyoux sync\`.`,
|
|
232
235
|
`- Owned component files in \`${config.componentsDir}\` may be edited; \`youiyoux sync\` 3-way merges upstream changes into them and reports drift.`,
|
|
233
236
|
"- After changing a component, call `ui_render` with its file (or run `youiyoux render <file>`) and look at the images: light and dark, desktop and phone, its accessibility issues and the diff against the base. Fix what it reports.",
|
|
237
|
+
"- People pin comments and change requests to components on captured screens. Before UI work, call `requests_list` (or run `youiyoux requests`); after making a requested change, capture its screen again (`youiyoux screens capture --base <app> --route <route>`) and call `request_addressed` with what you changed (file:line). Ask with `request_reply` when one is unclear. A person closes requests, never an agent.",
|
|
234
238
|
"- Before you finish, run `youiyoux check`; it must report 0 errors.",
|
|
235
239
|
diffInstruction(project2.root),
|
|
236
240
|
"- To change the System itself (a token, a prop, a rule), run `youiyoux plan` (or `system_plan`) and propose it. Agents never approve, publish or merge design changes.",
|
|
@@ -2047,7 +2051,7 @@ function renderDiscoverSearch(result) {
|
|
|
2047
2051
|
const width = Math.min(40, Math.max(...result.hits.map((h) => (h.source.ref ?? h.name).length)));
|
|
2048
2052
|
const rows = result.hits.flatMap((h) => {
|
|
2049
2053
|
const s = h.signals;
|
|
2050
|
-
const facts = [h.license === "unknown" ? style.warn("licence unknown") : h.license, s.via ? `${compact(s.via.weeklyDownloads)}/wk via ${s.via.package}` : `${compact(s.weeklyDownloads)}/wk`, `${compact(s.stars)}\u2605`, ...s.archived ? [style.error("archived")] : []].join(" \xB7 ");
|
|
2054
|
+
const facts = [h.license === "unknown" ? style.warn("licence unknown") : copyleft(h.license) ? style.warn(`${h.license} (copyleft)`) : h.license, s.via ? `${compact(s.via.weeklyDownloads)}/wk via ${s.via.package}` : `${compact(s.weeklyDownloads)}/wk`, `${compact(s.stars)}\u2605`, ...s.archived ? [style.error("archived")] : []].join(" \xB7 ");
|
|
2051
2055
|
return [` ${padEnd(truncate(h.source.ref ?? h.name, 40), width)} ${truncate(h.summary, 72)}`, ` ${" ".repeat(width)} ${style.dim(facts)} ${h.install ? h.install.command : ""}`];
|
|
2052
2056
|
});
|
|
2053
2057
|
const from = result.offset ?? 0;
|
|
@@ -2087,7 +2091,7 @@ import { homedir, userInfo } from "node:os";
|
|
|
2087
2091
|
import { join as join12, resolve as resolve6 } from "node:path";
|
|
2088
2092
|
async function swapImpact(candidate, family) {
|
|
2089
2093
|
try {
|
|
2090
|
-
const { discoverIndexPath: discoverIndexPath2, sharedStore: sharedStore2 } = await import("./src-
|
|
2094
|
+
const { discoverIndexPath: discoverIndexPath2, sharedStore: sharedStore2 } = await import("./src-YUC5PIDK.js");
|
|
2091
2095
|
const path = discoverIndexPath2();
|
|
2092
2096
|
if (!process.env.DATABASE_URL && !existsSync(path)) return null;
|
|
2093
2097
|
const impact = await (await sharedStore2(path, process.env, { readOnly: true })).swapImpact(candidate, family);
|
|
@@ -2098,7 +2102,7 @@ async function swapImpact(candidate, family) {
|
|
|
2098
2102
|
}
|
|
2099
2103
|
async function libraryLicence(id) {
|
|
2100
2104
|
try {
|
|
2101
|
-
const { discoverCacheDir: discoverCacheDir2, findListing } = await import("./src-
|
|
2105
|
+
const { discoverCacheDir: discoverCacheDir2, findListing } = await import("./src-YUC5PIDK.js");
|
|
2102
2106
|
const { entry } = await findListing(discoverCacheDir2(void 0, process.env), id);
|
|
2103
2107
|
return entry.id === id ? entry.license : null;
|
|
2104
2108
|
} catch {
|
|
@@ -2106,7 +2110,7 @@ async function libraryLicence(id) {
|
|
|
2106
2110
|
}
|
|
2107
2111
|
}
|
|
2108
2112
|
async function startRuleEditor(options) {
|
|
2109
|
-
const { FileStore, RuleWorkflow, serveWorkflow } = await import("./src-
|
|
2113
|
+
const { FileStore, RuleWorkflow, serveWorkflow } = await import("./src-U5NTDPUX.js");
|
|
2110
2114
|
const projectRoot = resolve6(options.project);
|
|
2111
2115
|
const load2 = { ...options.config ? { configPath: resolve6(options.config) } : {}, ...options.design ? { designRoot: resolve6(options.design) } : {}, ...options.root ? { productRoot: resolve6(options.root) } : {} };
|
|
2112
2116
|
const project2 = await loadProject(projectRoot, load2);
|
|
@@ -2160,6 +2164,44 @@ async function runHub(toolRoot, options) {
|
|
|
2160
2164
|
watcher?.kill("SIGTERM");
|
|
2161
2165
|
}
|
|
2162
2166
|
}
|
|
2167
|
+
function previewsPlan(toolRoot, options) {
|
|
2168
|
+
const web = join13(toolRoot, "apps/web");
|
|
2169
|
+
const registry = options.registry ?? "@shadcn";
|
|
2170
|
+
const args = [join13(web, "scripts/capture-discover-thumbs.ts"), "--hub", `http://localhost:${options.port ?? DEFAULT_HUB_PORT}`];
|
|
2171
|
+
if (registry !== "all") args.push("--registry", registry);
|
|
2172
|
+
for (const key2 of ["role", "limit"]) if (options[key2]) args.push(`--${key2}`, options[key2]);
|
|
2173
|
+
if (options.cache) args.push("--cache", resolve7(options.cache));
|
|
2174
|
+
if (options.force) args.push("--force");
|
|
2175
|
+
return { web, args };
|
|
2176
|
+
}
|
|
2177
|
+
async function runPreviews(toolRoot, options) {
|
|
2178
|
+
const plan = previewsPlan(toolRoot, options);
|
|
2179
|
+
await access4(join13(plan.web, "node_modules/playwright-core")).catch(() => {
|
|
2180
|
+
throw new Error(`the hub's dependencies are not installed: run \`pnpm install\` in ${toolRoot}`);
|
|
2181
|
+
});
|
|
2182
|
+
return run6(plan.args, plan.web, {});
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
// ../cli/src/requests.ts
|
|
2186
|
+
function cliNext(brief) {
|
|
2187
|
+
return brief.next.replace(/call request_addressed with what you changed \(file:line\)/, `run youiyoux requests addressed ${brief.id} --message "<what you changed, with file:line>"`).replace(/request_reply/g, `youiyoux requests reply ${brief.id} --message "\u2026"`);
|
|
2188
|
+
}
|
|
2189
|
+
function renderBrief(brief, full = false) {
|
|
2190
|
+
const lines = [
|
|
2191
|
+
`${style.bold(brief.id)} ${brief.kind} ${brief.status === "open" ? style.warn(brief.status) : style.dim(brief.status)} ${brief.route} ${brief.component}${brief.lookalike ? style.dim(" (hand-built lookalike)") : ""}${brief.at ? ` ${brief.at}` : ""}`,
|
|
2192
|
+
` \u201C${brief.ask}\u201D ${style.dim(`\xB7 ${brief.from} \xB7 ${brief.scope}`)}`
|
|
2193
|
+
];
|
|
2194
|
+
if (brief.picture) lines.push(` ${style.dim("picture")} ${brief.picture}${brief.box ? style.dim(` (box ${brief.box.x},${brief.box.y} ${brief.box.width}\xD7${brief.box.height} px)`) : ""}`);
|
|
2195
|
+
for (const entry of full ? brief.thread : brief.thread.slice(-2)) lines.push(` ${style.dim("\xB7")} ${entry}`);
|
|
2196
|
+
if (!full && brief.thread.length > 2) lines.push(style.dim(` \u2026 ${brief.thread.length - 2} earlier in the thread: youiyoux requests show ${brief.id}`));
|
|
2197
|
+
lines.push(` ${style.dim("next")} ${cliNext(brief)}`);
|
|
2198
|
+
return lines.join("\n");
|
|
2199
|
+
}
|
|
2200
|
+
function renderRequests(briefs, status, unreadable) {
|
|
2201
|
+
const lines = briefs.length ? briefs.map((b) => renderBrief(b)) : [`No ${status === "all" ? "" : `${status} `}requests on the screens.`];
|
|
2202
|
+
for (const u of unreadable) lines.push(style.error(`\u2716 ${u.file} is not a youi.request/v1: ${u.reason}`));
|
|
2203
|
+
return lines.join("\n\n");
|
|
2204
|
+
}
|
|
2163
2205
|
|
|
2164
2206
|
// ../cli/src/index-store.ts
|
|
2165
2207
|
import { appendFile, mkdir as mkdir3, readFile as readFile4, stat, rename, mkdtemp as mkdtemp2, rm as rm3 } from "node:fs/promises";
|
|
@@ -2784,7 +2826,7 @@ function scaleTokens(index, file, usage = { count: /* @__PURE__ */ new Map(), by
|
|
|
2784
2826
|
var escape = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2785
2827
|
async function reportTokens(module, tokens, usage) {
|
|
2786
2828
|
if (isShowcase(module.file) || module.lang !== "css" && module.jsx.length === 0) return [];
|
|
2787
|
-
const { parseModule: parseModule2 } = await import("./src-
|
|
2829
|
+
const { parseModule: parseModule2 } = await import("./src-ZS76UD7E.js");
|
|
2788
2830
|
let source = withoutVariables(module.source);
|
|
2789
2831
|
if (module.lang !== "css") {
|
|
2790
2832
|
source = maskFunctions(source, /(?:repeating-)?(?:linear|radial|conic)-gradient\s*\(/gi);
|
|
@@ -4276,6 +4318,15 @@ ${style.bold("Anywhere")} ${style.dim("no design system needed")}
|
|
|
4276
4318
|
<first project>/.youi/inventory.json unless --out, and records the scan
|
|
4277
4319
|
(project, commit, time, counts, families) in the local index for trends
|
|
4278
4320
|
inventory --history every recorded scan per project, newest first, with what changed
|
|
4321
|
+
requests [--status open|addressed|closed|all] [--route r] [--json]
|
|
4322
|
+
comments and change requests people pinned to components on captured
|
|
4323
|
+
screens: what is asked, the file:line, the picture, and what to do next
|
|
4324
|
+
requests show <id> | reply <id> --message <text> | addressed <id> --message <what you changed>
|
|
4325
|
+
read one, reply, or mark it done (as an agent; a person closes it in the hub)
|
|
4326
|
+
screens capture --base <url> [--route r] [--project dir] [--out dir] [--storage-state file] [--json]
|
|
4327
|
+
photograph the routes in <project>/.youi/screens/screens.json, light and
|
|
4328
|
+
dark, from the app running in development at <url>, and place each
|
|
4329
|
+
component on them with the line that rendered it (for youiyoux ui)
|
|
4279
4330
|
render [file|component\u2026] [--base ref] [--json]
|
|
4280
4331
|
see a component you changed: its looks drawn with the project's own code
|
|
4281
4332
|
and CSS in headless Chromium, light and dark at 1280 and 390 px, axe's
|
|
@@ -4347,6 +4398,9 @@ ${style.bold("Discover")} ${style.dim("UI components by need, across shadcn reg
|
|
|
4347
4398
|
and facets (role, source, licence, headless/styled); --all also lists
|
|
4348
4399
|
every other registry, kept apart from the default search
|
|
4349
4400
|
discover show <id|ref> [--source] [--json] one candidate: provenance, licence evidence, dependencies
|
|
4401
|
+
discover previews [--port n] [--registry @shadcn|all] [--role r] [--limit n] [--force]
|
|
4402
|
+
photograph candidates in your theme for the hub's gallery, from a hub
|
|
4403
|
+
running on your project (youiyoux ui --project <dir>)
|
|
4350
4404
|
(cache: --cache, else YOUI_DISCOVER_CACHE, else ~/.cache/youiyoux/discover)
|
|
4351
4405
|
|
|
4352
4406
|
${style.bold("Index")} ${style.dim("the local store of derived data: rebuildable, never the authority")}
|
|
@@ -4439,6 +4493,10 @@ var OPTIONS = {
|
|
|
4439
4493
|
license: { type: "string" },
|
|
4440
4494
|
icons: { type: "boolean" },
|
|
4441
4495
|
source: { type: "boolean" },
|
|
4496
|
+
registry: { type: "string" },
|
|
4497
|
+
"storage-state": { type: "string" },
|
|
4498
|
+
message: { type: "string" },
|
|
4499
|
+
status: { type: "string" },
|
|
4442
4500
|
"max-registries": { type: "string" },
|
|
4443
4501
|
offset: { type: "string" },
|
|
4444
4502
|
history: { type: "boolean", default: false },
|
|
@@ -4877,7 +4935,7 @@ async function cmdUi(values) {
|
|
|
4877
4935
|
async function cmdDetect(values, positionals) {
|
|
4878
4936
|
const target = detectTarget(positionals);
|
|
4879
4937
|
if (!target) throw new UsageError("youiyoux detect <repo-path> or youiyoux detect <url\u2026> [--expose] (one repo, or one or more URLs; not both)");
|
|
4880
|
-
const { repoReport, siteReport, writeReport } = await import("./src-
|
|
4938
|
+
const { repoReport, siteReport, writeReport } = await import("./src-DS43LCRA.js");
|
|
4881
4939
|
const out = resolve12(values.out ?? ".youi/detect");
|
|
4882
4940
|
const report = target.kind === "repo" ? await repoReport(target.path) : await siteReport(target.urls, { out, expose: values.expose, ...process.env.YOUI_CHROMIUM ? { executablePath: process.env.YOUI_CHROMIUM } : {} });
|
|
4883
4941
|
const file = await writeReport(report, out);
|
|
@@ -4903,13 +4961,68 @@ async function cmdRender(values, positionals, io) {
|
|
|
4903
4961
|
return 1;
|
|
4904
4962
|
}
|
|
4905
4963
|
}
|
|
4964
|
+
async function cmdRequests(values, positionals) {
|
|
4965
|
+
const usage = "youiyoux requests [--status open|addressed|closed|all] [--route r] or youiyoux requests show <id> | reply <id> --message <text> | addressed <id> --message <what you changed>";
|
|
4966
|
+
const [action, id, ...rest] = positionals;
|
|
4967
|
+
if (rest.length > 0) throw new UsageError(usage);
|
|
4968
|
+
const { RequestStore, requestBrief } = await import("./src-U5NTDPUX.js");
|
|
4969
|
+
const project2 = await loadProject(resolve12(values.project ?? process.cwd()), loadOptions(values)).catch(() => null);
|
|
4970
|
+
const root = project2?.root ?? resolve12(values.root ?? values.project ?? process.cwd());
|
|
4971
|
+
const store = new RequestStore(root, project2?.config.id ?? basename3(root));
|
|
4972
|
+
const agent = { kind: "agent", name: "youiyoux CLI" };
|
|
4973
|
+
const one = (request) => {
|
|
4974
|
+
const brief = requestBrief(request, root);
|
|
4975
|
+
if (values.json) json(brief);
|
|
4976
|
+
else print(renderBrief(brief, true));
|
|
4977
|
+
return 0;
|
|
4978
|
+
};
|
|
4979
|
+
if (!action || action === "list") {
|
|
4980
|
+
if (id) throw new UsageError(usage);
|
|
4981
|
+
const status = values.status ?? "open";
|
|
4982
|
+
if (!["open", "addressed", "closed", "all"].includes(status)) throw new UsageError("--status takes open, addressed, closed or all");
|
|
4983
|
+
const { requests, unreadable } = await store.list();
|
|
4984
|
+
const briefs = requests.filter((r) => (status === "all" || r.status === status) && (!values.route || r.target.route === values.route)).map((r) => requestBrief(r, root));
|
|
4985
|
+
if (values.json) json({ requests: briefs, unreadable });
|
|
4986
|
+
else print(renderRequests(briefs, status, unreadable));
|
|
4987
|
+
return unreadable.length ? 1 : 0;
|
|
4988
|
+
}
|
|
4989
|
+
if (!id) throw new UsageError(usage);
|
|
4990
|
+
if (action === "show") return one(await store.get(id));
|
|
4991
|
+
if (action === "reply" || action === "addressed") {
|
|
4992
|
+
if (!values.message?.trim()) throw new UsageError(`youiyoux requests ${action} ${id} --message <${action === "reply" ? "text" : "what you changed, with file:line"}>`);
|
|
4993
|
+
return one(action === "reply" ? await store.reply(agent, id, values.message) : await store.setStatus(agent, id, "addressed", values.message));
|
|
4994
|
+
}
|
|
4995
|
+
throw new UsageError(usage);
|
|
4996
|
+
}
|
|
4997
|
+
async function cmdScreens(values, positionals) {
|
|
4998
|
+
if (positionals[0] !== "capture" || positionals.length > 1 || !values.base) throw new UsageError("youiyoux screens capture --base <url of the app in development> [--route <one route>] [--project dir] [--out <screens dir>] [--storage-state <signed-in session>] [--json]");
|
|
4999
|
+
const project2 = await loadProject(resolve12(values.project ?? process.cwd()), loadOptions(values)).catch(() => null);
|
|
5000
|
+
const root = project2?.root ?? resolve12(values.root ?? values.project ?? process.cwd());
|
|
5001
|
+
const dir = resolve12(values.out ?? join22(root, ".youi/screens"));
|
|
5002
|
+
if (!existsSync4(join22(dir, "screens.json"))) {
|
|
5003
|
+
process.stderr.write(`${style.error("\u2716")} no screens.json in ${dir}: list the routes to capture there, as {"schema":"youiyoux.screens/v1","project":"<name>","source":"<what the app is>","capturedAt":"","viewport":{"width":1440,"height":900},"screens":[{"route":"/","path":"/"}]}
|
|
5004
|
+
`);
|
|
5005
|
+
return 1;
|
|
5006
|
+
}
|
|
5007
|
+
const { launchBrowser } = await import("./src-DS43LCRA.js");
|
|
5008
|
+
const browser = await launchBrowser(process.env.YOUI_CHROMIUM, { purpose: { what: "youiyoux screens capture", command: "youiyoux screens capture" } });
|
|
5009
|
+
try {
|
|
5010
|
+
const report = await captureScreens(dir, { base: values.base, root, browser, ...values.route ? { routes: [values.route] } : {}, ...values["storage-state"] ? { storageState: resolve12(values["storage-state"]) } : {}, log: (line) => process.stderr.write(`${style.dim(line)}
|
|
5011
|
+
`) });
|
|
5012
|
+
if (values.json) json(report);
|
|
5013
|
+
else print(captureText(report));
|
|
5014
|
+
return report.screens.every((s) => s.error) ? 1 : 0;
|
|
5015
|
+
} finally {
|
|
5016
|
+
await browser.close();
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
4906
5019
|
async function cmdReport(values, positionals, io) {
|
|
4907
5020
|
if (positionals.length > 1) throw new UsageError("youiyoux report [path] [--out dir] [--render [--yes]] [--include-code] [--json] (one repo)");
|
|
4908
5021
|
const result = await runReport({ ...positionals[0] ? { path: positionals[0] } : {}, ...values.out ? { out: values.out } : {}, render: values.render, yes: values.yes, includeCode: values["include-code"], json: values.json }, io.report ?? {});
|
|
4909
5022
|
return result.code;
|
|
4910
5023
|
}
|
|
4911
5024
|
async function cmdMcp(values) {
|
|
4912
|
-
const { startStdioServer } = await import("./src-
|
|
5025
|
+
const { startStdioServer } = await import("./src-YGEZCUAO.js");
|
|
4913
5026
|
await startStdioServer({ projectRoot: values.project ?? process.cwd(), ...loadOptions(values), ...values.cache ? { discoverCache: values.cache } : {} });
|
|
4914
5027
|
return -1;
|
|
4915
5028
|
}
|
|
@@ -4941,6 +5054,11 @@ async function cmdDiscover(values, positionals, io) {
|
|
|
4941
5054
|
${style.dim(`store \u2192 ${storeLocation({ path })} (${plural(loaded.chosen, "listing")})`)}`);
|
|
4942
5055
|
return 0;
|
|
4943
5056
|
}
|
|
5057
|
+
if (action === "previews") {
|
|
5058
|
+
if (rest.length > 0) throw new UsageError("youiyoux discover previews [--port n] [--registry @shadcn|all] [--role r] [--limit n] [--force]");
|
|
5059
|
+
positiveInt(values.limit, "--limit");
|
|
5060
|
+
return runPreviews(TOOL_ROOT, { ...values.port ? { port: values.port } : {}, ...values.registry ? { registry: values.registry } : {}, ...values.role ? { role: values.role } : {}, ...values.limit ? { limit: values.limit } : {}, ...values.cache ? { cache: values.cache } : {}, force: values.force });
|
|
5061
|
+
}
|
|
4944
5062
|
if (action === "show") {
|
|
4945
5063
|
if (!rest[0]) throw new UsageError("youiyoux discover show <id|ref>");
|
|
4946
5064
|
if (values.source) {
|
|
@@ -4987,6 +5105,8 @@ var COMMANDS = {
|
|
|
4987
5105
|
index: cmdIndex,
|
|
4988
5106
|
report: cmdReport,
|
|
4989
5107
|
render: cmdRender,
|
|
5108
|
+
screens: cmdScreens,
|
|
5109
|
+
requests: cmdRequests,
|
|
4990
5110
|
detect: cmdDetect,
|
|
4991
5111
|
build: cmdBuild,
|
|
4992
5112
|
parity: cmdParity,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
external_exports,
|
|
7
7
|
sha256,
|
|
8
8
|
writeFileAtomic
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-C3TSTYP7.js";
|
|
10
10
|
|
|
11
11
|
// ../discover/src/aliases.ts
|
|
12
12
|
var CONCEPTS = [
|
|
@@ -112,7 +112,7 @@ function cleanData(value) {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
// ../discover/src/sources.ts
|
|
115
|
-
var CURATED = ["@coss", "@kibo-ui", "@magicui", "@
|
|
115
|
+
var CURATED = ["@coss", "@kibo-ui", "@magicui", "@aceternity"];
|
|
116
116
|
var SHADCN = {
|
|
117
117
|
name: "@shadcn",
|
|
118
118
|
homepage: "https://ui.shadcn.com",
|
|
@@ -1796,7 +1796,7 @@ function showCandidate(index, query) {
|
|
|
1796
1796
|
|
|
1797
1797
|
// ../discover/src/signals.ts
|
|
1798
1798
|
var HOUR = 36e5;
|
|
1799
|
-
var SIGNAL_TTL = { npmMs: 24 * HOUR, githubMs: 7 * 24 * HOUR, registryRepoMs: 30 * 24 * HOUR };
|
|
1799
|
+
var SIGNAL_TTL = { npmMs: 24 * HOUR, githubMs: 7 * 24 * HOUR, registryRepoMs: 30 * 24 * HOUR, registryRepoMissMs: 24 * HOUR };
|
|
1800
1800
|
function defaultBudgets(token) {
|
|
1801
1801
|
return token ? { npmPackages: 400, githubRepos: 600, githubSearches: 30 } : { npmPackages: 200, githubRepos: 50, githubSearches: 10 };
|
|
1802
1802
|
}
|
|
@@ -1823,6 +1823,34 @@ function sameHomepage(a, b) {
|
|
|
1823
1823
|
const ka = key(a);
|
|
1824
1824
|
return ka !== null && ka === key(b);
|
|
1825
1825
|
}
|
|
1826
|
+
var PATH_TENANTS = /* @__PURE__ */ new Set(["github.com", "gitlab.com", "bitbucket.org", "codeberg.org", "npmjs.com", "codesandbox.io", "stackblitz.com", "gitbook.io", "medium.com", "notion.site"]);
|
|
1827
|
+
function sameSite(repository, registry) {
|
|
1828
|
+
const parts = (value) => {
|
|
1829
|
+
try {
|
|
1830
|
+
const url = new URL(value.includes("://") ? value : `https://${value}`);
|
|
1831
|
+
return { host: url.hostname.replace(/^www\./, "").toLowerCase(), path: url.pathname.replace(/\/+$/, "").toLowerCase() };
|
|
1832
|
+
} catch {
|
|
1833
|
+
return null;
|
|
1834
|
+
}
|
|
1835
|
+
};
|
|
1836
|
+
if (!repository || !registry) return false;
|
|
1837
|
+
const repo = parts(repository);
|
|
1838
|
+
const home = parts(registry);
|
|
1839
|
+
if (!repo || !home || repo.host !== home.host) return false;
|
|
1840
|
+
if (PATH_TENANTS.has(repo.host)) return repo.path === home.path && repo.path !== "";
|
|
1841
|
+
return repo.path === "" || home.path === repo.path || home.path.startsWith(`${repo.path}/`);
|
|
1842
|
+
}
|
|
1843
|
+
var NOT_OWNERS = /* @__PURE__ */ new Set(["about", "apps", "collections", "contact", "enterprise", "explore", "features", "login", "marketplace", "orgs", "pricing", "settings", "site", "sponsors", "topics"]);
|
|
1844
|
+
function linkedRepos(html) {
|
|
1845
|
+
const names = [];
|
|
1846
|
+
for (const match of html.matchAll(/https?:\/\/(?:www\.)?github\.com\/([A-Za-z0-9-]+)\/([A-Za-z0-9_.-]+)/g)) {
|
|
1847
|
+
const owner = match[1];
|
|
1848
|
+
const repo = match[2].replace(/\.git$/, "").replace(/\.+$/, "");
|
|
1849
|
+
if (NOT_OWNERS.has(owner.toLowerCase()) || !repo || repo.startsWith(".")) continue;
|
|
1850
|
+
names.push(`${owner}/${repo}`);
|
|
1851
|
+
}
|
|
1852
|
+
return byUse(names);
|
|
1853
|
+
}
|
|
1826
1854
|
var GithubRepoBody = external_exports.object({
|
|
1827
1855
|
full_name: external_exports.string(),
|
|
1828
1856
|
html_url: external_exports.string(),
|
|
@@ -1886,9 +1914,19 @@ async function refreshSignals(entries, registries, previous, client, now, budget
|
|
|
1886
1914
|
npm[name] = { weeklyDownloads: typeof count2 === "number" ? count2 : null, license: spdxOrNull(meta?.license), repo: githubRepo(typeof repository === "string" ? repository : null), fetchedAt: at };
|
|
1887
1915
|
});
|
|
1888
1916
|
registryRepos[SHADCN.name] = { repo: SHADCN.repo, checkedAt: at };
|
|
1889
|
-
const
|
|
1890
|
-
|
|
1891
|
-
|
|
1917
|
+
const known = (name) => {
|
|
1918
|
+
const prior = registryRepos[name];
|
|
1919
|
+
return fresh(prior?.checkedAt, prior?.repo ? SIGNAL_TTL.registryRepoMs : SIGNAL_TTL.registryRepoMissMs, now);
|
|
1920
|
+
};
|
|
1921
|
+
const unsearched = [...registries].filter((r) => r.name !== SHADCN.name && r.homepage && !known(r.name)).sort((a, b) => b.items - a.items || a.name.localeCompare(b.name));
|
|
1922
|
+
const spend = { repoCalls: budgets.githubRepos };
|
|
1923
|
+
for (const registry of unsearched) {
|
|
1924
|
+
const linked = await homepageRepo(registry.homepage, client, github, at, report, spend);
|
|
1925
|
+
if (linked) {
|
|
1926
|
+
registryRepos[registry.name] = { repo: linked, checkedAt: at };
|
|
1927
|
+
continue;
|
|
1928
|
+
}
|
|
1929
|
+
if (report.github.searches >= budgets.githubSearches || !client.hasBudget("github-search")) continue;
|
|
1892
1930
|
const query = `${sourceSlug(registry.name).replace(/-ui$/, "")} in:name`;
|
|
1893
1931
|
const result = await client.json(`https://api.github.com/search/repositories?q=${encodeURIComponent(query)}&per_page=10`);
|
|
1894
1932
|
report.github.searches++;
|
|
@@ -1915,7 +1953,7 @@ async function refreshSignals(entries, registries, previous, client, now, budget
|
|
|
1915
1953
|
}
|
|
1916
1954
|
return true;
|
|
1917
1955
|
});
|
|
1918
|
-
const repoTodo = repoStale.slice(0,
|
|
1956
|
+
const repoTodo = repoStale.slice(0, spend.repoCalls);
|
|
1919
1957
|
await pool(repoTodo, async (repo) => {
|
|
1920
1958
|
if (!client.hasBudget("github-core")) return;
|
|
1921
1959
|
const result = await client.json(`https://api.github.com/repos/${repo}`);
|
|
@@ -1931,12 +1969,35 @@ async function refreshSignals(entries, registries, previous, client, now, budget
|
|
|
1931
1969
|
report.github.failed++;
|
|
1932
1970
|
return;
|
|
1933
1971
|
}
|
|
1934
|
-
|
|
1935
|
-
github[repo] = { found: true, repo: body.full_name, htmlUrl: body.html_url, stars: body.stargazers_count, pushedAt: body.pushed_at, archived: body.archived, spdx: spdxOrNull(body.license?.spdx_id), fetchedAt: at };
|
|
1972
|
+
github[repo] = githubSignal(parsed.data, at);
|
|
1936
1973
|
});
|
|
1937
1974
|
report.github.leftUnknown = repos.filter((repo) => !github[repo]).length;
|
|
1938
1975
|
return { signals: { npm, github, registryRepos }, report };
|
|
1939
1976
|
}
|
|
1977
|
+
function githubSignal(body, at) {
|
|
1978
|
+
return { found: true, repo: body.full_name, htmlUrl: body.html_url, stars: body.stargazers_count, pushedAt: body.pushed_at, archived: body.archived, spdx: spdxOrNull(body.license?.spdx_id), fetchedAt: at };
|
|
1979
|
+
}
|
|
1980
|
+
var HOMEPAGE_REPOS = 3;
|
|
1981
|
+
async function homepageRepo(homepage, client, github, at, report, spend) {
|
|
1982
|
+
const page = await client.get(homepage, "text/html");
|
|
1983
|
+
client.cache.delete(homepage);
|
|
1984
|
+
if (!page.ok) return null;
|
|
1985
|
+
for (const repo of linkedRepos(page.body).slice(0, HOMEPAGE_REPOS)) {
|
|
1986
|
+
if (spend.repoCalls <= 0 || !client.hasBudget("github-core")) return null;
|
|
1987
|
+
spend.repoCalls--;
|
|
1988
|
+
const result = await client.json(`https://api.github.com/repos/${repo}`);
|
|
1989
|
+
report.github.looked++;
|
|
1990
|
+
if (!result.ok) {
|
|
1991
|
+
if (result.reason === "rate-limited") report.github.rateLimited = true;
|
|
1992
|
+
continue;
|
|
1993
|
+
}
|
|
1994
|
+
const parsed = GithubRepoBody.safeParse(result.value);
|
|
1995
|
+
if (!parsed.success || !sameSite(parsed.data.homepage, homepage)) continue;
|
|
1996
|
+
github[parsed.data.full_name] = githubSignal(parsed.data, at);
|
|
1997
|
+
return parsed.data.full_name;
|
|
1998
|
+
}
|
|
1999
|
+
return null;
|
|
2000
|
+
}
|
|
1940
2001
|
function repoOf(entry, signals) {
|
|
1941
2002
|
const registry = registryOf(entry);
|
|
1942
2003
|
if (registry) return signals.registryRepos[registry]?.repo ?? null;
|
|
@@ -2086,6 +2147,8 @@ async function syncIndex(options) {
|
|
|
2086
2147
|
else if (options.maxRegistries !== void 0 && toFetch.length >= options.maxRegistries) sources.push({ id: registry.name, url: registryUrl(registry.template), outcome: "skipped", reason: "over --max-registries", httpStatus: null, items: 0, health: healthOf(registry) });
|
|
2087
2148
|
else toFetch.push(registry);
|
|
2088
2149
|
}
|
|
2150
|
+
const missing = directory2.ok ? selected.filter((name) => !listed.some((r) => r.name === name)) : [];
|
|
2151
|
+
for (const name of missing) sources.push({ id: name, url: SHADCN.directory, outcome: "skipped", reason: "not in the registry directory", httpStatus: null, items: 0, health: null });
|
|
2089
2152
|
const community = await Promise.all(
|
|
2090
2153
|
toFetch.map(async (registry) => {
|
|
2091
2154
|
const url = registryUrl(registry.template);
|
|
@@ -2147,7 +2210,7 @@ async function syncIndex(options) {
|
|
|
2147
2210
|
catalogBytes: await catalogBytes(options.cacheDir),
|
|
2148
2211
|
selectedSources: selected.length,
|
|
2149
2212
|
index: { bytes: Buffer.byteLength(JSON.stringify(index) + "\n"), entries: final.length, mirrorsCollapsed, iconRegistriesSkipped: sources.filter((s) => s.reason === iconReason).length },
|
|
2150
|
-
warnings: client.warnings,
|
|
2213
|
+
warnings: [...client.warnings, ...missing.map((name) => `${name} is chosen but the registry directory no longer lists it: \`youiyoux discover sources remove ${name}\``)],
|
|
2151
2214
|
builtAt,
|
|
2152
2215
|
durationMs: Math.round(performance.now() - started),
|
|
2153
2216
|
entries: { total: final.length, official: final.filter((e) => e.source.ref?.startsWith(`${SHADCN.name}/`)).length, community: final.filter((e) => e.source.kind === "shadcn-registry" && !e.source.ref?.startsWith(`${SHADCN.name}/`)).length, npm: final.filter((e) => e.source.kind === "npm").length },
|
|
@@ -2706,6 +2769,8 @@ export {
|
|
|
2706
2769
|
keyPackage,
|
|
2707
2770
|
registryOf,
|
|
2708
2771
|
sameHomepage,
|
|
2772
|
+
sameSite,
|
|
2773
|
+
linkedRepos,
|
|
2709
2774
|
refreshSignals,
|
|
2710
2775
|
applySignals,
|
|
2711
2776
|
dedupe,
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { createRequire as __youiRequire } from "node:module"; const require = __youiRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_FILES,
|
|
4
|
+
DRAFT_ID,
|
|
5
|
+
DesignFiles,
|
|
6
|
+
FileStore,
|
|
7
|
+
GitError,
|
|
8
|
+
JsonEditError,
|
|
9
|
+
MAX_FINDINGS,
|
|
10
|
+
MAX_LISTED,
|
|
11
|
+
MAX_TITLE,
|
|
12
|
+
MemoryStore,
|
|
13
|
+
REQUESTS_DIR,
|
|
14
|
+
RequestStore,
|
|
15
|
+
RuleWorkflow,
|
|
16
|
+
SESSION_HEADER,
|
|
17
|
+
WORKFLOW_VERSION,
|
|
18
|
+
WorkflowError,
|
|
19
|
+
adoptionRefusal,
|
|
20
|
+
authorize,
|
|
21
|
+
branchTip,
|
|
22
|
+
changesDigest,
|
|
23
|
+
comparePreview,
|
|
24
|
+
componentChanges,
|
|
25
|
+
contentDigest,
|
|
26
|
+
createHandler,
|
|
27
|
+
createReviewBranch,
|
|
28
|
+
defaultBranch,
|
|
29
|
+
deleteJsonPath,
|
|
30
|
+
describeContrast,
|
|
31
|
+
describeLibrary,
|
|
32
|
+
describeStyle,
|
|
33
|
+
draftStatus,
|
|
34
|
+
effectiveStateEdits,
|
|
35
|
+
effectiveTokenEdits,
|
|
36
|
+
emptyStyleContent,
|
|
37
|
+
fieldsFromRule,
|
|
38
|
+
git,
|
|
39
|
+
hasChanges,
|
|
40
|
+
headCommit,
|
|
41
|
+
isAncestor,
|
|
42
|
+
libraryDigest,
|
|
43
|
+
libraryPath,
|
|
44
|
+
librarySlug,
|
|
45
|
+
listAt,
|
|
46
|
+
listTreeAt,
|
|
47
|
+
locate,
|
|
48
|
+
newContrastFailures,
|
|
49
|
+
newRuleFields,
|
|
50
|
+
normalizeLibraryContent,
|
|
51
|
+
normalizeStyleContent,
|
|
52
|
+
previewStyle,
|
|
53
|
+
previewSummary,
|
|
54
|
+
readAt,
|
|
55
|
+
readJsonPath,
|
|
56
|
+
renderContract,
|
|
57
|
+
renderContractStates,
|
|
58
|
+
renderLibraryEntry,
|
|
59
|
+
renderRuleYaml,
|
|
60
|
+
renderTokenEdits,
|
|
61
|
+
requestBrief,
|
|
62
|
+
scannerExecution,
|
|
63
|
+
serveWorkflow,
|
|
64
|
+
setJsonPath,
|
|
65
|
+
styleDigest,
|
|
66
|
+
styleSlug,
|
|
67
|
+
toRuleSpec,
|
|
68
|
+
tokenPathOf,
|
|
69
|
+
validateContent,
|
|
70
|
+
validateLibraryContent,
|
|
71
|
+
validateStyleContent
|
|
72
|
+
} from "./chunk-OIHNEGWH.js";
|
|
73
|
+
import "./chunk-L5BV4PI7.js";
|
|
74
|
+
import "./chunk-S7UV34H5.js";
|
|
75
|
+
import "./chunk-C3TSTYP7.js";
|
|
76
|
+
import "./chunk-E4HNK7VF.js";
|
|
77
|
+
export {
|
|
78
|
+
DEFAULT_FILES,
|
|
79
|
+
DRAFT_ID,
|
|
80
|
+
DesignFiles,
|
|
81
|
+
RuleWorkflow as DesignWorkflow,
|
|
82
|
+
FileStore,
|
|
83
|
+
GitError,
|
|
84
|
+
JsonEditError,
|
|
85
|
+
MAX_FINDINGS,
|
|
86
|
+
MAX_LISTED,
|
|
87
|
+
MAX_TITLE,
|
|
88
|
+
MemoryStore,
|
|
89
|
+
REQUESTS_DIR,
|
|
90
|
+
RequestStore,
|
|
91
|
+
RuleWorkflow,
|
|
92
|
+
SESSION_HEADER,
|
|
93
|
+
WORKFLOW_VERSION,
|
|
94
|
+
WorkflowError,
|
|
95
|
+
adoptionRefusal,
|
|
96
|
+
authorize,
|
|
97
|
+
branchTip,
|
|
98
|
+
changesDigest,
|
|
99
|
+
comparePreview,
|
|
100
|
+
componentChanges,
|
|
101
|
+
contentDigest,
|
|
102
|
+
createHandler,
|
|
103
|
+
createReviewBranch,
|
|
104
|
+
defaultBranch,
|
|
105
|
+
deleteJsonPath,
|
|
106
|
+
describeContrast,
|
|
107
|
+
describeLibrary,
|
|
108
|
+
describeStyle,
|
|
109
|
+
draftStatus,
|
|
110
|
+
effectiveStateEdits,
|
|
111
|
+
effectiveTokenEdits,
|
|
112
|
+
emptyStyleContent,
|
|
113
|
+
fieldsFromRule,
|
|
114
|
+
git,
|
|
115
|
+
hasChanges,
|
|
116
|
+
headCommit,
|
|
117
|
+
isAncestor,
|
|
118
|
+
libraryDigest,
|
|
119
|
+
libraryPath,
|
|
120
|
+
librarySlug,
|
|
121
|
+
listAt,
|
|
122
|
+
listTreeAt,
|
|
123
|
+
locate,
|
|
124
|
+
newContrastFailures,
|
|
125
|
+
newRuleFields,
|
|
126
|
+
normalizeLibraryContent,
|
|
127
|
+
normalizeStyleContent,
|
|
128
|
+
previewStyle,
|
|
129
|
+
previewSummary,
|
|
130
|
+
readAt,
|
|
131
|
+
readJsonPath,
|
|
132
|
+
renderContract,
|
|
133
|
+
renderContractStates,
|
|
134
|
+
renderLibraryEntry,
|
|
135
|
+
renderRuleYaml,
|
|
136
|
+
renderTokenEdits,
|
|
137
|
+
requestBrief,
|
|
138
|
+
scannerExecution,
|
|
139
|
+
serveWorkflow,
|
|
140
|
+
setJsonPath,
|
|
141
|
+
styleDigest,
|
|
142
|
+
styleSlug,
|
|
143
|
+
toRuleSpec,
|
|
144
|
+
tokenPathOf,
|
|
145
|
+
validateContent,
|
|
146
|
+
validateLibraryContent,
|
|
147
|
+
validateStyleContent
|
|
148
|
+
};
|