@geekmidas/cli 10.0.0-alpha.0 → 10.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1224,13 +1224,6 @@ export default defineWorkspace({
1224
1224
  schema: 'zod',
1225
1225
  },
1226
1226
  },
1227
- // Backend selection, and nothing else. Whether a Postgres exists comes from
1228
- // declaring a database, not from a flag here — so `db` and `storage` are
1229
- // ignored rather than obeyed, and the two cannot disagree.
1230
- services: {
1231
- cache: 'db',
1232
- mail: 'ses',
1233
- },
1234
1227
  deploy: {
1235
1228
  default: 'dokploy',
1236
1229
  },
package/dist/index.cjs CHANGED
@@ -43,7 +43,7 @@ const prompts = require_chunk.__toESM(require("prompts"));
43
43
 
44
44
  //#region package.json
45
45
  var name = "@geekmidas/cli";
46
- var version = "9.0.2";
46
+ var version = "10.0.0-alpha.0";
47
47
  var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
48
48
  var private$1 = false;
49
49
  var type = "module";
@@ -7364,26 +7364,26 @@ const CLI_VERSION = `~${pkg.version}`;
7364
7364
  * Run: pnpm --filter @geekmidas/cli sync-versions
7365
7365
  */
7366
7366
  const GEEKMIDAS_VERSIONS = {
7367
- "@geekmidas/audit": "~9.0.2",
7368
- "@geekmidas/auth": "~9.0.2",
7369
- "@geekmidas/cache": "~9.0.2",
7370
- "@geekmidas/client": "~9.0.2",
7371
- "@geekmidas/cloud": "~9.0.2",
7372
- "@geekmidas/constructs": "~9.0.2",
7373
- "@geekmidas/db": "~9.0.2",
7374
- "@geekmidas/emailkit": "~9.0.2",
7375
- "@geekmidas/envkit": "~9.0.2",
7376
- "@geekmidas/errors": "~9.0.2",
7377
- "@geekmidas/events": "~9.0.2",
7378
- "@geekmidas/logger": "~9.0.2",
7379
- "@geekmidas/manifest": "~9.0.2",
7380
- "@geekmidas/rate-limit": "~9.0.2",
7381
- "@geekmidas/schema": "~9.0.2",
7382
- "@geekmidas/services": "~9.0.2",
7383
- "@geekmidas/storage": "~9.0.2",
7384
- "@geekmidas/studio": "~9.0.2",
7385
- "@geekmidas/telescope": "~9.0.2",
7386
- "@geekmidas/testkit": "~9.0.2",
7367
+ "@geekmidas/audit": "~10.0.0-alpha.0",
7368
+ "@geekmidas/auth": "~10.0.0-alpha.0",
7369
+ "@geekmidas/cache": "~10.0.0-alpha.0",
7370
+ "@geekmidas/client": "~10.0.0-alpha.0",
7371
+ "@geekmidas/cloud": "~10.0.0-alpha.0",
7372
+ "@geekmidas/constructs": "~10.0.0-alpha.0",
7373
+ "@geekmidas/db": "~10.0.0-alpha.0",
7374
+ "@geekmidas/emailkit": "~10.0.0-alpha.0",
7375
+ "@geekmidas/envkit": "~10.0.0-alpha.0",
7376
+ "@geekmidas/errors": "~10.0.0-alpha.0",
7377
+ "@geekmidas/events": "~10.0.0-alpha.0",
7378
+ "@geekmidas/logger": "~10.0.0-alpha.0",
7379
+ "@geekmidas/manifest": "~10.0.0-alpha.0",
7380
+ "@geekmidas/rate-limit": "~10.0.0-alpha.0",
7381
+ "@geekmidas/schema": "~10.0.0-alpha.0",
7382
+ "@geekmidas/services": "~10.0.0-alpha.0",
7383
+ "@geekmidas/storage": "~10.0.0-alpha.0",
7384
+ "@geekmidas/studio": "~10.0.0-alpha.0",
7385
+ "@geekmidas/telescope": "~10.0.0-alpha.0",
7386
+ "@geekmidas/testkit": "~10.0.0-alpha.0",
7387
7387
  "@geekmidas/cli": CLI_VERSION
7388
7388
  };
