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

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 (76) 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/{SSMStateStore-oda9xOGc.mjs → SSMStateStore-7hPWW7v7.mjs} +12 -7
  7. package/dist/{SSMStateStore-oda9xOGc.mjs.map → SSMStateStore-7hPWW7v7.mjs.map} +1 -1
  8. package/dist/{SSMStateStore-DD7jKrCO.cjs → SSMStateStore-C7KcDSTb.cjs} +12 -7
  9. package/dist/{SSMStateStore-DD7jKrCO.cjs.map → SSMStateStore-C7KcDSTb.cjs.map} +1 -1
  10. package/dist/{backends-BNrMPlJb.mjs → backends-BcHL7Gy_.mjs} +2 -2
  11. package/dist/{backends-BNrMPlJb.mjs.map → backends-BcHL7Gy_.mjs.map} +1 -1
  12. package/dist/{backends-nBauiBkt.cjs → backends-_gQdAzBK.cjs} +2 -2
  13. package/dist/{backends-nBauiBkt.cjs.map → backends-_gQdAzBK.cjs.map} +1 -1
  14. package/dist/{config-XEd-dKVX.mjs → config-20V08LZp.mjs} +2 -3
  15. package/dist/config-20V08LZp.mjs.map +1 -0
  16. package/dist/{config-C7NZG2tr.cjs → config-CP6wsLHA.cjs} +2 -3
  17. package/dist/config-CP6wsLHA.cjs.map +1 -0
  18. package/dist/config.cjs +2 -2
  19. package/dist/config.d.cts +2 -2
  20. package/dist/config.d.mts +2 -2
  21. package/dist/config.mjs +2 -2
  22. package/dist/{encryption-DSHYN5ap.cjs → encryption-10Srqiix.cjs} +4 -4
  23. package/dist/{encryption-DSHYN5ap.cjs.map → encryption-10Srqiix.cjs.map} +1 -1
  24. package/dist/{encryption-Bc1cMdeY.mjs → encryption-KQTYFEzU.mjs} +4 -4
  25. package/dist/{encryption-Bc1cMdeY.mjs.map → encryption-KQTYFEzU.mjs.map} +1 -1
  26. package/dist/{github-CWflxaV4.cjs → github-DtRUkHN8.cjs} +3 -3
  27. package/dist/{github-CWflxaV4.cjs.map → github-DtRUkHN8.cjs.map} +1 -1
  28. package/dist/{github-DWHXTcwL.mjs → github-y7OEj59M.mjs} +3 -3
  29. package/dist/{github-DWHXTcwL.mjs.map → github-y7OEj59M.mjs.map} +1 -1
  30. package/dist/{index-B8nraKvg.d.mts → index-DMcjpvd-.d.cts} +2 -2
  31. package/dist/{index-B8nraKvg.d.mts.map → index-DMcjpvd-.d.cts.map} +1 -1
  32. package/dist/{index-BvBQS89a.d.cts → index-RM92lx8A.d.mts} +2 -2
  33. package/dist/{index-BvBQS89a.d.cts.map → index-RM92lx8A.d.mts.map} +1 -1
  34. package/dist/index.cjs +201 -1084
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.mjs +201 -1084
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/{migrate-PcQg692O.mjs → migrate-CS3DkO6y.mjs} +4 -4
  39. package/dist/{migrate-PcQg692O.mjs.map → migrate-CS3DkO6y.mjs.map} +1 -1
  40. package/dist/{migrate-DHMRgnP6.cjs → migrate-DQ54y2WD.cjs} +4 -4
  41. package/dist/{migrate-DHMRgnP6.cjs.map → migrate-DQ54y2WD.cjs.map} +1 -1
  42. package/dist/openapi.cjs +2 -2
  43. package/dist/openapi.d.cts +1 -1
  44. package/dist/openapi.d.mts +1 -1
  45. package/dist/openapi.mjs +2 -2
  46. package/dist/{ready-bES_Jk5v.mjs → ready-BSpUZnNo.mjs} +2 -2
  47. package/dist/ready-BSpUZnNo.mjs.map +1 -0
  48. package/dist/{ready-BefA4mM0.cjs → ready-MUhVJDHe.cjs} +2 -2
  49. package/dist/ready-MUhVJDHe.cjs.map +1 -0
  50. package/dist/reconcile/public.d.cts +1 -1
  51. package/dist/reconcile/public.d.mts +1 -1
  52. package/dist/{types-Cgj-cq2m.d.mts → types-BIyIQUR-.d.cts} +3 -30
  53. package/dist/{types-CmxMhLGp.d.cts.map → types-BIyIQUR-.d.cts.map} +1 -1
  54. package/dist/{types-CmxMhLGp.d.cts → types-CmQl6zaP.d.mts} +2 -31
  55. package/dist/{types-Cgj-cq2m.d.mts.map → types-CmQl6zaP.d.mts.map} +1 -1
  56. package/dist/vitest.cjs +1 -1
  57. package/dist/vitest.mjs +1 -1
  58. package/dist/workspace/index.cjs +1 -1
  59. package/dist/workspace/index.d.cts +2 -2
  60. package/dist/workspace/index.d.mts +2 -2
  61. package/dist/workspace/index.mjs +1 -1
  62. package/dist/{workspace-CXvYabDJ.cjs → workspace-BbPJVCto.cjs} +5 -5
  63. package/dist/{workspace-CXvYabDJ.cjs.map → workspace-BbPJVCto.cjs.map} +1 -1
  64. package/dist/{workspace-DL_99LJC.cjs → workspace-BpdXIeWV.cjs} +1 -16
  65. package/dist/{workspace-DL_99LJC.cjs.map → workspace-BpdXIeWV.cjs.map} +1 -1
  66. package/dist/{workspace-DHK2N1mq.mjs → workspace-C2mFV53i.mjs} +1 -16
  67. package/dist/{workspace-DHK2N1mq.mjs.map → workspace-C2mFV53i.mjs.map} +1 -1
  68. package/dist/{workspace-BE0WHPw9.mjs → workspace-CgWcE_Yr.mjs} +5 -5
  69. package/dist/{workspace-BE0WHPw9.mjs.map → workspace-CgWcE_Yr.mjs.map} +1 -1
  70. package/package.json +13 -14
  71. package/dist/OpenApiTsGenerator-DKmAorGX.mjs.map +0 -1
  72. package/dist/OpenApiTsGenerator-WlUHjimW.cjs.map +0 -1
  73. package/dist/config-C7NZG2tr.cjs.map +0 -1
  74. package/dist/config-XEd-dKVX.mjs.map +0 -1
  75. package/dist/ready-BefA4mM0.cjs.map +0 -1
  76. package/dist/ready-bES_Jk5v.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env -S npx tsx
