create-newt-app 0.35.5 → 0.36.0
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 +308 -313
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { existsSync, promises, readdirSync } from "fs";
|
|
|
11
11
|
import path from "path";
|
|
12
12
|
import https from "node:https";
|
|
13
13
|
//#region package.json
|
|
14
|
-
var version = "0.
|
|
14
|
+
var version = "0.36.0";
|
|
15
15
|
var engines = { "node": ">=24.0.0" };
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/templates/root/index.ts
|
|
@@ -177,44 +177,71 @@ pnpm dev
|
|
|
177
177
|
\`\`\`
|
|
178
178
|
|
|
179
179
|
Open [http://localhost:3000](http://localhost:3000).
|
|
180
|
-
<% if (deployment === '
|
|
180
|
+
<% if (deployment === 'none') { -%>
|
|
181
181
|
|
|
182
|
-
## Production
|
|
182
|
+
## Production
|
|
183
|
+
|
|
184
|
+
\`\`\`sh
|
|
185
|
+
pnpm db:migrate && pnpm build
|
|
186
|
+
pnpm --filter @<%= projectName %>/web start
|
|
187
|
+
\`\`\`
|
|
188
|
+
|
|
189
|
+
Open [http://localhost:3000](http://localhost:3000).
|
|
190
|
+
<% } else if (deployment === 'spa') { -%>
|
|
191
|
+
|
|
192
|
+
## Production
|
|
183
193
|
|
|
184
194
|
NestJS serves the static export and the API from one origin, so point \`BETTER_AUTH_URL\` at it:
|
|
185
195
|
|
|
186
196
|
\`\`\`sh
|
|
187
|
-
pnpm db:migrate
|
|
188
|
-
pnpm build
|
|
197
|
+
pnpm db:migrate && pnpm build
|
|
189
198
|
cd apps/api
|
|
190
199
|
BETTER_AUTH_URL=http://localhost:3001 pnpm start:prod
|
|
191
200
|
\`\`\`
|
|
192
201
|
|
|
193
202
|
Open [http://localhost:3001](http://localhost:3001). In a real deployment, set \`BETTER_AUTH_URL\` to the public URL.
|
|
203
|
+
<% } else if (deployment === 'standalone') { -%>
|
|
204
|
+
|
|
205
|
+
## Production
|
|
206
|
+
|
|
207
|
+
\`\`\`sh
|
|
208
|
+
docker compose up --build
|
|
209
|
+
\`\`\`
|
|
210
|
+
|
|
211
|
+
The \`migrate\` service applies migrations before the app starts. Open [http://localhost:3000](http://localhost:3000); set \`BETTER_AUTH_URL\` to the public URL in a real deployment.
|
|
194
212
|
<% } -%>
|
|
195
213
|
|
|
196
|
-
##
|
|
214
|
+
## Commands
|
|
197
215
|
|
|
198
|
-
-
|
|
216
|
+
- \`pnpm dev\`: run in development
|
|
217
|
+
- \`pnpm build\`, \`pnpm typecheck\`, \`pnpm test\`: build, type-check, and test every workspace
|
|
218
|
+
- \`pnpm lint:check\`: lint (fails on errors); \`pnpm format:fix\`: apply formatting
|
|
219
|
+
- \`pnpm db:migrate\`: run migrations; \`pnpm db:make <name>\`: scaffold a new one
|
|
199
220
|
<% if (nest === 'on') { -%>
|
|
200
|
-
-
|
|
201
|
-
<% } else if (nest === 'di-only') { -%>
|
|
202
|
-
- **api**: NestJS providers, resolved from the web process (no HTTP server)
|
|
221
|
+
- \`pnpm --filter @<%= projectName %>/api test:e2e\`: run the e2e suite
|
|
203
222
|
<% } -%>
|
|
204
223
|
|
|
205
|
-
##
|
|
224
|
+
## Environment
|
|
206
225
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
-
|
|
210
|
-
|
|
211
|
-
|
|
226
|
+
Set in \`.env\` (a committed \`.env.example\` documents each one):
|
|
227
|
+
|
|
228
|
+
- **BETTER_AUTH_URL**: the public origin of the app
|
|
229
|
+
- **BETTER_AUTH_SECRET**: a random secret used to sign sessions
|
|
230
|
+
<% if (database === 'postgres') { -%>
|
|
231
|
+
- **DATABASE_URL**: your Postgres connection string
|
|
232
|
+
<% } else { -%>
|
|
233
|
+
- **DATABASE_URL**: not set for SQLite (the app uses \`dev.db\` at the repo root); set it to a Postgres URL to use Postgres
|
|
212
234
|
<% } -%>
|
|
213
|
-
- **\`@<%= projectName %>/typescript-config\`**: shared tsconfig
|
|
214
235
|
|
|
215
|
-
##
|
|
236
|
+
## Layout
|
|
216
237
|
|
|
217
|
-
|
|
238
|
+
- **\`apps/web\`**: Next.js frontend (port 3000)
|
|
239
|
+
<% if (nest === 'on') { -%>
|
|
240
|
+
- **\`apps/api\`**: NestJS backend (port 3001)
|
|
241
|
+
<% } else if (nest === 'di-only') { -%>
|
|
242
|
+
- **\`apps/api\`**: NestJS providers, resolved in-process by the web app
|
|
243
|
+
<% } -%>
|
|
244
|
+
- **\`packages/\`**: \`auth\`, \`db\`, \`ui\`<% if (linter === 'eslint') { %>, \`eslint-config\`<% } %>, and shared \`typescript-config\`
|
|
218
245
|
`
|
|
219
246
|
},
|
|
220
247
|
{
|
|
@@ -252,7 +279,24 @@ Read \`docs/README.md\` inside that installed package first, then read the relev
|
|
|
252
279
|
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.
|
|
253
280
|
<!-- END:turborepo-agent-rules --><% if (shadcn) { %>
|
|
254
281
|
|
|
255
|
-
After making changes, run \`pnpm lint:check\` and fix all errors.<% }
|
|
282
|
+
After making changes, run \`pnpm lint:check\` and fix all errors.<% } %>
|
|
283
|
+
|
|
284
|
+
# Project notes
|
|
285
|
+
|
|
286
|
+
- **web** runs on port 3000<% if (nest === 'on') { %>; **api** (NestJS) runs on port 3001<% } %>.
|
|
287
|
+
<% if (nest === 'on') { -%>
|
|
288
|
+
- In development, \`apps/web\` rewrites \`/api/*\` to \`http://localhost:3001/api/*\` (see \`apps/web/next.config.js\`). The backend is a separate process; start both from the repo root with \`pnpm dev\`.
|
|
289
|
+
<% } else if (nest === 'di-only') { -%>
|
|
290
|
+
- There is no separate backend process. API routes are Next.js route handlers that resolve NestJS providers in-process.
|
|
291
|
+
<% } else { -%>
|
|
292
|
+
- There is no backend. API routes are served in-process by Next.js route handlers.
|
|
293
|
+
<% } -%>
|
|
294
|
+
- Migrations live in \`packages/db\`. Run \`pnpm db:migrate\`; scaffold a new one with \`pnpm db:make <name>\`.
|
|
295
|
+
- Environment is read from the root \`.env\` (see \`.env.example\`): \`DATABASE_URL\`, \`BETTER_AUTH_URL\`, \`BETTER_AUTH_SECRET\`.
|
|
296
|
+
<% if (nest !== 'off') { -%>
|
|
297
|
+
- NestJS controllers must validate request bodies with a schema (the api registers a global \`StandardSchemaValidationPipe\`); keep the todo controller as the reference for how to do it.
|
|
298
|
+
<% } -%>
|
|
299
|
+
`
|
|
256
300
|
},
|
|
257
301
|
{
|
|
258
302
|
filename: "CLAUDE.md",
|
|
@@ -260,13 +304,11 @@ After making changes, run \`pnpm lint:check\` and fix all errors.<% } %>`
|
|
|
260
304
|
}
|
|
261
305
|
] };
|
|
262
306
|
//#endregion
|
|
263
|
-
//#region src/templates/web/
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
filename: "apps/web/package.json",
|
|
269
|
-
template: `{
|
|
307
|
+
//#region src/templates/web/templates/package-json.ts
|
|
308
|
+
var package_json_default$7 = {
|
|
309
|
+
when: (s) => s.nest !== "di-only" && !s.stylex,
|
|
310
|
+
filename: "apps/web/package.json",
|
|
311
|
+
template: `{
|
|
270
312
|
"name": "web",
|
|
271
313
|
"version": "0.1.0",
|
|
272
314
|
"type": "module",
|
|
@@ -298,10 +340,12 @@ const web$1 = {
|
|
|
298
340
|
"typescript": "<%= versions.typescript %>"
|
|
299
341
|
}
|
|
300
342
|
}`
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
343
|
+
};
|
|
344
|
+
//#endregion
|
|
345
|
+
//#region src/templates/web/templates/gitignore.ts
|
|
346
|
+
var gitignore_default = {
|
|
347
|
+
filename: "apps/web/.gitignore",
|
|
348
|
+
template: `# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
305
349
|
|
|
306
350
|
# dependencies
|
|
307
351
|
/node_modules
|
|
@@ -337,50 +381,13 @@ yarn-error.log*
|
|
|
337
381
|
# typescript
|
|
338
382
|
*.tsbuildinfo
|
|
339
383
|
next-env.d.ts`
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
First, run the development server:
|
|
348
|
-
|
|
349
|
-
\`\`\`bash
|
|
350
|
-
npm run dev
|
|
351
|
-
# or
|
|
352
|
-
yarn dev
|
|
353
|
-
# or
|
|
354
|
-
pnpm dev
|
|
355
|
-
# or
|
|
356
|
-
bun dev
|
|
357
|
-
\`\`\`
|
|
358
|
-
|
|
359
|
-
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
|
360
|
-
|
|
361
|
-
You can start editing the page by modifying \`app/page.tsx\`. The page auto-updates as you edit the file.
|
|
362
|
-
|
|
363
|
-
This project uses [\`next/font\`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load Inter, a custom Google Font.
|
|
364
|
-
|
|
365
|
-
## Learn More
|
|
366
|
-
|
|
367
|
-
To learn more about Next.js, take a look at the following resources:
|
|
368
|
-
|
|
369
|
-
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
|
370
|
-
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
|
371
|
-
|
|
372
|
-
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
|
373
|
-
|
|
374
|
-
## Deploy on Vercel
|
|
375
|
-
|
|
376
|
-
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
|
377
|
-
|
|
378
|
-
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.`
|
|
379
|
-
},
|
|
380
|
-
{
|
|
381
|
-
when: (s) => s.deployment === "none" && s.nest === "on",
|
|
382
|
-
filename: "apps/web/next.config.js",
|
|
383
|
-
template: `import dotenv from 'dotenv';
|
|
384
|
+
};
|
|
385
|
+
//#endregion
|
|
386
|
+
//#region src/templates/web/templates/next-config.ts
|
|
387
|
+
var next_config_default$2 = {
|
|
388
|
+
when: (s) => s.deployment === "none" && s.nest === "on",
|
|
389
|
+
filename: "apps/web/next.config.js",
|
|
390
|
+
template: `import dotenv from 'dotenv';
|
|
384
391
|
import { resolve } from 'path';
|
|
385
392
|
|
|
386
393
|
// Load root .env first, then local .env (local takes precedence)
|
|
@@ -400,16 +407,20 @@ const nextConfig = {
|
|
|
400
407
|
};
|
|
401
408
|
|
|
402
409
|
export default nextConfig;`
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
410
|
+
};
|
|
411
|
+
//#endregion
|
|
412
|
+
//#region src/templates/web/templates/postcss-config.ts
|
|
413
|
+
var postcss_config_default$3 = {
|
|
414
|
+
when: (s) => !s.stylex,
|
|
415
|
+
filename: "apps/web/postcss.config.mjs",
|
|
416
|
+
template: `export { default } from "@<%= projectName %>/ui/postcss.config";`
|
|
417
|
+
};
|
|
418
|
+
//#endregion
|
|
419
|
+
//#region src/templates/web/templates/tsconfig.ts
|
|
420
|
+
var tsconfig_default$5 = {
|
|
421
|
+
when: (s) => s.nest !== "di-only",
|
|
422
|
+
filename: "apps/web/tsconfig.json",
|
|
423
|
+
template: `{
|
|
413
424
|
"extends": "@<%= projectName %>/typescript-config/nextjs.json",
|
|
414
425
|
"compilerOptions": {
|
|
415
426
|
"plugins": [
|
|
@@ -431,11 +442,13 @@ export default nextConfig;`
|
|
|
431
442
|
],
|
|
432
443
|
"exclude": ["node_modules"]
|
|
433
444
|
}`
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
445
|
+
};
|
|
446
|
+
//#endregion
|
|
447
|
+
//#region src/templates/web/templates/layout.ts
|
|
448
|
+
var layout_default$2 = {
|
|
449
|
+
when: (s) => !s.shadcn && !s.stylex,
|
|
450
|
+
filename: "apps/web/app/layout.tsx",
|
|
451
|
+
template: `import type { Metadata } from "next";
|
|
439
452
|
import localFont from "next/font/local";
|
|
440
453
|
import Providers from "@/app/providers";
|
|
441
454
|
import "@<%= projectName %>/ui/globals.css";
|
|
@@ -478,11 +491,13 @@ export default function RootLayout({
|
|
|
478
491
|
</html>
|
|
479
492
|
);
|
|
480
493
|
}`
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
494
|
+
};
|
|
495
|
+
//#endregion
|
|
496
|
+
//#region src/templates/web/templates/page.ts
|
|
497
|
+
var page_default$2 = {
|
|
498
|
+
when: (s) => !s.todoExample && !s.shadcn && !s.stylex,
|
|
499
|
+
filename: "apps/web/app/page.tsx",
|
|
500
|
+
template: `'use client';
|
|
486
501
|
|
|
487
502
|
import { useQuery } from '@tanstack/react-query';
|
|
488
503
|
import { authClient } from '@/lib/auth-client';
|
|
@@ -590,11 +605,13 @@ export default function Home() {
|
|
|
590
605
|
</main>
|
|
591
606
|
);
|
|
592
607
|
}`
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
608
|
+
};
|
|
609
|
+
//#endregion
|
|
610
|
+
//#region src/templates/web/templates/providers.ts
|
|
611
|
+
var providers_default$1 = {
|
|
612
|
+
when: (s) => !s.shadcn,
|
|
613
|
+
filename: "apps/web/app/providers.tsx",
|
|
614
|
+
template: `'use client';
|
|
598
615
|
|
|
599
616
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
600
617
|
import { useState } from 'react';
|
|
@@ -603,11 +620,13 @@ export default function Providers({ children }: { children: React.ReactNode }) {
|
|
|
603
620
|
const [client] = useState(() => new QueryClient());
|
|
604
621
|
return <QueryClientProvider client={client}>{children}</QueryClientProvider>;
|
|
605
622
|
}`
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
623
|
+
};
|
|
624
|
+
//#endregion
|
|
625
|
+
//#region src/templates/web/templates/auth-form.ts
|
|
626
|
+
var auth_form_default$2 = {
|
|
627
|
+
when: (s) => !s.shadcn && !s.stylex,
|
|
628
|
+
filename: "apps/web/app/auth-form.tsx",
|
|
629
|
+
template: `'use client';
|
|
611
630
|
|
|
612
631
|
import { useForm } from '@tanstack/react-form';
|
|
613
632
|
import { useState } from 'react';
|
|
@@ -735,23 +754,29 @@ export function AuthForm() {
|
|
|
735
754
|
</>
|
|
736
755
|
);
|
|
737
756
|
}`
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
757
|
+
};
|
|
758
|
+
//#endregion
|
|
759
|
+
//#region src/templates/web/templates/auth-route.ts
|
|
760
|
+
var auth_route_default = {
|
|
761
|
+
filename: "apps/web/app/api/auth/[...all]/route.ts",
|
|
762
|
+
template: `import { auth } from "@<%= projectName %>/auth";
|
|
742
763
|
import { toNextJsHandler } from "better-auth/next-js";
|
|
743
764
|
|
|
744
765
|
export const { GET, POST } = toNextJsHandler(auth);`
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
766
|
+
};
|
|
767
|
+
//#endregion
|
|
768
|
+
//#region src/templates/web/templates/auth-client.ts
|
|
769
|
+
var auth_client_default = {
|
|
770
|
+
filename: "apps/web/lib/auth-client.ts",
|
|
771
|
+
template: `import { createAuthClient } from "better-auth/react";
|
|
749
772
|
|
|
750
773
|
export const authClient = createAuthClient();`
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
774
|
+
};
|
|
775
|
+
//#endregion
|
|
776
|
+
//#region src/templates/web/templates/manifest.ts
|
|
777
|
+
var manifest_default = {
|
|
778
|
+
filename: "apps/web/app/manifest.json",
|
|
779
|
+
template: `{
|
|
755
780
|
"name": "<%= projectName %>",
|
|
756
781
|
"short_name": "<%= projectName %>",
|
|
757
782
|
"icons": [
|
|
@@ -772,7 +797,109 @@ export const authClient = createAuthClient();`
|
|
|
772
797
|
"background_color": "#ffffff",
|
|
773
798
|
"display": "standalone"
|
|
774
799
|
}`
|
|
775
|
-
|
|
800
|
+
};
|
|
801
|
+
//#endregion
|
|
802
|
+
//#region src/templates/versions.ts
|
|
803
|
+
const versions = {
|
|
804
|
+
"@babel/plugin-proposal-decorators": "^8.0.2",
|
|
805
|
+
"@babel/plugin-transform-class-properties": "^8.0.1",
|
|
806
|
+
"@base-ui/react": "^1.6.0",
|
|
807
|
+
"@eslint/js": "^9.39.1",
|
|
808
|
+
"@nestjs/cli": "^12.0.7",
|
|
809
|
+
"@nestjs/common": "^12.1.0",
|
|
810
|
+
"@nestjs/core": "^12.1.0",
|
|
811
|
+
"@nestjs/platform-express": "^12.1.0",
|
|
812
|
+
"@nestjs/schematics": "^12.0.5",
|
|
813
|
+
"@nestjs/serve-static": "^12.0.0",
|
|
814
|
+
"@nestjs/testing": "^12.1.0",
|
|
815
|
+
"@next/eslint-plugin-next": "^16.4.0",
|
|
816
|
+
"@oxlint/plugins": "^1.74.0",
|
|
817
|
+
"@shadcn/lint": "^0.1.0",
|
|
818
|
+
"@shadcn/react": "^0.2.1",
|
|
819
|
+
"@stylexjs/babel-plugin": "0.19.0",
|
|
820
|
+
"@stylexjs/postcss-plugin": "0.19.0",
|
|
821
|
+
"@stylexjs/stylex": "0.19.0",
|
|
822
|
+
"@swc/core": "^1.10.0",
|
|
823
|
+
"@tailwindcss/postcss": "^4.2.1",
|
|
824
|
+
"@tanstack/react-form": "^1.28.5",
|
|
825
|
+
"@tanstack/react-query": "^5.90.21",
|
|
826
|
+
"@thallesp/nestjs-better-auth": "^2.8.0",
|
|
827
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
828
|
+
"@types/express": "^5.0.0",
|
|
829
|
+
"@types/jest": "^30.0.0",
|
|
830
|
+
"@types/node": "^24.13.3",
|
|
831
|
+
"@types/pg": "^8.11.13",
|
|
832
|
+
"@types/react": "19.2.14",
|
|
833
|
+
"@types/react-dom": "19.2.3",
|
|
834
|
+
"@types/supertest": "^6.0.2",
|
|
835
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
836
|
+
auth: "^1.5.5",
|
|
837
|
+
"babel-plugin-transform-typescript-metadata": "^0.4.0",
|
|
838
|
+
"better-auth": "^1.2.8",
|
|
839
|
+
"better-sqlite3": "^12.11.1",
|
|
840
|
+
"class-variance-authority": "^0.7.1",
|
|
841
|
+
clsx: "^2.1.1",
|
|
842
|
+
cmdk: "^1.1.1",
|
|
843
|
+
cn: "^0.3.0",
|
|
844
|
+
"date-fns": "^4.2.1",
|
|
845
|
+
dotenv: "^17.3.1",
|
|
846
|
+
"dotenv-cli": "^11.0.0",
|
|
847
|
+
"embla-carousel-react": "^8.6.0",
|
|
848
|
+
eslint: "^9.39.1",
|
|
849
|
+
"eslint-config-prettier": "^10.1.1",
|
|
850
|
+
"eslint-plugin-only-warn": "^1.1.0",
|
|
851
|
+
"eslint-plugin-react": "^7.37.5",
|
|
852
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
853
|
+
"eslint-plugin-turbo": "^2.7.1",
|
|
854
|
+
globals: "^16.5.0",
|
|
855
|
+
"input-otp": "^1.4.2",
|
|
856
|
+
jest: "^30.0.0",
|
|
857
|
+
kysely: "^0.28.2",
|
|
858
|
+
"lucide-react": "^1.16.0",
|
|
859
|
+
next: "16.4.0",
|
|
860
|
+
"next-themes": "^0.4.6",
|
|
861
|
+
oxfmt: "^0.59.0",
|
|
862
|
+
oxlint: "^1.80.0",
|
|
863
|
+
pg: "^8.14.1",
|
|
864
|
+
prettier: "^3.7.4",
|
|
865
|
+
react: "^19.2.4",
|
|
866
|
+
"react-day-picker": "^10.0.1",
|
|
867
|
+
"react-dom": "^19.2.4",
|
|
868
|
+
"react-resizable-panels": "^4.11.1",
|
|
869
|
+
recharts: "^3.8.0",
|
|
870
|
+
"reflect-metadata": "^0.2.2",
|
|
871
|
+
rxjs: "^7.8.1",
|
|
872
|
+
shadcn: "^4.7.0",
|
|
873
|
+
sonner: "^2.0.7",
|
|
874
|
+
supertest: "^7.0.0",
|
|
875
|
+
"tailwind-merge": "^3.6.0",
|
|
876
|
+
tailwindcss: "^4.2.1",
|
|
877
|
+
"ts-jest": "^29.2.5",
|
|
878
|
+
tsx: "^4.19.4",
|
|
879
|
+
turbo: "^2.8.16",
|
|
880
|
+
"tw-animate-css": "^1.4.0",
|
|
881
|
+
typescript: "6.0.2",
|
|
882
|
+
"typescript-eslint": "^8.50.0",
|
|
883
|
+
"unplugin-swc": "^1.5.9",
|
|
884
|
+
vitest: "^4.1.10",
|
|
885
|
+
zod: "^4.6.5"
|
|
886
|
+
};
|
|
887
|
+
//#endregion
|
|
888
|
+
//#region src/templates/web/index.ts
|
|
889
|
+
const web$1 = {
|
|
890
|
+
templates: [
|
|
891
|
+
package_json_default$7,
|
|
892
|
+
gitignore_default,
|
|
893
|
+
next_config_default$2,
|
|
894
|
+
postcss_config_default$3,
|
|
895
|
+
tsconfig_default$5,
|
|
896
|
+
layout_default$2,
|
|
897
|
+
page_default$2,
|
|
898
|
+
providers_default$1,
|
|
899
|
+
auth_form_default$2,
|
|
900
|
+
auth_route_default,
|
|
901
|
+
auth_client_default,
|
|
902
|
+
manifest_default
|
|
776
903
|
],
|
|
777
904
|
staticFiles: [
|
|
778
905
|
{
|
|
@@ -807,15 +934,21 @@ export const authClient = createAuthClient();`
|
|
|
807
934
|
src: "web/static/public/web-app-manifest-512x512.png",
|
|
808
935
|
filename: "apps/web/public/web-app-manifest-512x512.png"
|
|
809
936
|
}
|
|
810
|
-
]
|
|
937
|
+
],
|
|
938
|
+
packages: [{
|
|
939
|
+
package: "zod",
|
|
940
|
+
module: "apps/web",
|
|
941
|
+
version: versions.zod
|
|
942
|
+
}]
|
|
811
943
|
};
|
|
812
944
|
//#endregion
|
|
813
945
|
//#region src/templates/api/index.ts
|
|
814
|
-
const api$1 = {
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
946
|
+
const api$1 = {
|
|
947
|
+
templates: [
|
|
948
|
+
{
|
|
949
|
+
when: (s) => s.nest === "on" && s.deployment !== "spa",
|
|
950
|
+
filename: "apps/api/package.json",
|
|
951
|
+
template: `{
|
|
819
952
|
"name": "api",
|
|
820
953
|
"version": "0.0.1",
|
|
821
954
|
"private": true,
|
|
@@ -849,10 +982,10 @@ const api$1 = { templates: [
|
|
|
849
982
|
"typescript": "<%= versions.typescript %>"
|
|
850
983
|
}
|
|
851
984
|
}`
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
filename: "apps/api/nest-cli.json",
|
|
988
|
+
template: `{
|
|
856
989
|
"$schema": "https://json.schemastore.org/nest-cli",
|
|
857
990
|
"collection": "@nestjs/schematics",
|
|
858
991
|
"sourceRoot": "src",
|
|
@@ -860,11 +993,11 @@ const api$1 = { templates: [
|
|
|
860
993
|
"deleteOutDir": true
|
|
861
994
|
}
|
|
862
995
|
}`
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
996
|
+
},
|
|
997
|
+
{
|
|
998
|
+
when: (s) => s.nest === "on",
|
|
999
|
+
filename: "apps/api/tsconfig.json",
|
|
1000
|
+
template: `{
|
|
868
1001
|
"compilerOptions": {
|
|
869
1002
|
"module": "nodenext",
|
|
870
1003
|
"moduleResolution": "nodenext",
|
|
@@ -888,28 +1021,28 @@ const api$1 = { templates: [
|
|
|
888
1021
|
},
|
|
889
1022
|
"exclude": ["vitest.config.mts", "vitest.config.e2e.mts", "node_modules", "dist"]
|
|
890
1023
|
}`
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1024
|
+
},
|
|
1025
|
+
{
|
|
1026
|
+
filename: "apps/api/tsconfig.build.json",
|
|
1027
|
+
template: `{
|
|
895
1028
|
"extends": "./tsconfig.json",
|
|
896
1029
|
"exclude": ["node_modules", "test", "dist", "**/*spec.ts", "vitest.config.mts", "vitest.config.e2e.mts", "jest.config.ts"]
|
|
897
1030
|
}`
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
when: (s) => s.nest === "di-only" && !s.todoExample,
|
|
1034
|
+
filename: "apps/api/src/app.module.ts",
|
|
1035
|
+
template: `import { Module } from '@nestjs/common';
|
|
903
1036
|
import { AppService } from './app.service';
|
|
904
1037
|
|
|
905
1038
|
@Module({
|
|
906
1039
|
providers: [AppService],
|
|
907
1040
|
})
|
|
908
1041
|
export class AppModule {}`
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
1042
|
+
},
|
|
1043
|
+
{
|
|
1044
|
+
filename: "apps/api/src/app.service.ts",
|
|
1045
|
+
template: `import { Injectable } from '@nestjs/common';
|
|
913
1046
|
|
|
914
1047
|
@Injectable()
|
|
915
1048
|
export class AppService {
|
|
@@ -917,10 +1050,10 @@ export class AppService {
|
|
|
917
1050
|
return 'Hello from Nest';
|
|
918
1051
|
}
|
|
919
1052
|
}`
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
filename: "apps/api/src/app.service.spec.ts",
|
|
1056
|
+
template: `import { Test, TestingModule } from '@nestjs/testing';
|
|
924
1057
|
import { AppService } from './app.service';
|
|
925
1058
|
|
|
926
1059
|
describe('AppService', () => {
|
|
@@ -938,23 +1071,14 @@ describe('AppService', () => {
|
|
|
938
1071
|
expect(service).toBeDefined();
|
|
939
1072
|
});
|
|
940
1073
|
});`
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
\`\`\`sh
|
|
951
|
-
pnpm dev # watch mode
|
|
952
|
-
pnpm build # production build
|
|
953
|
-
pnpm test # unit tests<% if (nest === 'on') { %>
|
|
954
|
-
pnpm test:e2e # e2e tests<% } %>
|
|
955
|
-
\`\`\``
|
|
956
|
-
}
|
|
957
|
-
] };
|
|
1074
|
+
}
|
|
1075
|
+
],
|
|
1076
|
+
packages: [{
|
|
1077
|
+
package: "zod",
|
|
1078
|
+
module: "apps/api",
|
|
1079
|
+
version: versions.zod
|
|
1080
|
+
}]
|
|
1081
|
+
};
|
|
958
1082
|
//#endregion
|
|
959
1083
|
//#region src/templates/auth/index.ts
|
|
960
1084
|
const auth = { templates: [
|
|
@@ -1106,12 +1230,21 @@ import { FileMigrationProvider, Migrator } from "kysely";
|
|
|
1106
1230
|
import { db } from "./index.js";
|
|
1107
1231
|
|
|
1108
1232
|
async function main() {
|
|
1233
|
+
const migrationFolder = path.join(process.cwd(), "src/migrations");
|
|
1234
|
+
try {
|
|
1235
|
+
await fs.access(migrationFolder);
|
|
1236
|
+
} catch {
|
|
1237
|
+
console.log("no migrations yet");
|
|
1238
|
+
await db.destroy();
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1109
1242
|
const migrator = new Migrator({
|
|
1110
1243
|
db,
|
|
1111
1244
|
provider: new FileMigrationProvider({
|
|
1112
1245
|
fs,
|
|
1113
1246
|
path,
|
|
1114
|
-
migrationFolder
|
|
1247
|
+
migrationFolder,
|
|
1115
1248
|
}),
|
|
1116
1249
|
});
|
|
1117
1250
|
|
|
@@ -1178,23 +1311,6 @@ async function main() {
|
|
|
1178
1311
|
main();`
|
|
1179
1312
|
};
|
|
1180
1313
|
//#endregion
|
|
1181
|
-
//#region src/templates/db/templates/migrations-readme.ts
|
|
1182
|
-
var migrations_readme_default = {
|
|
1183
|
-
filename: "packages/db/src/migrations/README.md",
|
|
1184
|
-
template: `# Migrations
|
|
1185
|
-
|
|
1186
|
-
Kysely migrations run in filename order. Each file exports \`up\` and \`down\`.
|
|
1187
|
-
|
|
1188
|
-
\`\`\`bash
|
|
1189
|
-
pnpm db:make add_widgets # scaffold a new migration
|
|
1190
|
-
pnpm db:migrate # apply pending migrations
|
|
1191
|
-
\`\`\`
|
|
1192
|
-
|
|
1193
|
-
Migrations are written with Kysely's schema builder, so one file compiles to
|
|
1194
|
-
both SQLite (dev) and Postgres (prod). Prefer dialect-agnostic column types
|
|
1195
|
-
(\`text\`, \`integer\`) and app-generated string ids over auto-increment.`
|
|
1196
|
-
};
|
|
1197
|
-
//#endregion
|
|
1198
1314
|
//#region src/templates/db/templates/package-json-sqlite.ts
|
|
1199
1315
|
var package_json_sqlite_default = {
|
|
1200
1316
|
filename: "packages/db/package.json",
|
|
@@ -1310,8 +1426,7 @@ const shared = [
|
|
|
1310
1426
|
tsconfig_default$2,
|
|
1311
1427
|
src_schema_default,
|
|
1312
1428
|
src_migrate_default,
|
|
1313
|
-
scripts_new_migration_default
|
|
1314
|
-
migrations_readme_default
|
|
1429
|
+
scripts_new_migration_default
|
|
1315
1430
|
];
|
|
1316
1431
|
const dbSqlite = { templates: [
|
|
1317
1432
|
...shared,
|
|
@@ -1545,92 +1660,6 @@ const ui$1 = { templates: [
|
|
|
1545
1660
|
tsconfig_default$1
|
|
1546
1661
|
] };
|
|
1547
1662
|
//#endregion
|
|
1548
|
-
//#region src/templates/versions.ts
|
|
1549
|
-
const versions = {
|
|
1550
|
-
"@babel/plugin-proposal-decorators": "^8.0.2",
|
|
1551
|
-
"@babel/plugin-transform-class-properties": "^8.0.1",
|
|
1552
|
-
"@base-ui/react": "^1.6.0",
|
|
1553
|
-
"@eslint/js": "^9.39.1",
|
|
1554
|
-
"@nestjs/cli": "^12.0.7",
|
|
1555
|
-
"@nestjs/common": "^12.1.0",
|
|
1556
|
-
"@nestjs/core": "^12.1.0",
|
|
1557
|
-
"@nestjs/platform-express": "^12.1.0",
|
|
1558
|
-
"@nestjs/schematics": "^12.0.5",
|
|
1559
|
-
"@nestjs/serve-static": "^12.0.0",
|
|
1560
|
-
"@nestjs/testing": "^12.1.0",
|
|
1561
|
-
"@next/eslint-plugin-next": "^16.3.4",
|
|
1562
|
-
"@oxlint/plugins": "^1.74.0",
|
|
1563
|
-
"@shadcn/lint": "^0.1.0",
|
|
1564
|
-
"@shadcn/react": "^0.2.1",
|
|
1565
|
-
"@stylexjs/babel-plugin": "0.19.0",
|
|
1566
|
-
"@stylexjs/postcss-plugin": "0.19.0",
|
|
1567
|
-
"@stylexjs/stylex": "0.19.0",
|
|
1568
|
-
"@swc/core": "^1.10.0",
|
|
1569
|
-
"@tailwindcss/postcss": "^4.2.1",
|
|
1570
|
-
"@tanstack/react-form": "^1.28.5",
|
|
1571
|
-
"@tanstack/react-query": "^5.90.21",
|
|
1572
|
-
"@thallesp/nestjs-better-auth": "^2.8.0",
|
|
1573
|
-
"@types/better-sqlite3": "^7.6.13",
|
|
1574
|
-
"@types/express": "^5.0.0",
|
|
1575
|
-
"@types/jest": "^30.0.0",
|
|
1576
|
-
"@types/node": "^24.13.3",
|
|
1577
|
-
"@types/pg": "^8.11.13",
|
|
1578
|
-
"@types/react": "19.2.14",
|
|
1579
|
-
"@types/react-dom": "19.2.3",
|
|
1580
|
-
"@types/supertest": "^6.0.2",
|
|
1581
|
-
"@vitest/coverage-v8": "^4.1.10",
|
|
1582
|
-
auth: "^1.5.5",
|
|
1583
|
-
"babel-plugin-transform-typescript-metadata": "^0.4.0",
|
|
1584
|
-
"better-auth": "^1.2.8",
|
|
1585
|
-
"better-sqlite3": "^12.11.1",
|
|
1586
|
-
"class-variance-authority": "^0.7.1",
|
|
1587
|
-
clsx: "^2.1.1",
|
|
1588
|
-
cmdk: "^1.1.1",
|
|
1589
|
-
cn: "^0.3.0",
|
|
1590
|
-
"date-fns": "^4.2.1",
|
|
1591
|
-
dotenv: "^17.3.1",
|
|
1592
|
-
"dotenv-cli": "^11.0.0",
|
|
1593
|
-
"embla-carousel-react": "^8.6.0",
|
|
1594
|
-
eslint: "^9.39.1",
|
|
1595
|
-
"eslint-config-prettier": "^10.1.1",
|
|
1596
|
-
"eslint-plugin-only-warn": "^1.1.0",
|
|
1597
|
-
"eslint-plugin-react": "^7.37.5",
|
|
1598
|
-
"eslint-plugin-react-hooks": "^5.2.0",
|
|
1599
|
-
"eslint-plugin-turbo": "^2.7.1",
|
|
1600
|
-
globals: "^16.5.0",
|
|
1601
|
-
"input-otp": "^1.4.2",
|
|
1602
|
-
jest: "^30.0.0",
|
|
1603
|
-
kysely: "^0.28.2",
|
|
1604
|
-
"lucide-react": "^1.16.0",
|
|
1605
|
-
next: "16.3.4",
|
|
1606
|
-
"next-themes": "^0.4.6",
|
|
1607
|
-
oxfmt: "^0.59.0",
|
|
1608
|
-
oxlint: "^1.80.0",
|
|
1609
|
-
pg: "^8.14.1",
|
|
1610
|
-
prettier: "^3.7.4",
|
|
1611
|
-
react: "^19.2.4",
|
|
1612
|
-
"react-day-picker": "^10.0.1",
|
|
1613
|
-
"react-dom": "^19.2.4",
|
|
1614
|
-
"react-resizable-panels": "^4.11.1",
|
|
1615
|
-
recharts: "^3.8.0",
|
|
1616
|
-
"reflect-metadata": "^0.2.2",
|
|
1617
|
-
rxjs: "^7.8.1",
|
|
1618
|
-
shadcn: "^4.7.0",
|
|
1619
|
-
sonner: "^2.0.7",
|
|
1620
|
-
supertest: "^7.0.0",
|
|
1621
|
-
"tailwind-merge": "^3.6.0",
|
|
1622
|
-
tailwindcss: "^4.2.1",
|
|
1623
|
-
"ts-jest": "^29.2.5",
|
|
1624
|
-
tsx: "^4.19.4",
|
|
1625
|
-
turbo: "^2.8.16",
|
|
1626
|
-
"tw-animate-css": "^1.4.0",
|
|
1627
|
-
typescript: "6.0.2",
|
|
1628
|
-
"typescript-eslint": "^8.50.0",
|
|
1629
|
-
"unplugin-swc": "^1.5.9",
|
|
1630
|
-
vitest: "^4.1.10",
|
|
1631
|
-
zod: "^4.6.5"
|
|
1632
|
-
};
|
|
1633
|
-
//#endregion
|
|
1634
1663
|
//#region src/templates/shadcn-ui/index.ts
|
|
1635
1664
|
const shadcnUi = {
|
|
1636
1665
|
templates: [
|
|
@@ -11275,37 +11304,10 @@ var plugin_package_json_default = {
|
|
|
11275
11304
|
}`
|
|
11276
11305
|
};
|
|
11277
11306
|
//#endregion
|
|
11278
|
-
//#region src/templates/anti-slop/templates/plugin-readme.ts
|
|
11279
|
-
var plugin_readme_default = {
|
|
11280
|
-
filename: "tools/oxlint/anti-slop/README.md",
|
|
11281
|
-
template: `# anti-slop
|
|
11282
|
-
|
|
11283
|
-
Oxlint rules that reject low-evidence TypeScript patterns, vendored from
|
|
11284
|
-
[dmmulroy/anti-slop](https://github.com/dmmulroy/anti-slop) at \`6d538555cb15\` (MIT, see LICENSE).
|
|
11285
|
-
|
|
11286
|
-
Upstream ships these to be vendored rather than depended on, so these files are
|
|
11287
|
-
yours: read them, change the messages, delete the rules you disagree with.
|
|
11288
|
-
|
|
11289
|
-
\`.oxlintrc.json\` registers the plugin and turns every rule on as an error.
|
|
11290
|
-
Turn one off there:
|
|
11291
|
-
|
|
11292
|
-
\`\`\`json
|
|
11293
|
-
{
|
|
11294
|
-
"rules": {
|
|
11295
|
-
"anti-slop/no-runtime-typeof": "off"
|
|
11296
|
-
}
|
|
11297
|
-
}
|
|
11298
|
-
\`\`\`
|
|
11299
|
-
|
|
11300
|
-
Vendored shadcn components under \`packages/ui/src/components\` are exempt, since
|
|
11301
|
-
they are upstream code you re-pull rather than write.
|
|
11302
|
-
`
|
|
11303
|
-
};
|
|
11304
|
-
//#endregion
|
|
11305
11307
|
//#region src/templates/anti-slop/index.ts
|
|
11306
11308
|
const plugin = "tools/oxlint/anti-slop";
|
|
11307
11309
|
const antiSlop = {
|
|
11308
|
-
templates: [plugin_package_json_default
|
|
11310
|
+
templates: [plugin_package_json_default],
|
|
11309
11311
|
staticFiles: [
|
|
11310
11312
|
{
|
|
11311
11313
|
src: "anti-slop/static/LICENSE",
|
|
@@ -13847,18 +13849,11 @@ const todoExampleApi = { templates: [
|
|
|
13847
13849
|
db_schema_default,
|
|
13848
13850
|
db_migration_todos_default
|
|
13849
13851
|
] };
|
|
13850
|
-
const todoExampleControllers = {
|
|
13851
|
-
|
|
13852
|
-
|
|
13853
|
-
|
|
13854
|
-
|
|
13855
|
-
],
|
|
13856
|
-
packages: [{
|
|
13857
|
-
package: "zod",
|
|
13858
|
-
module: "apps/api",
|
|
13859
|
-
version: versions.zod
|
|
13860
|
-
}]
|
|
13861
|
-
};
|
|
13852
|
+
const todoExampleControllers = { templates: [
|
|
13853
|
+
todos_controller_default,
|
|
13854
|
+
todos_module_controllers_default,
|
|
13855
|
+
app_module_controllers_default
|
|
13856
|
+
] };
|
|
13862
13857
|
const todoExampleDi = { templates: [
|
|
13863
13858
|
web_todos_route_default,
|
|
13864
13859
|
web_todos_id_route_default,
|