cascivo 0.1.4 → 0.2.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 +14 -8
- package/dist/{audit-AHr4MDMK.mjs → audit-BRn4MeXD.mjs} +8 -8
- package/dist/{audit-AHr4MDMK.mjs.map → audit-BRn4MeXD.mjs.map} +1 -1
- package/dist/config-CsnCR5eh.mjs +82 -0
- package/dist/config-CsnCR5eh.mjs.map +1 -0
- package/dist/{eject-D_mC1lsq.mjs → eject-B92gZhLX.mjs} +3 -3
- package/dist/{eject-D_mC1lsq.mjs.map → eject-B92gZhLX.mjs.map} +1 -1
- package/dist/fs-m7ZvuBBm.mjs +24 -0
- package/dist/fs-m7ZvuBBm.mjs.map +1 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +590 -120
- package/dist/index.mjs.map +1 -1
- package/dist/template-init-DGEgatij.mjs +179 -0
- package/dist/template-init-DGEgatij.mjs.map +1 -0
- package/package.json +2 -2
- package/readme.body.md +14 -8
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { r as writeFileSafe } from "./fs-m7ZvuBBm.mjs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
//#region src/commands/template-init.ts
|
|
6
|
+
function pascal(name) {
|
|
7
|
+
return name.split(/[-_/]/).filter(Boolean).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
|
|
8
|
+
}
|
|
9
|
+
function rawUrl(repo, path) {
|
|
10
|
+
if (!repo) return path;
|
|
11
|
+
return `https://raw.githubusercontent.com/${repo}/main/${path}`;
|
|
12
|
+
}
|
|
13
|
+
function pageSource(name, components) {
|
|
14
|
+
const comp = pascal(name);
|
|
15
|
+
return `${components.length > 0 ? `// Components installed via the template's registryDependencies:\n// ${components.join(", ")}\n` : ""}import './${name}.module.css'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* ${comp} template page. Owned, copy-paste source — adapt freely.
|
|
19
|
+
* Presentational only: no useState/useEffect (cascade house rules).
|
|
20
|
+
*/
|
|
21
|
+
export function ${comp}Page() {
|
|
22
|
+
return (
|
|
23
|
+
<main className="${name}-page">
|
|
24
|
+
<h1>${comp}</h1>
|
|
25
|
+
{/* Compose the template's components here. */}
|
|
26
|
+
</main>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
}
|
|
31
|
+
function cssSource(name) {
|
|
32
|
+
return `@layer components {
|
|
33
|
+
.${name}-page {
|
|
34
|
+
display: grid;
|
|
35
|
+
gap: var(--cascivo-space-4, 1rem);
|
|
36
|
+
padding: var(--cascivo-space-4, 1rem);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
}
|
|
41
|
+
function fixturesSource(name) {
|
|
42
|
+
return `/** Mock data for the ${name} template. Replace with your real source. */
|
|
43
|
+
export const ${name.replace(/-/g, "_")}Fixtures = {
|
|
44
|
+
items: [],
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
}
|
|
48
|
+
function templateMetaSource(meta) {
|
|
49
|
+
return `import type { TemplateMeta } from '@cascivo/registry'
|
|
50
|
+
|
|
51
|
+
export const meta: TemplateMeta = ${JSON.stringify(meta, null, 2)}
|
|
52
|
+
`;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build the files + registry item for a new template. Pure — no I/O — so it can
|
|
56
|
+
* be unit-tested. The caller writes the files and merges the item into
|
|
57
|
+
* `cascade-registry.json`.
|
|
58
|
+
*/
|
|
59
|
+
function buildTemplateScaffold(opts) {
|
|
60
|
+
const { name, category, framework, components, repo, license, author } = opts;
|
|
61
|
+
const dir = `src/${name}`;
|
|
62
|
+
const pageTarget = `src/pages/${name}.tsx`;
|
|
63
|
+
const cssTarget = `src/pages/${name}.module.css`;
|
|
64
|
+
const fixturesTarget = `src/fixtures/${name}.ts`;
|
|
65
|
+
const files = [
|
|
66
|
+
{
|
|
67
|
+
path: `${dir}/${name}.tsx`,
|
|
68
|
+
contents: pageSource(name, components)
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
path: `${dir}/${name}.module.css`,
|
|
72
|
+
contents: cssSource(name)
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
path: `${dir}/fixtures.ts`,
|
|
76
|
+
contents: fixturesSource(name)
|
|
77
|
+
}
|
|
78
|
+
];
|
|
79
|
+
const meta = {
|
|
80
|
+
intent: `${pascal(name)} template`,
|
|
81
|
+
framework,
|
|
82
|
+
category,
|
|
83
|
+
screenshots: [{
|
|
84
|
+
light: rawUrl(repo, `screenshots/${name}-light.png`),
|
|
85
|
+
alt: `${name} preview (light)`
|
|
86
|
+
}],
|
|
87
|
+
fileRoles: {
|
|
88
|
+
[pageTarget]: "page",
|
|
89
|
+
[cssTarget]: "asset",
|
|
90
|
+
[fixturesTarget]: "fixture"
|
|
91
|
+
},
|
|
92
|
+
pages: [{
|
|
93
|
+
name: pascal(name),
|
|
94
|
+
target: pageTarget
|
|
95
|
+
}]
|
|
96
|
+
};
|
|
97
|
+
const item = {
|
|
98
|
+
schemaVersion: 2,
|
|
99
|
+
name,
|
|
100
|
+
type: "template",
|
|
101
|
+
description: `${pascal(name)} template`,
|
|
102
|
+
category,
|
|
103
|
+
version: "0.1.0",
|
|
104
|
+
license,
|
|
105
|
+
...author ? { author } : {},
|
|
106
|
+
...repo ? { homepage: `https://github.com/${repo}` } : {},
|
|
107
|
+
files: [
|
|
108
|
+
{
|
|
109
|
+
url: rawUrl(repo, `${dir}/${name}.tsx`),
|
|
110
|
+
target: pageTarget
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
url: rawUrl(repo, `${dir}/${name}.module.css`),
|
|
114
|
+
target: cssTarget
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
url: rawUrl(repo, `${dir}/fixtures.ts`),
|
|
118
|
+
target: fixturesTarget
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
dependencies: [],
|
|
122
|
+
registryDependencies: components,
|
|
123
|
+
tags: [category, "template"],
|
|
124
|
+
meta
|
|
125
|
+
};
|
|
126
|
+
files.push({
|
|
127
|
+
path: `${dir}/${name}.template.ts`,
|
|
128
|
+
contents: templateMetaSource(meta)
|
|
129
|
+
});
|
|
130
|
+
return {
|
|
131
|
+
files,
|
|
132
|
+
item
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function flag(args, key) {
|
|
136
|
+
const eq = args.find((a) => a.startsWith(`--${key}=`));
|
|
137
|
+
if (eq) return eq.slice(key.length + 3);
|
|
138
|
+
const idx = args.indexOf(`--${key}`);
|
|
139
|
+
const next = idx !== -1 ? args[idx + 1] : void 0;
|
|
140
|
+
return next && !next.startsWith("--") ? next : void 0;
|
|
141
|
+
}
|
|
142
|
+
async function templateInit(args, cwd = process.cwd()) {
|
|
143
|
+
const name = args.find((a) => !a.startsWith("-"));
|
|
144
|
+
if (!name) {
|
|
145
|
+
console.error("Usage: cascivo template init <name> [--category dashboard] [--framework react-vite] [--components card,line-chart] [--repo owner/repo]");
|
|
146
|
+
process.exitCode = 1;
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const componentsArg = flag(args, "components");
|
|
150
|
+
const opts = {
|
|
151
|
+
name,
|
|
152
|
+
category: flag(args, "category") ?? "misc",
|
|
153
|
+
framework: flag(args, "framework") ?? "react-vite",
|
|
154
|
+
components: componentsArg ? componentsArg.split(",").map((c) => c.trim()).filter(Boolean) : [],
|
|
155
|
+
license: flag(args, "license") ?? "MIT",
|
|
156
|
+
...flag(args, "repo") ? { repo: flag(args, "repo") } : {},
|
|
157
|
+
...flag(args, "author") ? { author: flag(args, "author") } : {}
|
|
158
|
+
};
|
|
159
|
+
const { files, item } = buildTemplateScaffold(opts);
|
|
160
|
+
for (const file of files) await writeFileSafe(join(cwd, file.path), file.contents);
|
|
161
|
+
const registryPath = resolve(cwd, "cascivo-registry.json");
|
|
162
|
+
let index;
|
|
163
|
+
if (existsSync(registryPath)) {
|
|
164
|
+
index = JSON.parse(await readFile(registryPath, "utf8"));
|
|
165
|
+
index.items = (index.items ?? []).filter((i) => i.name !== item.name);
|
|
166
|
+
index.items.push(item);
|
|
167
|
+
} else index = {
|
|
168
|
+
schemaVersion: 2,
|
|
169
|
+
name: opts.repo ?? name,
|
|
170
|
+
items: [item]
|
|
171
|
+
};
|
|
172
|
+
await writeFileSafe(registryPath, `${JSON.stringify(index, null, 2)}\n`);
|
|
173
|
+
console.log(`Scaffolded template "${name}" (${files.length} files + cascivo-registry.json).`);
|
|
174
|
+
console.log("Next: fill in the page, capture screenshots, then `cascivo registry build`.");
|
|
175
|
+
}
|
|
176
|
+
//#endregion
|
|
177
|
+
export { templateInit };
|
|
178
|
+
|
|
179
|
+
//# sourceMappingURL=template-init-DGEgatij.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-init-DGEgatij.mjs","names":[],"sources":["../src/commands/template-init.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { readFile } from 'node:fs/promises'\nimport { join, resolve } from 'node:path'\nimport type { RegistryItem, TemplateMeta } from '@cascivo/registry'\nimport { writeFileSafe } from '../utils/fs.js'\n\nexport interface TemplateInitOptions {\n /** kebab-case template name (also the source folder + registry item name). */\n name: string\n /** Discovery category, e.g. \"dashboard\". */\n category: string\n /** Target framework for the page source. */\n framework: TemplateMeta['framework']\n /** Components the template composes (registry names). */\n components: string[]\n /** Repo owner/name used to build raw file URLs and the homepage. */\n repo?: string\n /** License SPDX id. */\n license: string\n /** Author. */\n author?: string\n}\n\nexport interface ScaffoldFile {\n /** Path relative to the template repo root. */\n path: string\n contents: string\n}\n\nfunction pascal(name: string): string {\n return name\n .split(/[-_/]/)\n .filter(Boolean)\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1))\n .join('')\n}\n\nfunction rawUrl(repo: string | undefined, path: string): string {\n if (!repo) return path\n return `https://raw.githubusercontent.com/${repo}/main/${path}`\n}\n\nfunction pageSource(name: string, components: string[]): string {\n const comp = pascal(name)\n const importLine =\n components.length > 0\n ? `// Components installed via the template's registryDependencies:\\n// ${components.join(', ')}\\n`\n : ''\n return `${importLine}import './${name}.module.css'\n\n/**\n * ${comp} template page. Owned, copy-paste source — adapt freely.\n * Presentational only: no useState/useEffect (cascade house rules).\n */\nexport function ${comp}Page() {\n return (\n <main className=\"${name}-page\">\n <h1>${comp}</h1>\n {/* Compose the template's components here. */}\n </main>\n )\n}\n`\n}\n\nfunction cssSource(name: string): string {\n return `@layer components {\n .${name}-page {\n display: grid;\n gap: var(--cascivo-space-4, 1rem);\n padding: var(--cascivo-space-4, 1rem);\n }\n}\n`\n}\n\nfunction fixturesSource(name: string): string {\n return `/** Mock data for the ${name} template. Replace with your real source. */\nexport const ${name.replace(/-/g, '_')}Fixtures = {\n items: [],\n}\n`\n}\n\nfunction templateMetaSource(meta: TemplateMeta): string {\n return `import type { TemplateMeta } from '@cascivo/registry'\n\nexport const meta: TemplateMeta = ${JSON.stringify(meta, null, 2)}\n`\n}\n\n/**\n * Build the files + registry item for a new template. Pure — no I/O — so it can\n * be unit-tested. The caller writes the files and merges the item into\n * `cascade-registry.json`.\n */\nexport function buildTemplateScaffold(opts: TemplateInitOptions): {\n files: ScaffoldFile[]\n item: RegistryItem\n} {\n const { name, category, framework, components, repo, license, author } = opts\n const dir = `src/${name}`\n const pageTarget = `src/pages/${name}.tsx`\n const cssTarget = `src/pages/${name}.module.css`\n const fixturesTarget = `src/fixtures/${name}.ts`\n\n const files: ScaffoldFile[] = [\n { path: `${dir}/${name}.tsx`, contents: pageSource(name, components) },\n { path: `${dir}/${name}.module.css`, contents: cssSource(name) },\n { path: `${dir}/fixtures.ts`, contents: fixturesSource(name) },\n ]\n\n const meta: TemplateMeta = {\n intent: `${pascal(name)} template`,\n framework,\n category,\n screenshots: [\n { light: rawUrl(repo, `screenshots/${name}-light.png`), alt: `${name} preview (light)` },\n ],\n fileRoles: {\n [pageTarget]: 'page',\n [cssTarget]: 'asset',\n [fixturesTarget]: 'fixture',\n },\n pages: [{ name: pascal(name), target: pageTarget }],\n }\n\n const item: RegistryItem = {\n schemaVersion: 2,\n name,\n type: 'template',\n description: `${pascal(name)} template`,\n category,\n version: '0.1.0',\n license,\n ...(author ? { author } : {}),\n ...(repo ? { homepage: `https://github.com/${repo}` } : {}),\n files: [\n { url: rawUrl(repo, `${dir}/${name}.tsx`), target: pageTarget },\n { url: rawUrl(repo, `${dir}/${name}.module.css`), target: cssTarget },\n { url: rawUrl(repo, `${dir}/fixtures.ts`), target: fixturesTarget },\n ],\n dependencies: [],\n registryDependencies: components,\n tags: [category, 'template'],\n meta,\n }\n\n files.push({ path: `${dir}/${name}.template.ts`, contents: templateMetaSource(meta) })\n\n return { files, item }\n}\n\nfunction flag(args: string[], key: string): string | undefined {\n const eq = args.find((a) => a.startsWith(`--${key}=`))\n if (eq) return eq.slice(key.length + 3)\n const idx = args.indexOf(`--${key}`)\n const next = idx !== -1 ? args[idx + 1] : undefined\n return next && !next.startsWith('--') ? next : undefined\n}\n\nexport async function templateInit(args: string[], cwd: string = process.cwd()): Promise<void> {\n const name = args.find((a) => !a.startsWith('-'))\n if (!name) {\n console.error(\n 'Usage: cascivo template init <name> [--category dashboard] [--framework react-vite] [--components card,line-chart] [--repo owner/repo]',\n )\n process.exitCode = 1\n return\n }\n\n const componentsArg = flag(args, 'components')\n const opts: TemplateInitOptions = {\n name,\n category: flag(args, 'category') ?? 'misc',\n framework: (flag(args, 'framework') as TemplateMeta['framework']) ?? 'react-vite',\n components: componentsArg\n ? componentsArg\n .split(',')\n .map((c) => c.trim())\n .filter(Boolean)\n : [],\n license: flag(args, 'license') ?? 'MIT',\n ...(flag(args, 'repo') ? { repo: flag(args, 'repo')! } : {}),\n ...(flag(args, 'author') ? { author: flag(args, 'author')! } : {}),\n }\n\n const { files, item } = buildTemplateScaffold(opts)\n\n for (const file of files) {\n await writeFileSafe(join(cwd, file.path), file.contents)\n }\n\n // Merge into cascivo-registry.json (create if missing).\n const registryPath = resolve(cwd, 'cascivo-registry.json')\n let index: { schemaVersion: 2; name: string; items: RegistryItem[] }\n if (existsSync(registryPath)) {\n index = JSON.parse(await readFile(registryPath, 'utf8')) as typeof index\n index.items = (index.items ?? []).filter((i) => i.name !== item.name)\n index.items.push(item)\n } else {\n index = { schemaVersion: 2, name: opts.repo ?? name, items: [item] }\n }\n await writeFileSafe(registryPath, `${JSON.stringify(index, null, 2)}\\n`)\n\n console.log(`Scaffolded template \"${name}\" (${files.length} files + cascivo-registry.json).`)\n console.log('Next: fill in the page, capture screenshots, then `cascivo registry build`.')\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cascivo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "CLI — npx cascivo init / add / list / update",
|
|
6
6
|
"keywords": [
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"provenance": true
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@cascivo/registry": "^0.1.
|
|
45
|
+
"@cascivo/registry": "^0.1.5"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^25",
|
package/readme.body.md
CHANGED
|
@@ -3,17 +3,23 @@ The `cascivo` CLI drives the copy-paste workflow — it scaffolds config, copies
|
|
|
3
3
|
## Commands
|
|
4
4
|
|
|
5
5
|
```sh
|
|
6
|
-
npx cascivo
|
|
7
|
-
cascivo
|
|
8
|
-
cascivo
|
|
9
|
-
cascivo
|
|
10
|
-
cascivo
|
|
11
|
-
cascivo
|
|
12
|
-
cascivo
|
|
6
|
+
npx cascivo create my-app # scaffold a full app — Vite + React, app shell, side nav, theme
|
|
7
|
+
npx cascivo create my-app --template owner/repo/dashboard # …and start from a template
|
|
8
|
+
npx cascivo init # scaffold cascivo.config.ts + tokens; detects your package manager
|
|
9
|
+
cascivo add button card # copy component source from the registry into your project
|
|
10
|
+
cascivo add owner/repo/button # install from any third-party registry
|
|
11
|
+
cascivo add owner/repo/dashboard # install a template (its components + page/fixture files)
|
|
12
|
+
cascivo view owner/repo/dashboard # preview an item (or template) before installing
|
|
13
|
+
cascivo list # list available components
|
|
14
|
+
cascivo update # pull newer versions of copied components
|
|
15
|
+
cascivo audit --ai # flag hard-coded values, invented props, missing wiring
|
|
16
|
+
cascivo build # build a registry from your own components
|
|
13
17
|
```
|
|
14
18
|
|
|
19
|
+
A **template** is a registry item (`type: "template"`) that bundles a working page with the components it composes (in `registryDependencies`) and its own page/fixture files (each with a `target`). `cascivo add` installs the component closure into your components directory and writes the template's files to their targets; `create --template` does the same into a freshly scaffolded app.
|
|
20
|
+
|
|
15
21
|
## How it works
|
|
16
22
|
|
|
17
|
-
`init` detects npm / pnpm / yarn / bun, writes `cascivo.config.ts`, and wires up the token and theme imports. `add` resolves each component from [`registry.json`](https://github.com/cascivo/cascivo/blob/main/registry.json), fetches its source (TSX + CSS module + manifest) from GitHub raw URLs, and drops it into the path from your config — pulling in any dependencies it needs.
|
|
23
|
+
`create` scaffolds a complete Vite + React + TypeScript app — pre-wired with the cascivo app shell, side navigation, header, and your chosen theme. It asks for a project name, theme, and the nav sections you want, then generates a section component for each. Pass `--theme`, `--sections "Dashboard, Reports"`, or `--yes` to skip the prompts. `init` detects npm / pnpm / yarn / bun, writes `cascivo.config.ts`, and wires up the token and theme imports. `add` resolves each component from [`registry.json`](https://github.com/cascivo/cascivo/blob/main/registry.json), fetches its source (TSX + CSS module + manifest) from GitHub raw URLs, and drops it into the path from your config — pulling in any dependencies it needs.
|
|
18
24
|
|
|
19
25
|
Because the registry model is open, `add owner/repo/component` installs from any compatible registry, not just the first-party one. See the [registry starter](https://github.com/cascivo/cascivo/tree/main/apps/examples/registry-starter) to publish your own.
|