cronus-ui 0.6.17 → 0.6.19

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.17` here), not
52
+ - The default registry is pinned to the CLI package version (`v0.6.19` 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.17/registry"
83
+ "registry": "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.6.19/registry"
84
84
  }
85
85
  ```
86
86
 
@@ -20,7 +20,7 @@
20
20
  */
21
21
  import { existsSync } from "node:fs";
22
22
  import { rm } from "node:fs/promises";
23
- import { goldPatchAppShellChrome, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, } from "../compose/gold-path.js";
23
+ import { goldPatchAppShellChrome, goldPatchHomePage, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, } 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";
@@ -235,12 +235,19 @@ export async function addPage(options) {
235
235
  }
236
236
  else {
237
237
  let content = renderPage(planPage, config);
238
- // saas/admin: compose gold-patches /team (MembersPanel). Writing the
239
- // catalog TeamBlock would undo that — re-apply the same idempotent patch.
240
- if (isGoldPathTemplate(appName) && planPage.route === "/team" && chromeGroup === "shell") {
241
- const patched = goldPatchTeamPage(content);
242
- if (patched !== undefined)
243
- content = patched;
238
+ // saas/admin: compose gold-patches / (ItemsPanel) and /team (MembersPanel).
239
+ // Writing the catalog dashboard/stats or TeamBlock would undo that.
240
+ if (isGoldPathTemplate(appName) && chromeGroup === "shell") {
241
+ if (planPage.route === "/") {
242
+ const patched = goldPatchHomePage(content);
243
+ if (patched !== undefined)
244
+ content = patched;
245
+ }
246
+ else if (planPage.route === "/team") {
247
+ const patched = goldPatchTeamPage(content);
248
+ if (patched !== undefined)
249
+ content = patched;
250
+ }
244
251
  }
245
252
  await writeFileEnsured(pageDest, content);
246
253
  generatedFiles.push(pageRel);
@@ -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, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, } from "../compose/gold-path.js";
8
+ import { goldPatchAppShellChrome, goldPatchHomePage, goldPatchShellLayout, goldPatchTeamPage, isGoldPathTemplate, 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";
@@ -423,7 +423,7 @@ function statusLabel(plan) {
423
423
  }
424
424
  /**
425
425
  * saas/admin: upgrade 3-ways chrome against the catalog item (Mara) and
426
- * layout/team against the catalog compose render. After any write (or a
426
+ * layout/team/home against the catalog compose render. After any write (or a
427
427
  * catalog file already on disk), re-apply the gold-path identity. Idempotent;
428
428
  * skipped when conflict markers are present.
429
429
  */
@@ -457,12 +457,29 @@ function goldPathSurfaceRels(cwd, composed) {
457
457
  "src/app/(shell)/layout.tsx",
458
458
  "app/(shell)/team/page.tsx",
459
459
  "src/app/(shell)/team/page.tsx",
460
+ "app/(shell)/page.tsx",
461
+ "src/app/(shell)/page.tsx",
460
462
  ]) {
461
463
  if (existsSync(join(cwd, rel)))
462
464
  rels.add(rel);
463
465
  }
464
466
  return [...rels];
465
467
  }
468
+ /**
469
+ * `--all` on saas/admin: re-emit compose's `always: true` gold-path files so
470
+ * CLI gold-path fixes reach apps composed on an older release. Named upgrades
471
+ * (e.g. `upgrade stats`) do not touch them. auth.ts / schema stay user-owned.
472
+ */
473
+ async function reemitGoldPathOwnedOnUpgrade(cwd, config, composed, upgradeComposed) {
474
+ if (!upgradeComposed)
475
+ return;
476
+ if (!Object.keys(composed).some((key) => isGoldPathTemplate(key)))
477
+ return;
478
+ const written = await reemitGoldPathOwned(cwd, config);
479
+ if (written.length === 0)
480
+ return;
481
+ log.ok(`gold-path owned: re-emitted ${written.join(", ")}`);
482
+ }
466
483
  async function repatchGoldPathSurfaces(cwd, config, composed) {
467
484
  if (!Object.keys(composed).some((key) => isGoldPathTemplate(key)))
468
485
  return;
@@ -475,6 +492,9 @@ async function repatchGoldPathSurfaces(cwd, config, composed) {
475
492
  if (/(^|\/)\(shell\)\/team\/page\.tsx$/.test(rel)) {
476
493
  await repatchGoldPathFile(cwd, rel, goldPatchTeamPage, "MembersPanel");
477
494
  }
495
+ if (/(^|\/)\(shell\)\/page\.tsx$/.test(rel)) {
496
+ await repatchGoldPathFile(cwd, rel, goldPatchHomePage, "ItemsPanel");
497
+ }
478
498
  }
479
499
  }