2
2
  import { n as __require, t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mjs";
3
3
  import { i as ConstructGenerator, t as discover } from "./discover-Cf2jAcgF.mjs";
4
- import { d as parseModuleConfig, f as appKey, l as loadWorkspaceConfig, n as NotABackendApp, o as loadAppConfig, p as derivedApps, r as NotInAnApp, s as loadConfig, t as ConfigNotFound, u as loadWorkspaceSettings } from "./config-XEd-dKVX.mjs";
5
- import { D as assertDeployedStage, E as TEST_STAGE, O as deployedProblems, T as InvalidStages, a as getAppBuildOrder, b as getDeployTargetError, k as stageProblems, m as stripPublicPrefix, o as getAppGkmConfig, p as getPublicEnvPrefix, t as allConstructGlobs, x as isDeployTargetSupported } from "./workspace-DHK2N1mq.mjs";
4
+ import { d as parseModuleConfig, f as appKey, l as loadWorkspaceConfig, n as NotABackendApp, o as loadAppConfig, p as derivedApps, r as NotInAnApp, s as loadConfig, t as ConfigNotFound, u as loadWorkspaceSettings } from "./config-20V08LZp.mjs";
5
+ import { D as assertDeployedStage, E as TEST_STAGE, O as deployedProblems, T as InvalidStages, a as getAppBuildOrder, b as getDeployTargetError, k as stageProblems, m as stripPublicPrefix, o as getAppGkmConfig, p as getPublicEnvPrefix, t as allConstructGlobs, x as isDeployTargetSupported } from "./workspace-C2mFV53i.mjs";
6
6
  import { a as withCustomSecret, i as toEmbeddableSecrets, n as maskPassword, t as initStageSecrets } from "./storage-BzaUxmqe.mjs";
7
7
  import { a as getKeyPath, i as FileSecretsStore, n as secretsStoreFor } from "./store-DeGATCS-.mjs";
8
- import { C as loadEnvFiles, S as isPortAvailable, T as prepareEntryCredentials, _ as fakeKey, a as reconcileWorkspace, b as createEntryWrapper, c as LOCAL_CA_PATH, d as postgresDatabaseNames, f as quoteIdentifier, g as describeServices, h as rootSite, i as derivedContainers, l as forgetState, m as resourceName, n as backendsOf$1, p as pgClient, r as constructGlobs, s as COMPOSE_PATH, t as FAKE_ENV, u as applyPostgres, v as primaryPortKey, w as loadSecretsForApp, x as findAvailablePort, y as createCredentialsPreload } from "./workspace-BE0WHPw9.mjs";
9
- import { n as EndpointGenerator, r as runtimeFor } from "./OpenApiTsGenerator-DKmAorGX.mjs";
8
+ import { C as loadEnvFiles, S as isPortAvailable, T as prepareEntryCredentials, _ as fakeKey, a as reconcileWorkspace, b as createEntryWrapper, c as LOCAL_CA_PATH, d as postgresDatabaseNames, f as quoteIdentifier, g as describeServices, h as rootSite, i as derivedContainers, l as forgetState, m as resourceName, n as backendsOf$1, p as pgClient, r as constructGlobs, s as COMPOSE_PATH, t as FAKE_ENV, u as applyPostgres, v as primaryPortKey, w as loadSecretsForApp, x as findAvailablePort, y as createCredentialsPreload } from "./workspace-CgWcE_Yr.mjs";
9
+ import { n as EndpointGenerator, r as runtimeFor } from "./OpenApiTsGenerator-NThANByQ.mjs";
10
10
  import { generateOpenApi, openapiCommand, resolveOpenApiConfig } from "./openapi.mjs";
11
- import { a as writeTestHarness, c as driversFor, i as TEST_MANIFEST_ENV, n as TEST_READY_FILE, o as SubscriberGenerator, s as cacheBackendsIn, t as TEST_READY_ENV } from "./ready-bES_Jk5v.mjs";
12
- import { i as storageBackendFor, n as eventsBackendFor, r as providerOf, t as cacheBackendFor } from "./backends-BNrMPlJb.mjs";
11
+ import { a as writeTestHarness, c as driversFor, i as TEST_MANIFEST_ENV, n as TEST_READY_FILE, o as SubscriberGenerator, s as cacheBackendsIn, t as TEST_READY_ENV } from "./ready-BSpUZnNo.mjs";
12
+ import { i as storageBackendFor, n as eventsBackendFor, r as providerOf, t as cacheBackendFor } from "./backends-BcHL7Gy_.mjs";
13
13
  import { n as withCompute, r as withRoutes, t as manifestModule } from "./emit-C1e8qD08.mjs";
14
14
  import { createRequire } from "node:module";
15
15
  import { Command } from "commander";
@@ -42,7 +42,7 @@ import { Queue } from "@geekmidas/constructs/queue";
42
42
  import { Topic } from "@geekmidas/constructs/topic";
43
43
  import { lookup } from "node:dns/promises";
44
44
  //#region package.json
45
- var version = "10.0.0-alpha.55";
45
+ var version = "10.0.0-alpha.57";
46
46
  //#endregion
47
47
  //#region src/auth/credentials.ts
48
48
  /**
@@ -1333,30 +1333,6 @@ function normalizeTelescopeConfig(config) {
1333
1333
  };
1334
1334
  }
1335
1335
  /**
1336
- * Normalize studio configuration
1337
- * @internal Exported for testing
1338
- */
1339
- function normalizeStudioConfig(config) {
1340
- if (config === false) return;
1341
- if (typeof config === "string") {
1342
- const { path: studioPath, importPattern: studioImportPattern } = parseModuleConfig(config, "studio");
1343
- return {
1344
- enabled: true,
1345
- studioPath,
1346
- studioImportPattern,
1347
- path: "/__studio",
1348
- schema: "public"
1349
- };
1350
- }
1351
- if (!(config === true || config === void 0 || config.enabled !== false)) return;
1352
- const studioConfig = typeof config === "object" ? config : {};
1353
- return {
1354
- enabled: true,
1355
- path: studioConfig.path ?? "/__studio",
1356
- schema: studioConfig.schema ?? "public"
1357
- };
1358
- }
1359
- /**
1360
1336
  * Normalize hooks configuration
1361
1337
  * @internal Exported for testing
1362
1338
  */
@@ -1433,7 +1409,6 @@ async function devCommand(options) {
1433
1409
  if (missing.length > 0) logger$9.warn(`⚠️ Missing env files: ${missing.join(", ")}`);
1434
1410
  }
1435
1411
  const telescope = normalizeTelescopeConfig(config.telescope);
1436
- const studio = normalizeStudioConfig(config.studio);
1437
1412
  const hooks = normalizeHooksConfig(config.hooks, appRoot);
1438
1413
  const enableOpenApi = resolveOpenApiConfig(config).enabled;
1439
1414
  const build = (bustCache = false) => quietly(() => buildApp({
@@ -1444,7 +1419,7 @@ async function devCommand(options) {
1444
1419
  enableOpenApi,
1445
1420
  cacheBackend: cacheBackendFor(providerOf(workspace ?? config)),
1446
1421
  telescope,
1447
- studio,
1422
+ databaseApi: true,
1448
1423
  hooks,
1449
1424
  skipBundle: true,
1450
1425
  bustCache,
@@ -1477,7 +1452,7 @@ async function devCommand(options) {
1477
1452
  secretsJsonPath = join(secretsDir, secretsFileName);
1478
1453
  await writeFile(secretsJsonPath, JSON.stringify(appSecrets, null, 2));
1479
1454
  }
1480
- const devServer = new DevServer(options.port ?? workspaceAppPort ?? 3e3, options.portExplicit ?? workspaceAppPort !== void 0, enableOpenApi, telescope, studio, runtime, appRoot, secretsJsonPath, initial.selfServing !== void 0);
1455
+ const devServer = new DevServer(options.port ?? workspaceAppPort ?? 3e3, options.portExplicit ?? workspaceAppPort !== void 0, enableOpenApi, telescope, initial.databaseApi, runtime, appRoot, secretsJsonPath, initial.selfServing !== void 0);
1481
1456
  devServer.label = workspaceAppName ?? "server";
1482
1457
  devServer.publicUrl = publicUrl;
1483
1458
  await devServer.start();
@@ -1765,9 +1740,9 @@ async function workspaceDevCommand(configured, options) {
1765
1740
  for (const { id, port } of fakes) logger$9.log(`🎭 ${id} fake: http://localhost:${port}`);
1766
1741
  logger$9.log(options.migrate || options.seed ? "🗄️ Migrating the databases" : "🗄️ Checking for pending migrations");
1767
1742
  if (options.migrate || options.seed) {
1768
- const { prepareDevDatabases } = await import("./migrate-PcQg692O.mjs");
1743
+ const { prepareDevDatabases } = await import("./migrate-CS3DkO6y.mjs");
1769
1744
  await prepareDevDatabases(workspace, reconciled.env, { seed: !!options.seed });
1770
- } else await import("./migrate-PcQg692O.mjs").then(({ reportPendingMigrations }) => reportPendingMigrations(workspace, reconciled.env)).catch((error) => {
1745
+ } else await import("./migrate-CS3DkO6y.mjs").then(({ reportPendingMigrations }) => reportPendingMigrations(workspace, reconciled.env)).catch((error) => {
1771
1746
  logger$9.log(`⚠️ Could not check for pending migrations: ${error instanceof Error ? error.message : String(error)}`);
1772
1747
  });
1773
1748
  const appUrls = {};
@@ -2161,7 +2136,7 @@ var DevServer = class {
2161
2136
  portExplicit;
2162
2137
  enableOpenApi;
2163
2138
  telescope;
2164
- studio;
2139
+ databaseApi;
2165
2140
  runtime;
2166
2141
  appRoot;
2167
2142
  secretsJsonPath;
@@ -2170,12 +2145,12 @@ var DevServer = class {
2170
2145
  isRunning = false;
2171
2146
  actualPort;
2172
2147
  startTime = Date.now();
2173
- constructor(requestedPort, portExplicit, enableOpenApi, telescope, studio, runtime = "node", appRoot = process.cwd(), secretsJsonPath, selfServing = false) {
2148
+ constructor(requestedPort, portExplicit, enableOpenApi, telescope, databaseApi, runtime = "node", appRoot = process.cwd(), secretsJsonPath, selfServing = false) {
2174
2149
  this.requestedPort = requestedPort;
2175
2150
  this.portExplicit = portExplicit;
2176
2151
  this.enableOpenApi = enableOpenApi;
2177
2152
  this.telescope = telescope;
2178
- this.studio = studio;
2153
+ this.databaseApi = databaseApi;
2179
2154
  this.runtime = runtime;
2180
2155
  this.appRoot = appRoot;
2181
2156
  this.secretsJsonPath = secretsJsonPath;
@@ -2232,7 +2207,7 @@ var DevServer = class {
2232
2207
  const tools = this.selfServing ? [] : [
2233
2208
  ...this.enableOpenApi ? ["docs /__docs"] : [],
2234
2209
  ...this.telescope ? [`telescope ${this.telescope.path}`] : [],
2235
- ...this.studio ? [`studio ${this.studio.path}`] : []
2210
+ ...this.databaseApi ? [`db ${this.databaseApi}`] : []
2236
2211
  ];
2237
2212
  if (tools.length > 0) logger$9.log(` ${tools.join(" · ")}`);
2238
2213
  }
@@ -2879,18 +2854,26 @@ function keyFingerprint(masterKey) {
2879
2854
  return createHash("sha256").update(masterKey).digest("hex").slice(0, 8);
2880
2855
  }
2881
2856
  //#endregion
2857
+ //#region src/build/types.ts
2858
+ /**
2859
+ * Where `gkm dev` serves the database's read-only JSON API
2860
+ * (`@geekmidas/db/introspect`). Under `/__gkm` with the rest of what the dev
2861
+ * server adds, so it cannot collide with an application route.
2862
+ */
2863
+ const DEV_DATABASE_API_PATH = "/__gkm/db";
2864
+ //#endregion
2882
2865
  //#region src/build/owners.ts
2883
2866
  /**
2884
2867
  * What a generated entry imports its runtime from, read off the discovered
2885
2868
  * constructs: the surface it serves, every construct a runnable can be built
2886
- * from, and the database Studio browses.
2869
+ * from, and the database the dev server's JSON API reads.
2887
2870
  *
2888
2871
  * `gkm build` and `gkm dev` both write entries that import the surface for its
2889
2872
  * logger and environment parser, so both ask here. A dev server that skipped it
2890
2873
  * had nothing to import them from.
2891
2874
  */
2892
2875
  function ownersContext(options) {
2893
- const { declared, sources, workspaceRoot, appRoot, studio } = options;
2876
+ const { declared, sources, workspaceRoot, appRoot, databaseApi } = options;
2894
2877
  const surfaces = restApis(declared);
2895
2878
  const primary = servedSurface(declared, workspaceRoot, appRoot) ?? surfaces.find((d) => d.endpoints.length === 0) ?? surfaces[0];
2896
2879
  const browsable = Object.entries(declared).find(([, d]) => d.kind === "database");
@@ -2917,13 +2900,13 @@ function ownersContext(options) {
2917
2900
  exportName: primarySource.exportName
2918
2901
  } } : {}
2919
2902
  } } : {},
2920
- studio: studio && browsableSource ? {
2921
- ...studio,
2903
+ ...databaseApi && browsableSource ? { databaseApi: {
2904
+ path: DEV_DATABASE_API_PATH,
2922
2905
  database: {
2923
2906
  specifier: browsableSource.file,
2924
2907
  exportName: browsableSource.exportName
2925
2908
  }
2926
- } : studio
2909
+ } } : {}
2927
2910
  };
2928
2911
  }
2929
2912
  /**
@@ -3106,8 +3089,6 @@ async function buildOneApp(input) {
3106
3089
  logger$8.log(`Loading constructs from: ${formatRoutes(config.constructs)}`);
3107
3090
  const telescope = production ? void 0 : normalizeTelescopeConfig(config.telescope);
3108
3091
  if (telescope) logger$8.log(`🔭 Telescope enabled at ${telescope.path}`);
3109
- const studio = production ? void 0 : normalizeStudioConfig(config.studio);
3110
- if (studio) logger$8.log(`🗄️ Studio enabled at ${studio.path}`);
3111
3092
  const hooks = normalizeHooksConfig(config.hooks, appRoot);
3112
3093
  if (hooks) logger$8.log(`🪝 Server hooks enabled`);
3113
3094
  return buildApp({
@@ -3119,7 +3100,6 @@ async function buildOneApp(input) {
3119
3100
  cacheBackend,
3120
3101
  production,
3121
3102
  telescope,
3122
- studio,
3123
3103
  hooks,
3124
3104
  markOptional: options.markOptional ?? false,
3125
3105
  skipBundle: options.skipBundle ?? false,
@@ -3162,7 +3142,7 @@ async function writeManifest(input) {
3162
3142
  * dev did not, and failed on exactly the apps the build had learned to handle.
3163
3143
  */
3164
3144
  async function buildApp(input) {
3165
- const { config, workspaceRoot, appRoot, target, enableOpenApi, cacheBackend, production, telescope, studio, hooks, bustCache = false } = input;
3145
+ const { config, workspaceRoot, appRoot, target, enableOpenApi, cacheBackend, production, telescope, databaseApi, hooks, bustCache = false } = input;
3166
3146
  const constructGlobs = config.constructs;
3167
3147
  const constructSources = {};
3168
3148
  const declared = constructGlobs ? await discover({
@@ -3187,7 +3167,7 @@ async function buildApp(input) {
3187
3167
  sources: constructSources,
3188
3168
  workspaceRoot,
3189
3169
  appRoot,
3190
- studio
3170
+ databaseApi
3191
3171
  });
3192
3172
  const buildContext = {
3193
3173
  ...derived,
@@ -3246,7 +3226,10 @@ async function buildApp(input) {
3246
3226
  openapi: config.openapi,
3247
3227
  root: workspaceRoot
3248
3228
  });
3249
- return result;
3229
+ return {
3230
+ ...result,
3231
+ ...buildContext.databaseApi ? { databaseApi: buildContext.databaseApi.path } : {}
3232
+ };
3250
3233
  }
3251
3234
  async function buildForTarget(target, context, appRoot, workspaceRoot, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, queueGenerator, topicGenerator, endpoints, functions, crons, subscribers, queues, topics, enableOpenApi, skipBundle, stage) {
3252
3235
  const outputDir = join(appRoot, ".gkm", target);
@@ -8854,7 +8837,7 @@ async function createStateStore(options) {
8854
8837
  }
8855
8838
  if (config.provider === "ssm") {
8856
8839
  if (!workspaceName) throw new StateStoreNeedsWorkspaceName("ssm");
8857
- const { SSMStateStore } = await import("./SSMStateStore-oda9xOGc.mjs");
8840
+ const { SSMStateStore } = await import("./SSMStateStore-7hPWW7v7.mjs");
8858
8841
  const ssm = config;
8859
8842
  return SSMStateStore.create({
8860
8843
  workspaceName,
@@ -9520,7 +9503,7 @@ opened.
9520
9503
  `;
9521
9504
  }
9522
9505
  function agentsContent(options, template) {
9523
- const { name, monorepo, telescope, studio, packageManager } = options;
9506
+ const { name, monorepo, telescope, packageManager } = options;
9524
9507
  const { database } = options.constructs;
9525
9508
  const constructsGlob = monorepo ? WORKSPACE_CONSTRUCTS_GLOB : CONSTRUCTS_GLOB;
9526
9509
  const isWorker = template.name === "worker";
@@ -9615,13 +9598,13 @@ export const config = envParser
9615
9598
  as \`undefined\` in exactly the environments that matter.`);
9616
9599
  sections.push(conventionsSection());
9617
9600
  sections.push(testingSection(database));
9618
- if (telescope || studio) {
9619
- const tools = [telescope && "**Telescope** — request and exception monitoring", studio && "**Studio** — dev dashboard and database browser"].filter(Boolean);
9601
+ if (telescope || database) {
9602
+ 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);
9620
9603
  sections.push(`## Dev tools
9621
9604
 
9622
9605
  ${tools.map((t) => `- ${t}`).join("\n")}
9623
9606
 
9624
- Both are derived from declared constructs. Neither needs wiring up by hand.`);
9607
+ 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.`);
9625
9608
  }
9626
9609
  sections.push(`## Before you say it works
9627
9610
 
@@ -10064,11 +10047,7 @@ const TOOLCHAIN_VERSIONS = {
10064
10047
  esbuild: "~0.28.2",
10065
10048
  vitest: "~5.0.2",
10066
10049
  vite: "~8.3.1",
10067
- "@vitejs/plugin-react": "^6.1.1",
10068
- storybook: "^10.6.0",
10069
- "@storybook/addon-docs": "^10.6.0",
10070
- "@storybook/addon-a11y": "^10.6.0",
10071
- "@storybook/react-vite": "^10.6.0"
10050
+ "@vitejs/plugin-react": "^6.1.1"
10072
10051
  };
10073
10052
  /**
10074
10053
  * The Expo app's packages, which track an Expo SDK release (57) rather than
@@ -10128,26 +10107,25 @@ function loadPackageJson() {
10128
10107
  * Run: pnpm --filter @geekmidas/cli sync-versions
10129
10108
  */
10130
10109
  const GEEKMIDAS_VERSIONS = {
10131
- "@geekmidas/audit": "~10.0.0-alpha.55",
10132
- "@geekmidas/auth": "~10.0.0-alpha.55",
10133
- "@geekmidas/cache": "~10.0.0-alpha.55",
10134
- "@geekmidas/client": "~10.0.0-alpha.55",
10135
- "@geekmidas/cloud": "~10.0.0-alpha.55",
10136
- "@geekmidas/constructs": "~10.0.0-alpha.55",
10137
- "@geekmidas/db": "~10.0.0-alpha.55",
10138
- "@geekmidas/emailkit": "~10.0.0-alpha.55",
10139
- "@geekmidas/envkit": "~10.0.0-alpha.55",
10140
- "@geekmidas/errors": "~10.0.0-alpha.55",
10141
- "@geekmidas/events": "~10.0.0-alpha.55",
10142
- "@geekmidas/logger": "~10.0.0-alpha.55",
10143
- "@geekmidas/manifest": "~10.0.0-alpha.55",
10144
- "@geekmidas/rate-limit": "~10.0.0-alpha.55",
10145
- "@geekmidas/schema": "~10.0.0-alpha.55",
10146
- "@geekmidas/services": "~10.0.0-alpha.55",
10147
- "@geekmidas/storage": "~10.0.0-alpha.55",
10148
- "@geekmidas/studio": "~10.0.0-alpha.55",
10149
- "@geekmidas/telescope": "~10.0.0-alpha.55",
10150
- "@geekmidas/testkit": "~10.0.0-alpha.55",
10110
+ "@geekmidas/audit": "~10.0.0-alpha.57",
10111
+ "@geekmidas/auth": "~10.0.0-alpha.57",
10112
+ "@geekmidas/cache": "~10.0.0-alpha.57",
10113
+ "@geekmidas/client": "~10.0.0-alpha.57",
10114
+ "@geekmidas/cloud": "~10.0.0-alpha.57",
10115
+ "@geekmidas/constructs": "~10.0.0-alpha.57",
10116
+ "@geekmidas/db": "~10.0.0-alpha.57",
10117
+ "@geekmidas/emailkit": "~10.0.0-alpha.57",
10118
+ "@geekmidas/envkit": "~10.0.0-alpha.57",
10119
+ "@geekmidas/errors": "~10.0.0-alpha.57",
10120
+ "@geekmidas/events": "~10.0.0-alpha.57",
10121
+ "@geekmidas/logger": "~10.0.0-alpha.57",
10122
+ "@geekmidas/manifest": "~10.0.0-alpha.57",
10123
+ "@geekmidas/rate-limit": "~10.0.0-alpha.57",
10124
+ "@geekmidas/schema": "~10.0.0-alpha.57",
10125
+ "@geekmidas/services": "~10.0.0-alpha.57",
10126
+ "@geekmidas/storage": "~10.0.0-alpha.57",
10127
+ "@geekmidas/telescope": "~10.0.0-alpha.57",
10128
+ "@geekmidas/testkit": "~10.0.0-alpha.57",
10151
10129
  "@geekmidas/cli": `~${loadPackageJson().version}`
10152
10130
  };
10153
10131
  //#endregion
@@ -10270,14 +10248,13 @@ export default defineConfig({
10270
10248
  * Generate configuration files (gkm.config.ts, tsconfig.json, biome.json, turbo.json)
10271
10249
  */
10272
10250
  function generateConfigFiles(options, template) {
10273
- const { telescope, studio, routesStructure } = options;
10251
+ const { telescope, routesStructure } = options;
10274
10252
  const isServerless = template.name === "serverless";
10275
10253
  const hasWorker = template.name === "worker";
10276
10254
  const isFullstack = options.template === "fullstack";
10277
10255
  const getRoutesGlob = () => routesGlob(routesStructure);
10278
10256
  if (isFullstack) return generateSingleAppConfigFiles(options, template, {
10279
10257
  telescope,
10280
- studio,
10281
10258
  routesStructure,
10282
10259
  isServerless,
10283
10260
  hasWorker,
@@ -10303,8 +10280,6 @@ export default defineConfig({${stagesBlock(options.stages)}${options.monorepo ?
10303
10280
  enabled: true,
10304
10281
  path: '/__telescope',
10305
10282
  },`;
10306
- if (studio) gkmConfig += `
10307
- studio: './src/config/studio#studio',`;
10308
10283
  gkmConfig += `
10309
10284
  openapi: {
10310
10285
  enabled: true,
@@ -11853,7 +11828,6 @@ function generateMonorepoFiles(options, _template) {
11853
11828
  lint: "biome lint .",
11854
11829
  fmt: "biome format . --write",
11855
11830
  "fmt:check": "biome format .",
11856
- ...isFullstack ? { storybook: "pnpm --filter ./packages/ui storybook" } : {},
11857
11831
  ...deploy.scripts
11858
11832
  },
11859
11833
  dependencies: {
@@ -12394,14 +12368,13 @@ export const cache = new Cache('${kv.id}');
12394
12368
  * Generate package.json with dependencies based on template and options
12395
12369
  */
12396
12370
  function generatePackageJson(options, template) {
12397
- const { name, telescope, studio, monorepo } = options;
12371
+ const { name, telescope, monorepo } = options;
12398
12372
  const { database, cache, uploads, mail } = options.constructs;
12399
12373
  const dependencies = { ...template.dependencies };
12400
12374
  const devDependencies = { ...template.devDependencies };
12401
12375
  const scripts = { ...template.scripts };
12402
12376
  if (options.loggerType === "pino") dependencies.pino = DEPENDENCY_VERSIONS.pino;
12403
12377
  if (telescope) dependencies["@geekmidas/telescope"] = GEEKMIDAS_VERSIONS["@geekmidas/telescope"];
12404
- if (studio) dependencies["@geekmidas/studio"] = GEEKMIDAS_VERSIONS["@geekmidas/studio"];
12405
12378
  const declares = !monorepo;
12406
12379
  if (declares && (database || uploads || cache || mail)) dependencies["@geekmidas/manifest"] = GEEKMIDAS_VERSIONS["@geekmidas/manifest"];
12407
12380
  if (declares && uploads) dependencies["@geekmidas/storage"] = GEEKMIDAS_VERSIONS["@geekmidas/storage"];
@@ -12542,158 +12515,33 @@ export type Factory = ReturnType<typeof createFactory>;
12542
12515
  }];
12543
12516
  }
12544
12517
  //#endregion
12545
- //#region src/init/generators/ui.ts
12518
+ //#region src/init/generators/shadcn.ts
12546
12519
  /**
12547
- * Generate UI package files for fullstack template
12548
- * Based on @geekmidas/ui with shadcn/ui, Tailwind CSS v4, and Storybook
12549
- */
12550
- function generateUiPackageFiles(options) {
12551
- if (!options.monorepo || options.template !== "fullstack") return [];
12552
- const packageJson = {
12553
- name: `@${options.name}/ui`,
12554
- version: "0.0.1",
12555
- private: true,
12556
- type: "module",
12557
- exports: {
12558
- ".": "./src/index.ts",
12559
- "./components": "./src/components/index.ts",
12560
- "./lib/utils": "./src/lib/utils.ts",
12561
- "./styles": "./src/styles/globals.css"
12562
- },
12563
- scripts: {
12564
- "ts:check": "tsc --noEmit",
12565
- storybook: "storybook dev -p 6006",
12566
- "build:storybook": "storybook build -o dist/storybook"
12567
- },
12568
- dependencies: {
12569
- "@radix-ui/react-dialog": DEPENDENCY_VERSIONS["@radix-ui/react-dialog"],
12570
- "@radix-ui/react-label": DEPENDENCY_VERSIONS["@radix-ui/react-label"],
12571
- "@radix-ui/react-separator": DEPENDENCY_VERSIONS["@radix-ui/react-separator"],
12572
- "@radix-ui/react-slot": DEPENDENCY_VERSIONS["@radix-ui/react-slot"],
12573
- "@radix-ui/react-tabs": DEPENDENCY_VERSIONS["@radix-ui/react-tabs"],
12574
- "@radix-ui/react-tooltip": DEPENDENCY_VERSIONS["@radix-ui/react-tooltip"],
12575
- "class-variance-authority": DEPENDENCY_VERSIONS["class-variance-authority"],
12576
- clsx: DEPENDENCY_VERSIONS["clsx"],
12577
- "lucide-react": DEPENDENCY_VERSIONS["lucide-react"],
12578
- "tailwind-merge": DEPENDENCY_VERSIONS["tailwind-merge"]
12579
- },
12580
- devDependencies: {
12581
- "@storybook/addon-a11y": TOOLCHAIN_VERSIONS["@storybook/addon-a11y"],
12582
- "@storybook/addon-docs": TOOLCHAIN_VERSIONS["@storybook/addon-docs"],
12583
- "@storybook/react-vite": TOOLCHAIN_VERSIONS["@storybook/react-vite"],
12584
- "@tailwindcss/vite": DEPENDENCY_VERSIONS["@tailwindcss/vite"],
12585
- "@types/react": DEPENDENCY_VERSIONS["@types/react"],
12586
- "@types/react-dom": DEPENDENCY_VERSIONS["@types/react-dom"],
12587
- react: DEPENDENCY_VERSIONS["react"],
12588
- "react-dom": DEPENDENCY_VERSIONS["react-dom"],
12589
- storybook: TOOLCHAIN_VERSIONS["storybook"],
12590
- tailwindcss: DEPENDENCY_VERSIONS["tailwindcss"],
12591
- typescript: TOOLCHAIN_VERSIONS["typescript"],
12592
- vite: TOOLCHAIN_VERSIONS["vite"]
12593
- },
12594
- peerDependencies: {
12595
- react: ">=18.0.0",
12596
- "react-dom": ">=18.0.0",
12597
- tailwindcss: ">=4.0.0"
12598
- }
12599
- };
12600
- const tsConfig = {
12601
- extends: "../../tsconfig.json",
12602
- compilerOptions: {
12603
- jsx: "react-jsx",
12604
- lib: [
12605
- "ES2023",
12606
- "DOM",
12607
- "DOM.Iterable"
12608
- ],
12609
- noEmit: true,
12610
- allowImportingTsExtensions: true,
12611
- paths: { "~/*": ["./src/*"] }
12612
- },
12613
- include: ["src/**/*"],
12614
- exclude: [
12615
- "node_modules",
12616
- "dist",
12617
- "**/*.stories.tsx"
12618
- ]
12619
- };
12620
- const componentsJson = {
12621
- $schema: "https://ui.shadcn.com/schema.json",
12622
- style: "new-york",
12623
- rsc: false,
12624
- tsx: true,
12625
- tailwind: {
12626
- config: "",
12627
- css: "src/styles/globals.css",
12628
- baseColor: "neutral",
12629
- cssVariables: true,
12630
- prefix: ""
12631
- },
12632
- aliases: {
12633
- components: "~/components",
12634
- utils: "~/lib/utils",
12635
- ui: "~/components/ui",
12636
- lib: "~/lib",
12637
- hooks: "~/hooks"
12638
- },
12639
- iconLibrary: "lucide"
12640
- };
12641
- const storybookMain = `import type { StorybookConfig } from '@storybook/react-vite';
12642
-
12643
- const config: StorybookConfig = {
12644
- stories: ['../src/**/*.stories.@(ts|tsx)'],
12645
- // Controls, actions, backgrounds, viewport and interactions are part of
12646
- // \`storybook\` itself; docs and a11y are add-ons.
12647
- addons: ['@storybook/addon-docs', '@storybook/addon-a11y'],
12648
- framework: {
12649
- name: '@storybook/react-vite',
12650
- options: {},
12651
- },
12652
- // \`react-docgen\` parses components itself. The TypeScript-based docgen
12653
- // calls into TypeScript's JavaScript API, which TypeScript 7 no longer ships.
12654
- typescript: {
12655
- reactDocgen: 'react-docgen',
12656
- },
12657
- viteFinal: async (config) => {
12658
- // Add Tailwind CSS v4 plugin
12659
- const tailwindcss = await import('@tailwindcss/vite');
12660
- config.plugins = config.plugins || [];
12661
- config.plugins.push(tailwindcss.default());
12662
- return config;
12663
- },
12664
- };
12665
-
12666
- export default config;
12667
- `;
12668
- const storybookPreview = `import type { Preview } from '@storybook/react-vite';
12669
- import '../src/styles/globals.css';
12670
-
12671
- const preview: Preview = {
12672
- // The starting background is a global, not a parameter.
12673
- initialGlobals: {
12674
- backgrounds: { value: 'dark' },
12675
- },
12676
- parameters: {
12677
- backgrounds: {
12678
- options: {
12679
- dark: { name: 'dark', value: '#171717' },
12680
- surface: { name: 'surface', value: '#1c1c1c' },
12681
- light: { name: 'light', value: '#fafafa' },
12682
- },
12683
- },
12684
- controls: {
12685
- matchers: {
12686
- color: /(background|color)$/i,
12687
- date: /Date$/i,
12688
- },
12689
- },
12690
- layout: 'centered',
12691
- },
12520
+ * shadcn/ui components, written into the web app that uses them.
12521
+ *
12522
+ * shadcn is copy-in by design: the components are the app's own source, to
12523
+ * edit and add to with `npx shadcn@latest add`. A shared workspace package of
12524
+ * them was one more package to build and version for code only the web app
12525
+ * imported.
12526
+ */
12527
+ /** What the components below import. */
12528
+ const SHADCN_DEPENDENCIES = {
12529
+ "@radix-ui/react-dialog": DEPENDENCY_VERSIONS["@radix-ui/react-dialog"],
12530
+ "@radix-ui/react-label": DEPENDENCY_VERSIONS["@radix-ui/react-label"],
12531
+ "@radix-ui/react-separator": DEPENDENCY_VERSIONS["@radix-ui/react-separator"],
12532
+ "@radix-ui/react-slot": DEPENDENCY_VERSIONS["@radix-ui/react-slot"],
12533
+ "@radix-ui/react-tabs": DEPENDENCY_VERSIONS["@radix-ui/react-tabs"],
12534
+ "@radix-ui/react-tooltip": DEPENDENCY_VERSIONS["@radix-ui/react-tooltip"],
12535
+ "class-variance-authority": DEPENDENCY_VERSIONS["class-variance-authority"],
12536
+ clsx: DEPENDENCY_VERSIONS["clsx"],
12537
+ "lucide-react": DEPENDENCY_VERSIONS["lucide-react"],
12538
+ "tailwind-merge": DEPENDENCY_VERSIONS["tailwind-merge"]
12692
12539
  };
12693
-
12694
- export default preview;
12695
- `;
12696
- const globalsCss = `@import "tailwindcss";
12540
+ /**
12541
+ * Tailwind v4 with the shadcn theme tokens — the stylesheet the app imports
12542
+ * once, at its root.
12543
+ */
12544
+ const SHADCN_GLOBALS_CSS = `@import "tailwindcss";
12697
12545
 
12698
12546
  @theme {
12699
12547
  --color-background: hsl(var(--background));
@@ -12777,14 +12625,56 @@ export default preview;
12777
12625
  }
12778
12626
  }
12779
12627
  `;
12780
- const utilsTs = `import { type ClassValue, clsx } from 'clsx';
12628
+ /**
12629
+ * The components, `cn`, and the `components.json` that tells the shadcn CLI
12630
+ * where they live.
12631
+ *
12632
+ * @param appDir the web app, relative to the workspace root (`apps/web`)
12633
+ * @param css the stylesheet holding {@link SHADCN_GLOBALS_CSS}, relative to
12634
+ * the app
12635
+ * @param options.rsc whether the app renders React Server Components, so
12636
+ * `shadcn add` marks what it writes `'use client'`. The radix-based
12637
+ * components here carry the directive either way; outside RSC it is inert.
12638
+ */
12639
+ function shadcnFiles(appDir, css, options) {
12640
+ const componentsJson = {
12641
+ $schema: "https://ui.shadcn.com/schema.json",
12642
+ style: "new-york",
12643
+ rsc: options.rsc,
12644
+ tsx: true,
12645
+ tailwind: {
12646
+ config: "",
12647
+ css,
12648
+ baseColor: "neutral",
12649
+ cssVariables: true,
12650
+ prefix: ""
12651
+ },
12652
+ aliases: {
12653
+ components: "~/components",
12654
+ utils: "~/lib/utils",
12655
+ ui: "~/components/ui",
12656
+ lib: "~/lib",
12657
+ hooks: "~/hooks"
12658
+ },
12659
+ iconLibrary: "lucide"
12660
+ };
12661
+ return [
12662
+ {
12663
+ path: `${appDir}/components.json`,
12664
+ content: `${JSON.stringify(componentsJson, null, 2)}\n`
12665
+ },
12666
+ {
12667
+ path: `${appDir}/src/lib/utils.ts`,
12668
+ content: `import { type ClassValue, clsx } from 'clsx';
12781
12669
  import { twMerge } from 'tailwind-merge';
12782
12670
 
12783
12671
  export function cn(...inputs: ClassValue[]) {
12784
12672
  return twMerge(clsx(inputs));
12785
12673
  }
12786
- `;
12787
- const buttonTsx = `import { Slot } from '@radix-ui/react-slot';
12674
+ `
12675
+ },
12676
+ ...Object.entries({
12677
+ button: `import { Slot } from '@radix-ui/react-slot';
12788
12678
  import { cva, type VariantProps } from 'class-variance-authority';
12789
12679
  import * as React from 'react';
12790
12680
 
@@ -12841,73 +12731,8 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
12841
12731
  Button.displayName = 'Button';
12842
12732
 
12843
12733
  export { Button, buttonVariants };
12844
- `;
12845
- const buttonStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12846
- import { Button } from '~/components/ui/button';
12847
-
12848
- const meta: Meta<typeof Button> = {
12849
- title: 'Components/Button',
12850
- component: Button,
12851
- tags: ['autodocs'],
12852
- argTypes: {
12853
- variant: {
12854
- control: 'select',
12855
- options: ['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'],
12856
- },
12857
- size: {
12858
- control: 'select',
12859
- options: ['default', 'sm', 'lg', 'icon'],
12860
- },
12861
- },
12862
- };
12863
-
12864
- export default meta;
12865
- type Story = StoryObj<typeof Button>;
12866
-
12867
- export const Default: Story = {
12868
- args: {
12869
- children: 'Button',
12870
- variant: 'default',
12871
- size: 'default',
12872
- },
12873
- };
12874
-
12875
- export const Secondary: Story = {
12876
- args: {
12877
- children: 'Secondary',
12878
- variant: 'secondary',
12879
- },
12880
- };
12881
-
12882
- export const Destructive: Story = {
12883
- args: {
12884
- children: 'Destructive',
12885
- variant: 'destructive',
12886
- },
12887
- };
12888
-
12889
- export const Outline: Story = {
12890
- args: {
12891
- children: 'Outline',
12892
- variant: 'outline',
12893
- },
12894
- };
12895
-
12896
- export const Ghost: Story = {
12897
- args: {
12898
- children: 'Ghost',
12899
- variant: 'ghost',
12900
- },
12901
- };
12902
-
12903
- export const Link: Story = {
12904
- args: {
12905
- children: 'Link',
12906
- variant: 'link',
12907
- },
12908
- };
12909
- `;
12910
- const inputTsx = `import * as React from 'react';
12734
+ `,
12735
+ input: `import * as React from 'react';
12911
12736
 
12912
12737
  import { cn } from '~/lib/utils';
12913
12738
 
@@ -12929,8 +12754,8 @@ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(
12929
12754
  Input.displayName = 'Input';
12930
12755
 
12931
12756
  export { Input };
12932
- `;
12933
- const cardTsx = `import * as React from 'react';
12757
+ `,
12758
+ card: `import * as React from 'react';
12934
12759
 
12935
12760
  import { cn } from '~/lib/utils';
12936
12761
 
@@ -13006,124 +12831,10 @@ const CardFooter = React.forwardRef<
13006
12831
  CardFooter.displayName = 'CardFooter';
13007
12832
 
13008
12833
  export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
13009
- `;
13010
- const inputStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13011
- import { Input } from '~/components/ui/input';
13012
-
13013
- const meta: Meta<typeof Input> = {
13014
- title: 'Components/Input',
13015
- component: Input,
13016
- tags: ['autodocs'],
13017
- argTypes: {
13018
- type: {
13019
- control: 'select',
13020
- options: ['text', 'email', 'password', 'number', 'search', 'tel', 'url'],
13021
- },
13022
- disabled: {
13023
- control: 'boolean',
13024
- },
13025
- },
13026
- };
13027
-
13028
- export default meta;
13029
- type Story = StoryObj<typeof Input>;
13030
-
13031
- export const Default: Story = {
13032
- args: {
13033
- placeholder: 'Enter text...',
13034
- },
13035
- };
13036
-
13037
- export const Email: Story = {
13038
- args: {
13039
- type: 'email',
13040
- placeholder: 'Enter email...',
13041
- },
13042
- };
13043
-
13044
- export const Password: Story = {
13045
- args: {
13046
- type: 'password',
13047
- placeholder: 'Enter password...',
13048
- },
13049
- };
13050
-
13051
- export const Disabled: Story = {
13052
- args: {
13053
- placeholder: 'Disabled input',
13054
- disabled: true,
13055
- },
13056
- };
13057
-
13058
- export const WithValue: Story = {
13059
- args: {
13060
- defaultValue: 'Hello World',
13061
- },
13062
- };
13063
- `;
13064
- const cardStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13065
- import { Button } from '~/components/ui/button';
13066
- import {
13067
- Card,
13068
- CardContent,
13069
- CardDescription,
13070
- CardFooter,
13071
- CardHeader,
13072
- CardTitle,
13073
- } from '~/components/ui/card';
13074
- import { Input } from '~/components/ui/input';
13075
-
13076
- const meta: Meta<typeof Card> = {
13077
- title: 'Components/Card',
13078
- component: Card,
13079
- tags: ['autodocs'],
13080
- };
13081
-
13082
- export default meta;
13083
- type Story = StoryObj<typeof Card>;
13084
-
13085
- export const Default: Story = {
13086
- render: () => (
13087
- <Card className="w-[350px]">
13088
- <CardHeader>
13089
- <CardTitle>Card Title</CardTitle>
13090
- <CardDescription>Card description goes here.</CardDescription>
13091
- </CardHeader>
13092
- <CardContent>
13093
- <p>Card content goes here.</p>
13094
- </CardContent>
13095
- </Card>
13096
- ),
13097
- };
13098
-
13099
- export const WithFooter: Story = {
13100
- render: () => (
13101
- <Card className="w-[350px]">
13102
- <CardHeader>
13103
- <CardTitle>Create Account</CardTitle>
13104
- <CardDescription>Enter your details below.</CardDescription>
13105
- </CardHeader>
13106
- <CardContent className="space-y-4">
13107
- <Input placeholder="Email" type="email" />
13108
- <Input placeholder="Password" type="password" />
13109
- </CardContent>
13110
- <CardFooter className="flex justify-between">
13111
- <Button variant="outline">Cancel</Button>
13112
- <Button>Create</Button>
13113
- </CardFooter>
13114
- </Card>
13115
- ),
13116
- };
12834
+ `,
12835
+ label: `'use client';
13117
12836
 
13118
- export const Simple: Story = {
13119
- render: () => (
13120
- <Card className="w-[350px] p-6">
13121
- <p>Simple card with just content.</p>
13122
- </Card>
13123
- ),
13124
- };
13125
- `;
13126
- const labelTsx = `import * as LabelPrimitive from '@radix-ui/react-label';
12837
+ import * as LabelPrimitive from '@radix-ui/react-label';
13127
12838
  import { cva, type VariantProps } from 'class-variance-authority';
13128
12839
  import * as React from 'react';
13129
12840
 
@@ -13147,47 +12858,8 @@ const Label = React.forwardRef<
13147
12858
  Label.displayName = LabelPrimitive.Root.displayName;
13148
12859
 
13149
12860
  export { Label };
13150
- `;
13151
- const labelStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13152
- import { Input } from '~/components/ui/input';
13153
- import { Label } from '~/components/ui/label';
13154
-
13155
- const meta: Meta<typeof Label> = {
13156
- title: 'Components/Label',
13157
- component: Label,
13158
- tags: ['autodocs'],
13159
- };
13160
-
13161
- export default meta;
13162
- type Story = StoryObj<typeof Label>;
13163
-
13164
- export const Default: Story = {
13165
- args: {
13166
- children: 'Label',
13167
- },
13168
- };
13169
-
13170
- export const WithInput: Story = {
13171
- render: () => (
13172
- <div className="grid w-full max-w-sm items-center gap-1.5">
13173
- <Label htmlFor="email">Email</Label>
13174
- <Input type="email" id="email" placeholder="Email" />
13175
- </div>
13176
- ),
13177
- };
13178
-
13179
- export const Disabled: Story = {
13180
- render: () => (
13181
- <div className="grid w-full max-w-sm items-center gap-1.5">
13182
- <Label htmlFor="disabled" className="peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
13183
- Disabled
13184
- </Label>
13185
- <Input type="text" id="disabled" placeholder="Disabled" disabled className="peer" />
13186
- </div>
13187
- ),
13188
- };
13189
- `;
13190
- const badgeTsx = `import { cva, type VariantProps } from 'class-variance-authority';
12861
+ `,
12862
+ badge: `import { cva, type VariantProps } from 'class-variance-authority';
13191
12863
  import * as React from 'react';
13192
12864
 
13193
12865
  import { cn } from '~/lib/utils';
@@ -13223,54 +12895,10 @@ function Badge({ className, variant, ...props }: BadgeProps) {
13223
12895
  }
13224
12896
 
13225
12897
  export { Badge, badgeVariants };
13226
- `;
13227
- const badgeStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13228
- import { Badge } from '~/components/ui/badge';
13229
-
13230
- const meta: Meta<typeof Badge> = {
13231
- title: 'Components/Badge',
13232
- component: Badge,
13233
- tags: ['autodocs'],
13234
- argTypes: {
13235
- variant: {
13236
- control: 'select',
13237
- options: ['default', 'secondary', 'destructive', 'outline'],
13238
- },
13239
- },
13240
- };
13241
-
13242
- export default meta;
13243
- type Story = StoryObj<typeof Badge>;
13244
-
13245
- export const Default: Story = {
13246
- args: {
13247
- children: 'Badge',
13248
- variant: 'default',
13249
- },
13250
- };
13251
-
13252
- export const Secondary: Story = {
13253
- args: {
13254
- children: 'Secondary',
13255
- variant: 'secondary',
13256
- },
13257
- };
13258
-
13259
- export const Destructive: Story = {
13260
- args: {
13261
- children: 'Destructive',
13262
- variant: 'destructive',
13263
- },
13264
- };
12898
+ `,
12899
+ separator: `'use client';
13265
12900
 
13266
- export const Outline: Story = {
13267
- args: {
13268
- children: 'Outline',
13269
- variant: 'outline',
13270
- },
13271
- };
13272
- `;
13273
- const separatorTsx = `import * as SeparatorPrimitive from '@radix-ui/react-separator';
12901
+ import * as SeparatorPrimitive from '@radix-ui/react-separator';
13274
12902
  import * as React from 'react';
13275
12903
 
13276
12904
  import { cn } from '~/lib/utils';
@@ -13299,59 +12927,10 @@ const Separator = React.forwardRef<
13299
12927
  Separator.displayName = SeparatorPrimitive.Root.displayName;
13300
12928
 
13301
12929
  export { Separator };
13302
- `;
13303
- const separatorStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13304
- import { Separator } from '~/components/ui/separator';
13305
-
13306
- const meta: Meta<typeof Separator> = {
13307
- title: 'Components/Separator',
13308
- component: Separator,
13309
- tags: ['autodocs'],
13310
- argTypes: {
13311
- orientation: {
13312
- control: 'select',
13313
- options: ['horizontal', 'vertical'],
13314
- },
13315
- },
13316
- };
13317
-
13318
- export default meta;
13319
- type Story = StoryObj<typeof Separator>;
13320
-
13321
- export const Horizontal: Story = {
13322
- render: () => (
13323
- <div className="w-[300px]">
13324
- <div className="space-y-1">
13325
- <h4 className="text-sm font-medium leading-none">Radix Primitives</h4>
13326
- <p className="text-sm text-muted-foreground">
13327
- An open-source UI component library.
13328
- </p>
13329
- </div>
13330
- <Separator className="my-4" />
13331
- <div className="flex h-5 items-center space-x-4 text-sm">
13332
- <div>Blog</div>
13333
- <Separator orientation="vertical" />
13334
- <div>Docs</div>
13335
- <Separator orientation="vertical" />
13336
- <div>Source</div>
13337
- </div>
13338
- </div>
13339
- ),
13340
- };
12930
+ `,
12931
+ tabs: `'use client';
13341
12932
 
13342
- export const Vertical: Story = {
13343
- render: () => (
13344
- <div className="flex h-5 items-center space-x-4 text-sm">
13345
- <div>Blog</div>
13346
- <Separator orientation="vertical" />
13347
- <div>Docs</div>
13348
- <Separator orientation="vertical" />
13349
- <div>Source</div>
13350
- </div>
13351
- ),
13352
- };
13353
- `;
13354
- const tabsTsx = `import * as TabsPrimitive from '@radix-ui/react-tabs';
12933
+ import * as TabsPrimitive from '@radix-ui/react-tabs';
13355
12934
  import * as React from 'react';
13356
12935
 
13357
12936
  import { cn } from '~/lib/utils';
@@ -13404,81 +12983,10 @@ const TabsContent = React.forwardRef<
13404
12983
  TabsContent.displayName = TabsPrimitive.Content.displayName;
13405
12984
 
13406
12985
  export { Tabs, TabsList, TabsTrigger, TabsContent };
13407
- `;
13408
- const tabsStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13409
- import { Tabs, TabsContent, TabsList, TabsTrigger } from '~/components/ui/tabs';
13410
- import { Button } from '~/components/ui/button';
13411
- import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '~/components/ui/card';
13412
- import { Input } from '~/components/ui/input';
13413
- import { Label } from '~/components/ui/label';
13414
-
13415
- const meta: Meta<typeof Tabs> = {
13416
- title: 'Components/Tabs',
13417
- component: Tabs,
13418
- tags: ['autodocs'],
13419
- };
12986
+ `,
12987
+ tooltip: `'use client';
13420
12988
 
13421
- export default meta;
13422
- type Story = StoryObj<typeof Tabs>;
13423
-
13424
- export const Default: Story = {
13425
- render: () => (
13426
- <Tabs defaultValue="account" className="w-[400px]">
13427
- <TabsList>
13428
- <TabsTrigger value="account">Account</TabsTrigger>
13429
- <TabsTrigger value="password">Password</TabsTrigger>
13430
- </TabsList>
13431
- <TabsContent value="account">
13432
- <Card>
13433
- <CardHeader>
13434
- <CardTitle>Account</CardTitle>
13435
- <CardDescription>
13436
- Make changes to your account here. Click save when you're done.
13437
- </CardDescription>
13438
- </CardHeader>
13439
- <CardContent className="space-y-2">
13440
- <div className="space-y-1">
13441
- <Label htmlFor="name">Name</Label>
13442
- <Input id="name" defaultValue="Pedro Duarte" />
13443
- </div>
13444
- <div className="space-y-1">
13445
- <Label htmlFor="username">Username</Label>
13446
- <Input id="username" defaultValue="@peduarte" />
13447
- </div>
13448
- </CardContent>
13449
- <CardFooter>
13450
- <Button>Save changes</Button>
13451
- </CardFooter>
13452
- </Card>
13453
- </TabsContent>
13454
- <TabsContent value="password">
13455
- <Card>
13456
- <CardHeader>
13457
- <CardTitle>Password</CardTitle>
13458
- <CardDescription>
13459
- Change your password here. After saving, you'll be logged out.
13460
- </CardDescription>
13461
- </CardHeader>
13462
- <CardContent className="space-y-2">
13463
- <div className="space-y-1">
13464
- <Label htmlFor="current">Current password</Label>
13465
- <Input id="current" type="password" />
13466
- </div>
13467
- <div className="space-y-1">
13468
- <Label htmlFor="new">New password</Label>
13469
- <Input id="new" type="password" />
13470
- </div>
13471
- </CardContent>
13472
- <CardFooter>
13473
- <Button>Save password</Button>
13474
- </CardFooter>
13475
- </Card>
13476
- </TabsContent>
13477
- </Tabs>
13478
- ),
13479
- };
13480
- `;
13481
- const tooltipTsx = `import * as TooltipPrimitive from '@radix-ui/react-tooltip';
12989
+ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
13482
12990
  import * as React from 'react';
13483
12991
 
13484
12992
  import { cn } from '~/lib/utils';
@@ -13508,80 +13016,10 @@ const TooltipContent = React.forwardRef<
13508
13016
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
13509
13017
 
13510
13018
  export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
13511
- `;
13512
- const tooltipStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13513
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '~/components/ui/tooltip';
13514
- import { Button } from '~/components/ui/button';
13515
-
13516
- const meta: Meta<typeof Tooltip> = {
13517
- title: 'Components/Tooltip',
13518
- component: Tooltip,
13519
- tags: ['autodocs'],
13520
- decorators: [
13521
- (Story) => (
13522
- <TooltipProvider>
13523
- <Story />
13524
- </TooltipProvider>
13525
- ),
13526
- ],
13527
- };
13528
-
13529
- export default meta;
13530
- type Story = StoryObj<typeof Tooltip>;
13531
-
13532
- export const Default: Story = {
13533
- render: () => (
13534
- <Tooltip>
13535
- <TooltipTrigger asChild>
13536
- <Button variant="outline">Hover me</Button>
13537
- </TooltipTrigger>
13538
- <TooltipContent>
13539
- <p>Add to library</p>
13540
- </TooltipContent>
13541
- </Tooltip>
13542
- ),
13543
- };
13019
+ `,
13020
+ dialog: `'use client';
13544
13021
 
13545
- export const Positions: Story = {
13546
- render: () => (
13547
- <div className="flex gap-4">
13548
- <Tooltip>
13549
- <TooltipTrigger asChild>
13550
- <Button variant="outline">Top</Button>
13551
- </TooltipTrigger>
13552
- <TooltipContent side="top">
13553
- <p>Top tooltip</p>
13554
- </TooltipContent>
13555
- </Tooltip>
13556
- <Tooltip>
13557
- <TooltipTrigger asChild>
13558
- <Button variant="outline">Bottom</Button>
13559
- </TooltipTrigger>
13560
- <TooltipContent side="bottom">
13561
- <p>Bottom tooltip</p>
13562
- </TooltipContent>
13563
- </Tooltip>
13564
- <Tooltip>
13565
- <TooltipTrigger asChild>
13566
- <Button variant="outline">Left</Button>
13567
- </TooltipTrigger>
13568
- <TooltipContent side="left">
13569
- <p>Left tooltip</p>
13570
- </TooltipContent>
13571
- </Tooltip>
13572
- <Tooltip>
13573
- <TooltipTrigger asChild>
13574
- <Button variant="outline">Right</Button>
13575
- </TooltipTrigger>
13576
- <TooltipContent side="right">
13577
- <p>Right tooltip</p>
13578
- </TooltipContent>
13579
- </Tooltip>
13580
- </div>
13581
- ),
13582
- };
13583
- `;
13584
- const dialogTsx = `import * as DialogPrimitive from '@radix-ui/react-dialog';
13022
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
13585
13023
  import { X } from 'lucide-react';
13586
13024
  import * as React from 'react';
13587
13025
 
@@ -13701,255 +13139,11 @@ export {
13701
13139
  DialogTitle,
13702
13140
  DialogDescription,
13703
13141
  };
13704
- `;
13705
- const dialogStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
13706
- import {
13707
- Dialog,
13708
- DialogContent,
13709
- DialogDescription,
13710
- DialogFooter,
13711
- DialogHeader,
13712
- DialogTitle,
13713
- DialogTrigger,
13714
- } from '~/components/ui/dialog';
13715
- import { Button } from '~/components/ui/button';
13716
- import { Input } from '~/components/ui/input';
13717
- import { Label } from '~/components/ui/label';
13718
-
13719
- const meta: Meta<typeof Dialog> = {
13720
- title: 'Components/Dialog',
13721
- component: Dialog,
13722
- tags: ['autodocs'],
13723
- };
13724
-
13725
- export default meta;
13726
- type Story = StoryObj<typeof Dialog>;
13727
-
13728
- export const Default: Story = {
13729
- render: () => (
13730
- <Dialog>
13731
- <DialogTrigger asChild>
13732
- <Button variant="outline">Edit Profile</Button>
13733
- </DialogTrigger>
13734
- <DialogContent className="sm:max-w-[425px]">
13735
- <DialogHeader>
13736
- <DialogTitle>Edit profile</DialogTitle>
13737
- <DialogDescription>
13738
- Make changes to your profile here. Click save when you're done.
13739
- </DialogDescription>
13740
- </DialogHeader>
13741
- <div className="grid gap-4 py-4">
13742
- <div className="grid grid-cols-4 items-center gap-4">
13743
- <Label htmlFor="name" className="text-right">
13744
- Name
13745
- </Label>
13746
- <Input id="name" defaultValue="Pedro Duarte" className="col-span-3" />
13747
- </div>
13748
- <div className="grid grid-cols-4 items-center gap-4">
13749
- <Label htmlFor="username" className="text-right">
13750
- Username
13751
- </Label>
13752
- <Input id="username" defaultValue="@peduarte" className="col-span-3" />
13753
- </div>
13754
- </div>
13755
- <DialogFooter>
13756
- <Button type="submit">Save changes</Button>
13757
- </DialogFooter>
13758
- </DialogContent>
13759
- </Dialog>
13760
- ),
13761
- };
13762
-
13763
- export const Alert: Story = {
13764
- render: () => (
13765
- <Dialog>
13766
- <DialogTrigger asChild>
13767
- <Button variant="destructive">Delete Account</Button>
13768
- </DialogTrigger>
13769
- <DialogContent>
13770
- <DialogHeader>
13771
- <DialogTitle>Are you absolutely sure?</DialogTitle>
13772
- <DialogDescription>
13773
- This action cannot be undone. This will permanently delete your
13774
- account and remove your data from our servers.
13775
- </DialogDescription>
13776
- </DialogHeader>
13777
- <DialogFooter>
13778
- <Button variant="outline">Cancel</Button>
13779
- <Button variant="destructive">Delete</Button>
13780
- </DialogFooter>
13781
- </DialogContent>
13782
- </Dialog>
13783
- ),
13784
- };
13785
- `;
13786
- const componentsUiIndex = `export { Button, type ButtonProps, buttonVariants } from './button/index.tsx';
13787
- export { Input } from './input/index.tsx';
13788
- export {
13789
- Card,
13790
- CardHeader,
13791
- CardFooter,
13792
- CardTitle,
13793
- CardDescription,
13794
- CardContent,
13795
- } from './card/index.tsx';
13796
- export { Label } from './label/index.tsx';
13797
- export { Badge, type BadgeProps, badgeVariants } from './badge/index.tsx';
13798
- export { Separator } from './separator/index.tsx';
13799
- export { Tabs, TabsList, TabsTrigger, TabsContent } from './tabs/index.tsx';
13800
- export {
13801
- Tooltip,
13802
- TooltipTrigger,
13803
- TooltipContent,
13804
- TooltipProvider,
13805
- } from './tooltip/index.tsx';
13806
- export {
13807
- Dialog,
13808
- DialogPortal,
13809
- DialogOverlay,
13810
- DialogTrigger,
13811
- DialogClose,
13812
- DialogContent,
13813
- DialogHeader,
13814
- DialogFooter,
13815
- DialogTitle,
13816
- DialogDescription,
13817
- } from './dialog/index.tsx';
13818
- `;
13819
- const buttonIndexTsx = buttonTsx;
13820
- const inputIndexTsx = inputTsx;
13821
- const cardIndexTsx = cardTsx;
13822
- const componentsIndex = `export * from './ui/index.ts';
13823
- `;
13824
- const indexTs = `// @${options.name}/ui - Shared UI component library
13825
-
13826
- // shadcn/ui components
13827
- export * from './components/index.ts';
13828
-
13829
- // Utilities
13830
- export { cn } from './lib/utils.ts';
13831
- `;
13832
- return [
13833
- {
13834
- path: "packages/ui/package.json",
13835
- content: `${JSON.stringify(packageJson, null, 2)}\n`
13836
- },
13837
- {
13838
- path: "packages/ui/tsconfig.json",
13839
- content: `${JSON.stringify(tsConfig, null, 2)}\n`
13840
- },
13841
- {
13842
- path: "packages/ui/components.json",
13843
- content: `${JSON.stringify(componentsJson, null, 2)}\n`
13844
- },
13845
- {
13846
- path: "packages/ui/.storybook/main.ts",
13847
- content: storybookMain
13848
- },
13849
- {
13850
- path: "packages/ui/.storybook/preview.ts",
13851
- content: storybookPreview
13852
- },
13853
- {
13854
- path: "packages/ui/src/styles/globals.css",
13855
- content: globalsCss
13856
- },
13857
- {
13858
- path: "packages/ui/src/lib/utils.ts",
13859
- content: utilsTs
13860
- },
13861
- {
13862
- path: "packages/ui/src/components/ui/button/index.tsx",
13863
- content: buttonIndexTsx
13864
- },
13865
- {
13866
- path: "packages/ui/src/components/ui/button/button.stories.tsx",
13867
- content: buttonStories
13868
- },
13869
- {
13870
- path: "packages/ui/src/components/ui/input/index.tsx",
13871
- content: inputIndexTsx
13872
- },
13873
- {
13874
- path: "packages/ui/src/components/ui/input/input.stories.tsx",
13875
- content: inputStories
13876
- },
13877
- {
13878
- path: "packages/ui/src/components/ui/card/index.tsx",
13879
- content: cardIndexTsx
13880
- },
13881
- {
13882
- path: "packages/ui/src/components/ui/card/card.stories.tsx",
13883
- content: cardStories
13884
- },
13885
- {
13886
- path: "packages/ui/src/components/ui/label/index.tsx",
13887
- content: labelTsx
13888
- },
13889
- {
13890
- path: "packages/ui/src/components/ui/label/label.stories.tsx",
13891
- content: labelStories
13892
- },
13893
- {
13894
- path: "packages/ui/src/components/ui/badge/index.tsx",
13895
- content: badgeTsx
13896
- },
13897
- {
13898
- path: "packages/ui/src/components/ui/badge/badge.stories.tsx",
13899
- content: badgeStories
13900
- },
13901
- {
13902
- path: "packages/ui/src/components/ui/separator/index.tsx",
13903
- content: separatorTsx
13904
- },
13905
- {
13906
- path: "packages/ui/src/components/ui/separator/separator.stories.tsx",
13907
- content: separatorStories
13908
- },
13909
- {
13910
- path: "packages/ui/src/components/ui/tabs/index.tsx",
13911
- content: tabsTsx
13912
- },
13913
- {
13914
- path: "packages/ui/src/components/ui/tabs/tabs.stories.tsx",
13915
- content: tabsStories
13916
- },
13917
- {
13918
- path: "packages/ui/src/components/ui/tooltip/index.tsx",
13919
- content: tooltipTsx
13920
- },
13921
- {
13922
- path: "packages/ui/src/components/ui/tooltip/tooltip.stories.tsx",
13923
- content: tooltipStories
13924
- },
13925
- {
13926
- path: "packages/ui/src/components/ui/dialog/index.tsx",
13927
- content: dialogTsx
13928
- },
13929
- {
13930
- path: "packages/ui/src/components/ui/dialog/dialog.stories.tsx",
13931
- content: dialogStories
13932
- },
13933
- {
13934
- path: "packages/ui/src/components/ui/index.ts",
13935
- content: componentsUiIndex
13936
- },
13937
- {
13938
- path: "packages/ui/src/components/index.ts",
13939
- content: componentsIndex
13940
- },
13941
- {
13942
- path: "packages/ui/src/index.ts",
13943
- content: indexTs
13944
- },
13945
- {
13946
- path: "packages/ui/.gitignore",
13947
- content: `node_modules/
13948
- dist/
13949
- storybook-static/
13950
- *.log
13951
13142
  `
13952
- }
13143
+ }).map(([name, content]) => ({
13144
+ path: `${appDir}/src/components/ui/${name}.tsx`,
13145
+ content
13146
+ }))
13953
13147
  ];
13954
13148
  }
13955
13149
  //#endregion
@@ -13961,7 +13155,6 @@ function generateWebAppFiles(options) {
13961
13155
  if (!options.monorepo || options.template !== "fullstack") return [];
13962
13156
  const packageName = `@${options.name}/web`;
13963
13157
  const modelsPackage = `@${options.name}/models`;
13964
- const uiPackage = `@${options.name}/ui`;
13965
13158
  const packageJson = {
13966
13159
  name: packageName,
13967
13160
  version: "0.0.1",
@@ -13975,7 +13168,7 @@ function generateWebAppFiles(options) {
13975
13168
  },
13976
13169
  dependencies: {
13977
13170
  [modelsPackage]: "workspace:*",
13978
- [uiPackage]: "workspace:*",
13171
+ ...SHADCN_DEPENDENCIES,
13979
13172
  "@geekmidas/client": GEEKMIDAS_VERSIONS["@geekmidas/client"],
13980
13173
  "@geekmidas/envkit": GEEKMIDAS_VERSIONS["@geekmidas/envkit"],
13981
13174
  "@tanstack/react-query": DEPENDENCY_VERSIONS["@tanstack/react-query"],
@@ -14000,7 +13193,7 @@ function generateWebAppFiles(options) {
14000
13193
  const nextConfig: NextConfig = {
14001
13194
  output: 'standalone',
14002
13195
  reactStrictMode: true,
14003
- transpilePackages: ['${modelsPackage}', '${uiPackage}'],
13196
+ transpilePackages: ['${modelsPackage}'],
14004
13197
  };
14005
13198
 
14006
13199
  export default nextConfig;
@@ -14033,12 +13226,10 @@ export default nextConfig;
14033
13226
  incremental: true,
14034
13227
  plugins: [{ name: "next" }],
14035
13228
  paths: {
14036
- "~/*": ["./src/*", "../../packages/ui/src/*"],
13229
+ "~/*": ["./src/*"],
14037
13230
  [`@${options.name}/client/*`]: ["../../.gkm/client/*"],
14038
13231
  [`${modelsPackage}`]: ["../../packages/models/src"],
14039
- [`${modelsPackage}/*`]: ["../../packages/models/src/*"],
14040
- [`${uiPackage}`]: ["../../packages/ui/src"],
14041
- [`${uiPackage}/*`]: ["../../packages/ui/src/*"]
13232
+ [`${modelsPackage}/*`]: ["../../packages/models/src/*"]
14042
13233
  }
14043
13234
  },
14044
13235
  include: [
@@ -14134,8 +13325,6 @@ export const api = createApi({
14134
13325
  baseURL: clientConfig.apiUrl,
14135
13326
  queryClient: getQueryClient(),
14136
13327
  });
14137
- `;
14138
- const globalsCss = `@import '${uiPackage}/styles';
14139
13328
  `;
14140
13329
  const layoutTsx = `import type { Metadata } from 'next';
14141
13330
  import { Providers } from './providers.tsx';
@@ -14161,7 +13350,14 @@ export default function RootLayout({
14161
13350
  }
14162
13351
  `;
14163
13352
  const pageTsx = `import { api } from '~/api/index.ts';
14164
- import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle } from '${uiPackage}/components';
13353
+ import { Button } from '~/components/ui/button.tsx';
13354
+ import {
13355
+ Card,
13356
+ CardContent,
13357
+ CardDescription,
13358
+ CardHeader,
13359
+ CardTitle,
13360
+ } from '~/components/ui/card.tsx';
14165
13361
 
14166
13362
  export default async function Home() {
14167
13363
  // Type-safe API call using the generated client
@@ -14201,7 +13397,7 @@ export default async function Home() {
14201
13397
  <li>Run <code className="rounded bg-muted px-1">gkm openapi</code> to generate typed API client</li>
14202
13398
  <li>Edit <code className="rounded bg-muted px-1">apps/web/src/app/page.tsx</code> to customize this page</li>
14203
13399
  <li>Add API routes in <code className="rounded bg-muted px-1">apps/api/src/endpoints/</code></li>
14204
- <li>Add UI components with <code className="rounded bg-muted px-1">npx shadcn@latest add</code> in packages/ui</li>
13400
+ <li>Add UI components with <code className="rounded bg-muted px-1">npx shadcn@latest add</code> in apps/web</li>
14205
13401
  </ul>
14206
13402
  <div className="flex gap-4">
14207
13403
  <Button>Get Started</Button>
@@ -14213,6 +13409,11 @@ export default async function Home() {
14213
13409
  </main>
14214
13410
  );
14215
13411
  }
13412
+ `;
13413
+ const gitignore = `.next/
13414
+ node_modules/
13415
+ .env.local
13416
+ *.log
14216
13417
  `;
14217
13418
  return [
14218
13419
  {
@@ -14233,8 +13434,9 @@ export default async function Home() {
14233
13434
  },
14234
13435
  {
14235
13436
  path: "apps/web/src/app/globals.css",
14236
- content: globalsCss
13437
+ content: SHADCN_GLOBALS_CSS
14237
13438
  },
13439
+ ...shadcnFiles("apps/web", "src/app/globals.css", { rsc: true }),
14238
13440
  {
14239
13441
  path: "apps/web/src/app/layout.tsx",
14240
13442
  content: layoutTsx
@@ -14269,11 +13471,7 @@ export default async function Home() {
14269
13471
  },
14270
13472
  {
14271
13473
  path: "apps/web/.gitignore",
14272
- content: `.next/
14273
- node_modules/
14274
- .env.local
14275
- *.log
14276
- `
13474
+ content: gitignore
14277
13475
  }
14278
13476
  ];
14279
13477
  }
@@ -14289,7 +13487,6 @@ function generateTanStackWebFiles(options) {
14289
13487
  if (!options.monorepo || options.template !== "fullstack") return [];
14290
13488
  const packageName = `@${options.name}/web`;
14291
13489
  const modelsPackage = `@${options.name}/models`;
14292
- const uiPackage = `@${options.name}/ui`;
14293
13490
  const packageJson = {
14294
13491
  name: packageName,
14295
13492
  version: "0.0.1",
@@ -14303,7 +13500,7 @@ function generateTanStackWebFiles(options) {
14303
13500
  },
14304
13501
  dependencies: {
14305
13502
  [modelsPackage]: "workspace:*",
14306
- [uiPackage]: "workspace:*",
13503
+ ...SHADCN_DEPENDENCIES,
14307
13504
  "@geekmidas/client": GEEKMIDAS_VERSIONS["@geekmidas/client"],
14308
13505
  "@geekmidas/envkit": GEEKMIDAS_VERSIONS["@geekmidas/envkit"],
14309
13506
  "@tanstack/react-query": DEPENDENCY_VERSIONS["@tanstack/react-query"],
@@ -14370,11 +13567,9 @@ export default defineConfig({
14370
13567
  incremental: true,
14371
13568
  types: ["vite/client"],
14372
13569
  paths: {
14373
- "~/*": ["./src/*", "../../packages/ui/src/*"],
13570
+ "~/*": ["./src/*"],
14374
13571
  [modelsPackage]: ["../../packages/models/src"],
14375
13572
  [`${modelsPackage}/*`]: ["../../packages/models/src/*"],
14376
- [uiPackage]: ["../../packages/ui/src"],
14377
- [`${uiPackage}/*`]: ["../../packages/ui/src/*"],
14378
13573
  [`@${options.name}/client/*`]: ["../../.gkm/client/*"]
14379
13574
  }
14380
13575
  },
@@ -14577,10 +13772,15 @@ function HomeComponent() {
14577
13772
  );
14578
13773
  }
14579
13774
  `;
14580
- const globalsCss = `@import '${uiPackage}/styles';
14581
-
13775
+ const globalsCss = `${SHADCN_GLOBALS_CSS}
14582
13776
  @source "../..";
14583
- @source "../../../../packages/ui/src";
13777
+ `;
13778
+ const gitignore = `.output/
13779
+ .vinxi/
13780
+ node_modules/
13781
+ .env.local
13782
+ *.log
13783
+ src/routeTree.gen.ts
14584
13784
  `;
14585
13785
  return [
14586
13786
  {
@@ -14635,15 +13835,10 @@ function HomeComponent() {
14635
13835
  path: "apps/web/src/styles/globals.css",
14636
13836
  content: globalsCss
14637
13837
  },
13838
+ ...shadcnFiles("apps/web", "src/styles/globals.css", { rsc: false }),
14638
13839
  {
14639
13840
  path: "apps/web/.gitignore",
14640
- content: `.output/
14641
- .vinxi/
14642
- node_modules/
14643
- .env.local
14644
- *.log
14645
- src/routeTree.gen.ts
14646
- `
13841
+ content: gitignore
14647
13842
  }
14648
13843
  ];
14649
13844
  }
@@ -14692,7 +13887,7 @@ const apiTemplate = {
14692
13887
  const { cache, uploads, mail: sendsMail } = options.constructs;
14693
13888
  const bucket = storageFor();
14694
13889
  const kv = cacheFor();
14695
- const db = databaseFor();
13890
+ databaseFor();
14696
13891
  const mail = emailFor();
14697
13892
  const src = (path) => `~/${path}`;
14698
13893
  const declares = !monorepo;
@@ -14991,41 +14186,6 @@ export const telescope = new Telescope({
14991
14186
  storage: new InMemoryStorage({ maxEntries: 100 }),
14992
14187
  enabled: process.env.NODE_ENV === 'development',
14993
14188
  });
14994
- `
14995
- });
14996
- if (options.studio && options.constructs.database) files.push({
14997
- path: "src/config/studio.ts",
14998
- content: `import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
14999
- import { Kysely, PostgresDialect } from 'kysely';
15000
- import pg from 'pg';
15001
- import { type Database, database } from '${declares ? src("constructs/database.ts") : constructsImport("database")}';
15002
- import { envParser } from '${src("config/env.ts")}';
15003
-
15004
- const studioConfig = envParser
15005
- .create((get) => ({
15006
- databaseUrl: get('${db.urlKey}').string(),
15007
- }))
15008
- .parse();
15009
-
15010
- // Studio's own client, built the way the construct builds its own — the same
15011
- // plugins — so the browser shows what the app's queries see.
15012
- const db = new Kysely<Database>({
15013
- ...database.clientConfig,
15014
- dialect: new PostgresDialect({
15015
- pool: new pg.Pool({ connectionString: studioConfig.databaseUrl }),
15016
- }),
15017
- });
15018
-
15019
- export const studio = new Studio<Database>({
15020
- monitoring: {
15021
- storage: new InMemoryMonitoringStorage({ maxEntries: 100 }),
15022
- },
15023
- data: {
15024
- db,
15025
- cursor: { field: 'id', direction: Direction.Desc },
15026
- },
15027
- enabled: process.env.NODE_ENV === 'development',
15028
- });
15029
14189
  `
15030
14190
  });
15031
14191
  return files;
@@ -15073,7 +14233,7 @@ const templates = {
15073
14233
  },
15074
14234
  files: (options) => {
15075
14235
  const { loggerType, routesStructure, name } = options;
15076
- const db = databaseFor();
14236
+ databaseFor();
15077
14237
  const loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';
15078
14238
 
15079
14239
  export const logger = createLogger();
@@ -15155,40 +14315,6 @@ export const telescope = new Telescope({
15155
14315
  storage: new InMemoryStorage({ maxEntries: 100 }),
15156
14316
  enabled: process.env.NODE_ENV === 'development',
15157
14317
  });
15158
- `
15159
- });
15160
- if (options.studio && options.constructs.database) files.push({
15161
- path: "src/config/studio.ts",
15162
- content: `import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
15163
- import { Kysely, PostgresDialect } from 'kysely';
15164
- import pg from 'pg';
15165
- import type { Database } from '~/constructs/database.ts';
15166
- import { envParser } from '~/config/env.ts';
15167
-
15168
- // The key the database construct publishes — not a hand-written DATABASE_URL.
15169
- const studioConfig = envParser
15170
- .create((get) => ({
15171
- databaseUrl: get('${db.urlKey}').string(),
15172
- }))
15173
- .parse();
15174
-
15175
- // Create a Kysely instance for Studio
15176
- const db = new Kysely<Database>({
15177
- dialect: new PostgresDialect({
15178
- pool: new pg.Pool({ connectionString: studioConfig.databaseUrl }),
15179
- }),
15180
- });
15181
-
15182
- export const studio = new Studio<Database>({
15183
- monitoring: {
15184
- storage: new InMemoryMonitoringStorage({ maxEntries: 100 }),
15185
- },
15186
- data: {
15187
- db,
15188
- cursor: { field: 'id', direction: Direction.Desc },
15189
- },
15190
- enabled: process.env.NODE_ENV === 'development',
15191
- });
15192
14318
  `
15193
14319
  });
15194
14320
  return files;
@@ -15909,7 +15035,7 @@ async function initCommand(projectName, options = {}) {
15909
15035
  {
15910
15036
  type: options.yes ? null : "confirm",
15911
15037
  name: "telescope",
15912
- message: "Include Telescope (debugging dashboard)?",
15038
+ message: "Include Telescope (request, exception and log recording)?",
15913
15039
  initial: true
15914
15040
  },
15915
15041
  {
@@ -15964,13 +15090,11 @@ async function initCommand(projectName, options = {}) {
15964
15090
  };
15965
15091
  const pkgManager = options.pm ? options.pm : options.yes ? "pnpm" : answers.packageManager ?? detectedPkgManager;
15966
15092
  const deployTarget = options.deploy ?? (options.yes ? "none" : answers.deployTarget ?? "none");
15967
- const database = constructs.database;
15968
15093
  const frontendFramework = isFullstack ? options.yes ? "nextjs" : answers.frontendFramework ?? "nextjs" : void 0;
15969
15094
  const templateOptions = {
15970
15095
  name,
15971
15096
  template,
15972
15097
  telescope: options.yes ? true : answers.telescope ?? true,
15973
- studio: database,
15974
15098
  loggerType: options.yes ? "pino" : answers.loggerType ?? "pino",
15975
15099
  routesStructure: options.yes ? "centralized-endpoints" : answers.routesStructure ?? "centralized-endpoints",
15976
15100
  monorepo,
@@ -16007,7 +15131,6 @@ async function initCommand(projectName, options = {}) {
16007
15131
  ] : [];
16008
15132
  const webAppFiles = isFullstack ? frontendFramework === "tanstack-start" ? generateTanStackWebFiles(templateOptions) : frontendFramework === "expo" ? generateExpoAppFiles(templateOptions) : generateWebAppFiles(templateOptions) : [];
16009
15133
  const authAppFiles = isFullstack ? generateAuthAppFiles(templateOptions) : [];
16010
- const uiPackageFiles = isFullstack ? generateUiPackageFiles(templateOptions) : [];
16011
15134
  for (const { path, content } of rootFiles) {
16012
15135
  const fullPath = join(targetDir, path);
16013
15136
  await mkdir(dirname(fullPath), { recursive: true });
@@ -16028,11 +15151,6 @@ async function initCommand(projectName, options = {}) {
16028
15151
  await mkdir(dirname(fullPath), { recursive: true });
16029
15152
  await writeFile(fullPath, content);
16030
15153
  }
16031
- for (const { path, content } of uiPackageFiles) {
16032
- const fullPath = join(targetDir, path);
16033
- await mkdir(dirname(fullPath), { recursive: true });
16034
- await writeFile(fullPath, content);
16035
- }
16036
15154
  console.log("🔐 Initializing encrypted secrets...\n");
16037
15155
  const local = templateOptions.stages.local;
16038
15156
  const devSecrets = createStageSecrets(local, [], { projectName: name });
@@ -16135,8 +15253,7 @@ function printNextSteps(projectName, options, pkgManager) {
16135
15253
  }
16136
15254
  }
16137
15255
  console.log(` ├── packages/`);
16138
- console.log(` │ ├── models/ # Shared Zod schemas`);
16139
- if (isFullstackTemplate(options.template)) console.log(` │ └── ui/ # Shared UI components`);
15256
+ console.log(` │ └── models/ # Shared Zod schemas`);
16140
15257
  console.log(` ├── .gkm/secrets/ # Encrypted secrets`);
16141
15258
  console.log(` ├── gkm.config.ts # Workspace config`);
16142
15259
  console.log(` └── turbo.json # Turbo config`);
@@ -16890,7 +16007,7 @@ function testDatabases(reconciled) {
16890
16007
  * starts without the reference data the app needs.
16891
16008
  */
16892
16009
  async function migrateTestStage(workspace, env) {
16893
- const { migrateAndSeed } = await import("./migrate-PcQg692O.mjs");
16010
+ const { migrateAndSeed } = await import("./migrate-CS3DkO6y.mjs");
16894
16011
  const { discover } = await import("./discover-Cf2jAcgF.mjs").then((n) => n.n);
16895
16012
  const sources = {};
16896
16013
  const manifest = await discover({
@@ -17321,7 +16438,7 @@ program.command("migrate").description("Apply each database construct's migratio
17321
16438
  try {
17322
16439
  const globalOptions = program.opts();
17323
16440
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17324
- const { migrateCommand } = await import("./migrate-PcQg692O.mjs");
16441
+ const { migrateCommand } = await import("./migrate-CS3DkO6y.mjs");
17325
16442
  await migrateCommand({
17326
16443
  ...options,
17327
16444
  ...construct ? { construct } : {}
@@ -17335,7 +16452,7 @@ program.command("seed").description("Migrate, then run each database construct's
17335
16452
  try {
17336
16453
  const globalOptions = program.opts();
17337
16454
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17338
- const { seedCommand } = await import("./migrate-PcQg692O.mjs");
16455
+ const { seedCommand } = await import("./migrate-CS3DkO6y.mjs");
17339
16456
  await seedCommand({
17340
16457
  ...options,
17341
16458
  ...construct ? { construct } : {}
@@ -17349,7 +16466,7 @@ program.command("migration").description("Write a construct's next migration: an
17349
16466
  try {
17350
16467
  const globalOptions = program.opts();
17351
16468
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17352
- const { migrationCommand } = await import("./migrate-PcQg692O.mjs");
16469
+ const { migrationCommand } = await import("./migrate-CS3DkO6y.mjs");
17353
16470
  await migrationCommand({
17354
16471
  construct,
17355
16472
  ...name ? { name } : {}
@@ -17447,7 +16564,7 @@ program.command("encryption:rotate").description("Add a new current key to an En
17447
16564
  try {
17448
16565
  const globalOptions = program.opts();
17449
16566
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17450
- const { encryptionRotateCommand } = await import("./encryption-Bc1cMdeY.mjs");
16567
+ const { encryptionRotateCommand } = await import("./encryption-KQTYFEzU.mjs");
17451
16568
  await encryptionRotateCommand(construct, options);
17452
16569
  } catch (error) {
17453
16570
  console.error(formatError(error));
@@ -17458,7 +16575,7 @@ program.command("encryption:retire").description("Remove an old key from an Encr
17458
16575
  try {
17459
16576
  const globalOptions = program.opts();
17460
16577
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17461
- const { encryptionRetireCommand } = await import("./encryption-Bc1cMdeY.mjs");
16578
+ const { encryptionRetireCommand } = await import("./encryption-KQTYFEzU.mjs");
17462
16579
  await encryptionRetireCommand(construct, key, options);
17463
16580
  } catch (error) {
17464
16581
  console.error(formatError(error));
@@ -17510,7 +16627,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
17510
16627
  console.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
17511
16628
  process.exit(1);
17512
16629
  }
17513
- const { derivedContainers } = await import("./workspace-BE0WHPw9.mjs").then((n) => n.o);
16630
+ const { derivedContainers } = await import("./workspace-CgWcE_Yr.mjs").then((n) => n.o);
17514
16631
  const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers(workspace, stage));
17515
16632
  if (!result) {
17516
16633
  console.log(`\n✓ Secrets for stage "${stage}" are up-to-date`);
@@ -17569,7 +16686,7 @@ program.command("deploy:github").description("Let GitHub Actions deploy a stage:
17569
16686
  try {
17570
16687
  const globalOptions = program.opts();
17571
16688
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
17572
- const { deployGithubCommand } = await import("./github-DWHXTcwL.mjs");
16689
+ const { deployGithubCommand } = await import("./github-y7OEj59M.mjs");
17573
16690
  await deployGithubCommand(options);
17574
16691
  } catch (error) {
17575
16692
  console.error(formatError(error));