@estiva-app/ui 0.21.1 → 0.23.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/README.md +21 -0
- package/dist/Avatar.d.ts +3 -0
- package/dist/Avatar.d.ts.map +1 -1
- package/dist/Banner.d.ts +20 -2
- package/dist/Banner.d.ts.map +1 -1
- package/dist/ChipInput.d.ts +3 -0
- package/dist/ChipInput.d.ts.map +1 -1
- package/dist/CommandPalette.d.ts +6 -0
- package/dist/CommandPalette.d.ts.map +1 -1
- package/dist/ContainerHeader.d.ts +25 -0
- package/dist/ContainerHeader.d.ts.map +1 -0
- package/dist/EmptyState.d.ts +10 -1
- package/dist/EmptyState.d.ts.map +1 -1
- package/dist/IdentityMenu.d.ts +3 -0
- package/dist/IdentityMenu.d.ts.map +1 -1
- package/dist/Menu.d.ts +7 -0
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Skeleton.d.ts +2 -0
- package/dist/Skeleton.d.ts.map +1 -1
- package/dist/Toast.d.ts +5 -0
- package/dist/Toast.d.ts.map +1 -1
- package/dist/Toolbar.d.ts +4 -0
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Tooltip.d.ts +4 -0
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/gates/app-checks.d.ts.map +1 -1
- package/dist/gates/{chunk-ZGJ2J5NU.js → chunk-EA33NP5B.js} +275 -11
- package/dist/gates/chunk-EA33NP5B.js.map +7 -0
- package/dist/gates/{chunk-AUXD4GCY.js → chunk-GTQZEHPC.js} +15 -1
- package/dist/gates/chunk-GTQZEHPC.js.map +7 -0
- package/dist/gates/cli.js +1 -1
- package/dist/gates/create-app.d.ts +2 -0
- package/dist/gates/create-app.d.ts.map +1 -1
- package/dist/gates/create-app.js +1 -1
- package/dist/gates/index.js +25 -3
- package/dist/gates/index.js.map +2 -2
- package/dist/gates/status.d.ts +2 -0
- package/dist/gates/status.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +69 -48
- package/dist/index.js.map +4 -4
- package/dist/registry/app-DQI6WLHR.js +10 -0
- package/dist/registry/app-DQI6WLHR.js.map +7 -0
- package/dist/registry/app.d.ts +21 -0
- package/dist/registry/app.d.ts.map +1 -0
- package/dist/registry/build-LGFCCOLR.js +27 -0
- package/dist/registry/build-LGFCCOLR.js.map +7 -0
- package/dist/registry/build.d.ts +95 -0
- package/dist/registry/build.d.ts.map +1 -0
- package/dist/registry/chunk-E4JNV7PC.js +155 -0
- package/dist/registry/chunk-E4JNV7PC.js.map +7 -0
- package/dist/registry/chunk-NJN4MQAM.js +397 -0
- package/dist/registry/chunk-NJN4MQAM.js.map +7 -0
- package/dist/registry/chunk-W2B2G7OE.js +188 -0
- package/dist/registry/chunk-W2B2G7OE.js.map +7 -0
- package/dist/registry/chunk-WMFF3MPP.js +648 -0
- package/dist/registry/chunk-WMFF3MPP.js.map +7 -0
- package/dist/registry/cli.d.ts +2 -0
- package/dist/registry/cli.d.ts.map +1 -0
- package/dist/registry/cli.js +176 -0
- package/dist/registry/cli.js.map +7 -0
- package/dist/registry/find.d.ts +54 -0
- package/dist/registry/find.d.ts.map +1 -0
- package/dist/registry/index.d.ts +17 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +34 -0
- package/dist/registry/index.js.map +7 -0
- package/dist/registry/schema.d.ts +224 -0
- package/dist/registry/schema.d.ts.map +1 -0
- package/package.json +15 -2
- package/registry.json +4615 -0
- package/src/Avatar.tsx +3 -0
- package/src/Banner.mdx +17 -4
- package/src/Banner.stories.tsx +22 -0
- package/src/Banner.test.tsx +35 -0
- package/src/Banner.tsx +34 -9
- package/src/ChipInput.tsx +3 -0
- package/src/CommandPalette.tsx +6 -0
- package/src/ContainerHeader.mdx +56 -0
- package/src/ContainerHeader.stories.tsx +62 -0
- package/src/ContainerHeader.test.tsx +47 -0
- package/src/ContainerHeader.tsx +45 -0
- package/src/EmptyState.mdx +12 -0
- package/src/EmptyState.stories.tsx +6 -1
- package/src/EmptyState.test.tsx +18 -1
- package/src/EmptyState.tsx +14 -1
- package/src/IdentityMenu.tsx +3 -0
- package/src/Menu.tsx +7 -0
- package/src/Skeleton.tsx +2 -0
- package/src/Toast.tsx +5 -0
- package/src/Toolbar.tsx +4 -0
- package/src/Tooltip.tsx +4 -0
- package/src/gates/app-checks.ts +23 -1
- package/src/gates/create-app.test.ts +77 -6
- package/src/gates/create-app.ts +288 -15
- package/src/gates/status.ts +16 -0
- package/src/index.ts +1 -0
- package/src/registry/app.test.ts +562 -0
- package/src/registry/app.ts +854 -0
- package/src/registry/build.ts +679 -0
- package/src/registry/cli.ts +204 -0
- package/src/registry/find.ts +232 -0
- package/src/registry/index.ts +31 -0
- package/src/registry/registry.test.ts +448 -0
- package/src/registry/schema.ts +419 -0
- package/dist/gates/chunk-AUXD4GCY.js.map +0 -7
- package/dist/gates/chunk-ZGJ2J5NU.js.map +0 -7
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/registry/app.ts"],
|
|
4
|
+
"sourcesContent": ["/// <reference types=\"node\" />\n/**\n * An app's catalogue (UIG-13): every part in an app's own code, what it is for,\n * where it is used, and which of four kinds it is.\n *\n * **Built fresh, never committed** (Katerina, 18 September 2026). The package is\n * public and Peek and Ship are private, so an app's catalogue lives nowhere but\n * in its own code: `estiva-ui find` and `estiva-ui check` build it each time,\n * which takes about a second, and `estiva-ui build` writes it to a file only\n * when asked. A file that is never kept can never drift.\n *\n * **A file is not a part, and a folder says nothing.** Peek's `components/ui`\n * holds one-line pass-ons beside 187-line components, one file can hold six\n * parts, and a part can draw nothing at all (a provider, a listener). So the\n * target set is every name an app's `.tsx` files export that is a part: a\n * function that draws, or a name drawn as a tag somewhere in the app. The kind\n * is read from the code, and only from the code:\n *\n * - **re-export** \u2014 its file only hands a package part on.\n * - **one-off** \u2014 one file of the app uses it.\n * - **reusable** \u2014 two or more do.\n * - **promote-candidate** \u2014 two or more do, and everything it uses is already in\n * the package, so it could move there as it is. Katerina rules on each.\n * - **unused** \u2014 no file of the app uses it; its stories or tests may.\n *\n * Where the count is wrong \u2014 a general part only one screen uses yet \u2014 a person\n * writes the kind beside the part, with the reason, and the catalogue shows it:\n *\n * /**\n * * A timeline of what happened to a thing.\n * * @registry reusable: general; one screen uses it so far\n * *\\/\n *\n * TypeScript is the app's own install, as it is for the package's builder.\n */\nimport { existsSync, readFileSync, readdirSync, statSync } from 'node:fs'\nimport { basename, dirname, extname, join, relative, resolve, sep } from 'node:path'\nimport ts from 'typescript'\nimport { firstSentence, pageOpening, readModule, sanitize, toId, PACKAGE_IMPORT, type Resolved } from './build'\nimport { SCHEMA_VERSION, type AppFacts, type EntryClass, type FileWithoutPart, type Registry, type RegistryEntry } from './schema'\n\nexport interface AppBuildOptions {\n /** The app's folder: where its `package.json` and `src/` are. Ship's is `web`. */\n root?: string\n /** The name its entries are recorded under \u2014 `peek`, `ship`. Defaults to the app's package name. */\n repo?: string\n /** The package's own catalogue, for the parts an app part shares a name with. Defaults to the one this builder ships beside. */\n packageRegistry?: Registry | null\n /** The packages the package itself depends on. An import of one never ties a part to its app. Defaults to the package's own. */\n packageDependencies?: string[]\n}\n\n/** The kinds a person may write beside a part. A pass-on is a fact about its file; so is being used nowhere. */\nconst WRITABLE: EntryClass[] = ['reusable', 'one-off', 'promote-candidate']\nconst WRITTEN = /^@registry\\s+([a-z-]+)\\s*:\\s*(.+)$/m\n\nconst isStory = (file: string) => /\\.stories\\.[cm]?[jt]sx?$/.test(file)\nconst isTest = (file: string) => /\\.(test|spec)\\.[cm]?[jt]sx?$/.test(file) || /(^|\\/)__(tests|mocks)__\\//.test(file)\nconst isPascal = (name: string) => /^[A-Z][A-Za-z0-9]*$/.test(name) && !/^[A-Z0-9_]+$/.test(name)\n/**\n * What a dynamic `import('./x')` takes from its file. Written as\n * `import('./Settings').then((m) => ({ default: m.SettingsPage }))`, only the names\n * read off the module; otherwise the whole module (`*`), whose default a caller\n * then takes.\n */\nfunction pickedFrom(call: ts.CallExpression): { imported: string; local: string }[] {\n const then = call.parent\n const invoked = then?.parent\n if (then && ts.isPropertyAccessExpression(then) && then.name.text === 'then' && invoked && ts.isCallExpression(invoked)) {\n const callback = invoked.arguments[0]\n const param = callback && (ts.isArrowFunction(callback) || ts.isFunctionExpression(callback)) ? callback.parameters[0]?.name : undefined\n if (param && ts.isIdentifier(param)) {\n const names = new Set<string>()\n const visit = (n: ts.Node) => {\n if (ts.isPropertyAccessExpression(n) && ts.isIdentifier(n.expression) && n.expression.text === param.text) names.add(n.name.text)\n ts.forEachChild(n, visit)\n }\n visit(callback)\n if (names.size) return [...names].map((imported) => ({ imported, local: '(dynamic)' }))\n }\n }\n return [{ imported: '*', local: '(dynamic)' }]\n}\n\n/**\n * `export default memo(TopicRow)`: the default is TopicRow, wrapped. A call on\n * a name, with no function written into it, hands that name out, so the export\n * is read as if it named it \u2014 one part, whose comment and props are its own.\n */\nfunction unwrapDefault<T extends { isDefault: boolean; local: string | null; node: ts.Node | null }>(ex: T): T {\n if (!ex.isDefault || ex.local || !ex.node || !ts.isExpression(ex.node)) return ex\n const name = handedOut(ex.node)\n return name ? { ...ex, local: name, node: null } : ex\n}\n\n/**\n * The name an `export default \u2026` hands out, under whatever it is wrapped in:\n * `memo(forwardRef(Row))`, `Row as ComponentType`, `Row satisfies FC`,\n * `styled(Row)\\`\u2026\\``. `null` when what is exported is written right there.\n */\nfunction handedOut(expression: ts.Expression): string | null {\n let e: ts.Expression = expression\n for (;;) {\n if (ts.isIdentifier(e)) return e.text\n if (ts.isParenthesizedExpression(e) || ts.isAsExpression(e) || ts.isSatisfiesExpression(e) || ts.isNonNullExpression(e) || ts.isTypeAssertionExpression(e)) e = e.expression\n else if (ts.isTaggedTemplateExpression(e)) e = e.tag\n else if (ts.isCallExpression(e) && e.arguments[0] && !e.arguments.some((a) => ts.isArrowFunction(a) || ts.isFunctionExpression(a))) e = e.arguments[0]\n else return null\n }\n}\n\n/** `memo-page` \u2192 `MemoPage`, `topic_view` \u2192 `TopicView`. */\nconst pascalOf = (stem: string) => stem.split(/[^A-Za-z0-9]+/).filter(Boolean).map((word) => word[0].toUpperCase() + word.slice(1)).join('')\n/** A default with no name of its own takes its file's \u2014 or, for `settings/index.tsx`, its folder's. */\nconst defaultNameOf = (file: string) => {\n const stem = basename(file, extname(file))\n return pascalOf(stem === 'index' ? basename(dirname(file)) : stem)\n}\nconst CODE = ['.tsx', '.ts', '.jsx', '.js', '.mts', '.cts']\n\n/** `@scope/name/sub` \u2192 `@scope/name`; `name/sub` \u2192 `name`. */\nfunction packageOf(specifier: string): string {\n const parts = specifier.split('/')\n return specifier.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0]\n}\n\n/** What the package this builder belongs to depends on, and its catalogue. Read from beside the builder. */\nfunction packageSelf(): { dependencies: string[]; registry: Registry | null } {\n const at = (rel: string) => new URL(rel, import.meta.url)\n const manifest = JSON.parse(readFileSync(at('../../package.json'), 'utf8')) as { name: string; dependencies?: Record<string, string>; peerDependencies?: Record<string, string> }\n const registryUrl = at('../../registry.json')\n const registry = existsSync(registryUrl) ? (JSON.parse(readFileSync(registryUrl, 'utf8')) as Registry) : null\n return { dependencies: [manifest.name, ...Object.keys(manifest.dependencies ?? {}), ...Object.keys(manifest.peerDependencies ?? {})], registry }\n}\n\n/**\n * The import aliases an app's `tsconfig*.json` files declare \u2014 `@/*` \u2192\n * `<root>/src/*` \u2014 and the `baseUrl` folders a bare `src/Card` is read from.\n */\nfunction readAliases(root: string): { aliases: { prefix: string; target: string }[]; bases: string[] } {\n const aliases: { prefix: string; target: string }[] = []\n const bases: string[] = []\n for (const name of readdirSync(root).filter((file) => /^tsconfig.*\\.json$/.test(file)).sort()) {\n const read = ts.readConfigFile(join(root, name), ts.sys.readFile)\n const options = (read.config?.compilerOptions ?? {}) as { paths?: Record<string, string[]>; baseUrl?: string }\n const base = resolve(root, options.baseUrl ?? '.')\n if (options.baseUrl !== undefined && !bases.includes(base)) bases.push(base)\n for (const [pattern, targets] of Object.entries(options.paths ?? {})) {\n if (!pattern.endsWith('/*') || !targets[0]?.endsWith('/*')) continue\n const prefix = pattern.slice(0, -1)\n if (!aliases.some((alias) => alias.prefix === prefix)) aliases.push({ prefix, target: resolve(base, targets[0].slice(0, -2)) })\n }\n }\n return { aliases, bases }\n}\n\nfunction walk(dir: string): string[] {\n return readdirSync(dir).flatMap((name) => {\n if (name === 'node_modules' || name.startsWith('.')) return []\n const path = join(dir, name)\n return statSync(path).isDirectory() ? walk(path) : [path]\n })\n}\n\n/** One import, re-export or dynamic import of a file, resolved. */\ninterface Link {\n specifier: string\n /** An app code file, relative to the app; `null` for a package; `'?'` for anything else. */\n target: string | null\n /** `imported` name \u2192 local name; `*` for a namespace or a dynamic import. Type-only names are left out. */\n names: { imported: string; local: string }[]\n typeOnly: boolean\n kind: 'import' | 're-export' | 'dynamic'\n}\n\n/** A part a file exports, before anything is known about its use. */\ninterface Found {\n file: string\n /** The name it is exported as; a default export takes its own name, or the file's. */\n name: string\n /** The name it has inside its file, where it has one. */\n local: string | null\n defaultExport: boolean\n /** A pass-on: the package and the name it hands on. */\n from: { specifier: string; name: string } | null\n}\n\n/** Everything one file says, read once. */\ninterface FileFacts {\n file: string\n source: string\n sf: ts.SourceFile\n links: Link[]\n /** `exported name` \u2192 local name, and whether it is the default. */\n exports: { name: string; local: string | null; isDefault: boolean; node: ts.Node | null }[]\n /** Pass-ons and barrel entries: `export { A } from '\u2026'`. */\n reexports: { name: string; source: string; specifier: string; target: string | null }[]\n starFrom: { specifier: string; target: string | null }[]\n /** `export * as Parts from './parts'`: a name that stands for another file's parts. */\n namespaces: { name: string; target: string | null }[]\n /** Every name drawn as a JSX tag in this file. */\n tags: Set<string>\n /** Each imported value name \u2192 where it came from, for `import { X } from '\u2026'` then `export { X }`. */\n bindings: Map<string, { specifier: string; imported: string; target: string | null }>\n}\n\n/** Whether a node draws: JSX, or `createElement` / `createPortal`. */\nfunction draws(node: ts.Node): boolean {\n let found = false\n const visit = (n: ts.Node) => {\n if (found) return\n if (ts.isJsxElement(n) || ts.isJsxSelfClosingElement(n) || ts.isJsxFragment(n)) {\n found = true\n return\n }\n if (ts.isCallExpression(n)) {\n const callee = ts.isPropertyAccessExpression(n.expression) ? n.expression.name.text : ts.isIdentifier(n.expression) ? n.expression.text : ''\n if (callee === 'createElement' || callee === 'createPortal') {\n found = true\n return\n }\n }\n ts.forEachChild(n, visit)\n }\n visit(node)\n return found\n}\n\n/**\n * Whether a file names `local` anywhere but in `home` (its own declaration), its\n * imports and its export lines \u2014 as a tag, a value, or passed along. A property\n * name, an attribute name and a type are not uses of the part.\n */\nfunction mentions(sf: ts.SourceFile, local: string, home: ts.Node | null): boolean {\n let named = false\n const visit = (n: ts.Node) => {\n if (named) return\n if (ts.isIdentifier(n) && n.text === local) {\n const parent = n.parent\n // The name of something else that happens to be spelled the same \u2014 a\n // property of a type or a class, a member, another declaration \u2014 is not the part.\n const declares = (ts.isPropertySignature(parent) || ts.isPropertyDeclaration(parent) || ts.isMethodDeclaration(parent) || ts.isMethodSignature(parent) || ts.isGetAccessorDeclaration(parent) || ts.isSetAccessorDeclaration(parent) || ts.isEnumMember(parent) || ts.isVariableDeclaration(parent) || ts.isFunctionDeclaration(parent) || ts.isClassDeclaration(parent) || ts.isParameter(parent) || ts.isBindingElement(parent)) && (parent as { name?: ts.Node }).name === n\n const bindingKey = ts.isBindingElement(parent) && parent.propertyName === n\n const isName = declares || bindingKey || (ts.isPropertyAccessExpression(parent) && parent.name === n) || (ts.isPropertyAssignment(parent) && parent.name === n) || ts.isJsxAttribute(parent) || ts.isExportSpecifier(parent) || ts.isImportSpecifier(parent) || ts.isJsxClosingElement(parent)\n // `SlashMenu.displayName = 'SlashMenu'` sets something on the part; it does not use it.\n const configures = ts.isPropertyAccessExpression(parent) && parent.expression === n && ts.isBinaryExpression(parent.parent) && parent.parent.left === parent && parent.parent.operatorToken.kind === ts.SyntaxKind.EqualsToken\n if (configures) {\n ts.forEachChild(n, visit)\n return\n }\n let inType = false\n for (let a: ts.Node | undefined = parent; a && a !== sf; a = a.parent) if (ts.isTypeNode(a)) inType = true\n if (!isName && !inType && !shadowed(n, local, sf)) named = true\n }\n ts.forEachChild(n, visit)\n }\n for (const s of sf.statements) {\n if (s === home || ts.isExportDeclaration(s) || ts.isImportDeclaration(s)) continue\n // `export default Row`, `memo(forwardRef(Row))`, `Row as ComponentType` hand the\n // part out; they do not use it. Anything else written into the default is code.\n if (ts.isExportAssignment(s) && handedOut(s.expression)) continue\n visit(s)\n }\n return named\n}\n\n/** Whether a binding name \u2014 `Icon`, `{ icon: Icon }`, `[Icon]` \u2014 binds `local`. */\nfunction binds(name: ts.BindingName | undefined, local: string): boolean {\n if (!name) return false\n if (ts.isIdentifier(name)) return name.text === local\n return name.elements.some((element) => !ts.isOmittedExpression(element) && binds(element.name, local))\n}\n\n/**\n * Whether `n` means something declared closer than the file: a parameter\n * (`Item({ icon: Icon }) { return <Icon /> }`), or a constant, function or class\n * of an enclosing block. That `Icon` is not the file's part called Icon.\n */\nfunction shadowed(n: ts.Node, local: string, sf: ts.SourceFile): boolean {\n for (let a: ts.Node | undefined = n.parent; a && a !== sf; a = a.parent) {\n if (ts.isFunctionLike(a)) {\n if (a.parameters.some((p) => binds(p.name, local))) return true\n if ((ts.isFunctionExpression(a) || ts.isClassExpression(a)) && a.name?.text === local) return true\n }\n if (ts.isCatchClause(a) && binds(a.variableDeclaration?.name, local)) return true\n if (ts.isBlock(a) || ts.isModuleBlock(a) || ts.isCaseClause(a) || ts.isDefaultClause(a)) {\n for (const s of a.statements) {\n if (ts.isVariableStatement(s) && s.declarationList.declarations.some((d) => binds(d.name, local))) return true\n if ((ts.isFunctionDeclaration(s) || ts.isClassDeclaration(s)) && s.name?.text === local) return true\n }\n }\n if ((ts.isForStatement(a) || ts.isForOfStatement(a) || ts.isForInStatement(a)) && a.initializer && ts.isVariableDeclarationList(a.initializer) && a.initializer.declarations.some((d) => binds(d.name, local))) return true\n }\n return false\n}\n\n/**\n * The thing a declaration holds, if it is a function, a class, or a call that\n * wraps one (`forwardRef`, `memo`) \u2014 as a constant, or written straight into\n * `export default \u2026`.\n */\nfunction drawingBody(node: ts.Node): ts.Node | null {\n if (ts.isFunctionDeclaration(node) || ts.isClassDeclaration(node)) return node\n const init = ts.isVariableDeclaration(node) ? node.initializer : ts.isExpression(node) ? node : undefined\n if (!init) return null\n if (ts.isArrowFunction(init) || ts.isFunctionExpression(init) || ts.isClassExpression(init)) return init\n if (ts.isCallExpression(init)) {\n const callee = init.expression.getText()\n if (/(^|\\.)createContext$/.test(callee)) return null\n if (init.arguments.some((a) => ts.isArrowFunction(a) || ts.isFunctionExpression(a))) return init\n }\n return null\n}\n\n/**\n * Read one app and return its catalogue.\n *\n * Throws on anything it cannot explain, with every problem at once: a part with\n * no purpose, a written kind it does not know. A catalogue that quietly drops\n * what it could not read would answer \"we have nothing for that\" when the\n * truth is \"the builder gave up\".\n */\nexport function buildAppRegistry({ root = process.cwd(), repo, packageRegistry, packageDependencies }: AppBuildOptions = {}): Registry {\n const app = resolve(root)\n const src = join(app, 'src')\n if (!existsSync(src)) throw new Error(`${app} has no src/ folder: estiva-ui reads an app's parts from src/`)\n const manifest = JSON.parse(readFileSync(join(app, 'package.json'), 'utf8')) as { name?: string; version?: string; scripts?: Record<string, string> }\n const self = packageRegistry === undefined || packageDependencies === undefined ? packageSelf() : null\n const theRegistry = packageRegistry === undefined ? (self?.registry ?? null) : packageRegistry\n const allowed = new Set(packageDependencies ?? self?.dependencies ?? [])\n const repoName = repo ?? manifest.name ?? basename(app)\n const { aliases, bases } = readAliases(app)\n const rel = (abs: string) => relative(app, abs).split(sep).join('/')\n\n const files = walk(src)\n .filter((path) => CODE.includes(extname(path)) && !path.endsWith('.d.ts'))\n .map(rel)\n .sort()\n const known = new Set(files)\n\n /** Where an import points: an app code file, a package (`null`), or something else (`'?'`). */\n const resolveSpecifier = (from: string, specifier: string): string | null => {\n let base: string | null = null\n if (specifier.startsWith('.')) base = resolve(app, dirname(from), specifier)\n else {\n const alias = aliases.find((a) => specifier.startsWith(a.prefix))\n if (alias) base = join(alias.target, specifier.slice(alias.prefix.length))\n }\n const lookUp = (at: string): string | null => {\n const stem = at.replace(/\\.(js|jsx)$/, '')\n for (const candidate of [at, ...CODE.map((e) => stem + e), ...CODE.map((e) => join(at, `index${e}`))]) {\n const r = rel(candidate)\n if (known.has(r)) return r\n }\n return null\n }\n if (base === null) {\n // A bare `src/Card` is the app's own when its tsconfig's baseUrl says so; otherwise a package.\n for (const folder of bases) {\n const hit = lookUp(join(folder, specifier))\n if (hit) return hit\n }\n return null\n }\n return lookUp(base) ?? '?'\n }\n\n // \u2500\u2500 Read every file once \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\n const facts = new Map<string, FileFacts>()\n for (const file of files) {\n const source = readFileSync(join(app, file), 'utf8')\n const sf = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true, /x$/.test(file) ? ts.ScriptKind.TSX : ts.ScriptKind.TS)\n const links: Link[] = []\n const exports: FileFacts['exports'] = []\n const reexports: FileFacts['reexports'] = []\n const starFrom: FileFacts['starFrom'] = []\n const namespaces: FileFacts['namespaces'] = []\n for (const statement of sf.statements) {\n if (ts.isImportDeclaration(statement)) {\n if (!ts.isStringLiteral(statement.moduleSpecifier)) continue\n const specifier = statement.moduleSpecifier.text\n const clause = statement.importClause\n const names: Link['names'] = []\n if (clause && !clause.isTypeOnly) {\n if (clause.name) names.push({ imported: 'default', local: clause.name.text })\n const bindings = clause.namedBindings\n if (bindings && ts.isNamedImports(bindings)) for (const e of bindings.elements) if (!e.isTypeOnly) names.push({ imported: (e.propertyName ?? e.name).text, local: e.name.text })\n if (bindings && ts.isNamespaceImport(bindings)) names.push({ imported: '*', local: bindings.name.text })\n }\n links.push({ specifier, target: resolveSpecifier(file, specifier), names, typeOnly: !!clause?.isTypeOnly || (clause !== undefined && names.length === 0 && !!clause.namedBindings), kind: 'import' })\n continue\n }\n if (ts.isExportDeclaration(statement)) {\n const specifier = statement.moduleSpecifier && ts.isStringLiteral(statement.moduleSpecifier) ? statement.moduleSpecifier.text : null\n if (specifier === null) {\n if (!statement.isTypeOnly && statement.exportClause && ts.isNamedExports(statement.exportClause)) {\n // `export { Page as default }` is the file's default, named Page.\n for (const e of statement.exportClause.elements) if (!e.isTypeOnly) exports.push({ name: e.name.text, local: (e.propertyName ?? e.name).text, isDefault: e.name.text === 'default', node: null })\n }\n continue\n }\n const target = resolveSpecifier(file, specifier)\n links.push({ specifier, target, names: [], typeOnly: statement.isTypeOnly, kind: 're-export' })\n if (statement.isTypeOnly) continue\n if (!statement.exportClause) starFrom.push({ specifier, target })\n else if (ts.isNamedExports(statement.exportClause)) {\n for (const e of statement.exportClause.elements) if (!e.isTypeOnly) reexports.push({ name: e.name.text, source: (e.propertyName ?? e.name).text, specifier, target })\n } else if (ts.isNamespaceExport(statement.exportClause)) {\n // `export * as Parts from './parts'`: a caller's `Parts.Card` is the parts file's Card.\n namespaces.push({ name: statement.exportClause.name.text, target })\n }\n continue\n }\n if (ts.isExportAssignment(statement) && !statement.isExportEquals) {\n const e = statement.expression\n exports.push({ name: 'default', local: ts.isIdentifier(e) ? e.text : null, isDefault: true, node: ts.isIdentifier(e) ? null : e })\n continue\n }\n const mods = ts.canHaveModifiers(statement) ? (ts.getModifiers(statement) ?? []) : []\n if (!mods.some((m) => m.kind === ts.SyntaxKind.ExportKeyword)) continue\n const isDefault = mods.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword)\n // An overload's signature is not a part of its own: the part is the one with a body.\n if (ts.isFunctionDeclaration(statement) && !statement.body) continue\n if (ts.isFunctionDeclaration(statement) || ts.isClassDeclaration(statement)) {\n exports.push({ name: isDefault ? 'default' : (statement.name?.text ?? 'default'), local: statement.name?.text ?? null, isDefault, node: statement })\n } else if (ts.isVariableStatement(statement)) {\n for (const d of statement.declarationList.declarations) if (ts.isIdentifier(d.name)) exports.push({ name: d.name.text, local: d.name.text, isDefault: false, node: d })\n }\n }\n const tags = new Set<string>()\n const visit = (n: ts.Node) => {\n if (ts.isCallExpression(n) && n.expression.kind === ts.SyntaxKind.ImportKeyword && n.arguments[0] && ts.isStringLiteralLike(n.arguments[0])) {\n const specifier = n.arguments[0].text\n links.push({ specifier, target: resolveSpecifier(file, specifier), names: pickedFrom(n), typeOnly: false, kind: 'dynamic' })\n }\n if ((ts.isJsxOpeningElement(n) || ts.isJsxSelfClosingElement(n)) && ts.isIdentifier(n.tagName)) tags.add(n.tagName.text)\n ts.forEachChild(n, visit)\n }\n visit(sf)\n const bindings: FileFacts['bindings'] = new Map()\n for (const link of links) if (link.kind === 'import') for (const n of link.names) if (n.imported !== '*') bindings.set(n.local, { specifier: link.specifier, imported: n.imported, target: link.target })\n facts.set(file, { file, source, sf, links, exports, reexports, starFrom, namespaces, tags, bindings })\n }\n\n const drawnAnywhere = new Set<string>()\n for (const f of facts.values()) for (const tag of f.tags) drawnAnywhere.add(tag)\n\n /** A top-level declaration of a file, by its local name. */\n const declarationOf = (f: FileFacts, local: string): ts.Node | null => {\n for (const s of f.sf.statements) {\n // Past an overload's signature, to the function with a body.\n if (ts.isFunctionDeclaration(s) && s.name?.text === local && !s.body) continue\n if ((ts.isFunctionDeclaration(s) || ts.isClassDeclaration(s)) && s.name?.text === local) return s\n if (ts.isVariableStatement(s)) for (const d of s.declarationList.declarations) if (ts.isIdentifier(d.name) && d.name.text === local) return d\n }\n return null\n }\n\n // \u2500\u2500 The parts \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const problems: string[] = []\n const found: Found[] = []\n const targets = files.filter((file) => file.endsWith('.tsx') && !isStory(file) && !isTest(file))\n for (const file of targets) {\n const f = facts.get(file)!\n for (const written of f.exports) {\n const ex = unwrapDefault(written)\n // `export default memo(Avatar)` with Avatar imported: not Avatar handed on, but a\n // new part of this file that wraps it, named after the file.\n // Only a name that is a part's: `createBrowserRouter(routes)` hands out no part.\n if (ex !== written && ex.local && isPascal(ex.local) && !declarationOf(f, ex.local) && f.bindings.has(ex.local)) {\n found.push({ file, name: defaultNameOf(file), local: null, defaultExport: true, from: null })\n continue\n }\n // `export function App` and `export default App` \u2014 or `export default memo(App)`: one part, not two.\n if (ex.isDefault && ex.local && f.exports.some((other) => !other.isDefault && other.local === ex.local)) continue\n const node = ex.node ?? (ex.local ? declarationOf(f, ex.local) : null)\n // A default with no name of its own takes its file's, as a name: `memo-page.tsx` \u2192 MemoPage.\n const own = ex.local ?? (ex.isDefault ? defaultNameOf(file) : ex.name)\n const name = ex.isDefault ? own : ex.name\n if (!isPascal(name)) continue\n // `import { SkeletonBar } from '@estiva-app/ui'` and later `export { SkeletonBar }`:\n // handed on, exactly as `export { SkeletonBar } from '@estiva-app/ui'` is.\n // From another file of the app it is a barrel, and the part is listed there.\n const bound = node === null && ex.local ? f.bindings.get(ex.local) : undefined\n if (bound) {\n if (bound.target === null) found.push({ file, name, local: null, defaultExport: ex.isDefault, from: { specifier: bound.specifier, name: bound.imported } })\n continue\n }\n // `export const SkeletonSidebarList = SkeletonList`, SkeletonList imported: the\n // package's part under a second name, handed on. From an app file, a barrel.\n const alias = node && ts.isVariableDeclaration(node) && node.initializer && ts.isIdentifier(node.initializer) ? f.bindings.get(node.initializer.text) : undefined\n if (alias) {\n if (alias.target === null) found.push({ file, name, local: null, defaultExport: ex.isDefault, from: { specifier: alias.specifier, name: alias.imported } })\n continue\n }\n const body = node ? drawingBody(node) : null\n const isPart = (body !== null && draws(body)) || drawnAnywhere.has(ex.local ?? name)\n if (isPart) found.push({ file, name, local: ex.local, defaultExport: ex.isDefault, from: null })\n }\n for (const re of f.reexports) {\n // Handing on another file of the app is a barrel: the part is listed where it is written.\n if (re.target !== null || !isPascal(re.name)) continue\n found.push({ file, name: re.name, local: null, defaultExport: false, from: { specifier: re.specifier, name: re.source } })\n }\n for (const star of f.starFrom) {\n if (star.target === null) problems.push(`${file} hands on everything from '${star.specifier}' with export *: name the parts it hands on, so the catalogue can list them`)\n }\n }\n\n // \u2500\u2500 Where each is used \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\u2500\n const key = (file: string, name: string) => `${file}#${name}`\n const byKey = new Map(found.map((p) => [key(p.file, p.name), p]))\n const partsIn = (file: string) => found.filter((p) => p.file === file)\n /** The part a file's default export is, however it was written. */\n const defaultPartOf = (file: string): Found | null => {\n const written = facts.get(file)?.exports.find((e) => e.isDefault)\n if (!written) return null\n const d = unwrapDefault(written)\n return partsIn(file).find((p) => p.defaultExport || (d.local !== null && p.local === d.local)) ?? null\n }\n\n /** What `name`, imported from `file`, really is: follows barrels to the file that writes it. */\n const origin = (file: string, name: string, seen = new Set<string>()): Found | null => {\n if (seen.has(key(file, name))) return null\n seen.add(key(file, name))\n const direct = byKey.get(key(file, name))\n if (direct) return direct\n const f = facts.get(file)\n if (!f) return null\n // `export default Foo` elsewhere in the file: the default is Foo's part.\n if (name === 'default') {\n const d = defaultPartOf(file)\n if (d) return d\n }\n const re = f.reexports.find((r) => r.name === name)\n if (re && re.target && re.target !== '?') return origin(re.target, re.source, seen)\n // `import { X } from './X'` and `export { X }`: a barrel written in two lines.\n const ex = f.exports.find((e) => (name === 'default' ? e.isDefault : e.name === name && !e.isDefault))\n const renamed = ex?.node && ts.isVariableDeclaration(ex.node) && ex.node.initializer && ts.isIdentifier(ex.node.initializer) ? f.bindings.get(ex.node.initializer.text) : undefined\n const bound = (ex?.local && !ex.node && !declarationOf(f, ex.local) ? f.bindings.get(ex.local) : undefined) ?? renamed\n if (bound?.target && bound.target !== '?') return origin(bound.target, bound.imported, seen)\n for (const star of f.starFrom) if (star.target && star.target !== '?') {\n const hit = origin(star.target, name, seen)\n if (hit) return hit\n }\n return null\n }\n /** Every part a file hands out, through its barrels too. */\n const everyPartOf = (file: string, seen = new Set<string>()): Found[] => {\n if (seen.has(file)) return []\n seen.add(file)\n const f = facts.get(file)\n if (!f) return []\n const out = [...partsIn(file)]\n for (const re of f.reexports) if (re.target && re.target !== '?') { const o = origin(re.target, re.source); if (o) out.push(o) }\n for (const star of f.starFrom) if (star.target && star.target !== '?') out.push(...everyPartOf(star.target, seen))\n for (const ns of f.namespaces) if (ns.target && ns.target !== '?') out.push(...everyPartOf(ns.target, seen))\n return out\n }\n /** The parts a namespace export stands for, followed through barrels. */\n const namespaceParts = (file: string, name: string, seen = new Set<string>()): Found[] => {\n if (seen.has(`${file}#${name}`)) return []\n seen.add(`${file}#${name}`)\n const f = facts.get(file)\n if (!f) return []\n const ns = f.namespaces.find((x) => x.name === name)\n if (ns) return ns.target && ns.target !== '?' ? everyPartOf(ns.target) : []\n const re = f.reexports.find((r) => r.name === name)\n if (re?.target && re.target !== '?') return namespaceParts(re.target, re.source, seen)\n return f.starFrom.flatMap((star) => (star.target && star.target !== '?' ? namespaceParts(star.target, name, seen) : []))\n }\n\n const users = new Map<string, { app: Set<string>; stories: Set<string>; tests: Set<string> }>()\n for (const p of found) users.set(key(p.file, p.name), { app: new Set(), stories: new Set(), tests: new Set() })\n for (const f of facts.values()) {\n const bucket = (p: Found) => {\n const u = users.get(key(p.file, p.name))!\n return isStory(f.file) ? u.stories : isTest(f.file) ? u.tests : u.app\n }\n for (const link of f.links) {\n if (link.kind === 're-export' || link.typeOnly || !link.target || link.target === '?') continue\n for (const n of link.names) {\n if (n.imported === '*') {\n // `lazy(() => import('./Page'))` loads the default; a namespace may use any.\n const theDefault = link.kind === 'dynamic' ? defaultPartOf(link.target) : null\n const chosen = theDefault ? [theDefault] : everyPartOf(link.target)\n for (const p of chosen) if (p.file !== f.file) bucket(p).add(f.file)\n continue\n }\n const p = origin(link.target, n.imported)\n // A file that imports a part only to export it again hands it on; it does not use it.\n const handsOn = f.exports.some((e) => e.local === n.local && e.node === null) && !mentions(f.sf, n.local, null)\n if (handsOn) continue\n if (p) {\n if (p.file !== f.file) bucket(p).add(f.file)\n continue\n }\n // `import { Parts } from './barrel'`, where the barrel says `export * as Parts from './parts'`.\n for (const part of namespaceParts(link.target, n.imported)) if (part.file !== f.file) bucket(part).add(f.file)\n }\n }\n }\n // Its own file uses it when something there, other than its own declaration and\n // the export line, names it \u2014 a card drawn by the list beside it.\n for (const p of found) {\n if (p.from || !p.local) continue\n const f = facts.get(p.file)!\n const decl = declarationOf(f, p.local)\n const home = decl ? (ts.isVariableDeclaration(decl) ? decl.parent.parent : decl) : null\n if (mentions(f.sf, p.local, home)) users.get(key(p.file, p.name))!.app.add(p.file)\n }\n\n // \u2500\u2500 What ties each file to the app \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\n // A file is tied when it imports a package the package does not itself depend\n // on, something that is not code, or an app file that is tied. Types count: a\n // part typed by Peek's data is Peek's.\n const directTies = new Map<string, string[]>()\n const appDeps = new Map<string, string[]>()\n for (const f of facts.values()) {\n const ties: string[] = []\n const deps: string[] = []\n for (const link of f.links) {\n if (link.target === null) {\n const tie = link.specifier.startsWith('node:') ? link.specifier : allowed.has(packageOf(link.specifier)) ? null : packageOf(link.specifier)\n if (tie && !ties.includes(tie)) ties.push(tie)\n } else if (link.target === '?') {\n if (!ties.includes(link.specifier)) ties.push(link.specifier)\n } else if (link.target !== f.file && !deps.includes(link.target)) deps.push(link.target)\n }\n directTies.set(f.file, ties)\n appDeps.set(f.file, deps)\n }\n const tied = new Set([...directTies].filter(([, t]) => t.length > 0).map(([file]) => file))\n for (let changed = true; changed; ) {\n changed = false\n for (const [file, deps] of appDeps) if (!tied.has(file) && deps.some((d) => tied.has(d))) (tied.add(file), (changed = true))\n }\n const tiesOf = (file: string) => [...directTies.get(file)!, ...appDeps.get(file)!.filter((d) => tied.has(d))].sort()\n\n // \u2500\u2500 Stories: which one shows a part \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\n const stories = files.filter(isStory).map((file) => {\n const f = facts.get(file)!\n let title: string | null = null\n let component: string | null = null\n let noDocs = false\n const names: string[] = []\n for (const s of f.sf.statements) {\n if (!ts.isVariableStatement(s)) continue\n const exported = (ts.getModifiers(s) ?? []).some((m) => m.kind === ts.SyntaxKind.ExportKeyword)\n for (const d of s.declarationList.declarations) {\n if (!ts.isIdentifier(d.name)) continue\n if (d.name.text === 'meta') {\n let init = d.initializer\n while (init && (ts.isSatisfiesExpression(init) || ts.isAsExpression(init) || ts.isParenthesizedExpression(init))) init = init.expression\n if (init && ts.isObjectLiteralExpression(init)) {\n for (const prop of init.properties) {\n if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name)) continue\n if (prop.name.text === 'title' && ts.isStringLiteralLike(prop.initializer)) title = prop.initializer.text\n if (prop.name.text === 'component' && ts.isIdentifier(prop.initializer)) component = prop.initializer.text\n if (prop.name.text === 'tags' && ts.isArrayLiteralExpression(prop.initializer)) noDocs = prop.initializer.elements.some((e) => ts.isStringLiteralLike(e) && e.text === '!autodocs')\n }\n }\n } else if (exported) names.push(d.name.text)\n }\n }\n // Which part each local name is, through the imports.\n const imported = new Map<string, Found>()\n for (const link of f.links) {\n if (!link.target || link.target === '?') continue\n for (const n of link.names) {\n if (n.imported === '*') continue\n const p = origin(link.target, n.imported)\n if (p) imported.set(n.local, p)\n }\n }\n return { file, title, component: component ? (imported.get(component) ?? null) : null, noDocs, names, imports: [...imported.values()] }\n })\n const storyOf = (p: Found) => {\n const stem = (file: string) => basename(file).replace(/\\.stories\\.[cm]?[jt]sx?$/, '')\n const own = basename(p.file, extname(p.file))\n const candidates = stories.filter((s) => s.title && s.names.length && (s.component === p || (s.imports.includes(p) && (stem(s.file) === p.name || stem(s.file) === own))))\n candidates.sort((a, b) => Number(b.component === p) - Number(a.component === p) || a.file.localeCompare(b.file))\n const s = candidates[0]\n if (!s || !s.title) return { docsId: null, storyId: null }\n return { docsId: s.noDocs ? null : `${sanitize(s.title)}--docs`, storyId: toId(s.title, s.names.includes(p.name) ? p.name : s.names[0]) }\n }\n\n // \u2500\u2500 Props, read the way the package's are \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\n type Module = ReturnType<typeof readModule>\n const modules = new Map<string, Module>()\n const moduleAt = (file: string): Module => {\n const held = modules.get(file)\n if (held) return held\n const read = readModule(facts.get(file)!.source, (specifier, typeName): Resolved | undefined => {\n // A wrapper typed by the package's own props takes what the package's part\n // takes. The package names every part's props type after the part \u2014\n // `SearchInputProps` is `SearchInput`'s, all 65 of them \u2014 so its entry answers.\n if (specifier === PACKAGE_IMPORT) {\n const part = typeName.endsWith('Props') ? theRegistry?.entries.find((entry) => entry.name === typeName.slice(0, -'Props'.length)) : undefined\n return part ? { props: part.props, variants: part.variants } : undefined\n }\n const target = resolveSpecifier(file, specifier)\n return target && target !== '?' ? moduleAt(target).resolveName(typeName) : undefined\n // A comment directly above a part is that part's, first in its file or not.\n }, { lendFirstComment: false })\n modules.set(file, read)\n return read\n }\n\n // \u2500\u2500 The entries \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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n const namesakes = new Set((theRegistry?.entries ?? []).map((e) => e.name))\n const importPathOf = (file: string) => {\n const abs = join(app, file)\n const alias = aliases.find((a) => abs.startsWith(a.target + sep))\n const stem = file.replace(/\\.[cm]?[jt]sx?$/, '').replace(/\\/index$/, '')\n return alias ? `${alias.prefix}${relative(alias.target, join(app, stem)).split(sep).join('/')}` : stem\n }\n const port = /(?:-p|--port)[\\s=]+(\\d+)/.exec(manifest.scripts?.storybook ?? '')?.[1] ?? '6006'\n\n const entries: RegistryEntry[] = []\n for (const p of found) {\n const u = users.get(key(p.file, p.name))!\n const usedIn = [...u.app].sort()\n const pass = p.from\n const onePart = partsIn(p.file).filter((q) => !q.from).length === 1\n const module = pass ? null : moduleAt(p.file)\n // A default written as an expression has no name in its file: the builder keeps it as `default`.\n const declared = pass ? undefined : module!.declarations.get(p.local ?? 'default')\n const header = module?.headerDoc ?? ''\n // The file's default may carry its comment on `export default memo(Row)` rather than on Row.\n const doc = declared?.doc || (defaultPartOf(p.file) === p ? (module?.declarations.get('default')?.doc ?? '') : '')\n\n // Purpose: its page, else its own comment, else \u2014 for a file of one part \u2014\n // the file's. A pass-on says whose it is.\n const page = pass ? null : join(dirname(p.file), `${p.name}.mdx`).split(sep).join('/')\n const pageText = page && existsSync(join(app, page)) ? pageOpening(readFileSync(join(app, page), 'utf8')) : ''\n let purpose = ''\n let purposeFrom: RegistryEntry['purposeFrom'] = 'comment'\n if (pass) {\n const as = pass.name === p.name ? '' : ` as ${p.name}`\n purpose = pass.specifier === PACKAGE_IMPORT ? `The package's ${pass.name}, handed on${as} so the app can import it from ${importPathOf(p.file)}.` : `${pass.name} from ${pass.specifier}, handed on${as} so the app can import it from ${importPathOf(p.file)}.`\n purposeFrom = 'package'\n } else if (firstSentence(pageText)) {\n purpose = firstSentence(pageText)\n purposeFrom = 'page'\n } else if (firstSentence(doc)) {\n purpose = firstSentence(doc)\n } else if (onePart && firstSentence(header)) {\n purpose = firstSentence(header)\n purposeFrom = 'file'\n }\n if (!purpose) {\n problems.push(`${p.name} in ${p.file} has no one-line description. Write one as a /** \u2026 */ comment directly above it${onePart ? ', or at the top of the file' : ''}.`)\n continue\n }\n\n // Its kind: written beside it, or read from the evidence.\n const writtenLine = WRITTEN.exec(doc) ?? (onePart ? WRITTEN.exec(header) : null)\n const ties = pass ? [] : tiesOf(p.file)\n let cls: EntryClass\n let reason: string\n let written = false\n if (pass) {\n cls = 're-export'\n reason = `Its file only hands on ${pass.specifier === PACKAGE_IMPORT ? `the package's ${pass.name}` : `${pass.name} from ${pass.specifier}`}.`\n if (writtenLine) problems.push(`${p.name} in ${p.file} is a pass-on, so its kind is read from the file: remove \"@registry ${writtenLine[1]}\"`)\n } else if (writtenLine) {\n const said = writtenLine[1] as EntryClass\n if (!WRITABLE.includes(said)) {\n problems.push(`${p.name} in ${p.file} says \"@registry ${writtenLine[1]}\": the kinds a person may write are ${WRITABLE.join(', ')}`)\n continue\n }\n cls = said\n reason = writtenLine[2].trim()\n written = true\n } else if (usedIn.length === 0) {\n cls = 'unused'\n reason = u.stories.size ? 'No file of the app uses it; only its stories do.' : u.tests.size ? 'No file of the app uses it; only its tests do.' : 'Nothing uses it.'\n } else if (usedIn.length === 1) {\n cls = 'one-off'\n reason = `Used in one place: ${usedIn[0]}.`\n } else if (ties.length) {\n cls = 'reusable'\n reason = `Used in ${usedIn.length} places, and tied to the app by ${ties[0]}${ties.length > 1 ? ` and ${ties.length - 1} more` : ''}.`\n } else {\n cls = 'promote-candidate'\n reason = `Used in ${usedIn.length} places, and everything it uses is already in the package.`\n }\n\n const shape: Resolved = declared ? module!.resolve(declared.propsType) : { props: [], variants: [] }\n const facts_: AppFacts = {\n class: cls,\n reason,\n written,\n handsOn: pass ? (pass.specifier === PACKAGE_IMPORT ? pass.name : `${pass.name} from ${pass.specifier}`) : null,\n usedIn,\n tiedTo: ties,\n packageNamesake: namesakes.has(p.name) && !(pass && pass.specifier === PACKAGE_IMPORT && pass.name === p.name) ? p.name : null,\n defaultExport: p.defaultExport,\n }\n const { docsId, storyId } = pass ? { docsId: null, storyId: null } : storyOf(p)\n entries.push({\n name: p.name,\n repo: repoName,\n kind: 'component',\n importPath: importPathOf(p.file),\n sourceFile: p.file,\n purpose,\n purposeFrom,\n props: shape.props,\n variants: shape.variants,\n ownsBehaviours: [],\n status: declared?.deprecated ? 'deprecated' : 'stable',\n migrationStage: null,\n docsId,\n storyId,\n docPage: pageText ? page : null,\n app: facts_,\n })\n }\n\n if (problems.length) throw new Error(`the catalogue of ${repoName} cannot be built:\\n ${problems.join('\\n ')}`)\n\n entries.sort((a, b) => a.name.localeCompare(b.name) || a.sourceFile.localeCompare(b.sourceFile))\n const withParts = new Set(found.map((p) => p.file))\n const filesWithoutParts: FileWithoutPart[] = targets\n .filter((file) => !withParts.has(file))\n .map((file) => {\n const f = facts.get(file)!\n const names = [...f.exports.map((e) => (e.isDefault ? (e.local ?? 'a default') : e.name)), ...f.reexports.map((r) => r.name)]\n return { file, reason: names.length ? `It exports no part, only ${names.join(', ')}.` : 'It exports nothing.' }\n })\n\n return {\n schemaVersion: SCHEMA_VERSION,\n builtFrom: {\n kind: 'app',\n repo: repoName,\n package: manifest.name ?? repoName,\n packageVersion: manifest.version ?? '0.0.0',\n exports: found.length,\n typeExports: 0,\n files: targets.length,\n },\n storybook: {\n docsPath: '/?path=/docs/{docsId}',\n storyPath: '/?path=/story/{storyId}',\n devUrl: `http://localhost:${port}`,\n },\n entries,\n excluded: [],\n filesWithoutParts,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["bindings", "p", "s"]
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/registry/cli.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
findInRegistries,
|
|
4
|
+
formatFindings
|
|
5
|
+
} from "./chunk-W2B2G7OE.js";
|
|
6
|
+
import {
|
|
7
|
+
CLASSES,
|
|
8
|
+
validateRegistry
|
|
9
|
+
} from "./chunk-E4JNV7PC.js";
|
|
10
|
+
|
|
11
|
+
// src/registry/cli.ts
|
|
12
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { basename, resolve } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
var packageBuilder = () => import("./build-LGFCCOLR.js");
|
|
16
|
+
var appBuilder = () => import("./app-DQI6WLHR.js");
|
|
17
|
+
var [command, ...rest] = process.argv.slice(2);
|
|
18
|
+
var VALUED = ["--limit", "--out", "--file", "--root", "--repo", "--also"];
|
|
19
|
+
var flag = (name) => rest.includes(`--${name}`);
|
|
20
|
+
var value = (name) => {
|
|
21
|
+
const at = rest.indexOf(`--${name}`);
|
|
22
|
+
return at === -1 ? void 0 : rest[at + 1];
|
|
23
|
+
};
|
|
24
|
+
var values = (name) => rest.flatMap((word, i) => word === `--${name}` && rest[i + 1] !== void 0 ? [rest[i + 1]] : []);
|
|
25
|
+
var plain = () => {
|
|
26
|
+
const out = [];
|
|
27
|
+
for (let i = 0; i < rest.length; i++) {
|
|
28
|
+
if (rest[i].startsWith("--")) {
|
|
29
|
+
if (VALUED.includes(rest[i])) i += 1;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
out.push(rest[i]);
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
};
|
|
36
|
+
var root = resolve(value("root") ?? ".");
|
|
37
|
+
var manifestAt = (folder) => JSON.parse(readFileSync(resolve(folder, "package.json"), "utf8"));
|
|
38
|
+
var isPackage = existsSync(resolve(root, "package.json")) && manifestAt(root).name === "@estiva-app/ui";
|
|
39
|
+
function packageRegistryPath() {
|
|
40
|
+
const named = value("file");
|
|
41
|
+
if (named) return resolve(named);
|
|
42
|
+
if (isPackage) return resolve(root, "registry.json");
|
|
43
|
+
return fileURLToPath(new URL("../../registry.json", import.meta.url));
|
|
44
|
+
}
|
|
45
|
+
function readPackageRegistry() {
|
|
46
|
+
const path = packageRegistryPath();
|
|
47
|
+
if (!existsSync(path)) throw new Error(`no registry.json at ${path} \u2014 run "estiva-ui build" in the package first`);
|
|
48
|
+
const registry = JSON.parse(readFileSync(path, "utf8"));
|
|
49
|
+
const problems = validateRegistry(registry);
|
|
50
|
+
if (problems.length) throw new Error(`${path} does not match the schema:
|
|
51
|
+
${problems.join("\n ")}`);
|
|
52
|
+
return registry;
|
|
53
|
+
}
|
|
54
|
+
async function buildApp(folder, repo) {
|
|
55
|
+
const { buildAppRegistry } = await appBuilder();
|
|
56
|
+
const registry = buildAppRegistry({ root: folder, repo });
|
|
57
|
+
const problems = validateRegistry(registry);
|
|
58
|
+
if (problems.length) throw new Error(`the catalogue of ${registry.builtFrom.repo} does not match its own schema:
|
|
59
|
+
${problems.join("\n ")}`);
|
|
60
|
+
return registry;
|
|
61
|
+
}
|
|
62
|
+
function summary(registry) {
|
|
63
|
+
const count = (cls) => registry.entries.filter((entry) => entry.app?.class === cls).length;
|
|
64
|
+
const kinds = CLASSES.map((cls) => `${count(cls)} ${cls}`).join(", ");
|
|
65
|
+
const files = registry.builtFrom.files ?? 0;
|
|
66
|
+
return `${registry.builtFrom.repo}: ${registry.entries.length} parts in ${files - registry.filesWithoutParts.length} files (${registry.filesWithoutParts.length} more hold none) \u2014 ${kinds}. Every part is described and sorted.`;
|
|
67
|
+
}
|
|
68
|
+
async function main() {
|
|
69
|
+
switch (command) {
|
|
70
|
+
case "find": {
|
|
71
|
+
const query = plain().join(" ");
|
|
72
|
+
if (!query.trim()) {
|
|
73
|
+
process.stderr.write("estiva-ui find <words\u2026> \u2014 what the thing you need does, in words\n");
|
|
74
|
+
return 1;
|
|
75
|
+
}
|
|
76
|
+
const registries = [readPackageRegistry()];
|
|
77
|
+
const add = async (folder, repo) => {
|
|
78
|
+
try {
|
|
79
|
+
registries.push(await buildApp(folder, repo));
|
|
80
|
+
} catch (error) {
|
|
81
|
+
const [first, ...more] = String(error instanceof Error ? error.message : error).split("\n");
|
|
82
|
+
process.stderr.write(`not searched: ${first}${more.length ? `
|
|
83
|
+
${more.slice(0, 3).join("\n")}${more.length > 3 ? `
|
|
84
|
+
\u2026and ${more.length - 3} more \u2014 run "estiva-ui check" there` : ""}` : ""}
|
|
85
|
+
`);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
if (!isPackage) await add(root, value("repo"));
|
|
89
|
+
for (const also of values("also")) {
|
|
90
|
+
const [name, folder] = also.includes("=") ? [also.slice(0, also.indexOf("=")), also.slice(also.indexOf("=") + 1)] : [void 0, also];
|
|
91
|
+
const at = resolve(root, folder);
|
|
92
|
+
if (!existsSync(resolve(at, "package.json"))) {
|
|
93
|
+
process.stderr.write(`not searched: ${name ?? basename(at)} \u2014 nothing at ${at}
|
|
94
|
+
`);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
await add(at, name);
|
|
98
|
+
}
|
|
99
|
+
const limit = Number(value("limit") ?? 5);
|
|
100
|
+
const findings = findInRegistries(registries, query, { limit: Number.isFinite(limit) && limit > 0 ? limit : 5 });
|
|
101
|
+
if (flag("json")) {
|
|
102
|
+
process.stdout.write(`${JSON.stringify(findings.map((finding) => finding.entry), null, 2)}
|
|
103
|
+
`);
|
|
104
|
+
return 0;
|
|
105
|
+
}
|
|
106
|
+
process.stdout.write(`${formatFindings(registries, findings, query)}
|
|
107
|
+
`);
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
case "build": {
|
|
111
|
+
const out = resolve(root, value("out") ?? "registry.json");
|
|
112
|
+
if (isPackage) {
|
|
113
|
+
const { buildRegistry, serializeRegistry: serializeRegistry2 } = await packageBuilder();
|
|
114
|
+
const registry2 = buildRegistry({ root });
|
|
115
|
+
const problems = validateRegistry(registry2);
|
|
116
|
+
if (problems.length) {
|
|
117
|
+
process.stderr.write(`the registry this build produced does not match its own schema:
|
|
118
|
+
${problems.join("\n ")}
|
|
119
|
+
`);
|
|
120
|
+
return 1;
|
|
121
|
+
}
|
|
122
|
+
writeFileSync(out, serializeRegistry2(registry2), "utf8");
|
|
123
|
+
process.stdout.write(`${out}: ${registry2.entries.length} entries from ${registry2.builtFrom.exports} exports
|
|
124
|
+
`);
|
|
125
|
+
return 0;
|
|
126
|
+
}
|
|
127
|
+
const { serializeRegistry } = await packageBuilder();
|
|
128
|
+
const registry = await buildApp(root, value("repo"));
|
|
129
|
+
writeFileSync(out, serializeRegistry(registry), "utf8");
|
|
130
|
+
process.stdout.write(`${out}: ${summary(registry)}
|
|
131
|
+
`);
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
case "check": {
|
|
135
|
+
if (!isPackage) {
|
|
136
|
+
process.stdout.write(`${summary(await buildApp(root, value("repo")))}
|
|
137
|
+
`);
|
|
138
|
+
return 0;
|
|
139
|
+
}
|
|
140
|
+
const { buildRegistry, serializeRegistry } = await packageBuilder();
|
|
141
|
+
const path = packageRegistryPath();
|
|
142
|
+
const built = buildRegistry({ root });
|
|
143
|
+
const problems = validateRegistry(built);
|
|
144
|
+
if (problems.length) {
|
|
145
|
+
process.stderr.write(`the registry does not match its own schema:
|
|
146
|
+
${problems.join("\n ")}
|
|
147
|
+
`);
|
|
148
|
+
return 1;
|
|
149
|
+
}
|
|
150
|
+
if (!existsSync(path)) {
|
|
151
|
+
process.stderr.write(`${path} is missing \u2014 run "npm run registry"
|
|
152
|
+
`);
|
|
153
|
+
return 1;
|
|
154
|
+
}
|
|
155
|
+
if (readFileSync(path, "utf8").replace(/\r\n/g, "\n") !== serializeRegistry(built)) {
|
|
156
|
+
process.stderr.write(`${path} is not what the code produces \u2014 run "npm run registry" and commit the result
|
|
157
|
+
`);
|
|
158
|
+
return 1;
|
|
159
|
+
}
|
|
160
|
+
process.stdout.write(`${path}: current, ${built.entries.length} entries from ${built.builtFrom.exports} exports
|
|
161
|
+
`);
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
default:
|
|
165
|
+
process.stderr.write("estiva-ui <find | build | check>\n");
|
|
166
|
+
return 1;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
process.exitCode = await main();
|
|
171
|
+
} catch (error) {
|
|
172
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}
|
|
173
|
+
`);
|
|
174
|
+
process.exitCode = 1;
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/registry/cli.ts"],
|
|
4
|
+
"sourcesContent": ["/// <reference types=\"node\" />\n/**\n * `estiva-ui` \u2014 the catalogue as a command (UIG-12, UIG-13; docs/GATES.md \u00A723\n * for why it ships in the package rather than as a script pasted into each repo).\n *\n * estiva-ui find <words\u2026> [--also [name=]<folder>]\u2026 [--json] [--limit n]\n * estiva-ui build [--out <path>]\n * estiva-ui check\n *\n * Every command takes `--root <folder>` (the library it reads; default: here)\n * and `--repo <name>` (what an app's entries are called; default: its package name).\n *\n * **In the package** (`@estiva-app/ui` itself): `build` writes the committed\n * `registry.json`, and `check` rebuilds it and fails on a single byte of drift.\n *\n * **In an app**: nothing is committed (Katerina, 18 September 2026 \u2014 the\n * package is public, the apps are private). `check` builds the app's catalogue\n * and fails when a part has no one-line description or cannot be sorted; CI's\n * `gate` job runs it. `build` writes the catalogue to a file only when asked.\n *\n * `find` searches the package's catalogue \u2014 the one shipped inside the installed\n * package, or this repo's own in the package \u2014 plus, in an app, the app's own,\n * built fresh, plus each `--also` app that sits beside it.\n */\nimport { existsSync, readFileSync, writeFileSync } from 'node:fs'\nimport { basename, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { findInRegistries, formatFindings } from './find'\nimport { CLASSES, validateRegistry, type Registry } from './schema'\n\n/**\n * The builders, loaded only when they are used.\n *\n * They read TypeScript with TypeScript, and `typescript` is a dev dependency of\n * the app that installs this package \u2014 a real one in Peek, Ship and this repo,\n * and possibly absent elsewhere. A static import made the bundler put the whole\n * builder in the same chunk as `find`, so `npx estiva-ui find \u2026` died with\n * ERR_MODULE_NOT_FOUND before opening the file it needed.\n */\nconst packageBuilder = () => import('./build')\nconst appBuilder = () => import('./app')\n\nconst [command, ...rest] = process.argv.slice(2)\nconst VALUED = ['--limit', '--out', '--file', '--root', '--repo', '--also']\nconst flag = (name: string) => rest.includes(`--${name}`)\nconst value = (name: string) => {\n const at = rest.indexOf(`--${name}`)\n return at === -1 ? undefined : rest[at + 1]\n}\nconst values = (name: string) => rest.flatMap((word, i) => (word === `--${name}` && rest[i + 1] !== undefined ? [rest[i + 1]] : []))\n/** Everything that is not a flag or a flag's value: the words of the question. */\nconst plain = () => {\n const out: string[] = []\n for (let i = 0; i < rest.length; i++) {\n if (rest[i].startsWith('--')) {\n if (VALUED.includes(rest[i])) i += 1\n continue\n }\n out.push(rest[i])\n }\n return out\n}\n\nconst root = resolve(value('root') ?? '.')\nconst manifestAt = (folder: string) => JSON.parse(readFileSync(resolve(folder, 'package.json'), 'utf8')) as { name?: string }\n/** The package itself, or an app that installs it. */\nconst isPackage = existsSync(resolve(root, 'package.json')) && manifestAt(root).name === '@estiva-app/ui'\n\n/** The package's committed catalogue: `--file`, this repo's own in the package, else the copy inside the installed package. */\nfunction packageRegistryPath(): string {\n const named = value('file')\n if (named) return resolve(named)\n if (isPackage) return resolve(root, 'registry.json')\n // dist/registry/cli.js \u2192 the package's own root. Never an app's own folder:\n // a registry.json there is the app's, written by `estiva-ui build`.\n return fileURLToPath(new URL('../../registry.json', import.meta.url))\n}\n\nfunction readPackageRegistry(): Registry {\n const path = packageRegistryPath()\n if (!existsSync(path)) throw new Error(`no registry.json at ${path} \u2014 run \"estiva-ui build\" in the package first`)\n const registry = JSON.parse(readFileSync(path, 'utf8')) as Registry\n const problems = validateRegistry(registry)\n // A malformed catalogue is worse than none: it would answer, wrongly.\n if (problems.length) throw new Error(`${path} does not match the schema:\\n ${problems.join('\\n ')}`)\n return registry\n}\n\nasync function buildApp(folder: string, repo: string | undefined): Promise<Registry> {\n const { buildAppRegistry } = await appBuilder()\n const registry = buildAppRegistry({ root: folder, repo })\n const problems = validateRegistry(registry)\n if (problems.length) throw new Error(`the catalogue of ${registry.builtFrom.repo} does not match its own schema:\\n ${problems.join('\\n ')}`)\n return registry\n}\n\n/** One line per kind, in a fixed order, so two runs read the same. */\nfunction summary(registry: Registry): string {\n const count = (cls: string) => registry.entries.filter((entry) => entry.app?.class === cls).length\n const kinds = CLASSES.map((cls) => `${count(cls)} ${cls}`).join(', ')\n const files = registry.builtFrom.files ?? 0\n return `${registry.builtFrom.repo}: ${registry.entries.length} parts in ${files - registry.filesWithoutParts.length} files (${registry.filesWithoutParts.length} more hold none) \u2014 ${kinds}. Every part is described and sorted.`\n}\n\nasync function main(): Promise<number> {\n switch (command) {\n case 'find': {\n const query = plain().join(' ')\n if (!query.trim()) {\n process.stderr.write('estiva-ui find <words\u2026> \u2014 what the thing you need does, in words\\n')\n return 1\n }\n const registries: Registry[] = [readPackageRegistry()]\n // An app that cannot be read is said out loud, and the rest still answer.\n const add = async (folder: string, repo: string | undefined) => {\n try {\n registries.push(await buildApp(folder, repo))\n } catch (error) {\n const [first, ...more] = String(error instanceof Error ? error.message : error).split('\\n')\n process.stderr.write(`not searched: ${first}${more.length ? `\\n${more.slice(0, 3).join('\\n')}${more.length > 3 ? `\\n \u2026and ${more.length - 3} more \u2014 run \"estiva-ui check\" there` : ''}` : ''}\\n`)\n }\n }\n if (!isPackage) await add(root, value('repo'))\n for (const also of values('also')) {\n const [name, folder] = also.includes('=') ? [also.slice(0, also.indexOf('=')), also.slice(also.indexOf('=') + 1)] : [undefined, also]\n const at = resolve(root, folder)\n if (!existsSync(resolve(at, 'package.json'))) {\n process.stderr.write(`not searched: ${name ?? basename(at)} \u2014 nothing at ${at}\\n`)\n continue\n }\n await add(at, name)\n }\n const limit = Number(value('limit') ?? 5)\n const findings = findInRegistries(registries, query, { limit: Number.isFinite(limit) && limit > 0 ? limit : 5 })\n if (flag('json')) {\n process.stdout.write(`${JSON.stringify(findings.map((finding) => finding.entry), null, 2)}\\n`)\n return 0\n }\n process.stdout.write(`${formatFindings(registries, findings, query)}\\n`)\n // Nothing found is not a failure \u2014 it is the answer that sends a session\n // to ask rather than to invent.\n return 0\n }\n\n case 'build': {\n const out = resolve(root, value('out') ?? 'registry.json')\n if (isPackage) {\n const { buildRegistry, serializeRegistry } = await packageBuilder()\n const registry = buildRegistry({ root })\n const problems = validateRegistry(registry)\n if (problems.length) {\n process.stderr.write(`the registry this build produced does not match its own schema:\\n ${problems.join('\\n ')}\\n`)\n return 1\n }\n writeFileSync(out, serializeRegistry(registry), 'utf8')\n process.stdout.write(`${out}: ${registry.entries.length} entries from ${registry.builtFrom.exports} exports\\n`)\n return 0\n }\n const { serializeRegistry } = await packageBuilder()\n const registry = await buildApp(root, value('repo'))\n writeFileSync(out, serializeRegistry(registry), 'utf8')\n process.stdout.write(`${out}: ${summary(registry)}\\n`)\n return 0\n }\n\n case 'check': {\n if (!isPackage) {\n process.stdout.write(`${summary(await buildApp(root, value('repo')))}\\n`)\n return 0\n }\n const { buildRegistry, serializeRegistry } = await packageBuilder()\n const path = packageRegistryPath()\n const built = buildRegistry({ root })\n const problems = validateRegistry(built)\n if (problems.length) {\n process.stderr.write(`the registry does not match its own schema:\\n ${problems.join('\\n ')}\\n`)\n return 1\n }\n if (!existsSync(path)) {\n process.stderr.write(`${path} is missing \u2014 run \"npm run registry\"\\n`)\n return 1\n }\n // Byte for byte. The point of the check is that the committed file cannot\n // drift from the code; \"near enough\" is drift.\n if (readFileSync(path, 'utf8').replace(/\\r\\n/g, '\\n') !== serializeRegistry(built)) {\n process.stderr.write(`${path} is not what the code produces \u2014 run \"npm run registry\" and commit the result\\n`)\n return 1\n }\n process.stdout.write(`${path}: current, ${built.entries.length} entries from ${built.builtFrom.exports} exports\\n`)\n return 0\n }\n\n default:\n process.stderr.write('estiva-ui <find | build | check>\\n')\n return 1\n }\n}\n\ntry {\n process.exitCode = await main()\n} catch (error) {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`)\n process.exitCode = 1\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["serializeRegistry", "registry"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The catalogue's reader (UIG-12): `ui:find <words>`.
|
|
3
|
+
*
|
|
4
|
+
* It exists to prove the format. A schema nobody consumes is a schema nobody
|
|
5
|
+
* has tested, and the questions it has to answer are regression tests, not the
|
|
6
|
+
* scope: "floating panel" must find `Popover`, "scrolling" `ScrollArea`,
|
|
7
|
+
* "empty" `EmptyState`.
|
|
8
|
+
*
|
|
9
|
+
* It is also the answer to "what do we have for this?", which is the question
|
|
10
|
+
* the wall cannot answer: a lint rule refuses the wrong thing, and this is
|
|
11
|
+
* where the right one is named (UIG-20 makes a session ask it first).
|
|
12
|
+
*/
|
|
13
|
+
import type { Registry, RegistryEntry } from './schema';
|
|
14
|
+
export interface Finding {
|
|
15
|
+
entry: RegistryEntry;
|
|
16
|
+
/** How many of the query's words matched anywhere. Ranked on this first. */
|
|
17
|
+
matched: number;
|
|
18
|
+
score: number;
|
|
19
|
+
/** Which fields matched, for the reader to say why. */
|
|
20
|
+
where: string[];
|
|
21
|
+
/**
|
|
22
|
+
* The props the query named **by name**, so the answer shows those rather
|
|
23
|
+
* than all of them. A prop whose note merely carries one of the words counts
|
|
24
|
+
* towards the score and is not shown: on "floating panel", six of `Popover`'s
|
|
25
|
+
* notes say "panel", and printing all six buries the answer.
|
|
26
|
+
*/
|
|
27
|
+
props: string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Search name, purpose, behaviours and variants.
|
|
31
|
+
*
|
|
32
|
+
* A row that answers more of the question comes first, whatever it scored:
|
|
33
|
+
* "floating panel" has to reach `Popover`, whose purpose carries both words,
|
|
34
|
+
* over `MenuPanel`, whose name carries one of them loudly.
|
|
35
|
+
*/
|
|
36
|
+
export declare function findInRegistry(registry: Registry, query: string, { limit }?: {
|
|
37
|
+
limit?: number;
|
|
38
|
+
}): Finding[];
|
|
39
|
+
/**
|
|
40
|
+
* Search several catalogues as one: the package's, the app's own, and any app
|
|
41
|
+
* beside it (UIG-13).
|
|
42
|
+
*
|
|
43
|
+
* An app's pass-on is not a result of its own — it is the package's part, and
|
|
44
|
+
* the package's entry answers for it, saying which apps hand it on. At the
|
|
45
|
+
* same strength the package's part comes first: it is the one to reach for.
|
|
46
|
+
*/
|
|
47
|
+
export declare function findInRegistries(registries: Registry[], query: string, { limit }?: {
|
|
48
|
+
limit?: number;
|
|
49
|
+
}): Finding[];
|
|
50
|
+
/** `http://localhost:6008/?path=/docs/overlays-popover--docs`, or `null` where the entry has no page. */
|
|
51
|
+
export declare function docsLink(registry: Registry, entry: RegistryEntry): string | null;
|
|
52
|
+
/** What the command prints: the import line first, because that is what the reader came for. */
|
|
53
|
+
export declare function formatFindings(searched: Registry | Registry[], findings: Finding[], query: string): string;
|
|
54
|
+
//# sourceMappingURL=find.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../src/registry/find.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAEvD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,aAAa,CAAA;IACpB,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;IACb,uDAAuD;IACvD,KAAK,EAAE,MAAM,EAAE,CAAA;IACf;;;;;OAKG;IACH,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAoDD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,KAAS,EAAE,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,EAAE,CAEnH;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,KAAS,EAAE,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,EAAE,CAmEzH;AAED,yGAAyG;AACzG,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAGhF;AAUD,gGAAgG;AAChG,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAgD1G"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@estiva-app/ui/registry` — the component catalogue (UIG-12, seam S2).
|
|
3
|
+
*
|
|
4
|
+
* The one copy, here, as every gate piece is (docs/GATES.md §23): the skill
|
|
5
|
+
* (UIG-20), the copy detector (UIG-25) and the merged search (UIG-19) read
|
|
6
|
+
* this, and no repo keeps a parser of its own.
|
|
7
|
+
*
|
|
8
|
+
* The data itself is `registry.json` at the package's root, committed and
|
|
9
|
+
* shipped. Read it with `estiva-ui find`, or import these to read it yourself.
|
|
10
|
+
* An app's own catalogue (UIG-13) is built from its code with
|
|
11
|
+
* `buildAppRegistry` each time it is read, and never committed.
|
|
12
|
+
*/
|
|
13
|
+
export { buildRegistry, readIndexExports, serializeRegistry, type BuildOptions } from './build';
|
|
14
|
+
export { buildAppRegistry, type AppBuildOptions } from './app';
|
|
15
|
+
export { docsLink, findInRegistries, findInRegistry, formatFindings, type Finding } from './find';
|
|
16
|
+
export { CLASSES, SCHEMA_VERSION, validateRegistry, type AppFacts, type EntryBehaviour, type EntryClass, type FileWithoutPart, type EntryKind, type EntryStatus, type EntryVariant, type PurposeSource, type Registry, type RegistryEntry, type RegistryExclusion, } from './schema';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAA;AAC/F,OAAO,EAAE,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,OAAO,CAAA;AAC9D,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,cAAc,EAAE,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAA;AACjG,OAAO,EACL,OAAO,EACP,cAAc,EACd,gBAAgB,EAChB,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACvB,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
docsLink,
|
|
4
|
+
findInRegistries,
|
|
5
|
+
findInRegistry,
|
|
6
|
+
formatFindings
|
|
7
|
+
} from "./chunk-W2B2G7OE.js";
|
|
8
|
+
import {
|
|
9
|
+
buildAppRegistry
|
|
10
|
+
} from "./chunk-WMFF3MPP.js";
|
|
11
|
+
import {
|
|
12
|
+
buildRegistry,
|
|
13
|
+
readIndexExports,
|
|
14
|
+
serializeRegistry
|
|
15
|
+
} from "./chunk-NJN4MQAM.js";
|
|
16
|
+
import {
|
|
17
|
+
CLASSES,
|
|
18
|
+
SCHEMA_VERSION,
|
|
19
|
+
validateRegistry
|
|
20
|
+
} from "./chunk-E4JNV7PC.js";
|
|
21
|
+
export {
|
|
22
|
+
CLASSES,
|
|
23
|
+
SCHEMA_VERSION,
|
|
24
|
+
buildAppRegistry,
|
|
25
|
+
buildRegistry,
|
|
26
|
+
docsLink,
|
|
27
|
+
findInRegistries,
|
|
28
|
+
findInRegistry,
|
|
29
|
+
formatFindings,
|
|
30
|
+
readIndexExports,
|
|
31
|
+
serializeRegistry,
|
|
32
|
+
validateRegistry
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=index.js.map
|