7389
7389
 
@@ -7442,119 +7442,6 @@ function generateAuthAppFiles(options) {
7442
7442
  include: ["src/**/*.ts"],
7443
7443
  exclude: ["node_modules", "dist"]
7444
7444
  };
7445
- const envTs = `import { Credentials } from '@geekmidas/envkit/credentials';
7446
- import { EnvironmentParser } from '@geekmidas/envkit';
7447
-
7448
- export const envParser = new EnvironmentParser({ ...process.env, ...Credentials });
7449
-
7450
- // Global config - only minimal shared values
7451
- // Service-specific config should be parsed where needed
7452
- export const config = envParser
7453
- .create((get) => ({
7454
- nodeEnv: get('NODE_ENV').enum(['development', 'test', 'production']).default('development'),
7455
- stage: get('STAGE').enum(['development', 'staging', 'production']).default('development'),
7456
- }))
7457
- .parse();
7458
- `;
7459
- const loggerTs = `import { createLogger } from '@geekmidas/logger/${options.loggerType}';
7460
-
7461
- export const logger = createLogger();
7462
- `;
7463
- const authTs = `import { betterAuth } from 'better-auth';
7464
- import { magicLink } from 'better-auth/plugins';
7465
- import pg from 'pg';
7466
- import { envParser } from './config/env.ts';
7467
- import { logger } from './config/logger.ts';
7468
-
7469
- // Parse auth-specific config (no defaults - values from secrets)
7470
- const authConfig = envParser
7471
- .create((get) => ({
7472
- databaseUrl: get('DATABASE_URL').string(),
7473
- baseUrl: get('BETTER_AUTH_URL').string(),
7474
- trustedOrigins: get('BETTER_AUTH_TRUSTED_ORIGINS').string(),
7475
- secret: get('BETTER_AUTH_SECRET').string(),
7476
- }))
7477
- .parse();
7478
-
7479
- export const auth = betterAuth({
7480
- database: new pg.Pool({
7481
- connectionString: authConfig.databaseUrl,
7482
- }),
7483
- baseURL: authConfig.baseUrl,
7484
- trustedOrigins: authConfig.trustedOrigins.split(','),
7485
- secret: authConfig.secret,
7486
- plugins: [
7487
- magicLink({
7488
- sendMagicLink: async ({ email, url }) => {
7489
- // TODO: Implement email sending using @geekmidas/emailkit
7490
- // For development, log the magic link
7491
- logger.info({ email, url }, 'Magic link generated');
7492
- console.log('\\n================================');
7493
- console.log('MAGIC LINK FOR:', email);
7494
- console.log(url);
7495
- console.log('================================\\n');
7496
- },
7497
- expiresIn: 300, // 5 minutes
7498
- }),
7499
- ],
7500
- emailAndPassword: {
7501
- enabled: false, // Only magic link for now
7502
- },
7503
- });
7504
-
7505
- export type Auth = typeof auth;
7506
- `;
7507
- const indexTs = `import { Hono } from 'hono';
7508
- import { cors } from 'hono/cors';
7509
- import { serve } from '@hono/node-server';
7510
- import { auth } from './auth.ts';
7511
- import { envParser } from './config/env.ts';
7512
- import { logger } from './config/logger.ts';
7513
-
7514
- // Parse server config (no defaults - values from secrets)
7515
- const serverConfig = envParser
7516
- .create((get) => ({
7517
- port: get('PORT').string().transform(Number),
7518
- trustedOrigins: get('BETTER_AUTH_TRUSTED_ORIGINS').string(),
7519
- }))
7520
- .parse();
7521
-
7522
- const app = new Hono();
7523
-
7524
- // CORS must be registered before routes
7525
- app.use(
7526
- '/api/auth/*',
7527
- cors({
7528
- origin: serverConfig.trustedOrigins.split(','),
7529
- allowHeaders: ['Content-Type', 'Authorization'],
7530
- allowMethods: ['POST', 'GET', 'OPTIONS'],
7531
- credentials: true,
7532
- }),
7533
- );
7534
-
7535
- // Health check endpoint
7536
- app.get('/health', (c) => {
7537
- return c.json({
7538
- status: 'ok',
7539
- service: 'auth',
7540
- timestamp: new Date().toISOString(),
7541
- });
7542
- });
7543
-
7544
- // Mount better-auth handler
7545
- app.on(['POST', 'GET'], '/api/auth/*', (c) => {
7546
- return auth.handler(c.req.raw);
7547
- });
7548
-
7549
- logger.info({ port: serverConfig.port }, 'Starting auth server');
7550
-
7551
- serve({
7552
- fetch: app.fetch,
7553
- port: serverConfig.port,
7554
- }, (info) => {
7555
- logger.info({ port: info.port }, 'Auth server running');
7556
- });
7557
- `;
7558
7445
  const gitignore = `node_modules/
7559
7446
  dist/
7560
7447
  .env.local
@@ -7569,22 +7456,6 @@ dist/
7569
7456
  path: "apps/auth/tsconfig.json",
7570
7457
  content: `${JSON.stringify(tsConfig, null, 2)}\n`
7571
7458
  },
7572
- {
7573
- path: "apps/auth/src/config/env.ts",
7574
- content: envTs
7575
- },
7576
- {
7577
- path: "apps/auth/src/config/logger.ts",
7578
- content: loggerTs
7579
- },
7580
- {
7581
- path: "apps/auth/src/auth.ts",
7582
- content: authTs
7583
- },
7584
- {
7585
- path: "apps/auth/src/index.ts",
7586
- content: indexTs
7587
- },
7588
7459
  {
7589
7460
  path: "apps/auth/.gitignore",
7590
7461
  content: gitignore
@@ -7797,6 +7668,7 @@ export default defineConfig({${options.monorepo ? "" : `
7797
7668
  baseUrl: ".",
