create-newt-app 0.34.1 → 0.35.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/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import { existsSync, promises } from "fs";
11
11
  import path from "path";
12
12
  import https from "node:https";
13
13
  //#region package.json
14
- var version = "0.34.1";
14
+ var version = "0.35.1";
15
15
  var engines = { "node": ">=24.0.0" };
16
16
  //#endregion
17
17
  //#region src/templates/root/index.ts
@@ -166,7 +166,7 @@ allowBuilds:
166
166
  filename: "README.md",
167
167
  template: `# <%= projectName %>
168
168
 
169
- Full-stack monorepo: Next.js 16<% if (nest !== 'off') { %> + NestJS 11<% } %> + better-auth + <%= database === 'postgres' ? 'Postgres' : 'SQLite' %>.
169
+ Full-stack monorepo: Next.js 16<% if (nest !== 'off') { %> + NestJS 12<% } %> + better-auth + <%= database === 'postgres' ? 'Postgres' : 'SQLite' %>.
170
170
 
171
171
  ## Quick start
172
172
 
@@ -196,6 +196,10 @@ Open [http://localhost:3000](http://localhost:3000).
196
196
  - **\`@<%= projectName %>/eslint-config\`**: shared ESLint config
197
197
  <% } -%>
198
198
  - **\`@<%= projectName %>/typescript-config\`**: shared tsconfig
199
+
200
+ ## Formatting
201
+
202
+ \`pnpm format\` checks without modifying files and fails if any file is unformatted; \`pnpm format:fix\` applies formatting.
199
203
  `
200
204
  },
201
205
  {
@@ -220,7 +224,18 @@ BETTER_AUTH_SECRET=generate-with-openssl-rand-base64-32
220
224
  # This is NOT the Next.js you know
221
225
 
222
226
  This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in \`node_modules/next/dist/docs/\` before writing any code. Heed deprecation notices.
223
- <!-- END:nextjs-agent-rules --><% if (shadcn) { %>
227
+ <!-- END:nextjs-agent-rules -->
228
+
229
+ <!-- BEGIN:turborepo-agent-rules -->
230
+
231
+ # This is NOT the Turborepo you know
232
+
233
+ Turborepo configuration, task behavior, and CLI commands can vary between installed versions and may differ from your training data. Resolve the \`turbo\` package from this file's directory or relevant workspace; in monorepos, it may not be visible from the repository root. For example, run \`node -p "require.resolve('turbo/package.json')"\` from a workspace that depends on \`turbo\`.
234
+
235
+ Read \`docs/README.md\` inside that installed package first, then read the relevant pages from its \`docs/\` directory before changing Turborepo configuration or commands. Heed deprecation notices. These bundled docs match the installed package version and are available without network access.
236
+
237
+ This block is written and re-added by \`turbo\` before repository-scoped commands when an AI agent is detected. In the Turborepo source repository, its template is defined in \`crates/turborepo-cli/src/cli/agent_guidance.rs\`. Removing the managed block while updates are enabled means a later qualifying invocation will add it again. Set \`"agentGuidance": false\` in the root \`turbo.json\` or \`turbo.jsonc\` to opt out; this does not remove an existing block. Keep the block committed with your work to avoid an uncommitted change on the next agent invocation.
238
+ <!-- END:turborepo-agent-rules --><% if (shadcn) { %>
224
239
 
225
240
  After making changes, run \`pnpm lint:check\` and fix all errors.<% } %>`
226
241
  },
