cronus-ui 0.6.22 → 0.7.1
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 +2 -2
- package/dist/commands/add-page.js +17 -2
- package/dist/commands/upgrade.js +5 -2
- package/dist/compose/gold-path.d.ts +14 -3
- package/dist/compose/gold-path.js +86 -4
- package/dist/config.d.ts +2 -2
- package/dist/config.js +1 -1
- package/package.json +2 -2
- package/templates/apps/admin.json +1 -1
- package/templates/apps/saas.json +1 -1
package/README.md
CHANGED
|
@@ -49,7 +49,7 @@ Notes that match the commander surface:
|
|
|
49
49
|
`packages/cli/scripts/build-registry.ts` — each item carries its source, its npm
|
|
50
50
|
`dependencies`, and its `registryDependencies` (other components it imports),
|
|
51
51
|
derived by parsing imports.
|
|
52
|
-
- The default registry is pinned to the CLI package version (`v0.
|
|
52
|
+
- The default registry is pinned to the CLI package version (`v0.7.1` here), not
|
|
53
53
|
mutable `main`, so a published CLI reads the registry snapshot it was released
|
|
54
54
|
with. Use `-r, --registry ./registry` when testing local registry changes before
|
|
55
55
|
a release tag exists.
|
|
@@ -80,7 +80,7 @@ Notes that match the commander surface:
|
|
|
80
80
|
"lib": "lib",
|
|
81
81
|
"blocks": "components/blocks"
|
|
82
82
|
},
|
|
83
|
-
"registry": "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.
|
|
83
|
+
"registry": "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.7.1/registry"
|
|
84
84
|
}
|
|
85
85
|
```
|
|
86
86
|
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
* inherited wholesale from the shared renderer.
|
|
20
20
|
*/
|
|
21
21
|
import { existsSync } from "node:fs";
|
|
22
|
-
import { rm } from "node:fs/promises";
|
|
23
|
-
import { goldPatchAppShellChrome, goldPatchHomePage, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, } from "../compose/gold-path.js";
|
|
22
|
+
import { readFile, rm } from "node:fs/promises";
|
|
23
|
+
import { GOLD_PATH_AUTH_SPLIT_FILES, goldPatchAppShellChrome, goldPatchHomePage, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, patchGoldPathAuthSplit, } from "../compose/gold-path.js";
|
|
24
24
|
import { blockRefParts } from "../compose/manifest.js";
|
|
25
25
|
import { buildComposePlan, ComposePlanError, } from "../compose/plan.js";
|
|
26
26
|
import { baseSnapshotDir, reloadManifest } from "../compose/reload.js";
|
|
@@ -306,6 +306,21 @@ export async function addPage(options) {
|
|
|
306
306
|
generatedFiles.push(rel);
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
|
+
if (isGoldPathTemplate(appName)) {
|
|
310
|
+
for (const file of GOLD_PATH_AUTH_SPLIT_FILES) {
|
|
311
|
+
const rel = `${config.paths.blocks}/${file}`;
|
|
312
|
+
const dest = resolveSafeDest(targetDir, ".", rel);
|
|
313
|
+
if (!existsSync(dest))
|
|
314
|
+
continue;
|
|
315
|
+
const current = await readFile(dest, "utf8");
|
|
316
|
+
const patched = patchGoldPathAuthSplit(current);
|
|
317
|
+
if (patched === undefined || patched === current)
|
|
318
|
+
continue;
|
|
319
|
+
await writeFileEnsured(dest, patched);
|
|
320
|
+
if (!generatedFiles.includes(rel))
|
|
321
|
+
generatedFiles.push(rel);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
309
324
|
// --- Grow composed{} (pages union + files union) + persist ----------------
|
|
310
325
|
const nextPages = [...new Set([...composedRecord.choices.pages, options.route])];
|
|
311
326
|
// Preserve manifest order of the routes the app actually has.
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -5,7 +5,7 @@ import { tmpdir } from "node:os";
|
|
|
5
5
|
import { join } from "node:path";
|
|
6
6
|
import { createInterface } from "node:readline/promises";
|
|
7
7
|
import pc from "picocolors";
|
|
8
|
-
import { goldPatchAppShellChrome, goldPatchHomePage, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, reemitGoldPathOwned, } from "../compose/gold-path.js";
|
|
8
|
+
import { GOLD_PATH_AUTH_SPLIT_FILES, goldPatchAppShellChrome, goldPatchHomePage, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, patchGoldPathAuthSplit, reemitGoldPathOwned, } from "../compose/gold-path.js";
|
|
9
9
|
import { buildComposePlan } from "../compose/plan.js";
|
|
10
10
|
import { baseSnapshotDest, filterManifestToComposedPages, listBaseSnapshotRels, readBaseSnapshot, reloadManifest, } from "../compose/reload.js";
|
|
11
11
|
import { renderPlan } from "../compose/render.js";
|
|
@@ -484,7 +484,10 @@ async function repatchGoldPathSurfaces(cwd, config, composed) {
|
|
|
484
484
|
if (!Object.keys(composed).some((key) => isGoldPathTemplate(key)))
|
|
485
485
|
return;
|
|
486
486
|
const authImport = `${config.aliases.lib}/auth`;
|
|
487
|
-
await repatchGoldPathFile(cwd, join(config.paths.blocks, "app-shell-chrome.tsx"), goldPatchAppShellChrome, "WorkspaceMenu / InviteMember / SessionUser / nav");
|
|
487
|
+
await repatchGoldPathFile(cwd, join(config.paths.blocks, "app-shell-chrome.tsx"), goldPatchAppShellChrome, "WorkspaceMenu / InviteMember / SessionUser / nav / notifications");
|
|
488
|
+
for (const file of GOLD_PATH_AUTH_SPLIT_FILES) {
|
|
489
|
+
await repatchGoldPathFile(cwd, join(config.paths.blocks, file), patchGoldPathAuthSplit, "auth split without Dana Reyes");
|
|
490
|
+
}
|
|
488
491
|
for (const rel of goldPathSurfaceRels(cwd, composed)) {
|
|
489
492
|
if (/(^|\/)\(shell\)\/layout\.tsx$/.test(rel)) {
|
|
490
493
|
await repatchGoldPathFile(cwd, rel, (source) => goldPatchShellLayout(source, authImport), "session gate");
|
|
@@ -6,11 +6,14 @@ import type { CronusUIConfig } from "../config.js";
|
|
|
6
6
|
export declare const GOLD_PATH_TEMPLATES: Set<string>;
|
|
7
7
|
export declare function isGoldPathTemplate(name: string): boolean;
|
|
8
8
|
/**
|
|
9
|
-
* Re-apply WorkspaceMenu / InviteMember / SessionUser onto catalog app-shell-chrome
|
|
10
|
-
*
|
|
11
|
-
* and upgrade so neither restores Mara
|
|
9
|
+
* Re-apply WorkspaceMenu / InviteMember / SessionUser onto catalog app-shell-chrome,
|
|
10
|
+
* drop catalog demo routes from APP_NAV, and remove the dead Notifications button.
|
|
11
|
+
* Idempotent. Used by add-page --nav and upgrade so neither restores Mara,
|
|
12
|
+
* Analytics/Billing/Settings in the nav, nor a no-op Bell.
|
|
12
13
|
*/
|
|
13
14
|
export declare function goldPatchAppShellChrome(source: string): string | undefined;
|
|
15
|
+
/** Installed split-auth copies compose writes for saas/admin. */
|
|
16
|
+
export declare const GOLD_PATH_AUTH_SPLIT_FILES: readonly ["login-split.tsx", "signup-split.tsx", "forgot-password-split.tsx"];
|
|
14
17
|
/**
|
|
15
18
|
* Re-apply the session gate onto a catalog shell layout.
|
|
16
19
|
* Idempotent. Used by add-page (new shell group) and upgrade.
|
|
@@ -49,6 +52,14 @@ export interface ApplyGoldPathResult {
|
|
|
49
52
|
skipped: string[];
|
|
50
53
|
}
|
|
51
54
|
export declare function goldPathLayout(config: CronusUIConfig): GoldPathLayout;
|
|
55
|
+
/**
|
|
56
|
+
* Drop the catalog Dana Reyes / Northwind testimonial column from a split auth
|
|
57
|
+
* block. Idempotent. Returns undefined when the quote is missing and the file
|
|
58
|
+
* is not an already-stripped gold-path split.
|
|
59
|
+
*/
|
|
60
|
+
export declare function patchGoldPathAuthSplit(source: string): string | undefined;
|
|
61
|
+
/** Remove the no-op Notifications Bell from gold-path chrome. Idempotent. */
|
|
62
|
+
export declare function patchGoldPathChromeNotifications(source: string): string | undefined;
|
|
52
63
|
/**
|
|
53
64
|
* Drop catalog demo hrefs from `const APP_NAV`. Idempotent. Keeps Items, Team,
|
|
54
65
|
* and any user-added link. Returns undefined when the const is missing.
|
|
@@ -20,13 +20,20 @@ const GOLD_AUTH_IMPORT = "@/lib/auth";
|
|
|
20
20
|
const GOLD_MEMBERS_IMPORT = "@/components/members-panel";
|
|
21
21
|
const GOLD_ITEMS_IMPORT = "@/components/items-panel";
|
|
22
22
|
/**
|
|
23
|
-
* Re-apply WorkspaceMenu / InviteMember / SessionUser onto catalog app-shell-chrome
|
|
24
|
-
*
|
|
25
|
-
* and upgrade so neither restores Mara
|
|
23
|
+
* Re-apply WorkspaceMenu / InviteMember / SessionUser onto catalog app-shell-chrome,
|
|
24
|
+
* drop catalog demo routes from APP_NAV, and remove the dead Notifications button.
|
|
25
|
+
* Idempotent. Used by add-page --nav and upgrade so neither restores Mara,
|
|
26
|
+
* Analytics/Billing/Settings in the nav, nor a no-op Bell.
|
|
26
27
|
*/
|
|
27
28
|
export function goldPatchAppShellChrome(source) {
|
|
28
29
|
return patchChromeSource(source, GOLD_WORKSPACE_IMPORT, GOLD_INVITE_IMPORT, GOLD_SESSION_IMPORT);
|
|
29
30
|
}
|
|
31
|
+
/** Installed split-auth copies compose writes for saas/admin. */
|
|
32
|
+
export const GOLD_PATH_AUTH_SPLIT_FILES = [
|
|
33
|
+
"login-split.tsx",
|
|
34
|
+
"signup-split.tsx",
|
|
35
|
+
"forgot-password-split.tsx",
|
|
36
|
+
];
|
|
30
37
|
/**
|
|
31
38
|
* Re-apply the session gate onto a catalog shell layout.
|
|
32
39
|
* Idempotent. Used by add-page (new shell group) and upgrade.
|
|
@@ -1125,6 +1132,64 @@ function serializeGoldPathAppNav(links) {
|
|
|
1125
1132
|
.join("\n");
|
|
1126
1133
|
return `const APP_NAV = [\n${rows}\n];`;
|
|
1127
1134
|
}
|
|
1135
|
+
/**
|
|
1136
|
+
* Drop the catalog Dana Reyes / Northwind testimonial column from a split auth
|
|
1137
|
+
* block. Idempotent. Returns undefined when the quote is missing and the file
|
|
1138
|
+
* is not an already-stripped gold-path split.
|
|
1139
|
+
*/
|
|
1140
|
+
export function patchGoldPathAuthSplit(source) {
|
|
1141
|
+
const hasQuote = source.includes("Dana Reyes") || source.includes("Northwind Labs");
|
|
1142
|
+
if (!hasQuote) {
|
|
1143
|
+
if (source.includes("lg:grid-cols-2"))
|
|
1144
|
+
return undefined;
|
|
1145
|
+
if (source.includes("Sign in to your Cronus workspace") ||
|
|
1146
|
+
source.includes("Create your Cronus workspace") ||
|
|
1147
|
+
source.includes("Join the workspace") ||
|
|
1148
|
+
source.includes("Check your inbox")) {
|
|
1149
|
+
return source;
|
|
1150
|
+
}
|
|
1151
|
+
return undefined;
|
|
1152
|
+
}
|
|
1153
|
+
let out = source.replace(/(?:\n\s*\{\/\* Brand panel \*\/\})?\s*<div className="relative overflow-hidden bg-gradient-primary-strong[\s\S]*?Head of Growth, Northwind Labs[\s\S]*?<\/figure>\s*<\/div>\s*<\/div>/, "");
|
|
1154
|
+
if (out === source)
|
|
1155
|
+
return undefined;
|
|
1156
|
+
out = out.replace(" lg:grid-cols-2", "");
|
|
1157
|
+
out = out.replace(" max-w-4xl", " max-w-md");
|
|
1158
|
+
out = out.replace(" lg:order-2", "");
|
|
1159
|
+
out = out.replace(" lg:order-1", "");
|
|
1160
|
+
out = dropUnusedFromImport(out, "lucide-react");
|
|
1161
|
+
out = dropUnusedFromImport(out, "@cronus-ui/ui");
|
|
1162
|
+
return out;
|
|
1163
|
+
}
|
|
1164
|
+
/** Remove the no-op Notifications Bell from gold-path chrome. Idempotent. */
|
|
1165
|
+
export function patchGoldPathChromeNotifications(source) {
|
|
1166
|
+
if (!source.includes('aria-label="Notifications"'))
|
|
1167
|
+
return undefined;
|
|
1168
|
+
let out = source.replace(/\n\s*<Button variant="ghost" size="icon-sm" aria-label="Notifications">\s*<Bell className="size-4" aria-hidden="true" \/>\s*<\/Button>/, "");
|
|
1169
|
+
if (out === source)
|
|
1170
|
+
return undefined;
|
|
1171
|
+
out = dropUnusedFromImport(out, "lucide-react");
|
|
1172
|
+
return out;
|
|
1173
|
+
}
|
|
1174
|
+
function dropUnusedFromImport(source, fromModule) {
|
|
1175
|
+
const escaped = fromModule.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1176
|
+
const re = new RegExp(`import \\{([^}]+)\\} from "${escaped}";\\n`);
|
|
1177
|
+
const match = source.match(re);
|
|
1178
|
+
if (!match || match.index === undefined)
|
|
1179
|
+
return source;
|
|
1180
|
+
const names = (match[1] ?? "")
|
|
1181
|
+
.split(",")
|
|
1182
|
+
.map((part) => part.trim())
|
|
1183
|
+
.filter(Boolean);
|
|
1184
|
+
const rest = source.slice(0, match.index) + source.slice(match.index + match[0].length);
|
|
1185
|
+
const kept = names.filter((name) => new RegExp(`(?:<|{)${name}\\b`).test(rest));
|
|
1186
|
+
if (kept.length === names.length)
|
|
1187
|
+
return source;
|
|
1188
|
+
if (kept.length === 0) {
|
|
1189
|
+
return source.slice(0, match.index) + source.slice(match.index + match[0].length);
|
|
1190
|
+
}
|
|
1191
|
+
return `${source.slice(0, match.index)}import { ${kept.join(", ")} } from "${fromModule}";\n${source.slice(match.index + match[0].length)}`;
|
|
1192
|
+
}
|
|
1128
1193
|
/**
|
|
1129
1194
|
* Drop catalog demo hrefs from `const APP_NAV`. Idempotent. Keeps Items, Team,
|
|
1130
1195
|
* and any user-added link. Returns undefined when the const is missing.
|
|
@@ -1207,9 +1272,12 @@ export function patchChromeSource(source, workspaceImport, inviteImport, session
|
|
|
1207
1272
|
const navPatched = patchGoldPathAppNav(out);
|
|
1208
1273
|
if (navPatched !== undefined)
|
|
1209
1274
|
out = navPatched;
|
|
1275
|
+
const notifyPatched = patchGoldPathChromeNotifications(out);
|
|
1276
|
+
if (notifyPatched !== undefined)
|
|
1277
|
+
out = notifyPatched;
|
|
1210
1278
|
if (out !== source)
|
|
1211
1279
|
return out;
|
|
1212
|
-
if (widgetsTouched || navPatched !== undefined)
|
|
1280
|
+
if (widgetsTouched || (navPatched !== undefined && navPatched === source))
|
|
1213
1281
|
return source;
|
|
1214
1282
|
return undefined;
|
|
1215
1283
|
}
|
|
@@ -1500,6 +1568,20 @@ export async function applyGoldPath(options) {
|
|
|
1500
1568
|
}
|
|
1501
1569
|
}
|
|
1502
1570
|
}
|
|
1571
|
+
const blocksDir = posix(config.paths.blocks);
|
|
1572
|
+
for (const file of GOLD_PATH_AUTH_SPLIT_FILES) {
|
|
1573
|
+
const rel = `${blocksDir}/${file}`;
|
|
1574
|
+
const dest = resolveSafeDest(targetDir, ".", rel);
|
|
1575
|
+
if (!existsSync(dest))
|
|
1576
|
+
continue;
|
|
1577
|
+
const current = await readFile(dest, "utf8");
|
|
1578
|
+
const patched = patchGoldPathAuthSplit(current);
|
|
1579
|
+
if (patched === undefined || patched === current)
|
|
1580
|
+
continue;
|
|
1581
|
+
await writeFileEnsured(dest, patched);
|
|
1582
|
+
if (!written.includes(rel))
|
|
1583
|
+
written.push(rel);
|
|
1584
|
+
}
|
|
1503
1585
|
const layoutRel = shellLayoutRel(appDir, generatedFiles);
|
|
1504
1586
|
if (layoutRel !== undefined) {
|
|
1505
1587
|
const dest = resolveSafeDest(targetDir, ".", layoutRel);
|
package/dist/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const CONFIG_FILE = "cronus-ui.json";
|
|
2
|
-
export declare const CLI_VERSION = "0.
|
|
3
|
-
export declare const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.
|
|
2
|
+
export declare const CLI_VERSION = "0.7.1";
|
|
3
|
+
export declare const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.7.1/registry";
|
|
4
4
|
/** Manifest entry `add`/`upgrade` record per installed registry item. */
|
|
5
5
|
export interface InstalledRecord {
|
|
6
6
|
/** Registry release the files came from (git tag without the leading "v"). */
|
package/dist/config.js
CHANGED
|
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
export const CONFIG_FILE = "cronus-ui.json";
|
|
5
|
-
export const CLI_VERSION = "0.
|
|
5
|
+
export const CLI_VERSION = "0.7.1";
|
|
6
6
|
export const DEFAULT_REGISTRY = `https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v${CLI_VERSION}/registry`;
|
|
7
7
|
export const DEFAULT_CONFIG = {
|
|
8
8
|
aliases: { ui: "@/components/ui", lib: "@/lib", blocks: "@/components/blocks" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cronus-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "cronus-ui — add Cronus UI components to your project, shadcn-style (copy-paste registry).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"registry:check": "bun run scripts/check-registry.ts"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@cronus-ui/ai-kit": "0.
|
|
57
|
+
"@cronus-ui/ai-kit": "0.7.1",
|
|
58
58
|
"commander": "^15.0.0",
|
|
59
59
|
"picocolors": "^1.1.1"
|
|
60
60
|
},
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"planVersion": 1,
|
|
5
5
|
"manifest": {
|
|
6
6
|
"title": "Admin",
|
|
7
|
-
"description": "
|
|
7
|
+
"description": "Authenticated gold path: split login/signup, password reset, Items in a sidebar shell. Catalog demo pages (users, analytics, board, audit) ship as files, not in the nav — composed from validated blocks.",
|
|
8
8
|
"chrome": {
|
|
9
9
|
"shell": { "block": "app-shell-chrome" },
|
|
10
10
|
"bare": {}
|
package/templates/apps/saas.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"planVersion": 1,
|
|
5
5
|
"manifest": {
|
|
6
6
|
"title": "SaaS",
|
|
7
|
-
"description": "
|
|
7
|
+
"description": "Authenticated gold path: split login/signup, password reset, Items and Team in a sidebar shell. Catalog demo pages (analytics, billing, settings, welcome, setup wizard, checklist) ship as files, not in the nav — all from validated blocks.",
|
|
8
8
|
"chrome": {
|
|
9
9
|
"shell": { "block": "app-shell-chrome" },
|
|
10
10
|
"bare": {}
|