7798
7669
  paths: {
7799
7670
  "~/*": ["./src/*"],
7671
+ [`@${options.name}/constructs/*`]: ["../../constructs/*"],
7800
7672
  [`@${options.name}/*`]: ["../../packages/*/src"]
7801
7673
  }
7802
7674
  },
@@ -9191,6 +9063,10 @@ coverage/
9191
9063
  `;
9192
9064
  const tsConfig = {
9193
9065
  compilerOptions: {
9066
+ ...isFullstack ? {
9067
+ baseUrl: ".",
9068
+ paths: { [`@${options.name}/constructs/*`]: ["./constructs/*"] }
9069
+ } : {},
9194
9070
  target: "ES2022",
9195
9071
  module: "NodeNext",
9196
9072
  moduleResolution: "NodeNext",
@@ -9300,124 +9176,212 @@ export default defineConfig({
9300
9176
  return files$1;
9301
9177
  }
9302
9178
  /**
9303
- * Generate the frontend app entry for the workspace config based on the
9304
- * selected `frontendFramework`. Defaults to Next.js for backwards compat.
9305
- */
9306
- function generateFrontendAppEntry(options) {
9307
- switch (options.frontendFramework) {
9308
- case "tanstack-start": return `web: {
9309
- type: 'web',
9310
- framework: 'tanstack-start',
9311
- path: 'apps/web',
9312
- port: 3001,
9313
- dependencies: ['api', 'auth'],
9314
- config: {
9315
- client: './src/config/client.ts',
9316
- server: './src/config/server.ts',
9317
- },
9318
- },`;
9319
- case "expo": return `app: {
9320
- type: 'mobile',
9321
- framework: 'expo',
9322
- path: 'apps/app',
9323
- port: 8081,
9324
- dependencies: ['api', 'auth'],
9325
- },`;
9326
- default: return `web: {
9327
- type: 'web',
9328
- framework: 'nextjs',
9329
- path: 'apps/web',
9330
- port: 3001,
9331
- dependencies: ['api', 'auth'],
9332
- config: {
9333
- client: './src/config/client.ts',
9334
- server: './src/config/server.ts',
9335
- },
9336
- },`;
9337
- }
9338
- }
9339
- /**
9340
- * Generate gkm.config.ts with defineWorkspace for fullstack template
9179
+ * `gkm.config.ts` for the fullstack workspace.
9180
+ *
9181
+ * What is *not* here is the point. There is no `apps` block: the apps are the
9182
+ * constructs that said they have a process — a `RestApi`, a `BetterAuth`, a
9183
+ * `StaticSite` — and naming them again here would be the same sentence written
9184
+ * twice with only one copy checked.
9185
+ *
9186
+ * There is no `services` block either unless something non-default was picked.
9187
+ * Every key defaults from the deploy target: on a server target a cache is a
9188
+ * table in the database that is already there, storage is MinIO, mail is SES.
9341
9189
  */
