create-newt-app 0.31.10 → 0.32.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.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +130 -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.0";
|
|
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
|
}
|
|
@@ -10009,6 +10012,7 @@ export default nextJsConfig;`
|
|
|
10009
10012
|
//#endregion
|
|
10010
10013
|
//#region src/templates/api/templates/eslint-config.ts
|
|
10011
10014
|
var eslint_config_default$1 = {
|
|
10015
|
+
when: (s) => s.nest !== "off",
|
|
10012
10016
|
filename: "apps/api/eslint.config.mjs",
|
|
10013
10017
|
template: `// @ts-check
|
|
10014
10018
|
import eslint from '@eslint/js';
|
|
@@ -10732,7 +10736,7 @@ describe('AppController (e2e)', () => {
|
|
|
10732
10736
|
//#region src/templates/deployment-standalone/index.ts
|
|
10733
10737
|
const deploymentStandalone = { templates: [
|
|
10734
10738
|
{
|
|
10735
|
-
when: (s) =>
|
|
10739
|
+
when: (s) => s.nest === "on",
|
|
10736
10740
|
filename: "Dockerfile",
|
|
10737
10741
|
template: `FROM node:24-alpine AS base
|
|
10738
10742
|
ENV PNPM_HOME="/pnpm"
|
|
@@ -10770,7 +10774,7 @@ WORKDIR /app
|
|
|
10770
10774
|
CMD ["pnpm", "db:migrate"]`
|
|
10771
10775
|
},
|
|
10772
10776
|
{
|
|
10773
|
-
when: (s) =>
|
|
10777
|
+
when: (s) => s.nest === "on",
|
|
10774
10778
|
filename: "docker-compose.yml",
|
|
10775
10779
|
template: `x-app-env: &app-env
|
|
10776
10780
|
BETTER_AUTH_SECRET: \${BETTER_AUTH_SECRET}
|
|
@@ -10848,7 +10852,7 @@ volumes:
|
|
|
10848
10852
|
db_data:`
|
|
10849
10853
|
},
|
|
10850
10854
|
{
|
|
10851
|
-
when: (s) =>
|
|
10855
|
+
when: (s) => s.nest === "on",
|
|
10852
10856
|
filename: "apps/web/next.config.js",
|
|
10853
10857
|
template: `import dotenv from 'dotenv';
|
|
10854
10858
|
import { resolve } from 'path';
|
|
@@ -11098,8 +11102,7 @@ export async function GET() {
|
|
|
11098
11102
|
"scripts": {
|
|
11099
11103
|
"dev": "next dev --port 3000",
|
|
11100
11104
|
"build": "next build",
|
|
11101
|
-
"start": "next start"
|
|
11102
|
-
"db:migrate": "better-auth migrate"
|
|
11105
|
+
"start": "next start"
|
|
11103
11106
|
},
|
|
11104
11107
|
"dependencies": {
|
|
11105
11108
|
"@<%= projectName %>/api": "workspace:*",
|
|
@@ -11183,8 +11186,38 @@ export default nextConfig;`
|
|
|
11183
11186
|
}
|
|
11184
11187
|
] };
|
|
11185
11188
|
//#endregion
|
|
11186
|
-
//#region src/templates/
|
|
11187
|
-
const
|
|
11189
|
+
//#region src/templates/nest-off/index.ts
|
|
11190
|
+
const nestOff = { templates: [{
|
|
11191
|
+
when: (s) => s.deployment === "none",
|
|
11192
|
+
filename: "apps/web/next.config.js",
|
|
11193
|
+
template: `import dotenv from 'dotenv';
|
|
11194
|
+
import { resolve } from 'path';
|
|
11195
|
+
|
|
11196
|
+
// Load root .env first, then local .env (local takes precedence)
|
|
11197
|
+
dotenv.config({ path: resolve(process.cwd(), '../../.env') });
|
|
11198
|
+
dotenv.config({ path: resolve(process.cwd(), '.env') });
|
|
11199
|
+
|
|
11200
|
+
// No /api rewrite: there is no second process, so Next serves /api itself.
|
|
11201
|
+
/** @type {import('next').NextConfig} */
|
|
11202
|
+
const nextConfig = {};
|
|
11203
|
+
|
|
11204
|
+
export default nextConfig;`
|
|
11205
|
+
}, {
|
|
11206
|
+
filename: "apps/web/app/api/hello/route.ts",
|
|
11207
|
+
template: `import { NextResponse } from 'next/server';
|
|
11208
|
+
import { headers } from 'next/headers';
|
|
11209
|
+
import { auth } from '@<%= projectName %>/auth';
|
|
11210
|
+
|
|
11211
|
+
export async function GET() {
|
|
11212
|
+
const session = await auth.api.getSession({ headers: await headers() });
|
|
11213
|
+
return NextResponse.json({
|
|
11214
|
+
message: session?.user.name ? \`Hello \${session.user.name}\` : 'Hello from Next',
|
|
11215
|
+
});
|
|
11216
|
+
}`
|
|
11217
|
+
}] };
|
|
11218
|
+
//#endregion
|
|
11219
|
+
//#region src/templates/deployment-standalone-web/index.ts
|
|
11220
|
+
const deploymentStandaloneWeb = { templates: [
|
|
11188
11221
|
{
|
|
11189
11222
|
filename: "Dockerfile",
|
|
11190
11223
|
template: `FROM node:24-alpine AS base
|
|
@@ -11196,11 +11229,11 @@ FROM base AS build
|
|
|
11196
11229
|
WORKDIR /app
|
|
11197
11230
|
COPY . .
|
|
11198
11231
|
RUN pnpm install --frozen-lockfile
|
|
11199
|
-
RUN pnpm build --filter=web --filter=@<%= projectName %>/api --filter=@<%= projectName %>/auth
|
|
11232
|
+
RUN pnpm build --filter=web<% if (nest === 'di-only') { %> --filter=@<%= projectName %>/api<% } %> --filter=@<%= projectName %>/auth
|
|
11200
11233
|
|
|
11201
11234
|
# --- web ---
|
|
11202
|
-
#
|
|
11203
|
-
# Next.js
|
|
11235
|
+
# One image: <% if (nest === 'di-only') { %>Nest is wired into the Next.js server rather than bootstrapped
|
|
11236
|
+
# on its own port<% } else { %>Next.js serves /api itself<% } %>, so there is no separate api stage.
|
|
11204
11237
|
FROM base AS web
|
|
11205
11238
|
WORKDIR /app
|
|
11206
11239
|
ENV NODE_ENV=production
|
|
@@ -11285,11 +11318,11 @@ import { resolve } from 'path';
|
|
|
11285
11318
|
dotenv.config({ path: resolve(process.cwd(), '../../.env') });
|
|
11286
11319
|
dotenv.config({ path: resolve(process.cwd(), '.env') });
|
|
11287
11320
|
|
|
11288
|
-
// No /api rewrite:
|
|
11289
|
-
//
|
|
11321
|
+
// No /api rewrite: Next serves /api itself, so there is no api container to
|
|
11322
|
+
// proxy to.
|
|
11290
11323
|
/** @type {import('next').NextConfig} */
|
|
11291
11324
|
const nextConfig = {
|
|
11292
|
-
output: "standalone"
|
|
11325
|
+
output: "standalone",<% if (nest === 'di-only') { %>
|
|
11293
11326
|
serverExternalPackages: [
|
|
11294
11327
|
'@<%= projectName %>/api',
|
|
11295
11328
|
'@<%= projectName %>/db',
|
|
@@ -11300,7 +11333,7 @@ const nextConfig = {
|
|
|
11300
11333
|
'@thallesp/nestjs-better-auth',
|
|
11301
11334
|
'reflect-metadata',
|
|
11302
11335
|
'express',
|
|
11303
|
-
]
|
|
11336
|
+
],<% } %>
|
|
11304
11337
|
};
|
|
11305
11338
|
|
|
11306
11339
|
export default nextConfig;`
|
|
@@ -11358,7 +11391,7 @@ describe('AppController', () => {
|
|
|
11358
11391
|
});`
|
|
11359
11392
|
},
|
|
11360
11393
|
{
|
|
11361
|
-
when: (s) =>
|
|
11394
|
+
when: (s) => s.nest === "on" && !s.todoExample,
|
|
11362
11395
|
filename: "apps/api/src/app.module.ts",
|
|
11363
11396
|
template: `<% if (deployment === 'spa') { %>import { join } from 'path';
|
|
11364
11397
|
<% } %>import { Module } from '@nestjs/common';
|
|
@@ -11411,7 +11444,7 @@ void bootstrap();`
|
|
|
11411
11444
|
//#endregion
|
|
11412
11445
|
//#region src/templates/todo-example/templates/todos-module.ts
|
|
11413
11446
|
var todos_module_default = {
|
|
11414
|
-
when: (s) => s.
|
|
11447
|
+
when: (s) => s.nest === "di-only",
|
|
11415
11448
|
filename: "apps/api/src/todos/todos.module.ts",
|
|
11416
11449
|
template: `import { Module } from '@nestjs/common';
|
|
11417
11450
|
import { TodosService } from './todos.service';
|
|
@@ -11671,7 +11704,7 @@ export class TodosModule {}`
|
|
|
11671
11704
|
//#endregion
|
|
11672
11705
|
//#region src/templates/todo-example/templates/app-module-controllers.ts
|
|
11673
11706
|
var app_module_controllers_default = {
|
|
11674
|
-
when: (s) =>
|
|
11707
|
+
when: (s) => s.nest === "on" && s.todoExample,
|
|
11675
11708
|
filename: "apps/api/src/app.module.ts",
|
|
11676
11709
|
template: `<% if (deployment === 'spa') { %>import { join } from 'path';
|
|
11677
11710
|
<% } %>import { Module } from '@nestjs/common';
|
|
@@ -11702,7 +11735,7 @@ export class AppModule {}`
|
|
|
11702
11735
|
//#endregion
|
|
11703
11736
|
//#region src/templates/todo-example/templates/app-module-di.ts
|
|
11704
11737
|
var app_module_di_default = {
|
|
11705
|
-
when: (s) => s.
|
|
11738
|
+
when: (s) => s.nest === "di-only" && s.todoExample,
|
|
11706
11739
|
filename: "apps/api/src/app.module.ts",
|
|
11707
11740
|
template: `import { Module } from '@nestjs/common';
|
|
11708
11741
|
import { AppService } from './app.service';
|
|
@@ -12306,35 +12339,36 @@ const E2E_FILES = [
|
|
|
12306
12339
|
"apps/api/vitest.config.e2e.mts"
|
|
12307
12340
|
];
|
|
12308
12341
|
function selectModules(selection) {
|
|
12309
|
-
const { deployment,
|
|
12342
|
+
const { deployment, nest, todoExample, shadcn, database, linter, testing, extras } = selection;
|
|
12310
12343
|
const deploymentModule = deployment === "standalone" ? deploymentStandalone : deployment === "spa" ? singleProcessStaticExport : null;
|
|
12311
12344
|
const webModule = deployment === "spa" ? {
|
|
12312
12345
|
...web$1,
|
|
12313
12346
|
templates: web$1.templates.filter((t) => t.filename !== "apps/web/app/api/auth/[...all]/route.ts")
|
|
12314
12347
|
} : web$1;
|
|
12315
12348
|
const selectedTesting = testing === "vitest" ? testingVitest : testingJest;
|
|
12316
|
-
const testingModule =
|
|
12349
|
+
const testingModule = nest === "off" ? null : nest === "di-only" ? {
|
|
12317
12350
|
...selectedTesting,
|
|
12318
12351
|
templates: selectedTesting.templates.filter((t) => !E2E_FILES.includes(t.filename)),
|
|
12319
12352
|
scripts: selectedTesting.scripts?.filter((s) => s.name !== "test:e2e")
|
|
12320
12353
|
} : selectedTesting;
|
|
12354
|
+
const nestModule = nest === "di-only" ? nestDiOnly : nest === "off" ? nestOff : apiControllers;
|
|
12321
12355
|
return [
|
|
12322
12356
|
root$2,
|
|
12323
12357
|
webModule,
|
|
12324
|
-
api$1,
|
|
12358
|
+
...nest === "off" ? [] : [api$1],
|
|
12325
12359
|
database === "postgres" ? dbPostgres : dbSqlite,
|
|
12326
12360
|
auth,
|
|
12327
12361
|
shadcn ? shadcnUi : ui$1,
|
|
12328
12362
|
linter === "oxc" ? oxc : eslintConfig,
|
|
12329
12363
|
...extras.includes("anti-slop") ? [antiSlop] : [],
|
|
12330
12364
|
typescriptConfig,
|
|
12331
|
-
testingModule,
|
|
12365
|
+
...testingModule ? [testingModule] : [],
|
|
12332
12366
|
...deploymentModule ? [deploymentModule] : [],
|
|
12333
|
-
|
|
12334
|
-
...
|
|
12367
|
+
nestModule,
|
|
12368
|
+
...nest !== "on" && deployment === "standalone" ? [deploymentStandaloneWeb] : [],
|
|
12335
12369
|
...todoExample ? [
|
|
12336
12370
|
todoExampleApi,
|
|
12337
|
-
...
|
|
12371
|
+
...nest === "di-only" ? [todoExampleDi] : [todoExampleControllers],
|
|
12338
12372
|
shadcn ? todoExampleShadcn : todoExampleWeb
|
|
12339
12373
|
] : []
|
|
12340
12374
|
];
|
|
@@ -12442,10 +12476,21 @@ function validateExtrasCombo(extras, linter) {
|
|
|
12442
12476
|
};
|
|
12443
12477
|
return { valid: true };
|
|
12444
12478
|
}
|
|
12445
|
-
function validateDeploymentCombo(deployment,
|
|
12446
|
-
if (deployment === "spa" &&
|
|
12479
|
+
function validateDeploymentCombo(deployment, nest) {
|
|
12480
|
+
if (deployment === "spa" && nest === "di-only") return {
|
|
12481
|
+
valid: false,
|
|
12482
|
+
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."
|
|
12483
|
+
};
|
|
12484
|
+
if (deployment === "spa" && nest === "off") return {
|
|
12447
12485
|
valid: false,
|
|
12448
|
-
error: "--deployment spa cannot be combined with --nest
|
|
12486
|
+
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."
|
|
12487
|
+
};
|
|
12488
|
+
return { valid: true };
|
|
12489
|
+
}
|
|
12490
|
+
function validateExampleCombo(todoExample, nest) {
|
|
12491
|
+
if (todoExample && nest === "off") return {
|
|
12492
|
+
valid: false,
|
|
12493
|
+
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
12494
|
};
|
|
12450
12495
|
return { valid: true };
|
|
12451
12496
|
}
|
|
@@ -12502,7 +12547,7 @@ async function scaffold(modules, options) {
|
|
|
12502
12547
|
}
|
|
12503
12548
|
const templateData = {
|
|
12504
12549
|
projectName: options.name,
|
|
12505
|
-
|
|
12550
|
+
nest: options.selection.nest,
|
|
12506
12551
|
testing: options.testing,
|
|
12507
12552
|
database: options.database,
|
|
12508
12553
|
deployment: options.deployment,
|
|
@@ -12590,7 +12635,7 @@ function buildPayload(report) {
|
|
|
12590
12635
|
database: selection.database,
|
|
12591
12636
|
linter: selection.linter,
|
|
12592
12637
|
deployment: selection.deployment,
|
|
12593
|
-
|
|
12638
|
+
nest: selection.nest,
|
|
12594
12639
|
todoExample: selection.todoExample,
|
|
12595
12640
|
antiSlop: selection.extras.includes("anti-slop")
|
|
12596
12641
|
};
|
|
@@ -12635,6 +12680,11 @@ const DEPLOYMENT_CHOICES = [
|
|
|
12635
12680
|
"standalone",
|
|
12636
12681
|
"spa"
|
|
12637
12682
|
];
|
|
12683
|
+
const NEST_CHOICES = [
|
|
12684
|
+
"on",
|
|
12685
|
+
"off",
|
|
12686
|
+
"di-only"
|
|
12687
|
+
];
|
|
12638
12688
|
const EXTRAS_CHOICES = ["anti-slop"];
|
|
12639
12689
|
var TaskBuilder = class {
|
|
12640
12690
|
tasks = [];
|
|
@@ -12654,7 +12704,28 @@ async function doInit(options) {
|
|
|
12654
12704
|
message: "Use shadcn/ui?",
|
|
12655
12705
|
initialValue: true
|
|
12656
12706
|
}),
|
|
12657
|
-
|
|
12707
|
+
nest: () => p.select({
|
|
12708
|
+
message: "NestJS?",
|
|
12709
|
+
options: [
|
|
12710
|
+
{
|
|
12711
|
+
value: "on",
|
|
12712
|
+
label: "On",
|
|
12713
|
+
hint: "apps/api on port 3001"
|
|
12714
|
+
},
|
|
12715
|
+
{
|
|
12716
|
+
value: "di-only",
|
|
12717
|
+
label: "DI only",
|
|
12718
|
+
hint: "no HTTP server; Next.js route handlers inject its services"
|
|
12719
|
+
},
|
|
12720
|
+
{
|
|
12721
|
+
value: "off",
|
|
12722
|
+
label: "Off",
|
|
12723
|
+
hint: "no apps/api; Next.js owns the backend"
|
|
12724
|
+
}
|
|
12725
|
+
],
|
|
12726
|
+
initialValue: "on"
|
|
12727
|
+
}),
|
|
12728
|
+
testing: ({ results }) => results.nest === "off" ? void 0 : p.select({
|
|
12658
12729
|
message: "Testing framework?",
|
|
12659
12730
|
options: [{
|
|
12660
12731
|
value: "jest",
|
|
@@ -12696,11 +12767,7 @@ async function doInit(options) {
|
|
|
12696
12767
|
}],
|
|
12697
12768
|
required: false
|
|
12698
12769
|
}) : void 0,
|
|
12699
|
-
|
|
12700
|
-
message: "Use NestJS for dependency injection only?",
|
|
12701
|
-
initialValue: false
|
|
12702
|
-
}),
|
|
12703
|
-
todoExample: () => p.confirm({
|
|
12770
|
+
todoExample: ({ results }) => results.nest === "off" ? void 0 : p.confirm({
|
|
12704
12771
|
message: "Include the todo example?",
|
|
12705
12772
|
initialValue: true
|
|
12706
12773
|
}),
|
|
@@ -12717,11 +12784,11 @@ async function doInit(options) {
|
|
|
12717
12784
|
label: "Standalone + Dockerfile",
|
|
12718
12785
|
hint: "Dockerfiles + docker-compose.yml"
|
|
12719
12786
|
},
|
|
12720
|
-
...results.
|
|
12787
|
+
...results.nest === "on" ? [{
|
|
12721
12788
|
value: "spa",
|
|
12722
12789
|
label: "SPA Mode",
|
|
12723
12790
|
hint: "static export served by NestJS"
|
|
12724
|
-
}]
|
|
12791
|
+
}] : []
|
|
12725
12792
|
],
|
|
12726
12793
|
initialValue: "none"
|
|
12727
12794
|
})
|
|
@@ -12746,16 +12813,18 @@ async function doInit(options) {
|
|
|
12746
12813
|
const database = options.nonInteractive ? options.database : answers.database ?? "sqlite";
|
|
12747
12814
|
const linter = options.nonInteractive ? options.linter : answers.linter ?? "eslint";
|
|
12748
12815
|
const deployment = options.nonInteractive ? options.deployment : answers.deployment ?? "none";
|
|
12749
|
-
const
|
|
12750
|
-
const todoExample = options.nonInteractive ? options.includeExample : answers.todoExample ?? true;
|
|
12816
|
+
const nest = options.nonInteractive ? options.nest : answers.nest ?? "on";
|
|
12817
|
+
const todoExample = options.nonInteractive ? options.includeExample : nest !== "off" && (answers.todoExample ?? true);
|
|
12751
12818
|
const extras = options.nonInteractive ? options.extras : answers.extras ?? [];
|
|
12752
|
-
const deploymentCombo = validateDeploymentCombo(deployment,
|
|
12819
|
+
const deploymentCombo = validateDeploymentCombo(deployment, nest);
|
|
12753
12820
|
if (!deploymentCombo.valid) throw new Error(deploymentCombo.error);
|
|
12821
|
+
const exampleCombo = validateExampleCombo(todoExample, nest);
|
|
12822
|
+
if (!exampleCombo.valid) throw new Error(exampleCombo.error);
|
|
12754
12823
|
const extrasCombo = validateExtrasCombo(extras, linter);
|
|
12755
12824
|
if (!extrasCombo.valid) throw new Error(extrasCombo.error);
|
|
12756
12825
|
const selection = {
|
|
12757
12826
|
deployment,
|
|
12758
|
-
|
|
12827
|
+
nest,
|
|
12759
12828
|
todoExample,
|
|
12760
12829
|
shadcn: useShadcn,
|
|
12761
12830
|
database,
|
|
@@ -12826,7 +12895,7 @@ async function doInit(options) {
|
|
|
12826
12895
|
}
|
|
12827
12896
|
}
|
|
12828
12897
|
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
|
|
12898
|
+
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
12899
|
intro(`Create a ${chalk.blue("newt")} app.`);
|
|
12831
12900
|
const explicitFlags = Object.entries({
|
|
12832
12901
|
shadcn: "--shadcn",
|
|
@@ -12834,7 +12903,7 @@ program.name("create-newt-app").version(version).description("Create a new newt-
|
|
|
12834
12903
|
database: "--database",
|
|
12835
12904
|
linter: "--linter",
|
|
12836
12905
|
deployment: "--deployment",
|
|
12837
|
-
|
|
12906
|
+
nest: "--nest",
|
|
12838
12907
|
includeExample: "--include-example",
|
|
12839
12908
|
extras: "--extras"
|
|
12840
12909
|
}).filter(([option]) => command.getOptionValueSource(option) === "cli").map(([, flag]) => flag);
|
|
@@ -12861,6 +12930,11 @@ program.name("create-newt-app").version(version).description("Create a new newt-
|
|
|
12861
12930
|
value: options.deployment,
|
|
12862
12931
|
allowed: DEPLOYMENT_CHOICES
|
|
12863
12932
|
},
|
|
12933
|
+
{
|
|
12934
|
+
flag: "--nest",
|
|
12935
|
+
value: options.nest,
|
|
12936
|
+
allowed: NEST_CHOICES
|
|
12937
|
+
},
|
|
12864
12938
|
...extras.map((extra) => ({
|
|
12865
12939
|
flag: "--extras",
|
|
12866
12940
|
value: extra,
|
|
@@ -12881,7 +12955,7 @@ program.name("create-newt-app").version(version).description("Create a new newt-
|
|
|
12881
12955
|
database: options.database,
|
|
12882
12956
|
linter: options.linter,
|
|
12883
12957
|
deployment: options.deployment,
|
|
12884
|
-
|
|
12958
|
+
nest: options.nest,
|
|
12885
12959
|
includeExample: options.includeExample,
|
|
12886
12960
|
extras,
|
|
12887
12961
|
explicitFlags
|