480
500
  /** Statuses that write the planned content to disk unconditionally. */
@@ -829,6 +849,7 @@ export async function upgrade(names, options) {
829
849
  const newlyInstalled = await installPendingBlocks(itemPlans, config, cwd, targetVersion);
830
850
  Object.assign(installed, newlyInstalled);
831
851
  const written = await applyPlans(itemPlans, options, confirm);
852
+ await reemitGoldPathOwnedOnUpgrade(cwd, config, composed, upgradeComposed);
832
853
  await repatchGoldPathSurfaces(cwd, config, composed);
833
854
  await refreshComposeSnapshots(itemPlans);
834
855
  // Manifest: record every item that now fully embodies the target release.
@@ -20,6 +20,11 @@ export declare function goldPatchShellLayout(source: string, authImport?: string
20
20
  * Idempotent. Used by add-page --overwrite /team and upgrade.
21
21
  */
22
22
  export declare function goldPatchTeamPage(source: string, membersImport?: string): string | undefined;
23
+ /**
24
+ * Re-apply ItemsPanel onto a catalog saas/admin home (drop dashboard/stats).
25
+ * Idempotent. Used by add-page --overwrite / and upgrade.
26
+ */
27
+ export declare function goldPatchHomePage(source: string, itemsImport?: string): string | undefined;
23
28
  /** Production npm specs installed with the gold path (devDeps are merged into package.json). */
24
29
  export declare const GOLD_PATH_DEPENDENCIES: readonly ["drizzle-orm@^0.45.2", "better-sqlite3@^12.0.0", "better-auth@^1.7.2"];
25
30
  export interface GoldPathLayout {
@@ -62,9 +67,15 @@ export declare function patchTeamPageSource(source: string, membersImport: strin
62
67
  * app chrome. Idempotent. Returns undefined when AppShellNav is missing.
63
68
  */
64
69
  export declare function patchShellLayoutSource(source: string, authImport: string): string | undefined;
70
+ /**
71
+ * Re-emit compose's `always: true` gold-path files. Idempotent when bytes
72
+ * already match. Used by `upgrade --all` so CLI gold-path fixes reach apps
73
+ * composed on an older release without clobbering auth.ts / schema.
74
+ */
75
+ export declare function reemitGoldPathOwned(targetDir: string, config: CronusUIConfig): Promise<string[]>;
65
76
  /**
66
77
  * Write sqlite + Drizzle + Better-Auth files into a composed saas/admin app.
67
- * Overwrites lib/auth-adapter.ts, lib/items.ts, and lib/members.ts always.
78
+ * Overwrites owned adapters/panels always (`always: true`).
68
79
  * Patches the shell home, /team, and shell layout only when compose wrote them
69
80
  * this run.
70
81
  */
@@ -17,6 +17,7 @@ const GOLD_INVITE_IMPORT = "@/components/invite-member";
17
17
  const GOLD_SESSION_IMPORT = "@/components/session-user";
18
18
  const GOLD_AUTH_IMPORT = "@/lib/auth";
19
19
  const GOLD_MEMBERS_IMPORT = "@/components/members-panel";
20
+ const GOLD_ITEMS_IMPORT = "@/components/items-panel";
20
21
  /**
21
22
  * Re-apply WorkspaceMenu / InviteMember / SessionUser onto catalog app-shell-chrome.
22
23
  * Idempotent. Used by add-page --nav and upgrade so neither restores Mara.
@@ -38,6 +39,13 @@ export function goldPatchShellLayout(source, authImport = GOLD_AUTH_IMPORT) {
38
39
  export function goldPatchTeamPage(source, membersImport = GOLD_MEMBERS_IMPORT) {
39
40
  return patchTeamPageSource(source, membersImport);
40
41
  }
42
+ /**
43
+ * Re-apply ItemsPanel onto a catalog saas/admin home (drop dashboard/stats).
44
+ * Idempotent. Used by add-page --overwrite / and upgrade.
45
+ */
46
+ export function goldPatchHomePage(source, itemsImport = GOLD_ITEMS_IMPORT) {
47
+ return patchHomePageSource(source, itemsImport);
48
+ }
41
49
  /** Production npm specs installed with the gold path (devDeps are merged into package.json). */
42
50
  export const GOLD_PATH_DEPENDENCIES = [
43
51
  "drizzle-orm@^0.45.2",
@@ -1278,97 +1286,115 @@ async function writeRel(targetDir, rel, content, overwrite, always, written, ski
1278
1286
  written.push(rel);
1279
1287
  }
1280
1288
  /**
1281
- * Write sqlite + Drizzle + Better-Auth files into a composed saas/admin app.
1282
- * Overwrites lib/auth-adapter.ts, lib/items.ts, and lib/members.ts always.
1283
- * Patches the shell home, /team, and shell layout only when compose wrote them
1284
- * this run.
1289
+ * Gold-path files compose always overwrites (`always: true`). Scaffold files
1290
+ * (auth.ts, schema, middleware) are not in this list — those stay user-owned
1291
+ * after the first write.
1285
1292
  */
1286
- export async function applyGoldPath(options) {
1287
- const { targetDir, config, generatedFiles, overwrite } = options;
1293
+ function goldPathOwnedFiles(config, appDir) {
1288
1294
  const layout = goldPathLayout(config);
1289
- const appDir = resolveAppDir(targetDir, layout, generatedFiles);
1290
- const middlewareRel = appDir === "src/app"
1291
- ? "src/middleware.ts"
1292
- : appDir === "app"
1293
- ? "middleware.ts"
1294
- : layout.middlewareRel;
1295
1295
  const authImport = `${config.aliases.lib}/auth`;
1296
1296
  const authClientImport = `${config.aliases.lib}/auth-client`;
1297
1297
  const itemsActionsImport = `${config.aliases.lib}/items`;
1298
1298
  const itemsViewImport = "@/components/items-view";
1299
- const itemsImport = "@/components/items-panel";
1300
1299
  const membersActionsImport = `${config.aliases.lib}/members`;
1301
1300
  const membersViewImport = "@/components/members-view";
1302
- const membersImport = "@/components/members-panel";
1303
- const workspaceImport = "@/components/workspace-menu";
1304
1301
  const inviteImport = "@/components/invite-member";
1305
- const sessionImport = "@/components/session-user";
1306
- const chromeRel = `${posix(config.paths.blocks)}/app-shell-chrome.tsx`;
1307
- const written = [];
1308
- const skipped = [];
1309
- const files = [
1310
- { rel: "drizzle.config.ts", content: drizzleConfigSource(layout.dbDir) },
1311
- { rel: `${layout.dbDir}/schema.ts`, content: dbSchemaSource() },
1312
- { rel: `${layout.dbDir}/index.ts`, content: dbClientSource() },
1313
- { rel: `${layout.libDir}/auth.ts`, content: authServerSource() },
1314
- { rel: `${layout.libDir}/auth-client.ts`, content: authClientSource() },
1315
- { rel: `${layout.libDir}/auth-adapter.ts`, content: authAdapterSource(), always: true },
1316
- {
1317
- rel: `${layout.libDir}/items.ts`,
1318
- content: itemsActionsSource(authImport),
1319
- always: true,
1320
- },
1321
- {
1322
- rel: `${appDir}/api/auth/[...all]/route.ts`,
1323
- content: authRouteSource(authImport),
1324
- },
1325
- { rel: middlewareRel, content: middlewareSource() },
1302
+ return [
1303
+ { rel: `${layout.libDir}/auth-adapter.ts`, content: authAdapterSource() },
1304
+ { rel: `${layout.libDir}/items.ts`, content: itemsActionsSource(authImport) },
1326
1305
  {
1327
1306
  rel: `${layout.componentsDir}/items-panel.tsx`,
1328
1307
  content: itemsPanelSource(itemsActionsImport, itemsViewImport),
1329
- always: true,
1330
1308
  },
1331
1309
  {
1332
1310
  rel: `${layout.componentsDir}/items-view.tsx`,
1333
1311
  content: itemsViewSource(itemsActionsImport),
1334
- always: true,
1335
- },
1336
- {
1337
- rel: `${layout.libDir}/members.ts`,
1338
- content: membersActionsSource(authImport),
1339
- always: true,
1340
1312
  },
1313
+ { rel: `${layout.libDir}/members.ts`, content: membersActionsSource(authImport) },
1341
1314
  {
1342
1315
  rel: `${layout.componentsDir}/members-panel.tsx`,
1343
1316
  content: membersPanelSource(membersActionsImport, membersViewImport),
1344
- always: true,
1345
1317
  },
1346
1318
  {
1347
1319
  rel: `${layout.componentsDir}/members-view.tsx`,
1348
1320
  content: membersViewSource(inviteImport),
1349
- always: true,
1350
1321
  },
1351
1322
  {
1352
1323
  rel: `${layout.componentsDir}/workspace-menu.tsx`,
1353
1324
  content: workspaceMenuSource(authClientImport),
1354
- always: true,
1355
1325
  },
1356
1326
  {
1357
1327
  rel: `${layout.componentsDir}/invite-member.tsx`,
1358
1328
  content: inviteMemberSource(authClientImport),
1359
- always: true,
1360
1329
  },
1361
1330
  {
1362
1331
  rel: `${layout.componentsDir}/session-user.tsx`,
1363
1332
  content: sessionUserSource(authClientImport),
1364
- always: true,
1365
1333
  },
1366
1334
  {
1367
1335
  rel: `${appDir}/(bare)/accept-invitation/page.tsx`,
1368
1336
  content: acceptInvitationPageSource(authClientImport),
1369
- always: true,
1370
1337
  },
1371
1338
  ];
1339
+ }
1340
+ /**
1341
+ * Re-emit compose's `always: true` gold-path files. Idempotent when bytes
1342
+ * already match. Used by `upgrade --all` so CLI gold-path fixes reach apps
1343
+ * composed on an older release without clobbering auth.ts / schema.
1344
+ */
1345
+ export async function reemitGoldPathOwned(targetDir, config) {
1346
+ const layout = goldPathLayout(config);
1347
+ const appDir = resolveAppDir(targetDir, layout, []);
1348
+ const written = [];
1349
+ for (const file of goldPathOwnedFiles(config, appDir)) {
1350
+ const dest = resolveSafeDest(targetDir, ".", file.rel);
1351
+ if (existsSync(dest)) {
1352
+ const current = await readFile(dest, "utf8");
1353
+ if (current === file.content)
1354
+ continue;
1355
+ }
1356
+ await writeFileEnsured(dest, file.content);
1357
+ written.push(file.rel);
1358
+ }
1359
+ return written;
1360
+ }
1361
+ /**
1362
+ * Write sqlite + Drizzle + Better-Auth files into a composed saas/admin app.
1363
+ * Overwrites owned adapters/panels always (`always: true`).
1364
+ * Patches the shell home, /team, and shell layout only when compose wrote them
1365
+ * this run.
1366
+ */
1367
+ export async function applyGoldPath(options) {
1368
+ const { targetDir, config, generatedFiles, overwrite } = options;
1369
+ const layout = goldPathLayout(config);
1370
+ const appDir = resolveAppDir(targetDir, layout, generatedFiles);
1371
+ const middlewareRel = appDir === "src/app"
1372
+ ? "src/middleware.ts"
1373
+ : appDir === "app"
1374
+ ? "middleware.ts"
1375
+ : layout.middlewareRel;
1376
+ const authImport = `${config.aliases.lib}/auth`;
1377
+ const itemsImport = "@/components/items-panel";
1378
+ const membersImport = "@/components/members-panel";
1379
+ const workspaceImport = "@/components/workspace-menu";
1380
+ const inviteImport = "@/components/invite-member";
1381
+ const sessionImport = "@/components/session-user";
1382
+ const chromeRel = `${posix(config.paths.blocks)}/app-shell-chrome.tsx`;
1383
+ const written = [];
1384
+ const skipped = [];
1385
+ const files = [
1386
+ { rel: "drizzle.config.ts", content: drizzleConfigSource(layout.dbDir) },
1387
+ { rel: `${layout.dbDir}/schema.ts`, content: dbSchemaSource() },
1388
+ { rel: `${layout.dbDir}/index.ts`, content: dbClientSource() },
1389
+ { rel: `${layout.libDir}/auth.ts`, content: authServerSource() },
1390
+ { rel: `${layout.libDir}/auth-client.ts`, content: authClientSource() },
1391
+ {
1392
+ rel: `${appDir}/api/auth/[...all]/route.ts`,
1393
+ content: authRouteSource(authImport),
1394
+ },
1395
+ { rel: middlewareRel, content: middlewareSource() },
1396
+ ...goldPathOwnedFiles(config, appDir).map((file) => ({ ...file, always: true })),
1397
+ ];
1372
1398
  for (const file of files) {
1373
1399
  await writeRel(targetDir, file.rel, file.content, overwrite, file.always === true, written, skipped);
1374
1400
  }
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.17";
3
- export declare const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.6.17/registry";
2
+ export declare const CLI_VERSION = "0.6.19";
3
+ export declare const DEFAULT_REGISTRY = "https://raw.githubusercontent.com/pedrogbraz/cronus-ui/v0.6.19/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.17";
5
+ export const CLI_VERSION = "0.6.19";
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.17",
3
+ "version": "0.6.19",
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.17",
57
+ "@cronus-ui/ai-kit": "0.6.19",
58
58
  "commander": "^15.0.0",
59
59
  "picocolors": "^1.1.1"
60
60
  },