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 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.6.22` here), not
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.6.22/registry"
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.
@@ -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
- * and drop catalog demo routes from APP_NAV. Idempotent. Used by add-page --nav
11
- * and upgrade so neither restores Mara nor Analytics/Billing/Settings in the nav.
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
- * and drop catalog demo routes from APP_NAV. Idempotent. Used by add-page --nav
25
- * and upgrade so neither restores Mara nor Analytics/Billing/Settings in the nav.
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.6.22";
3
- export declare const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.6.22/registry";
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.6.22";
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.6.22",
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.6.22",
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": "An admin console: split login/signup, password reset, an (app) shell, overview, users, analytics, a sprint board and an audit trail — composed from validated blocks.",
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": {}
@@ -4,7 +4,7 @@
4
4
  "planVersion": 1,
5
5
  "manifest": {
6
6
  "title": "SaaS",
7
- "description": "A complete multi-page SaaS app: split login/signup, password reset, a sidebar-shell dashboard, analytics, team, billing and settings, plus welcome, setup wizard and checklist — all from validated blocks.",
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": {}