@nexusts/cli 0.8.3 → 0.9.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/commands/init.d.ts +2 -12
- package/dist/commands/new.d.ts +6 -6
- package/dist/core/index.d.ts +1 -0
- package/dist/core/scaffold.d.ts +38 -0
- package/dist/index.js +695 -733
- package/dist/index.js.map +15 -14
- package/dist/templates/controller/nest.d.ts +3 -3
- package/dist/templates/crud/controller.d.ts +3 -2
- package/dist/templates/repository/repository.d.ts +6 -1
- package/dist/templates/service/service.d.ts +3 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -19,7 +19,7 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
19
19
|
var __require = import.meta.require;
|
|
20
20
|
|
|
21
21
|
// packages/cli/src/commands/info.ts
|
|
22
|
-
import { resolve as
|
|
22
|
+
import { resolve as resolve5 } from "path";
|
|
23
23
|
|
|
24
24
|
// packages/cli/src/core/args.ts
|
|
25
25
|
var LONG_RE = /^--([^=]+)(?:=(.*))?$/;
|
|
@@ -511,67 +511,9 @@ function loadVersion() {
|
|
|
511
511
|
}
|
|
512
512
|
}
|
|
513
513
|
var VERSION = loadVersion();
|
|
514
|
-
// packages/cli/src/
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
aliases: ["i"],
|
|
518
|
-
summary: "Show project configuration",
|
|
519
|
-
description: "Prints the resolved nx.config.ts plus relevant env vars.",
|
|
520
|
-
async run(ctx) {
|
|
521
|
-
logger.heading("NexusTS CLI \u2014 Project Info");
|
|
522
|
-
logger.info(colors.bold("Resolved configuration"));
|
|
523
|
-
logger.blank();
|
|
524
|
-
logger.table([
|
|
525
|
-
["routing", String(ctx.config.routing)],
|
|
526
|
-
["view", String(ctx.config.view)],
|
|
527
|
-
["orm", String(ctx.config.orm)],
|
|
528
|
-
["dialect", String(ctx.config.dialect ?? "(none)")],
|
|
529
|
-
["database.driver", String(ctx.config.database.driver)],
|
|
530
|
-
["database.url", String(ctx.config.database.url)],
|
|
531
|
-
["inertia.frontend", String(ctx.config.inertia.frontend)],
|
|
532
|
-
["inertia.ssr", String(ctx.config.inertia.ssr)],
|
|
533
|
-
["inertia.version", String(ctx.config.inertia.version)]
|
|
534
|
-
]);
|
|
535
|
-
logger.blank();
|
|
536
|
-
logger.info(colors.bold("Paths"));
|
|
537
|
-
logger.blank();
|
|
538
|
-
for (const [k, v] of Object.entries(ctx.config.paths)) {
|
|
539
|
-
logger.table([[k, v]]);
|
|
540
|
-
}
|
|
541
|
-
logger.blank();
|
|
542
|
-
logger.info(colors.bold("Environment"));
|
|
543
|
-
logger.blank();
|
|
544
|
-
const envKeys = [
|
|
545
|
-
"NODE_ENV",
|
|
546
|
-
"PORT",
|
|
547
|
-
"NEXUS_DEBUG",
|
|
548
|
-
"NO_COLOR",
|
|
549
|
-
"FORCE_COLOR",
|
|
550
|
-
"NX_ROUTING",
|
|
551
|
-
"NX_VIEW",
|
|
552
|
-
"NX_ORM",
|
|
553
|
-
"NX_DATABASE_DRIVER",
|
|
554
|
-
"NX_DATABASE_URL",
|
|
555
|
-
"NX_INERTIA_FRONTEND",
|
|
556
|
-
"NX_INERTIA_SSR"
|
|
557
|
-
];
|
|
558
|
-
for (const k of envKeys) {
|
|
559
|
-
const v = process.env[k];
|
|
560
|
-
logger.table([[k, v === undefined ? colors.dim("(unset)") : v]]);
|
|
561
|
-
}
|
|
562
|
-
logger.blank();
|
|
563
|
-
logger.info(colors.bold("Working directory"));
|
|
564
|
-
logger.blank();
|
|
565
|
-
logger.info(` ${resolve4(ctx.cwd)}`);
|
|
566
|
-
logger.blank();
|
|
567
|
-
return 0;
|
|
568
|
-
}
|
|
569
|
-
};
|
|
570
|
-
var info_default = infoCommand;
|
|
571
|
-
|
|
572
|
-
// packages/cli/src/commands/init.ts
|
|
573
|
-
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
|
|
574
|
-
import { resolve as resolve5 } from "path";
|
|
514
|
+
// packages/cli/src/core/scaffold.ts
|
|
515
|
+
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
516
|
+
import { resolve as resolve4 } from "path";
|
|
575
517
|
|
|
576
518
|
// packages/cli/src/templates/controller/adonis.ts
|
|
577
519
|
var adonis_default = `
|
|
@@ -636,45 +578,51 @@ export const {{ camel }}Routes = {
|
|
|
636
578
|
|
|
637
579
|
// packages/cli/src/templates/controller/nest.ts
|
|
638
580
|
var nest_default = `
|
|
639
|
-
import {
|
|
581
|
+
import { Controller, Delete, Get, Inject, Post, Put, inputValue } from '@nexusts/core';
|
|
582
|
+
import type { Context } from 'hono';
|
|
640
583
|
import { {{ service }} } from '../services/{{ kebab }}.service.js';
|
|
641
584
|
|
|
642
585
|
@Controller('/{{ kebab }}s')
|
|
643
586
|
export class {{ name }}Controller {
|
|
644
|
-
|
|
587
|
+
@Inject({{ service }}) declare {{ serviceCamel }}: {{ service }};
|
|
645
588
|
|
|
646
589
|
@Get('/')
|
|
647
|
-
async index() {
|
|
590
|
+
async index(ctx: Context) {
|
|
648
591
|
return this.{{ serviceCamel }}.findAll();
|
|
649
592
|
}
|
|
650
593
|
|
|
651
594
|
@Get('/:id')
|
|
652
|
-
async show(
|
|
653
|
-
|
|
595
|
+
async show(ctx: Context) {
|
|
596
|
+
const id = inputValue(ctx.req.param('id')).number().required().value();
|
|
597
|
+
return this.{{ serviceCamel }}.findOne(id);
|
|
654
598
|
}
|
|
655
599
|
|
|
656
600
|
@Post('/')
|
|
657
|
-
async create(
|
|
658
|
-
|
|
601
|
+
async create(ctx: Context) {
|
|
602
|
+
const body = await ctx.req.json();
|
|
603
|
+
return { status: 201, body: await this.{{ serviceCamel }}.create(body) };
|
|
659
604
|
}
|
|
660
605
|
|
|
661
606
|
@Put('/:id')
|
|
662
|
-
async update(
|
|
663
|
-
|
|
607
|
+
async update(ctx: Context) {
|
|
608
|
+
const id = inputValue(ctx.req.param('id')).number().required().value();
|
|
609
|
+
const body = await ctx.req.json();
|
|
610
|
+
return this.{{ serviceCamel }}.update(id, body);
|
|
664
611
|
}
|
|
665
612
|
|
|
666
613
|
@Delete('/:id')
|
|
667
|
-
async destroy(
|
|
668
|
-
|
|
614
|
+
async destroy(ctx: Context) {
|
|
615
|
+
const id = inputValue(ctx.req.param('id')).number().required().value();
|
|
616
|
+
return this.{{ serviceCamel }}.delete(id);
|
|
669
617
|
}
|
|
670
618
|
}
|
|
671
619
|
`.trimStart();
|
|
672
620
|
|
|
673
621
|
// packages/cli/src/templates/crud/controller.ts
|
|
674
622
|
var controller_default = `
|
|
675
|
-
import {
|
|
623
|
+
import { Controller, Delete, Get, Inject, Post, Put, inputValue } from '@nexusts/core';
|
|
676
624
|
import { z } from 'zod';
|
|
677
|
-
import {
|
|
625
|
+
import type { Context } from 'hono';
|
|
678
626
|
import { {{ service }} } from '../services/{{ kebab }}.service.js';
|
|
679
627
|
{{#hasInertia}}import { Inertia } from '@nexusts/view';{{/hasInertia}}
|
|
680
628
|
|
|
@@ -685,13 +633,11 @@ const Create{{ name }}Schema = z.object({
|
|
|
685
633
|
|
|
686
634
|
@Controller('/{{ kebab }}s')
|
|
687
635
|
export class {{ controller }} {
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
{{#hasInertia}} @Inject(Inertia.TOKEN) private readonly inertia: Inertia,{{/hasInertia}}
|
|
691
|
-
) {}
|
|
636
|
+
@Inject({{ service }}) declare {{ camel }}Service: {{ service }};
|
|
637
|
+
{{#hasInertia}} @Inject(Inertia.TOKEN) declare inertia: Inertia;{{/hasInertia}}
|
|
692
638
|
|
|
693
639
|
@Get('/')
|
|
694
|
-
async index() {
|
|
640
|
+
async index(ctx: Context) {
|
|
695
641
|
const items = await this.{{ camel }}Service.findAll();
|
|
696
642
|
{{#hasInertia}}
|
|
697
643
|
return this.inertia.render('{{ viewComponent }}', { items });
|
|
@@ -702,8 +648,9 @@ export class {{ controller }} {
|
|
|
702
648
|
}
|
|
703
649
|
|
|
704
650
|
@Get('/:id')
|
|
705
|
-
async show(
|
|
706
|
-
const
|
|
651
|
+
async show(ctx: Context) {
|
|
652
|
+
const id = inputValue(ctx.req.param('id')).number().required().value();
|
|
653
|
+
const item = await this.{{ camel }}Service.findOne(id);
|
|
707
654
|
{{#hasInertia}}
|
|
708
655
|
return this.inertia.render('{{ viewShowComponent }}', { item });
|
|
709
656
|
{{/hasInertia}}
|
|
@@ -713,23 +660,22 @@ export class {{ controller }} {
|
|
|
713
660
|
}
|
|
714
661
|
|
|
715
662
|
@Post('/')
|
|
716
|
-
|
|
717
|
-
|
|
663
|
+
async create(ctx: Context) {
|
|
664
|
+
const body = Create{{ name }}Schema.parse(await ctx.req.json());
|
|
718
665
|
return { status: 201, body: await this.{{ camel }}Service.create(body) };
|
|
719
666
|
}
|
|
720
667
|
|
|
721
668
|
@Put('/:id')
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
) {
|
|
727
|
-
return await this.{{ camel }}Service.update(Number(id), body);
|
|
669
|
+
async update(ctx: Context) {
|
|
670
|
+
const id = inputValue(ctx.req.param('id')).number().required().value();
|
|
671
|
+
const body = Create{{ name }}Schema.partial().parse(await ctx.req.json());
|
|
672
|
+
return await this.{{ camel }}Service.update(id, body);
|
|
728
673
|
}
|
|
729
674
|
|
|
730
675
|
@Delete('/:id')
|
|
731
|
-
async destroy(
|
|
732
|
-
|
|
676
|
+
async destroy(ctx: Context) {
|
|
677
|
+
const id = inputValue(ctx.req.param('id')).number().required().value();
|
|
678
|
+
return await this.{{ camel }}Service.delete(id);
|
|
733
679
|
}
|
|
734
680
|
}
|
|
735
681
|
`.trimStart();
|
|
@@ -1066,26 +1012,21 @@ import type { {{ name }}, New{{ name }} } from '../models/{{ kebab }}.model.js';
|
|
|
1066
1012
|
|
|
1067
1013
|
@Injectable()
|
|
1068
1014
|
export class {{ repository }} extends DrizzleRepository<typeof {{ snake }}, {{ name }}> {
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
) {
|
|
1072
|
-
super(db, {{ snake }});
|
|
1073
|
-
}
|
|
1015
|
+
@Inject(DrizzleService.TOKEN) declare db: DrizzleService;
|
|
1016
|
+
protected readonly table = {{ snake }};
|
|
1074
1017
|
}
|
|
1075
1018
|
`.trimStart();
|
|
1076
1019
|
|
|
1077
1020
|
// packages/cli/src/templates/service/service.ts
|
|
1078
1021
|
var service_default = `
|
|
1079
|
-
import {
|
|
1022
|
+
import { Injectable, Inject } from '@nexusts/core';
|
|
1080
1023
|
{{#hasRepo}}import { eq } from '@nexusts/drizzle';
|
|
1081
1024
|
import { {{ repository }} } from '../repositories/{{ kebab }}.repository.js';
|
|
1082
1025
|
import { {{ snake }} } from '../models/{{ kebab }}.model.js';{{/hasRepo}}
|
|
1083
1026
|
|
|
1084
1027
|
@Injectable()
|
|
1085
1028
|
export class {{ name }}Service {
|
|
1086
|
-
|
|
1087
|
-
@Inject({{ repository }}) private readonly {{ repositoryCamel }}: {{ repository }},
|
|
1088
|
-
{{/hasRepo}}) {}
|
|
1029
|
+
{{#hasRepo}}@Inject({{ repository }}) declare {{ repositoryCamel }}: {{ repository }};{{/hasRepo}}
|
|
1089
1030
|
|
|
1090
1031
|
async findAll() {
|
|
1091
1032
|
{{#hasRepo}}return this.{{ repositoryCamel }}.findAll();{{/hasRepo}}
|
|
@@ -1164,140 +1105,506 @@ var templates = {
|
|
|
1164
1105
|
}
|
|
1165
1106
|
};
|
|
1166
1107
|
|
|
1108
|
+
// packages/cli/src/core/scaffold.ts
|
|
1109
|
+
function ensureDirectories(target, view) {
|
|
1110
|
+
mkdirSync2(resolve4(target, "app/controllers"), { recursive: true });
|
|
1111
|
+
mkdirSync2(resolve4(target, "app/modules"), { recursive: true });
|
|
1112
|
+
mkdirSync2(resolve4(target, "app/services"), { recursive: true });
|
|
1113
|
+
mkdirSync2(resolve4(target, "app/models"), { recursive: true });
|
|
1114
|
+
mkdirSync2(resolve4(target, "app/repositories"), { recursive: true });
|
|
1115
|
+
mkdirSync2(resolve4(target, "app/dto"), { recursive: true });
|
|
1116
|
+
mkdirSync2(resolve4(target, "public"), { recursive: true });
|
|
1117
|
+
if (view === "inertia") {
|
|
1118
|
+
mkdirSync2(resolve4(target, "resources/js/Pages"), { recursive: true });
|
|
1119
|
+
} else if (view !== "none") {
|
|
1120
|
+
mkdirSync2(resolve4(target, "resources/views"), { recursive: true });
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
function computeDeps(view, orm, db, frontend) {
|
|
1124
|
+
const deps = {
|
|
1125
|
+
"@nexusts/core": "*",
|
|
1126
|
+
hono: "^4.6.0",
|
|
1127
|
+
zod: "^3.23.8"
|
|
1128
|
+
};
|
|
1129
|
+
const devDeps = {};
|
|
1130
|
+
if (orm === "drizzle") {
|
|
1131
|
+
deps["@nexusts/drizzle"] = "*";
|
|
1132
|
+
deps["drizzle-orm"] = "^0.45.0";
|
|
1133
|
+
if (db === "postgres")
|
|
1134
|
+
deps["pg"] = "^8.13.0";
|
|
1135
|
+
if (db === "mysql")
|
|
1136
|
+
deps["mysql2"] = "^3.11.0";
|
|
1137
|
+
if (db === "sqlite" || db === "node-sqlite" || db === "bun-sqlite")
|
|
1138
|
+
deps["better-sqlite3"] = "^12.0.0";
|
|
1139
|
+
devDeps["drizzle-kit"] = "^0.31.0";
|
|
1140
|
+
}
|
|
1141
|
+
if (view !== "none") {
|
|
1142
|
+
deps["@nexusts/static"] = "*";
|
|
1143
|
+
}
|
|
1144
|
+
deps["@nexusts/view"] = "*";
|
|
1145
|
+
if (view === "inertia") {
|
|
1146
|
+
if (frontend === "vue") {
|
|
1147
|
+
deps["@inertiajs/vue3"] = "^3.0.0";
|
|
1148
|
+
deps["vue"] = "^3.5.0";
|
|
1149
|
+
} else {
|
|
1150
|
+
deps["@inertiajs/react"] = "^3.0.0";
|
|
1151
|
+
deps["react"] = "^19.0.0";
|
|
1152
|
+
deps["react-dom"] = "^19.0.0";
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
return { deps, devDeps };
|
|
1156
|
+
}
|
|
1157
|
+
function buildPackageJson(name, deps, devDeps, view, frontend) {
|
|
1158
|
+
const scripts = {
|
|
1159
|
+
dev: "bun --hot app/main.ts",
|
|
1160
|
+
build: "bun run build.ts",
|
|
1161
|
+
start: "bun app/main.ts",
|
|
1162
|
+
test: "vitest",
|
|
1163
|
+
nx: "nx"
|
|
1164
|
+
};
|
|
1165
|
+
if (view === "inertia") {
|
|
1166
|
+
const ext = frontend === "vue" ? "ts" : "tsx";
|
|
1167
|
+
scripts["build:frontend"] = `bun build ./resources/js/app.${ext} --outdir=./public --target=browser --format=esm --minify`;
|
|
1168
|
+
scripts["dev"] = `bun run build:frontend && bun --hot app/main.ts`;
|
|
1169
|
+
}
|
|
1170
|
+
const pkg = {
|
|
1171
|
+
name,
|
|
1172
|
+
version: "0.1.0",
|
|
1173
|
+
type: "module",
|
|
1174
|
+
private: true,
|
|
1175
|
+
scripts,
|
|
1176
|
+
dependencies: deps
|
|
1177
|
+
};
|
|
1178
|
+
if (Object.keys(devDeps).length > 0) {
|
|
1179
|
+
pkg.devDependencies = devDeps;
|
|
1180
|
+
}
|
|
1181
|
+
return pkg;
|
|
1182
|
+
}
|
|
1183
|
+
function generateNxConfig(target, opts) {
|
|
1184
|
+
const code = render(templates.project["nx.config.ts"], {
|
|
1185
|
+
routing: opts.routing,
|
|
1186
|
+
view: opts.view,
|
|
1187
|
+
viewPaths: opts.view === "none" ? "" : "resources/views",
|
|
1188
|
+
orm: opts.orm,
|
|
1189
|
+
dbDriver: opts.db,
|
|
1190
|
+
dbUrl: opts.dbUrl,
|
|
1191
|
+
inertiaFrontend: opts.frontend,
|
|
1192
|
+
inertiaSSR: opts.ssr,
|
|
1193
|
+
inertiaVersion: "1.0.0"
|
|
1194
|
+
});
|
|
1195
|
+
writeFileSync2(resolve4(target, "nx.config.ts"), code);
|
|
1196
|
+
}
|
|
1197
|
+
function generateDrizzleConfig(target, db, dbUrl) {
|
|
1198
|
+
if (db !== "bun-sqlite" && db !== "node-sqlite" && db !== "libsql" && db !== "postgres" && db !== "mysql")
|
|
1199
|
+
return;
|
|
1200
|
+
const dialect = db === "bun-sqlite" || db === "node-sqlite" || db === "libsql" ? "sqlite" : db === "postgres" ? "postgresql" : "mysql";
|
|
1201
|
+
const code = render(templates.project["drizzle.config.ts"], {
|
|
1202
|
+
dialect,
|
|
1203
|
+
dbUrl: dbUrl || "app.db"
|
|
1204
|
+
});
|
|
1205
|
+
writeFileSync2(resolve4(target, "drizzle.config.ts"), code);
|
|
1206
|
+
}
|
|
1207
|
+
function generateEnvFile() {
|
|
1208
|
+
return [
|
|
1209
|
+
"# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
1210
|
+
"# NexusTS \u2014 Environment Variables (committed to git)",
|
|
1211
|
+
"#",
|
|
1212
|
+
"# Shared defaults for all environments. Override locally via",
|
|
1213
|
+
"# .env.local (gitignored) or by environment via .env.{NODE_ENV}",
|
|
1214
|
+
"# (e.g. .env.production, .env.development).",
|
|
1215
|
+
"# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
1216
|
+
"",
|
|
1217
|
+
"# \u2500\u2500 App \u2500\u2500",
|
|
1218
|
+
"NODE_ENV=development",
|
|
1219
|
+
"PORT=3000",
|
|
1220
|
+
"",
|
|
1221
|
+
"# \u2500\u2500 Session secret (REQUIRED) \u2500\u2500",
|
|
1222
|
+
"# Generate with: openssl rand -base64 32",
|
|
1223
|
+
"SESSION_SECRET=change-me-in-production",
|
|
1224
|
+
"",
|
|
1225
|
+
"# \u2500\u2500 Database: SQLite (default, zero config) \u2500\u2500",
|
|
1226
|
+
"DATABASE_URL=app.db",
|
|
1227
|
+
"",
|
|
1228
|
+
"# \u2500\u2500 Database: PostgreSQL \u2500\u2500",
|
|
1229
|
+
"# DATABASE_URL=postgres://user:password@localhost:5432/myapp",
|
|
1230
|
+
"",
|
|
1231
|
+
"# \u2500\u2500 Database: MySQL \u2500\u2500",
|
|
1232
|
+
"# DATABASE_URL=mysql://user:password@localhost:3306/myapp",
|
|
1233
|
+
"",
|
|
1234
|
+
"# \u2500\u2500 Better Auth (if using nexusjs/auth) \u2500\u2500",
|
|
1235
|
+
"# BETTER_AUTH_SECRET=",
|
|
1236
|
+
"# BETTER_AUTH_URL=http://localhost:3000"
|
|
1237
|
+
].join(`
|
|
1238
|
+
`) + `
|
|
1239
|
+
`;
|
|
1240
|
+
}
|
|
1241
|
+
function generateEnvLocalFile() {
|
|
1242
|
+
return [
|
|
1243
|
+
"# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
1244
|
+
"# NexusTS \u2014 Local Overrides (DO NOT COMMIT to git)",
|
|
1245
|
+
"#",
|
|
1246
|
+
"# This file is gitignored. Use it for secrets and local",
|
|
1247
|
+
"# configuration that should never be checked in.",
|
|
1248
|
+
"# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
|
|
1249
|
+
"",
|
|
1250
|
+
"# Override any value from .env here:",
|
|
1251
|
+
"# DATABASE_URL=postgres://user:password@localhost:5432/myapp",
|
|
1252
|
+
"# SESSION_SECRET=my-local-secret"
|
|
1253
|
+
].join(`
|
|
1254
|
+
`) + `
|
|
1255
|
+
`;
|
|
1256
|
+
}
|
|
1257
|
+
function generateGitIgnore() {
|
|
1258
|
+
return `# NexusTS
|
|
1259
|
+
node_modules/
|
|
1260
|
+
app.db
|
|
1261
|
+
*.db
|
|
1262
|
+
.env.local
|
|
1263
|
+
dist/
|
|
1264
|
+
`;
|
|
1265
|
+
}
|
|
1266
|
+
function generateProjectFiles(target, opts) {
|
|
1267
|
+
const created = [];
|
|
1268
|
+
const write = (path, content) => {
|
|
1269
|
+
writeFileSync2(resolve4(target, path), content);
|
|
1270
|
+
created.push(path);
|
|
1271
|
+
};
|
|
1272
|
+
generateNxConfig(target, opts);
|
|
1273
|
+
write("public/.gitkeep", "");
|
|
1274
|
+
if (opts.view === "inertia") {
|
|
1275
|
+
if (opts.frontend === "vue") {
|
|
1276
|
+
write("resources/js/Pages/Welcome.vue", `<template>
|
|
1277
|
+
<main style="font-family: system-ui, sans-serif; max-width: 560px; margin: 2em auto">
|
|
1278
|
+
<h1>Hello, {{ name }}!</h1>
|
|
1279
|
+
</main>
|
|
1280
|
+
</template>
|
|
1281
|
+
|
|
1282
|
+
<script setup lang="ts">
|
|
1283
|
+
defineProps<{ name: string }>();
|
|
1284
|
+
</script>
|
|
1285
|
+
`);
|
|
1286
|
+
write("resources/js/app.ts", `import { createInertiaApp } from "@inertiajs/vue3";
|
|
1287
|
+
import { createApp, h } from "vue";
|
|
1288
|
+
import Welcome from "./Pages/Welcome.vue";
|
|
1289
|
+
|
|
1290
|
+
createInertiaApp({
|
|
1291
|
+
resolve: (name: string) => {
|
|
1292
|
+
if (name === "Welcome") return Welcome;
|
|
1293
|
+
throw new Error("Unknown page: " + name);
|
|
1294
|
+
},
|
|
1295
|
+
setup({ el, App, props }: any) {
|
|
1296
|
+
createApp({ render: () => h(App, props) }).mount(el);
|
|
1297
|
+
},
|
|
1298
|
+
});
|
|
1299
|
+
`);
|
|
1300
|
+
} else {
|
|
1301
|
+
write("resources/js/Pages/Welcome.tsx", `import { useState } from "react";
|
|
1302
|
+
|
|
1303
|
+
export default function Welcome({ name }: { name: string }) {
|
|
1304
|
+
const [count, setCount] = useState(0);
|
|
1305
|
+
return (
|
|
1306
|
+
<main style={{ fontFamily: "system-ui, sans-serif", maxWidth: 560, margin: "2em auto" }}>
|
|
1307
|
+
<h1>Hello, {name}!</h1>
|
|
1308
|
+
<p>Counter: <strong>{count}</strong></p>
|
|
1309
|
+
<button onClick={() => setCount((c) => c + 1)} style={{ padding: "0.5em 1em" }}>
|
|
1310
|
+
+1
|
|
1311
|
+
</button>
|
|
1312
|
+
</main>
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1315
|
+
`);
|
|
1316
|
+
write("resources/js/app.tsx", `import { createInertiaApp } from "@inertiajs/react";
|
|
1317
|
+
import { createRoot } from "react-dom/client";
|
|
1318
|
+
import Welcome from "./Pages/Welcome.js";
|
|
1319
|
+
|
|
1320
|
+
createInertiaApp({
|
|
1321
|
+
resolve: (name: string) => {
|
|
1322
|
+
if (name === "Welcome") return Welcome;
|
|
1323
|
+
throw new Error("Unknown page: " + name);
|
|
1324
|
+
},
|
|
1325
|
+
setup({ el, App, props }: any) {
|
|
1326
|
+
createRoot(el).render(<App {...props} />);
|
|
1327
|
+
},
|
|
1328
|
+
});
|
|
1329
|
+
`);
|
|
1330
|
+
}
|
|
1331
|
+
} else if (opts.view !== "none") {
|
|
1332
|
+
write("resources/views/welcome.html", `<h1>Welcome to ${opts.name}</h1>
|
|
1333
|
+
<p>This is a sample Rendu template.</p>
|
|
1334
|
+
<p>Founded <?= year ?>.</p>
|
|
1335
|
+
`);
|
|
1336
|
+
}
|
|
1337
|
+
write(".env", generateEnvFile());
|
|
1338
|
+
write(".env.local", generateEnvLocalFile());
|
|
1339
|
+
write(".gitignore", generateGitIgnore());
|
|
1340
|
+
{
|
|
1341
|
+
const hasView = opts.view !== "none";
|
|
1342
|
+
const staticMw = hasView ? `import { StaticModule } from '@nexusts/static';
|
|
1343
|
+
const staticMiddleware = StaticModule.mount({ root: './public', prefix: '/static' });
|
|
1344
|
+
` : "";
|
|
1345
|
+
const staticOpt = hasView ? `
|
|
1346
|
+
middleware: [staticMiddleware],` : "";
|
|
1347
|
+
write("app/main.ts", `import { Application } from '@nexusts/core';
|
|
1348
|
+
${staticMw}import { AppModule } from './app.module.js';
|
|
1349
|
+
|
|
1350
|
+
const app = new Application(AppModule, {
|
|
1351
|
+
logging: true,
|
|
1352
|
+
port: Number(process.env['PORT'] ?? 3000),${staticOpt}
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
await app.listen();
|
|
1356
|
+
console.log('[nexus] Listening on http://localhost:' + (process.env['PORT'] ?? 3000));
|
|
1357
|
+
`);
|
|
1358
|
+
}
|
|
1359
|
+
{
|
|
1360
|
+
const hasOrm = opts.orm === "drizzle";
|
|
1361
|
+
const ormImport = hasOrm ? `import { DrizzleModule } from '@nexusts/drizzle';
|
|
1362
|
+
` : "";
|
|
1363
|
+
const forRootDialect = opts.db === "bun-sqlite" ? "bun-sqlite" : "sqlite";
|
|
1364
|
+
const ormBlock = hasOrm ? ` DrizzleModule.forRoot({
|
|
1365
|
+
dialect: '${forRootDialect}',
|
|
1366
|
+
connection: { filename: '${opts.dbUrl || "app.db"}' },
|
|
1367
|
+
logging: true,
|
|
1368
|
+
})` : "";
|
|
1369
|
+
const isInertia = opts.view === "inertia";
|
|
1370
|
+
const inertiaImport = isInertia ? `import { Inertia } from '@nexusts/view';
|
|
1371
|
+
` : "";
|
|
1372
|
+
const inertiaProvider = isInertia ? ` providers: [{ provide: Inertia.TOKEN, useValue: new Inertia({ scripts: ['/static/app.js'] }) }],
|
|
1373
|
+
` : "";
|
|
1374
|
+
write("app/app.module.ts", `${ormImport}${inertiaImport}import { Module } from '@nexusts/core';
|
|
1375
|
+
import { HomeController } from './controllers/home.controller.js';
|
|
1376
|
+
|
|
1377
|
+
@Module({
|
|
1378
|
+
imports: [${hasOrm ? `
|
|
1379
|
+
${ormBlock},
|
|
1380
|
+
` : ""} ],
|
|
1381
|
+
${inertiaProvider} controllers: [HomeController],
|
|
1382
|
+
})
|
|
1383
|
+
export class AppModule {}
|
|
1384
|
+
`);
|
|
1385
|
+
}
|
|
1386
|
+
{
|
|
1387
|
+
if (opts.view === "inertia") {
|
|
1388
|
+
write("app/controllers/home.controller.ts", `import { Controller, Get, Inject } from '@nexusts/core';
|
|
1389
|
+
import { Inertia } from '@nexusts/view';
|
|
1390
|
+
|
|
1391
|
+
@Controller('/')
|
|
1392
|
+
export class HomeController {
|
|
1393
|
+
@Inject(Inertia.TOKEN) private inertia!: Inertia;
|
|
1394
|
+
|
|
1395
|
+
@Get('/')
|
|
1396
|
+
index() {
|
|
1397
|
+
return this.inertia.render('Welcome', { name: 'NexusTS' });
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
`);
|
|
1401
|
+
} else if (opts.view !== "none") {
|
|
1402
|
+
write("app/controllers/home.controller.ts", `import { Controller, Get } from '@nexusts/core';
|
|
1403
|
+
|
|
1404
|
+
@Controller('/')
|
|
1405
|
+
export class HomeController {
|
|
1406
|
+
@Get('/')
|
|
1407
|
+
index() {
|
|
1408
|
+
return {
|
|
1409
|
+
view: 'welcome.html',
|
|
1410
|
+
data: { year: new Date().getFullYear() },
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
`);
|
|
1415
|
+
} else {
|
|
1416
|
+
write("app/controllers/home.controller.ts", `import { Controller, Get } from '@nexusts/core';
|
|
1417
|
+
|
|
1418
|
+
@Controller('/')
|
|
1419
|
+
export class HomeController {
|
|
1420
|
+
@Get('/')
|
|
1421
|
+
index() {
|
|
1422
|
+
return { status: 200, body: { message: 'Hello from NexusTS!' } };
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
`);
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
if (opts.orm === "drizzle") {
|
|
1429
|
+
generateDrizzleConfig(target, opts.db, opts.dbUrl);
|
|
1430
|
+
}
|
|
1431
|
+
write("README.md", `# ${opts.name}
|
|
1432
|
+
|
|
1433
|
+
A NexusTS project.
|
|
1434
|
+
|
|
1435
|
+
## Run
|
|
1436
|
+
|
|
1437
|
+
\`\`\`bash
|
|
1438
|
+
bun install
|
|
1439
|
+
bun run dev
|
|
1440
|
+
\`\`\`
|
|
1441
|
+
|
|
1442
|
+
## Scaffolding
|
|
1443
|
+
|
|
1444
|
+
\`\`\`bash
|
|
1445
|
+
bunx nx make:crud Post
|
|
1446
|
+
\`\`\`
|
|
1447
|
+
`);
|
|
1448
|
+
return created;
|
|
1449
|
+
}
|
|
1450
|
+
// packages/cli/src/commands/info.ts
|
|
1451
|
+
var infoCommand = {
|
|
1452
|
+
name: "info",
|
|
1453
|
+
aliases: ["i"],
|
|
1454
|
+
summary: "Show project configuration",
|
|
1455
|
+
description: "Prints the resolved nx.config.ts plus relevant env vars.",
|
|
1456
|
+
async run(ctx) {
|
|
1457
|
+
logger.heading("NexusTS CLI \u2014 Project Info");
|
|
1458
|
+
logger.info(colors.bold("Resolved configuration"));
|
|
1459
|
+
logger.blank();
|
|
1460
|
+
logger.table([
|
|
1461
|
+
["routing", String(ctx.config.routing)],
|
|
1462
|
+
["view", String(ctx.config.view)],
|
|
1463
|
+
["orm", String(ctx.config.orm)],
|
|
1464
|
+
["dialect", String(ctx.config.dialect ?? "(none)")],
|
|
1465
|
+
["database.driver", String(ctx.config.database.driver)],
|
|
1466
|
+
["database.url", String(ctx.config.database.url)],
|
|
1467
|
+
["inertia.frontend", String(ctx.config.inertia.frontend)],
|
|
1468
|
+
["inertia.ssr", String(ctx.config.inertia.ssr)],
|
|
1469
|
+
["inertia.version", String(ctx.config.inertia.version)]
|
|
1470
|
+
]);
|
|
1471
|
+
logger.blank();
|
|
1472
|
+
logger.info(colors.bold("Paths"));
|
|
1473
|
+
logger.blank();
|
|
1474
|
+
for (const [k, v] of Object.entries(ctx.config.paths)) {
|
|
1475
|
+
logger.table([[k, v]]);
|
|
1476
|
+
}
|
|
1477
|
+
logger.blank();
|
|
1478
|
+
logger.info(colors.bold("Environment"));
|
|
1479
|
+
logger.blank();
|
|
1480
|
+
const envKeys = [
|
|
1481
|
+
"NODE_ENV",
|
|
1482
|
+
"PORT",
|
|
1483
|
+
"NEXUS_DEBUG",
|
|
1484
|
+
"NO_COLOR",
|
|
1485
|
+
"FORCE_COLOR",
|
|
1486
|
+
"NX_ROUTING",
|
|
1487
|
+
"NX_VIEW",
|
|
1488
|
+
"NX_ORM",
|
|
1489
|
+
"NX_DATABASE_DRIVER",
|
|
1490
|
+
"NX_DATABASE_URL",
|
|
1491
|
+
"NX_INERTIA_FRONTEND",
|
|
1492
|
+
"NX_INERTIA_SSR"
|
|
1493
|
+
];
|
|
1494
|
+
for (const k of envKeys) {
|
|
1495
|
+
const v = process.env[k];
|
|
1496
|
+
logger.table([[k, v === undefined ? colors.dim("(unset)") : v]]);
|
|
1497
|
+
}
|
|
1498
|
+
logger.blank();
|
|
1499
|
+
logger.info(colors.bold("Working directory"));
|
|
1500
|
+
logger.blank();
|
|
1501
|
+
logger.info(` ${resolve5(ctx.cwd)}`);
|
|
1502
|
+
logger.blank();
|
|
1503
|
+
return 0;
|
|
1504
|
+
}
|
|
1505
|
+
};
|
|
1506
|
+
var info_default = infoCommand;
|
|
1507
|
+
|
|
1167
1508
|
// packages/cli/src/commands/init.ts
|
|
1509
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
1510
|
+
import { resolve as resolve6 } from "path";
|
|
1511
|
+
var VALID_OPTIONS = {
|
|
1512
|
+
style: ["nest", "adonis", "functional"],
|
|
1513
|
+
view: ["rendu", "edge", "eta", "inertia", "none"],
|
|
1514
|
+
orm: ["drizzle", "prisma", "kysely", "none"],
|
|
1515
|
+
db: ["bun-sqlite", "node-sqlite", "libsql", "postgres", "mysql", "none"],
|
|
1516
|
+
frontend: ["react", "vue", "svelte", "solid"]
|
|
1517
|
+
};
|
|
1518
|
+
async function resolveOpt(flags, key, valid, defaultVal, interactive) {
|
|
1519
|
+
const flagVal = flags[key];
|
|
1520
|
+
if (flagVal) {
|
|
1521
|
+
if (valid.includes(flagVal))
|
|
1522
|
+
return flagVal;
|
|
1523
|
+
if (!interactive) {
|
|
1524
|
+
logger.error(`Invalid --${key} "${flagVal}". Valid values: ${valid.join(", ")}`);
|
|
1525
|
+
process.exit(1);
|
|
1526
|
+
}
|
|
1527
|
+
logger.warn(`"${flagVal}" is not valid for --${key}. Please choose from the list.`);
|
|
1528
|
+
}
|
|
1529
|
+
const label = key === "style" ? "Routing style" : key === "view" ? "View engine" : key === "orm" ? "ORM driver" : key === "db" ? "Database driver" : "Inertia frontend";
|
|
1530
|
+
for (;; ) {
|
|
1531
|
+
const answer = await select(label, [...valid], { default: defaultVal });
|
|
1532
|
+
if (valid.includes(answer))
|
|
1533
|
+
return answer;
|
|
1534
|
+
logger.warn(`"${answer}" is not valid. Please choose from: ${valid.join(", ")}`);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1168
1537
|
var initCommand = {
|
|
1169
1538
|
name: "init",
|
|
1170
1539
|
aliases: ["i"],
|
|
1171
|
-
summary: "Initialize
|
|
1172
|
-
description: "
|
|
1540
|
+
summary: "Initialize NexusTS in an existing directory",
|
|
1541
|
+
description: "Scaffolds a new NexusTS project in the current or target directory. Non-destructive: skips existing files, merges package.json and tsconfig.json.",
|
|
1173
1542
|
examples: [
|
|
1174
1543
|
"nx init",
|
|
1175
|
-
"nx init ./my-
|
|
1544
|
+
"nx init ./my-app",
|
|
1176
1545
|
"nx init --style nest --view inertia --orm drizzle --db bun-sqlite",
|
|
1177
1546
|
"nx init --force"
|
|
1178
1547
|
],
|
|
1179
1548
|
flags: [
|
|
1180
1549
|
{ name: "target", description: "Target directory (default: cwd)" },
|
|
1181
|
-
{
|
|
1182
|
-
name: "style",
|
|
1183
|
-
description: "Routing style (nest|adonis|functional|mixed)"
|
|
1184
|
-
},
|
|
1550
|
+
{ name: "style", description: "Routing style (nest|adonis|functional)" },
|
|
1185
1551
|
{ name: "view", description: "View engine (rendu|edge|eta|inertia|none)" },
|
|
1186
1552
|
{ name: "orm", description: "ORM driver (drizzle|prisma|kysely|none)" },
|
|
1187
|
-
{
|
|
1188
|
-
name: "db",
|
|
1189
|
-
description: "Database driver (bun-sqlite|node-sqlite|libsql|postgres|mysql|none)"
|
|
1190
|
-
},
|
|
1553
|
+
{ name: "db", description: "Database driver (bun-sqlite|node-sqlite|libsql|postgres|mysql|none)" },
|
|
1191
1554
|
{
|
|
1192
1555
|
name: "frontend",
|
|
1193
1556
|
description: "Inertia frontend (react|vue|svelte|solid)"
|
|
1194
1557
|
},
|
|
1195
1558
|
{ name: "no-ssr", description: "Disable Inertia SSR" },
|
|
1196
|
-
{ name: "force", description: "Overwrite files
|
|
1197
|
-
{ name: "no-interaction", description: "
|
|
1559
|
+
{ name: "force", description: "Overwrite existing files" },
|
|
1560
|
+
{ name: "no-interaction", description: "Skip interactive prompts" }
|
|
1198
1561
|
],
|
|
1199
1562
|
async run(ctx) {
|
|
1200
|
-
const interactive =
|
|
1563
|
+
const interactive = flagBool(ctx.flags, "interaction", true);
|
|
1201
1564
|
const force = flagBool(ctx.flags, "force", false);
|
|
1202
|
-
const target =
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
const routing = ctx.flags["style"] ?? await select("Routing style", ["nest", "adonis", "functional"], {
|
|
1209
|
-
interactive,
|
|
1210
|
-
default: "nest"
|
|
1211
|
-
});
|
|
1212
|
-
const view = ctx.flags["view"] ?? await select("View engine", ["rendu", "edge", "eta", "inertia", "none"], {
|
|
1213
|
-
interactive,
|
|
1214
|
-
default: "rendu"
|
|
1215
|
-
});
|
|
1216
|
-
const orm = ctx.flags["orm"] ?? await select("ORM driver", ["drizzle", "prisma", "kysely", "none"], {
|
|
1217
|
-
interactive,
|
|
1218
|
-
default: "drizzle"
|
|
1219
|
-
});
|
|
1220
|
-
const db = ctx.flags["db"] ?? await select("Database driver", ["bun-sqlite", "node-sqlite", "libsql", "postgres", "mysql", "none"], {
|
|
1221
|
-
interactive,
|
|
1222
|
-
default: "bun-sqlite"
|
|
1223
|
-
});
|
|
1224
|
-
const frontend = ctx.flags["frontend"] ?? await select("Inertia frontend", ["react", "vue", "svelte", "solid"], {
|
|
1225
|
-
interactive,
|
|
1226
|
-
default: "react"
|
|
1227
|
-
});
|
|
1565
|
+
const target = resolve6(ctx.cwd, ctx.flags.target ?? ".");
|
|
1566
|
+
const routing = await resolveOpt(ctx.flags, "style", VALID_OPTIONS.style, "nest", interactive);
|
|
1567
|
+
const view = await resolveOpt(ctx.flags, "view", VALID_OPTIONS.view, "rendu", interactive);
|
|
1568
|
+
const orm = await resolveOpt(ctx.flags, "orm", VALID_OPTIONS.orm, "drizzle", interactive);
|
|
1569
|
+
const db = await resolveOpt(ctx.flags, "db", VALID_OPTIONS.db, "bun-sqlite", interactive);
|
|
1570
|
+
const frontend = await resolveOpt(ctx.flags, "frontend", VALID_OPTIONS.frontend, "react", interactive);
|
|
1228
1571
|
const ssr = !flagBool(ctx.flags, "no-ssr", false);
|
|
1572
|
+
const name = target.split("/").pop() ?? "nexus-app";
|
|
1573
|
+
const dbUrl = db === "bun-sqlite" || db === "node-sqlite" ? "app.db" : "";
|
|
1229
1574
|
const plan = [
|
|
1230
|
-
{ path: "nx.config.ts", mode: "write" },
|
|
1231
1575
|
{ path: "package.json", mode: "merge-pkg" },
|
|
1232
1576
|
{ path: "tsconfig.json", mode: "merge-tsconfig" },
|
|
1233
|
-
{ path: "public/.gitkeep", mode: "write" },
|
|
1234
|
-
...view !== "none" ? [{ path: "resources/views/welcome.html", mode: "write" }] : [],
|
|
1235
1577
|
{ path: ".env", mode: "skip" },
|
|
1236
1578
|
{ path: ".env.local", mode: "skip" },
|
|
1237
1579
|
{ path: ".gitignore", mode: "skip" },
|
|
1238
|
-
|
|
1580
|
+
{ path: "nx.config.ts", mode: "write" },
|
|
1581
|
+
{ path: "public/.gitkeep", mode: "write" },
|
|
1239
1582
|
{ path: "app/main.ts", mode: "write" },
|
|
1240
1583
|
{ path: "app/app.module.ts", mode: "write" },
|
|
1241
1584
|
{ path: "app/controllers/home.controller.ts", mode: "write" },
|
|
1242
|
-
{ path: "README.md", mode: "write" }
|
|
1585
|
+
{ path: "README.md", mode: "write" },
|
|
1586
|
+
...view === "inertia" ? [
|
|
1587
|
+
{ path: `resources/js/Pages/Welcome.${frontend === "vue" ? "vue" : "tsx"}`, mode: "write" },
|
|
1588
|
+
{ path: `resources/js/app.${frontend === "vue" ? "ts" : "tsx"}`, mode: "write" }
|
|
1589
|
+
] : view !== "none" ? [{ path: "resources/views/welcome.html", mode: "write" }] : [],
|
|
1590
|
+
...orm === "drizzle" ? [{ path: "drizzle.config.ts", mode: "write" }] : []
|
|
1243
1591
|
];
|
|
1244
1592
|
const created = [];
|
|
1245
1593
|
const skipped = [];
|
|
1246
1594
|
const merged = [];
|
|
1247
|
-
|
|
1248
|
-
mkdirSync2(resolve5(target, "public"), { recursive: true });
|
|
1249
|
-
if (view !== "none") {
|
|
1250
|
-
mkdirSync2(resolve5(target, "resources/views"), { recursive: true });
|
|
1251
|
-
}
|
|
1595
|
+
ensureDirectories(target, view);
|
|
1252
1596
|
for (const entry of plan) {
|
|
1253
|
-
const abs =
|
|
1597
|
+
const abs = resolve6(target, entry.path);
|
|
1254
1598
|
const exists = existsSync4(abs);
|
|
1255
1599
|
if (entry.mode === "merge-pkg") {
|
|
1256
|
-
const
|
|
1257
|
-
"@nexusts/core": "*",
|
|
1258
|
-
"reflect-metadata": "^0.2.2",
|
|
1259
|
-
hono: "^4.6.0",
|
|
1260
|
-
zod: "^3.23.8"
|
|
1261
|
-
};
|
|
1262
|
-
const devDeps = {};
|
|
1263
|
-
if (orm === "drizzle") {
|
|
1264
|
-
coreDeps["@nexusts/drizzle"] = "*";
|
|
1265
|
-
coreDeps["drizzle-orm"] = "^0.45.0";
|
|
1266
|
-
if (db === "postgres")
|
|
1267
|
-
coreDeps["pg"] = "^8.13.0";
|
|
1268
|
-
if (db === "mysql")
|
|
1269
|
-
coreDeps["mysql2"] = "^3.11.0";
|
|
1270
|
-
if (db === "sqlite" || db === "node-sqlite" || db === "bun-sqlite")
|
|
1271
|
-
coreDeps["better-sqlite3"] = "^12.0.0";
|
|
1272
|
-
devDeps["drizzle-kit"] = "^0.31.0";
|
|
1273
|
-
}
|
|
1274
|
-
if (view !== "none") {
|
|
1275
|
-
coreDeps["@nexusts/static"] = "*";
|
|
1276
|
-
}
|
|
1600
|
+
const { deps, devDeps } = computeDeps(view, orm, db, frontend);
|
|
1277
1601
|
if (exists) {
|
|
1278
|
-
mergePackageJson(abs,
|
|
1602
|
+
mergePackageJson(abs, deps, devDeps, view, frontend);
|
|
1279
1603
|
merged.push(entry.path);
|
|
1280
1604
|
} else {
|
|
1281
|
-
const pkgJson =
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
type: "module",
|
|
1285
|
-
private: true,
|
|
1286
|
-
scripts: {
|
|
1287
|
-
dev: "bun --hot app/main.ts",
|
|
1288
|
-
build: "bun run build.ts",
|
|
1289
|
-
start: "bun app/main.ts",
|
|
1290
|
-
test: "vitest",
|
|
1291
|
-
nx: "nx"
|
|
1292
|
-
},
|
|
1293
|
-
dependencies: coreDeps
|
|
1294
|
-
};
|
|
1295
|
-
if (orm === "drizzle") {
|
|
1296
|
-
pkgJson.devDependencies = {
|
|
1297
|
-
"drizzle-kit": "^0.31.0"
|
|
1298
|
-
};
|
|
1299
|
-
}
|
|
1300
|
-
writeFileSync2(abs, JSON.stringify(pkgJson, null, 2));
|
|
1605
|
+
const pkgJson = buildPackageJson(name, deps, devDeps, view, frontend);
|
|
1606
|
+
writeFileSync3(abs, `${JSON.stringify(pkgJson, null, 2)}
|
|
1607
|
+
`);
|
|
1301
1608
|
created.push(entry.path);
|
|
1302
1609
|
}
|
|
1303
1610
|
continue;
|
|
@@ -1310,7 +1617,7 @@ var initCommand = {
|
|
|
1310
1617
|
});
|
|
1311
1618
|
merged.push(entry.path);
|
|
1312
1619
|
} else {
|
|
1313
|
-
|
|
1620
|
+
writeFileSync3(abs, defaultTsconfig());
|
|
1314
1621
|
created.push(entry.path);
|
|
1315
1622
|
}
|
|
1316
1623
|
continue;
|
|
@@ -1319,226 +1626,43 @@ var initCommand = {
|
|
|
1319
1626
|
skipped.push(entry.path);
|
|
1320
1627
|
continue;
|
|
1321
1628
|
}
|
|
1322
|
-
const content = renderContent(entry.path, {
|
|
1323
|
-
routing,
|
|
1324
|
-
view,
|
|
1325
|
-
viewPaths: view === "none" ? "" : "resources/views",
|
|
1326
|
-
orm,
|
|
1327
|
-
dbDriver: db,
|
|
1328
|
-
dbUrl: db === "bun-sqlite" || db === "node-sqlite" ? "app.db" : "",
|
|
1329
|
-
inertiaFrontend: frontend,
|
|
1330
|
-
inertiaSSR: ssr,
|
|
1331
|
-
inertiaVersion: "1.0.0",
|
|
1332
|
-
targetName: target.split("/").pop() ?? "nexus-app"
|
|
1333
|
-
});
|
|
1334
|
-
writeFileSync2(abs, content);
|
|
1335
1629
|
created.push(entry.path);
|
|
1336
1630
|
}
|
|
1631
|
+
const scaffoldOpts = { target, name, routing, view, orm, db, frontend, ssr, dbUrl };
|
|
1632
|
+
const scaffoldFiles = generateProjectFiles(target, scaffoldOpts);
|
|
1633
|
+
for (const f of scaffoldFiles) {
|
|
1634
|
+
if (!plan.some((p) => p.path === f)) {
|
|
1635
|
+
created.push(f);
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1337
1638
|
logger.success(`initialized NexusTS in ${target}`);
|
|
1338
1639
|
logger.blank();
|
|
1339
|
-
if (created.length)
|
|
1640
|
+
if (created.length)
|
|
1340
1641
|
logger.heading("Created");
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
if (merged.length) {
|
|
1642
|
+
for (const f of created)
|
|
1643
|
+
logger.info(` + ${f}`);
|
|
1644
|
+
if (merged.length)
|
|
1345
1645
|
logger.heading("Merged into existing files");
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
if (skipped.length) {
|
|
1646
|
+
for (const f of merged)
|
|
1647
|
+
logger.info(` ~ ${f}`);
|
|
1648
|
+
if (skipped.length)
|
|
1350
1649
|
logger.heading("Skipped (already exist; use --force to overwrite)");
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
}
|
|
1354
|
-
logger.blank();
|
|
1355
|
-
logger.heading("Next steps");
|
|
1356
|
-
logger.info(` cd ${target === ctx.cwd ? "." : target}`);
|
|
1357
|
-
logger.info(` bun install`);
|
|
1358
|
-
logger.info(` bun run dev`);
|
|
1650
|
+
for (const f of skipped)
|
|
1651
|
+
logger.info(` - ${f}`);
|
|
1359
1652
|
logger.blank();
|
|
1360
1653
|
return 0;
|
|
1361
1654
|
}
|
|
1362
1655
|
};
|
|
1363
|
-
function
|
|
1364
|
-
switch (path) {
|
|
1365
|
-
case "nx.config.ts":
|
|
1366
|
-
return render(templates.project["nx.config.ts"], ctx);
|
|
1367
|
-
case "public/.gitkeep":
|
|
1368
|
-
return "";
|
|
1369
|
-
case "resources/views/welcome.html":
|
|
1370
|
-
return `<h1>Welcome to ${ctx.targetName}</h1>
|
|
1371
|
-
<p>This is a sample Rendu template.</p>
|
|
1372
|
-
<p>Founded <?= year ?>.</p>
|
|
1373
|
-
`;
|
|
1374
|
-
case ".gitignore":
|
|
1375
|
-
return `# NexusTS
|
|
1376
|
-
node_modules/
|
|
1377
|
-
app.db
|
|
1378
|
-
*.db
|
|
1379
|
-
.env.local
|
|
1380
|
-
dist/
|
|
1381
|
-
`;
|
|
1382
|
-
case ".env":
|
|
1383
|
-
return `# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1384
|
-
# NexusTS \u2014 Environment Variables (committed to git)
|
|
1385
|
-
#
|
|
1386
|
-
# Shared defaults for all environments. Override locally via
|
|
1387
|
-
# .env.local (gitignored) or by environment via .env.{NODE_ENV}
|
|
1388
|
-
# (e.g. .env.production, .env.development).
|
|
1389
|
-
#
|
|
1390
|
-
# Uncomment the database config for your driver:
|
|
1391
|
-
# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1392
|
-
|
|
1393
|
-
# \u2500\u2500 App \u2500\u2500
|
|
1394
|
-
NODE_ENV=development
|
|
1395
|
-
PORT=3000
|
|
1396
|
-
|
|
1397
|
-
# \u2500\u2500 Session secret (REQUIRED) \u2500\u2500
|
|
1398
|
-
# Generate with: openssl rand -base64 32
|
|
1399
|
-
SESSION_SECRET=change-me-in-production
|
|
1400
|
-
|
|
1401
|
-
# \u2500\u2500 Database: SQLite (default, zero config) \u2500\u2500
|
|
1402
|
-
DATABASE_URL=app.db
|
|
1403
|
-
|
|
1404
|
-
# \u2500\u2500 Database: PostgreSQL \u2500\u2500
|
|
1405
|
-
# DATABASE_URL=postgres://user:password@localhost:5432/myapp
|
|
1406
|
-
|
|
1407
|
-
# \u2500\u2500 Database: MySQL \u2500\u2500
|
|
1408
|
-
# DATABASE_URL=mysql://user:password@localhost:3306/myapp
|
|
1409
|
-
|
|
1410
|
-
# \u2500\u2500 Better Auth (if using nexusjs/auth) \u2500\u2500
|
|
1411
|
-
# BETTER_AUTH_SECRET=
|
|
1412
|
-
# BETTER_AUTH_URL=http://localhost:3000
|
|
1413
|
-
`;
|
|
1414
|
-
case ".env.local":
|
|
1415
|
-
return `# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1416
|
-
# NexusTS \u2014 Local Overrides (DO NOT COMMIT to git)
|
|
1417
|
-
#
|
|
1418
|
-
# This file is gitignored. Use it for secrets and local
|
|
1419
|
-
# configuration that should never be checked in.
|
|
1420
|
-
# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
1421
|
-
|
|
1422
|
-
# Override any value from .env here:
|
|
1423
|
-
# DATABASE_URL=postgres://user:password@localhost:5432/myapp
|
|
1424
|
-
# SESSION_SECRET=my-local-secret
|
|
1425
|
-
`;
|
|
1426
|
-
case "drizzle.config.ts": {
|
|
1427
|
-
const dialect = ctx.dbDriver === "bun-sqlite" || ctx.dbDriver === "node-sqlite" || ctx.dbDriver === "libsql" ? "sqlite" : ctx.dbDriver === "postgres" ? "postgresql" : "sqlite";
|
|
1428
|
-
return render(templates.project["drizzle.config.ts"], {
|
|
1429
|
-
dialect,
|
|
1430
|
-
dbUrl: ctx.dbUrl || "app.db"
|
|
1431
|
-
});
|
|
1432
|
-
}
|
|
1433
|
-
case "app/main.ts": {
|
|
1434
|
-
const hasView = ctx.view !== "none";
|
|
1435
|
-
const staticMw = hasView ? `import { StaticModule } from '@nexusts/static';
|
|
1436
|
-
` + `const staticMiddleware = StaticModule.mount({ root: './public', prefix: '/static' });
|
|
1437
|
-
` : "";
|
|
1438
|
-
const staticOpt = hasView ? `
|
|
1439
|
-
middleware: [staticMiddleware],` : "";
|
|
1440
|
-
return `import 'reflect-metadata';
|
|
1441
|
-
import { Application } from '@nexusts/core';
|
|
1442
|
-
${staticMw}import { AppModule } from './app.module.js';
|
|
1443
|
-
|
|
1444
|
-
const app = new Application(AppModule, {
|
|
1445
|
-
logging: true,
|
|
1446
|
-
port: Number(process.env['PORT'] ?? 3000),${staticOpt}
|
|
1447
|
-
});
|
|
1448
|
-
|
|
1449
|
-
await app.listen();
|
|
1450
|
-
console.log('[nexus] Listening on http://localhost:' + (process.env['PORT'] ?? 3000));
|
|
1451
|
-
`;
|
|
1452
|
-
}
|
|
1453
|
-
case "app/app.module.ts": {
|
|
1454
|
-
const hasOrm = ctx.orm === "drizzle";
|
|
1455
|
-
const ormImport = hasOrm ? `import { DrizzleModule } from '@nexusts/drizzle';
|
|
1456
|
-
` : "";
|
|
1457
|
-
const forRootDialect = ctx.dbDriver === "bun-sqlite" ? "bun-sqlite" : "sqlite";
|
|
1458
|
-
const forRootFile = ctx.dbUrl || "app.db";
|
|
1459
|
-
const ormBlock = hasOrm ? ` DrizzleModule.forRoot({
|
|
1460
|
-
dialect: '` + forRootDialect + `',
|
|
1461
|
-
connection: { filename: '` + forRootFile + `' },
|
|
1462
|
-
logging: true,
|
|
1463
|
-
})` : "";
|
|
1464
|
-
return `${ormImport}import { Module } from '@nexusts/core';
|
|
1465
|
-
import { HomeController } from './controllers/home.controller.js';
|
|
1466
|
-
|
|
1467
|
-
@Module({
|
|
1468
|
-
imports: [${hasOrm ? `
|
|
1469
|
-
${ormBlock},
|
|
1470
|
-
` : ""} ],
|
|
1471
|
-
controllers: [HomeController],
|
|
1472
|
-
})
|
|
1473
|
-
export class AppModule {}
|
|
1474
|
-
`;
|
|
1475
|
-
}
|
|
1476
|
-
case "app/controllers/home.controller.ts": {
|
|
1477
|
-
const hasView = ctx.view !== "none";
|
|
1478
|
-
const body = hasView ? `{
|
|
1479
|
-
view: 'welcome.html',
|
|
1480
|
-
data: { year: new Date().getFullYear() },
|
|
1481
|
-
}` : `{ status: 200, body: { message: 'Hello from NexusTS!' } }`;
|
|
1482
|
-
return `import { Controller, Get } from '@nexusts/core';
|
|
1483
|
-
|
|
1484
|
-
@Controller('/')
|
|
1485
|
-
export class HomeController {
|
|
1486
|
-
@Get('/')
|
|
1487
|
-
index() {
|
|
1488
|
-
return ${body};
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
`;
|
|
1492
|
-
}
|
|
1493
|
-
case "README.md":
|
|
1494
|
-
return `# ${ctx.targetName}
|
|
1495
|
-
|
|
1496
|
-
A NexusTS project.
|
|
1497
|
-
|
|
1498
|
-
## Run
|
|
1499
|
-
|
|
1500
|
-
\`\`\`bash
|
|
1501
|
-
bun install
|
|
1502
|
-
bun run dev
|
|
1503
|
-
\`\`\`
|
|
1504
|
-
|
|
1505
|
-
## Scaffolding
|
|
1506
|
-
|
|
1507
|
-
\`\`\`bash
|
|
1508
|
-
bunx nx make:crud Post
|
|
1509
|
-
\`\`\`
|
|
1510
|
-
`;
|
|
1511
|
-
default:
|
|
1512
|
-
throw new Error(`No render template for: ${path}`);
|
|
1513
|
-
}
|
|
1514
|
-
}
|
|
1515
|
-
function defaultTsconfig() {
|
|
1516
|
-
return `{
|
|
1517
|
-
"compilerOptions": {
|
|
1518
|
-
"target": "ES2022",
|
|
1519
|
-
"module": "ESNext",
|
|
1520
|
-
"moduleResolution": "bundler",
|
|
1521
|
-
"experimentalDecorators": true,
|
|
1522
|
-
"emitDecoratorMetadata": true,
|
|
1523
|
-
"strict": true,
|
|
1524
|
-
"esModuleInterop": true,
|
|
1525
|
-
"skipLibCheck": true,
|
|
1526
|
-
"types": ["bun-types"]
|
|
1527
|
-
},
|
|
1528
|
-
"include": ["app/**/*.ts", "nx.config.ts"]
|
|
1529
|
-
}
|
|
1530
|
-
`;
|
|
1531
|
-
}
|
|
1532
|
-
function mergePackageJson(path, additions, devAdditions = {}) {
|
|
1656
|
+
function mergePackageJson(path, additions, devAdditions = {}, view, frontend) {
|
|
1533
1657
|
const raw = readFileSync4(path, "utf8");
|
|
1534
1658
|
const pkg = parseJsonLoose(raw);
|
|
1535
1659
|
let changed = false;
|
|
1536
|
-
if (!pkg
|
|
1537
|
-
pkg
|
|
1660
|
+
if (!pkg.type) {
|
|
1661
|
+
pkg.type = "module";
|
|
1538
1662
|
changed = true;
|
|
1539
1663
|
}
|
|
1540
|
-
if (!pkg
|
|
1541
|
-
pkg
|
|
1664
|
+
if (!pkg.private) {
|
|
1665
|
+
pkg.private = true;
|
|
1542
1666
|
changed = true;
|
|
1543
1667
|
}
|
|
1544
1668
|
const SCRIPTS = {
|
|
@@ -1548,38 +1672,41 @@ function mergePackageJson(path, additions, devAdditions = {}) {
|
|
|
1548
1672
|
test: "vitest",
|
|
1549
1673
|
nx: "nx"
|
|
1550
1674
|
};
|
|
1551
|
-
|
|
1675
|
+
if (view === "inertia") {
|
|
1676
|
+
const ext = frontend === "vue" ? "ts" : "tsx";
|
|
1677
|
+
SCRIPTS["build:frontend"] = `bun build ./resources/js/app.${ext} --outdir=./public --target=browser --format=esm --minify`;
|
|
1678
|
+
SCRIPTS.dev = `bun run build:frontend && bun --hot app/main.ts`;
|
|
1679
|
+
}
|
|
1680
|
+
const existingScripts = pkg.scripts ?? {};
|
|
1552
1681
|
for (const [k, v] of Object.entries(SCRIPTS)) {
|
|
1553
1682
|
if (!(k in existingScripts)) {
|
|
1554
1683
|
existingScripts[k] = v;
|
|
1555
1684
|
changed = true;
|
|
1556
1685
|
}
|
|
1557
1686
|
}
|
|
1558
|
-
if (Object.keys(existingScripts).length > 0)
|
|
1559
|
-
pkg
|
|
1560
|
-
}
|
|
1561
|
-
const deps = pkg["dependencies"] ?? {};
|
|
1687
|
+
if (Object.keys(existingScripts).length > 0)
|
|
1688
|
+
pkg.scripts = existingScripts;
|
|
1689
|
+
const deps = pkg.dependencies ?? {};
|
|
1562
1690
|
for (const [k, v] of Object.entries(additions)) {
|
|
1563
1691
|
if (!(k in deps)) {
|
|
1564
1692
|
deps[k] = v;
|
|
1565
1693
|
changed = true;
|
|
1566
1694
|
}
|
|
1567
1695
|
}
|
|
1568
|
-
pkg
|
|
1696
|
+
pkg.dependencies = deps;
|
|
1569
1697
|
if (Object.keys(devAdditions).length > 0) {
|
|
1570
|
-
const devDeps = pkg
|
|
1698
|
+
const devDeps = pkg.devDependencies ?? {};
|
|
1571
1699
|
for (const [k, v] of Object.entries(devAdditions)) {
|
|
1572
1700
|
if (!(k in devDeps)) {
|
|
1573
1701
|
devDeps[k] = v;
|
|
1574
1702
|
changed = true;
|
|
1575
1703
|
}
|
|
1576
1704
|
}
|
|
1577
|
-
pkg
|
|
1705
|
+
pkg.devDependencies = devDeps;
|
|
1578
1706
|
}
|
|
1579
|
-
if (changed)
|
|
1580
|
-
|
|
1707
|
+
if (changed)
|
|
1708
|
+
writeFileSync3(path, `${JSON.stringify(pkg, null, 2)}
|
|
1581
1709
|
`);
|
|
1582
|
-
}
|
|
1583
1710
|
}
|
|
1584
1711
|
function mergeTsconfig(path, additions) {
|
|
1585
1712
|
const raw = readFileSync4(path, "utf8");
|
|
@@ -1592,32 +1719,45 @@ function mergeTsconfig(path, additions) {
|
|
|
1592
1719
|
changed = true;
|
|
1593
1720
|
}
|
|
1594
1721
|
}
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
changed = true;
|
|
1722
|
+
cfg.compilerOptions = co;
|
|
1723
|
+
const include = cfg.include ?? [];
|
|
1724
|
+
for (const g of ["app/**/*.ts", "nx.config.ts"]) {
|
|
1725
|
+
if (!include.includes(g)) {
|
|
1726
|
+
include.push(g);
|
|
1727
|
+
changed = true;
|
|
1728
|
+
}
|
|
1603
1729
|
}
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
cfg
|
|
1607
|
-
writeFileSync2(path, JSON.stringify(cfg, null, 2) + `
|
|
1730
|
+
cfg.include = include;
|
|
1731
|
+
if (changed)
|
|
1732
|
+
writeFileSync3(path, `${JSON.stringify(cfg, null, 2)}
|
|
1608
1733
|
`);
|
|
1609
|
-
|
|
1734
|
+
}
|
|
1735
|
+
function defaultTsconfig() {
|
|
1736
|
+
return `{
|
|
1737
|
+
"compilerOptions": {
|
|
1738
|
+
"target": "ES2022",
|
|
1739
|
+
"module": "ESNext",
|
|
1740
|
+
"moduleResolution": "bundler",
|
|
1741
|
+
"experimentalDecorators": true,
|
|
1742
|
+
"emitDecoratorMetadata": true,
|
|
1743
|
+
"strict": true,
|
|
1744
|
+
"esModuleInterop": true,
|
|
1745
|
+
"skipLibCheck": true,
|
|
1746
|
+
"types": ["@types/bun"]
|
|
1747
|
+
},
|
|
1748
|
+
"include": ["app/**/*.ts", "nx.config.ts"]
|
|
1749
|
+
}
|
|
1750
|
+
`;
|
|
1610
1751
|
}
|
|
1611
1752
|
var init_default = initCommand;
|
|
1612
1753
|
|
|
1613
1754
|
// packages/cli/src/commands/make-auth.ts
|
|
1614
|
-
import { resolve as
|
|
1755
|
+
import { resolve as resolve7 } from "path";
|
|
1615
1756
|
var AUTH_INSTANCE_TEMPLATE = `/**
|
|
1616
1757
|
* Better-auth instance \u2014 generated by \`nx make:auth\`.
|
|
1617
1758
|
*
|
|
1618
1759
|
* Edit \`nx.config.ts\` (\`auth\` section) instead of this file when possible.
|
|
1619
1760
|
*/
|
|
1620
|
-
import 'reflect-metadata';
|
|
1621
1761
|
import { createAuth } from '@nexusts/auth';
|
|
1622
1762
|
|
|
1623
1763
|
export const auth = createAuth({
|
|
@@ -1726,7 +1866,7 @@ var makeAuthCommand = {
|
|
|
1726
1866
|
passkeyRpId: rpId,
|
|
1727
1867
|
passkeyOrigin: Array.isArray(origin) ? origin.join(",") : origin
|
|
1728
1868
|
});
|
|
1729
|
-
const authOut =
|
|
1869
|
+
const authOut = resolve7(ctx.cwd, "app/auth/auth.ts");
|
|
1730
1870
|
if (writeFile(authOut, authCode)) {
|
|
1731
1871
|
logger.success(`created ${authOut}`);
|
|
1732
1872
|
} else {
|
|
@@ -1736,7 +1876,7 @@ var makeAuthCommand = {
|
|
|
1736
1876
|
providers: providers.length > 0,
|
|
1737
1877
|
entries
|
|
1738
1878
|
});
|
|
1739
|
-
const envOut =
|
|
1879
|
+
const envOut = resolve7(ctx.cwd, ".env.example");
|
|
1740
1880
|
if (writeFile(envOut, envCode, { skipIfExists: true })) {
|
|
1741
1881
|
logger.success(`created ${envOut}`);
|
|
1742
1882
|
} else {
|
|
@@ -1762,7 +1902,7 @@ var makeAuthCommand = {
|
|
|
1762
1902
|
var make_auth_default = makeAuthCommand;
|
|
1763
1903
|
|
|
1764
1904
|
// packages/cli/src/commands/make-controller.ts
|
|
1765
|
-
import { resolve as
|
|
1905
|
+
import { resolve as resolve8 } from "path";
|
|
1766
1906
|
var makeControllerCommand = {
|
|
1767
1907
|
name: "make:controller",
|
|
1768
1908
|
aliases: ["mc", "make-controller"],
|
|
@@ -1808,7 +1948,7 @@ var makeControllerCommand = {
|
|
|
1808
1948
|
service: serviceName,
|
|
1809
1949
|
serviceCamel
|
|
1810
1950
|
}).replace(/import .*\n/g, skipService ? (m) => m.includes("services/") ? "" : m : (m) => m);
|
|
1811
|
-
const out =
|
|
1951
|
+
const out = resolve8(ctx.cwd, ctx.config.paths.controllers, `${variants.kebab}.controller.ts`);
|
|
1812
1952
|
const ok = writeFile(out, code, { skipIfExists: false });
|
|
1813
1953
|
if (!ok) {
|
|
1814
1954
|
logger.error(`Refusing to overwrite existing file: ${out}`);
|
|
@@ -1823,7 +1963,7 @@ var make_controller_default = makeControllerCommand;
|
|
|
1823
1963
|
|
|
1824
1964
|
// packages/cli/src/commands/make-crud.ts
|
|
1825
1965
|
import { mkdirSync as mkdirSync3 } from "fs";
|
|
1826
|
-
import { dirname as dirname3, resolve as
|
|
1966
|
+
import { dirname as dirname3, resolve as resolve9 } from "path";
|
|
1827
1967
|
|
|
1828
1968
|
// packages/cli/src/templates/model/drizzle-dialect.ts
|
|
1829
1969
|
function renderDrizzleDialect(dialect) {
|
|
@@ -1871,10 +2011,10 @@ var DIALECT_SPECS = {
|
|
|
1871
2011
|
tableFn: "sqliteTable",
|
|
1872
2012
|
idHelper: "integer",
|
|
1873
2013
|
idOpts: "{ autoIncrement: true }",
|
|
1874
|
-
tsTimestamp: "
|
|
1875
|
-
tsDateMode: "",
|
|
1876
|
-
defaultTs: ".$defaultFn(() =>
|
|
1877
|
-
defaultTsUpdate: ""
|
|
2014
|
+
tsTimestamp: "integer",
|
|
2015
|
+
tsDateMode: ", { mode: 'timestamp' }",
|
|
2016
|
+
defaultTs: ".$defaultFn(() => Date.now())",
|
|
2017
|
+
defaultTsUpdate: ".$defaultFn(() => Date.now())"
|
|
1878
2018
|
},
|
|
1879
2019
|
sqlite: {
|
|
1880
2020
|
imports: ["sqliteTable", "integer", "text", "real"],
|
|
@@ -1998,7 +2138,7 @@ var makeCrudCommand = {
|
|
|
1998
2138
|
viewShowComponent,
|
|
1999
2139
|
hasInertia
|
|
2000
2140
|
});
|
|
2001
|
-
const out =
|
|
2141
|
+
const out = resolve9(ctx.cwd, ctx.config.paths.controllers, `${variants.kebab}.controller.ts`);
|
|
2002
2142
|
if (!writeFile(out, code, { skipIfExists: true })) {
|
|
2003
2143
|
logger.warn(`skipped (exists): ${out}`);
|
|
2004
2144
|
} else {
|
|
@@ -2016,7 +2156,7 @@ var makeCrudCommand = {
|
|
|
2016
2156
|
repository,
|
|
2017
2157
|
repositoryCamel: variants.camel + "Repository"
|
|
2018
2158
|
});
|
|
2019
|
-
const out =
|
|
2159
|
+
const out = resolve9(ctx.cwd, ctx.config.paths.services, `${variants.kebab}.service.ts`);
|
|
2020
2160
|
if (!writeFile(out, code, { skipIfExists: true })) {
|
|
2021
2161
|
logger.warn(`skipped (exists): ${out}`);
|
|
2022
2162
|
} else {
|
|
@@ -2050,7 +2190,7 @@ var makeCrudCommand = {
|
|
|
2050
2190
|
prismaBlock: ""
|
|
2051
2191
|
});
|
|
2052
2192
|
}
|
|
2053
|
-
const out =
|
|
2193
|
+
const out = resolve9(ctx.cwd, ctx.config.paths.models, `${variants.kebab}.model.ts`);
|
|
2054
2194
|
if (!writeFile(out, code, { skipIfExists: true })) {
|
|
2055
2195
|
logger.warn(`skipped (exists): ${out}`);
|
|
2056
2196
|
} else {
|
|
@@ -2066,7 +2206,7 @@ var makeCrudCommand = {
|
|
|
2066
2206
|
tableName,
|
|
2067
2207
|
repository
|
|
2068
2208
|
});
|
|
2069
|
-
const repoOut =
|
|
2209
|
+
const repoOut = resolve9(ctx.cwd, `${ctx.config.paths.app}/repositories`, `${variants.kebab}.repository.ts`);
|
|
2070
2210
|
mkdirSync3(dirname3(repoOut), { recursive: true });
|
|
2071
2211
|
if (!writeFile(repoOut, repoCode, { skipIfExists: true })) {
|
|
2072
2212
|
logger.warn(`skipped (exists): ${repoOut}`);
|
|
@@ -2081,7 +2221,7 @@ var makeCrudCommand = {
|
|
|
2081
2221
|
camel: variants.camel,
|
|
2082
2222
|
kebab: variants.kebab
|
|
2083
2223
|
});
|
|
2084
|
-
const out =
|
|
2224
|
+
const out = resolve9(ctx.cwd, ctx.config.paths.dto, `${variants.kebab}.dto.ts`);
|
|
2085
2225
|
if (!writeFile(out, code, { skipIfExists: true })) {
|
|
2086
2226
|
logger.warn(`skipped (exists): ${out}`);
|
|
2087
2227
|
} else {
|
|
@@ -2099,7 +2239,7 @@ var makeCrudCommand = {
|
|
|
2099
2239
|
repository,
|
|
2100
2240
|
hasRepo: !noRepo
|
|
2101
2241
|
});
|
|
2102
|
-
const out =
|
|
2242
|
+
const out = resolve9(ctx.cwd, ctx.config.paths.modules, `${variants.kebab}.module.ts`);
|
|
2103
2243
|
if (!writeFile(out, code, { skipIfExists: true })) {
|
|
2104
2244
|
logger.warn(`skipped (exists): ${out}`);
|
|
2105
2245
|
} else {
|
|
@@ -2115,7 +2255,7 @@ var makeCrudCommand = {
|
|
|
2115
2255
|
controller,
|
|
2116
2256
|
service
|
|
2117
2257
|
});
|
|
2118
|
-
const out =
|
|
2258
|
+
const out = resolve9(ctx.cwd, "tests", `${variants.kebab}.test.ts`);
|
|
2119
2259
|
if (!writeFile(out, code, { skipIfExists: true })) {
|
|
2120
2260
|
logger.warn(`skipped (exists): ${out}`);
|
|
2121
2261
|
} else {
|
|
@@ -2151,7 +2291,7 @@ function renderDrizzleColumns(dialect) {
|
|
|
2151
2291
|
var make_crud_default = makeCrudCommand;
|
|
2152
2292
|
|
|
2153
2293
|
// packages/cli/src/commands/make-listener.ts
|
|
2154
|
-
import { resolve as
|
|
2294
|
+
import { resolve as resolve10 } from "path";
|
|
2155
2295
|
var LISTENER_TEMPLATE = `
|
|
2156
2296
|
import { Inject, Injectable } from '@nexusts/core';
|
|
2157
2297
|
import { EventService, OnEvent } from '@nexusts/events';
|
|
@@ -2202,7 +2342,7 @@ var makeListenerCommand = {
|
|
|
2202
2342
|
name: variants.pascal,
|
|
2203
2343
|
kebab: variants.kebab
|
|
2204
2344
|
});
|
|
2205
|
-
const out =
|
|
2345
|
+
const out = resolve10(ctx.cwd, "app/events/listeners", `${variants.kebab}.listener.ts`);
|
|
2206
2346
|
if (writeFile(out, code, { skipIfExists: true })) {
|
|
2207
2347
|
logger.success(`created ${out}`);
|
|
2208
2348
|
} else {
|
|
@@ -2222,7 +2362,7 @@ var makeListenerCommand = {
|
|
|
2222
2362
|
var make_listener_default = makeListenerCommand;
|
|
2223
2363
|
|
|
2224
2364
|
// packages/cli/src/commands/make-middleware.ts
|
|
2225
|
-
import { resolve as
|
|
2365
|
+
import { resolve as resolve11 } from "path";
|
|
2226
2366
|
var makeMiddlewareCommand = {
|
|
2227
2367
|
name: "make:middleware",
|
|
2228
2368
|
aliases: ["mwm", "make-middleware"],
|
|
@@ -2239,7 +2379,7 @@ var makeMiddlewareCommand = {
|
|
|
2239
2379
|
const code = render(templates.middleware, {
|
|
2240
2380
|
name: variants.pascal
|
|
2241
2381
|
});
|
|
2242
|
-
const out =
|
|
2382
|
+
const out = resolve11(ctx.cwd, ctx.config.paths.middleware, `${variants.kebab}.middleware.ts`);
|
|
2243
2383
|
writeFile(out, code);
|
|
2244
2384
|
logger.success(`created ${out}`);
|
|
2245
2385
|
logger.finger(`register with: app.server.app.use('*', new ${variants.pascal}Middleware().handle)`);
|
|
@@ -2249,7 +2389,7 @@ var makeMiddlewareCommand = {
|
|
|
2249
2389
|
var make_middleware_default = makeMiddlewareCommand;
|
|
2250
2390
|
|
|
2251
2391
|
// packages/cli/src/commands/make-migration.ts
|
|
2252
|
-
import { resolve as
|
|
2392
|
+
import { resolve as resolve12 } from "path";
|
|
2253
2393
|
var makeMigrationCommand = {
|
|
2254
2394
|
name: "make:migration",
|
|
2255
2395
|
aliases: ["mkm", "make-migration"],
|
|
@@ -2321,7 +2461,7 @@ var makeMigrationCommand = {
|
|
|
2321
2461
|
return 1;
|
|
2322
2462
|
}
|
|
2323
2463
|
const filename = `${formatTimestamp(new Date)}_${variants.snake}.${extension}`;
|
|
2324
|
-
const out =
|
|
2464
|
+
const out = resolve12(ctx.cwd, ctx.config.paths.migrations, filename);
|
|
2325
2465
|
writeFile(out, code);
|
|
2326
2466
|
logger.success(`created ${out}`);
|
|
2327
2467
|
if (isDrizzle) {
|
|
@@ -2409,7 +2549,7 @@ function formatTimestamp(d) {
|
|
|
2409
2549
|
var make_migration_default = makeMigrationCommand;
|
|
2410
2550
|
|
|
2411
2551
|
// packages/cli/src/commands/make-model.ts
|
|
2412
|
-
import { resolve as
|
|
2552
|
+
import { resolve as resolve13 } from "path";
|
|
2413
2553
|
var makeModelCommand = {
|
|
2414
2554
|
name: "make:model",
|
|
2415
2555
|
aliases: ["mmodel", "make-model"],
|
|
@@ -2481,7 +2621,7 @@ var makeModelCommand = {
|
|
|
2481
2621
|
prismaBlock
|
|
2482
2622
|
});
|
|
2483
2623
|
}
|
|
2484
|
-
const out =
|
|
2624
|
+
const out = resolve13(ctx.cwd, ctx.config.paths.models, `${variants.kebab}.model.ts`);
|
|
2485
2625
|
writeFile(out, code);
|
|
2486
2626
|
logger.success(`created ${out}`);
|
|
2487
2627
|
logger.finger(`run \`nx make:migration create_${tableName}_table\` to scaffold a migration.`);
|
|
@@ -2540,7 +2680,7 @@ function capitalize(s) {
|
|
|
2540
2680
|
var make_model_default = makeModelCommand;
|
|
2541
2681
|
|
|
2542
2682
|
// packages/cli/src/commands/make-module.ts
|
|
2543
|
-
import { resolve as
|
|
2683
|
+
import { resolve as resolve14 } from "path";
|
|
2544
2684
|
var makeModuleCommand = {
|
|
2545
2685
|
name: "make:module",
|
|
2546
2686
|
aliases: ["mm", "make-module"],
|
|
@@ -2574,7 +2714,7 @@ var makeModuleCommand = {
|
|
|
2574
2714
|
hasService,
|
|
2575
2715
|
hasRepo
|
|
2576
2716
|
});
|
|
2577
|
-
const out =
|
|
2717
|
+
const out = resolve14(ctx.cwd, ctx.config.paths.modules, `${variants.kebab}.module.ts`);
|
|
2578
2718
|
writeFile(out, code);
|
|
2579
2719
|
logger.success(`created ${out}`);
|
|
2580
2720
|
logger.finger(`add ${variants.pascal}Module to AppModule.imports.`);
|
|
@@ -2584,7 +2724,7 @@ var makeModuleCommand = {
|
|
|
2584
2724
|
var make_module_default = makeModuleCommand;
|
|
2585
2725
|
|
|
2586
2726
|
// packages/cli/src/commands/make-queue.ts
|
|
2587
|
-
import { resolve as
|
|
2727
|
+
import { resolve as resolve15 } from "path";
|
|
2588
2728
|
var WORKER_TEMPLATE = `
|
|
2589
2729
|
import { Inject, Injectable } from '@nexusts/core';
|
|
2590
2730
|
import { QueueService, OnQueueReady } from '@nexusts/queue';
|
|
@@ -2712,7 +2852,7 @@ var makeQueueCommand = {
|
|
|
2712
2852
|
name: variants.pascal,
|
|
2713
2853
|
kebab: variants.kebab
|
|
2714
2854
|
});
|
|
2715
|
-
const out =
|
|
2855
|
+
const out = resolve15(ctx.cwd, "app/queue/workers", `${variants.kebab}.worker.ts`);
|
|
2716
2856
|
if (writeFile(out, code, { skipIfExists: true })) {
|
|
2717
2857
|
logger.success(`created ${out}`);
|
|
2718
2858
|
} else {
|
|
@@ -2724,7 +2864,7 @@ var makeQueueCommand = {
|
|
|
2724
2864
|
name: variants.pascal,
|
|
2725
2865
|
kebab: variants.kebab
|
|
2726
2866
|
});
|
|
2727
|
-
const out =
|
|
2867
|
+
const out = resolve15(ctx.cwd, "app/queue/jobs", `${variants.kebab}.job.ts`);
|
|
2728
2868
|
if (writeFile(out, code, { skipIfExists: true })) {
|
|
2729
2869
|
logger.success(`created ${out}`);
|
|
2730
2870
|
} else {
|
|
@@ -2748,7 +2888,7 @@ var make_queue_default = makeQueueCommand;
|
|
|
2748
2888
|
|
|
2749
2889
|
// packages/cli/src/commands/make-repository.ts
|
|
2750
2890
|
import { mkdirSync as mkdirSync4 } from "fs";
|
|
2751
|
-
import { resolve as
|
|
2891
|
+
import { resolve as resolve16, dirname as dirname4 } from "path";
|
|
2752
2892
|
var makeRepositoryCommand = {
|
|
2753
2893
|
name: "make:repository",
|
|
2754
2894
|
aliases: ["mr", "make-repository", "make:repo"],
|
|
@@ -2773,7 +2913,7 @@ var makeRepositoryCommand = {
|
|
|
2773
2913
|
snake: variants.snake,
|
|
2774
2914
|
repository
|
|
2775
2915
|
});
|
|
2776
|
-
const out =
|
|
2916
|
+
const out = resolve16(ctx.cwd, `${ctx.config.paths.app}/repositories`, `${variants.kebab}.repository.ts`);
|
|
2777
2917
|
mkdirSync4(dirname4(out), { recursive: true });
|
|
2778
2918
|
writeFile(out, code);
|
|
2779
2919
|
logger.success(`created ${out}`);
|
|
@@ -2783,7 +2923,7 @@ var makeRepositoryCommand = {
|
|
|
2783
2923
|
var make_repository_default = makeRepositoryCommand;
|
|
2784
2924
|
|
|
2785
2925
|
// packages/cli/src/commands/make-schedule.ts
|
|
2786
|
-
import { resolve as
|
|
2926
|
+
import { resolve as resolve17 } from "path";
|
|
2787
2927
|
var TASK_TEMPLATE = `
|
|
2788
2928
|
import { Injectable } from '@nexusts/core';
|
|
2789
2929
|
import { Cron, Interval, Timeout } from '@nexusts/schedule';
|
|
@@ -2827,7 +2967,7 @@ var makeScheduleCommand = {
|
|
|
2827
2967
|
name: variants.pascal,
|
|
2828
2968
|
kebab: variants.kebab
|
|
2829
2969
|
});
|
|
2830
|
-
const out =
|
|
2970
|
+
const out = resolve17(ctx.cwd, "app/schedule/tasks", `${variants.kebab}.task.ts`);
|
|
2831
2971
|
if (writeFile(out, code, { skipIfExists: true })) {
|
|
2832
2972
|
logger.success(`created ${out}`);
|
|
2833
2973
|
} else {
|
|
@@ -2845,7 +2985,7 @@ var makeScheduleCommand = {
|
|
|
2845
2985
|
var make_schedule_default = makeScheduleCommand;
|
|
2846
2986
|
|
|
2847
2987
|
// packages/cli/src/commands/make-service.ts
|
|
2848
|
-
import { resolve as
|
|
2988
|
+
import { resolve as resolve18 } from "path";
|
|
2849
2989
|
var makeServiceCommand = {
|
|
2850
2990
|
name: "make:service",
|
|
2851
2991
|
aliases: ["ms", "make-service"],
|
|
@@ -2877,7 +3017,7 @@ var makeServiceCommand = {
|
|
|
2877
3017
|
repository,
|
|
2878
3018
|
repositoryCamel
|
|
2879
3019
|
});
|
|
2880
|
-
const out =
|
|
3020
|
+
const out = resolve18(ctx.cwd, ctx.config.paths.services, `${variants.kebab}.service.ts`);
|
|
2881
3021
|
writeFile(out, code);
|
|
2882
3022
|
logger.success(`created ${out}`);
|
|
2883
3023
|
return 0;
|
|
@@ -2886,7 +3026,7 @@ var makeServiceCommand = {
|
|
|
2886
3026
|
var make_service_default = makeServiceCommand;
|
|
2887
3027
|
|
|
2888
3028
|
// packages/cli/src/commands/make-session.ts
|
|
2889
|
-
import { resolve as
|
|
3029
|
+
import { resolve as resolve19 } from "path";
|
|
2890
3030
|
var SESSION_TEMPLATE = `
|
|
2891
3031
|
import { Inject, Injectable } from '@nexusts/core';
|
|
2892
3032
|
import { SessionService } from '@nexusts/session';
|
|
@@ -2948,7 +3088,7 @@ var makeSessionCommand = {
|
|
|
2948
3088
|
name: variants.pascal,
|
|
2949
3089
|
kebab: variants.kebab
|
|
2950
3090
|
});
|
|
2951
|
-
const out =
|
|
3091
|
+
const out = resolve19(ctx.cwd, "app/session/services", `${variants.kebab}.session.ts`);
|
|
2952
3092
|
if (writeFile(out, code, { skipIfExists: true })) {
|
|
2953
3093
|
logger.success(`created ${out}`);
|
|
2954
3094
|
} else {
|
|
@@ -2966,7 +3106,7 @@ var makeSessionCommand = {
|
|
|
2966
3106
|
var make_session_default = makeSessionCommand;
|
|
2967
3107
|
|
|
2968
3108
|
// packages/cli/src/commands/make-validator.ts
|
|
2969
|
-
import { resolve as
|
|
3109
|
+
import { resolve as resolve20 } from "path";
|
|
2970
3110
|
var makeValidatorCommand = {
|
|
2971
3111
|
name: "make:validator",
|
|
2972
3112
|
aliases: ["mv", "make-validator"],
|
|
@@ -2983,7 +3123,7 @@ var makeValidatorCommand = {
|
|
|
2983
3123
|
const code = render(templates.validator, {
|
|
2984
3124
|
name: variants.pascal
|
|
2985
3125
|
});
|
|
2986
|
-
const out =
|
|
3126
|
+
const out = resolve20(ctx.cwd, ctx.config.paths.dto, `${variants.kebab}.dto.ts`);
|
|
2987
3127
|
writeFile(out, code);
|
|
2988
3128
|
logger.success(`created ${out}`);
|
|
2989
3129
|
return 0;
|
|
@@ -2994,7 +3134,7 @@ var make_validator_default = makeValidatorCommand;
|
|
|
2994
3134
|
// packages/cli/src/commands/db-migrate.ts
|
|
2995
3135
|
import { spawn } from "child_process";
|
|
2996
3136
|
import { existsSync as existsSync5 } from "fs";
|
|
2997
|
-
import { resolve as
|
|
3137
|
+
import { resolve as resolve21 } from "path";
|
|
2998
3138
|
var dbMigrateCommand = {
|
|
2999
3139
|
name: "db:migrate",
|
|
3000
3140
|
aliases: ["db:m", "migrate"],
|
|
@@ -3029,9 +3169,9 @@ var dbMigrateCommand = {
|
|
|
3029
3169
|
}
|
|
3030
3170
|
],
|
|
3031
3171
|
async run(ctx) {
|
|
3032
|
-
const folder = ctx.flags["folder"] ??
|
|
3172
|
+
const folder = ctx.flags["folder"] ?? resolve21(ctx.cwd, ctx.config.paths.migrations);
|
|
3033
3173
|
const dialect = ctx.flags["dialect"] ?? ctx.config.dialect ?? "bun-sqlite";
|
|
3034
|
-
const configPath = ctx.flags["config"] ??
|
|
3174
|
+
const configPath = ctx.flags["config"] ?? resolve21(ctx.cwd, "drizzle.config.ts");
|
|
3035
3175
|
const wantStatus = Boolean(ctx.flags["status"]);
|
|
3036
3176
|
const generateName = ctx.flags["generate"];
|
|
3037
3177
|
if (generateName) {
|
|
@@ -3078,7 +3218,6 @@ async function runStatus(cwd, folder, dialect, configUrl = "") {
|
|
|
3078
3218
|
return 1;
|
|
3079
3219
|
}
|
|
3080
3220
|
const script = `
|
|
3081
|
-
import 'reflect-metadata';
|
|
3082
3221
|
import { DrizzleService } from '@nexusts/drizzle';
|
|
3083
3222
|
|
|
3084
3223
|
const url = ${JSON.stringify(url)};
|
|
@@ -3092,7 +3231,7 @@ const applied = await svc.appliedMigrations();
|
|
|
3092
3231
|
console.log(JSON.stringify({ total: applied.length, applied }, null, 2));
|
|
3093
3232
|
await svc.close();
|
|
3094
3233
|
`;
|
|
3095
|
-
const tmpFile =
|
|
3234
|
+
const tmpFile = resolve21(cwd, ".nx-migrate-status.mjs");
|
|
3096
3235
|
await import("fs/promises").then((m) => m.writeFile(tmpFile, script, "utf-8"));
|
|
3097
3236
|
try {
|
|
3098
3237
|
const code = await new Promise((resP) => {
|
|
@@ -3116,7 +3255,7 @@ function readEnvUrl(dialect) {
|
|
|
3116
3255
|
var db_migrate_default = dbMigrateCommand;
|
|
3117
3256
|
|
|
3118
3257
|
// packages/cli/src/commands/db-generate.ts
|
|
3119
|
-
import { resolve as
|
|
3258
|
+
import { resolve as resolve22 } from "path";
|
|
3120
3259
|
var dbGenerateCommand = {
|
|
3121
3260
|
name: "db:generate",
|
|
3122
3261
|
aliases: ["db:g", "db-generate", "generate-migration"],
|
|
@@ -3149,7 +3288,7 @@ var dbGenerateCommand = {
|
|
|
3149
3288
|
logger.info(`Generating raw SQL migration: ${name} (dialect=${dialect})`);
|
|
3150
3289
|
return runSqlTemplate(ctx.cwd, name, dialect);
|
|
3151
3290
|
}
|
|
3152
|
-
const configPath =
|
|
3291
|
+
const configPath = resolve22(ctx.cwd, "drizzle.config.ts");
|
|
3153
3292
|
const args2 = ["generate", "--config", configPath];
|
|
3154
3293
|
if (name)
|
|
3155
3294
|
args2.push("--name", name);
|
|
@@ -3158,7 +3297,7 @@ var dbGenerateCommand = {
|
|
|
3158
3297
|
}
|
|
3159
3298
|
};
|
|
3160
3299
|
async function runSqlTemplate(cwd, name, dialect) {
|
|
3161
|
-
const { mkdirSync: mkdirSync5, writeFileSync:
|
|
3300
|
+
const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync4 } = await import("fs");
|
|
3162
3301
|
const { join } = await import("path");
|
|
3163
3302
|
const migrationsDir = join(cwd, "app", "database", "migrations");
|
|
3164
3303
|
mkdirSync5(migrationsDir, { recursive: true });
|
|
@@ -3174,7 +3313,7 @@ async function runSqlTemplate(cwd, name, dialect) {
|
|
|
3174
3313
|
-- Generated: ${new Date().toISOString()}
|
|
3175
3314
|
|
|
3176
3315
|
`;
|
|
3177
|
-
|
|
3316
|
+
writeFileSync4(filepath, header);
|
|
3178
3317
|
logger.success(`created ${filepath}`);
|
|
3179
3318
|
logger.info("Edit the SQL file, then run `nx db:migrate` to apply it.");
|
|
3180
3319
|
return 0;
|
|
@@ -3185,7 +3324,7 @@ var db_generate_default = dbGenerateCommand;
|
|
|
3185
3324
|
import { spawn as spawn2 } from "child_process";
|
|
3186
3325
|
import { existsSync as existsSync6 } from "fs";
|
|
3187
3326
|
import { mkdir, readdir, writeFile as writeFile2, unlink } from "fs/promises";
|
|
3188
|
-
import { resolve as
|
|
3327
|
+
import { resolve as resolve23 } from "path";
|
|
3189
3328
|
var SEED_TEMPLATE = `/**
|
|
3190
3329
|
* Seed: {name}
|
|
3191
3330
|
*
|
|
@@ -3255,7 +3394,7 @@ var dbSeedCommand = {
|
|
|
3255
3394
|
}
|
|
3256
3395
|
],
|
|
3257
3396
|
async run(ctx) {
|
|
3258
|
-
const folder =
|
|
3397
|
+
const folder = resolve23(ctx.cwd, ctx.flags["folder"] ?? ctx.config.paths?.seeds ?? "db/seeds");
|
|
3259
3398
|
const dialect = ctx.flags["dialect"] ?? ctx.config.dialect ?? "bun-sqlite";
|
|
3260
3399
|
const createName = ctx.flags["create"];
|
|
3261
3400
|
const fileName = ctx.flags["file"];
|
|
@@ -3266,7 +3405,7 @@ var dbSeedCommand = {
|
|
|
3266
3405
|
if (!existsSync6(folder)) {
|
|
3267
3406
|
logger.info(`creating empty seeds folder at ${folder}`);
|
|
3268
3407
|
await mkdir(folder, { recursive: true });
|
|
3269
|
-
await writeFile2(
|
|
3408
|
+
await writeFile2(resolve23(folder, "_README.ts"), `// Seed files go here. Run with: nx db:seed
|
|
3270
3409
|
`, "utf-8");
|
|
3271
3410
|
return 0;
|
|
3272
3411
|
}
|
|
@@ -3290,12 +3429,11 @@ var dbSeedCommand = {
|
|
|
3290
3429
|
if (reset) {
|
|
3291
3430
|
logger.warn("--reset is set: truncating every table in the schema before running seeds.");
|
|
3292
3431
|
}
|
|
3293
|
-
const seedImports = target.map((f, i) => `import seed_${i} from ${JSON.stringify(
|
|
3432
|
+
const seedImports = target.map((f, i) => `import seed_${i} from ${JSON.stringify(resolve23(folder, f))};`).join(`
|
|
3294
3433
|
`);
|
|
3295
3434
|
const seedCalls = target.map((_, i) => ` await seed_${i}({ db, logger, dialect, truncate: (t) => db.truncate(t) });`).join(`
|
|
3296
3435
|
`);
|
|
3297
3436
|
const script = `
|
|
3298
|
-
import 'reflect-metadata';
|
|
3299
3437
|
import { DrizzleService } from '@nexusts/drizzle';
|
|
3300
3438
|
import { Logger } from '@nexusts/logger';
|
|
3301
3439
|
|
|
@@ -3324,7 +3462,7 @@ ${seedCalls}
|
|
|
3324
3462
|
await db.close();
|
|
3325
3463
|
logger.info(\`Seeds complete (\${${target.length}} file(s))\`);
|
|
3326
3464
|
`;
|
|
3327
|
-
const tmpFile =
|
|
3465
|
+
const tmpFile = resolve23(ctx.cwd, ".nx-db-seed.mjs");
|
|
3328
3466
|
await writeFile2(tmpFile, script, "utf-8");
|
|
3329
3467
|
try {
|
|
3330
3468
|
const code = await new Promise((resP) => {
|
|
@@ -3366,11 +3504,11 @@ async function createSeedFile(folder, name) {
|
|
|
3366
3504
|
await mkdir(folder, { recursive: true });
|
|
3367
3505
|
let candidate = `${name}.ts`;
|
|
3368
3506
|
let i = 1;
|
|
3369
|
-
while (existsSync6(
|
|
3507
|
+
while (existsSync6(resolve23(folder, candidate))) {
|
|
3370
3508
|
candidate = `${name}_${i}.ts`;
|
|
3371
3509
|
i++;
|
|
3372
3510
|
}
|
|
3373
|
-
const path =
|
|
3511
|
+
const path = resolve23(folder, candidate);
|
|
3374
3512
|
const body = SEED_TEMPLATE.replace(/\{name\}/g, name);
|
|
3375
3513
|
await writeFile2(path, body, "utf-8");
|
|
3376
3514
|
logger.info(`created ${path}`);
|
|
@@ -3383,8 +3521,34 @@ function readEnvUrl2(dialect) {
|
|
|
3383
3521
|
var db_seed_default = dbSeedCommand;
|
|
3384
3522
|
|
|
3385
3523
|
// packages/cli/src/commands/new.ts
|
|
3386
|
-
import { existsSync as existsSync7, mkdirSync as mkdirSync5, writeFileSync as
|
|
3387
|
-
import { resolve as
|
|
3524
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, writeFileSync as writeFileSync4 } from "fs";
|
|
3525
|
+
import { resolve as resolve24 } from "path";
|
|
3526
|
+
var VALID_OPTIONS2 = {
|
|
3527
|
+
style: ["nest", "adonis", "functional"],
|
|
3528
|
+
view: ["rendu", "edge", "eta", "inertia", "none"],
|
|
3529
|
+
orm: ["drizzle", "prisma", "kysely", "none"],
|
|
3530
|
+
db: ["bun-sqlite", "node-sqlite", "libsql", "postgres", "mysql", "none"],
|
|
3531
|
+
frontend: ["react", "vue", "svelte", "solid"]
|
|
3532
|
+
};
|
|
3533
|
+
async function resolveOpt2(flags, key, valid, defaultVal, interactive) {
|
|
3534
|
+
const flagVal = flags[key];
|
|
3535
|
+
if (flagVal) {
|
|
3536
|
+
if (valid.includes(flagVal))
|
|
3537
|
+
return flagVal;
|
|
3538
|
+
if (!interactive) {
|
|
3539
|
+
logger.error(`Invalid --${key} "${flagVal}". Valid values: ${valid.join(", ")}`);
|
|
3540
|
+
process.exit(1);
|
|
3541
|
+
}
|
|
3542
|
+
logger.warn(`"${flagVal}" is not valid for --${key}. Please choose from the list.`);
|
|
3543
|
+
}
|
|
3544
|
+
const label = key === "style" ? "Routing style" : key === "view" ? "View engine" : key === "orm" ? "ORM driver" : key === "db" ? "Database driver" : "Inertia frontend";
|
|
3545
|
+
for (;; ) {
|
|
3546
|
+
const answer = await select(label, [...valid], { default: defaultVal });
|
|
3547
|
+
if (valid.includes(answer))
|
|
3548
|
+
return answer;
|
|
3549
|
+
logger.warn(`"${answer}" is not valid. Please choose from: ${valid.join(", ")}`);
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3388
3552
|
var newCommand = {
|
|
3389
3553
|
name: "new",
|
|
3390
3554
|
aliases: ["n"],
|
|
@@ -3392,131 +3556,38 @@ var newCommand = {
|
|
|
3392
3556
|
description: "Generates a new project directory with nx.config.ts, tsconfig, package.json, and a starter app/main.ts.",
|
|
3393
3557
|
examples: [
|
|
3394
3558
|
"nx new my-app",
|
|
3395
|
-
"nx new my-app --
|
|
3559
|
+
"nx new my-app --view inertia --frontend vue"
|
|
3396
3560
|
],
|
|
3397
3561
|
flags: [
|
|
3398
|
-
{
|
|
3399
|
-
name: "style",
|
|
3400
|
-
description: "Routing style (nest|adonis|functional|mixed)"
|
|
3401
|
-
},
|
|
3562
|
+
{ name: "style", description: "Routing style (nest|adonis|functional)" },
|
|
3402
3563
|
{ name: "view", description: "View engine (rendu|edge|eta|inertia|none)" },
|
|
3403
3564
|
{ name: "orm", description: "ORM driver (drizzle|prisma|kysely|none)" },
|
|
3404
|
-
{
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
},
|
|
3408
|
-
{
|
|
3409
|
-
name: "frontend",
|
|
3410
|
-
description: "Inertia frontend (react|vue|svelte|solid)"
|
|
3411
|
-
},
|
|
3412
|
-
{ name: "no-ssr", description: "Disable Inertia SSR" },
|
|
3413
|
-
{ name: "no-interaction", description: "Disable interactive prompts" }
|
|
3565
|
+
{ name: "db", description: "Database driver" },
|
|
3566
|
+
{ name: "frontend", description: "Inertia frontend (react|vue|svelte|solid)" },
|
|
3567
|
+
{ name: "no-ssr", description: "Disable SSR" }
|
|
3414
3568
|
],
|
|
3415
3569
|
async run(ctx) {
|
|
3416
3570
|
const name = ctx.positional[0];
|
|
3417
3571
|
if (!name) {
|
|
3418
|
-
logger.error("Usage: nx new <
|
|
3572
|
+
logger.error("Usage: nx new <name>");
|
|
3419
3573
|
return 1;
|
|
3420
3574
|
}
|
|
3421
|
-
const interactive =
|
|
3422
|
-
const target =
|
|
3575
|
+
const interactive = flagBool(ctx.flags, "interaction", true);
|
|
3576
|
+
const target = resolve24(ctx.cwd, name);
|
|
3423
3577
|
if (existsSync7(target)) {
|
|
3424
|
-
logger.error(`Directory already exists
|
|
3578
|
+
logger.error(`Directory "${name}" already exists.`);
|
|
3425
3579
|
return 1;
|
|
3426
3580
|
}
|
|
3427
|
-
const routing = ctx.flags
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
const
|
|
3432
|
-
interactive,
|
|
3433
|
-
default: "rendu"
|
|
3434
|
-
});
|
|
3435
|
-
const orm = ctx.flags["orm"] ?? await select("ORM driver", ["drizzle", "prisma", "kysely", "none"], {
|
|
3436
|
-
interactive,
|
|
3437
|
-
default: "drizzle"
|
|
3438
|
-
});
|
|
3439
|
-
const db = ctx.flags["db"] ?? await select("Database driver", ["bun-sqlite", "node-sqlite", "libsql", "postgres", "mysql", "none"], {
|
|
3440
|
-
interactive,
|
|
3441
|
-
default: "bun-sqlite"
|
|
3442
|
-
});
|
|
3443
|
-
const frontend = ctx.flags["frontend"] ?? await select("Inertia frontend", ["react", "vue", "svelte", "solid"], {
|
|
3444
|
-
interactive,
|
|
3445
|
-
default: "react"
|
|
3446
|
-
});
|
|
3581
|
+
const routing = await resolveOpt2(ctx.flags, "style", VALID_OPTIONS2.style, "nest", interactive);
|
|
3582
|
+
const view = await resolveOpt2(ctx.flags, "view", VALID_OPTIONS2.view, "rendu", interactive);
|
|
3583
|
+
const orm = await resolveOpt2(ctx.flags, "orm", VALID_OPTIONS2.orm, "drizzle", interactive);
|
|
3584
|
+
const db = await resolveOpt2(ctx.flags, "db", VALID_OPTIONS2.db, "bun-sqlite", interactive);
|
|
3585
|
+
const frontend = await resolveOpt2(ctx.flags, "frontend", VALID_OPTIONS2.frontend, "react", interactive);
|
|
3447
3586
|
const ssr = !flagBool(ctx.flags, "no-ssr", false);
|
|
3448
|
-
mkdirSync5(
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
mkdirSync5(resolve23(target, "public"), { recursive: true });
|
|
3453
|
-
writeFileSync3(resolve23(target, "public/.gitkeep"), "");
|
|
3454
|
-
if (view !== "none") {
|
|
3455
|
-
writeFileSync3(resolve23(target, "resources/views/welcome.html"), `<h1>Welcome to ${name}</h1>
|
|
3456
|
-
<p>This is a sample Rendu template.</p>
|
|
3457
|
-
<p>Founded <?= year ?>.</p>
|
|
3458
|
-
`);
|
|
3459
|
-
}
|
|
3460
|
-
writeFileSync3(resolve23(target, ".env"), generateEnvFile());
|
|
3461
|
-
writeFileSync3(resolve23(target, ".env.local"), generateEnvLocalFile());
|
|
3462
|
-
writeFileSync3(resolve23(target, ".gitignore"), generateGitIgnore());
|
|
3463
|
-
const code = render(templates.project["nx.config.ts"], {
|
|
3464
|
-
routing,
|
|
3465
|
-
view,
|
|
3466
|
-
viewPaths: view === "none" ? "" : "resources/views",
|
|
3467
|
-
orm,
|
|
3468
|
-
dbDriver: db,
|
|
3469
|
-
dbUrl: db === "bun-sqlite" || db === "node-sqlite" ? "app.db" : "",
|
|
3470
|
-
inertiaFrontend: frontend,
|
|
3471
|
-
inertiaSSR: ssr,
|
|
3472
|
-
inertiaVersion: "1.0.0"
|
|
3473
|
-
});
|
|
3474
|
-
writeFileSync3(resolve23(target, "nx.config.ts"), code);
|
|
3475
|
-
if (orm === "drizzle") {
|
|
3476
|
-
const dialect = db === "bun-sqlite" || db === "node-sqlite" || db === "libsql" ? "sqlite" : db === "postgres" ? "postgresql" : "sqlite";
|
|
3477
|
-
const drizzleConfig = render(templates.project["drizzle.config.ts"], {
|
|
3478
|
-
dialect,
|
|
3479
|
-
dbUrl: db === "bun-sqlite" || db === "node-sqlite" ? "app.db" : ""
|
|
3480
|
-
});
|
|
3481
|
-
writeFileSync3(resolve23(target, "drizzle.config.ts"), drizzleConfig);
|
|
3482
|
-
}
|
|
3483
|
-
const deps = {
|
|
3484
|
-
"@nexusts/core": "*",
|
|
3485
|
-
"reflect-metadata": "^0.2.2",
|
|
3486
|
-
hono: "^4.6.0",
|
|
3487
|
-
zod: "^3.23.8"
|
|
3488
|
-
};
|
|
3489
|
-
if (orm === "drizzle") {
|
|
3490
|
-
deps["@nexusts/drizzle"] = "*";
|
|
3491
|
-
deps["drizzle-orm"] = "^0.45.0";
|
|
3492
|
-
if (db === "postgres")
|
|
3493
|
-
deps["pg"] = "^8.13.0";
|
|
3494
|
-
if (db === "mysql")
|
|
3495
|
-
deps["mysql2"] = "^3.11.0";
|
|
3496
|
-
if (db === "sqlite" || db === "node-sqlite" || db === "bun-sqlite")
|
|
3497
|
-
deps["better-sqlite3"] = "^12.0.0";
|
|
3498
|
-
}
|
|
3499
|
-
if (view !== "none") {
|
|
3500
|
-
deps["@nexusts/static"] = "*";
|
|
3501
|
-
}
|
|
3502
|
-
const pkgJson = {
|
|
3503
|
-
name,
|
|
3504
|
-
version: "0.1.0",
|
|
3505
|
-
type: "module",
|
|
3506
|
-
scripts: {
|
|
3507
|
-
dev: "bun --hot app/main.ts",
|
|
3508
|
-
build: "bun run build.ts",
|
|
3509
|
-
start: "bun app/main.ts",
|
|
3510
|
-
test: "vitest",
|
|
3511
|
-
nx: "nx"
|
|
3512
|
-
},
|
|
3513
|
-
dependencies: deps
|
|
3514
|
-
};
|
|
3515
|
-
if (orm === "drizzle") {
|
|
3516
|
-
pkgJson.devDependencies = { "drizzle-kit": "^0.31.0" };
|
|
3517
|
-
}
|
|
3518
|
-
writeFileSync3(resolve23(target, "package.json"), JSON.stringify(pkgJson, null, 2));
|
|
3519
|
-
writeFileSync3(resolve23(target, "tsconfig.json"), `{
|
|
3587
|
+
mkdirSync5(target, { recursive: true });
|
|
3588
|
+
const dbUrl = db === "bun-sqlite" || db === "node-sqlite" ? "app.db" : "";
|
|
3589
|
+
ensureDirectories(target, view);
|
|
3590
|
+
writeFileSync4(resolve24(target, "tsconfig.json"), `{
|
|
3520
3591
|
"compilerOptions": {
|
|
3521
3592
|
"target": "ES2022",
|
|
3522
3593
|
"module": "ESNext",
|
|
@@ -3526,81 +3597,22 @@ var newCommand = {
|
|
|
3526
3597
|
"strict": true,
|
|
3527
3598
|
"esModuleInterop": true,
|
|
3528
3599
|
"skipLibCheck": true,
|
|
3529
|
-
"types": ["bun
|
|
3600
|
+
"types": ["@types/bun"]
|
|
3530
3601
|
},
|
|
3531
3602
|
"include": ["app/**/*.ts", "nx.config.ts"]
|
|
3532
3603
|
}
|
|
3533
3604
|
`);
|
|
3534
|
-
const
|
|
3535
|
-
const
|
|
3536
|
-
|
|
3537
|
-
` : "";
|
|
3538
|
-
const staticOption = hasView ? `
|
|
3539
|
-
middleware: [staticMiddleware],` : "";
|
|
3540
|
-
writeFileSync3(resolve23(target, "app/main.ts"), `import 'reflect-metadata';
|
|
3541
|
-
import { Application } from '@nexusts/core';
|
|
3542
|
-
${staticImport}import { AppModule } from './app.module.js';
|
|
3543
|
-
|
|
3544
|
-
const app = new Application(AppModule, {
|
|
3545
|
-
logging: true,
|
|
3546
|
-
port: Number(process.env['PORT'] ?? 3000),${staticOption}
|
|
3547
|
-
});
|
|
3548
|
-
|
|
3549
|
-
await app.listen();
|
|
3550
|
-
console.log('[nexus] Listening on http://localhost:' + (process.env['PORT'] ?? 3000));
|
|
3551
|
-
`);
|
|
3552
|
-
const ormImport = orm === "drizzle" ? `import { DrizzleModule } from '@nexusts/drizzle';
|
|
3553
|
-
` : "";
|
|
3554
|
-
const forRootDialect = db === "bun-sqlite" ? "bun-sqlite" : "sqlite";
|
|
3555
|
-
const ormBlock = orm === "drizzle" ? ` DrizzleModule.forRoot({
|
|
3556
|
-
dialect: '${forRootDialect}',
|
|
3557
|
-
connection: { filename: 'app.db' },
|
|
3558
|
-
logging: true,
|
|
3559
|
-
})` : "";
|
|
3560
|
-
writeFileSync3(resolve23(target, "app/app.module.ts"), `${ormImport}import { Module } from '@nexusts/core';
|
|
3561
|
-
import { HomeController } from './controllers/home.controller.js';
|
|
3562
|
-
|
|
3563
|
-
@Module({
|
|
3564
|
-
imports: [${orm === "drizzle" ? `
|
|
3565
|
-
${ormBlock},
|
|
3566
|
-
` : ""} ],
|
|
3567
|
-
controllers: [HomeController],
|
|
3568
|
-
})
|
|
3569
|
-
export class AppModule {}
|
|
3570
|
-
`);
|
|
3571
|
-
mkdirSync5(resolve23(target, "app/controllers"), { recursive: true });
|
|
3572
|
-
const homeViewReturn = view !== "none" ? `{
|
|
3573
|
-
view: 'welcome.html',
|
|
3574
|
-
data: { year: new Date().getFullYear() },
|
|
3575
|
-
}` : `{ status: 200, body: { message: 'Hello from NexusTS!' } }`;
|
|
3576
|
-
writeFileSync3(resolve23(target, "app/controllers/home.controller.ts"), `import { Controller, Get } from '@nexusts/core';
|
|
3577
|
-
|
|
3578
|
-
@Controller('/')
|
|
3579
|
-
export class HomeController {
|
|
3580
|
-
@Get('/')
|
|
3581
|
-
index() {
|
|
3582
|
-
return ${homeViewReturn};
|
|
3583
|
-
}
|
|
3584
|
-
}
|
|
3585
|
-
`);
|
|
3586
|
-
writeFileSync3(resolve23(target, "README.md"), `# ${name}
|
|
3587
|
-
|
|
3588
|
-
A new NexusTS project.
|
|
3589
|
-
|
|
3590
|
-
## Run
|
|
3591
|
-
|
|
3592
|
-
\`\`\`bash
|
|
3593
|
-
bun install
|
|
3594
|
-
bun run dev
|
|
3595
|
-
\`\`\`
|
|
3596
|
-
|
|
3597
|
-
## Scaffolding
|
|
3598
|
-
|
|
3599
|
-
\`\`\`bash
|
|
3600
|
-
bunx nx make:crud Post
|
|
3601
|
-
\`\`\`
|
|
3605
|
+
const { deps, devDeps } = computeDeps(view, orm, db, frontend);
|
|
3606
|
+
const pkgJson = buildPackageJson(name, deps, devDeps, view, frontend);
|
|
3607
|
+
writeFileSync4(resolve24(target, "package.json"), `${JSON.stringify(pkgJson, null, 2)}
|
|
3602
3608
|
`);
|
|
3603
|
-
|
|
3609
|
+
const opts = { target, name, routing, view, orm, db, frontend, ssr, dbUrl };
|
|
3610
|
+
const files = generateProjectFiles(target, opts);
|
|
3611
|
+
logger.success(`created ${name}`);
|
|
3612
|
+
for (const f of files)
|
|
3613
|
+
logger.info(` + ${f}`);
|
|
3614
|
+
logger.info(` + tsconfig.json`);
|
|
3615
|
+
logger.info(` + package.json`);
|
|
3604
3616
|
logger.blank();
|
|
3605
3617
|
logger.heading("Next steps");
|
|
3606
3618
|
logger.info(` cd ${name}`);
|
|
@@ -3610,62 +3622,11 @@ bunx nx make:crud Post
|
|
|
3610
3622
|
return 0;
|
|
3611
3623
|
}
|
|
3612
3624
|
};
|
|
3613
|
-
function generateEnvFile() {
|
|
3614
|
-
return `# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3615
|
-
# NexusTS \u2014 Environment Variables (committed to git)
|
|
3616
|
-
#
|
|
3617
|
-
# Shared defaults for all environments. Override locally via
|
|
3618
|
-
# .env.local (gitignored) or by environment via .env.{NODE_ENV}
|
|
3619
|
-
# (e.g. .env.production, .env.development).
|
|
3620
|
-
#
|
|
3621
|
-
# Uncomment the database config for your driver:
|
|
3622
|
-
# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3623
|
-
|
|
3624
|
-
# \u2500\u2500 App \u2500\u2500
|
|
3625
|
-
NODE_ENV=development
|
|
3626
|
-
PORT=3000
|
|
3627
|
-
|
|
3628
|
-
# \u2500\u2500 Session secret (REQUIRED) \u2500\u2500
|
|
3629
|
-
# Generate with: openssl rand -base64 32
|
|
3630
|
-
SESSION_SECRET=change-me-in-production
|
|
3631
|
-
|
|
3632
|
-
# \u2500\u2500 Database: SQLite (default, zero config) \u2500\u2500
|
|
3633
|
-
DATABASE_URL=app.db
|
|
3634
|
-
|
|
3635
|
-
# \u2500\u2500 Database: PostgreSQL \u2500\u2500
|
|
3636
|
-
# DATABASE_URL=postgres://user:password@localhost:5432/myapp
|
|
3637
|
-
|
|
3638
|
-
# \u2500\u2500 Database: MySQL \u2500\u2500
|
|
3639
|
-
# DATABASE_URL=mysql://user:password@localhost:3306/myapp
|
|
3640
|
-
`;
|
|
3641
|
-
}
|
|
3642
|
-
function generateEnvLocalFile() {
|
|
3643
|
-
return `# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3644
|
-
# NexusTS \u2014 Local Overrides (DO NOT COMMIT to git)
|
|
3645
|
-
#
|
|
3646
|
-
# This file is gitignored. Use it for secrets and local
|
|
3647
|
-
# configuration that should never be checked in.
|
|
3648
|
-
# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
3649
|
-
|
|
3650
|
-
# Override any value from .env here:
|
|
3651
|
-
# DATABASE_URL=postgres://user:password@localhost:5432/myapp
|
|
3652
|
-
# SESSION_SECRET=my-local-secret
|
|
3653
|
-
`;
|
|
3654
|
-
}
|
|
3655
|
-
function generateGitIgnore() {
|
|
3656
|
-
return `# NexusTS
|
|
3657
|
-
node_modules/
|
|
3658
|
-
app.db
|
|
3659
|
-
*.db
|
|
3660
|
-
.env.local
|
|
3661
|
-
dist/
|
|
3662
|
-
`;
|
|
3663
|
-
}
|
|
3664
3625
|
var new_default = newCommand;
|
|
3665
3626
|
|
|
3666
3627
|
// packages/cli/src/commands/config.ts
|
|
3667
|
-
import { existsSync as existsSync8, readFileSync as readFileSync5, writeFileSync as
|
|
3668
|
-
import { resolve as
|
|
3628
|
+
import { existsSync as existsSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
3629
|
+
import { resolve as resolve25 } from "path";
|
|
3669
3630
|
var DEFAULT_VALUES = {
|
|
3670
3631
|
routing: "nest",
|
|
3671
3632
|
view: "rendu",
|
|
@@ -3780,12 +3741,12 @@ var configCommand = {
|
|
|
3780
3741
|
async run(ctx) {
|
|
3781
3742
|
const interactive = !flagBool(ctx.flags, "no-interaction", false);
|
|
3782
3743
|
const force = flagBool(ctx.flags, "force", false);
|
|
3783
|
-
const target =
|
|
3744
|
+
const target = resolve25(ctx.cwd, ctx.flags["target"] ?? ".");
|
|
3784
3745
|
if (!existsSync8(target)) {
|
|
3785
3746
|
logger.error(`Target directory does not exist: ${target}`);
|
|
3786
3747
|
return 1;
|
|
3787
3748
|
}
|
|
3788
|
-
const nxConfigPath =
|
|
3749
|
+
const nxConfigPath = resolve25(target, "nx.config.ts");
|
|
3789
3750
|
const values = parseExistingConfig(nxConfigPath);
|
|
3790
3751
|
const flag = (k) => ctx.flags[k];
|
|
3791
3752
|
const flagBoolStrict = (k, def) => flagBool(ctx.flags, k, def);
|
|
@@ -3840,7 +3801,7 @@ var configCommand = {
|
|
|
3840
3801
|
writeNxConfig(target, values);
|
|
3841
3802
|
logger.info(` + nx.config.ts`);
|
|
3842
3803
|
}
|
|
3843
|
-
const drizzleConfigPath =
|
|
3804
|
+
const drizzleConfigPath = resolve25(target, "drizzle.config.ts");
|
|
3844
3805
|
if (values.orm === "drizzle") {
|
|
3845
3806
|
const dialect = driverToDialect(values.dbDriver);
|
|
3846
3807
|
const dbUrl = values.dbUrl;
|
|
@@ -3868,11 +3829,11 @@ var configCommand = {
|
|
|
3868
3829
|
};
|
|
3869
3830
|
function writeNxConfig(target, values) {
|
|
3870
3831
|
const code = render(templates.project["nx.config.ts"], values);
|
|
3871
|
-
|
|
3832
|
+
writeFileSync5(resolve25(target, "nx.config.ts"), code);
|
|
3872
3833
|
}
|
|
3873
3834
|
function writeDrizzleConfig(target, values) {
|
|
3874
3835
|
const code = render(templates.project["drizzle.config.ts"], values);
|
|
3875
|
-
|
|
3836
|
+
writeFileSync5(resolve25(target, "drizzle.config.ts"), code);
|
|
3876
3837
|
}
|
|
3877
3838
|
var config_default = configCommand;
|
|
3878
3839
|
|
|
@@ -3881,9 +3842,9 @@ import {
|
|
|
3881
3842
|
existsSync as existsSync9,
|
|
3882
3843
|
mkdirSync as mkdirSync6,
|
|
3883
3844
|
readFileSync as readFileSync6,
|
|
3884
|
-
writeFileSync as
|
|
3845
|
+
writeFileSync as writeFileSync6
|
|
3885
3846
|
} from "fs";
|
|
3886
|
-
import { dirname as dirname5, resolve as
|
|
3847
|
+
import { dirname as dirname5, resolve as resolve26 } from "path";
|
|
3887
3848
|
import * as readline from "readline";
|
|
3888
3849
|
import * as vm from "vm";
|
|
3889
3850
|
var BANNER = (() => {
|
|
@@ -3965,10 +3926,10 @@ var replCommand = {
|
|
|
3965
3926
|
async run(ctx) {
|
|
3966
3927
|
const mod = ctx.flags["module"];
|
|
3967
3928
|
const noBoot = Boolean(ctx.flags["no-boot"]);
|
|
3968
|
-
const histPath =
|
|
3929
|
+
const histPath = resolve26(ctx.cwd, ctx.flags["history"] ?? ".nx-repl-history");
|
|
3969
3930
|
const env = { console };
|
|
3970
3931
|
if (!noBoot) {
|
|
3971
|
-
const modPath =
|
|
3932
|
+
const modPath = resolve26(ctx.cwd, mod ?? "app/app.module.ts");
|
|
3972
3933
|
if (!existsSync9(modPath)) {
|
|
3973
3934
|
logger.error(`module not found: ${modPath}`);
|
|
3974
3935
|
logger.info("pass --module <path> or --no-boot to skip booting");
|
|
@@ -4286,7 +4247,7 @@ function saveHistoryFile(path, history) {
|
|
|
4286
4247
|
const dir = dirname5(path);
|
|
4287
4248
|
if (!existsSync9(dir))
|
|
4288
4249
|
mkdirSync6(dir, { recursive: true });
|
|
4289
|
-
|
|
4250
|
+
writeFileSync6(path, history.slice(-1000).join(`
|
|
4290
4251
|
`));
|
|
4291
4252
|
} catch {}
|
|
4292
4253
|
}
|
|
@@ -4294,7 +4255,8 @@ var repl_default = replCommand;
|
|
|
4294
4255
|
|
|
4295
4256
|
// packages/cli/src/commands/route-list.ts
|
|
4296
4257
|
import { readdirSync, statSync as statSync2 } from "fs";
|
|
4297
|
-
import { resolve as
|
|
4258
|
+
import { resolve as resolve27 } from "path";
|
|
4259
|
+
import { safeGetMeta } from "@nexusts/core/di/safe-reflect";
|
|
4298
4260
|
var routeListCommand = {
|
|
4299
4261
|
name: "route:list",
|
|
4300
4262
|
aliases: ["routes", "route-list"],
|
|
@@ -4304,7 +4266,7 @@ var routeListCommand = {
|
|
|
4304
4266
|
{ name: "format", description: "Output format: table (default) | json" }
|
|
4305
4267
|
],
|
|
4306
4268
|
async run(ctx) {
|
|
4307
|
-
const controllersDir =
|
|
4269
|
+
const controllersDir = resolve27(ctx.cwd, ctx.config.paths.controllers);
|
|
4308
4270
|
try {
|
|
4309
4271
|
statSync2(controllersDir);
|
|
4310
4272
|
} catch {
|
|
@@ -4318,16 +4280,16 @@ var routeListCommand = {
|
|
|
4318
4280
|
}
|
|
4319
4281
|
const routes = [];
|
|
4320
4282
|
for (const file of files) {
|
|
4321
|
-
const fullPath =
|
|
4283
|
+
const fullPath = resolve27(controllersDir, file);
|
|
4322
4284
|
try {
|
|
4323
4285
|
const mod = await import(`${fullPath}?t=${Date.now()}`);
|
|
4324
4286
|
for (const exportName of Object.keys(mod)) {
|
|
4325
4287
|
const cls = mod[exportName];
|
|
4326
4288
|
if (typeof cls !== "function")
|
|
4327
4289
|
continue;
|
|
4328
|
-
const controllerMeta =
|
|
4290
|
+
const controllerMeta = safeGetMeta("nexus:controller", cls);
|
|
4329
4291
|
const prefix = controllerMeta?.prefix ?? "";
|
|
4330
|
-
const routeList =
|
|
4292
|
+
const routeList = safeGetMeta("nexus:routes", cls) ?? [];
|
|
4331
4293
|
for (const r of routeList) {
|
|
4332
4294
|
routes.push({
|
|
4333
4295
|
method: String(r.method).toUpperCase(),
|
|
@@ -4520,5 +4482,5 @@ main().then((code) => process.exit(code)).catch((err) => {
|
|
|
4520
4482
|
process.exit(1);
|
|
4521
4483
|
});
|
|
4522
4484
|
|
|
4523
|
-
//# debugId=
|
|
4485
|
+
//# debugId=B2F4C39893BC135664756E2164756E21
|
|
4524
4486
|
//# sourceMappingURL=index.js.map
|