@geekmidas/cli 10.0.0-alpha.55 → 10.0.0-alpha.56

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.
Files changed (72) hide show
  1. package/README.md +9 -8
  2. package/dist/{OpenApiTsGenerator-WlUHjimW.cjs → OpenApiTsGenerator-BLRQ7Iu9.cjs} +25 -49
  3. package/dist/OpenApiTsGenerator-BLRQ7Iu9.cjs.map +1 -0
  4. package/dist/{OpenApiTsGenerator-DKmAorGX.mjs → OpenApiTsGenerator-NThANByQ.mjs} +25 -49
  5. package/dist/OpenApiTsGenerator-NThANByQ.mjs.map +1 -0
  6. package/dist/{backends-BNrMPlJb.mjs → backends-BcHL7Gy_.mjs} +2 -2
  7. package/dist/{backends-BNrMPlJb.mjs.map → backends-BcHL7Gy_.mjs.map} +1 -1
  8. package/dist/{backends-nBauiBkt.cjs → backends-_gQdAzBK.cjs} +2 -2
  9. package/dist/{backends-nBauiBkt.cjs.map → backends-_gQdAzBK.cjs.map} +1 -1
  10. package/dist/{config-XEd-dKVX.mjs → config-20V08LZp.mjs} +2 -3
  11. package/dist/config-20V08LZp.mjs.map +1 -0
  12. package/dist/{config-C7NZG2tr.cjs → config-CP6wsLHA.cjs} +2 -3
  13. package/dist/config-CP6wsLHA.cjs.map +1 -0
  14. package/dist/config.cjs +2 -2
  15. package/dist/config.d.cts +2 -2
  16. package/dist/config.d.mts +2 -2
  17. package/dist/config.mjs +2 -2
  18. package/dist/{encryption-DSHYN5ap.cjs → encryption-10Srqiix.cjs} +4 -4
  19. package/dist/{encryption-DSHYN5ap.cjs.map → encryption-10Srqiix.cjs.map} +1 -1
  20. package/dist/{encryption-Bc1cMdeY.mjs → encryption-KQTYFEzU.mjs} +4 -4
  21. package/dist/{encryption-Bc1cMdeY.mjs.map → encryption-KQTYFEzU.mjs.map} +1 -1
  22. package/dist/{github-CWflxaV4.cjs → github-DtRUkHN8.cjs} +3 -3
  23. package/dist/{github-CWflxaV4.cjs.map → github-DtRUkHN8.cjs.map} +1 -1
  24. package/dist/{github-DWHXTcwL.mjs → github-y7OEj59M.mjs} +3 -3
  25. package/dist/{github-DWHXTcwL.mjs.map → github-y7OEj59M.mjs.map} +1 -1
  26. package/dist/{index-B8nraKvg.d.mts → index-DMcjpvd-.d.cts} +2 -2
  27. package/dist/{index-B8nraKvg.d.mts.map → index-DMcjpvd-.d.cts.map} +1 -1
  28. package/dist/{index-BvBQS89a.d.cts → index-RM92lx8A.d.mts} +2 -2
  29. package/dist/{index-BvBQS89a.d.cts.map → index-RM92lx8A.d.mts.map} +1 -1
  30. package/dist/index.cjs +200 -1083
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.mjs +200 -1083
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/{migrate-PcQg692O.mjs → migrate-CS3DkO6y.mjs} +4 -4
  35. package/dist/{migrate-PcQg692O.mjs.map → migrate-CS3DkO6y.mjs.map} +1 -1
  36. package/dist/{migrate-DHMRgnP6.cjs → migrate-DQ54y2WD.cjs} +4 -4
  37. package/dist/{migrate-DHMRgnP6.cjs.map → migrate-DQ54y2WD.cjs.map} +1 -1
  38. package/dist/openapi.cjs +2 -2
  39. package/dist/openapi.d.cts +1 -1
  40. package/dist/openapi.d.mts +1 -1
  41. package/dist/openapi.mjs +2 -2
  42. package/dist/{ready-bES_Jk5v.mjs → ready-BSpUZnNo.mjs} +2 -2
  43. package/dist/ready-BSpUZnNo.mjs.map +1 -0
  44. package/dist/{ready-BefA4mM0.cjs → ready-MUhVJDHe.cjs} +2 -2
  45. package/dist/ready-MUhVJDHe.cjs.map +1 -0
  46. package/dist/reconcile/public.d.cts +1 -1
  47. package/dist/reconcile/public.d.mts +1 -1
  48. package/dist/{types-Cgj-cq2m.d.mts → types-BIyIQUR-.d.cts} +3 -30
  49. package/dist/{types-CmxMhLGp.d.cts.map → types-BIyIQUR-.d.cts.map} +1 -1
  50. package/dist/{types-CmxMhLGp.d.cts → types-CmQl6zaP.d.mts} +2 -31
  51. package/dist/{types-Cgj-cq2m.d.mts.map → types-CmQl6zaP.d.mts.map} +1 -1
  52. package/dist/vitest.cjs +1 -1
  53. package/dist/vitest.mjs +1 -1
  54. package/dist/workspace/index.cjs +1 -1
  55. package/dist/workspace/index.d.cts +2 -2
  56. package/dist/workspace/index.d.mts +2 -2
  57. package/dist/workspace/index.mjs +1 -1
  58. package/dist/{workspace-CXvYabDJ.cjs → workspace-BbPJVCto.cjs} +5 -5
  59. package/dist/{workspace-CXvYabDJ.cjs.map → workspace-BbPJVCto.cjs.map} +1 -1
  60. package/dist/{workspace-DL_99LJC.cjs → workspace-BpdXIeWV.cjs} +1 -16
  61. package/dist/{workspace-DL_99LJC.cjs.map → workspace-BpdXIeWV.cjs.map} +1 -1
  62. package/dist/{workspace-DHK2N1mq.mjs → workspace-C2mFV53i.mjs} +1 -16
  63. package/dist/{workspace-DHK2N1mq.mjs.map → workspace-C2mFV53i.mjs.map} +1 -1
  64. package/dist/{workspace-BE0WHPw9.mjs → workspace-CgWcE_Yr.mjs} +5 -5
  65. package/dist/{workspace-BE0WHPw9.mjs.map → workspace-CgWcE_Yr.mjs.map} +1 -1
  66. package/package.json +13 -14
  67. package/dist/OpenApiTsGenerator-DKmAorGX.mjs.map +0 -1
  68. package/dist/OpenApiTsGenerator-WlUHjimW.cjs.map +0 -1
  69. package/dist/config-C7NZG2tr.cjs.map +0 -1
  70. package/dist/config-XEd-dKVX.mjs.map +0 -1
  71. package/dist/ready-BefA4mM0.cjs.map +0 -1
  72. package/dist/ready-bES_Jk5v.mjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -2,15 +2,15 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
4
4
  const require_discover = require("./discover-DXNviAh-.cjs");
5
- const require_config = require("./config-C7NZG2tr.cjs");
6
- const require_workspace = require("./workspace-DL_99LJC.cjs");
5
+ const require_config = require("./config-CP6wsLHA.cjs");
6
+ const require_workspace = require("./workspace-BpdXIeWV.cjs");
7
7
  const require_storage = require("./storage-CSGoC3bK.cjs");
8
8
  const require_store = require("./store-DQgxT_WR.cjs");
9
- const require_workspace$1 = require("./workspace-CXvYabDJ.cjs");
10
- const require_OpenApiTsGenerator = require("./OpenApiTsGenerator-WlUHjimW.cjs");
9
+ const require_workspace$1 = require("./workspace-BbPJVCto.cjs");
10
+ const require_OpenApiTsGenerator = require("./OpenApiTsGenerator-BLRQ7Iu9.cjs");
11
11
  const require_openapi = require("./openapi.cjs");
12
- const require_ready = require("./ready-BefA4mM0.cjs");
13
- const require_backends = require("./backends-nBauiBkt.cjs");
12
+ const require_ready = require("./ready-MUhVJDHe.cjs");
13
+ const require_backends = require("./backends-_gQdAzBK.cjs");
14
14
  const require_emit = require("./emit-Dmc1nvdS.cjs");
15
15
  let commander = require("commander");
16
16
  let node_process = require("node:process");
@@ -48,7 +48,7 @@ let _geekmidas_constructs_queue = require("@geekmidas/constructs/queue");
48
48
  let _geekmidas_constructs_topic = require("@geekmidas/constructs/topic");
49
49
  let node_dns_promises = require("node:dns/promises");
50
50
  //#region package.json
51
- var version = "10.0.0-alpha.55";
51
+ var version = "10.0.0-alpha.56";
52
52
  //#endregion
53
53
  //#region src/auth/credentials.ts
54
54
  /**
@@ -1339,30 +1339,6 @@ function normalizeTelescopeConfig(config) {
1339
1339
  };
1340
1340
  }
1341
1341
  /**
1342
- * Normalize studio configuration
1343
- * @internal Exported for testing
1344
- */
1345
- function normalizeStudioConfig(config) {
1346
- if (config === false) return;
1347
- if (typeof config === "string") {
1348
- const { path: studioPath, importPattern: studioImportPattern } = require_config.parseModuleConfig(config, "studio");
1349
- return {
1350
- enabled: true,
1351
- studioPath,
1352
- studioImportPattern,
1353
- path: "/__studio",
1354
- schema: "public"
1355
- };
1356
- }
1357
- if (!(config === true || config === void 0 || config.enabled !== false)) return;
1358
- const studioConfig = typeof config === "object" ? config : {};
1359
- return {
1360
- enabled: true,
1361
- path: studioConfig.path ?? "/__studio",
1362
- schema: studioConfig.schema ?? "public"
1363
- };
1364
- }
1365
- /**
1366
1342
  * Normalize hooks configuration
1367
1343
  * @internal Exported for testing
1368
1344
  */
@@ -1439,7 +1415,6 @@ async function devCommand(options) {
1439
1415
  if (missing.length > 0) logger$9.warn(`⚠️ Missing env files: ${missing.join(", ")}`);
1440
1416
  }
1441
1417
  const telescope = normalizeTelescopeConfig(config.telescope);
1442
- const studio = normalizeStudioConfig(config.studio);
1443
1418
  const hooks = normalizeHooksConfig(config.hooks, appRoot);
1444
1419
  const enableOpenApi = require_openapi.resolveOpenApiConfig(config).enabled;
