@cascivo/registry 0.1.0 → 0.1.2

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 CHANGED
@@ -1,13 +1,35 @@
1
1
  <!-- generated by scripts/readme/generate.ts — edit readme.body.md, not this file -->
2
2
 
3
- # @cascivo/registry
3
+ <div align="center">
4
+ <a href="https://cascivo.com"><img src="https://cascivo.com/favicon.svg" width="72" height="72" alt="cascivo logo"></a>
5
+ <h1>@cascivo/registry</h1>
6
+ <p><strong>Registry schema v2 types, validation, and static build for the cascivo ecosystem</strong></p>
4
7
 
5
- > Registry schema v2 types, validation, and static build for the cascade ecosystem
8
+ [![npm](https://img.shields.io/npm/v/%40cascivo%2Fregistry?style=flat-square&color=0079bf)](https://www.npmjs.com/package/@cascivo/registry)
9
+ [![downloads](https://img.shields.io/npm/dm/%40cascivo%2Fregistry?style=flat-square&color=0079bf)](https://www.npmjs.com/package/@cascivo/registry)
10
+ [![license](https://img.shields.io/npm/l/%40cascivo%2Fregistry?style=flat-square&color=0079bf)](https://github.com/cascivo/cascivo/blob/main/LICENSE)
11
+ ![types](https://img.shields.io/badge/types-included-0079bf?style=flat-square&logo=typescript&logoColor=white)
6
12
 
7
- [cascivo.com](https://cascivo.com) · [Docs](https://docs.cascivo.com) · [Storybook](https://storybook.cascivo.com) · [GitHub](https://github.com/urbanisierung/cascivo)
13
+ [npm](https://www.npmjs.com/package/@cascivo/registry) · [cascivo.com](https://cascivo.com) · [Docs](https://docs.cascivo.com) · [Storybook](https://storybook.cascivo.com) · [GitHub](https://github.com/cascivo/cascivo)
14
+
15
+ </div>
16
+
17
+ ---
8
18
 
9
19
  Registry client and type definitions — reads `registry.json` and validates component entries. Used internally by the CLI and MCP server.
10
20
 
21
+ ## shadcn registry interop
22
+
23
+ In addition to cascivo's own registry, the build emits a **shadcn-registry-compatible** projection so the shadcn CLI can install a cascivo component directly:
24
+
25
+ ```sh
26
+ npx shadcn add https://<host>/r/shadcn/button.json
27
+ ```
28
+
29
+ Each `r/shadcn/<name>.json` is a shadcn `registry:component` item with the source files inlined as `content`. This is purely additive — `npx cascivo add` and cascivo's own `registry.json` schema are unchanged.
30
+
31
+ **CSS-native caveat:** cascivo components are `.tsx` + `.module.css` and rely on the `@cascivo/core` peer plus a `@cascivo/themes` stylesheet import — there is no Tailwind config or `cssVars` block to merge. After adding a component via the shadcn CLI, install `@cascivo/core` and import a theme (e.g. `@cascivo/themes/light.css`).
32
+
11
33
  ## Install
12
34
 
13
35
  ```sh
@@ -16,4 +38,6 @@ pnpm add @cascivo/registry
16
38
 
17
39
  ---
18
40
 
19
- [cascivo.com](https://cascivo.com) · [Docs](https://docs.cascivo.com) · [Storybook](https://storybook.cascivo.com) · [GitHub](https://github.com/urbanisierung/cascivo) · AI agents: use [`@cascivo/mcp`](https://github.com/urbanisierung/cascivo/tree/main/packages/mcp) and [`registry.json`](https://github.com/urbanisierung/cascivo/blob/main/registry.json) · MIT
41
+ [cascivo.com](https://cascivo.com) · [Docs](https://docs.cascivo.com) · [Storybook](https://storybook.cascivo.com) · [GitHub](https://github.com/cascivo/cascivo) · AI agents: use [`@cascivo/mcp`](https://github.com/cascivo/cascivo/tree/main/packages/mcp) and [`registry.json`](https://github.com/cascivo/cascivo/blob/main/registry.json) · MIT
42
+
43
+ <div align="center"><a href="https://cascivo.com"><img src="https://cascivo.com/favicon.svg" width="28" height="28" alt="cascivo"></a></div>
package/dist/index.d.mts CHANGED
@@ -71,6 +71,38 @@ declare function parseLegacyRegistry(raw: unknown): RegistryIndex;
71
71
  //#region src/build.d.ts
72
72
  declare function buildRegistry(index: RegistryIndex, outDir: string): Promise<void>;
73
73
  //#endregion
74
+ //#region src/shadcn.d.ts
75
+ type ShadcnItemType = 'registry:component' | 'registry:block' | 'registry:lib' | 'registry:ui' | 'registry:hook' | 'registry:theme' | 'registry:style' | 'registry:file';
76
+ interface ShadcnRegistryFile {
77
+ path: string;
78
+ type: ShadcnItemType;
79
+ content?: string;
80
+ target?: string;
81
+ }
82
+ interface ShadcnRegistryItem {
83
+ $schema: string;
84
+ name: string;
85
+ type: ShadcnItemType;
86
+ description?: string;
87
+ dependencies?: string[];
88
+ registryDependencies?: string[];
89
+ files: ShadcnRegistryFile[];
90
+ categories?: string[];
91
+ meta?: Record<string, unknown>;
92
+ }
93
+ interface ToShadcnOptions {
94
+ /** Resolve a cascivo file URL to its source text, to inline as `content`. */
95
+ resolveContent?: (fileUrl: string) => string | undefined;
96
+ }
97
+ /** Flatten a possibly-prefixed cascivo name ("block/x") into a shadcn slug. */
98
+ declare function shadcnName(name: string): string;
99
+ declare function toShadcnItem(item: RegistryItem, opts?: ToShadcnOptions): ShadcnRegistryItem;
100
+ /**
101
+ * Write one shadcn `r/<name>.json` per item (with inlined file content when a
102
+ * resolver is supplied) plus a lean `registry.json` index (content omitted).
103
+ */
104
+ declare function writeShadcnRegistry(index: RegistryIndex, outDir: string, opts?: ToShadcnOptions): Promise<void>;
105
+ //#endregion
74
106
  //#region src/advisories.d.ts
75
107
  declare function matchAdvisories(item: Pick<RegistryItem, 'advisories'>, lockedVersion: string): RegistryAdvisory[];
76
108
  //#endregion
@@ -95,5 +127,5 @@ interface DirectoryValidationResult {
95
127
  }
96
128
  declare function validateDirectory(raw: unknown): DirectoryValidationResult;
97
129
  //#endregion
98
- export { type DirectoryEntry, type DirectoryValidationResult, type LegacyRegistry, type LegacyRegistryEntry, type RegistryAdvisory, type RegistryDirectory, type RegistryFile, type RegistryIndex, type RegistryItem, type RegistryItemType, type ValidationResult, buildRegistry, matchAdvisories, parseLegacyRegistry, validateDirectory, validateIndex, validateItem };
130
+ export { type DirectoryEntry, type DirectoryValidationResult, type LegacyRegistry, type LegacyRegistryEntry, type RegistryAdvisory, type RegistryDirectory, type RegistryFile, type RegistryIndex, type RegistryItem, type RegistryItemType, type ShadcnItemType, type ShadcnRegistryFile, type ShadcnRegistryItem, type ToShadcnOptions, type ValidationResult, buildRegistry, matchAdvisories, parseLegacyRegistry, shadcnName, toShadcnItem, validateDirectory, validateIndex, validateItem, writeShadcnRegistry };
99
131
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/validate.ts","../src/build.ts","../src/advisories.ts","../src/directory.ts"],"mappings":";UAAiB,YAAA;EACf,GAAA;EACA,MAAM;AAAA;AAAA,KAGI,gBAAA;AAAA,UASK,gBAAA;EACf,EAAA;EACA,QAAA;EACA,gBAAA;EACA,OAAA;EACA,OAAA;EACA,IAAA;AAAA;AAAA,UAGe,YAAA;EACf,aAAA;EACA,IAAA;EACA,IAAA,EAAM,gBAAA;EACN,WAAA;EACA,QAAA;EACA,OAAA;EACA,SAAA;IAAc,OAAA;IAAiB,IAAA;EAAA;EAC/B,MAAA;EACA,OAAA;EACA,QAAA;EACA,KAAA,EAAO,YAAA;EACP,OAAA;EACA,YAAA;EACA,oBAAA;EACA,IAAA;EACA,IAAA;EACA,UAAA,GAAa,gBAAA;AAAA;AAAA,UAGE,aAAA;EACf,aAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA,EAAO,YAAY;AAAA;AAAA,UAGJ,mBAAA;EACf,IAAA;EACA,IAAA;EACA,WAAA;EACA,QAAA;EACA,OAAA;EACA,KAAA;EACA,OAAA;EACA,YAAA;EACA,IAAA;EACA,IAAA;AAAA;AAAA,UAGe,cAAA;EACf,OAAA;EACA,WAAA;EACA,UAAA,EAAY,mBAAmB;AAAA;;;UChEhB,gBAAA;EACf,EAAA;EACA,MAAA;EACA,QAAA;AAAA;AAAA,iBAcc,YAAA,CAAa,GAAA,YAAe,gBAAgB;AAAA,iBAsF5C,aAAA,CAAc,GAAA,YAAe,gBAAgB;AAAA,iBAkC7C,mBAAA,CAAoB,GAAA,YAAe,aAAa;;;iBC5H1C,aAAA,CAAc,KAAA,EAAO,aAAA,EAAe,MAAA,WAAiB,OAAO;;;iBC4ClE,eAAA,CACd,IAAA,EAAM,IAAA,CAAK,YAAA,iBACX,aAAA,WACC,gBAAA;;;UC9Dc,cAAA;EACf,SAAA;EACA,IAAA;EACA,WAAA;EACA,QAAA;EACA,WAAA;EACA,IAAA;EACA,QAAA;AAAA;AAAA,UAGe,iBAAA;EACf,aAAA;EACA,UAAA,EAAY,cAAc;AAAA;AAAA,UAGX,yBAAA;EACf,EAAA;EACA,MAAA;EACA,QAAA;AAAA;AAAA,iBAoBc,iBAAA,CAAkB,GAAA,YAAe,yBAAyB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/validate.ts","../src/build.ts","../src/shadcn.ts","../src/advisories.ts","../src/directory.ts"],"mappings":";UAAiB,YAAA;EACf,GAAA;EACA,MAAM;AAAA;AAAA,KAGI,gBAAA;AAAA,UASK,gBAAA;EACf,EAAA;EACA,QAAA;EACA,gBAAA;EACA,OAAA;EACA,OAAA;EACA,IAAA;AAAA;AAAA,UAGe,YAAA;EACf,aAAA;EACA,IAAA;EACA,IAAA,EAAM,gBAAA;EACN,WAAA;EACA,QAAA;EACA,OAAA;EACA,SAAA;IAAc,OAAA;IAAiB,IAAA;EAAA;EAC/B,MAAA;EACA,OAAA;EACA,QAAA;EACA,KAAA,EAAO,YAAA;EACP,OAAA;EACA,YAAA;EACA,oBAAA;EACA,IAAA;EACA,IAAA;EACA,UAAA,GAAa,gBAAA;AAAA;AAAA,UAGE,aAAA;EACf,aAAA;EACA,IAAA;EACA,QAAA;EACA,KAAA,EAAO,YAAY;AAAA;AAAA,UAGJ,mBAAA;EACf,IAAA;EACA,IAAA;EACA,WAAA;EACA,QAAA;EACA,OAAA;EACA,KAAA;EACA,OAAA;EACA,YAAA;EACA,IAAA;EACA,IAAA;AAAA;AAAA,UAGe,cAAA;EACf,OAAA;EACA,WAAA;EACA,UAAA,EAAY,mBAAmB;AAAA;;;UChEhB,gBAAA;EACf,EAAA;EACA,MAAA;EACA,QAAA;AAAA;AAAA,iBAcc,YAAA,CAAa,GAAA,YAAe,gBAAgB;AAAA,iBAsF5C,aAAA,CAAc,GAAA,YAAe,gBAAgB;AAAA,iBAkC7C,mBAAA,CAAoB,GAAA,YAAe,aAAa;;;iBC5H1C,aAAA,CAAc,KAAA,EAAO,aAAA,EAAe,MAAA,WAAiB,OAAO;;;KCItE,cAAA;AAAA,UAUK,kBAAA;EACf,IAAA;EACA,IAAA,EAAM,cAAc;EACpB,OAAA;EACA,MAAA;AAAA;AAAA,UAGe,kBAAA;EACf,OAAA;EACA,IAAA;EACA,IAAA,EAAM,cAAA;EACN,WAAA;EACA,YAAA;EACA,oBAAA;EACA,KAAA,EAAO,kBAAA;EACP,UAAA;EACA,IAAA,GAAO,MAAA;AAAA;AAAA,UAGQ,eAAA;EH5Bf;EG8BA,cAAA,IAAkB,OAAe;AAAA;AH3BnC;AAAA,iBGyCgB,UAAA,CAAW,IAAY;AAAA,iBASvB,YAAA,CAAa,IAAA,EAAM,YAAA,EAAc,IAAA,GAAM,eAAA,GAAuB,kBAAA;;;;;iBA+BxD,mBAAA,CACpB,KAAA,EAAO,aAAA,EACP,MAAA,UACA,IAAA,GAAM,eAAA,GACL,OAAA;;;iBCjDa,eAAA,CACd,IAAA,EAAM,IAAA,CAAK,YAAA,iBACX,aAAA,WACC,gBAAA;;;UC9Dc,cAAA;EACf,SAAA;EACA,IAAA;EACA,WAAA;EACA,QAAA;EACA,WAAA;EACA,IAAA;EACA,QAAA;AAAA;AAAA,UAGe,iBAAA;EACf,aAAA;EACA,UAAA,EAAY,cAAc;AAAA;AAAA,UAGX,yBAAA;EACf,EAAA;EACA,MAAA;EACA,QAAA;AAAA;AAAA,iBAoBc,iBAAA,CAAkB,GAAA,YAAe,yBAAyB"}
package/dist/index.mjs CHANGED
@@ -163,6 +163,89 @@ async function buildRegistry(index, outDir) {
163
163
  }
164
164
  }
165
165
  //#endregion
166
+ //#region src/shadcn.ts
167
+ /**
168
+ * shadcn-registry-compatible projection of the cascivo registry.
169
+ *
170
+ * This is purely ADDITIVE interop: it maps cascivo's own `RegistryItem`s into
171
+ * the shadcn `registry:*` item schema so the shadcn CLI can install a cascivo
172
+ * component (`npx shadcn add <host>/r/shadcn/<name>.json`). cascivo's own
173
+ * `registry.json` schema is untouched.
174
+ *
175
+ * cascivo is CSS-native: components ship `.tsx` + `.module.css` and rely on a
176
+ * `@cascivo/themes` import plus the `@cascivo/core` peer — there is no Tailwind
177
+ * config, so no `cssVars`/`tailwind` block is emitted.
178
+ */
179
+ const SHADCN_ITEM_SCHEMA = "https://ui.shadcn.com/schema/registry-item.json";
180
+ const SHADCN_REGISTRY_SCHEMA = "https://ui.shadcn.com/schema/registry.json";
181
+ const TYPE_MAP = {
182
+ component: "registry:component",
183
+ layout: "registry:block",
184
+ block: "registry:block",
185
+ section: "registry:block",
186
+ chart: "registry:component",
187
+ theme: "registry:theme",
188
+ style: "registry:style"
189
+ };
190
+ /** Flatten a possibly-prefixed cascivo name ("block/x") into a shadcn slug. */
191
+ function shadcnName(name) {
192
+ return name.replace(/\//g, "-");
193
+ }
194
+ function filePath(fileUrl, slug) {
195
+ return `${slug}/${fileUrl.split("/").pop() ?? fileUrl}`;
196
+ }
197
+ function toShadcnItem(item, opts = {}) {
198
+ const slug = shadcnName(item.name);
199
+ const type = TYPE_MAP[item.type] ?? "registry:component";
200
+ const out = {
201
+ $schema: SHADCN_ITEM_SCHEMA,
202
+ name: slug,
203
+ type,
204
+ files: item.files.map((f) => {
205
+ const file = {
206
+ path: filePath(f.url, slug),
207
+ type
208
+ };
209
+ const content = opts.resolveContent?.(f.url);
210
+ if (content !== void 0) file.content = content;
211
+ return file;
212
+ })
213
+ };
214
+ if (item.description) out.description = item.description;
215
+ if (item.dependencies.length > 0) out.dependencies = [...item.dependencies];
216
+ if (item.registryDependencies && item.registryDependencies.length > 0) out.registryDependencies = [...item.registryDependencies];
217
+ if (item.category) out.categories = [item.category];
218
+ out.meta = { cascivo: {
219
+ type: item.type,
220
+ version: item.version
221
+ } };
222
+ return out;
223
+ }
224
+ /**
225
+ * Write one shadcn `r/<name>.json` per item (with inlined file content when a
226
+ * resolver is supplied) plus a lean `registry.json` index (content omitted).
227
+ */
228
+ async function writeShadcnRegistry(index, outDir, opts = {}) {
229
+ await mkdir(outDir, { recursive: true });
230
+ const items = [...index.items].sort((a, b) => a.name.localeCompare(b.name)).map((it) => toShadcnItem(it, opts));
231
+ for (const item of items) await writeFile(join(outDir, `${item.name}.json`), `${JSON.stringify(item, null, 2)}\n`, "utf8");
232
+ const indexItems = items.map((it) => ({
233
+ ...it,
234
+ files: it.files.map((f) => ({
235
+ path: f.path,
236
+ type: f.type,
237
+ ...f.target ? { target: f.target } : {}
238
+ }))
239
+ }));
240
+ const registry = {
241
+ $schema: SHADCN_REGISTRY_SCHEMA,
242
+ name: index.name,
243
+ ...index.homepage ? { homepage: index.homepage } : {},
244
+ items: indexItems
245
+ };
246
+ await writeFile(join(outDir, "registry.json"), `${JSON.stringify(registry, null, 2)}\n`, "utf8");
247
+ }
248
+ //#endregion
166
249
  //#region src/advisories.ts
167
250
  function parseVersionParts(v) {
168
251
  return v.replace(/^[^0-9]*/, "").split(".").map(Number);
@@ -268,6 +351,6 @@ function validateDirectory(raw) {
268
351
  };
269
352
  }
270
353
  //#endregion
271
- export { buildRegistry, matchAdvisories, parseLegacyRegistry, validateDirectory, validateIndex, validateItem };
354
+ export { buildRegistry, matchAdvisories, parseLegacyRegistry, shadcnName, toShadcnItem, validateDirectory, validateIndex, validateItem, writeShadcnRegistry };
272
355
 
273
356
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/validate.ts","../src/build.ts","../src/advisories.ts","../src/directory.ts"],"sourcesContent":["import type { RegistryIndex, RegistryItem } from './types.ts'\n\nexport interface ValidationResult {\n ok: boolean\n errors: string[]\n warnings: string[]\n}\n\nconst VALID_TYPES = new Set(['component', 'layout', 'block', 'chart', 'section', 'theme', 'style'])\nconst VALID_SEVERITIES = new Set(['low', 'moderate', 'high', 'critical'])\n\nfunction ok(warnings: string[] = []): ValidationResult {\n return { ok: true, errors: [], warnings }\n}\n\nfunction fail(errors: string[], warnings: string[] = []): ValidationResult {\n return { ok: false, errors, warnings }\n}\n\nexport function validateItem(raw: unknown): ValidationResult {\n if (!raw || typeof raw !== 'object') {\n return fail(['Item must be an object'])\n }\n const obj = raw as Record<string, unknown>\n const errors: string[] = []\n const warnings: string[] = []\n\n if (obj['schemaVersion'] !== 2) {\n errors.push(`schemaVersion must be 2, got ${JSON.stringify(obj['schemaVersion'])}`)\n }\n if (typeof obj['name'] !== 'string' || !obj['name']) {\n errors.push('name is required and must be a non-empty string')\n }\n if (!VALID_TYPES.has(obj['type'] as string)) {\n errors.push(\n `type must be one of ${[...VALID_TYPES].join('|')}, got ${JSON.stringify(obj['type'])}`,\n )\n }\n if (typeof obj['description'] !== 'string') {\n errors.push('description is required and must be a string')\n }\n if (typeof obj['version'] !== 'string' || !obj['version']) {\n errors.push('version is required and must be a non-empty string')\n }\n if (!Array.isArray(obj['files'])) {\n errors.push('files is required and must be an array')\n }\n if (!Array.isArray(obj['dependencies'])) {\n errors.push('dependencies is required and must be an array')\n }\n if (!Array.isArray(obj['tags'])) {\n errors.push('tags is required and must be an array')\n }\n\n if (obj['advisories'] !== undefined) {\n if (!Array.isArray(obj['advisories'])) {\n errors.push('advisories must be an array')\n } else {\n const ids = new Set<string>()\n for (const adv of obj['advisories'] as unknown[]) {\n if (!adv || typeof adv !== 'object') {\n errors.push('each advisory must be an object')\n continue\n }\n const a = adv as Record<string, unknown>\n if (typeof a['id'] !== 'string') errors.push('advisory.id must be a string')\n else if (ids.has(a['id'] as string)) errors.push(`advisory id \"${a['id']}\" is not unique`)\n else ids.add(a['id'] as string)\n if (!VALID_SEVERITIES.has(a['severity'] as string))\n errors.push(`advisory.severity must be one of ${[...VALID_SEVERITIES].join('|')}`)\n if (typeof a['affectedVersions'] !== 'string')\n errors.push('advisory.affectedVersions must be a string')\n if (typeof a['summary'] !== 'string') errors.push('advisory.summary must be a string')\n }\n }\n }\n\n const knownKeys = new Set([\n 'schemaVersion',\n 'name',\n 'type',\n 'description',\n 'category',\n 'version',\n 'changelog',\n 'author',\n 'license',\n 'homepage',\n 'files',\n 'install',\n 'dependencies',\n 'registryDependencies',\n 'tags',\n 'meta',\n 'advisories',\n ])\n for (const key of Object.keys(obj)) {\n if (!knownKeys.has(key)) {\n warnings.push(`Unknown field \"${key}\" — ignored (forward compat)`)\n }\n }\n\n return errors.length > 0 ? fail(errors, warnings) : ok(warnings)\n}\n\nexport function validateIndex(raw: unknown): ValidationResult {\n if (!raw || typeof raw !== 'object') {\n return fail(['Index must be an object'])\n }\n const obj = raw as Record<string, unknown>\n const errors: string[] = []\n const warnings: string[] = []\n\n if (obj['schemaVersion'] !== 2) {\n errors.push(`schemaVersion must be 2, got ${JSON.stringify(obj['schemaVersion'])}`)\n }\n if (typeof obj['name'] !== 'string' || !obj['name']) {\n errors.push('name is required and must be a non-empty string')\n }\n if (!Array.isArray(obj['items'])) {\n errors.push('items is required and must be an array')\n } else {\n for (let i = 0; i < obj['items'].length; i++) {\n const itemResult = validateItem(obj['items'][i])\n for (const e of itemResult.errors) errors.push(`items[${i}]: ${e}`)\n for (const w of itemResult.warnings) warnings.push(`items[${i}]: ${w}`)\n }\n }\n\n const knownKeys = new Set(['schemaVersion', 'name', 'homepage', 'items'])\n for (const key of Object.keys(obj)) {\n if (!knownKeys.has(key)) {\n warnings.push(`Unknown field \"${key}\" — ignored (forward compat)`)\n }\n }\n\n return errors.length > 0 ? fail(errors, warnings) : ok(warnings)\n}\n\nexport function parseLegacyRegistry(raw: unknown): RegistryIndex {\n if (!raw || typeof raw !== 'object') throw new Error('Legacy registry must be an object')\n const obj = raw as Record<string, unknown>\n const topVersion = typeof obj['version'] === 'string' ? obj['version'] : '0.0.0'\n const components = Array.isArray(obj['components']) ? obj['components'] : []\n\n return {\n schemaVersion: 2,\n name: 'cascivo',\n items: (components as Record<string, unknown>[]).map((c) => {\n const item: RegistryItem = {\n schemaVersion: 2,\n name: typeof c['name'] === 'string' ? c['name'] : '',\n type: (c['type'] as RegistryItem['type']) ?? 'component',\n description: typeof c['description'] === 'string' ? c['description'] : '',\n version: topVersion,\n files: Array.isArray(c['files']) ? (c['files'] as string[]).map((url) => ({ url })) : [],\n dependencies: Array.isArray(c['dependencies']) ? (c['dependencies'] as string[]) : [],\n tags: Array.isArray(c['tags']) ? (c['tags'] as string[]) : [],\n }\n if (typeof c['category'] === 'string') item.category = c['category']\n if (typeof c['install'] === 'string') item.install = c['install']\n if (c['meta']) item.meta = c['meta'] as RegistryItem['meta']\n return item\n }),\n }\n}\n","import { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { RegistryIndex, RegistryItem } from './types.ts'\n\nfunction flatName(name: string): string {\n return name.replace(/\\//g, '-')\n}\n\nfunction itemWithoutExamples(item: RegistryItem): RegistryItem {\n if (!item.meta || typeof item.meta !== 'object') return item\n const meta = item.meta as Record<string, unknown>\n if (!Array.isArray(meta['examples']) || meta['examples'].length === 0) return item\n return { ...item, meta: { ...meta, examples: [] } }\n}\n\nexport async function buildRegistry(index: RegistryIndex, outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true })\n\n const sortedItems = [...index.items].sort((a, b) => a.name.localeCompare(b.name))\n\n const indexOut: RegistryIndex = {\n schemaVersion: 2,\n name: index.name,\n ...(index.homepage ? { homepage: index.homepage } : {}),\n items: sortedItems.map(itemWithoutExamples),\n }\n await writeFile(join(outDir, 'registry.json'), `${JSON.stringify(indexOut, null, 2)}\\n`, 'utf8')\n\n for (const item of sortedItems) {\n const flat = flatName(item.name)\n await writeFile(join(outDir, `${flat}.json`), `${JSON.stringify(item, null, 2)}\\n`, 'utf8')\n await writeFile(\n join(outDir, `${flat}@${item.version}.json`),\n `${JSON.stringify(item, null, 2)}\\n`,\n 'utf8',\n )\n }\n}\n","import type { RegistryAdvisory, RegistryItem } from './types.ts'\n\nfunction parseVersionParts(v: string): number[] {\n return v\n .replace(/^[^0-9]*/, '')\n .split('.')\n .map(Number)\n}\n\nfunction compareVersions(a: string, b: string): number {\n const pa = parseVersionParts(a)\n const pb = parseVersionParts(b)\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const na = pa[i] ?? 0\n const nb = pb[i] ?? 0\n if (na !== nb) return na - nb\n }\n return 0\n}\n\nfunction matchesRange(version: string, range: string): boolean {\n try {\n const trimmed = range.trim()\n if (trimmed.startsWith('>=')) {\n return compareVersions(version, trimmed.slice(2).trim()) >= 0\n }\n if (trimmed.startsWith('>')) {\n return compareVersions(version, trimmed.slice(1).trim()) > 0\n }\n if (trimmed.startsWith('<=')) {\n return compareVersions(version, trimmed.slice(2).trim()) <= 0\n }\n if (trimmed.startsWith('<')) {\n return compareVersions(version, trimmed.slice(1).trim()) < 0\n }\n if (trimmed.startsWith('^')) {\n const base = trimmed.slice(1).trim()\n const baseParts = parseVersionParts(base)\n const major = baseParts[0] ?? 0\n const vParts = parseVersionParts(version)\n const vMajor = vParts[0] ?? 0\n return vMajor === major && compareVersions(version, base) >= 0\n }\n if (trimmed.startsWith('~')) {\n const base = trimmed.slice(1).trim()\n const baseParts = parseVersionParts(base)\n const major = baseParts[0] ?? 0\n const minor = baseParts[1] ?? 0\n const vParts = parseVersionParts(version)\n const vMajor = vParts[0] ?? 0\n const vMinor = vParts[1] ?? 0\n return vMajor === major && vMinor === minor && compareVersions(version, base) >= 0\n }\n return version === trimmed\n } catch {\n return false\n }\n}\n\nexport function matchAdvisories(\n item: Pick<RegistryItem, 'advisories'>,\n lockedVersion: string,\n): RegistryAdvisory[] {\n if (!item.advisories) return []\n const matched: RegistryAdvisory[] = []\n for (const adv of item.advisories) {\n try {\n if (matchesRange(lockedVersion, adv.affectedVersions)) {\n matched.push(adv)\n }\n } catch {\n // malformed range — skip silently, never crash an audit\n }\n }\n return matched\n}\n","export interface DirectoryEntry {\n namespace: string\n name: string\n description: string\n homepage: string\n registryUrl: string\n tags: string[]\n verified: boolean\n}\n\nexport interface RegistryDirectory {\n schemaVersion: 1\n registries: DirectoryEntry[]\n}\n\nexport interface DirectoryValidationResult {\n ok: boolean\n errors: string[]\n warnings: string[]\n}\n\nfunction levenshtein(a: string, b: string): number {\n const m = a.length\n const n = b.length\n const dp: number[][] = Array.from({ length: m + 1 }, (_, i) =>\n Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)),\n )\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n dp[i]![j] =\n a[i - 1] === b[j - 1]\n ? dp[i - 1]![j - 1]!\n : 1 + Math.min(dp[i - 1]![j]!, dp[i]![j - 1]!, dp[i - 1]![j - 1]!)\n }\n }\n return dp[m]![n]!\n}\n\nexport function validateDirectory(raw: unknown): DirectoryValidationResult {\n if (!raw || typeof raw !== 'object') {\n return { ok: false, errors: ['Directory must be an object'], warnings: [] }\n }\n const obj = raw as Record<string, unknown>\n const errors: string[] = []\n const warnings: string[] = []\n\n if (obj['schemaVersion'] !== 1) {\n errors.push(`schemaVersion must be 1, got ${JSON.stringify(obj['schemaVersion'])}`)\n }\n if (!Array.isArray(obj['registries'])) {\n errors.push('registries must be an array')\n return { ok: false, errors, warnings }\n }\n\n const namespaces: string[] = []\n for (let i = 0; i < obj['registries'].length; i++) {\n const entry = obj['registries'][i] as Record<string, unknown>\n const ns = entry['namespace']\n if (typeof ns !== 'string' || !ns) errors.push(`registries[${i}].namespace is required`)\n else {\n if (namespaces.includes(ns)) errors.push(`Duplicate namespace \"${ns}\" at index ${i}`)\n namespaces.push(ns)\n }\n if (typeof entry['name'] !== 'string') errors.push(`registries[${i}].name is required`)\n if (typeof entry['description'] !== 'string')\n errors.push(`registries[${i}].description is required`)\n if (typeof entry['homepage'] !== 'string') errors.push(`registries[${i}].homepage is required`)\n if (typeof entry['registryUrl'] !== 'string')\n errors.push(`registries[${i}].registryUrl is required`)\n else if (!(entry['registryUrl'] as string).includes('{name}'))\n errors.push(`registries[${i}].registryUrl must contain {name} placeholder`)\n if (!Array.isArray(entry['tags'])) errors.push(`registries[${i}].tags must be an array`)\n if (typeof entry['verified'] !== 'boolean')\n errors.push(`registries[${i}].verified must be a boolean`)\n }\n\n for (let i = 0; i < namespaces.length; i++) {\n for (let j = i + 1; j < namespaces.length; j++) {\n const a = namespaces[i]!\n const b = namespaces[j]!\n if (levenshtein(a, b) <= 2) {\n warnings.push(\n `Namespaces \"${a}\" and \"${b}\" are suspiciously similar (Levenshtein distance ≤ 2)`,\n )\n }\n }\n }\n\n return { ok: errors.length === 0, errors, warnings }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/validate.ts","../src/build.ts","../src/shadcn.ts","../src/advisories.ts","../src/directory.ts"],"sourcesContent":["import type { RegistryIndex, RegistryItem } from './types.ts'\n\nexport interface ValidationResult {\n ok: boolean\n errors: string[]\n warnings: string[]\n}\n\nconst VALID_TYPES = new Set(['component', 'layout', 'block', 'chart', 'section', 'theme', 'style'])\nconst VALID_SEVERITIES = new Set(['low', 'moderate', 'high', 'critical'])\n\nfunction ok(warnings: string[] = []): ValidationResult {\n return { ok: true, errors: [], warnings }\n}\n\nfunction fail(errors: string[], warnings: string[] = []): ValidationResult {\n return { ok: false, errors, warnings }\n}\n\nexport function validateItem(raw: unknown): ValidationResult {\n if (!raw || typeof raw !== 'object') {\n return fail(['Item must be an object'])\n }\n const obj = raw as Record<string, unknown>\n const errors: string[] = []\n const warnings: string[] = []\n\n if (obj['schemaVersion'] !== 2) {\n errors.push(`schemaVersion must be 2, got ${JSON.stringify(obj['schemaVersion'])}`)\n }\n if (typeof obj['name'] !== 'string' || !obj['name']) {\n errors.push('name is required and must be a non-empty string')\n }\n if (!VALID_TYPES.has(obj['type'] as string)) {\n errors.push(\n `type must be one of ${[...VALID_TYPES].join('|')}, got ${JSON.stringify(obj['type'])}`,\n )\n }\n if (typeof obj['description'] !== 'string') {\n errors.push('description is required and must be a string')\n }\n if (typeof obj['version'] !== 'string' || !obj['version']) {\n errors.push('version is required and must be a non-empty string')\n }\n if (!Array.isArray(obj['files'])) {\n errors.push('files is required and must be an array')\n }\n if (!Array.isArray(obj['dependencies'])) {\n errors.push('dependencies is required and must be an array')\n }\n if (!Array.isArray(obj['tags'])) {\n errors.push('tags is required and must be an array')\n }\n\n if (obj['advisories'] !== undefined) {\n if (!Array.isArray(obj['advisories'])) {\n errors.push('advisories must be an array')\n } else {\n const ids = new Set<string>()\n for (const adv of obj['advisories'] as unknown[]) {\n if (!adv || typeof adv !== 'object') {\n errors.push('each advisory must be an object')\n continue\n }\n const a = adv as Record<string, unknown>\n if (typeof a['id'] !== 'string') errors.push('advisory.id must be a string')\n else if (ids.has(a['id'] as string)) errors.push(`advisory id \"${a['id']}\" is not unique`)\n else ids.add(a['id'] as string)\n if (!VALID_SEVERITIES.has(a['severity'] as string))\n errors.push(`advisory.severity must be one of ${[...VALID_SEVERITIES].join('|')}`)\n if (typeof a['affectedVersions'] !== 'string')\n errors.push('advisory.affectedVersions must be a string')\n if (typeof a['summary'] !== 'string') errors.push('advisory.summary must be a string')\n }\n }\n }\n\n const knownKeys = new Set([\n 'schemaVersion',\n 'name',\n 'type',\n 'description',\n 'category',\n 'version',\n 'changelog',\n 'author',\n 'license',\n 'homepage',\n 'files',\n 'install',\n 'dependencies',\n 'registryDependencies',\n 'tags',\n 'meta',\n 'advisories',\n ])\n for (const key of Object.keys(obj)) {\n if (!knownKeys.has(key)) {\n warnings.push(`Unknown field \"${key}\" — ignored (forward compat)`)\n }\n }\n\n return errors.length > 0 ? fail(errors, warnings) : ok(warnings)\n}\n\nexport function validateIndex(raw: unknown): ValidationResult {\n if (!raw || typeof raw !== 'object') {\n return fail(['Index must be an object'])\n }\n const obj = raw as Record<string, unknown>\n const errors: string[] = []\n const warnings: string[] = []\n\n if (obj['schemaVersion'] !== 2) {\n errors.push(`schemaVersion must be 2, got ${JSON.stringify(obj['schemaVersion'])}`)\n }\n if (typeof obj['name'] !== 'string' || !obj['name']) {\n errors.push('name is required and must be a non-empty string')\n }\n if (!Array.isArray(obj['items'])) {\n errors.push('items is required and must be an array')\n } else {\n for (let i = 0; i < obj['items'].length; i++) {\n const itemResult = validateItem(obj['items'][i])\n for (const e of itemResult.errors) errors.push(`items[${i}]: ${e}`)\n for (const w of itemResult.warnings) warnings.push(`items[${i}]: ${w}`)\n }\n }\n\n const knownKeys = new Set(['schemaVersion', 'name', 'homepage', 'items'])\n for (const key of Object.keys(obj)) {\n if (!knownKeys.has(key)) {\n warnings.push(`Unknown field \"${key}\" — ignored (forward compat)`)\n }\n }\n\n return errors.length > 0 ? fail(errors, warnings) : ok(warnings)\n}\n\nexport function parseLegacyRegistry(raw: unknown): RegistryIndex {\n if (!raw || typeof raw !== 'object') throw new Error('Legacy registry must be an object')\n const obj = raw as Record<string, unknown>\n const topVersion = typeof obj['version'] === 'string' ? obj['version'] : '0.0.0'\n const components = Array.isArray(obj['components']) ? obj['components'] : []\n\n return {\n schemaVersion: 2,\n name: 'cascivo',\n items: (components as Record<string, unknown>[]).map((c) => {\n const item: RegistryItem = {\n schemaVersion: 2,\n name: typeof c['name'] === 'string' ? c['name'] : '',\n type: (c['type'] as RegistryItem['type']) ?? 'component',\n description: typeof c['description'] === 'string' ? c['description'] : '',\n version: topVersion,\n files: Array.isArray(c['files']) ? (c['files'] as string[]).map((url) => ({ url })) : [],\n dependencies: Array.isArray(c['dependencies']) ? (c['dependencies'] as string[]) : [],\n tags: Array.isArray(c['tags']) ? (c['tags'] as string[]) : [],\n }\n if (typeof c['category'] === 'string') item.category = c['category']\n if (typeof c['install'] === 'string') item.install = c['install']\n if (c['meta']) item.meta = c['meta'] as RegistryItem['meta']\n return item\n }),\n }\n}\n","import { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { RegistryIndex, RegistryItem } from './types.ts'\n\nfunction flatName(name: string): string {\n return name.replace(/\\//g, '-')\n}\n\nfunction itemWithoutExamples(item: RegistryItem): RegistryItem {\n if (!item.meta || typeof item.meta !== 'object') return item\n const meta = item.meta as Record<string, unknown>\n if (!Array.isArray(meta['examples']) || meta['examples'].length === 0) return item\n return { ...item, meta: { ...meta, examples: [] } }\n}\n\nexport async function buildRegistry(index: RegistryIndex, outDir: string): Promise<void> {\n await mkdir(outDir, { recursive: true })\n\n const sortedItems = [...index.items].sort((a, b) => a.name.localeCompare(b.name))\n\n const indexOut: RegistryIndex = {\n schemaVersion: 2,\n name: index.name,\n ...(index.homepage ? { homepage: index.homepage } : {}),\n items: sortedItems.map(itemWithoutExamples),\n }\n await writeFile(join(outDir, 'registry.json'), `${JSON.stringify(indexOut, null, 2)}\\n`, 'utf8')\n\n for (const item of sortedItems) {\n const flat = flatName(item.name)\n await writeFile(join(outDir, `${flat}.json`), `${JSON.stringify(item, null, 2)}\\n`, 'utf8')\n await writeFile(\n join(outDir, `${flat}@${item.version}.json`),\n `${JSON.stringify(item, null, 2)}\\n`,\n 'utf8',\n )\n }\n}\n","/**\n * shadcn-registry-compatible projection of the cascivo registry.\n *\n * This is purely ADDITIVE interop: it maps cascivo's own `RegistryItem`s into\n * the shadcn `registry:*` item schema so the shadcn CLI can install a cascivo\n * component (`npx shadcn add <host>/r/shadcn/<name>.json`). cascivo's own\n * `registry.json` schema is untouched.\n *\n * cascivo is CSS-native: components ship `.tsx` + `.module.css` and rely on a\n * `@cascivo/themes` import plus the `@cascivo/core` peer — there is no Tailwind\n * config, so no `cssVars`/`tailwind` block is emitted.\n */\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { RegistryIndex, RegistryItem, RegistryItemType } from './types.ts'\n\nconst SHADCN_ITEM_SCHEMA = 'https://ui.shadcn.com/schema/registry-item.json'\nconst SHADCN_REGISTRY_SCHEMA = 'https://ui.shadcn.com/schema/registry.json'\n\nexport type ShadcnItemType =\n | 'registry:component'\n | 'registry:block'\n | 'registry:lib'\n | 'registry:ui'\n | 'registry:hook'\n | 'registry:theme'\n | 'registry:style'\n | 'registry:file'\n\nexport interface ShadcnRegistryFile {\n path: string\n type: ShadcnItemType\n content?: string\n target?: string\n}\n\nexport interface ShadcnRegistryItem {\n $schema: string\n name: string\n type: ShadcnItemType\n description?: string\n dependencies?: string[]\n registryDependencies?: string[]\n files: ShadcnRegistryFile[]\n categories?: string[]\n meta?: Record<string, unknown>\n}\n\nexport interface ToShadcnOptions {\n /** Resolve a cascivo file URL to its source text, to inline as `content`. */\n resolveContent?: (fileUrl: string) => string | undefined\n}\n\nconst TYPE_MAP: Record<RegistryItemType, ShadcnItemType> = {\n component: 'registry:component',\n layout: 'registry:block',\n block: 'registry:block',\n section: 'registry:block',\n chart: 'registry:component',\n theme: 'registry:theme',\n style: 'registry:style',\n}\n\n/** Flatten a possibly-prefixed cascivo name (\"block/x\") into a shadcn slug. */\nexport function shadcnName(name: string): string {\n return name.replace(/\\//g, '-')\n}\n\nfunction filePath(fileUrl: string, slug: string): string {\n const base = fileUrl.split('/').pop() ?? fileUrl\n return `${slug}/${base}`\n}\n\nexport function toShadcnItem(item: RegistryItem, opts: ToShadcnOptions = {}): ShadcnRegistryItem {\n const slug = shadcnName(item.name)\n const type = TYPE_MAP[item.type] ?? 'registry:component'\n\n const files: ShadcnRegistryFile[] = item.files.map((f) => {\n const file: ShadcnRegistryFile = { path: filePath(f.url, slug), type }\n const content = opts.resolveContent?.(f.url)\n if (content !== undefined) file.content = content\n return file\n })\n\n const out: ShadcnRegistryItem = {\n $schema: SHADCN_ITEM_SCHEMA,\n name: slug,\n type,\n files,\n }\n if (item.description) out.description = item.description\n if (item.dependencies.length > 0) out.dependencies = [...item.dependencies]\n if (item.registryDependencies && item.registryDependencies.length > 0) {\n out.registryDependencies = [...item.registryDependencies]\n }\n if (item.category) out.categories = [item.category]\n out.meta = { cascivo: { type: item.type, version: item.version } }\n return out\n}\n\n/**\n * Write one shadcn `r/<name>.json` per item (with inlined file content when a\n * resolver is supplied) plus a lean `registry.json` index (content omitted).\n */\nexport async function writeShadcnRegistry(\n index: RegistryIndex,\n outDir: string,\n opts: ToShadcnOptions = {},\n): Promise<void> {\n await mkdir(outDir, { recursive: true })\n\n const sorted = [...index.items].sort((a, b) => a.name.localeCompare(b.name))\n const items = sorted.map((it) => toShadcnItem(it, opts))\n\n for (const item of items) {\n await writeFile(join(outDir, `${item.name}.json`), `${JSON.stringify(item, null, 2)}\\n`, 'utf8')\n }\n\n const indexItems = items.map((it) => ({\n ...it,\n files: it.files.map((f) => ({\n path: f.path,\n type: f.type,\n ...(f.target ? { target: f.target } : {}),\n })),\n }))\n const registry = {\n $schema: SHADCN_REGISTRY_SCHEMA,\n name: index.name,\n ...(index.homepage ? { homepage: index.homepage } : {}),\n items: indexItems,\n }\n await writeFile(join(outDir, 'registry.json'), `${JSON.stringify(registry, null, 2)}\\n`, 'utf8')\n}\n","import type { RegistryAdvisory, RegistryItem } from './types.ts'\n\nfunction parseVersionParts(v: string): number[] {\n return v\n .replace(/^[^0-9]*/, '')\n .split('.')\n .map(Number)\n}\n\nfunction compareVersions(a: string, b: string): number {\n const pa = parseVersionParts(a)\n const pb = parseVersionParts(b)\n for (let i = 0; i < Math.max(pa.length, pb.length); i++) {\n const na = pa[i] ?? 0\n const nb = pb[i] ?? 0\n if (na !== nb) return na - nb\n }\n return 0\n}\n\nfunction matchesRange(version: string, range: string): boolean {\n try {\n const trimmed = range.trim()\n if (trimmed.startsWith('>=')) {\n return compareVersions(version, trimmed.slice(2).trim()) >= 0\n }\n if (trimmed.startsWith('>')) {\n return compareVersions(version, trimmed.slice(1).trim()) > 0\n }\n if (trimmed.startsWith('<=')) {\n return compareVersions(version, trimmed.slice(2).trim()) <= 0\n }\n if (trimmed.startsWith('<')) {\n return compareVersions(version, trimmed.slice(1).trim()) < 0\n }\n if (trimmed.startsWith('^')) {\n const base = trimmed.slice(1).trim()\n const baseParts = parseVersionParts(base)\n const major = baseParts[0] ?? 0\n const vParts = parseVersionParts(version)\n const vMajor = vParts[0] ?? 0\n return vMajor === major && compareVersions(version, base) >= 0\n }\n if (trimmed.startsWith('~')) {\n const base = trimmed.slice(1).trim()\n const baseParts = parseVersionParts(base)\n const major = baseParts[0] ?? 0\n const minor = baseParts[1] ?? 0\n const vParts = parseVersionParts(version)\n const vMajor = vParts[0] ?? 0\n const vMinor = vParts[1] ?? 0\n return vMajor === major && vMinor === minor && compareVersions(version, base) >= 0\n }\n return version === trimmed\n } catch {\n return false\n }\n}\n\nexport function matchAdvisories(\n item: Pick<RegistryItem, 'advisories'>,\n lockedVersion: string,\n): RegistryAdvisory[] {\n if (!item.advisories) return []\n const matched: RegistryAdvisory[] = []\n for (const adv of item.advisories) {\n try {\n if (matchesRange(lockedVersion, adv.affectedVersions)) {\n matched.push(adv)\n }\n } catch {\n // malformed range — skip silently, never crash an audit\n }\n }\n return matched\n}\n","export interface DirectoryEntry {\n namespace: string\n name: string\n description: string\n homepage: string\n registryUrl: string\n tags: string[]\n verified: boolean\n}\n\nexport interface RegistryDirectory {\n schemaVersion: 1\n registries: DirectoryEntry[]\n}\n\nexport interface DirectoryValidationResult {\n ok: boolean\n errors: string[]\n warnings: string[]\n}\n\nfunction levenshtein(a: string, b: string): number {\n const m = a.length\n const n = b.length\n const dp: number[][] = Array.from({ length: m + 1 }, (_, i) =>\n Array.from({ length: n + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)),\n )\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n dp[i]![j] =\n a[i - 1] === b[j - 1]\n ? dp[i - 1]![j - 1]!\n : 1 + Math.min(dp[i - 1]![j]!, dp[i]![j - 1]!, dp[i - 1]![j - 1]!)\n }\n }\n return dp[m]![n]!\n}\n\nexport function validateDirectory(raw: unknown): DirectoryValidationResult {\n if (!raw || typeof raw !== 'object') {\n return { ok: false, errors: ['Directory must be an object'], warnings: [] }\n }\n const obj = raw as Record<string, unknown>\n const errors: string[] = []\n const warnings: string[] = []\n\n if (obj['schemaVersion'] !== 1) {\n errors.push(`schemaVersion must be 1, got ${JSON.stringify(obj['schemaVersion'])}`)\n }\n if (!Array.isArray(obj['registries'])) {\n errors.push('registries must be an array')\n return { ok: false, errors, warnings }\n }\n\n const namespaces: string[] = []\n for (let i = 0; i < obj['registries'].length; i++) {\n const entry = obj['registries'][i] as Record<string, unknown>\n const ns = entry['namespace']\n if (typeof ns !== 'string' || !ns) errors.push(`registries[${i}].namespace is required`)\n else {\n if (namespaces.includes(ns)) errors.push(`Duplicate namespace \"${ns}\" at index ${i}`)\n namespaces.push(ns)\n }\n if (typeof entry['name'] !== 'string') errors.push(`registries[${i}].name is required`)\n if (typeof entry['description'] !== 'string')\n errors.push(`registries[${i}].description is required`)\n if (typeof entry['homepage'] !== 'string') errors.push(`registries[${i}].homepage is required`)\n if (typeof entry['registryUrl'] !== 'string')\n errors.push(`registries[${i}].registryUrl is required`)\n else if (!(entry['registryUrl'] as string).includes('{name}'))\n errors.push(`registries[${i}].registryUrl must contain {name} placeholder`)\n if (!Array.isArray(entry['tags'])) errors.push(`registries[${i}].tags must be an array`)\n if (typeof entry['verified'] !== 'boolean')\n errors.push(`registries[${i}].verified must be a boolean`)\n }\n\n for (let i = 0; i < namespaces.length; i++) {\n for (let j = i + 1; j < namespaces.length; j++) {\n const a = namespaces[i]!\n const b = namespaces[j]!\n if (levenshtein(a, b) <= 2) {\n warnings.push(\n `Namespaces \"${a}\" and \"${b}\" are suspiciously similar (Levenshtein distance ≤ 2)`,\n )\n }\n }\n }\n\n return { ok: errors.length === 0, errors, warnings }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@cascivo/registry",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "private": false,
5
- "description": "Registry schema v2 types, validation, and static build for the cascade ecosystem",
5
+ "description": "Registry schema v2 types, validation, and static build for the cascivo ecosystem",
6
6
  "keywords": [
7
7
  "cascivo",
8
8
  "components",
@@ -12,13 +12,13 @@
12
12
  "registry",
13
13
  "signals"
14
14
  ],
15
- "homepage": "https://github.com/urbanisierung/cascivo/tree/main/packages/registry#readme",
16
- "bugs": "https://github.com/urbanisierung/cascivo/issues",
15
+ "homepage": "https://github.com/cascivo/cascivo/tree/main/packages/registry#readme",
16
+ "bugs": "https://github.com/cascivo/cascivo/issues",
17
17
  "license": "MIT",
18
18
  "author": "urbanisierung",
19
19
  "repository": {
20
20
  "type": "git",
21
- "url": "git+https://github.com/urbanisierung/cascivo.git",
21
+ "url": "git+https://github.com/cascivo/cascivo.git",
22
22
  "directory": "packages/registry"
23
23
  },
24
24
  "files": [
@@ -40,7 +40,7 @@
40
40
  "devDependencies": {
41
41
  "@types/node": "^25",
42
42
  "typescript": "^5",
43
- "vite-plus": "^0.1.24"
43
+ "vite-plus": "^0.2.1"
44
44
  },
45
45
  "scripts": {
46
46
  "build": "vp pack",
package/readme.body.md CHANGED
@@ -1 +1,13 @@
1
1
  Registry client and type definitions — reads `registry.json` and validates component entries. Used internally by the CLI and MCP server.
2
+
3
+ ## shadcn registry interop
4
+
5
+ In addition to cascivo's own registry, the build emits a **shadcn-registry-compatible** projection so the shadcn CLI can install a cascivo component directly:
6
+
7
+ ```sh
8
+ npx shadcn add https://<host>/r/shadcn/button.json
9
+ ```
10
+
11
+ Each `r/shadcn/<name>.json` is a shadcn `registry:component` item with the source files inlined as `content`. This is purely additive — `npx cascivo add` and cascivo's own `registry.json` schema are unchanged.
12
+
13
+ **CSS-native caveat:** cascivo components are `.tsx` + `.module.css` and rely on the `@cascivo/core` peer plus a `@cascivo/themes` stylesheet import — there is no Tailwind config or `cssVars` block to merge. After adding a component via the shadcn CLI, install `@cascivo/core` and import a theme (e.g. `@cascivo/themes/light.css`).