9342
9190
  function generateWorkspaceConfig(options) {
9343
- const { telescope, services, deployTarget, routesStructure } = options;
9344
- const getRoutesGlob = () => {
9345
- switch (routesStructure) {
9346
- case "centralized-endpoints": return "./src/endpoints/**/*.ts";
9347
- case "centralized-routes": return "./src/routes/**/*.ts";
9348
- case "domain-based": return "./src/**/routes/*.ts";
9349
- }
9350
- };
9351
9191
  let config = `import { defineWorkspace } from '@geekmidas/cli/config';
9352
9192
 
9353
9193
  export default defineWorkspace({
9194
+ // The scope every physical name is built from: \`Database\` becomes
9195
+ // \`production-${options.name}-database\` on Dokploy and on AWS alike.
9354
9196
  name: '${options.name}',
9355
- apps: {
9356
- api: {
9357
- type: 'backend',
9358
- path: 'apps/api',
9359
- port: 3000,
9360
- routes: '${getRoutesGlob()}',
9361
- envParser: './src/config/env#envParser',
9362
- logger: './src/config/logger#logger',
9363
- dependencies: ['auth'],`;
9364
- if (telescope) config += `
9365
- telescope: {
9366
- enabled: true,
9367
- path: '/__telescope',
9368
- },`;
9369
- config += `
9370
- openapi: {
9371
- enabled: true,
9372
- },
9373
- },
9374
- auth: {
9375
- type: 'backend',
9376
- path: 'apps/auth',
9377
- port: 3002,
9378
- entry: './src/index.ts',
9379
- framework: 'better-auth',
9380
- envParser: './src/config/env#envParser',
9381
- logger: './src/config/logger#logger',
9382
- },
9383
- ${generateFrontendAppEntry(options)}
9384
- },
9385
- shared: {
9386
- packages: ['packages/*'],
9387
- models: {
9388
- path: 'packages/models',
9389
- schema: 'zod',
9390
- },
9391
- },`;
9392
- if (services.db || services.cache || services.mail || services.storage || services.events) {
9393
- config += `
9394
- services: {`;
9395
- if (services.db) config += `
9396
- db: true,`;
9397
- if (services.cache) config += `
9398
- cache: true,`;
9399
- if (services.mail) config += `
9400
- mail: true,`;
9401
- if (services.storage) config += `
9402
- storage: true,`;
9403
- if (services.events) config += `
9404
- events: '${services.events}',`;
9405
- config += `
9406
- },`;
9407
- }
9408
- if (deployTarget === "dokploy") config += `
9409
- deploy: {
9410
- default: 'dokploy',
9411
- },`;
9412
- config += `
9197
+
9198
+ // One glob, every kind. A declared database is why a Postgres exists, a
9199
+ // declared bucket is why MinIO does, a declared topic is why a broker does —
9200
+ // none of it listed here. It is also where the apps come from: a
9201
+ // \`StaticSite\` is an app, and so is every \`RestApi\`.
9202
+ constructs: './constructs/**/*.ts',
9203
+
9413
9204
  secrets: {
9414
9205
  enabled: true,
9415
- },`;
9416
- config += `
9206
+ },
9417
9207
  });
9418
9208
  `;
9209
+ if (options.services.events && options.services.events !== "pgboss") config = config.replace(" secrets: {", ` services: {
9210
+ events: '${options.services.events}',
9211
+ },
9212
+
9213
+ secrets: {`);
9419
9214
  return config;
9420
9215
  }