1445
1420
  const build = (bustCache = false) => quietly(() => buildApp({
@@ -1450,7 +1425,7 @@ async function devCommand(options) {
1450
1425
  enableOpenApi,
1451
1426
  cacheBackend: require_backends.cacheBackendFor(require_backends.providerOf(workspace ?? config)),
1452
1427
  telescope,
1453
- studio,
1428
+ databaseApi: true,
1454
1429
  hooks,
1455
1430
  skipBundle: true,
1456
1431
  bustCache,
@@ -1483,7 +1458,7 @@ async function devCommand(options) {
1483
1458
  secretsJsonPath = (0, node_path.join)(secretsDir, secretsFileName);
1484
1459
  await (0, node_fs_promises.writeFile)(secretsJsonPath, JSON.stringify(appSecrets, null, 2));
1485
1460
  }
1486
- const devServer = new DevServer(options.port ?? workspaceAppPort ?? 3e3, options.portExplicit ?? workspaceAppPort !== void 0, enableOpenApi, telescope, studio, runtime, appRoot, secretsJsonPath, initial.selfServing !== void 0);
1461
+ const devServer = new DevServer(options.port ?? workspaceAppPort ?? 3e3, options.portExplicit ?? workspaceAppPort !== void 0, enableOpenApi, telescope, initial.databaseApi, runtime, appRoot, secretsJsonPath, initial.selfServing !== void 0);
1487
1462
  devServer.label = workspaceAppName ?? "server";
1488
1463
  devServer.publicUrl = publicUrl;
1489
1464
  await devServer.start();
@@ -1771,9 +1746,9 @@ async function workspaceDevCommand(configured, options) {
1771
1746
  for (const { id, port } of fakes) logger$9.log(`🎭 ${id} fake: http://localhost:${port}`);
1772
1747
  logger$9.log(options.migrate || options.seed ? "🗄️ Migrating the databases" : "🗄️ Checking for pending migrations");
1773
1748
  if (options.migrate || options.seed) {
1774
- const { prepareDevDatabases } = await Promise.resolve().then(() => require("./migrate-DHMRgnP6.cjs"));
1749
+ const { prepareDevDatabases } = await Promise.resolve().then(() => require("./migrate-DQ54y2WD.cjs"));
1775
1750
  await prepareDevDatabases(workspace, reconciled.env, { seed: !!options.seed });
1776
- } else await Promise.resolve().then(() => require("./migrate-DHMRgnP6.cjs")).then(({ reportPendingMigrations }) => reportPendingMigrations(workspace, reconciled.env)).catch((error) => {
1751
+ } else await Promise.resolve().then(() => require("./migrate-DQ54y2WD.cjs")).then(({ reportPendingMigrations }) => reportPendingMigrations(workspace, reconciled.env)).catch((error) => {
1777
1752
  logger$9.log(`⚠️ Could not check for pending migrations: ${error instanceof Error ? error.message : String(error)}`);
1778
1753
  });
1779
1754
  const appUrls = {};
@@ -2167,7 +2142,7 @@ var DevServer = class {
2167
2142
  portExplicit;
2168
2143
  enableOpenApi;
2169
2144
  telescope;
2170
- studio;
2145
+ databaseApi;
2171
2146
  runtime;
2172
2147
  appRoot;
2173
2148
  secretsJsonPath;
@@ -2176,12 +2151,12 @@ var DevServer = class {
2176
2151
  isRunning = false;
2177
2152
  actualPort;
2178
2153
  startTime = Date.now();
2179
- constructor(requestedPort, portExplicit, enableOpenApi, telescope, studio, runtime = "node", appRoot = process.cwd(), secretsJsonPath, selfServing = false) {
2154
+ constructor(requestedPort, portExplicit, enableOpenApi, telescope, databaseApi, runtime = "node", appRoot = process.cwd(), secretsJsonPath, selfServing = false) {
2180
2155
  this.requestedPort = requestedPort;
2181
2156
  this.portExplicit = portExplicit;
2182
2157
  this.enableOpenApi = enableOpenApi;
2183
2158
  this.telescope = telescope;
2184
- this.studio = studio;
2159
+ this.databaseApi = databaseApi;
2185
2160
  this.runtime = runtime;
2186
2161
  this.appRoot = appRoot;
2187
2162
  this.secretsJsonPath = secretsJsonPath;
@@ -2238,7 +2213,7 @@ var DevServer = class {
2238
2213
  const tools = this.selfServing ? [] : [
2239
2214
  ...this.enableOpenApi ? ["docs /__docs"] : [],
2240
2215
  ...this.telescope ? [`telescope ${this.telescope.path}`] : [],
2241
- ...this.studio ? [`studio ${this.studio.path}`] : []
2216
+ ...this.databaseApi ? [`db ${this.databaseApi}`] : []
2242
2217
  ];
2243
2218
  if (tools.length > 0) logger$9.log(` ${tools.join(" · ")}`);
2244
2219
  }
@@ -2885,18 +2860,26 @@ function keyFingerprint(masterKey) {
2885
2860
  return (0, node_crypto.createHash)("sha256").update(masterKey).digest("hex").slice(0, 8);
2886
2861
  }
2887
2862
  //#endregion
2863
+ //#region src/build/types.ts
2864
+ /**
2865
+ * Where `gkm dev` serves the database's read-only JSON API
2866
+ * (`@geekmidas/db/introspect`). Under `/__gkm` with the rest of what the dev
2867
+ * server adds, so it cannot collide with an application route.
2868
+ */
2869
+ const DEV_DATABASE_API_PATH = "/__gkm/db";
2870
+ //#endregion
2888
2871
  //#region src/build/owners.ts
2889
2872
  /**
2890
2873
  * What a generated entry imports its runtime from, read off the discovered
2891
2874
  * constructs: the surface it serves, every construct a runnable can be built
2892
- * from, and the database Studio browses.
2875
+ * from, and the database the dev server's JSON API reads.
2893
2876
  *
2894
2877
  * `gkm build` and `gkm dev` both write entries that import the surface for its
2895
2878
  * logger and environment parser, so both ask here. A dev server that skipped it
2896
2879
  * had nothing to import them from.
2897
2880
  */
2898
2881
  function ownersContext(options) {
2899
- const { declared, sources, workspaceRoot, appRoot, studio } = options;
2882
+ const { declared, sources, workspaceRoot, appRoot, databaseApi } = options;
2900
2883
  const surfaces = restApis(declared);
2901
2884
  const primary = servedSurface(declared, workspaceRoot, appRoot) ?? surfaces.find((d) => d.endpoints.length === 0) ?? surfaces[0];
2902
2885
  const browsable = Object.entries(declared).find(([, d]) => d.kind === "database");
@@ -2923,13 +2906,13 @@ function ownersContext(options) {
2923
2906
  exportName: primarySource.exportName
2924
2907
  } } : {}
2925
2908
  } } : {},
2926
- studio: studio && browsableSource ? {
2927
- ...studio,
2909
+ ...databaseApi && browsableSource ? { databaseApi: {
2910
+ path: DEV_DATABASE_API_PATH,
2928
2911
  database: {
2929
2912
  specifier: browsableSource.file,
2930
2913
  exportName: browsableSource.exportName
2931
2914
  }
2932
- } : studio
2915
+ } } : {}
2933
2916
  };
2934
2917
  }
2935
2918
  /**
@@ -3112,8 +3095,6 @@ async function buildOneApp(input) {
3112
3095
  logger$8.log(`Loading constructs from: ${formatRoutes(config.constructs)}`);
3113
3096
  const telescope = production ? void 0 : normalizeTelescopeConfig(config.telescope);
3114
3097
  if (telescope) logger$8.log(`🔭 Telescope enabled at ${telescope.path}`);
3115
- const studio = production ? void 0 : normalizeStudioConfig(config.studio);
3116
- if (studio) logger$8.log(`🗄️ Studio enabled at ${studio.path}`);
3117
3098
  const hooks = normalizeHooksConfig(config.hooks, appRoot);
3118
3099
  if (hooks) logger$8.log(`🪝 Server hooks enabled`);
3119
3100
  return buildApp({
@@ -3125,7 +3106,6 @@ async function buildOneApp(input) {
3125
3106
  cacheBackend,
3126
3107
  production,
3127
3108
  telescope,
3128
- studio,
3129
3109
  hooks,
3130
3110
  markOptional: options.markOptional ?? false,
3131
3111
  skipBundle: options.skipBundle ?? false,
@@ -3168,7 +3148,7 @@ async function writeManifest(input) {
3168
3148
  * dev did not, and failed on exactly the apps the build had learned to handle.
3169
3149
  */
3170
3150
  async function buildApp(input) {
3171
- const { config, workspaceRoot, appRoot, target, enableOpenApi, cacheBackend, production, telescope, studio, hooks, bustCache = false } = input;
3151
+ const { config, workspaceRoot, appRoot, target, enableOpenApi, cacheBackend, production, telescope, databaseApi, hooks, bustCache = false } = input;
3172
3152
  const constructGlobs = config.constructs;
3173
3153
  const constructSources = {};
3174
3154
  const declared = constructGlobs ? await require_discover.discover({
@@ -3193,7 +3173,7 @@ async function buildApp(input) {
3193
3173
  sources: constructSources,
3194
3174
  workspaceRoot,
3195
3175
  appRoot,
3196
- studio
3176
+ databaseApi
3197
3177
  });
3198
3178
  const buildContext = {
3199
3179
  ...derived,
@@ -3252,7 +3232,10 @@ async function buildApp(input) {
3252
3232
  openapi: config.openapi,
3253
3233
  root: workspaceRoot
3254
3234
  });
3255
- return result;
3235
+ return {
3236
+ ...result,
3237
+ ...buildContext.databaseApi ? { databaseApi: buildContext.databaseApi.path } : {}
3238
+ };
3256
3239
  }
3257
3240
  async function buildForTarget(target, context, appRoot, workspaceRoot, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, queueGenerator, topicGenerator, endpoints, functions, crons, subscribers, queues, topics, enableOpenApi, skipBundle, stage) {
3258
3241
  const outputDir = (0, node_path.join)(appRoot, ".gkm", target);
@@ -9532,7 +9515,7 @@ opened.
9532
9515
  `;
9533
9516
  }
9534
9517
  function agentsContent(options, template) {
9535
- const { name, monorepo, telescope, studio, packageManager } = options;
9518
+ const { name, monorepo, telescope, packageManager } = options;
9536
9519
  const { database } = options.constructs;
9537
9520
  const constructsGlob = monorepo ? WORKSPACE_CONSTRUCTS_GLOB : CONSTRUCTS_GLOB;
9538
9521
  const isWorker = template.name === "worker";
@@ -9627,13 +9610,13 @@ export const config = envParser
9627
9610
  as \`undefined\` in exactly the environments that matter.`);
9628
9611
  sections.push(conventionsSection());
9629
9612
  sections.push(testingSection(database));
9630
- if (telescope || studio) {
9631
- const tools = [telescope && "**Telescope** — request and exception monitoring", studio && "**Studio** — dev dashboard and database browser"].filter(Boolean);
9613
+ if (telescope || database) {
9614
+ const tools = [telescope && "**Telescope** — requests, exceptions and logs as JSON at `/__telescope/api`", database && "**Database API** — `gkm dev` serves the declared database, read-only, as JSON at `/__gkm/db`"].filter(Boolean);
9632
9615
  sections.push(`## Dev tools
9633
9616
 
9634
9617
  ${tools.map((t) => `- ${t}`).join("\n")}
9635
9618
 
9636
- Both are derived from declared constructs. Neither needs wiring up by hand.`);
9619
+ Derived from declared constructs and served only by \`gkm dev\`: nothing to wire up by hand, and no UI — JSON for whatever tool you point at it.`);
9637
9620
  }
9638
9621
  sections.push(`## Before you say it works
9639
9622
 
@@ -10076,11 +10059,7 @@ const TOOLCHAIN_VERSIONS = {
10076
10059
  esbuild: "~0.28.2",
10077
10060
  vitest: "~5.0.2",
10078
10061
  vite: "~8.3.1",
10079
- "@vitejs/plugin-react": "^6.1.1",
10080
- storybook: "^10.6.0",
10081
- "@storybook/addon-docs": "^10.6.0",
10082
- "@storybook/addon-a11y": "^10.6.0",
10083
- "@storybook/react-vite": "^10.6.0"
10062
+ "@vitejs/plugin-react": "^6.1.1"
10084
10063
  };
10085
10064
  /**
10086
10065
  * The Expo app's packages, which track an Expo SDK release (57) rather than
@@ -10140,26 +10119,25 @@ function loadPackageJson() {
10140
10119
  * Run: pnpm --filter @geekmidas/cli sync-versions
10141
10120
  */
10142
10121
  const GEEKMIDAS_VERSIONS = {
10143
- "@geekmidas/audit": "~10.0.0-alpha.55",
10144
- "@geekmidas/auth": "~10.0.0-alpha.55",
10145
- "@geekmidas/cache": "~10.0.0-alpha.55",
10146
- "@geekmidas/client": "~10.0.0-alpha.55",
10147
- "@geekmidas/cloud": "~10.0.0-alpha.55",
10148
- "@geekmidas/constructs": "~10.0.0-alpha.55",
10149
- "@geekmidas/db": "~10.0.0-alpha.55",
10150
- "@geekmidas/emailkit": "~10.0.0-alpha.55",
10151
- "@geekmidas/envkit": "~10.0.0-alpha.55",
10152
- "@geekmidas/errors": "~10.0.0-alpha.55",
10153
- "@geekmidas/events": "~10.0.0-alpha.55",
10154
- "@geekmidas/logger": "~10.0.0-alpha.55",
10155
- "@geekmidas/manifest": "~10.0.0-alpha.55",
10156
- "@geekmidas/rate-limit": "~10.0.0-alpha.55",
10157
- "@geekmidas/schema": "~10.0.0-alpha.55",
10158
- "@geekmidas/services": "~10.0.0-alpha.55",
10159
- "@geekmidas/storage": "~10.0.0-alpha.55",
10160
- "@geekmidas/studio": "~10.0.0-alpha.55",
10161
- "@geekmidas/telescope": "~10.0.0-alpha.55",
10162
- "@geekmidas/testkit": "~10.0.0-alpha.55",
10122
+ "@geekmidas/audit": "~10.0.0-alpha.56",
10123
+ "@geekmidas/auth": "~10.0.0-alpha.56",
10124
+ "@geekmidas/cache": "~10.0.0-alpha.56",
10125
+ "@geekmidas/client": "~10.0.0-alpha.56",
10126
+ "@geekmidas/cloud": "~10.0.0-alpha.56",
10127
+ "@geekmidas/constructs": "~10.0.0-alpha.56",
10128
+ "@geekmidas/db": "~10.0.0-alpha.56",
10129
+ "@geekmidas/emailkit": "~10.0.0-alpha.56",
10130
+ "@geekmidas/envkit": "~10.0.0-alpha.56",
10131
+ "@geekmidas/errors": "~10.0.0-alpha.56",
10132
+ "@geekmidas/events": "~10.0.0-alpha.56",
10133
+ "@geekmidas/logger": "~10.0.0-alpha.56",
10134
+ "@geekmidas/manifest": "~10.0.0-alpha.56",
10135
+ "@geekmidas/rate-limit": "~10.0.0-alpha.56",
10136
+ "@geekmidas/schema": "~10.0.0-alpha.56",
10137
+ "@geekmidas/services": "~10.0.0-alpha.56",
10138
+ "@geekmidas/storage": "~10.0.0-alpha.56",
10139
+ "@geekmidas/telescope": "~10.0.0-alpha.56",
10140
+ "@geekmidas/testkit": "~10.0.0-alpha.56",
10163
10141
  "@geekmidas/cli": `~${loadPackageJson().version}`
10164
10142
  };
10165
10143
  //#endregion
@@ -10282,14 +10260,13 @@ export default defineConfig({
10282
10260
  * Generate configuration files (gkm.config.ts, tsconfig.json, biome.json, turbo.json)
10283
10261
  */
10284
10262
  function generateConfigFiles(options, template) {
10285
- const { telescope, studio, routesStructure } = options;
10263
+ const { telescope, routesStructure } = options;
10286
10264
  const isServerless = template.name === "serverless";
10287
10265
  const hasWorker = template.name === "worker";
10288
10266
  const isFullstack = options.template === "fullstack";
10289
10267
  const getRoutesGlob = () => routesGlob(routesStructure);
10290
10268
  if (isFullstack) return generateSingleAppConfigFiles(options, template, {
10291
10269
  telescope,
10292
- studio,
10293
10270
  routesStructure,
10294
10271
  isServerless,
10295
10272
  hasWorker,
@@ -10315,8 +10292,6 @@ export default defineConfig({${stagesBlock(options.stages)}${options.monorepo ?
10315
10292
  enabled: true,
10316
10293
  path: '/__telescope',
10317
10294
  },`;
10318
- if (studio) gkmConfig += `
10319
- studio: './src/config/studio#studio',`;
10320
10295
  gkmConfig += `
10321
10296
  openapi: {
10322
10297
  enabled: true,
@@ -11865,7 +11840,6 @@ function generateMonorepoFiles(options, _template) {
11865
11840
  lint: "biome lint .",
11866
11841
  fmt: "biome format . --write",
11867
11842
  "fmt:check": "biome format .",
11868
- ...isFullstack ? { storybook: "pnpm --filter ./packages/ui storybook" } : {},
11869
11843
  ...deploy.scripts
11870
11844
  },
11871
11845
  dependencies: {
@@ -12406,14 +12380,13 @@ export const cache = new Cache('${kv.id}');
12406
12380
  * Generate package.json with dependencies based on template and options
12407
12381
  */
12408
12382
  function generatePackageJson(options, template) {
12409
- const { name, telescope, studio, monorepo } = options;
12383
+ const { name, telescope, monorepo } = options;
12410
12384
  const { database, cache, uploads, mail } = options.constructs;
12411
12385
  const dependencies = { ...template.dependencies };
12412
12386
  const devDependencies = { ...template.devDependencies };
12413
12387
  const scripts = { ...template.scripts };
12414
12388
  if (options.loggerType === "pino") dependencies.pino = DEPENDENCY_VERSIONS.pino;
12415
12389
  if (telescope) dependencies["@geekmidas/telescope"] = GEEKMIDAS_VERSIONS["@geekmidas/telescope"];
12416
- if (studio) dependencies["@geekmidas/studio"] = GEEKMIDAS_VERSIONS["@geekmidas/studio"];
12417
12390
  const declares = !monorepo;
12418
12391
  if (declares && (database || uploads || cache || mail)) dependencies["@geekmidas/manifest"] = GEEKMIDAS_VERSIONS["@geekmidas/manifest"];
12419
12392
  if (declares && uploads) dependencies["@geekmidas/storage"] = GEEKMIDAS_VERSIONS["@geekmidas/storage"];
@@ -12554,158 +12527,33 @@ export type Factory = ReturnType<typeof createFactory>;
12554
12527
  }];
12555
12528
  }
12556
12529
  //#endregion
12557
- //#region src/init/generators/ui.ts
12530
+ //#region src/init/generators/shadcn.ts
12558
12531
  /**
12559
- * Generate UI package files for fullstack template
12560
- * Based on @geekmidas/ui with shadcn/ui, Tailwind CSS v4, and Storybook
12561
- */
12562
- function generateUiPackageFiles(options) {
12563
- if (!options.monorepo || options.template !== "fullstack") return [];
12564
- const packageJson = {
12565
- name: `@${options.name}/ui`,
12566
- version: "0.0.1",
12567
- private: true,
12568
- type: "module",
12569
- exports: {
12570
- ".": "./src/index.ts",
12571
- "./components": "./src/components/index.ts",
12572
- "./lib/utils": "./src/lib/utils.ts",
12573
- "./styles": "./src/styles/globals.css"
12574
- },
12575
- scripts: {
12576
- "ts:check": "tsc --noEmit",
12577
- storybook: "storybook dev -p 6006",
12578
- "build:storybook": "storybook build -o dist/storybook"
12579
- },
12580
- dependencies: {
12581
- "@radix-ui/react-dialog": DEPENDENCY_VERSIONS["@radix-ui/react-dialog"],
12582
- "@radix-ui/react-label": DEPENDENCY_VERSIONS["@radix-ui/react-label"],
12583
- "@radix-ui/react-separator": DEPENDENCY_VERSIONS["@radix-ui/react-separator"],
12584
- "@radix-ui/react-slot": DEPENDENCY_VERSIONS["@radix-ui/react-slot"],
12585
- "@radix-ui/react-tabs": DEPENDENCY_VERSIONS["@radix-ui/react-tabs"],
12586
- "@radix-ui/react-tooltip": DEPENDENCY_VERSIONS["@radix-ui/react-tooltip"],
12587
- "class-variance-authority": DEPENDENCY_VERSIONS["class-variance-authority"],
12588
- clsx: DEPENDENCY_VERSIONS["clsx"],
12589
- "lucide-react": DEPENDENCY_VERSIONS["lucide-react"],
12590
- "tailwind-merge": DEPENDENCY_VERSIONS["tailwind-merge"]
12591
- },
12592
- devDependencies: {
12593
- "@storybook/addon-a11y": TOOLCHAIN_VERSIONS["@storybook/addon-a11y"],
12594
- "@storybook/addon-docs": TOOLCHAIN_VERSIONS["@storybook/addon-docs"],
12595
- "@storybook/react-vite": TOOLCHAIN_VERSIONS["@storybook/react-vite"],
12596
- "@tailwindcss/vite": DEPENDENCY_VERSIONS["@tailwindcss/vite"],
12597
- "@types/react": DEPENDENCY_VERSIONS["@types/react"],
12598
- "@types/react-dom": DEPENDENCY_VERSIONS["@types/react-dom"],
12599
- react: DEPENDENCY_VERSIONS["react"],
12600
- "react-dom": DEPENDENCY_VERSIONS["react-dom"],
12601
- storybook: TOOLCHAIN_VERSIONS["storybook"],
12602
- tailwindcss: DEPENDENCY_VERSIONS["tailwindcss"],
12603
- typescript: TOOLCHAIN_VERSIONS["typescript"],
12604
- vite: TOOLCHAIN_VERSIONS["vite"]
12605
- },
12606
- peerDependencies: {
12607
- react: ">=18.0.0",
12608
- "react-dom": ">=18.0.0",
12609
- tailwindcss: ">=4.0.0"
12610
- }
12611
- };
12612
- const tsConfig = {
12613
- extends: "../../tsconfig.json",
12614
- compilerOptions: {
12615
- jsx: "react-jsx",
12616
- lib: [
12617
- "ES2023",
12618
- "DOM",
12619
- "DOM.Iterable"
12620
- ],
12621
- noEmit: true,
12622
- allowImportingTsExtensions: true,
12623
- paths: { "~/*": ["./src/*"] }
12624
- },
12625
- include: ["src/**/*"],
12626
- exclude: [
12627
- "node_modules",
12628
- "dist",
12629
- "**/*.stories.tsx"
12630
- ]
12631
- };
12632
- const componentsJson = {
12633
- $schema: "https://ui.shadcn.com/schema.json",
12634
- style: "new-york",
12635
- rsc: false,
12636
- tsx: true,
12637
- tailwind: {
12638
- config: "",
12639
- css: "src/styles/globals.css",
12640
- baseColor: "neutral",
12641
- cssVariables: true,
12642
- prefix: ""
12643
- },
12644
- aliases: {
12645
- components: "~/components",
12646
- utils: "~/lib/utils",
12647
- ui: "~/components/ui",
12648
- lib: "~/lib",
12649
- hooks: "~/hooks"
12650
- },
12651
- iconLibrary: "lucide"
12652
- };
12653
- const storybookMain = `import type { StorybookConfig } from '@storybook/react-vite';
12654
-
12655
- const config: StorybookConfig = {
12656
- stories: ['../src/**/*.stories.@(ts|tsx)'],
12657
- // Controls, actions, backgrounds, viewport and interactions are part of
12658
- // \`storybook\` itself; docs and a11y are add-ons.
12659
- addons: ['@storybook/addon-docs', '@storybook/addon-a11y'],
12660
- framework: {
12661
- name: '@storybook/react-vite',
12662
- options: {},
12663
- },
12664
- // \`react-docgen\` parses components itself. The TypeScript-based docgen
12665
- // calls into TypeScript's JavaScript API, which TypeScript 7 no longer ships.
12666
- typescript: {
12667
- reactDocgen: 'react-docgen',
12668
- },
12669
- viteFinal: async (config) => {
12670
- // Add Tailwind CSS v4 plugin
12671
- const tailwindcss = await import('@tailwindcss/vite');
12672
- config.plugins = config.plugins || [];
12673
- config.plugins.push(tailwindcss.default());
12674
- return config;
12675
- },
12676
- };
12677
-
12678
- export default config;
12679
- `;
12680
- const storybookPreview = `import type { Preview } from '@storybook/react-vite';
12681
- import '../src/styles/globals.css';
12682
-
12683
- const preview: Preview = {
12684
- // The starting background is a global, not a parameter.
12685
- initialGlobals: {
12686
- backgrounds: { value: 'dark' },
12687
- },
12688
- parameters: {
12689
- backgrounds: {
12690
- options: {
12691
- dark: { name: 'dark', value: '#171717' },
12692
- surface: { name: 'surface', value: '#1c1c1c' },
12693
- light: { name: 'light', value: '#fafafa' },
12694
- },
12695
- },
12696
- controls: {
12697
- matchers: {
12698
- color: /(background|color)$/i,
12699
- date: /Date$/i,
12700
- },
12701
- },
12702
- layout: 'centered',
12703
- },
12532
+ * shadcn/ui components, written into the web app that uses them.
12533
+ *
12534
+ * shadcn is copy-in by design: the components are the app's own source, to
12535
+ * edit and add to with `npx shadcn@latest add`. A shared workspace package of
12536
+ * them was one more package to build and version for code only the web app
12537
+ * imported.
12538
+ */
12539
+ /** What the components below import. */
12540
+ const SHADCN_DEPENDENCIES = {
12541
+ "@radix-ui/react-dialog": DEPENDENCY_VERSIONS["@radix-ui/react-dialog"],
12542
+ "@radix-ui/react-label": DEPENDENCY_VERSIONS["@radix-ui/react-label"],
12543
+ "@radix-ui/react-separator": DEPENDENCY_VERSIONS["@radix-ui/react-separator"],
12544
+ "@radix-ui/react-slot": DEPENDENCY_VERSIONS["@radix-ui/react-slot"],
12545
+ "@radix-ui/react-tabs": DEPENDENCY_VERSIONS["@radix-ui/react-tabs"],
12546
+ "@radix-ui/react-tooltip": DEPENDENCY_VERSIONS["@radix-ui/react-tooltip"],
12547
+ "class-variance-authority": DEPENDENCY_VERSIONS["class-variance-authority"],
12548
+ clsx: DEPENDENCY_VERSIONS["clsx"],
12549
+ "lucide-react": DEPENDENCY_VERSIONS["lucide-react"],
12550
+ "tailwind-merge": DEPENDENCY_VERSIONS["tailwind-merge"]
12704
12551
  };
12705
-
12706
- export default preview;
12707
- `;
12708
- const globalsCss = `@import "tailwindcss";
12552
+ /**
12553
+ * Tailwind v4 with the shadcn theme tokens — the stylesheet the app imports
12554
+ * once, at its root.
12555
+ */
12556
+ const SHADCN_GLOBALS_CSS = `@import "tailwindcss";
12709
12557
 
12710
12558
  @theme {
12711
12559
  --color-background: hsl(var(--background));
@@ -12789,14 +12637,56 @@ export default preview;
12789
12637
  }
12790
12638
  }
12791
12639
  `;
12792
- const utilsTs = `import { type ClassValue, clsx } from 'clsx';
12640
+ /**
12641
+ * The components, `cn`, and the `components.json` that tells the shadcn CLI
12642
+ * where they live.
12643
+ *
12644
+ * @param appDir the web app, relative to the workspace root (`apps/web`)
12645
+ * @param css the stylesheet holding {@link SHADCN_GLOBALS_CSS}, relative to
12646
+ * the app
12647
+ * @param options.rsc whether the app renders React Server Components, so
12648
+ * `shadcn add` marks what it writes `'use client'`. The radix-based
12649
+ * components here carry the directive either way; outside RSC it is inert.
12650
+ */
12651
+ function shadcnFiles(appDir, css, options) {
12652
+ const componentsJson = {
12653
+ $schema: "https://ui.shadcn.com/schema.json",
12654
+ style: "new-york",
12655
+ rsc: options.rsc,
12656
+ tsx: true,
12657
+ tailwind: {
12658
+ config: "",
12659
+ css,
12660
+ baseColor: "neutral",
12661
+ cssVariables: true,
12662
+ prefix: ""
12663
+ },
12664
+ aliases: {
12665
+ components: "~/components",
12666
+ utils: "~/lib/utils",
12667
+ ui: "~/components/ui",
12668
+ lib: "~/lib",
12669
+ hooks: "~/hooks"
12670
+ },
12671
+ iconLibrary: "lucide"
12672
+ };
12673
+ return [
12674
+ {
12675
+ path: `${appDir}/components.json`,
12676
+ content: `${JSON.stringify(componentsJson, null, 2)}\n`
12677
+ },
12678
+ {
12679
+ path: `${appDir}/src/lib/utils.ts`,
12680
+ content: `import { type ClassValue, clsx } from 'clsx';
12793
12681
  import { twMerge } from 'tailwind-merge';
12794
12682
 
12795
12683
  export function cn(...inputs: ClassValue[]) {
12796
12684
  return twMerge(clsx(inputs));
12797
12685
  }
12798
- `;
12799
- const buttonTsx = `import { Slot } from '@radix-ui/react-slot';
12686
+ `
12687
+ },
12688
+ ...Object.entries({
12689
+ button: `import { Slot } from '@radix-ui/react-slot';
12800
12690
  import { cva, type VariantProps } from 'class-variance-authority';
12801
12691
  import * as React from 'react';
12802
12692
 
@@ -12853,73 +12743,8 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
12853
12743
  Button.displayName = 'Button';
12854
12744
 
12855
12745
  export { Button, buttonVariants };
12856
- `;
12857
- const buttonStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12858
- import { Button } from '~/components/ui/button';
12859
-
12860
- const meta: Meta<typeof Button> = {
12861
- title: 'Components/Button',
12862
- component: Button,
12863
- tags: ['autodocs'],
12864
- argTypes: {
12865
- variant: {
12866
- control: 'select',
12867
- options: ['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'],
12868
- },
12869
- size: {
12870
- control: 'select',
12871
- options: ['default', 'sm', 'lg', 'icon'],
12872
- },
12873
- },
12874
- };
12875
-
12876
- export default meta;
12877
- type Story = StoryObj<typeof Button>;
12878
-
12879
- export const Default: Story = {
12880
- args: {
12881
- children: 'Button',
12882
- variant: 'default',
12883
- size: 'default',
12884
- },
12885
- };
12886
-
12887
- export const Secondary: Story = {
12888
- args: {
12889
- children: 'Secondary',
12890
- variant: 'secondary',
12891
- },
12892
- };
12893
-
12894
- export const Destructive: Story = {
12895
- args: {
12896
- children: 'Destructive',
12897
- variant: 'destructive',
12898
- },
12899
- };
12900
-
12901
- export const Outline: Story = {
12902
- args: {
12903
- children: 'Outline',
12904
- variant: 'outline',
12905
- },
12906
- };
12907
-
12908
- export const Ghost: Story = {
12909
- args: {
12910
- children: 'Ghost',
12911
- variant: 'ghost',
12912
- },
12913
- };
12914
-
12915
- export const Link: Story = {
12916
- args: {
12917
- children: 'Link',
12918
- variant: 'link',
12919
- },
12920
- };
12921
- `;
12922
- const inputTsx = `import * as React from 'react';
12746
+ `,
12747
+ input: `import * as React from 'react';
12923
12748
 
12924
12749
  import { cn } from '~/lib/utils';
12925
12750
 
@@ -12941,8 +12766,8 @@ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(
12941
12766
  Input.displayName = 'Input';
12942
12767
 
12943
12768
  export { Input };
12944
- `;
12945
- const cardTsx = `import * as React from 'react';
12769
+ `,
12770
+ card: `import * as React from 'react';
12946
12771
 
12947
12772
  import { cn } from '~/lib/utils';
12948
12773
 
@@ -13018,124 +12843,10 @@ const CardFooter = React.forwardRef<
13018
12843
  CardFooter.displayName = 'CardFooter';
13019
12844
 
13020
12845
  export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
13021
- `;
13022
- const inputStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13023
- import { Input } from '~/components/ui/input';
13024
-
13025
- const meta: Meta<typeof Input> = {
13026
- title: 'Components/Input',
13027
- component: Input,
13028
- tags: ['autodocs'],
13029
- argTypes: {
13030
- type: {
13031
- control: 'select',
13032
- options: ['text', 'email', 'password', 'number', 'search', 'tel', 'url'],
13033
- },
13034
- disabled: {
13035
- control: 'boolean',
13036
- },
13037
- },
13038
- };
13039
-
13040
- export default meta;
13041
- type Story = StoryObj<typeof Input>;
13042
-
13043
- export const Default: Story = {
13044
- args: {
13045
- placeholder: 'Enter text...',
13046
- },
13047
- };
13048
-
13049
- export const Email: Story = {
13050
- args: {
13051
- type: 'email',
13052
- placeholder: 'Enter email...',
13053
- },
13054
- };
13055
-
13056
- export const Password: Story = {
13057
- args: {
13058
- type: 'password',
13059
- placeholder: 'Enter password...',
13060
- },
13061
- };
13062
-
13063
- export const Disabled: Story = {
13064
- args: {
13065
- placeholder: 'Disabled input',
13066
- disabled: true,
13067
- },
13068
- };
13069
-
13070
- export const WithValue: Story = {
13071
- args: {
13072
- defaultValue: 'Hello World',
13073
- },
13074
- };
13075
- `;
13076
- const cardStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13077
- import { Button } from '~/components/ui/button';
13078
- import {
13079
- Card,
13080
- CardContent,
13081
- CardDescription,
13082
- CardFooter,
13083
- CardHeader,
13084
- CardTitle,
13085
- } from '~/components/ui/card';
13086
- import { Input } from '~/components/ui/input';
13087
-
13088
- const meta: Meta<typeof Card> = {
13089
- title: 'Components/Card',
13090
- component: Card,
13091
- tags: ['autodocs'],
13092
- };
13093
-
13094
- export default meta;
13095
- type Story = StoryObj<typeof Card>;
13096
-
13097
- export const Default: Story = {
13098
- render: () => (
13099
- <Card className="w-[350px]">
13100
- <CardHeader>
13101
- <CardTitle>Card Title</CardTitle>
13102
- <CardDescription>Card description goes here.</CardDescription>
13103
- </CardHeader>
13104
- <CardContent>
13105
- <p>Card content goes here.</p>
13106
- </CardContent>
13107
- </Card>
13108
- ),
13109
- };
13110
-
13111
- export const WithFooter: Story = {
13112
- render: () => (
13113
- <Card className="w-[350px]">
13114
- <CardHeader>
13115
- <CardTitle>Create Account</CardTitle>
13116
- <CardDescription>Enter your details below.</CardDescription>
13117
- </CardHeader>
13118
- <CardContent className="space-y-4">
13119
- <Input placeholder="Email" type="email" />
13120
- <Input placeholder="Password" type="password" />
13121
- </CardContent>
13122
- <CardFooter className="flex justify-between">
13123
- <Button variant="outline">Cancel</Button>
13124
- <Button>Create</Button>
13125
- </CardFooter>
13126
- </Card>
13127
- ),
13128
- };
12846
+ `,
12847
+ label: `'use client';
13129
12848
 
13130
- export const Simple: Story = {
13131
- render: () => (
13132
- <Card className="w-[350px] p-6">
13133
- <p>Simple card with just content.</p>
13134
- </Card>
13135
- ),
13136
- };
13137
- `;
13138
- const labelTsx = `import * as LabelPrimitive from '@radix-ui/react-label';
12849
+ import * as LabelPrimitive from '@radix-ui/react-label';
13139
12850
  import { cva, type VariantProps } from 'class-variance-authority';
13140
12851
  import * as React from 'react';
13141
12852
 
@@ -13159,47 +12870,8 @@ const Label = React.forwardRef<
13159
12870
  Label.displayName = LabelPrimitive.Root.displayName;
13160
12871
 
13161
12872
  export { Label };
13162
- `;
13163
- const labelStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13164
- import { Input } from '~/components/ui/input';
13165
- import { Label } from '~/components/ui/label';
13166
-
13167
- const meta: Meta<typeof Label> = {
13168
- title: 'Components/Label',
13169
- component: Label,
13170
- tags: ['autodocs'],
13171
- };
13172
-
13173
- export default meta;
13174
- type Story = StoryObj<typeof Label>;
13175
-
13176
- export const Default: Story = {
13177
- args: {
13178
- children: 'Label',
13179
- },
13180
- };
13181
-
13182
- export const WithInput: Story = {
13183
- render: () => (
13184
- <div className="grid w-full max-w-sm items-center gap-1.5">
13185
- <Label htmlFor="email">Email</Label>
13186
- <Input type="email" id="email" placeholder="Email" />
13187
- </div>
13188
- ),
13189
- };
13190
-
13191
- export const Disabled: Story = {
13192
- render: () => (
13193
- <div className="grid w-full max-w-sm items-center gap-1.5">
13194
- <Label htmlFor="disabled" className="peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
13195
- Disabled
13196
- </Label>
13197
- <Input type="text" id="disabled" placeholder="Disabled" disabled className="peer" />
13198
- </div>
13199
- ),
13200
- };
13201
- `;
13202
- const badgeTsx = `import { cva, type VariantProps } from 'class-variance-authority';
12873
+ `,
12874
+ badge: `import { cva, type VariantProps } from 'class-variance-authority';
13203
12875
  import * as React from 'react';
13204
12876
 
13205
12877
  import { cn } from '~/lib/utils';
@@ -13235,54 +12907,10 @@ function Badge({ className, variant, ...props }: BadgeProps) {
13235
12907
  }
13236
12908
 
13237
12909
  export { Badge, badgeVariants };
13238
- `;
13239
- const badgeStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13240
- import { Badge } from '~/components/ui/badge';
13241
-
13242
- const meta: Meta<typeof Badge> = {
13243
- title: 'Components/Badge',
13244
- component: Badge,
13245
- tags: ['autodocs'],
13246
- argTypes: {
13247
- variant: {
13248
- control: 'select',
13249
- options: ['default', 'secondary', 'destructive', 'outline'],
13250
- },
13251
- },
13252
- };
13253
-
13254
- export default meta;
13255
- type Story = StoryObj<typeof Badge>;
13256
-
13257
- export const Default: Story = {
13258
- args: {
13259
- children: 'Badge',
13260
- variant: 'default',
13261
- },
13262
- };
13263
-
13264
- export const Secondary: Story = {
13265
- args: {
13266
- children: 'Secondary',
13267
- variant: 'secondary',
13268
- },
13269
- };
13270
-
13271
- export const Destructive: Story = {
13272
- args: {
13273
- children: 'Destructive',
13274
- variant: 'destructive',
13275
- },
13276
- };
12910
+ `,
12911
+ separator: `'use client';
13277
12912
 
13278
- export const Outline: Story = {
13279
- args: {
13280
- children: 'Outline',
13281
- variant: 'outline',
13282
- },
13283
- };
13284
- `;
13285
- const separatorTsx = `import * as SeparatorPrimitive from '@radix-ui/react-separator';
12913
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
13286
12914
  import * as React from 'react';
13287
12915
 
13288
12916
  import { cn } from '~/lib/utils';
@@ -13311,59 +12939,10 @@ const Separator = React.forwardRef<
13311
12939
  Separator.displayName = SeparatorPrimitive.Root.displayName;
13312
12940
 
13313
12941
  export { Separator };
13314
- `;
13315
- const separatorStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13316
- import { Separator } from '~/components/ui/separator';
13317
-
13318
- const meta: Meta<typeof Separator> = {
13319
- title: 'Components/Separator',
13320
- component: Separator,
13321
- tags: ['autodocs'],
13322
- argTypes: {
13323
- orientation: {
13324
- control: 'select',
13325
- options: ['horizontal', 'vertical'],
13326
- },
13327
- },
13328
- };
13329
-
13330
- export default meta;
13331
- type Story = StoryObj<typeof Separator>;
13332
-
13333
- export const Horizontal: Story = {
13334
- render: () => (
13335
- <div className="w-[300px]">
13336
- <div className="space-y-1">
13337
- <h4 className="text-sm font-medium leading-none">Radix Primitives</h4>
13338
- <p className="text-sm text-muted-foreground">
13339
- An open-source UI component library.
13340
- </p>
13341
- </div>
13342
- <Separator className="my-4" />
13343
- <div className="flex h-5 items-center space-x-4 text-sm">
13344
- <div>Blog</div>
13345
- <Separator orientation="vertical" />
13346
- <div>Docs</div>
13347
- <Separator orientation="vertical" />
13348
- <div>Source</div>
13349
- </div>
13350
- </div>
13351
- ),
13352
- };
12942
+ `,
12943
+ tabs: `'use client';
13353
12944
 
13354
- export const Vertical: Story = {
13355
- render: () => (
13356
- <div className="flex h-5 items-center space-x-4 text-sm">
13357
- <div>Blog</div>
13358
- <Separator orientation="vertical" />
13359
- <div>Docs</div>
13360
- <Separator orientation="vertical" />
13361
- <div>Source</div>
13362
- </div>
13363
- ),
13364
- };
13365
- `;
13366
- const tabsTsx = `import * as TabsPrimitive from '@radix-ui/react-tabs';
12945
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
13367
12946
  import * as React from 'react';
13368
12947
 
13369
12948
  import { cn } from '~/lib/utils';
@@ -13416,81 +12995,10 @@ const TabsContent = React.forwardRef<
13416
12995
  TabsContent.displayName = TabsPrimitive.Content.displayName;
13417
12996
 
13418
12997
  export { Tabs, TabsList, TabsTrigger, TabsContent };
13419
- `;
13420
- const tabsStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13421
- import { Tabs, TabsContent, TabsList, TabsTrigger } from '~/components/ui/tabs';
13422
- import { Button } from '~/components/ui/button';
13423
- import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '~/components/ui/card';
13424
- import { Input } from '~/components/ui/input';
13425
- import { Label } from '~/components/ui/label';
13426
-
13427
- const meta: Meta<typeof Tabs> = {
13428
- title: 'Components/Tabs',
13429
- component: Tabs,
13430
- tags: ['autodocs'],
13431
- };
12998
+ `,
12999
+ tooltip: `'use client';
13432
13000
 
13433
- export default meta;
13434
- type Story = StoryObj<typeof Tabs>;
13435
-
13436
- export const Default: Story = {
13437
- render: () => (
13438
- <Tabs defaultValue="account" className="w-[400px]">
13439
- <TabsList>
13440
- <TabsTrigger value="account">Account</TabsTrigger>
13441
- <TabsTrigger value="password">Password</TabsTrigger>
13442
- </TabsList>
13443
- <TabsContent value="account">
13444
- <Card>
13445
- <CardHeader>
13446
- <CardTitle>Account</CardTitle>
13447
- <CardDescription>
13448
- Make changes to your account here. Click save when you're done.
13449
- </CardDescription>
13450
- </CardHeader>
13451
- <CardContent className="space-y-2">
13452
- <div className="space-y-1">
13453
- <Label htmlFor="name">Name</Label>
13454
- <Input id="name" defaultValue="Pedro Duarte" />
13455
- </div>
13456
- <div className="space-y-1">
13457
- <Label htmlFor="username">Username</Label>
13458
- <Input id="username" defaultValue="@peduarte" />
13459
- </div>
13460
- </CardContent>
13461
- <CardFooter>
13462
- <Button>Save changes</Button>
13463
- </CardFooter>
13464
- </Card>
13465
- </TabsContent>
13466
- <TabsContent value="password">
13467
- <Card>
13468
- <CardHeader>
13469
- <CardTitle>Password</CardTitle>
13470
- <CardDescription>
13471
- Change your password here. After saving, you'll be logged out.
13472
- </CardDescription>
13473
- </CardHeader>
13474
- <CardContent className="space-y-2">
13475
- <div className="space-y-1">
13476
- <Label htmlFor="current">Current password</Label>
13477
- <Input id="current" type="password" />
13478
- </div>
13479
- <div className="space-y-1">
13480
- <Label htmlFor="new">New password</Label>
13481
- <Input id="new" type="password" />
13482
- </div>
13483
- </CardContent>
13484
- <CardFooter>
13485
- <Button>Save password</Button>
13486
- </CardFooter>
13487
- </Card>
13488
- </TabsContent>
13489
- </Tabs>
13490
- ),
13491
- };
13492
- `;
13493
- const tooltipTsx = `import * as TooltipPrimitive from '@radix-ui/react-tooltip';
13001
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
13494
13002
  import * as React from 'react';
13495
13003
 
13496
13004
  import { cn } from '~/lib/utils';
@@ -13520,80 +13028,10 @@ const TooltipContent = React.forwardRef<
13520
13028
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
13521
13029
 
13522
13030
  export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
13523
- `;
13524
- const tooltipStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13525
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '~/components/ui/tooltip';
13526
- import { Button } from '~/components/ui/button';
13527
-
13528
- const meta: Meta<typeof Tooltip> = {
13529
- title: 'Components/Tooltip',
13530
- component: Tooltip,
13531
- tags: ['autodocs'],
13532
- decorators: [
13533
- (Story) => (
13534
- <TooltipProvider>
13535
- <Story />
13536
- </TooltipProvider>
13537
- ),
13538
- ],
13539
- };
13540
-
13541
- export default meta;
13542
- type Story = StoryObj<typeof Tooltip>;
13543
-
13544
- export const Default: Story = {
13545
- render: () => (
13546
- <Tooltip>
13547
- <TooltipTrigger asChild>
13548
- <Button variant="outline">Hover me</Button>
13549
- </TooltipTrigger>
13550
- <TooltipContent>
13551
- <p>Add to library</p>
13552
- </TooltipContent>
13553
- </Tooltip>
13554
- ),
13555
- };
13031
+ `,
13032
+ dialog: `'use client';
13556
13033
 
13557
- export const Positions: Story = {
13558
- render: () => (
13559
- <div className="flex gap-4">
13560
- <Tooltip>
13561
- <TooltipTrigger asChild>
13562
- <Button variant="outline">Top</Button>
13563
- </TooltipTrigger>
13564
- <TooltipContent side="top">
13565
- <p>Top tooltip</p>
13566
- </TooltipContent>
13567
- </Tooltip>
13568
- <Tooltip>
13569
- <TooltipTrigger asChild>
13570
- <Button variant="outline">Bottom</Button>
13571
- </TooltipTrigger>
13572
- <TooltipContent side="bottom">
13573
- <p>Bottom tooltip</p>
13574
- </TooltipContent>
13575
- </Tooltip>
13576
- <Tooltip>
13577
- <TooltipTrigger asChild>
13578
- <Button variant="outline">Left</Button>
13579
- </TooltipTrigger>
13580
- <TooltipContent side="left">
13581
- <p>Left tooltip</p>
13582
- </TooltipContent>
13583
- </Tooltip>
13584
- <Tooltip>
13585
- <TooltipTrigger asChild>
13586
- <Button variant="outline">Right</Button>
13587
- </TooltipTrigger>
13588
- <TooltipContent side="right">
13589
- <p>Right tooltip</p>
13590
- </TooltipContent>
13591
- </Tooltip>
13592
- </div>
13593
- ),
13594
- };
13595
- `;
13596
- const dialogTsx = `import * as DialogPrimitive from '@radix-ui/react-dialog';
13034
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
13597
13035
  import { X } from 'lucide-react';
13598
13036
  import * as React from 'react';
13599
13037
 
@@ -13713,255 +13151,11 @@ export {
13713
13151
  DialogTitle,
13714
13152
  DialogDescription,
13715
13153
  };
13716
- `;
13717
- const dialogStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13718
- import {
13719
- Dialog,
13720
- DialogContent,
13721
- DialogDescription,
13722
- DialogFooter,
13723
- DialogHeader,
13724
- DialogTitle,
13725
- DialogTrigger,
13726
- } from '~/components/ui/dialog';
13727
- import { Button } from '~/components/ui/button';
13728
- import { Input } from '~/components/ui/input';
13729
- import { Label } from '~/components/ui/label';
13730
-
13731
- const meta: Meta<typeof Dialog> = {
13732
- title: 'Components/Dialog',
13733
- component: Dialog,
13734
- tags: ['autodocs'],
13735
- };
13736
-
13737
- export default meta;
13738
- type Story = StoryObj<typeof Dialog>;
13739
-
13740
- export const Default: Story = {
13741
- render: () => (
13742
- <Dialog>
13743
- <DialogTrigger asChild>
13744
- <Button variant="outline">Edit Profile</Button>
13745
- </DialogTrigger>
13746
- <DialogContent className="sm:max-w-[425px]">
13747
- <DialogHeader>
13748
- <DialogTitle>Edit profile</DialogTitle>
13749
- <DialogDescription>
13750
- Make changes to your profile here. Click save when you're done.
13751
- </DialogDescription>
13752
- </DialogHeader>
13753
- <div className="grid gap-4 py-4">
13754
- <div className="grid grid-cols-4 items-center gap-4">
13755
- <Label htmlFor="name" className="text-right">
13756
- Name
13757
- </Label>
13758
- <Input id="name" defaultValue="Pedro Duarte" className="col-span-3" />
13759
- </div>
13760
- <div className="grid grid-cols-4 items-center gap-4">
13761
- <Label htmlFor="username" className="text-right">
13762
- Username
13763
- </Label>
13764
- <Input id="username" defaultValue="@peduarte" className="col-span-3" />
13765
- </div>
13766
- </div>
13767
- <DialogFooter>
13768
- <Button type="submit">Save changes</Button>
13769
- </DialogFooter>
13770
- </DialogContent>
13771
- </Dialog>
13772
- ),
13773
- };
13774
-
13775
- export const Alert: Story = {
13776
- render: () => (
13777
- <Dialog>
13778
- <DialogTrigger asChild>
13779
- <Button variant="destructive">Delete Account</Button>
13780
- </DialogTrigger>
13781
- <DialogContent>
13782
- <DialogHeader>
13783
- <DialogTitle>Are you absolutely sure?</DialogTitle>
13784
- <DialogDescription>
13785
- This action cannot be undone. This will permanently delete your
13786
- account and remove your data from our servers.
13787
- </DialogDescription>
13788
- </DialogHeader>
13789
- <DialogFooter>
13790
- <Button variant="outline">Cancel</Button>
13791
- <Button variant="destructive">Delete</Button>
13792
- </DialogFooter>
13793
- </DialogContent>
13794
- </Dialog>
13795
- ),
13796
- };
13797
- `;
13798
- const componentsUiIndex = `export { Button, type ButtonProps, buttonVariants } from './button/index.tsx';
13799
- export { Input } from './input/index.tsx';
13800
- export {
13801
- Card,
13802
- CardHeader,
13803
- CardFooter,
13804
- CardTitle,
13805
- CardDescription,
13806
- CardContent,
13807
- } from './card/index.tsx';
13808
- export { Label } from './label/index.tsx';
13809
- export { Badge, type BadgeProps, badgeVariants } from './badge/index.tsx';
13810
- export { Separator } from './separator/index.tsx';
13811
- export { Tabs, TabsList, TabsTrigger, TabsContent } from './tabs/index.tsx';
13812
- export {
13813
- Tooltip,
13814
- TooltipTrigger,
13815
- TooltipContent,
13816
- TooltipProvider,
13817
- } from './tooltip/index.tsx';
13818
- export {
13819
- Dialog,
13820
- DialogPortal,
13821
- DialogOverlay,
13822
- DialogTrigger,
13823
- DialogClose,
13824
- DialogContent,
13825
- DialogHeader,
13826
- DialogFooter,
13827
- DialogTitle,
13828
- DialogDescription,
13829
- } from './dialog/index.tsx';
13830
- `;
13831
- const buttonIndexTsx = buttonTsx;
13832
- const inputIndexTsx = inputTsx;
13833
- const cardIndexTsx = cardTsx;
13834
- const componentsIndex = `export * from './ui/index.ts';
13835
- `;
13836
- const indexTs = `// @${options.name}/ui - Shared UI component library
13837
-
13838
- // shadcn/ui components
13839
- export * from './components/index.ts';
13840
-
13841
- // Utilities
13842
- export { cn } from './lib/utils.ts';
13843
- `;
13844
- return [
13845
- {
13846
- path: "packages/ui/package.json",
13847
- content: `${JSON.stringify(packageJson, null, 2)}\n`
13848
- },
13849
- {
13850
- path: "packages/ui/tsconfig.json",
13851
- content: `${JSON.stringify(tsConfig, null, 2)}\n`
13852
- },
13853
- {
13854
- path: "packages/ui/components.json",
13855
- content: `${JSON.stringify(componentsJson, null, 2)}\n`
13856
- },
13857
- {
13858
- path: "packages/ui/.storybook/main.ts",
13859
- content: storybookMain
13860
- },
13861
- {
13862
- path: "packages/ui/.storybook/preview.ts",
13863
- content: storybookPreview
13864
- },
13865
- {
13866
- path: "packages/ui/src/styles/globals.css",
13867
- content: globalsCss
13868
- },
13869
- {
13870
- path: "packages/ui/src/lib/utils.ts",
13871
- content: utilsTs
13872
- },
13873
- {
13874
- path: "packages/ui/src/components/ui/button/index.tsx",
13875
- content: buttonIndexTsx
13876
- },
13877
- {
13878
- path: "packages/ui/src/components/ui/button/button.stories.tsx",
13879
- content: buttonStories
13880
- },
13881
- {
13882
- path: "packages/ui/src/components/ui/input/index.tsx",
13883
- content: inputIndexTsx
13884
- },
13885
- {
13886
- path: "packages/ui/src/components/ui/input/input.stories.tsx",
13887
- content: inputStories
13888
- },
13889
- {
13890
- path: "packages/ui/src/components/ui/card/index.tsx",
13891
- content: cardIndexTsx
13892
- },
13893
- {
13894
- path: "packages/ui/src/components/ui/card/card.stories.tsx",
13895
- content: cardStories
13896
- },
13897
- {
13898
- path: "packages/ui/src/components/ui/label/index.tsx",
13899
- content: labelTsx
13900
- },
13901
- {
13902
- path: "packages/ui/src/components/ui/label/label.stories.tsx",
13903
- content: labelStories
13904
- },
13905
- {
13906
- path: "packages/ui/src/components/ui/badge/index.tsx",
13907
- content: badgeTsx
13908
- },
13909
- {
13910
- path: "packages/ui/src/components/ui/badge/badge.stories.tsx",
13911
- content: badgeStories
13912
- },
13913
- {
13914
- path: "packages/ui/src/components/ui/separator/index.tsx",
13915
- content: separatorTsx
13916
- },
13917
- {
13918
- path: "packages/ui/src/components/ui/separator/separator.stories.tsx",
13919
- content: separatorStories
13920
- },
13921
- {
13922
- path: "packages/ui/src/components/ui/tabs/index.tsx",
13923
- content: tabsTsx
13924
- },
13925
- {
13926
- path: "packages/ui/src/components/ui/tabs/tabs.stories.tsx",
13927
- content: tabsStories
13928
- },
13929
- {
13930
- path: "packages/ui/src/components/ui/tooltip/index.tsx",
13931
- content: tooltipTsx
13932
- },
13933
- {
13934
- path: "packages/ui/src/components/ui/tooltip/tooltip.stories.tsx",
13935
- content: tooltipStories
13936
- },
13937
- {
13938
- path: "packages/ui/src/components/ui/dialog/index.tsx",
13939
- content: dialogTsx
13940
- },
13941
- {
13942
- path: "packages/ui/src/components/ui/dialog/dialog.stories.tsx",
13943
- content: dialogStories
13944
- },
13945
- {
13946
- path: "packages/ui/src/components/ui/index.ts",
13947
- content: componentsUiIndex
13948
- },
13949
- {
13950
- path: "packages/ui/src/components/index.ts",
13951
- content: componentsIndex
13952
- },
13953
- {
13954
- path: "packages/ui/src/index.ts",
13955
- content: indexTs
13956
- },
13957
- {
13958
- path: "packages/ui/.gitignore",
13959
- content: `node_modules/
13960
- dist/
13961
- storybook-static/
13962
- *.log
13963
13154
  `
13964
- }
13155
+ }).map(([name, content]) => ({
13156
+ path: `${appDir}/src/components/ui/${name}.tsx`,
13157
+ content
13158
+ }))
13965
13159
  ];
13966
13160
  }
13967
13161
  //#endregion
@@ -13973,7 +13167,6 @@ function generateWebAppFiles(options) {
13973
13167
  if (!options.monorepo || options.template !== "fullstack") return [];
13974
13168
  const packageName = `@${options.name}/web`;
13975
13169
  const modelsPackage = `@${options.name}/models`;
13976
- const uiPackage = `@${options.name}/ui`;
13977
13170
  const packageJson = {
13978
13171
  name: packageName,
13979
13172
  version: "0.0.1",
@@ -13987,7 +13180,7 @@ function generateWebAppFiles(options) {
13987
13180
  },
13988
13181
  dependencies: {
13989
13182
  [modelsPackage]: "workspace:*",
13990
- [uiPackage]: "workspace:*",
13183
+ ...SHADCN_DEPENDENCIES,
13991
13184
  "@geekmidas/client": GEEKMIDAS_VERSIONS["@geekmidas/client"],
13992
13185
  "@geekmidas/envkit": GEEKMIDAS_VERSIONS["@geekmidas/envkit"],
13993
13186
  "@tanstack/react-query": DEPENDENCY_VERSIONS["@tanstack/react-query"],
@@ -14012,7 +13205,7 @@ function generateWebAppFiles(options) {
14012
13205
  const nextConfig: NextConfig = {
14013
13206
  output: 'standalone',
14014
13207
  reactStrictMode: true,
14015
- transpilePackages: ['${modelsPackage}', '${uiPackage}'],
13208
+ transpilePackages: ['${modelsPackage}'],
14016
13209
  };
14017
13210
 
14018
13211
  export default nextConfig;
@@ -14045,12 +13238,10 @@ export default nextConfig;
14045
13238
  incremental: true,
14046
13239
  plugins: [{ name: "next" }],
14047
13240
  paths: {
14048
- "~/*": ["./src/*", "../../packages/ui/src/*"],
13241
+ "~/*": ["./src/*"],
14049
13242
  [`@${options.name}/client/*`]: ["../../.gkm/client/*"],
14050
13243
  [`${modelsPackage}`]: ["../../packages/models/src"],
14051
- [`${modelsPackage}/*`]: ["../../packages/models/src/*"],
14052
- [`${uiPackage}`]: ["../../packages/ui/src"],
14053
- [`${uiPackage}/*`]: ["../../packages/ui/src/*"]
13244
+ [`${modelsPackage}/*`]: ["../../packages/models/src/*"]
14054
13245
  }
14055
13246
  },
14056
13247
  include: [
@@ -14146,8 +13337,6 @@ export const api = createApi({
14146
13337
  baseURL: clientConfig.apiUrl,
14147
13338
  queryClient: getQueryClient(),
14148
13339
  });
14149
- `;
14150
- const globalsCss = `@import '${uiPackage}/styles';
14151
13340
  `;
14152
13341
  const layoutTsx = `import type { Metadata } from 'next';
14153
13342
  import { Providers } from './providers.tsx';
@@ -14173,7 +13362,14 @@ export default function RootLayout({
14173
13362
  }
14174
13363
  `;
14175
13364
  const pageTsx = `import { api } from '~/api/index.ts';
14176
- import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle } from '${uiPackage}/components';
13365
+ import { Button } from '~/components/ui/button.tsx';
13366
+ import {
13367
+ Card,
13368
+ CardContent,
13369
+ CardDescription,
13370
+ CardHeader,
13371
+ CardTitle,
13372
+ } from '~/components/ui/card.tsx';
14177
13373
 
14178
13374
  export default async function Home() {
14179
13375
  // Type-safe API call using the generated client
@@ -14213,7 +13409,7 @@ export default async function Home() {
14213
13409
  <li>Run <code className="rounded bg-muted px-1">gkm openapi</code> to generate typed API client</li>
14214
13410
  <li>Edit <code className="rounded bg-muted px-1">apps/web/src/app/page.tsx</code> to customize this page</li>
14215
13411
  <li>Add API routes in <code className="rounded bg-muted px-1">apps/api/src/endpoints/</code></li>
14216
- <li>Add UI components with <code className="rounded bg-muted px-1">npx shadcn@latest add</code> in packages/ui</li>
13412
+ <li>Add UI components with <code className="rounded bg-muted px-1">npx shadcn@latest add</code> in apps/web</li>
14217
13413
  </ul>
14218
13414
  <div className="flex gap-4">
14219
13415
  <Button>Get Started</Button>
@@ -14225,6 +13421,11 @@ export default async function Home() {
14225
13421
  </main>
14226
13422
  );
14227
13423
  }
13424
+ `;
13425
+ const gitignore = `.next/
13426
+ node_modules/
13427
+ .env.local
13428
+ *.log
14228
13429
  `;
14229
13430
  return [
14230
13431
  {
@@ -14245,8 +13446,9 @@ export default async function Home() {
14245
13446
  },
14246
13447
  {
14247
13448
  path: "apps/web/src/app/globals.css",
14248
- content: globalsCss
13449
+ content: SHADCN_GLOBALS_CSS
14249
13450
  },
13451
+ ...shadcnFiles("apps/web", "src/app/globals.css", { rsc: true }),
14250
13452
  {
14251
13453
  path: "apps/web/src/app/layout.tsx",
14252
13454
  content: layoutTsx
@@ -14281,11 +13483,7 @@ export default async function Home() {
14281
13483
  },
14282
13484
  {
14283
13485
  path: "apps/web/.gitignore",
14284
- content: `.next/
14285
- node_modules/
14286
- .env.local
14287
- *.log
14288
- `
13486
+ content: gitignore
14289
13487
  }
14290
13488
  ];
14291
13489
  }
@@ -14301,7 +13499,6 @@ function generateTanStackWebFiles(options) {
14301
13499
  if (!options.monorepo || options.template !== "fullstack") return [];
14302
13500
  const packageName = `@${options.name}/web`;
14303
13501
  const modelsPackage = `@${options.name}/models`;
14304
- const uiPackage = `@${options.name}/ui`;
14305
13502
  const packageJson = {
14306
13503
  name: packageName,
14307
13504
  version: "0.0.1",
@@ -14315,7 +13512,7 @@ function generateTanStackWebFiles(options) {
14315
13512
  },
14316
13513
  dependencies: {
14317
13514
  [modelsPackage]: "workspace:*",
14318
- [uiPackage]: "workspace:*",
13515
+ ...SHADCN_DEPENDENCIES,
14319
13516
  "@geekmidas/client": GEEKMIDAS_VERSIONS["@geekmidas/client"],
14320
13517
  "@geekmidas/envkit": GEEKMIDAS_VERSIONS["@geekmidas/envkit"],
14321
13518
  "@tanstack/react-query": DEPENDENCY_VERSIONS["@tanstack/react-query"],
@@ -14382,11 +13579,9 @@ export default defineConfig({
14382
13579
  incremental: true,
14383
13580
  types: ["vite/client"],
14384
13581
  paths: {
14385
- "~/*": ["./src/*", "../../packages/ui/src/*"],
13582
+ "~/*": ["./src/*"],
14386
13583
  [modelsPackage]: ["../../packages/models/src"],
14387
13584
  [`${modelsPackage}/*`]: ["../../packages/models/src/*"],
14388
- [uiPackage]: ["../../packages/ui/src"],
14389
- [`${uiPackage}/*`]: ["../../packages/ui/src/*"],
14390
13585
  [`@${options.name}/client/*`]: ["../../.gkm/client/*"]
14391
13586
  }
14392
13587
  },
@@ -14589,10 +13784,15 @@ function HomeComponent() {
14589
13784
  );
14590
13785
  }
14591
13786
  `;
14592
- const globalsCss = `@import '${uiPackage}/styles';
14593
-
13787
+ const globalsCss = `${SHADCN_GLOBALS_CSS}
14594
13788
  @source "../..";
14595
- @source "../../../../packages/ui/src";
13789
+ `;
13790
+ const gitignore = `.output/
13791
+ .vinxi/
13792
+ node_modules/
13793
+ .env.local
13794
+ *.log
13795
+ src/routeTree.gen.ts
14596
13796
  `;
14597
13797
  return [
14598
13798
  {
@@ -14647,15 +13847,10 @@ function HomeComponent() {
14647
13847
  path: "apps/web/src/styles/globals.css",
14648
13848
  content: globalsCss
14649
13849
  },
13850
+ ...shadcnFiles("apps/web", "src/styles/globals.css", { rsc: false }),
14650
13851
  {
14651
13852
  path: "apps/web/.gitignore",
14652
- content: `.output/
14653
- .vinxi/
14654
- node_modules/
14655
- .env.local
14656
- *.log
14657
- src/routeTree.gen.ts
14658
- `
13853
+ content: gitignore
14659
13854
  }
14660
13855
  ];
14661
13856
  }
@@ -14704,7 +13899,7 @@ const apiTemplate = {
14704
13899
  const { cache, uploads, mail: sendsMail } = options.constructs;
14705
13900
  const bucket = storageFor();
14706
13901
  const kv = cacheFor();
14707
- const db = databaseFor();
13902
+ databaseFor();
14708
13903
  const mail = emailFor();
14709
13904
  const src = (path) => `~/${path}`;
14710
13905
  const declares = !monorepo;
@@ -15003,41 +14198,6 @@ export const telescope = new Telescope({
15003
14198
  storage: new InMemoryStorage({ maxEntries: 100 }),
15004
14199
  enabled: process.env.NODE_ENV === 'development',
15005
14200
  });
15006
- `
15007
- });
15008
- if (options.studio && options.constructs.database) files.push({
15009
- path: "src/config/studio.ts",
15010
- content: `import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
15011
- import { Kysely, PostgresDialect } from 'kysely';
15012
- import pg from 'pg';
15013
- import { type Database, database } from '${declares ? src("constructs/database.ts") : constructsImport("database")}';
15014
- import { envParser } from '${src("config/env.ts")}';
15015
-
15016
- const studioConfig = envParser
15017
- .create((get) => ({
15018
- databaseUrl: get('${db.urlKey}').string(),
15019
- }))
15020
- .parse();
15021
-
15022
- // Studio's own client, built the way the construct builds its own — the same
15023
- // plugins — so the browser shows what the app's queries see.
15024
- const db = new Kysely<Database>({
15025
- ...database.clientConfig,
15026
- dialect: new PostgresDialect({
15027
- pool: new pg.Pool({ connectionString: studioConfig.databaseUrl }),
15028
- }),
15029
- });
15030
-
15031
- export const studio = new Studio<Database>({
15032
- monitoring: {
15033
- storage: new InMemoryMonitoringStorage({ maxEntries: 100 }),
15034
- },
15035
- data: {
15036
- db,
15037
- cursor: { field: 'id', direction: Direction.Desc },
15038
- },
15039
- enabled: process.env.NODE_ENV === 'development',
15040
- });
15041
14201
  `
15042
14202
  });
15043
14203
  return files;
@@ -15085,7 +14245,7 @@ const templates = {
15085
14245
  },
15086
14246
  files: (options) => {
15087
14247
  const { loggerType, routesStructure, name } = options;
15088
- const db = databaseFor();
14248
+ databaseFor();
15089
14249
  const loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';
15090
14250
 
15091
14251
  export const logger = createLogger();
@@ -15167,40 +14327,6 @@ export const telescope = new Telescope({
15167
14327
  storage: new InMemoryStorage({ maxEntries: 100 }),
15168
14328
  enabled: process.env.NODE_ENV === 'development',
15169
14329
  });
15170
- `
15171
- });
15172
- if (options.studio && options.constructs.database) files.push({
15173
- path: "src/config/studio.ts",
15174
- content: `import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
15175
- import { Kysely, PostgresDialect } from 'kysely';
15176
- import pg from 'pg';
15177
- import type { Database } from '~/constructs/database.ts';
15178
- import { envParser } from '~/config/env.ts';
15179
-
15180
- // The key the database construct publishes — not a hand-written DATABASE_URL.
15181
- const studioConfig = envParser
15182
- .create((get) => ({
15183
- databaseUrl: get('${db.urlKey}').string(),
15184
- }))
15185
- .parse();
15186
-
15187
- // Create a Kysely instance for Studio
15188
- const db = new Kysely<Database>({
15189
- dialect: new PostgresDialect({
15190
- pool: new pg.Pool({ connectionString: studioConfig.databaseUrl }),
15191
- }),
15192
- });
15193
-
15194
- export const studio = new Studio<Database>({
15195
- monitoring: {
15196
- storage: new InMemoryMonitoringStorage({ maxEntries: 100 }),
15197
- },
15198
- data: {
15199
- db,
15200
- cursor: { field: 'id', direction: Direction.Desc },
15201
- },
15202
- enabled: process.env.NODE_ENV === 'development',
15203
- });
15204
14330
  `
15205
14331
  });
15206
14332
  return files;
@@ -15921,7 +15047,7 @@ async function initCommand(projectName, options = {}) {
15921
15047
  {
15922
15048
  type: options.yes ? null : "confirm",
15923
15049
  name: "telescope",
15924
- message: "Include Telescope (debugging dashboard)?",
15050
+ message: "Include Telescope (request, exception and log recording)?",
15925
15051
  initial: true
15926
15052
  },
15927
15053
  {
@@ -15976,13 +15102,11 @@ async function initCommand(projectName, options = {}) {
15976
15102
  };
15977
15103
  const pkgManager = options.pm ? options.pm : options.yes ? "pnpm" : answers.packageManager ?? detectedPkgManager;
15978
15104
  const deployTarget = options.deploy ?? (options.yes ? "none" : answers.deployTarget ?? "none");
15979
- const database = constructs.database;
15980
15105
  const frontendFramework = isFullstack ? options.yes ? "nextjs" : answers.frontendFramework ?? "nextjs" : void 0;
15981
15106
  const templateOptions = {
15982
15107
  name,
15983
15108
  template,
15984
15109
  telescope: options.yes ? true : answers.telescope ?? true,
15985
- studio: database,
15986
15110
  loggerType: options.yes ? "pino" : answers.loggerType ?? "pino",
15987
15111
  routesStructure: options.yes ? "centralized-endpoints" : answers.routesStructure ?? "centralized-endpoints",
15988
15112
  monorepo,
@@ -16019,7 +15143,6 @@ async function initCommand(projectName, options = {}) {
16019
15143
  ] : [];
16020
15144
  const webAppFiles = isFullstack ? frontendFramework === "tanstack-start" ? generateTanStackWebFiles(templateOptions) : frontendFramework === "expo" ? generateExpoAppFiles(templateOptions) : generateWebAppFiles(templateOptions) : [];
16021
15145
  const authAppFiles = isFullstack ? generateAuthAppFiles(templateOptions) : [];
16022
- const uiPackageFiles = isFullstack ? generateUiPackageFiles(templateOptions) : [];
16023
15146
  for (const { path, content } of rootFiles) {
16024
15147
  const fullPath = (0, node_path.join)(targetDir, path);
16025
15148
  await (0, node_fs_promises.mkdir)((0, node_path.dirname)(fullPath), { recursive: true });
@@ -16040,11 +15163,6 @@ async function initCommand(projectName, options = {}) {
16040
15163
  await (0, node_fs_promises.mkdir)((0, node_path.dirname)(fullPath), { recursive: true });
16041
15164
  await (0, node_fs_promises.writeFile)(fullPath, content);
16042
15165
  }
16043
- for (const { path, content } of uiPackageFiles) {
16044
- const fullPath = (0, node_path.join)(targetDir, path);
16045
- await (0, node_fs_promises.mkdir)((0, node_path.dirname)(fullPath), { recursive: true });
16046
- await (0, node_fs_promises.writeFile)(fullPath, content);
16047
- }
16048
15166
  console.log("🔐 Initializing encrypted secrets...\n");
16049
15167
  const local = templateOptions.stages.local;
16050
15168
  const devSecrets = createStageSecrets(local, [], { projectName: name });
@@ -16147,8 +15265,7 @@ function printNextSteps(projectName, options, pkgManager) {
16147
15265
  }
16148
15266
  }
16149
15267
  console.log(` ├── packages/`);
16150
- console.log(` │ ├── models/ # Shared Zod schemas`);
16151
- if (isFullstackTemplate(options.template)) console.log(` │ └── ui/ # Shared UI components`);
15268
+ console.log(` │ └── models/ # Shared Zod schemas`);
16152
15269
  console.log(` ├── .gkm/secrets/ # Encrypted secrets`);
16153
15270
  console.log(` ├── gkm.config.ts # Workspace config`);
16154
15271
  console.log(` └── turbo.json # Turbo config`);
@@ -16902,7 +16019,7 @@ function testDatabases(reconciled) {
16902
16019
  * starts without the reference data the app needs.
16903
16020
  */
16904
16021
  async function migrateTestStage(workspace, env) {
16905
- const { migrateAndSeed } = await Promise.resolve().then(() => require("./migrate-DHMRgnP6.cjs"));
16022
+ const { migrateAndSeed } = await Promise.resolve().then(() => require("./migrate-DQ54y2WD.cjs"));
16906
16023
  const { discover } = await Promise.resolve().then(() => require("./discover-DXNviAh-.cjs")).then((n) => n.discover_exports);
16907
16024
  const sources = {};
16908
16025
  const manifest = await discover({
@@ -17333,7 +16450,7 @@ program.command("migrate").description("Apply each database construct's migratio
17333
16450
  try {
17334
16451
  const globalOptions = program.opts();
17335
16452
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17336
- const { migrateCommand } = await Promise.resolve().then(() => require("./migrate-DHMRgnP6.cjs"));
16453
+ const { migrateCommand } = await Promise.resolve().then(() => require("./migrate-DQ54y2WD.cjs"));
17337
16454
  await migrateCommand({
17338
16455
  ...options,
17339
16456
  ...construct ? { construct } : {}
@@ -17347,7 +16464,7 @@ program.command("seed").description("Migrate, then run each database construct's
17347
16464
  try {
17348
16465
  const globalOptions = program.opts();
17349
16466
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17350
- const { seedCommand } = await Promise.resolve().then(() => require("./migrate-DHMRgnP6.cjs"));
16467
+ const { seedCommand } = await Promise.resolve().then(() => require("./migrate-DQ54y2WD.cjs"));
17351
16468
  await seedCommand({
17352
16469
  ...options,
17353
16470
  ...construct ? { construct } : {}
@@ -17361,7 +16478,7 @@ program.command("migration").description("Write a construct's next migration: an
17361
16478
  try {
17362
16479
  const globalOptions = program.opts();
17363
16480
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17364
- const { migrationCommand } = await Promise.resolve().then(() => require("./migrate-DHMRgnP6.cjs"));
16481
+ const { migrationCommand } = await Promise.resolve().then(() => require("./migrate-DQ54y2WD.cjs"));
17365
16482
  await migrationCommand({
17366
16483
  construct,
17367
16484
  ...name ? { name } : {}
@@ -17459,7 +16576,7 @@ program.command("encryption:rotate").description("Add a new current key to an En
17459
16576
  try {
17460
16577
  const globalOptions = program.opts();
17461
16578
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17462
- const { encryptionRotateCommand } = await Promise.resolve().then(() => require("./encryption-DSHYN5ap.cjs"));
16579
+ const { encryptionRotateCommand } = await Promise.resolve().then(() => require("./encryption-10Srqiix.cjs"));
17463
16580
  await encryptionRotateCommand(construct, options);
17464
16581
  } catch (error) {
17465
16582
  console.error(formatError(error));
@@ -17470,7 +16587,7 @@ program.command("encryption:retire").description("Remove an old key from an Encr
17470
16587
  try {
17471
16588
  const globalOptions = program.opts();
17472
16589
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17473
- const { encryptionRetireCommand } = await Promise.resolve().then(() => require("./encryption-DSHYN5ap.cjs"));
16590
+ const { encryptionRetireCommand } = await Promise.resolve().then(() => require("./encryption-10Srqiix.cjs"));
17474
16591
  await encryptionRetireCommand(construct, key, options);
17475
16592
  } catch (error) {
17476
16593
  console.error(formatError(error));
@@ -17522,7 +16639,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
17522
16639
  console.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
17523
16640
  process.exit(1);
17524
16641
  }
17525
- const { derivedContainers } = await Promise.resolve().then(() => require("./workspace-CXvYabDJ.cjs")).then((n) => n.workspace_exports);
16642
+ const { derivedContainers } = await Promise.resolve().then(() => require("./workspace-BbPJVCto.cjs")).then((n) => n.workspace_exports);
17526
16643
  const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers(workspace, stage));
17527
16644
  if (!result) {
17528
16645
  console.log(`\n✓ Secrets for stage "${stage}" are up-to-date`);
@@ -17581,7 +16698,7 @@ program.command("deploy:github").description("Let GitHub Actions deploy a stage:
17581
16698
  try {
17582
16699
  const globalOptions = program.opts();
17583
16700
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17584
- const { deployGithubCommand } = await Promise.resolve().then(() => require("./github-CWflxaV4.cjs"));
16701
+ const { deployGithubCommand } = await Promise.resolve().then(() => require("./github-DtRUkHN8.cjs"));
17585
16702
  await deployGithubCommand(options);
17586
16703
  } catch (error) {
17587
16704
  console.error(formatError(error));