@geekmidas/cli 10.0.0-alpha.2 → 10.0.0-alpha.3

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/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 = "10.0.0-alpha.1";
46
+ var version = "10.0.0-alpha.2";
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";
@@ -7342,132 +7342,16 @@ function printStateDetails(state) {
7342
7342
  }
7343
7343
  }
7344
7344
 
7345
- //#endregion
7346
- //#region src/init/versions.ts
7347
- const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
7348
- function loadPackageJson() {
7349
- try {
7350
- return require$1("../package.json");
7351
- } catch {
7352
- return require$1("../../package.json");
7353
- }
7354
- }
7355
- const pkg = loadPackageJson();
7356
- /**
7357
- * CLI version resolved from package.json at runtime
7358
- */
7359
- const CLI_VERSION = `~${pkg.version}`;
7360
- /**
7361
- * Package versions for @geekmidas packages
7362
- *
7363
- * AUTO-GENERATED (except CLI) - Do not edit manually
7364
- * Run: pnpm --filter @geekmidas/cli sync-versions
7365
- */
7366
- const GEEKMIDAS_VERSIONS = {
7367
- "@geekmidas/audit": "~10.0.0-alpha.1",
7368
- "@geekmidas/auth": "~10.0.0-alpha.1",
7369
- "@geekmidas/cache": "~10.0.0-alpha.1",
7370
- "@geekmidas/client": "~10.0.0-alpha.1",
7371
- "@geekmidas/cloud": "~10.0.0-alpha.1",
7372
- "@geekmidas/constructs": "~10.0.0-alpha.1",
7373
- "@geekmidas/db": "~10.0.0-alpha.1",
7374
- "@geekmidas/emailkit": "~10.0.0-alpha.1",
7375
- "@geekmidas/envkit": "~10.0.0-alpha.1",
7376
- "@geekmidas/errors": "~10.0.0-alpha.1",
7377
- "@geekmidas/events": "~10.0.0-alpha.1",
7378
- "@geekmidas/logger": "~10.0.0-alpha.1",
7379
- "@geekmidas/manifest": "~10.0.0-alpha.1",
7380
- "@geekmidas/rate-limit": "~10.0.0-alpha.1",
7381
- "@geekmidas/schema": "~10.0.0-alpha.1",
7382
- "@geekmidas/services": "~10.0.0-alpha.1",
7383
- "@geekmidas/storage": "~10.0.0-alpha.1",
7384
- "@geekmidas/studio": "~10.0.0-alpha.1",
7385
- "@geekmidas/telescope": "~10.0.0-alpha.1",
7386
- "@geekmidas/testkit": "~10.0.0-alpha.1",
7387
- "@geekmidas/cli": CLI_VERSION
7388
- };
7389
-
7390
- //#endregion
7391
- //#region src/init/generators/auth.ts
7392
- /**
7393
- * Generate auth app files for fullstack template
7394
- * Uses better-auth with magic link authentication
7395
- */
7396
- function generateAuthAppFiles(options) {
7397
- if (!options.monorepo || options.template !== "fullstack") return [];
7398
- const packageName = `@${options.name}/auth`;
7399
- const modelsPackage = `@${options.name}/models`;
7400
- const packageJson = {
7401
- name: packageName,
7402
- version: "0.0.1",
7403
- private: true,
7404
- type: "module",
7405
- scripts: {
7406
- dev: "gkm dev --entry ./src/index.ts",
7407
- build: "tsc",
7408
- start: "node dist/index.js",
7409
- typecheck: "tsc --noEmit",
7410
- "db:migrate": "gkm exec -- npx @better-auth/cli migrate",
7411
- "db:generate": "gkm exec -- npx @better-auth/cli generate"
7412
- },
7413
- dependencies: {
7414
- [modelsPackage]: "workspace:*",
7415
- "@geekmidas/envkit": GEEKMIDAS_VERSIONS["@geekmidas/envkit"],
7416
- "@geekmidas/logger": GEEKMIDAS_VERSIONS["@geekmidas/logger"],
7417
- "@hono/node-server": "~1.13.0",
7418
- "better-auth": "~1.2.0",
7419
- hono: "~4.8.0",
7420
- kysely: "~0.27.0",
7421
- pg: "~8.13.0"
7422
- },
7423
- devDependencies: {
7424
- "@geekmidas/cli": GEEKMIDAS_VERSIONS["@geekmidas/cli"],
7425
- "@types/node": "~22.0.0",
7426
- "@types/pg": "~8.11.0",
7427
- tsx: "~4.20.0",
7428
- typescript: "~5.8.2"
7429
- }
7430
- };
7431
- const tsConfig = {
7432
- extends: "../../tsconfig.json",
7433
- compilerOptions: {
7434
- noEmit: true,
7435
- allowImportingTsExtensions: true,
7436
- baseUrl: ".",
7437
- paths: {
7438
- "~/*": ["./src/*"],
7439
- [`@${options.name}/*`]: ["../../packages/*/src"]
7440
- }
7441
- },
7442
- include: ["src/**/*.ts"],
7443
- exclude: ["node_modules", "dist"]
7444
- };
7445
- const gitignore = `node_modules/
7446
- dist/
7447
- .env.local
7448
- *.log
7449
- `;
7450
- return [
7451
- {
7452
- path: "apps/auth/package.json",
7453
- content: `${JSON.stringify(packageJson, null, 2)}\n`
7454
- },
7455
- {
7456
- path: "apps/auth/tsconfig.json",
7457
- content: `${JSON.stringify(tsConfig, null, 2)}\n`
7458
- },
7459
- {
7460
- path: "apps/auth/.gitignore",
7461
- content: gitignore
7462
- }
7463
- ];
7464
- }
7465
-
7466
7345
  //#endregion