@@ -516,7 +531,7 @@ export default function Home() {
516
531
  <p className="mb-2 text-muted-foreground">Learn more</p>
517
532
  <ul className="list-disc list-inside space-y-2 mt-2">
518
533
  <li>
519
- <Link href="https://newt-app.com">Documentation</Link>
534
+ <Link href="https://newt-app.com">newt-app</Link>
520
535
  </li>
521
536
  <li>
522
537
  <Link href="https://github.com/zeevo/newt-app">GitHub</Link>
@@ -1489,13 +1504,13 @@ const versions = {
1489
1504
  "@babel/plugin-transform-class-properties": "^8.0.1",
1490
1505
  "@base-ui/react": "^1.6.0",
1491
1506
  "@eslint/js": "^9.39.1",
1492
- "@nestjs/cli": "^11.0.0",
1493
- "@nestjs/common": "^11.0.1",
1494
- "@nestjs/core": "^11.0.1",
1495
- "@nestjs/platform-express": "^11.0.1",
1496
- "@nestjs/schematics": "^11.0.0",
1497
- "@nestjs/serve-static": "^5.0.0",
1498
- "@nestjs/testing": "^11.0.1",
1507
+ "@nestjs/cli": "^12.0.7",
1508
+ "@nestjs/common": "^12.1.0",
1509
+ "@nestjs/core": "^12.1.0",
1510
+ "@nestjs/platform-express": "^12.1.0",
1511
+ "@nestjs/schematics": "^12.0.5",
1512
+ "@nestjs/serve-static": "^12.0.0",
1513
+ "@nestjs/testing": "^12.1.0",
1499
1514
  "@next/eslint-plugin-next": "^16.3.4",
1500
1515
  "@oxlint/plugins": "^1.74.0",
1501
1516
  "@shadcn/lint": "^0.1.0",
@@ -1507,7 +1522,7 @@ const versions = {
1507
1522
  "@tailwindcss/postcss": "^4.2.1",
1508
1523
  "@tanstack/react-form": "^1.28.5",
1509
1524
  "@tanstack/react-query": "^5.90.21",
1510
- "@thallesp/nestjs-better-auth": "^2.5.1",
1525
+ "@thallesp/nestjs-better-auth": "^2.8.0",
1511
1526
  "@types/better-sqlite3": "^7.6.13",
1512
1527
  "@types/express": "^5.0.0",
1513
1528
  "@types/jest": "^30.0.0",
@@ -1565,7 +1580,8 @@ const versions = {
1565
1580
  typescript: "6.0.2",
1566
1581
  "typescript-eslint": "^8.50.0",
1567
1582
  "unplugin-swc": "^1.5.9",
1568
- vitest: "^4.1.10"
1583
+ vitest: "^4.1.10",
1584
+ zod: "^4.6.5"
1569
1585
  };
1570
1586
  //#endregion
1571
1587
  //#region src/templates/shadcn-ui/index.ts
@@ -2018,7 +2034,7 @@ export default function Home() {
2018
2034
  <p className="mb-2 text-muted-foreground">Learn more</p>
2019
2035
  <ul className="list-disc list-inside space-y-2 mt-2">
2020
2036
  <li>
2021
- <Link href="https://newt-app.com">Documentation</Link>
2037
+ <Link href="https://newt-app.com">newt-app</Link>
2022
2038
  </li>
2023
2039
  <li>
2024
2040
  <Link href="https://github.com/zeevo/newt-app">GitHub</Link>
@@ -10314,7 +10330,7 @@ export default function Home() {
10314
10330
  <p {...stylex.props(styles.muted)}>Learn more</p>
10315
10331
  <ul {...stylex.props(styles.list)}>
10316
10332
  <li>
10317
- <Link href="https://newt-app.com">Documentation</Link>
10333
+ <Link href="https://newt-app.com">newt-app</Link>
10318
10334
  </li>
10319
10335
  <li>
10320
10336
  <Link href="https://github.com/zeevo/newt-app">GitHub</Link>
@@ -11017,12 +11033,12 @@ const eslintConfig = {
11017
11033
  {
11018
11034
  module: root$1,
11019
11035
  name: "format",
11020
- script: `prettier --write "**/*.{ts,tsx,js,jsx,json,md,yaml,yml}"`
11036
+ script: `prettier --check "**/*.{ts,tsx,js,jsx,json,md,yaml,yml}"`
11021
11037
  },
11022
11038
  {
11023
11039
  module: root$1,
11024
- name: "format:check",
11025
- script: `prettier --check "**/*.{ts,tsx,js,jsx,json,md,yaml,yml}"`
11040
+ name: "format:fix",
11041
+ script: `prettier --write "**/*.{ts,tsx,js,jsx,json,md,yaml,yml}"`
11026
11042
  }
11027
11043
  ]
11028
11044
  };
@@ -11124,12 +11140,12 @@ const oxc = {
11124
11140
  {
11125
11141
  module: root,
11126
11142
  name: "format",
11127
- script: "oxfmt"
11143
+ script: "oxfmt --check"
11128
11144
  },
11129
11145
  {
11130
11146
  module: root,
11131
- name: "format:check",
11132
- script: "oxfmt --check"
11147
+ name: "format:fix",
11148
+ script: "oxfmt"
11133
11149
  }
11134
11150
  ]
11135
11151
  };
@@ -11435,22 +11451,22 @@ module.exports = {
11435
11451
  {
11436
11452
  module: "apps/api",
11437
11453
  name: "test",
11438
- script: "jest"
11454
+ script: "NODE_OPTIONS=--experimental-vm-modules jest"
11439
11455
  },
11440
11456
  {
11441
11457
  module: "apps/api",
11442
11458
  name: "test:watch",
11443
- script: "jest --watch"
11459
+ script: "NODE_OPTIONS=--experimental-vm-modules jest --watch"
11444
11460
  },
11445
11461
  {
11446
11462
  module: "apps/api",
11447
11463
  name: "test:cov",
11448
- script: "jest --coverage"
11464
+ script: "NODE_OPTIONS=--experimental-vm-modules jest --coverage"
11449
11465
  },
11450
11466
  {
11451
11467
  module: "apps/api",
11452
11468
  name: "test:debug",
11453
- script: "node --inspect-brk node_modules/.bin/jest --runInBand"
11469
+ script: "node --inspect-brk --experimental-vm-modules node_modules/.bin/jest --runInBand"
11454
11470
  },
11455
11471
  {
11456
11472
  module: "apps/api",
@@ -11909,14 +11925,12 @@ import { NestFactory } from '@nestjs/core';
11909
11925
  import { AppModule } from '@<%= projectName %>/api';
11910
11926
  import type { INestApplicationContext, Type, Abstract } from '@nestjs/common';
11911
11927
 
11912
- let context: INestApplicationContext | null = null;
11928
+ let context: Promise<INestApplicationContext> | null = null;
11913
11929
 
11914
- export async function getContext(): Promise<INestApplicationContext> {
11915
- if (!context) {
11916
- context = await NestFactory.createApplicationContext(AppModule, {
11917
- logger: false,
11918
- });
11919
- }
11930
+ export function getContext(): Promise<INestApplicationContext> {
11931
+ context ??= NestFactory.createApplicationContext(AppModule, {
11932
+ logger: false,
11933
+ });
11920
11934
  return context;
11921
11935
  }
11922
11936
 
@@ -12271,12 +12285,14 @@ import { resolve } from 'path';
12271
12285
  dotenv.config({ path: resolve(process.cwd(), '../../.env') });
12272
12286
  dotenv.config({ path: resolve(process.cwd(), '.env') });
12273
12287
 
12288
+ import { StandardSchemaValidationPipe } from '@nestjs/common';
12274
12289
  import { NestFactory } from '@nestjs/core';
12275
12290
  import { AppModule } from './app.module';
12276
12291
 
12277
12292
  async function bootstrap() {
12278
12293
  const app = await NestFactory.create(AppModule, { bodyParser: false });
12279
12294
  app.setGlobalPrefix('api');
12295
+ app.useGlobalPipes(new StandardSchemaValidationPipe());
12280
12296
  app.enableCors({
12281
12297
  origin: process.env.CORS_ORIGIN ?? 'http://localhost:3000',
12282
12298
  credentials: true,
@@ -12505,6 +12521,7 @@ var todos_controller_default = {
12505
12521
  } from '@nestjs/common';
12506
12522
  import { Session } from '@thallesp/nestjs-better-auth';
12507
12523
  import type { UserSession } from '@thallesp/nestjs-better-auth';
12524
+ import { z } from 'zod';
12508
12525
  import { TodosService } from './todos.service';
12509
12526
 
12510
12527
  @Controller('todos')
@@ -12517,7 +12534,10 @@ export class TodosController {
12517
12534
  }
12518
12535
 
12519
12536
  @Post()
12520
- create(@Session() session: UserSession, @Body('title') title: string) {
12537
+ create(
12538
+ @Session() session: UserSession,
12539
+ @Body('title', { schema: z.string().trim().min(1) }) title: string,
12540
+ ) {
12521
12541
  return this.todosService.create(session.user.id, title);
12522
12542
  }
12523
12543
 
@@ -12633,6 +12653,7 @@ export async function POST(req: Request) {
12633
12653
  var web_todos_id_route_default = {
12634
12654
  filename: "apps/web/app/api/todos/[id]/route.ts",
12635
12655
  template: `import { NextResponse } from 'next/server';
12656
+ import { HttpException } from '@nestjs/common';
12636
12657
  import { headers } from 'next/headers';
12637
12658
  import { inject } from '@/lib/nest';
12638
12659
  import { auth } from '@<%= projectName %>/auth';
@@ -12643,8 +12664,15 @@ export async function DELETE(_req: Request, { params }: { params: Promise<{ id:
12643
12664
  if (!session) return new NextResponse('Unauthorized', { status: 401 });
12644
12665
  const { id } = await params;
12645
12666
  const todos = await inject(TodosService);
12646
- await todos.remove(session.user.id, id);
12647
- return new NextResponse(null, { status: 204 });
12667
+ try {
12668
+ await todos.remove(session.user.id, id);
12669
+ return new NextResponse(null, { status: 204 });
12670
+ } catch (err) {
12671
+ if (err instanceof HttpException) {
12672
+ return NextResponse.json(err.getResponse(), { status: err.getStatus() });
12673
+ }
12674
+ throw err;
12675
+ }
12648
12676
  }`
12649
12677
  };
12650
12678
  //#endregion
@@ -12652,6 +12680,7 @@ export async function DELETE(_req: Request, { params }: { params: Promise<{ id:
12652
12680
  var web_todos_toggle_route_default = {
12653
12681
  filename: "apps/web/app/api/todos/[id]/toggle/route.ts",
12654
12682
  template: `import { NextResponse } from 'next/server';
12683
+ import { HttpException } from '@nestjs/common';
12655
12684
  import { headers } from 'next/headers';
12656
12685
  import { inject } from '@/lib/nest';
12657
12686
  import { auth } from '@<%= projectName %>/auth';
@@ -12662,7 +12691,14 @@ export async function PATCH(_req: Request, { params }: { params: Promise<{ id: s
12662
12691
  if (!session) return new NextResponse('Unauthorized', { status: 401 });
12663
12692
  const { id } = await params;
12664
12693
  const todos = await inject(TodosService);
12665
- return NextResponse.json(await todos.toggle(session.user.id, id));
12694
+ try {
12695
+ return NextResponse.json(await todos.toggle(session.user.id, id));
12696
+ } catch (err) {
12697
+ if (err instanceof HttpException) {
12698
+ return NextResponse.json(err.getResponse(), { status: err.getStatus() });
12699
+ }
12700
+ throw err;
12701
+ }
12666
12702
  }`
12667
12703
  };
12668
12704
  //#endregion
@@ -12876,7 +12912,7 @@ export default function Home() {
12876
12912
  <p className="mb-2 text-muted-foreground">Learn more</p>
12877
12913
  <ul className="list-disc list-inside space-y-2 mt-2">
12878
12914
  <li>
12879
- <Link href="https://newt-app.com">Documentation</Link>
12915
+ <Link href="https://newt-app.com">newt-app</Link>
12880
12916
  </li>
12881
12917
  <li>
12882
12918
  <Link href="https://github.com/zeevo/newt-app">GitHub</Link>
@@ -13130,7 +13166,7 @@ export default function Home() {
13130
13166
  <p className="mb-2 text-muted-foreground">Learn more</p>
13131
13167
  <ul className="list-disc list-inside space-y-2 mt-2">
13132
13168
  <li>
13133
- <Link href="https://newt-app.com">Documentation</Link>
13169
+ <Link href="https://newt-app.com">newt-app</Link>
13134
13170
  </li>
13135
13171
  <li>
13136
13172
  <Link href="https://github.com/zeevo/newt-app">GitHub</Link>
@@ -13457,7 +13493,7 @@ export default function Home() {
13457
13493
  <p {...stylex.props(styles.muted)}>Learn more</p>
13458
13494
  <ul {...stylex.props(styles.list)}>
13459
13495
  <li>
13460
- <Link href="https://newt-app.com">Documentation</Link>
13496
+ <Link href="https://newt-app.com">newt-app</Link>
13461
13497
  </li>
13462
13498
  <li>
13463
13499
  <Link href="https://github.com/zeevo/newt-app">GitHub</Link>
@@ -13574,11 +13610,18 @@ const todoExampleApi = { templates: [
13574
13610
  db_schema_default,
13575
13611
  db_migration_todos_default
13576
13612
  ] };
13577
- const todoExampleControllers = { templates: [
13578
- todos_controller_default,
13579
- todos_module_controllers_default,
13580
- app_module_controllers_default
13581
- ] };
13613
+ const todoExampleControllers = {
13614
+ templates: [
13615
+ todos_controller_default,
13616
+ todos_module_controllers_default,
13617
+ app_module_controllers_default
13618
+ ],
13619
+ packages: [{
13620
+ package: "zod",
13621
+ module: "apps/api",
13622
+ version: versions.zod
13623
+ }]
13624
+ };
13582
13625
  const todoExampleDi = { templates: [
13583
13626
  web_todos_route_default,
13584
13627
  web_todos_id_route_default,
@@ -13846,16 +13889,21 @@ async function pnpmInstall(cwd) {
13846
13889
  return await execa("pnpm", ["install"], { cwd });
13847
13890
  }
13848
13891
  async function pnpmFormat(cwd) {
13849
- return await execa("pnpm", ["format"], { cwd });
13892
+ return await execa("pnpm", ["format:fix"], { cwd });
13850
13893
  }
13851
13894
  async function initGit(cwd) {
13852
13895
  await execa("git", ["init"], { cwd });
13853
13896
  await execa("git", ["add", "."], { cwd });
13854
- await execa("git", [
13855
- "commit",
13856
- "-m",
13857
- "Initial commit"
13858
- ], { cwd });
13897
+ try {
13898
+ await execa("git", [
13899
+ "commit",
13900
+ "-m",
13901
+ "Initial commit"
13902
+ ], { cwd });
13903
+ return true;
13904
+ } catch {
13905
+ return false;
13906
+ }
13859
13907
  }
13860
13908
  //#endregion
13861
13909
  //#region src/telemetry.ts
@@ -14148,11 +14196,12 @@ async function doInit(options) {
14148
14196
  }
14149
14197
  });
14150
14198
  }
14199
+ let committed = true;
14151
14200
  if (options.git) taskBuilder.add({
14152
14201
  title: "Initializing git",
14153
14202
  task: async () => {
14154
- await initGit(name);
14155
- return "Initialized git.";
14203
+ committed = await initGit(name);
14204
+ return committed ? "Initialized git." : "Initialized git, but could not commit.";
14156
14205
  }
14157
14206
  });
14158
14207
  await p.tasks(taskBuilder.tasks);
@@ -14162,8 +14211,9 @@ async function doInit(options) {
14162
14211
  console.log(chalk.blue(` cd ${name}`));
14163
14212
  if (!options.install) {
14164
14213
  console.log(chalk.blue(` pnpm install`));
14165
- console.log(chalk.blue(` pnpm format`));
14214
+ console.log(chalk.blue(` pnpm format:fix`));
14166
14215
  }
14216
+ if (!committed) console.log(chalk.blue(` git commit -m "Initial commit"`));
14167
14217
  console.log(chalk.blue(` pnpm dev`));
14168
14218
  console.log();
14169
14219
  await reportRun({