9216
+ /**
9217
+ * The workspace's constructs, at its root rather than inside an app.
9218
+ *
9219
+ * They outlive the app that used them first: a site depending on the API is a
9220
+ * fact about the workspace, and a construct reaching across into a sibling
9221
+ * app's `src/` to state it is the shape this layout removes. Apps import them
9222
+ * through the `@<name>/constructs/*` path the root tsconfig maps.
9223
+ *
9224
+ * Every one of these is also an answer config used to give: the database is
9225
+ * why a Postgres exists, the surface and the site are the apps, and the edges
9226
+ * between them are the CORS origins and the build order.
9227
+ */
9228
+ function generateRootConstructs(options) {
9229
+ if (!options.monorepo || options.template !== "fullstack") return [];
9230
+ const { name: name$1, services, frontendFramework } = options;
9231
+ const db = databaseFor(name$1);
9232
+ const files$1 = [];
9233
+ files$1.push({
9234
+ path: "constructs/logger.ts",
9235
+ content: `import { createLogger } from '@geekmidas/logger/${options.loggerType}';
9236
+
9237
+ /**
9238
+ * The logger every endpoint runs with.
9239
+ *
9240
+ * Named once, here, because the surface carries it. It used to be
9241
+ * \`logger: './src/config/logger#logger'\` in config — a module path the build
9242
+ * printed into each generated handler, checked by nothing and wrong the moment
9243
+ * the file moved.
9244
+ */
9245
+ export const logger = createLogger();
9246
+ `
9247
+ });
9248
+ files$1.push({
9249
+ path: "constructs/database.ts",
9250
+ content: `import { KyselyDatabase } from '@geekmidas/constructs/database/kysely';
9251
+ import type { Generated } from 'kysely';
9252
+
9253
+ /** Your database schema. Add tables here. */
9254
+ export interface Database {
9255
+ users: {
9256
+ id: Generated<string>;
9257
+ name: string;
9258
+ email: string;
9259
+ created_at: Generated<Date>;
9260
+ };
9261
+ }
9262
+
9263
+ /**
9264
+ * The database, declared once.
9265
+ *
9266
+ * The container, the database inside it, its roles and schema, and
9267
+ * \`${db.urlKey}\` all derive from this line — which is why nothing lists
9268
+ * \`postgres\` anywhere.
9269
+ */
9270
+ export const database = new KyselyDatabase<Database, '${db.id}'>('${db.id}');
9271
+
9272
+ /**
9273
+ * The auth server's own schema in that same Postgres, with its own role.
9274
+ *
9275
+ * A schema tenant rather than a second database: one container, and a role
9276
+ * whose \`search_path\` is pinned, so Better Auth's tables cannot collide with
9277
+ * the application's.
9278
+ */
9279
+ export const authDb = database.schema<Record<string, never>, 'AuthDb'>('AuthDb');
9280
+ `
9281
+ });
9282
+ files$1.push({
9283
+ path: "constructs/auth.ts",
9284
+ content: `import { BetterAuth } from '@geekmidas/constructs/auth';
9285
+ import { authDb } from './database.ts';
9286
+
9287
+ /**
9288
+ * The auth server.
9289
+ *
9290
+ * There is no \`src/index.ts\` to go with this, and that is the point: the
9291
+ * routes are a wildcard, so no glob finds them and the build generates the
9292
+ * entry from this declaration instead. CORS, the trusted origins and the
9293
+ * cookie domain come from whatever declared an edge to it — nobody writes an
9294
+ * origin down.
9295
+ */
9296
+ export const auth = new BetterAuth('Auth', {
9297
+ database: authDb,
9298
+ basePath: '/api/auth',
9299
+ });
9300
+ `
9301
+ });
9302
+ files$1.push({
9303
+ path: "constructs/api.ts",
9304
+ content: `import { RestApi } from '@geekmidas/constructs/rest-api';
9305
+ import { auth } from './auth.ts';
9306
+ import { logger } from './logger.ts';
9307
+
9308
+ /**
9309
+ * The application's HTTP surface — one RestApi, one container.
9310
+ *
9311
+ * No \`app\`: \`Api\` means \`apps/api\`, which the id already said. The
9312
+ * \`code\` glob is here only because this scaffold puts its endpoints under
9313
+ * \`src/\`, where the conventional layout has them at the app root.
9314
+ */
9315
+ export const api = new RestApi('Api', {
9316
+ // Typed out rather than omitted: an API that ships open because a field was
9317
+ // left off is the one default worth refusing to have.
9318
+ defaultAuthorizer: 'none',
9319
+
9320
+ // The actual logger, not a path to one.
9321
+ logger,
9322
+
9323
+ app: {
9324
+ code: './src/{endpoints,functions,crons,queues,topics,subscribers}/**/*.ts',
9325
+ },
9326
+ }).auth(auth);
9327
+ `
9328
+ });
9329
+ const variant = frontendFramework === "tanstack-start" ? "{ variant: 'tanstack' }" : frontendFramework === "expo" ? void 0 : "{ variant: 'next' }";
9330
+ if (variant !== void 0) files$1.push({
9331
+ path: "constructs/site.ts",
9332
+ content: `import { StaticSite } from '@geekmidas/constructs/site';
9333
+ import { api } from './api.ts';
9334
+ import { auth } from './auth.ts';
9335
+
9336
+ /**
9337
+ * The frontend — a construct like any other, which is what makes it an app.
9338
+ *
9339
+ * No \`path\`: \`Web\` means \`apps/web\`. \`.dependsOn()\` is the single fact
9340
+ * behind four things that are hand-maintained otherwise: this site's
9341
+ * build-time API URL, the API's CORS origins, the auth server's trusted
9342
+ * origins, and which generated client lands here.
9343
+ */
9344
+ export const web = new StaticSite('Web', ${variant}).dependsOn([api, auth]);
9345
+ `
9346
+ });
9347
+ if (services.storage) {
9348
+ const bucket = storageFor(name$1);
9349
+ files$1.push({
9350
+ path: "constructs/storage.ts",
9351
+ content: `import { ObjectStorage } from '@geekmidas/constructs/object-storage';
9352
+
9353
+ /** A bucket — MinIO locally, S3 deployed, one declaration for both. */
9354
+ export const uploads = new ObjectStorage('${bucket.id}');
9355
+ `
9356
+ });
9357
+ }
9358
+ if (services.mail) {
9359
+ const mail = emailFor(name$1);
9360
+ files$1.push({
9361
+ path: "constructs/email.ts",
9362
+ content: `import { Email } from '@geekmidas/constructs/email';
9363
+
9364
+ /** Outbound mail — Mailpit locally, SES deployed. */
9365
+ export const email = new Email('${mail.id}', { templates: {} });
9366
+ `
9367
+ });
9368
+ }
9369
+ if (services.cache) {
9370
+ const kv = cacheFor(name$1);
9371
+ files$1.push({
9372
+ path: "constructs/cache.ts",
9373
+ content: `import { Cache } from '@geekmidas/constructs/cache';
9374
+
9375
+ /**
9376
+ * A cache. Which backend serves it follows the deploy target — a table in the
9377
+ * database on a server, Upstash on AWS — so nothing here says where it lives.
9378
+ */
9379
+ export const cache = new Cache('${kv.id}');
9380
+ `
9381
+ });
9382
+ }
9383
+ return files$1;
9384
+ }
9421
9385
 