7467
7346
  //#region src/init/constructs.ts
7468
7347
  /** The glob every generated config points at. One glob, every kind. */
7469
7348
  const CONSTRUCTS_GLOB = "./src/constructs/**/*.ts";
7470
7349
  /**
7350
+ * Where a workspace keeps its constructs: at the root, beside the apps that
7351
+ * share them, rather than inside any one of them.
7352
+ */
7353
+ const WORKSPACE_CONSTRUCTS_GLOB = "./constructs/**/*.ts";
7354
+ /**
7471
7355
  * The database a project named `name` declares.
7472
7356
  *
7473
7357
  * Named after the project rather than `Db`, so two apps in one workspace can
@@ -7577,6 +7461,458 @@ export async function down(db: Kysely<unknown>): Promise<void> {
7577
7461
  }];
7578
7462
  }
7579
7463
 
7464
+ //#endregion
7465
+ //#region src/init/generators/agents.ts
7466
+ /**
7467
+ * `AGENTS.md` and `CLAUDE.md` for a scaffolded project.
7468
+ *
7469
+ * A generated project is the first thing an agent sees, and without this it
7470
+ * sees only the output: a `gkm.config.ts` naming three keys, a `constructs/`
7471
+ * directory, and a build step that reads both. None of that says what the
7472
+ * shape *is*, so an agent reconstructs it from the framework it recognises —
7473
+ * and writes an Express app beside a `RestApi`, or restates in config what a
7474
+ * construct already declared, which is the exact mistake v10 exists to make
7475
+ * impossible.
7476
+ *
7477
+ * Instructions live in `AGENTS.md` because that is the file every tool reads.
7478
+ * `CLAUDE.md` points at it rather than copying it: two files saying the same
7479
+ * thing is two files to keep in step, and the copy that drifts is always the
7480
+ * one nobody opened.
7481
+ *
7482
+ * Content is derived from the same `TemplateOptions` the rest of the scaffold
7483
+ * is built from, so a project with no database gets no database section, and a
7484
+ * worker gets no endpoint guide. A guide that documents what was not generated
7485
+ * teaches the reader to distrust it.
7486
+ */
7487
+ function generateAgentFiles(options, template) {
7488
+ return [{
7489
+ path: "AGENTS.md",
7490
+ content: agentsContent(options, template)
7491
+ }, {
7492
+ path: "CLAUDE.md",
7493
+ content: claudeContent()
7494
+ }];
7495
+ }
7496
+ /**
7497
+ * The pointer.
7498
+ *
7499
+ * Deliberately short and deliberately not a summary — a summary is a second
7500
+ * copy of the conventions that ages independently of the first.
7501
+ */
7502
+ function claudeContent() {
7503
+ return `# CLAUDE.md
7504
+
7505
+ The conventions for this project live in [AGENTS.md](./AGENTS.md).
7506
+
7507
+ Read that file before writing code here. It is the single copy, kept that way
7508
+ on purpose: anything repeated here would be a second thing to keep in step, and
7509
+ the stale one is always the copy nobody opened.
7510
+ `;
7511
+ }
7512
+ function agentsContent(options, template) {
7513
+ const { name: name$1, monorepo, database, telescope, studio, packageManager, services } = options;
7514
+ const constructsGlob = monorepo ? WORKSPACE_CONSTRUCTS_GLOB : CONSTRUCTS_GLOB;
7515
+ const isWorker = template.name === "worker";
7516
+ const isServerless = template.name === "serverless";
7517
+ const run = packageManager === "npm" ? "npx" : `${packageManager} exec`;
7518
+ const sections = [];
7519
+ sections.push(`# Agent conventions — ${name$1}
7520
+
7521
+ Rules for anyone, human or agent, writing code in this project. Built with
7522
+ [\`@geekmidas/toolbox\`](https://github.com/geekmidas/toolbox).
7523
+
7524
+ Read this before adding a file. Most of what follows exists because the obvious
7525
+ approach from another framework produces something that compiles, runs, and is
7526
+ wrong in a way nothing catches.`);
7527
+ sections.push(`## The one idea
7528
+
7529
+ **Constructs declare; config does not restate.**
7530
+
7531
+ A construct — a \`RestApi\`, a database, a bucket, a topic — is the single
7532
+ declaration of a thing. The build reads those declarations and derives
7533
+ everything downstream from them: which containers exist, which apps get built,
7534
+ what the OpenAPI spec says, which env vars a process needs.
7535
+
7536
+ \`gkm.config.ts\` holds only what no construct can answer:
7537
+
7538
+ \`\`\`typescript
7539
+ export default defineWorkspace({
7540
+ name: '${name$1}',
7541
+ constructs: '${constructsGlob}',
7542
+ secrets: { enabled: true },
7543
+ });
7544
+ \`\`\`
7545
+
7546
+ If you find yourself adding a key to config that names something already
7547
+ declared in a construct — a path, a port, a route, a container — stop. That is
7548
+ the drift this design removes. The second copy is the one that goes wrong.`);
7549
+ sections.push(`## Layout
7550
+
7551
+ \`\`\`
7552
+ ${layoutBlock(options, template)}
7553
+ \`\`\`
7554
+
7555
+ Handlers are found by **one glob**, and what kind a file exports is decided by
7556
+ the value it exports, not by the directory it sits in.`);
7557
+ sections.push(`## Commands
7558
+
7559
+ \`\`\`bash
7560
+ ${run} gkm dev # dev server, hot reload, services up, secrets injected
7561
+ ${run} gkm build # production build
7562
+ ${run} gkm test # tests, with secrets injected
7563
+ ${run} gkm exec -- <cmd> # run any command with secrets injected
7564
+ ${run} gkm openapi # regenerate the OpenAPI spec
7565
+ \`\`\`
7566
+
7567
+ Secrets are encrypted at rest and injected at run time:
7568
+
7569
+ \`\`\`bash
7570
+ ${run} gkm secrets:set DATABASE_URL postgres://...
7571
+ ${run} gkm secrets:show
7572
+ \`\`\`
7573
+
7574
+ **Never run a tool that needs project env vars directly.** It will see an empty
7575
+ environment and fail in a way that looks like a config bug. Go through
7576
+ \`gkm exec --\`, which is what injects them.`);
7577
+ if (!isWorker) sections.push(endpointSection(options));
7578
+ if (isWorker || isServerless || services.events) sections.push(backgroundSection(template));
7579
+ if (database) sections.push(databaseSection());
7580
+ sections.push(`## Environment
7581
+
7582
+ Environment is parsed once, through \`envkit\`, and never read from
7583
+ \`process.env\` directly:
7584
+
7585
+ \`\`\`typescript
7586
+ import { EnvironmentParser } from '@geekmidas/envkit';
7587
+ import { Credentials } from '@geekmidas/envkit/credentials';
7588
+
7589
+ export const envParser = new EnvironmentParser({
7590
+ ...process.env,
7591
+ ...Credentials,
7592
+ });
7593
+
7594
+ export const config = envParser
7595
+ .create((get) => ({
7596
+ port: get('PORT').string().transform(Number).default(3000),
7597
+ }))
7598
+ .parse();
7599
+ \`\`\`
7600
+
7601
+ \`Credentials\` is what \`gkm dev\` and \`gkm exec\` inject. A bare
7602
+ \`process.env.FOO\` bypasses both the decryption and the validation, so it reads
7603
+ as \`undefined\` in exactly the environments that matter.`);
7604
+ sections.push(conventionsSection());
7605
+ sections.push(testingSection(database));
7606
+ if (telescope || studio) {
7607
+ const tools = [telescope && "**Telescope** — request and exception monitoring", studio && "**Studio** — dev dashboard and database browser"].filter(Boolean);
7608
+ sections.push(`## Dev tools
7609
+
7610
+ ${tools.map((t) => `- ${t}`).join("\n")}
7611
+
7612
+ Both are derived from declared constructs. Neither needs wiring up by hand.`);
7613
+ }
7614
+ sections.push(`## Before you say it works
7615
+
7616
+ \`\`\`bash
7617
+ ${run} gkm build
7618
+ \`\`\`
7619
+
7620
+ A build is the only thing that proves the manifest still resolves. Code that
7621
+ typechecks can still declare two constructs with one id, or a handler no glob
7622
+ reaches — and neither shows up until something reads the graph.`);
7623
+ return `${sections.join("\n\n")}\n`;
7624
+ }
7625
+ function layoutBlock(options, template) {
7626
+ const { monorepo, apiPath, database } = options;
7627
+ const isWorker = template.name === "worker";
7628
+ if (monorepo) return `constructs/ # every construct: the surface, the database, topics
7629
+ ${apiPath}/ # the API app
7630
+ gkm.config.ts # name, constructs glob, secrets`;
7631
+ const lines = ["src/constructs/ # the surface, and anything it declares", "src/config/ # env parser, logger"];
7632
+ if (!isWorker) lines.push("src/endpoints/ # HTTP handlers");
7633
+ if (isWorker) {
7634
+ lines.push("src/crons/ # scheduled work");
7635
+ lines.push("src/subscribers/ # topic consumers");
7636
+ }
7637
+ if (database) lines.push("src/db/ # migrations, schema");
7638
+ lines.push("gkm.config.ts # name, constructs glob, secrets");
7639
+ return lines.join("\n");
7640
+ }
7641
+ function endpointSection(options) {
7642
+ const { database } = options;
7643
+ return `## Adding an endpoint
7644
+
7645
+ An endpoint is built **from the surface that serves it**. That is where its
7646
+ logger, environment parser and authorizers come from, so none of them is passed
7647
+ per endpoint:
7648
+
7649
+ \`\`\`typescript
7650
+ import { z } from 'zod';
7651
+ import { router } from '../constructs/router.ts';
7652
+
7653
+ export const createUser = router
7654
+ .post('/users')
7655
+ .body(z.object({ name: z.string(), email: z.email() }))
7656
+ .output(z.object({ id: z.uuid() }))
7657
+ .handle(async ({ body, logger${database ? ", services" : ""} }) => {
7658
+ logger.info({ name: body.name }, 'creating user');
7659
+ ${database ? ` const user = await services.database
7660
+ .insertInto('users')
7661
+ .values({ name: body.name, email: body.email })
7662
+ .returningAll()
7663
+ .executeTakeFirstOrThrow();
7664
+
7665
+ return { id: user.id };` : ` return { id: crypto.randomUUID() };`}
7666
+ });
7667
+ \`\`\`
7668
+
7669
+ **Export it.** An endpoint that is never exported is never found — the glob
7670
+ loads the module and filters by value, so a handler assigned to a local
7671
+ \`const\` simply does not exist as far as the build is concerned.
7672
+
7673
+ **Do not write an HTTP server.** No \`express()\`, no \`new Hono()\`, no
7674
+ \`app.listen\`. The entry is generated from the surface; a hand-written server
7675
+ beside it is a second app that shadows the real one.
7676
+
7677
+ ### Branching the factory
7678
+
7679
+ Share what a *group* of endpoints needs by branching once, in its own file:
7680
+
7681
+ \`\`\`typescript
7682
+ export const router = api.endpoints${database ? ".database(database)" : ""};
7683
+ export const sessionRouter = router.session(/* … */);
7684
+ \`\`\`
7685
+
7686
+ Branch for a group, never for a single endpoint — a one-endpoint branch is
7687
+ indirection with nothing on the other side of it.`;
7688
+ }
7689
+ function backgroundSection(template) {
7690
+ const isWorker = template.name === "worker";
7691
+ return `## Background work
7692
+
7693
+ Crons, subscribers and functions are declared the same way endpoints are: as
7694
+ exported values the build discovers.
7695
+
7696
+ \`\`\`typescript
7697
+ // a scheduled job
7698
+ import { c } from '@geekmidas/constructs/crons';
7699
+
7700
+ export const cleanup = c
7701
+ .schedule('rate(1 day)')
7702
+ .handle(async ({ logger }) => {
7703
+ logger.info('cleaning up');
7704
+ });
7705
+ \`\`\`
7706
+
7707
+ \`\`\`typescript
7708
+ // a topic subscriber
7709
+ import { s } from '@geekmidas/constructs/subscribers';
7710
+ import { userEvents } from '../constructs/topics.ts';
7711
+
7712
+ export const onUserCreated = s
7713
+ .topic(userEvents)
7714
+ .subscribe(['user.created'])
7715
+ .handle(async ({ events, logger }) => {
7716
+ logger.info({ count: events.length }, 'handling user events');
7717
+ });
7718
+ \`\`\`
7719
+
7720
+ Handlers receive a **batch**, not one event. Both transports deliver in
7721
+ batches, so a per-event round trip is a round trip per event for no reason.
7722
+
7723
+ ${isWorker ? `This project is background work and nothing else — there is no HTTP surface
7724
+ to add routes to.` : `Declaring a topic is what makes the broker exist. Nothing lists it in config.`}`;
7725
+ }
7726
+ function databaseSection() {
7727
+ return `## Database
7728
+
7729
+ The database is a **construct**, not a hand-rolled service. Declaring it is what
7730
+ makes a Postgres exist locally and a database exist on deploy — nothing names
7731
+ \`postgres\` in config.
7732
+
7733
+ An endpoint reaches it by declaring the dependency, and gets it typed:
7734
+
7735
+ \`\`\`typescript
7736
+ export const listUsers = router
7737
+ .get('/users')
7738
+ .output(z.array(z.object({ id: z.uuid() })))
7739
+ .handle(async ({ services }) => {
7740
+ return services.database.selectFrom('users').selectAll().execute();
7741
+ });
7742
+ \`\`\`
7743
+
7744
+ Queries go through Kysely. Never open your own connection pool — the one the
7745
+ construct provides is the one that gets credentials, pooling and shutdown.`;
7746
+ }
7747
+ function conventionsSection() {
7748
+ return `## Conventions
7749
+
7750
+ **Zod formats are top-level schemas.**
7751
+
7752
+ \`\`\`typescript
7753
+ // yes
7754
+ z.email()
7755
+ z.url()
7756
+ z.uuid()
7757
+
7758
+ // no
7759
+ z.string().email()
7760
+ z.string().url()
7761
+ \`\`\`
7762
+
7763
+ Zod 4 made each format a schema in its own right. The chained form still runs,
7764
+ but it types as a \`ZodString\` carrying a check, so it cannot be composed or
7765
+ narrowed — and it emits different JSON Schema, which means a published API
7766
+ contract would depend on which spelling someone reached for.
7767
+
7768
+ \`envkit\` is not affected: \`get('ADMIN_EMAIL').string().email()\` is its own
7769
+ builder, not Zod's. Leave it alone.
7770
+
7771
+ **Style.** Two-space indent, single quotes, semicolons, trailing commas, 80
7772
+ columns. \`import type\` for type-only imports. Run the formatter rather than
7773
+ matching it by hand.
7774
+
7775
+ **Construct ids are unique.** Two constructs sharing an id fails discovery for
7776
+ the whole project, not just the second one.`;
7777
+ }
7778
+ function testingSection(database) {
7779
+ return `## Testing
7780
+
7781
+ **Integration over unit.** Prefer the real dependency to a mock — a real
7782
+ database, a real cache. Mocks are for things you genuinely cannot run:
7783
+ the filesystem, the clock, external HTTP (use MSW for that).
7784
+
7785
+ **Test behaviour, not implementation.** Assert what the code did, not which
7786
+ functions it called on the way.
7787
+
7788
+ \`\`\`bash
7789
+ ${database ? "gkm test # starts services, injects secrets, then runs vitest" : "gkm test"}
7790
+ \`\`\`
7791
+
7792
+ Run tests through \`gkm test\`, not \`vitest\` directly${database ? " — it is what starts the database and injects the secrets the suite needs" : ""}.`;
7793
+ }
7794
+
7795
+ //#endregion
7796
+ //#region src/init/versions.ts
7797
+ const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
7798
+ function loadPackageJson() {
7799
+ try {
7800
+ return require$1("../package.json");
7801
+ } catch {
7802
+ return require$1("../../package.json");
7803
+ }
7804
+ }
7805
+ const pkg = loadPackageJson();
7806
+ /**
7807
+ * CLI version resolved from package.json at runtime
7808
+ */
7809
+ const CLI_VERSION = `~${pkg.version}`;
7810
+ /**
7811
+ * Package versions for @geekmidas packages
7812
+ *
7813
+ * AUTO-GENERATED (except CLI) - Do not edit manually
7814
+ * Run: pnpm --filter @geekmidas/cli sync-versions
7815
+ */
7816
+ const GEEKMIDAS_VERSIONS = {
7817
+ "@geekmidas/audit": "~10.0.0-alpha.2",
7818
+ "@geekmidas/auth": "~10.0.0-alpha.2",
7819
+ "@geekmidas/cache": "~10.0.0-alpha.2",
7820
+ "@geekmidas/client": "~10.0.0-alpha.2",
7821
+ "@geekmidas/cloud": "~10.0.0-alpha.2",
7822
+ "@geekmidas/constructs": "~10.0.0-alpha.2",
7823
+ "@geekmidas/db": "~10.0.0-alpha.2",
7824
+ "@geekmidas/emailkit": "~10.0.0-alpha.2",
7825
+ "@geekmidas/envkit": "~10.0.0-alpha.2",
7826
+ "@geekmidas/errors": "~10.0.0-alpha.2",
7827
+ "@geekmidas/events": "~10.0.0-alpha.2",
7828
+ "@geekmidas/logger": "~10.0.0-alpha.2",
7829
+ "@geekmidas/manifest": "~10.0.0-alpha.2",
7830
+ "@geekmidas/rate-limit": "~10.0.0-alpha.2",
7831
+ "@geekmidas/schema": "~10.0.0-alpha.2",
7832
+ "@geekmidas/services": "~10.0.0-alpha.2",
7833
+ "@geekmidas/storage": "~10.0.0-alpha.2",
7834
+ "@geekmidas/studio": "~10.0.0-alpha.2",
7835
+ "@geekmidas/telescope": "~10.0.0-alpha.2",
7836
+ "@geekmidas/testkit": "~10.0.0-alpha.2",
7837
+ "@geekmidas/cli": CLI_VERSION
7838
+ };
7839
+
7840
+ //#endregion
7841
+ //#region src/init/generators/auth.ts
7842
+ /**
7843
+ * Generate auth app files for fullstack template
7844
+ * Uses better-auth with magic link authentication
7845
+ */
7846
+ function generateAuthAppFiles(options) {
7847
+ if (!options.monorepo || options.template !== "fullstack") return [];
7848
+ const packageName = `@${options.name}/auth`;
7849
+ const modelsPackage = `@${options.name}/models`;
7850
+ const packageJson = {
7851
+ name: packageName,
7852
+ version: "0.0.1",
7853
+ private: true,
7854
+ type: "module",
7855
+ scripts: {
7856
+ dev: "gkm dev --entry ./src/index.ts",
7857
+ build: "tsc",
7858
+ start: "node dist/index.js",
7859
+ typecheck: "tsc --noEmit",
7860
+ "db:migrate": "gkm exec -- npx @better-auth/cli migrate",
7861
+ "db:generate": "gkm exec -- npx @better-auth/cli generate"
7862
+ },
7863
+ dependencies: {
7864
+ [modelsPackage]: "workspace:*",
7865
+ "@geekmidas/envkit": GEEKMIDAS_VERSIONS["@geekmidas/envkit"],
7866
+ "@geekmidas/logger": GEEKMIDAS_VERSIONS["@geekmidas/logger"],
7867
+ "@hono/node-server": "~1.13.0",
7868
+ "better-auth": "~1.2.0",
7869
+ hono: "~4.8.0",
7870
+ kysely: "~0.27.0",
7871
+ pg: "~8.13.0"
7872
+ },
7873
+ devDependencies: {
7874
+ "@geekmidas/cli": GEEKMIDAS_VERSIONS["@geekmidas/cli"],
7875
+ "@types/node": "~22.0.0",
7876
+ "@types/pg": "~8.11.0",
7877
+ tsx: "~4.20.0",
7878
+ typescript: "~5.8.2"
7879
+ }
7880
+ };
7881
+ const tsConfig = {
7882
+ extends: "../../tsconfig.json",
7883
+ compilerOptions: {
7884
+ noEmit: true,
7885
+ allowImportingTsExtensions: true,
7886
+ baseUrl: ".",
7887
+ paths: {
7888
+ "~/*": ["./src/*"],
7889
+ [`@${options.name}/*`]: ["../../packages/*/src"]
7890
+ }
7891
+ },
7892
+ include: ["src/**/*.ts"],
7893
+ exclude: ["node_modules", "dist"]
7894
+ };
7895
+ const gitignore = `node_modules/
7896
+ dist/
7897
+ .env.local
7898
+ *.log
7899
+ `;
7900
+ return [
7901
+ {
7902
+ path: "apps/auth/package.json",
7903
+ content: `${JSON.stringify(packageJson, null, 2)}\n`
7904
+ },
7905
+ {
7906
+ path: "apps/auth/tsconfig.json",
7907
+ content: `${JSON.stringify(tsConfig, null, 2)}\n`
7908
+ },
7909
+ {
7910
+ path: "apps/auth/.gitignore",
7911
+ content: gitignore
7912
+ }
7913
+ ];
7914
+ }
7915
+
7580
7916
  //#endregion
7581
7917
  //#region src/init/generators/config.ts
7582
7918
  /**
@@ -9199,7 +9535,7 @@ export default defineWorkspace({
9199
9535
  // declared bucket is why MinIO does, a declared topic is why a broker does —
9200
9536
  // none of it listed here. It is also where the apps come from: a
9201
9537
  // \`StaticSite\` is an app, and so is every \`RestApi\`.
9202
- constructs: './constructs/**/*.ts',
9538
+ constructs: '${WORKSPACE_CONSTRUCTS_GLOB}',
9203
9539
 
9204
9540
  secrets: {
9205
9541
  enabled: true,
@@ -13183,6 +13519,7 @@ async function initCommand(projectName, options = {}) {
13183
13519
  ] : [];
13184
13520
  const dockerFiles = isMonorepo$1 && baseTemplate ? generateDockerFiles(templateOptions, baseTemplate, dbApps) : [];
13185
13521
  const rootFiles = baseTemplate ? [
13522
+ ...generateAgentFiles(templateOptions, baseTemplate),
13186
13523
  ...generateMonorepoFiles(templateOptions, baseTemplate),
13187
13524
  ...generateRootConstructs(templateOptions),
13188
13525
  ...generateModelsPackage(templateOptions)