create-newt-app 0.31.10 → 0.32.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.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +132 -56
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
//#region src/templates/types.d.ts
|
|
2
|
+
type Nest = "on" | "off" | "di-only";
|
|
2
3
|
type Extra = "anti-slop";
|
|
3
4
|
//#endregion
|
|
4
5
|
//#region src/index.d.ts
|
|
@@ -20,7 +21,7 @@ type Options = {
|
|
|
20
21
|
database: Database;
|
|
21
22
|
linter: Linter;
|
|
22
23
|
deployment: Deployment;
|
|
23
|
-
|
|
24
|
+
nest: Nest;
|
|
24
25
|
includeExample: boolean;
|
|
25
26
|
extras: readonly Extra[];
|
|
26
27
|
explicitFlags: readonly string[];
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/templates/types.ts","../src/index.ts"],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/templates/types.ts","../src/index.ts"],"mappings":";KAIY;KAgCA;;;cChBN;cACA;cACA;cACA;KAID,kBAAkB;KAClB,mBAAmB;KACnB,iBAAiB;KACjB,qBAAqB;KAcrB;EACH;EACA;EACA;EACA;EACA;EACA,SAAS;EACT,UAAU;EACV,QAAQ;EACR,YAAY;EACZ,MAAM;EACN;EACA,iBAAiB;EACjB;;iBAWoB,OAAO,SAAS,UAAO"}
|
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.
|
|
14
|
+
var version = "0.32.1";
|
|
15
15
|
var engines = { "node": ">=24.0.0" };
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/templates/root/index.ts
|
|
@@ -165,7 +165,7 @@ allowBuilds:
|
|
|
165
165
|
filename: "README.md",
|
|
166
166
|
template: `# <%= projectName %>
|
|
167
167
|
|
|
168
|
-
Full-stack monorepo: Next.js 16 + NestJS 11 + better-auth + <%= database === 'postgres' ? 'Postgres' : 'SQLite' %>.
|
|
168
|
+
Full-stack monorepo: Next.js 16<% if (nest !== 'off') { %> + NestJS 11<% } %> + better-auth + <%= database === 'postgres' ? 'Postgres' : 'SQLite' %>.
|
|
169
169
|
|
|
170
170
|
## Quick start
|
|
171
171
|
|
|
@@ -180,7 +180,11 @@ Open [http://localhost:3000](http://localhost:3000).
|
|
|
180
180
|
## Apps
|
|
181
181
|
|
|
182
182
|
- **web**: Next.js frontend (port 3000)
|
|
183
|
+
<% if (nest === 'on') { -%>
|
|
183
184
|
- **api**: NestJS backend (port 3001)
|
|
185
|
+
<% } else if (nest === 'di-only') { -%>
|
|
186
|
+
- **api**: NestJS providers, resolved from the web process (no HTTP server)
|
|
187
|
+
<% } -%>
|
|
184
188
|
|
|
185
189
|
## Packages
|
|
186
190
|
|
|
@@ -227,7 +231,7 @@ This version has breaking changes — APIs, conventions, and file structure may
|
|
|
227
231
|
const web$1 = {
|
|
228
232
|
templates: [
|
|
229
233
|
{
|
|
230
|
-
when: (s) =>
|
|
234
|
+
when: (s) => s.nest !== "di-only",
|
|
231
235
|
filename: "apps/web/package.json",
|
|
232
236
|
template: `{
|
|
233
237
|
"name": "web",
|
|
@@ -238,8 +242,7 @@ const web$1 = {
|
|
|
238
242
|
"dev": "next dev --port 3000",
|
|
239
243
|
"build": "next build",
|
|
240
244
|
"start": "next start",
|
|
241
|
-
"typecheck": "next typegen && tsc --noEmit"
|
|
242
|
-
"db:migrate": "better-auth migrate"
|
|
245
|
+
"typecheck": "next typegen && tsc --noEmit"
|
|
243
246
|
},
|
|
244
247
|
"dependencies": {
|
|
245
248
|
"@<%= projectName %>/auth": "workspace:*",
|
|
@@ -342,7 +345,7 @@ The easiest way to deploy your Next.js app is to use the [Vercel Platform](https
|
|
|
342
345
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.`
|
|
343
346
|
},
|
|
344
347
|
{
|
|
345
|
-
when: (s) => s.deployment === "none" &&
|
|
348
|
+
when: (s) => s.deployment === "none" && s.nest === "on",
|
|
346
349
|
filename: "apps/web/next.config.js",
|
|
347
350
|
template: `import dotenv from 'dotenv';
|
|
348
351
|
import { resolve } from 'path';
|
|
@@ -370,7 +373,7 @@ export default nextConfig;`
|
|
|
370
373
|
template: `export { default } from "@<%= projectName %>/ui/postcss.config";`
|
|
371
374
|
},
|
|
372
375
|
{
|
|
373
|
-
when: (s) =>
|
|
376
|
+
when: (s) => s.nest !== "di-only",
|
|
374
377
|
filename: "apps/web/tsconfig.json",
|
|
375
378
|
template: `{
|
|
376
379
|
"extends": "@<%= projectName %>/typescript-config/nextjs.json",
|
|
@@ -748,7 +751,7 @@ export const authClient: ReturnType<typeof createAuthClient> = createAuthClient(
|
|
|
748
751
|
//#region src/templates/api/index.ts
|
|
749
752
|
const api$1 = { templates: [
|
|
750
753
|
{
|
|
751
|
-
when: (s) =>
|
|
754
|
+
when: (s) => s.nest === "on" && s.deployment !== "spa",
|
|
752
755
|
filename: "apps/api/package.json",
|
|
753
756
|
template: `{
|
|
754
757
|
"name": "api",
|
|
@@ -797,7 +800,7 @@ const api$1 = { templates: [
|
|
|
797
800
|
}`
|
|
798
801
|
},
|
|
799
802
|
{
|
|
800
|
-
when: (s) =>
|
|
803
|
+
when: (s) => s.nest === "on",
|
|
801
804
|
filename: "apps/api/tsconfig.json",
|
|
802
805
|
template: `{
|
|
803
806
|
"compilerOptions": {
|
|
@@ -834,7 +837,7 @@ const api$1 = { templates: [
|
|
|
834
837
|
}`
|
|
835
838
|
},
|
|
836
839
|
{
|
|
837
|
-
when: (s) => s.
|
|
840
|
+
when: (s) => s.nest === "di-only" && !s.todoExample,
|
|
838
841
|
filename: "apps/api/src/app.module.ts",
|
|
839
842
|
template: `import { Module } from '@nestjs/common';
|
|
840
843
|
import { AppService } from './app.service';
|
|
@@ -887,7 +890,7 @@ NestJS backend for the monorepo.
|
|
|
887
890
|
\`\`\`sh
|
|
888
891
|
pnpm dev # watch mode
|
|
889
892
|
pnpm build # production build
|
|
890
|
-
pnpm test # unit tests<% if (
|
|
893
|
+
pnpm test # unit tests<% if (nest === 'on') { %>
|
|
891
894
|
pnpm test:e2e # e2e tests<% } %>
|
|
892
895
|
\`\`\``
|
|
893
896
|
}
|
|
@@ -938,6 +941,7 @@ export type Auth = typeof auth;`
|
|
|
938
941
|
filename: "packages/auth/tsconfig.json",
|
|
939
942
|
template: `{
|
|
940
943
|
"compilerOptions": {
|
|
944
|
+
"erasableSyntaxOnly": true,
|
|
941
945
|
"esModuleInterop": true,
|
|
942
946
|
"lib": ["es2022"],
|
|
943
947
|
"module": "NodeNext",
|
|
@@ -958,6 +962,7 @@ var tsconfig_default$2 = {
|
|
|
958
962
|
filename: "packages/db/tsconfig.json",
|
|
959
963
|
template: `{
|
|
960
964
|
"compilerOptions": {
|
|
965
|
+
"erasableSyntaxOnly": true,
|
|
961
966
|
"esModuleInterop": true,
|
|
962
967
|
"lib": ["es2022"],
|
|
963
968
|
"module": "NodeNext",
|
|
@@ -10009,6 +10014,7 @@ export default nextJsConfig;`
|
|
|
10009
10014
|
//#endregion
|
|
10010
10015
|
//#region src/templates/api/templates/eslint-config.ts
|
|
10011
10016
|
var eslint_config_default$1 = {
|
|
10017
|
+
when: (s) => s.nest !== "off",
|
|
10012
10018
|
filename: "apps/api/eslint.config.mjs",
|
|
10013
10019
|
template: `// @ts-check
|
|
10014
10020
|
import eslint from '@eslint/js';
|
|
@@ -10732,7 +10738,7 @@ describe('AppController (e2e)', () => {
|
|
|
10732
10738
|
//#region src/templates/deployment-standalone/index.ts
|
|
10733
10739
|
const deploymentStandalone = { templates: [
|
|
10734
10740
|
{
|
|
10735
|
-
when: (s) =>
|
|
10741
|
+
when: (s) => s.nest === "on",
|
|
10736
10742
|
filename: "Dockerfile",
|
|
10737
10743
|
template: `FROM node:24-alpine AS base
|
|
10738
10744
|
ENV PNPM_HOME="/pnpm"
|
|
@@ -10770,7 +10776,7 @@ WORKDIR /app
|
|
|
10770
10776
|
CMD ["pnpm", "db:migrate"]`
|
|
10771
10777
|
},
|
|
10772
10778
|
{
|
|
10773
|
-
when: (s) =>
|
|
10779
|
+
when: (s) => s.nest === "on",
|
|
10774
10780
|
filename: "docker-compose.yml",
|
|
10775
10781
|
template: `x-app-env: &app-env
|
|
10776
10782
|
BETTER_AUTH_SECRET: \${BETTER_AUTH_SECRET}
|
|
@@ -10848,7 +10854,7 @@ volumes:
|
|
|
10848
10854
|
db_data:`
|
|
10849
10855
|
},
|
|
10850
10856
|
{
|
|
10851
|
-
when: (s) =>
|
|
10857
|
+
when: (s) => s.nest === "on",
|
|
10852
10858
|
filename: "apps/web/next.config.js",
|
|
10853
10859
|
template: `import dotenv from 'dotenv';
|
|
10854
10860
|
import { resolve } from 'path';
|
|
@@ -11098,8 +11104,7 @@ export async function GET() {
|
|
|
11098
11104
|
"scripts": {
|
|
11099
11105
|
"dev": "next dev --port 3000",
|
|
11100
11106
|
"build": "next build",
|
|
11101
|
-
"start": "next start"
|
|
11102
|
-
"db:migrate": "better-auth migrate"
|
|
11107
|
+
"start": "next start"
|
|
11103
11108
|
},
|
|
11104
11109
|
"dependencies": {
|
|
11105
11110
|
"@<%= projectName %>/api": "workspace:*",
|
|
@@ -11183,8 +11188,38 @@ export default nextConfig;`
|
|
|
11183
11188
|
}
|
|
11184
11189
|
] };
|
|
11185
11190
|
//#endregion
|
|
11186
|
-
//#region src/templates/
|
|
11187
|
-
const
|
|
11191
|
+
//#region src/templates/nest-off/index.ts
|
|
11192
|
+
const nestOff = { templates: [{
|
|
11193
|
+
when: (s) => s.deployment === "none",
|
|
11194
|
+
filename: "apps/web/next.config.js",
|
|
11195
|
+
template: `import dotenv from 'dotenv';
|
|
11196
|
+
import { resolve } from 'path';
|
|
11197
|
+
|
|
11198
|
+
// Load root .env first, then local .env (local takes precedence)
|
|
11199
|
+
dotenv.config({ path: resolve(process.cwd(), '../../.env') });
|
|
11200
|
+
dotenv.config({ path: resolve(process.cwd(), '.env') });
|
|
11201
|
+
|
|
11202
|
+
// No /api rewrite: there is no second process, so Next serves /api itself.
|
|
11203
|
+
/** @type {import('next').NextConfig} */
|
|
11204
|
+
const nextConfig = {};
|
|
11205
|
+
|
|
11206
|
+
export default nextConfig;`
|
|
11207
|
+
}, {
|
|
11208
|
+
filename: "apps/web/app/api/hello/route.ts",
|
|
11209
|
+
template: `import { NextResponse } from 'next/server';
|
|
11210
|
+
import { headers } from 'next/headers';
|
|
11211
|
+
import { auth } from '@<%= projectName %>/auth';
|
|
11212
|
+
|
|
11213
|
+
export async function GET() {
|
|
11214
|
+
const session = await auth.api.getSession({ headers: await headers() });
|
|
11215
|
+
return NextResponse.json({
|
|
11216
|
+
message: session?.user.name ? \`Hello \${session.user.name}\` : 'Hello from Next',
|
|
11217
|
+
});
|
|
11218
|
+
}`
|
|
11219
|
+
}] };
|
|
11220
|
+
//#endregion
|
|
11221
|
+
//#region src/templates/deployment-standalone-web/index.ts
|
|
11222
|
+
const deploymentStandaloneWeb = { templates: [
|
|
11188
11223
|
{
|
|
11189
11224
|
filename: "Dockerfile",
|
|
11190
11225
|
template: `FROM node:24-alpine AS base
|
|
@@ -11196,11 +11231,11 @@ FROM base AS build
|
|
|
11196
11231
|
WORKDIR /app
|
|
11197
11232
|
COPY . .
|
|
11198
11233
|
RUN pnpm install --frozen-lockfile
|
|
11199
|
-
RUN pnpm build --filter=web --filter=@<%= projectName %>/api --filter=@<%= projectName %>/auth
|
|
11234
|
+
RUN pnpm build --filter=web<% if (nest === 'di-only') { %> --filter=@<%= projectName %>/api<% } %> --filter=@<%= projectName %>/auth
|
|
11200
11235
|
|
|
11201
11236
|
# --- web ---
|
|
11202
|
-
#
|
|
11203
|
-
# Next.js
|
|
11237
|
+
# One image: <% if (nest === 'di-only') { %>Nest is wired into the Next.js server rather than bootstrapped
|
|
11238
|
+
# on its own port<% } else { %>Next.js serves /api itself<% } %>, so there is no separate api stage.
|
|
11204
11239
|
FROM base AS web
|
|
11205
11240
|
WORKDIR /app
|
|
11206
11241
|
ENV NODE_ENV=production
|
|
@@ -11285,11 +11320,11 @@ import { resolve } from 'path';
|
|
|
11285
11320
|
dotenv.config({ path: resolve(process.cwd(), '../../.env') });
|
|
11286
11321
|
dotenv.config({ path: resolve(process.cwd(), '.env') });
|
|
11287
11322
|
|
|
11288
|
-
// No /api rewrite:
|
|
11289
|
-
//
|
|
11323
|
+
// No /api rewrite: Next serves /api itself, so there is no api container to
|
|
11324
|
+
// proxy to.
|
|
11290
11325
|
/** @type {import('next').NextConfig} */
|
|
11291
11326
|
const nextConfig = {
|
|
11292
|
-
output: "standalone"
|
|
11327
|
+
output: "standalone",<% if (nest === 'di-only') { %>
|
|
11293
11328
|
serverExternalPackages: [
|
|
11294
11329
|
'@<%= projectName %>/api',
|
|
11295
11330
|
'@<%= projectName %>/db',
|
|
@@ -11300,7 +11335,7 @@ const nextConfig = {
|
|
|
11300
11335
|
'@thallesp/nestjs-better-auth',
|
|
11301
11336
|
'reflect-metadata',
|
|
11302
11337
|
'express',
|
|
11303
|
-
]
|
|
11338
|
+
],<% } %>
|
|
11304
11339
|
};
|
|
11305
11340
|
|
|
11306
11341
|
export default nextConfig;`
|
|
@@ -11358,7 +11393,7 @@ describe('AppController', () => {
|
|
|
11358
11393
|
});`
|
|
11359
11394
|
},
|
|
11360
11395
|
{
|
|
11361
|
-
when: (s) =>
|
|
11396
|
+
when: (s) => s.nest === "on" && !s.todoExample,
|
|
11362
11397
|
filename: "apps/api/src/app.module.ts",
|
|
11363
11398
|
template: `<% if (deployment === 'spa') { %>import { join } from 'path';
|
|
11364
11399
|
<% } %>import { Module } from '@nestjs/common';
|
|
@@ -11411,7 +11446,7 @@ void bootstrap();`
|
|
|
11411
11446
|
//#endregion
|
|
11412
11447
|
//#region src/templates/todo-example/templates/todos-module.ts
|
|
11413
11448
|
var todos_module_default = {
|
|
11414
|
-
when: (s) => s.
|
|
11449
|
+
when: (s) => s.nest === "di-only",
|
|
11415
11450
|
filename: "apps/api/src/todos/todos.module.ts",
|
|
11416
11451
|
template: `import { Module } from '@nestjs/common';
|
|
11417
11452
|
import { TodosService } from './todos.service';
|
|
@@ -11671,7 +11706,7 @@ export class TodosModule {}`
|
|
|
11671
11706
|
//#endregion
|
|
11672
11707
|
//#region src/templates/todo-example/templates/app-module-controllers.ts
|
|
11673
11708
|
var app_module_controllers_default = {
|
|
11674
|
-
when: (s) =>
|
|
11709
|
+
when: (s) => s.nest === "on" && s.todoExample,
|
|
11675
11710
|
filename: "apps/api/src/app.module.ts",
|
|
11676
11711
|
template: `<% if (deployment === 'spa') { %>import { join } from 'path';
|
|
11677
11712
|
<% } %>import { Module } from '@nestjs/common';
|
|
@@ -11702,7 +11737,7 @@ export class AppModule {}`
|
|
|
11702
11737
|
//#endregion
|
|
11703
11738
|
//#region src/templates/todo-example/templates/app-module-di.ts
|
|
11704
11739
|
var app_module_di_default = {
|
|
11705
|
-
when: (s) => s.
|
|
11740
|
+
when: (s) => s.nest === "di-only" && s.todoExample,
|
|
11706
11741
|
filename: "apps/api/src/app.module.ts",
|
|
11707
11742
|
template: `import { Module } from '@nestjs/common';
|
|
11708
11743
|
import { AppService } from './app.service';
|
|
@@ -12306,35 +12341,36 @@ const E2E_FILES = [
|
|
|
12306
12341
|
"apps/api/vitest.config.e2e.mts"
|
|
12307
12342
|
];
|
|
12308
12343
|
function selectModules(selection) {
|
|
12309
|
-
const { deployment,
|
|
12344
|
+
const { deployment, nest, todoExample, shadcn, database, linter, testing, extras } = selection;
|
|
12310
12345
|
const deploymentModule = deployment === "standalone" ? deploymentStandalone : deployment === "spa" ? singleProcessStaticExport : null;
|
|
12311
12346
|
const webModule = deployment === "spa" ? {
|
|
12312
12347
|
...web$1,
|
|
12313
12348
|
templates: web$1.templates.filter((t) => t.filename !== "apps/web/app/api/auth/[...all]/route.ts")
|
|
12314
12349
|
} : web$1;
|
|
12315
12350
|
const selectedTesting = testing === "vitest" ? testingVitest : testingJest;
|
|
12316
|
-
const testingModule =
|
|
12351
|
+
const testingModule = nest === "off" ? null : nest === "di-only" ? {
|
|
12317
12352
|
...selectedTesting,
|
|
12318
12353
|
templates: selectedTesting.templates.filter((t) => !E2E_FILES.includes(t.filename)),
|
|
12319
12354
|
scripts: selectedTesting.scripts?.filter((s) => s.name !== "test:e2e")
|
|
12320
12355
|
} : selectedTesting;
|
|
12356
|
+
const nestModule = nest === "di-only" ? nestDiOnly : nest === "off" ? nestOff : apiControllers;
|
|
12321
12357
|
return [
|
|
12322
12358
|
root$2,
|
|
12323
12359
|
webModule,
|
|
12324
|
-
api$1,
|
|
12360
|
+
...nest === "off" ? [] : [api$1],
|
|
12325
12361
|
database === "postgres" ? dbPostgres : dbSqlite,
|
|
12326
12362
|
auth,
|
|
12327
12363
|
shadcn ? shadcnUi : ui$1,
|
|
12328
12364
|
linter === "oxc" ? oxc : eslintConfig,
|
|
12329
12365
|
...extras.includes("anti-slop") ? [antiSlop] : [],
|
|
12330
12366
|
typescriptConfig,
|
|
12331
|
-
testingModule,
|
|
12367
|
+
...testingModule ? [testingModule] : [],
|
|
12332
12368
|
...deploymentModule ? [deploymentModule] : [],
|
|
12333
|
-
|
|
12334
|
-
...
|
|
12369
|
+
nestModule,
|
|
12370
|
+
...nest !== "on" && deployment === "standalone" ? [deploymentStandaloneWeb] : [],
|
|
12335
12371
|
...todoExample ? [
|
|
12336
12372
|
todoExampleApi,
|
|
12337
|
-
...
|
|
12373
|
+
...nest === "di-only" ? [todoExampleDi] : [todoExampleControllers],
|
|
12338
12374
|
shadcn ? todoExampleShadcn : todoExampleWeb
|
|
12339
12375
|
] : []
|
|
12340
12376
|
];
|
|
@@ -12442,10 +12478,21 @@ function validateExtrasCombo(extras, linter) {
|
|
|
12442
12478
|
};
|
|
12443
12479
|
return { valid: true };
|
|
12444
12480
|
}
|
|
12445
|
-
function validateDeploymentCombo(deployment,
|
|
12446
|
-
if (deployment === "spa" &&
|
|
12481
|
+
function validateDeploymentCombo(deployment, nest) {
|
|
12482
|
+
if (deployment === "spa" && nest === "di-only") return {
|
|
12483
|
+
valid: false,
|
|
12484
|
+
error: "--deployment spa cannot be combined with --nest di-only.\nSPA mode statically exports Next.js (output: 'export'), which cannot include the\nAPI route handlers that di-only mode depends on. Pick one: --nest on to get SPA\nmode with NestJS controllers, or drop --deployment spa."
|
|
12485
|
+
};
|
|
12486
|
+
if (deployment === "spa" && nest === "off") return {
|
|
12447
12487
|
valid: false,
|
|
12448
|
-
error: "--deployment spa cannot be combined with --nest
|
|
12488
|
+
error: "--deployment spa cannot be combined with --nest off.\nSPA mode statically exports Next.js and hands the output to NestJS to serve, so\nthere is nothing left to serve it. Pick one: --nest on, or drop --deployment spa."
|
|
12489
|
+
};
|
|
12490
|
+
return { valid: true };
|
|
12491
|
+
}
|
|
12492
|
+
function validateExampleCombo(todoExample, nest) {
|
|
12493
|
+
if (todoExample && nest === "off") return {
|
|
12494
|
+
valid: false,
|
|
12495
|
+
error: "--include-example cannot be combined with --nest off.\nThe todo example is a Nest module: an @Injectable service plus either a controller\nor a Next.js route handler that resolves it. Pick one: --nest on or --nest di-only,\nor drop --include-example."
|
|
12449
12496
|
};
|
|
12450
12497
|
return { valid: true };
|
|
12451
12498
|
}
|
|
@@ -12502,7 +12549,7 @@ async function scaffold(modules, options) {
|
|
|
12502
12549
|
}
|
|
12503
12550
|
const templateData = {
|
|
12504
12551
|
projectName: options.name,
|
|
12505
|
-
|
|
12552
|
+
nest: options.selection.nest,
|
|
12506
12553
|
testing: options.testing,
|
|
12507
12554
|
database: options.database,
|
|
12508
12555
|
deployment: options.deployment,
|
|
@@ -12590,7 +12637,7 @@ function buildPayload(report) {
|
|
|
12590
12637
|
database: selection.database,
|
|
12591
12638
|
linter: selection.linter,
|
|
12592
12639
|
deployment: selection.deployment,
|
|
12593
|
-
|
|
12640
|
+
nest: selection.nest,
|
|
12594
12641
|
todoExample: selection.todoExample,
|
|
12595
12642
|
antiSlop: selection.extras.includes("anti-slop")
|
|
12596
12643
|
};
|
|
@@ -12635,6 +12682,11 @@ const DEPLOYMENT_CHOICES = [
|
|
|
12635
12682
|
"standalone",
|
|
12636
12683
|
"spa"
|
|
12637
12684
|
];
|
|
12685
|
+
const NEST_CHOICES = [
|
|
12686
|
+
"on",
|
|
12687
|
+
"off",
|
|
12688
|
+
"di-only"
|
|
12689
|
+
];
|
|
12638
12690
|
const EXTRAS_CHOICES = ["anti-slop"];
|
|
12639
12691
|
var TaskBuilder = class {
|
|
12640
12692
|
tasks = [];
|
|
@@ -12654,7 +12706,28 @@ async function doInit(options) {
|
|
|
12654
12706
|
message: "Use shadcn/ui?",
|
|
12655
12707
|
initialValue: true
|
|
12656
12708
|
}),
|
|
12657
|
-
|
|
12709
|
+
nest: () => p.select({
|
|
12710
|
+
message: "NestJS?",
|
|
12711
|
+
options: [
|
|
12712
|
+
{
|
|
12713
|
+
value: "on",
|
|
12714
|
+
label: "On",
|
|
12715
|
+
hint: "apps/api on port 3001"
|
|
12716
|
+
},
|
|
12717
|
+
{
|
|
12718
|
+
value: "di-only",
|
|
12719
|
+
label: "DI only",
|
|
12720
|
+
hint: "no HTTP server; Next.js route handlers inject its services"
|
|
12721
|
+
},
|
|
12722
|
+
{
|
|
12723
|
+
value: "off",
|
|
12724
|
+
label: "Off",
|
|
12725
|
+
hint: "no apps/api; Next.js owns the backend"
|
|
12726
|
+
}
|
|
12727
|
+
],
|
|
12728
|
+
initialValue: "on"
|
|
12729
|
+
}),
|
|
12730
|
+
testing: ({ results }) => results.nest === "off" ? void 0 : p.select({
|
|
12658
12731
|
message: "Testing framework?",
|
|
12659
12732
|
options: [{
|
|
12660
12733
|
value: "jest",
|
|
@@ -12696,11 +12769,7 @@ async function doInit(options) {
|
|
|
12696
12769
|
}],
|
|
12697
12770
|
required: false
|
|
12698
12771
|
}) : void 0,
|
|
12699
|
-
|
|
12700
|
-
message: "Use NestJS for dependency injection only?",
|
|
12701
|
-
initialValue: false
|
|
12702
|
-
}),
|
|
12703
|
-
todoExample: () => p.confirm({
|
|
12772
|
+
todoExample: ({ results }) => results.nest === "off" ? void 0 : p.confirm({
|
|
12704
12773
|
message: "Include the todo example?",
|
|
12705
12774
|
initialValue: true
|
|
12706
12775
|
}),
|
|
@@ -12717,11 +12786,11 @@ async function doInit(options) {
|
|
|
12717
12786
|
label: "Standalone + Dockerfile",
|
|
12718
12787
|
hint: "Dockerfiles + docker-compose.yml"
|
|
12719
12788
|
},
|
|
12720
|
-
...results.
|
|
12789
|
+
...results.nest === "on" ? [{
|
|
12721
12790
|
value: "spa",
|
|
12722
12791
|
label: "SPA Mode",
|
|
12723
12792
|
hint: "static export served by NestJS"
|
|
12724
|
-
}]
|
|
12793
|
+
}] : []
|
|
12725
12794
|
],
|
|
12726
12795
|
initialValue: "none"
|
|
12727
12796
|
})
|
|
@@ -12746,16 +12815,18 @@ async function doInit(options) {
|
|
|
12746
12815
|
const database = options.nonInteractive ? options.database : answers.database ?? "sqlite";
|
|
12747
12816
|
const linter = options.nonInteractive ? options.linter : answers.linter ?? "eslint";
|
|
12748
12817
|
const deployment = options.nonInteractive ? options.deployment : answers.deployment ?? "none";
|
|
12749
|
-
const
|
|
12750
|
-
const todoExample = options.nonInteractive ? options.includeExample : answers.todoExample ?? true;
|
|
12818
|
+
const nest = options.nonInteractive ? options.nest : answers.nest ?? "on";
|
|
12819
|
+
const todoExample = options.nonInteractive ? options.includeExample : nest !== "off" && (answers.todoExample ?? true);
|
|
12751
12820
|
const extras = options.nonInteractive ? options.extras : answers.extras ?? [];
|
|
12752
|
-
const deploymentCombo = validateDeploymentCombo(deployment,
|
|
12821
|
+
const deploymentCombo = validateDeploymentCombo(deployment, nest);
|
|
12753
12822
|
if (!deploymentCombo.valid) throw new Error(deploymentCombo.error);
|
|
12823
|
+
const exampleCombo = validateExampleCombo(todoExample, nest);
|
|
12824
|
+
if (!exampleCombo.valid) throw new Error(exampleCombo.error);
|
|
12754
12825
|
const extrasCombo = validateExtrasCombo(extras, linter);
|
|
12755
12826
|
if (!extrasCombo.valid) throw new Error(extrasCombo.error);
|
|
12756
12827
|
const selection = {
|
|
12757
12828
|
deployment,
|
|
12758
|
-
|
|
12829
|
+
nest,
|
|
12759
12830
|
todoExample,
|
|
12760
12831
|
shadcn: useShadcn,
|
|
12761
12832
|
database,
|
|
@@ -12826,7 +12897,7 @@ async function doInit(options) {
|
|
|
12826
12897
|
}
|
|
12827
12898
|
}
|
|
12828
12899
|
const program = new Command();
|
|
12829
|
-
program.name("create-newt-app").version(version).description("Create a new newt-app monorepo").argument("[name]").option("-ni, --no-install", "Skip pnpm install", true).option("-ng, --no-git", "Skip git initialization", true).option("--shadcn", "Include shadcn/ui", false).option("--testing <framework>", "Testing framework: vitest or jest", "jest").option("--database <database>", "Database: sqlite or postgres", "sqlite").option("--linter <linter>", "Linter: eslint or oxc", "eslint").option("--deployment <strategy>", "Deployment: none, standalone, or spa", "none").option("--nest
|
|
12900
|
+
program.name("create-newt-app").version(version).description("Create a new newt-app monorepo").argument("[name]").option("-ni, --no-install", "Skip pnpm install", true).option("-ng, --no-git", "Skip git initialization", true).option("--shadcn", "Include shadcn/ui", false).option("--testing <framework>", "Testing framework: vitest or jest", "jest").option("--database <database>", "Database: sqlite or postgres", "sqlite").option("--linter <linter>", "Linter: eslint or oxc", "eslint").option("--deployment <strategy>", "Deployment: none, standalone, or spa", "none").option("--nest <mode>", "NestJS: on, off, or di-only", "on").option("--include-example", "Include the todo example", false).option("--extras <list>", "Extras, comma-separated: anti-slop", "").action(async (name, options, command) => {
|
|
12830
12901
|
intro(`Create a ${chalk.blue("newt")} app.`);
|
|
12831
12902
|
const explicitFlags = Object.entries({
|
|
12832
12903
|
shadcn: "--shadcn",
|
|
@@ -12834,7 +12905,7 @@ program.name("create-newt-app").version(version).description("Create a new newt-
|
|
|
12834
12905
|
database: "--database",
|
|
12835
12906
|
linter: "--linter",
|
|
12836
12907
|
deployment: "--deployment",
|
|
12837
|
-
|
|
12908
|
+
nest: "--nest",
|
|
12838
12909
|
includeExample: "--include-example",
|
|
12839
12910
|
extras: "--extras"
|
|
12840
12911
|
}).filter(([option]) => command.getOptionValueSource(option) === "cli").map(([, flag]) => flag);
|
|
@@ -12861,6 +12932,11 @@ program.name("create-newt-app").version(version).description("Create a new newt-
|
|
|
12861
12932
|
value: options.deployment,
|
|
12862
12933
|
allowed: DEPLOYMENT_CHOICES
|
|
12863
12934
|
},
|
|
12935
|
+
{
|
|
12936
|
+
flag: "--nest",
|
|
12937
|
+
value: options.nest,
|
|
12938
|
+
allowed: NEST_CHOICES
|
|
12939
|
+
},
|
|
12864
12940
|
...extras.map((extra) => ({
|
|
12865
12941
|
flag: "--extras",
|
|
12866
12942
|
value: extra,
|
|
@@ -12881,7 +12957,7 @@ program.name("create-newt-app").version(version).description("Create a new newt-
|
|
|
12881
12957
|
database: options.database,
|
|
12882
12958
|
linter: options.linter,
|
|
12883
12959
|
deployment: options.deployment,
|
|
12884
|
-
|
|
12960
|
+
nest: options.nest,
|
|
12885
12961
|
includeExample: options.includeExample,
|
|
12886
12962
|
extras,
|
|
12887
12963
|
explicitFlags
|