9422
9386
  //#endregion
9423
9387
  //#region src/init/templates/api.ts
@@ -9484,9 +9448,16 @@ export const logger = createLogger();
9484
9448
  }
9485
9449
  }
9486
9450
  };
9487
- const apiImport = routesStructure === "domain-based" ? "../../constructs/api.js" : "../constructs/api.js";
9451
+ /**
9452
+ * Where a file at the app's `src/` root reaches a construct.
9453
+ *
9454
+ * A workspace keeps them at its own root, so the app goes through the
9455
+ * `@<name>/constructs/*` alias rather than climbing out with `../../`.
9456
+ */
9457
+ const constructsImport = (file) => monorepo ? `@${name$1}/constructs/${file}.ts` : `./constructs/${file}.ts`;
9458
+ const apiImport = monorepo ? `@${name$1}/constructs/api.ts` : routesStructure === "domain-based" ? "../../constructs/api.js" : "../constructs/api.js";
9488
9459
  const files$1 = [
9489
- {
9460
+ ...declares ? [{
9490
9461
  path: "src/constructs/api.ts",
9491
9462
  content: `import { RestApi } from '@geekmidas/constructs/rest-api';
9492
9463
  import { logger } from '../config/logger.ts';
@@ -9501,7 +9472,7 @@ export const api = new RestApi('Api', {
9501
9472
  logger,
9502
9473
  });
9503
9474
  `
9504
- },
9475
+ }] : [],
9505
9476
  {
9506
9477
  path: "src/config/env.ts",
9507
9478
  content: `import { Credentials } from '@geekmidas/envkit/credentials';
@@ -9676,8 +9647,8 @@ export const authService = {
9676
9647
  files$1.push({
9677
9648
  path: "src/router.ts",
9678
9649
  content: `import { UnauthorizedError } from '@geekmidas/errors';
9679
- import { api } from './constructs/api.ts';${options.database ? `
9680
- import { database } from './constructs/database.ts';` : ""}
9650
+ import { api } from '${constructsImport("api")}';${options.database ? `
9651
+ import { database } from '${constructsImport("database")}';` : ""}
9681
9652
  import { authService, type Session } from './services/auth.ts';
9682
9653
  import { logger } from './config/logger.ts';
9683
9654
 
@@ -9724,8 +9695,8 @@ export const profileEndpoint = sessionRouter
9724
9695
  }
9725
9696
  if (!monorepo) files$1.push({
9726
9697
  path: "src/router.ts",
9727
- content: `import { api } from './constructs/api.ts';${options.database ? `
9728
- import { database } from './constructs/database.ts';` : ""}
9698
+ content: `import { api } from '${constructsImport("api")}';${options.database ? `
9699
+ import { database } from '${constructsImport("database")}';` : ""}
9729
9700
 
9730
9701
  /**
9731
9702
  * The shared endpoint factory.
@@ -13211,7 +13182,11 @@ async function initCommand(projectName, options = {}) {
13211
13182
  ...isMonorepo$1 ? [] : generateDockerFiles(templateOptions, baseTemplate, dbApps)
13212
13183
  ] : [];
13213
13184
  const dockerFiles = isMonorepo$1 && baseTemplate ? generateDockerFiles(templateOptions, baseTemplate, dbApps) : [];
13214
- const rootFiles = baseTemplate ? [...generateMonorepoFiles(templateOptions, baseTemplate), ...generateModelsPackage(templateOptions)] : [];
13185
+ const rootFiles = baseTemplate ? [
13186
+ ...generateMonorepoFiles(templateOptions, baseTemplate),
13187
+ ...generateRootConstructs(templateOptions),
13188
+ ...generateModelsPackage(templateOptions)
13189
+ ] : [];
13215
13190
  const webAppFiles = isFullstack ? frontendFramework === "tanstack-start" ? generateTanStackWebFiles(templateOptions) : frontendFramework === "expo" ? generateExpoAppFiles(templateOptions) : generateWebAppFiles(templateOptions) : [];
13216
13191
  const authAppFiles = isFullstack ? generateAuthAppFiles(templateOptions) : [];
13217
13192
  const uiPackageFiles = isFullstack ? generateUiPackageFiles(templateOptions) : [];