@nexusts/cli 0.9.4 → 0.9.6
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/config.d.ts +1 -1
- package/dist/commands/db-generate.d.ts +8 -6
- package/dist/commands/db-migrate.d.ts +6 -15
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/make-crud.d.ts +1 -1
- package/dist/commands/make-model.d.ts +1 -1
- package/dist/commands/make-repository.d.ts +6 -0
- package/dist/core/config.d.ts +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/scaffold.d.ts +1 -1
- package/dist/index.js +466 -259
- package/dist/index.js.map +32 -31
- package/dist/templates/index.d.ts +5 -2
- package/dist/templates/migration/kysely.d.ts +14 -0
- package/dist/templates/model/kysely.d.ts +5 -1
- package/dist/templates/project/nx.config.d.ts +1 -1
- package/dist/templates/repository/kysely-repository.d.ts +15 -0
- package/dist/templates/service/service.d.ts +2 -0
- package/package.json +2 -2
- package/dist/templates/model/prisma.d.ts +0 -11
package/dist/index.js
CHANGED
|
@@ -168,14 +168,14 @@ async function loadConfig(cwd = process.cwd()) {
|
|
|
168
168
|
const mod = await import(path);
|
|
169
169
|
config = mod.default ?? mod;
|
|
170
170
|
} catch (importErr) {
|
|
171
|
-
console.warn(`[nx] Could not dynamically import ${candidate}: ${importErr.message
|
|
171
|
+
console.warn(`[nx] Could not dynamically import ${candidate}: ${importErr instanceof Error ? importErr.message : String(importErr)}. Falling back to defaults.`);
|
|
172
172
|
config = {};
|
|
173
173
|
}
|
|
174
174
|
}
|
|
175
175
|
configSource = candidate;
|
|
176
176
|
break;
|
|
177
177
|
} catch (err) {
|
|
178
|
-
throw new Error(`Failed to load ${candidate}: ${err.message
|
|
178
|
+
throw new Error(`Failed to load ${candidate}: ${err instanceof Error ? err.message : String(err)}`);
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
const merged = mergeWithEnv(DEFAULT_CONFIG, config);
|
|
@@ -186,7 +186,7 @@ async function loadConfig(cwd = process.cwd()) {
|
|
|
186
186
|
"mixed"
|
|
187
187
|
]);
|
|
188
188
|
assertEnum("view", merged.view, ["rendu", "edge", "inertia", "none"]);
|
|
189
|
-
assertEnum("orm", merged.orm, ["drizzle", "
|
|
189
|
+
assertEnum("orm", merged.orm, ["drizzle", "kysely", "none"]);
|
|
190
190
|
assertEnum("database.driver", merged.database.driver, [
|
|
191
191
|
"bun-sqlite",
|
|
192
192
|
"node-sqlite",
|
|
@@ -201,7 +201,7 @@ async function loadConfig(cwd = process.cwd()) {
|
|
|
201
201
|
"svelte",
|
|
202
202
|
"solid"
|
|
203
203
|
]);
|
|
204
|
-
if (process.env
|
|
204
|
+
if (process.env.NX_DEBUG === "1") {
|
|
205
205
|
console.log(`[nx] config source: ${configSource}`);
|
|
206
206
|
}
|
|
207
207
|
return merged;
|
|
@@ -215,22 +215,22 @@ function mergeWithEnv(base, override) {
|
|
|
215
215
|
inertia: { ...base.inertia, ...override.inertia ?? {} },
|
|
216
216
|
paths: { ...base.paths, ...override.paths ?? {} }
|
|
217
217
|
};
|
|
218
|
-
if (env
|
|
219
|
-
merged.routing = env
|
|
220
|
-
if (env
|
|
221
|
-
merged.view = env
|
|
222
|
-
if (env
|
|
223
|
-
merged.orm = env
|
|
224
|
-
if (env
|
|
225
|
-
merged.database.driver = env
|
|
226
|
-
if (env
|
|
227
|
-
merged.database.url = env
|
|
228
|
-
if (env
|
|
229
|
-
merged.inertia.frontend = env
|
|
230
|
-
if (env
|
|
231
|
-
merged.inertia.ssr = env
|
|
232
|
-
if (env
|
|
233
|
-
merged.inertia.version = env
|
|
218
|
+
if (env.NX_ROUTING)
|
|
219
|
+
merged.routing = env.NX_ROUTING;
|
|
220
|
+
if (env.NX_VIEW)
|
|
221
|
+
merged.view = env.NX_VIEW;
|
|
222
|
+
if (env.NX_ORM)
|
|
223
|
+
merged.orm = env.NX_ORM;
|
|
224
|
+
if (env.NX_DATABASE_DRIVER)
|
|
225
|
+
merged.database.driver = env.NX_DATABASE_DRIVER;
|
|
226
|
+
if (env.NX_DATABASE_URL)
|
|
227
|
+
merged.database.url = env.NX_DATABASE_URL;
|
|
228
|
+
if (env.NX_INERTIA_FRONTEND)
|
|
229
|
+
merged.inertia.frontend = env.NX_INERTIA_FRONTEND;
|
|
230
|
+
if (env.NX_INERTIA_SSR)
|
|
231
|
+
merged.inertia.ssr = env.NX_INERTIA_SSR !== "false" && env.NX_INERTIA_SSR !== "0";
|
|
232
|
+
if (env.NX_INERTIA_VERSION)
|
|
233
|
+
merged.inertia.version = env.NX_INERTIA_VERSION;
|
|
234
234
|
return merged;
|
|
235
235
|
}
|
|
236
236
|
function assertEnum(key, value, allowed) {
|
|
@@ -285,7 +285,7 @@ function pluralize(s) {
|
|
|
285
285
|
return `${s}s`;
|
|
286
286
|
}
|
|
287
287
|
// packages/cli/src/core/logger.ts
|
|
288
|
-
var USE_COLOR = process.env
|
|
288
|
+
var USE_COLOR = process.env.NO_COLOR === undefined && process.env.FORCE_COLOR !== "0" && process.stdout.isTTY === true;
|
|
289
289
|
var wrap = (open, close) => (s) => USE_COLOR ? `\x1B[${open}m${s}\x1B[${close}m` : s;
|
|
290
290
|
var c = {
|
|
291
291
|
reset: wrap(0, 0),
|
|
@@ -780,6 +780,30 @@ export const {{ snake }} = sqliteTable('{{ tableName }}', {
|
|
|
780
780
|
});
|
|
781
781
|
`.trimStart();
|
|
782
782
|
|
|
783
|
+
// packages/cli/src/templates/migration/kysely.ts
|
|
784
|
+
var kysely_default = `
|
|
785
|
+
import type { Kysely } from 'kysely';
|
|
786
|
+
|
|
787
|
+
/**
|
|
788
|
+
* Migration: {{ name }}
|
|
789
|
+
*
|
|
790
|
+
* Run with \`nx db:migrate\` or via Kysely's Migrator.
|
|
791
|
+
*/
|
|
792
|
+
export async function up(db: Kysely<any>): Promise<void> {
|
|
793
|
+
await db.schema
|
|
794
|
+
.createTable('{{ tableName }}')
|
|
795
|
+
.addColumn('id', 'integer', (col) => col.primaryKey().autoIncrement())
|
|
796
|
+
{{ columns }}
|
|
797
|
+
.addColumn('created_at', 'integer', (col) => col.notNull().defaultTo(0))
|
|
798
|
+
.addColumn('updated_at', 'integer', (col) => col.notNull().defaultTo(0))
|
|
799
|
+
.execute();
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
export async function down(db: Kysely<any>): Promise<void> {
|
|
803
|
+
await db.schema.dropTable('{{ tableName }}').execute();
|
|
804
|
+
}
|
|
805
|
+
`.trimStart();
|
|
806
|
+
|
|
783
807
|
// packages/cli/src/templates/migration/sql.ts
|
|
784
808
|
var sql_default = `
|
|
785
809
|
-- {{ timestamp }}_create_{{ snake }}.sql
|
|
@@ -812,93 +836,33 @@ export type New{{ name }} = typeof {{ snake }}.$inferInsert;
|
|
|
812
836
|
`.trimStart();
|
|
813
837
|
|
|
814
838
|
// packages/cli/src/templates/model/kysely.ts
|
|
815
|
-
var
|
|
839
|
+
var kysely_default2 = `
|
|
816
840
|
import type { Generated, Insertable, Selectable, Updateable } from 'kysely';
|
|
817
|
-
import { Kysely } from 'kysely';
|
|
818
841
|
import { Inject, Injectable } from '@nexusts/core';
|
|
842
|
+
import { KyselyService, KyselyRepository } from '@nexusts/kysely';
|
|
819
843
|
|
|
844
|
+
/**
|
|
845
|
+
* Table interface for {{ tableName }}.
|
|
846
|
+
*/
|
|
820
847
|
export interface {{ name }}Table {
|
|
821
848
|
id: Generated<number>;
|
|
822
849
|
{{ columns }}
|
|
823
|
-
created_at: Generated<
|
|
824
|
-
updated_at: Generated<
|
|
850
|
+
created_at: Generated<string>;
|
|
851
|
+
updated_at: Generated<string>;
|
|
825
852
|
}
|
|
826
853
|
|
|
854
|
+
/** Row types derived from the table interface. */
|
|
827
855
|
export type {{ name }} = Selectable<{{ name }}Table>;
|
|
828
856
|
export type New{{ name }} = Insertable<{{ name }}Table>;
|
|
829
857
|
export type {{ name }}Update = Updateable<{{ name }}Table>;
|
|
830
858
|
|
|
831
|
-
@Injectable()
|
|
832
|
-
export class {{ name }}Repository {
|
|
833
|
-
constructor(@Inject('DB') private readonly db: Kysely<any>) {}
|
|
834
|
-
|
|
835
|
-
findAll() {
|
|
836
|
-
return this.db.selectFrom('{{ tableName }}').selectAll().execute();
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
findOne(id: number) {
|
|
840
|
-
return this.db
|
|
841
|
-
.selectFrom('{{ tableName }}')
|
|
842
|
-
.selectAll()
|
|
843
|
-
.where('id', '=', id)
|
|
844
|
-
.executeTakeFirst();
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
create(data: New{{ name }}) {
|
|
848
|
-
return this.db.insertInto('{{ tableName }}').values(data).returningAll().executeTakeFirst();
|
|
849
|
-
}
|
|
850
|
-
|
|
851
|
-
update(id: number, data: {{ name }}Update) {
|
|
852
|
-
return this.db
|
|
853
|
-
.updateTable('{{ tableName }}')
|
|
854
|
-
.set(data)
|
|
855
|
-
.where('id', '=', id)
|
|
856
|
-
.returningAll()
|
|
857
|
-
.executeTakeFirst();
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
delete(id: number) {
|
|
861
|
-
return this.db.deleteFrom('{{ tableName }}').where('id', '=', id).execute();
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
`.trimStart();
|
|
865
|
-
|
|
866
|
-
// packages/cli/src/templates/model/prisma.ts
|
|
867
|
-
var prisma_default = `
|
|
868
859
|
/**
|
|
869
|
-
* {{
|
|
870
|
-
*
|
|
871
|
-
* Add this block to your schema.prisma file:
|
|
872
|
-
*
|
|
873
|
-
{{ prismaBlock }}
|
|
860
|
+
* Repository for {{ tableName }} \u2014 Lucid-style CRUD via KyselyRepository.
|
|
874
861
|
*/
|
|
875
|
-
|
|
876
|
-
import { PrismaClient } from '@prisma/client';
|
|
877
|
-
import { Inject, Injectable } from '@nexusts/core';
|
|
878
|
-
|
|
879
862
|
@Injectable()
|
|
880
|
-
export class {{ name }}Repository {
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
findAll() {
|
|
884
|
-
return this.prisma.{{ camel }}.findMany();
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
findOne(id: number) {
|
|
888
|
-
return this.prisma.{{ camel }}.findUnique({ where: { id } });
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
create(data: any) {
|
|
892
|
-
return this.prisma.{{ camel }}.create({ data });
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
update(id: number, data: any) {
|
|
896
|
-
return this.prisma.{{ camel }}.update({ where: { id }, data });
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
delete(id: number) {
|
|
900
|
-
return this.prisma.{{ camel }}.delete({ where: { id } });
|
|
901
|
-
}
|
|
863
|
+
export class {{ name }}Repository extends KyselyRepository<any, '{{ tableName }}'> {
|
|
864
|
+
@Inject(KyselyService.TOKEN) declare db: KyselyService<any>;
|
|
865
|
+
protected readonly tableName = '{{ tableName }}' as const;
|
|
902
866
|
}
|
|
903
867
|
`.trimStart();
|
|
904
868
|
|
|
@@ -947,7 +911,7 @@ export default {
|
|
|
947
911
|
*/
|
|
948
912
|
viewPaths: '{{ viewPaths }}',
|
|
949
913
|
|
|
950
|
-
/** ORM driver \u2014 \`drizzle\`, \`
|
|
914
|
+
/** ORM driver \u2014 \`drizzle\`, \`kysely\`, or \`none\`. */
|
|
951
915
|
orm: '{{ orm }}',
|
|
952
916
|
|
|
953
917
|
// ---------------------------------------------------------------------------
|
|
@@ -1017,12 +981,22 @@ export class {{ repository }} extends DrizzleRepository<typeof {{ snake }}, {{ n
|
|
|
1017
981
|
}
|
|
1018
982
|
`.trimStart();
|
|
1019
983
|
|
|
984
|
+
// packages/cli/src/templates/repository/kysely-repository.ts
|
|
985
|
+
var kysely_repository_default = `
|
|
986
|
+
import { Injectable, Inject } from '@nexusts/core';
|
|
987
|
+
import { KyselyService, KyselyRepository } from '@nexusts/kysely';
|
|
988
|
+
|
|
989
|
+
@Injectable()
|
|
990
|
+
export class {{ repository }} extends KyselyRepository<any, '{{ tableName }}'> {
|
|
991
|
+
@Inject(KyselyService.TOKEN) declare db: KyselyService<any>;
|
|
992
|
+
protected readonly tableName = '{{ tableName }}' as const;
|
|
993
|
+
}
|
|
994
|
+
`.trimStart();
|
|
995
|
+
|
|
1020
996
|
// packages/cli/src/templates/service/service.ts
|
|
1021
997
|
var service_default = `
|
|
1022
998
|
import { Injectable, Inject } from '@nexusts/core';
|
|
1023
|
-
{{#hasRepo}}import {
|
|
1024
|
-
import { {{ repository }} } from '../repositories/{{ kebab }}.repository.js';
|
|
1025
|
-
import { {{ snake }} } from '../models/{{ kebab }}.model.js';{{/hasRepo}}
|
|
999
|
+
{{#hasRepo}}import { {{ repository }} } from '../repositories/{{ kebab }}.repository.js';{{/hasRepo}}
|
|
1026
1000
|
|
|
1027
1001
|
@Injectable()
|
|
1028
1002
|
export class {{ name }}Service {
|
|
@@ -1034,7 +1008,7 @@ export class {{ name }}Service {
|
|
|
1034
1008
|
}
|
|
1035
1009
|
|
|
1036
1010
|
async findOne(id: number) {
|
|
1037
|
-
{{#hasRepo}}return this.{{ repositoryCamel }}.
|
|
1011
|
+
{{#hasRepo}}return this.{{ repositoryCamel }}.findById(id);{{/hasRepo}}
|
|
1038
1012
|
{{^hasRepo}}return { id }; // TODO: implement{{/hasRepo}}
|
|
1039
1013
|
}
|
|
1040
1014
|
|
|
@@ -1044,12 +1018,12 @@ export class {{ name }}Service {
|
|
|
1044
1018
|
}
|
|
1045
1019
|
|
|
1046
1020
|
async update(id: number, data: any) {
|
|
1047
|
-
{{#hasRepo}}return this.{{ repositoryCamel }}.
|
|
1021
|
+
{{#hasRepo}}return this.{{ repositoryCamel }}.updateById(id, data);{{/hasRepo}}
|
|
1048
1022
|
{{^hasRepo}}return { id, ...data }; // TODO: implement{{/hasRepo}}
|
|
1049
1023
|
}
|
|
1050
1024
|
|
|
1051
1025
|
async delete(id: number) {
|
|
1052
|
-
{{#hasRepo}}return this.{{ repositoryCamel }}.
|
|
1026
|
+
{{#hasRepo}}return this.{{ repositoryCamel }}.deleteById(id);{{/hasRepo}}
|
|
1053
1027
|
{{^hasRepo}}return { removed: id }; // TODO: implement{{/hasRepo}}
|
|
1054
1028
|
}
|
|
1055
1029
|
}
|
|
@@ -1080,17 +1054,20 @@ var templates = {
|
|
|
1080
1054
|
functional: functional_default
|
|
1081
1055
|
},
|
|
1082
1056
|
service: service_default,
|
|
1083
|
-
repository:
|
|
1057
|
+
repository: {
|
|
1058
|
+
drizzle: repository_default,
|
|
1059
|
+
kysely: kysely_repository_default
|
|
1060
|
+
},
|
|
1084
1061
|
module: module_default2,
|
|
1085
1062
|
validator: validator_default,
|
|
1086
1063
|
middleware: middleware_default,
|
|
1087
1064
|
model: {
|
|
1088
1065
|
drizzle: drizzle_default2,
|
|
1089
|
-
|
|
1090
|
-
kysely: kysely_default
|
|
1066
|
+
kysely: kysely_default2
|
|
1091
1067
|
},
|
|
1092
1068
|
migration: {
|
|
1093
1069
|
drizzle: drizzle_default,
|
|
1070
|
+
kysely: kysely_default,
|
|
1094
1071
|
sql: sql_default
|
|
1095
1072
|
},
|
|
1096
1073
|
crud: {
|
|
@@ -1131,13 +1108,17 @@ function computeDeps(view, orm, db, frontend) {
|
|
|
1131
1108
|
deps["@nexusts/drizzle"] = "*";
|
|
1132
1109
|
deps["drizzle-orm"] = "^0.45.0";
|
|
1133
1110
|
if (db === "postgres")
|
|
1134
|
-
deps
|
|
1111
|
+
deps.pg = "^8.13.0";
|
|
1135
1112
|
if (db === "mysql")
|
|
1136
|
-
deps
|
|
1113
|
+
deps.mysql2 = "^3.11.0";
|
|
1137
1114
|
if (db === "sqlite" || db === "node-sqlite" || db === "bun-sqlite")
|
|
1138
1115
|
deps["better-sqlite3"] = "^12.0.0";
|
|
1139
1116
|
devDeps["drizzle-kit"] = "^0.31.0";
|
|
1140
1117
|
}
|
|
1118
|
+
if (orm === "kysely") {
|
|
1119
|
+
deps["@nexusts/kysely"] = "*";
|
|
1120
|
+
deps.kysely = "^0.27.0";
|
|
1121
|
+
}
|
|
1141
1122
|
if (view !== "none") {
|
|
1142
1123
|
deps["@nexusts/static"] = "*";
|
|
1143
1124
|
}
|
|
@@ -1145,10 +1126,10 @@ function computeDeps(view, orm, db, frontend) {
|
|
|
1145
1126
|
if (view === "inertia") {
|
|
1146
1127
|
if (frontend === "vue") {
|
|
1147
1128
|
deps["@inertiajs/vue3"] = "^3.0.0";
|
|
1148
|
-
deps
|
|
1129
|
+
deps.vue = "^3.5.0";
|
|
1149
1130
|
} else {
|
|
1150
1131
|
deps["@inertiajs/react"] = "^3.0.0";
|
|
1151
|
-
deps
|
|
1132
|
+
deps.react = "^19.0.0";
|
|
1152
1133
|
deps["react-dom"] = "^19.0.0";
|
|
1153
1134
|
}
|
|
1154
1135
|
}
|
|
@@ -1165,7 +1146,7 @@ function buildPackageJson(name, deps, devDeps, view, frontend) {
|
|
|
1165
1146
|
if (view === "inertia") {
|
|
1166
1147
|
const ext = frontend === "vue" ? "ts" : "tsx";
|
|
1167
1148
|
scripts["build:frontend"] = `bun build ./resources/js/app.${ext} --outdir=./public --target=browser --format=esm --minify`;
|
|
1168
|
-
scripts
|
|
1149
|
+
scripts.dev = `bun run build:frontend && bun --hot app/main.ts`;
|
|
1169
1150
|
}
|
|
1170
1151
|
const pkg = {
|
|
1171
1152
|
name,
|
|
@@ -1205,7 +1186,7 @@ function generateDrizzleConfig(target, db, dbUrl) {
|
|
|
1205
1186
|
writeFileSync2(resolve4(target, "drizzle.config.ts"), code);
|
|
1206
1187
|
}
|
|
1207
1188
|
function generateEnvFile() {
|
|
1208
|
-
return [
|
|
1189
|
+
return `${[
|
|
1209
1190
|
"# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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
1191
|
"# NexusTS \u2014 Environment Variables (committed to git)",
|
|
1211
1192
|
"#",
|
|
@@ -1235,11 +1216,11 @@ function generateEnvFile() {
|
|
|
1235
1216
|
"# BETTER_AUTH_SECRET=",
|
|
1236
1217
|
"# BETTER_AUTH_URL=http://localhost:3000"
|
|
1237
1218
|
].join(`
|
|
1238
|
-
`)
|
|
1219
|
+
`)}
|
|
1239
1220
|
`;
|
|
1240
1221
|
}
|
|
1241
1222
|
function generateEnvLocalFile() {
|
|
1242
|
-
return [
|
|
1223
|
+
return `${[
|
|
1243
1224
|
"# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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
1225
|
"# NexusTS \u2014 Local Overrides (DO NOT COMMIT to git)",
|
|
1245
1226
|
"#",
|
|
@@ -1251,7 +1232,7 @@ function generateEnvLocalFile() {
|
|
|
1251
1232
|
"# DATABASE_URL=postgres://user:password@localhost:5432/myapp",
|
|
1252
1233
|
"# SESSION_SECRET=my-local-secret"
|
|
1253
1234
|
].join(`
|
|
1254
|
-
`)
|
|
1235
|
+
`)}
|
|
1255
1236
|
`;
|
|
1256
1237
|
}
|
|
1257
1238
|
function generateGitIgnore() {
|
|
@@ -1357,15 +1338,34 @@ console.log('[nexus] Listening on http://localhost:' + (process.env['PORT'] ?? 3
|
|
|
1357
1338
|
`);
|
|
1358
1339
|
}
|
|
1359
1340
|
{
|
|
1360
|
-
const
|
|
1361
|
-
const
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1341
|
+
const isDrizzle = opts.orm === "drizzle";
|
|
1342
|
+
const isKysely = opts.orm === "kysely";
|
|
1343
|
+
const hasOrm = isDrizzle || isKysely;
|
|
1344
|
+
let ormImport = "";
|
|
1345
|
+
let ormBlock = "";
|
|
1346
|
+
if (isDrizzle) {
|
|
1347
|
+
ormImport = `import { DrizzleModule } from '@nexusts/drizzle';
|
|
1348
|
+
`;
|
|
1349
|
+
const d = opts.db === "bun-sqlite" ? "bun-sqlite" : "sqlite";
|
|
1350
|
+
ormBlock = ` DrizzleModule.forRoot({
|
|
1351
|
+
dialect: '` + d + `',
|
|
1352
|
+
connection: { filename: '` + (opts.dbUrl || "app.db") + `' },
|
|
1353
|
+
logging: true,
|
|
1354
|
+
})`;
|
|
1355
|
+
} else if (isKysely) {
|
|
1356
|
+
ormImport = `import { KyselyModule, BunSqliteDialect } from '@nexusts/kysely';
|
|
1357
|
+
import { SqliteDialect } from 'kysely';
|
|
1358
|
+
import { Database } from 'bun:sqlite';
|
|
1359
|
+
`;
|
|
1360
|
+
ormBlock = ` KyselyModule.forRoot({
|
|
1361
|
+
config: {
|
|
1362
|
+
dialect: new SqliteDialect({
|
|
1363
|
+
database: BunSqliteDialect.wrap(new Database('` + (opts.dbUrl || "app.db") + `')),
|
|
1364
|
+
}),
|
|
1365
|
+
},
|
|
1367
1366
|
logging: true,
|
|
1368
|
-
})
|
|
1367
|
+
})`;
|
|
1368
|
+
}
|
|
1369
1369
|
const isInertia = opts.view === "inertia";
|
|
1370
1370
|
const inertiaImport = isInertia ? `import { Inertia } from '@nexusts/view';
|
|
1371
1371
|
` : "";
|
|
@@ -1383,9 +1383,8 @@ ${inertiaProvider} controllers: [HomeController],
|
|
|
1383
1383
|
export class AppModule {}
|
|
1384
1384
|
`);
|
|
1385
1385
|
}
|
|
1386
|
-
{
|
|
1387
|
-
|
|
1388
|
-
write("app/controllers/home.controller.ts", `import { Controller, Get, Inject } from '@nexusts/core';
|
|
1386
|
+
if (opts.view === "inertia") {
|
|
1387
|
+
write("app/controllers/home.controller.ts", `import { Controller, Get, Inject } from '@nexusts/core';
|
|
1389
1388
|
import { Inertia } from '@nexusts/view';
|
|
1390
1389
|
|
|
1391
1390
|
@Controller('/')
|
|
@@ -1398,8 +1397,8 @@ export class HomeController {
|
|
|
1398
1397
|
}
|
|
1399
1398
|
}
|
|
1400
1399
|
`);
|
|
1401
|
-
|
|
1402
|
-
|
|
1400
|
+
} else if (opts.view !== "none") {
|
|
1401
|
+
write("app/controllers/home.controller.ts", `import { Controller, Get } from '@nexusts/core';
|
|
1403
1402
|
|
|
1404
1403
|
@Controller('/')
|
|
1405
1404
|
export class HomeController {
|
|
@@ -1412,8 +1411,8 @@ export class HomeController {
|
|
|
1412
1411
|
}
|
|
1413
1412
|
}
|
|
1414
1413
|
`);
|
|
1415
|
-
|
|
1416
|
-
|
|
1414
|
+
} else {
|
|
1415
|
+
write("app/controllers/home.controller.ts", `import { Controller, Get } from '@nexusts/core';
|
|
1417
1416
|
|
|
1418
1417
|
@Controller('/')
|
|
1419
1418
|
export class HomeController {
|
|
@@ -1423,7 +1422,6 @@ export class HomeController {
|
|
|
1423
1422
|
}
|
|
1424
1423
|
}
|
|
1425
1424
|
`);
|
|
1426
|
-
}
|
|
1427
1425
|
}
|
|
1428
1426
|
if (opts.orm === "drizzle") {
|
|
1429
1427
|
generateDrizzleConfig(target, opts.db, opts.dbUrl);
|
|
@@ -1511,7 +1509,7 @@ import { resolve as resolve6 } from "path";
|
|
|
1511
1509
|
var VALID_OPTIONS = {
|
|
1512
1510
|
style: ["nest", "adonis", "functional"],
|
|
1513
1511
|
view: ["rendu", "edge", "eta", "inertia", "none"],
|
|
1514
|
-
orm: ["drizzle", "
|
|
1512
|
+
orm: ["drizzle", "kysely", "none"],
|
|
1515
1513
|
db: ["bun-sqlite", "node-sqlite", "libsql", "postgres", "mysql", "none"],
|
|
1516
1514
|
frontend: ["react", "vue", "svelte", "solid"]
|
|
1517
1515
|
};
|
|
@@ -1549,7 +1547,7 @@ var initCommand = {
|
|
|
1549
1547
|
{ name: "target", description: "Target directory (default: cwd)" },
|
|
1550
1548
|
{ name: "style", description: "Routing style (nest|adonis|functional)" },
|
|
1551
1549
|
{ name: "view", description: "View engine (rendu|edge|eta|inertia|none)" },
|
|
1552
|
-
{ name: "orm", description: "ORM driver (drizzle|
|
|
1550
|
+
{ name: "orm", description: "ORM driver (drizzle|kysely|none)" },
|
|
1553
1551
|
{ name: "db", description: "Database driver (bun-sqlite|node-sqlite|libsql|postgres|mysql|none)" },
|
|
1554
1552
|
{
|
|
1555
1553
|
name: "frontend",
|
|
@@ -1845,11 +1843,11 @@ var makeAuthCommand = {
|
|
|
1845
1843
|
async run(ctx) {
|
|
1846
1844
|
logger.heading("Scaffolding auth module");
|
|
1847
1845
|
const providers = flagList(ctx.flags, "provider");
|
|
1848
|
-
const jwtEnabled = ctx.flags
|
|
1849
|
-
const passkeyEnabled = ctx.flags
|
|
1846
|
+
const jwtEnabled = ctx.flags.jwt === true;
|
|
1847
|
+
const passkeyEnabled = ctx.flags.passkey === true;
|
|
1850
1848
|
const rpId = ctx.flags["rp-id"] ?? "localhost";
|
|
1851
1849
|
const rpName = ctx.flags["rp-name"] ?? "NexusTS App";
|
|
1852
|
-
const origin = ctx.flags
|
|
1850
|
+
const origin = ctx.flags.origin ?? "http://localhost:3000";
|
|
1853
1851
|
const entries = providers.map((p) => {
|
|
1854
1852
|
const known = KNOWN_PROVIDERS[p.toLowerCase()];
|
|
1855
1853
|
return {
|
|
@@ -1930,14 +1928,14 @@ var makeControllerCommand = {
|
|
|
1930
1928
|
return 1;
|
|
1931
1929
|
}
|
|
1932
1930
|
const variants = nameVariants(name);
|
|
1933
|
-
const style = ctx.flags
|
|
1931
|
+
const style = ctx.flags.style ?? ctx.config.routing;
|
|
1934
1932
|
if (!["nest", "adonis", "functional"].includes(style)) {
|
|
1935
1933
|
logger.error(`Unknown style: ${style}. Allowed: nest, adonis, functional.`);
|
|
1936
1934
|
return 1;
|
|
1937
1935
|
}
|
|
1938
1936
|
const skipService = ctx.flags["no-service"] === true;
|
|
1939
1937
|
const serviceName = `${variants.pascal}Service`;
|
|
1940
|
-
const serviceCamel = variants.camel
|
|
1938
|
+
const serviceCamel = `${variants.camel}Service`;
|
|
1941
1939
|
const tpl = templates.controller[style];
|
|
1942
1940
|
const code = render(tpl, {
|
|
1943
1941
|
name: variants.pascal,
|
|
@@ -2110,9 +2108,9 @@ var makeCrudCommand = {
|
|
|
2110
2108
|
return 1;
|
|
2111
2109
|
}
|
|
2112
2110
|
const variants = nameVariants(name);
|
|
2113
|
-
const style = ctx.flags
|
|
2114
|
-
const orm = ctx.flags
|
|
2115
|
-
const dialect = ctx.flags
|
|
2111
|
+
const style = ctx.flags.style ?? ctx.config.routing;
|
|
2112
|
+
const orm = ctx.flags.orm ?? ctx.config.orm;
|
|
2113
|
+
const dialect = ctx.flags.dialect ?? ctx.config.dialect ?? "bun-sqlite";
|
|
2116
2114
|
const noRepo = flagBool(ctx.flags, "no-repo", false) || orm === "none";
|
|
2117
2115
|
const noTest = flagBool(ctx.flags, "no-test", false);
|
|
2118
2116
|
const hasInertia = ctx.config.view === "inertia" && !flagBool(ctx.flags, "no-views", false);
|
|
@@ -2132,7 +2130,7 @@ var makeCrudCommand = {
|
|
|
2132
2130
|
snake: variants.snake,
|
|
2133
2131
|
tableName,
|
|
2134
2132
|
service,
|
|
2135
|
-
serviceCamel: variants.camel
|
|
2133
|
+
serviceCamel: `${variants.camel}Service`,
|
|
2136
2134
|
controller,
|
|
2137
2135
|
viewComponent,
|
|
2138
2136
|
viewShowComponent,
|
|
@@ -2154,7 +2152,7 @@ var makeCrudCommand = {
|
|
|
2154
2152
|
snake: variants.snake,
|
|
2155
2153
|
hasRepo: !noRepo,
|
|
2156
2154
|
repository,
|
|
2157
|
-
repositoryCamel: variants.camel
|
|
2155
|
+
repositoryCamel: `${variants.camel}Repository`
|
|
2158
2156
|
});
|
|
2159
2157
|
const out = resolve9(ctx.cwd, ctx.config.paths.services, `${variants.kebab}.service.ts`);
|
|
2160
2158
|
if (!writeFile(out, code, { skipIfExists: true })) {
|
|
@@ -2165,7 +2163,7 @@ var makeCrudCommand = {
|
|
|
2165
2163
|
}
|
|
2166
2164
|
}
|
|
2167
2165
|
if (!noRepo) {
|
|
2168
|
-
if (orm === "drizzle" || orm === "
|
|
2166
|
+
if (orm === "drizzle" || orm === "kysely") {
|
|
2169
2167
|
let code;
|
|
2170
2168
|
if (orm === "drizzle") {
|
|
2171
2169
|
const tpl = renderDrizzleDialect(dialect);
|
|
@@ -2175,8 +2173,7 @@ var makeCrudCommand = {
|
|
|
2175
2173
|
kebab: variants.kebab,
|
|
2176
2174
|
snake: variants.snake,
|
|
2177
2175
|
tableName,
|
|
2178
|
-
columns: renderDrizzleColumns(dialect)
|
|
2179
|
-
prismaBlock: ""
|
|
2176
|
+
columns: renderDrizzleColumns(dialect)
|
|
2180
2177
|
});
|
|
2181
2178
|
} else {
|
|
2182
2179
|
const tpl = templates.model[orm];
|
|
@@ -2186,8 +2183,7 @@ var makeCrudCommand = {
|
|
|
2186
2183
|
kebab: variants.kebab,
|
|
2187
2184
|
snake: variants.snake,
|
|
2188
2185
|
tableName,
|
|
2189
|
-
columns: renderDefaultColumns(orm)
|
|
2190
|
-
prismaBlock: ""
|
|
2186
|
+
columns: renderDefaultColumns(orm)
|
|
2191
2187
|
});
|
|
2192
2188
|
}
|
|
2193
2189
|
const out = resolve9(ctx.cwd, ctx.config.paths.models, `${variants.kebab}.model.ts`);
|
|
@@ -2198,7 +2194,8 @@ var makeCrudCommand = {
|
|
|
2198
2194
|
written.push(out);
|
|
2199
2195
|
}
|
|
2200
2196
|
}
|
|
2201
|
-
const
|
|
2197
|
+
const ormRepo = orm === "kysely" ? templates.repository.kysely : templates.repository.drizzle;
|
|
2198
|
+
const repoCode = render(ormRepo, {
|
|
2202
2199
|
name: variants.pascal,
|
|
2203
2200
|
camel: variants.camel,
|
|
2204
2201
|
kebab: variants.kebab,
|
|
@@ -2407,7 +2404,7 @@ var makeMigrationCommand = {
|
|
|
2407
2404
|
},
|
|
2408
2405
|
{
|
|
2409
2406
|
name: "orm",
|
|
2410
|
-
description: "Override ORM driver (drizzle|
|
|
2407
|
+
description: "Override ORM driver (drizzle|kysely|none)"
|
|
2411
2408
|
},
|
|
2412
2409
|
{
|
|
2413
2410
|
name: "dialect",
|
|
@@ -2420,19 +2417,30 @@ var makeMigrationCommand = {
|
|
|
2420
2417
|
logger.error("Usage: nx make:migration <Name> [--dialect ...]");
|
|
2421
2418
|
return 1;
|
|
2422
2419
|
}
|
|
2423
|
-
const orm = ctx.flags
|
|
2424
|
-
const dialect = ctx.flags
|
|
2420
|
+
const orm = ctx.flags.orm ?? ctx.config.orm;
|
|
2421
|
+
const dialect = ctx.flags.dialect ?? ctx.config.dialect ?? "bun-sqlite";
|
|
2425
2422
|
const isDrizzle = orm === "drizzle";
|
|
2426
|
-
const
|
|
2423
|
+
const isKysely = orm === "kysely";
|
|
2424
|
+
const useGenericSql = orm === "none";
|
|
2427
2425
|
const variants = nameVariants(name);
|
|
2428
2426
|
const tableName = inferTableName(name);
|
|
2429
|
-
const colsFlag = ctx.flags
|
|
2427
|
+
const colsFlag = ctx.flags.columns;
|
|
2430
2428
|
const cols = parseColumns(colsFlag ?? "title:text");
|
|
2431
2429
|
const drizzleColumns = renderDrizzleColumns2(cols, dialect);
|
|
2432
2430
|
const sqlColumns = renderSqlColumns(cols, dialect);
|
|
2433
2431
|
let code;
|
|
2434
2432
|
let extension;
|
|
2435
|
-
if (
|
|
2433
|
+
if (isKysely) {
|
|
2434
|
+
const tpl = templates.migration.kysely;
|
|
2435
|
+
code = render(tpl, {
|
|
2436
|
+
name: variants.pascal,
|
|
2437
|
+
snake: variants.snake,
|
|
2438
|
+
tableName,
|
|
2439
|
+
columns: renderKyselyColumns(cols),
|
|
2440
|
+
timestamp: formatTimestamp(new Date)
|
|
2441
|
+
});
|
|
2442
|
+
extension = "ts";
|
|
2443
|
+
} else if (isDrizzle) {
|
|
2436
2444
|
if (!isValidDialect(dialect)) {
|
|
2437
2445
|
logger.error(`Unsupported drizzle dialect: ${dialect}. Allowed: postgres, mysql, sqlite, bun-sqlite, d1.`);
|
|
2438
2446
|
return 1;
|
|
@@ -2457,17 +2465,17 @@ var makeMigrationCommand = {
|
|
|
2457
2465
|
});
|
|
2458
2466
|
extension = "sql";
|
|
2459
2467
|
} else {
|
|
2460
|
-
logger.error(`Unsupported ORM for migration: ${orm}. Allowed: drizzle,
|
|
2468
|
+
logger.error(`Unsupported ORM for migration: ${orm}. Allowed: drizzle, kysely, none.`);
|
|
2461
2469
|
return 1;
|
|
2462
2470
|
}
|
|
2463
2471
|
const filename = `${formatTimestamp(new Date)}_${variants.snake}.${extension}`;
|
|
2464
2472
|
const out = resolve12(ctx.cwd, ctx.config.paths.migrations, filename);
|
|
2465
2473
|
writeFile(out, code);
|
|
2466
2474
|
logger.success(`created ${out}`);
|
|
2467
|
-
if (isDrizzle) {
|
|
2468
|
-
logger.finger(`run \`nx migrate\` to apply pending migrations.`);
|
|
2475
|
+
if (isDrizzle || isKysely) {
|
|
2476
|
+
logger.finger(`run \`nx db:migrate\` to apply pending migrations.`);
|
|
2469
2477
|
} else {
|
|
2470
|
-
logger.finger(`run \`bun nx db:
|
|
2478
|
+
logger.finger(`run \`bun nx db:migrate\` or your migration tool.`);
|
|
2471
2479
|
}
|
|
2472
2480
|
return 0;
|
|
2473
2481
|
}
|
|
@@ -2478,11 +2486,11 @@ function isValidDialect(d) {
|
|
|
2478
2486
|
function inferTableName(input) {
|
|
2479
2487
|
const m = /^create_(\w+)_table$/.exec(input);
|
|
2480
2488
|
if (m)
|
|
2481
|
-
return m[1];
|
|
2489
|
+
return m[1] ?? "";
|
|
2482
2490
|
const m2 = /^(?:add|remove|drop|alter)_(\w+)_to_(\w+)$/.exec(input);
|
|
2483
2491
|
if (m2)
|
|
2484
|
-
return m2[2];
|
|
2485
|
-
return input.toLowerCase().replace(/s$/, "")
|
|
2492
|
+
return m2[2] ?? "";
|
|
2493
|
+
return `${input.toLowerCase().replace(/s$/, "")}s`;
|
|
2486
2494
|
}
|
|
2487
2495
|
function parseColumns(input) {
|
|
2488
2496
|
const list = Array.isArray(input) ? input : input.split(",");
|
|
@@ -2499,6 +2507,44 @@ function renderSqlColumns(cols, dialect) {
|
|
|
2499
2507
|
}).join(`
|
|
2500
2508
|
`);
|
|
2501
2509
|
}
|
|
2510
|
+
function renderKyselyColumns(cols) {
|
|
2511
|
+
return cols.map(([name, type]) => {
|
|
2512
|
+
const kyselyType = mapKyselyType(type);
|
|
2513
|
+
return ` .addColumn('${name}', '${kyselyType}', (col) => col.notNull())`;
|
|
2514
|
+
}).join(`
|
|
2515
|
+
`);
|
|
2516
|
+
}
|
|
2517
|
+
function mapKyselyType(type) {
|
|
2518
|
+
switch (type.toLowerCase()) {
|
|
2519
|
+
case "text":
|
|
2520
|
+
case "string":
|
|
2521
|
+
case "varchar":
|
|
2522
|
+
return "text";
|
|
2523
|
+
case "int":
|
|
2524
|
+
case "integer":
|
|
2525
|
+
return "integer";
|
|
2526
|
+
case "bigint":
|
|
2527
|
+
return "bigint";
|
|
2528
|
+
case "bool":
|
|
2529
|
+
case "boolean":
|
|
2530
|
+
return "boolean";
|
|
2531
|
+
case "float":
|
|
2532
|
+
case "number":
|
|
2533
|
+
case "real":
|
|
2534
|
+
case "double":
|
|
2535
|
+
return "real";
|
|
2536
|
+
case "datetime":
|
|
2537
|
+
case "timestamp":
|
|
2538
|
+
return "text";
|
|
2539
|
+
case "date":
|
|
2540
|
+
return "text";
|
|
2541
|
+
case "json":
|
|
2542
|
+
case "jsonb":
|
|
2543
|
+
return "text";
|
|
2544
|
+
default:
|
|
2545
|
+
return "text";
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2502
2548
|
function renderDrizzleColumns2(cols, dialect) {
|
|
2503
2549
|
return cols.map(([name, type]) => {
|
|
2504
2550
|
const helper = mapDrizzleType(dialect, type);
|
|
@@ -2554,7 +2600,7 @@ var makeModelCommand = {
|
|
|
2554
2600
|
name: "make:model",
|
|
2555
2601
|
aliases: ["mmodel", "make-model"],
|
|
2556
2602
|
summary: "Generate a model (table schema)",
|
|
2557
|
-
description: "Generates a model file under app/models/. The template is chosen from nx.config.ts's `orm` field (drizzle|
|
|
2603
|
+
description: "Generates a model file under app/models/. The template is chosen from nx.config.ts's `orm` field (drizzle|kysely). For drizzle, use --dialect to pick the import path.",
|
|
2558
2604
|
examples: [
|
|
2559
2605
|
"nx make:model User",
|
|
2560
2606
|
'nx make:model User --columns "name:text,email:text"',
|
|
@@ -2568,7 +2614,7 @@ var makeModelCommand = {
|
|
|
2568
2614
|
},
|
|
2569
2615
|
{
|
|
2570
2616
|
name: "orm",
|
|
2571
|
-
description: "Override ORM driver (drizzle|
|
|
2617
|
+
description: "Override ORM driver (drizzle|kysely)"
|
|
2572
2618
|
},
|
|
2573
2619
|
{
|
|
2574
2620
|
name: "dialect",
|
|
@@ -2581,20 +2627,19 @@ var makeModelCommand = {
|
|
|
2581
2627
|
logger.error("Usage: nx make:model <Name> [--columns name:type,...] [--dialect ...]");
|
|
2582
2628
|
return 1;
|
|
2583
2629
|
}
|
|
2584
|
-
const orm = ctx.flags
|
|
2585
|
-
if (orm !== "drizzle" && orm !== "
|
|
2586
|
-
logger.error(`Unsupported ORM: ${orm}. Allowed: drizzle,
|
|
2630
|
+
const orm = ctx.flags.orm ?? ctx.config.orm;
|
|
2631
|
+
if (orm !== "drizzle" && orm !== "kysely") {
|
|
2632
|
+
logger.error(`Unsupported ORM: ${orm}. Allowed: drizzle, kysely. Use --orm or set "orm" in nx.config.ts.`);
|
|
2587
2633
|
return 1;
|
|
2588
2634
|
}
|
|
2589
2635
|
const variants = nameVariants(name);
|
|
2590
2636
|
const tableName = variants.pluralSnake;
|
|
2591
2637
|
const colsFlag = flagList(ctx.flags, "columns");
|
|
2592
2638
|
const columns = colsFlag.length > 0 ? colsFlag : ["title:text"];
|
|
2593
|
-
const columnLines = renderColumns(columns, orm, ctx.flags
|
|
2594
|
-
const prismaBlock = renderPrismaBlock(variants.pascal, columns);
|
|
2639
|
+
const columnLines = renderColumns(columns, orm, ctx.flags.dialect);
|
|
2595
2640
|
let code;
|
|
2596
2641
|
if (orm === "drizzle") {
|
|
2597
|
-
const dialect = ctx.flags
|
|
2642
|
+
const dialect = ctx.flags.dialect ?? ctx.config.dialect ?? "bun-sqlite";
|
|
2598
2643
|
if (!isValidDialect2(dialect)) {
|
|
2599
2644
|
logger.error(`Unsupported drizzle dialect: ${dialect}. Allowed: postgres, mysql, sqlite, bun-sqlite, d1.`);
|
|
2600
2645
|
return 1;
|
|
@@ -2606,8 +2651,7 @@ var makeModelCommand = {
|
|
|
2606
2651
|
kebab: variants.kebab,
|
|
2607
2652
|
snake: variants.snake,
|
|
2608
2653
|
tableName,
|
|
2609
|
-
columns: columnLines
|
|
2610
|
-
prismaBlock
|
|
2654
|
+
columns: columnLines
|
|
2611
2655
|
});
|
|
2612
2656
|
} else {
|
|
2613
2657
|
const tpl = templates.model[orm];
|
|
@@ -2617,8 +2661,7 @@ var makeModelCommand = {
|
|
|
2617
2661
|
kebab: variants.kebab,
|
|
2618
2662
|
snake: variants.snake,
|
|
2619
2663
|
tableName,
|
|
2620
|
-
columns: columnLines
|
|
2621
|
-
prismaBlock
|
|
2664
|
+
columns: columnLines
|
|
2622
2665
|
});
|
|
2623
2666
|
}
|
|
2624
2667
|
const out = resolve13(ctx.cwd, ctx.config.paths.models, `${variants.kebab}.model.ts`);
|
|
@@ -2649,34 +2692,15 @@ function renderColumns(cols, orm, dialect) {
|
|
|
2649
2692
|
const tsType = colType === "text" ? "string" : colType;
|
|
2650
2693
|
return ` ${colName}: ${tsType},`;
|
|
2651
2694
|
}
|
|
2652
|
-
case "prisma":
|
|
2653
2695
|
default:
|
|
2654
|
-
return ` ${colName} ${colType},`;
|
|
2696
|
+
return ` ${colName}: ${colType},`;
|
|
2655
2697
|
}
|
|
2656
2698
|
}).join(`
|
|
2657
2699
|
`);
|
|
2658
2700
|
}
|
|
2659
|
-
function renderPrismaBlock(modelName, cols) {
|
|
2660
|
-
const fieldLines = cols.map((c2) => {
|
|
2661
|
-
const [name, type = "String"] = c2.split(":");
|
|
2662
|
-
return ` ${name.padEnd(16)} ${capitalize(type)}`;
|
|
2663
|
-
}).join(`
|
|
2664
|
-
`);
|
|
2665
|
-
return ` * model ${modelName} {
|
|
2666
|
-
* id Int @id @default(autoincrement())
|
|
2667
|
-
${fieldLines.split(`
|
|
2668
|
-
`).map((l) => ` *${l}`).join(`
|
|
2669
|
-
`)}
|
|
2670
|
-
* createdAt DateTime @default(now())
|
|
2671
|
-
* updatedAt DateTime @updatedAt
|
|
2672
|
-
* }`;
|
|
2673
|
-
}
|
|
2674
2701
|
function toCamel2(s) {
|
|
2675
2702
|
return s.replace(/_([a-z])/g, (_, c2) => c2.toUpperCase());
|
|
2676
2703
|
}
|
|
2677
|
-
function capitalize(s) {
|
|
2678
|
-
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
2679
|
-
}
|
|
2680
2704
|
var make_model_default = makeModelCommand;
|
|
2681
2705
|
|
|
2682
2706
|
// packages/cli/src/commands/make-module.ts
|
|
@@ -2702,7 +2726,7 @@ var makeModuleCommand = {
|
|
|
2702
2726
|
return 1;
|
|
2703
2727
|
}
|
|
2704
2728
|
const variants = nameVariants(name);
|
|
2705
|
-
const
|
|
2729
|
+
const _hasController = !flagBool(ctx.flags, "no-controller", false);
|
|
2706
2730
|
const hasService = !flagBool(ctx.flags, "no-service", false);
|
|
2707
2731
|
const hasRepo = !flagBool(ctx.flags, "no-repo", false) && ctx.config.orm !== "none";
|
|
2708
2732
|
const code = render(templates.module, {
|
|
@@ -2841,7 +2865,7 @@ var makeQueueCommand = {
|
|
|
2841
2865
|
return 1;
|
|
2842
2866
|
}
|
|
2843
2867
|
const variants = nameVariants(name);
|
|
2844
|
-
const backend = ctx.flags
|
|
2868
|
+
const backend = ctx.flags.backend ?? ctx.config.queue?.backend ?? "memory";
|
|
2845
2869
|
if (!["bullmq", "cloudflare", "memory"].includes(backend)) {
|
|
2846
2870
|
logger.error(`Unknown backend: ${backend}. Allowed: bullmq, cloudflare, memory.`);
|
|
2847
2871
|
return 1;
|
|
@@ -2877,7 +2901,7 @@ var makeQueueCommand = {
|
|
|
2877
2901
|
logger.info(` QueueModule.forRoot({ backend: '${backend}', ... })`);
|
|
2878
2902
|
logger.info(`2. Wire the worker + helper as providers:`);
|
|
2879
2903
|
logger.info(render(WIRE_HINT, { name: variants.pascal, kebab: variants.kebab }).split(`
|
|
2880
|
-
`).map((l) =>
|
|
2904
|
+
`).map((l) => ` ${l}`).join(`
|
|
2881
2905
|
`));
|
|
2882
2906
|
logger.info(`3. Replace the TODO in ${variants.pascal}Worker.handle() with your logic.`);
|
|
2883
2907
|
logger.blank();
|
|
@@ -2893,24 +2917,33 @@ var makeRepositoryCommand = {
|
|
|
2893
2917
|
name: "make:repository",
|
|
2894
2918
|
aliases: ["mr", "make-repository", "make:repo"],
|
|
2895
2919
|
summary: "Generate a repository class",
|
|
2896
|
-
description: "Generates a
|
|
2920
|
+
description: "Generates a repository class under app/repositories/. Adapts to the project's ORM (drizzle -> DrizzleRepository, kysely -> KyselyRepository). Requires a model file at app/models/<name>.model.ts.",
|
|
2897
2921
|
examples: [
|
|
2898
2922
|
"nx make:repository User",
|
|
2899
2923
|
"nx make:repository Post"
|
|
2900
2924
|
],
|
|
2925
|
+
flags: [
|
|
2926
|
+
{
|
|
2927
|
+
name: "orm",
|
|
2928
|
+
description: "Override ORM driver (drizzle|kysely)"
|
|
2929
|
+
}
|
|
2930
|
+
],
|
|
2901
2931
|
async run(ctx) {
|
|
2902
2932
|
const name = ctx.positional[0];
|
|
2903
2933
|
if (!name) {
|
|
2904
2934
|
logger.error("Usage: nx make:repository <Name>");
|
|
2905
2935
|
return 1;
|
|
2906
2936
|
}
|
|
2937
|
+
const orm = ctx.flags.orm ?? ctx.config.orm;
|
|
2907
2938
|
const variants = nameVariants(name);
|
|
2908
2939
|
const repository = `${variants.pascal}Repository`;
|
|
2909
|
-
const
|
|
2940
|
+
const tpl = orm === "kysely" ? templates.repository.kysely : templates.repository.drizzle;
|
|
2941
|
+
const code = render(tpl, {
|
|
2910
2942
|
name: variants.pascal,
|
|
2911
2943
|
camel: variants.camel,
|
|
2912
2944
|
kebab: variants.kebab,
|
|
2913
2945
|
snake: variants.snake,
|
|
2946
|
+
tableName: variants.pluralSnake,
|
|
2914
2947
|
repository
|
|
2915
2948
|
});
|
|
2916
2949
|
const out = resolve16(ctx.cwd, `${ctx.config.paths.app}/repositories`, `${variants.kebab}.repository.ts`);
|
|
@@ -3007,7 +3040,7 @@ var makeServiceCommand = {
|
|
|
3007
3040
|
const variants = nameVariants(name);
|
|
3008
3041
|
const hasRepo = ctx.flags["no-repo"] !== true && ctx.config.orm !== "none";
|
|
3009
3042
|
const repository = `${variants.pascal}Repository`;
|
|
3010
|
-
const repositoryCamel = variants.camel
|
|
3043
|
+
const repositoryCamel = `${variants.camel}Repository`;
|
|
3011
3044
|
const code = render(templates.service, {
|
|
3012
3045
|
name: variants.pascal,
|
|
3013
3046
|
camel: variants.camel,
|
|
@@ -3139,11 +3172,10 @@ var dbMigrateCommand = {
|
|
|
3139
3172
|
name: "db:migrate",
|
|
3140
3173
|
aliases: ["db:m", "migrate"],
|
|
3141
3174
|
summary: "Apply pending database migrations",
|
|
3142
|
-
description: "Runs the
|
|
3175
|
+
description: "Runs the configured migrator (drizzle-kit for Drizzle, Kysely Migrator for Kysely) against the migrations folder. Use --status to inspect. See also `nx db:seed` for fixture data.",
|
|
3143
3176
|
examples: [
|
|
3144
3177
|
"nx db:migrate",
|
|
3145
3178
|
"nx db:migrate --status",
|
|
3146
|
-
"nx db:migrate --generate 'add_email_to_users'",
|
|
3147
3179
|
"nx db:migrate --folder ./drizzle"
|
|
3148
3180
|
],
|
|
3149
3181
|
flags: [
|
|
@@ -3151,39 +3183,34 @@ var dbMigrateCommand = {
|
|
|
3151
3183
|
name: "status",
|
|
3152
3184
|
description: "List applied migrations and exit (no apply)."
|
|
3153
3185
|
},
|
|
3154
|
-
{
|
|
3155
|
-
name: "generate",
|
|
3156
|
-
description: "Run `drizzle-kit generate` with the given migration name."
|
|
3157
|
-
},
|
|
3158
3186
|
{
|
|
3159
3187
|
name: "folder",
|
|
3160
3188
|
description: "Override migrations folder (default: from nx.config.ts)."
|
|
3161
3189
|
},
|
|
3162
3190
|
{
|
|
3163
3191
|
name: "dialect",
|
|
3164
|
-
description: "
|
|
3192
|
+
description: "Database dialect (postgres|mysql|sqlite|bun-sqlite). Default: bun-sqlite."
|
|
3165
3193
|
},
|
|
3166
3194
|
{
|
|
3167
3195
|
name: "config",
|
|
3168
3196
|
description: "Path to drizzle.config.ts. Default: ./drizzle.config.ts."
|
|
3197
|
+
},
|
|
3198
|
+
{
|
|
3199
|
+
name: "orm",
|
|
3200
|
+
description: "Override ORM driver (drizzle|kysely)"
|
|
3169
3201
|
}
|
|
3170
3202
|
],
|
|
3171
3203
|
async run(ctx) {
|
|
3172
|
-
const
|
|
3173
|
-
const
|
|
3174
|
-
const
|
|
3175
|
-
const
|
|
3176
|
-
const
|
|
3177
|
-
if (
|
|
3178
|
-
return
|
|
3179
|
-
"generate",
|
|
3180
|
-
...existsSync5(configPath) ? [`--config=${configPath}`] : [],
|
|
3181
|
-
"--name",
|
|
3182
|
-
generateName
|
|
3183
|
-
]);
|
|
3204
|
+
const orm = ctx.flags.orm ?? ctx.config.orm;
|
|
3205
|
+
const folder = ctx.flags.folder ?? resolve21(ctx.cwd, ctx.config.paths.migrations);
|
|
3206
|
+
const dialect = ctx.flags.dialect ?? ctx.config.dialect ?? "bun-sqlite";
|
|
3207
|
+
const configPath = ctx.flags.config ?? resolve21(ctx.cwd, "drizzle.config.ts");
|
|
3208
|
+
const wantStatus = Boolean(ctx.flags.status);
|
|
3209
|
+
if (orm === "kysely") {
|
|
3210
|
+
return runKyselyMigrate(ctx.cwd, folder, dialect, wantStatus);
|
|
3184
3211
|
}
|
|
3185
3212
|
if (wantStatus) {
|
|
3186
|
-
return await runStatus(ctx.cwd, folder, dialect, ctx.config.database
|
|
3213
|
+
return await runStatus(ctx.cwd, folder, dialect, ctx.config.database.url);
|
|
3187
3214
|
}
|
|
3188
3215
|
return runDrizzleKit(ctx.cwd, [
|
|
3189
3216
|
"migrate",
|
|
@@ -3191,6 +3218,132 @@ var dbMigrateCommand = {
|
|
|
3191
3218
|
]);
|
|
3192
3219
|
}
|
|
3193
3220
|
};
|
|
3221
|
+
async function runKyselyMigrate(cwd, folder, dialect, statusOnly) {
|
|
3222
|
+
if (!existsSync5(folder)) {
|
|
3223
|
+
logger.warn(`migrations folder not found: ${folder}`);
|
|
3224
|
+
return 0;
|
|
3225
|
+
}
|
|
3226
|
+
const script = buildKyselyMigrateScript(folder, dialect, statusOnly);
|
|
3227
|
+
const tmpFile = resolve21(cwd, ".nx-kysely-migrate.mjs");
|
|
3228
|
+
const { writeFile: writeFile2, unlink } = await import("fs/promises");
|
|
3229
|
+
await writeFile2(tmpFile, script, "utf-8");
|
|
3230
|
+
try {
|
|
3231
|
+
const code = await new Promise((resP) => {
|
|
3232
|
+
const child = spawn("bun", [tmpFile], {
|
|
3233
|
+
cwd,
|
|
3234
|
+
stdio: "inherit",
|
|
3235
|
+
shell: process.platform === "win32"
|
|
3236
|
+
});
|
|
3237
|
+
child.on("exit", (c2) => resP(c2 ?? 0));
|
|
3238
|
+
child.on("error", () => resP(1));
|
|
3239
|
+
});
|
|
3240
|
+
return code;
|
|
3241
|
+
} finally {
|
|
3242
|
+
await unlink(tmpFile).catch(() => {});
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
function buildKyselyMigrateScript(folder, dialect, statusOnly) {
|
|
3246
|
+
const dialectSetup = buildDialectSetup(dialect);
|
|
3247
|
+
const tableName = "kysely_migration";
|
|
3248
|
+
return `
|
|
3249
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
3250
|
+
import { dirname, join } from "node:path";
|
|
3251
|
+
|
|
3252
|
+
const migrationsFolder = ${JSON.stringify(folder)};
|
|
3253
|
+
|
|
3254
|
+
// Build the Kysely instance with the configured dialect.
|
|
3255
|
+
${dialectSetup}
|
|
3256
|
+
|
|
3257
|
+
import {
|
|
3258
|
+
Kysely,
|
|
3259
|
+
Migrator,
|
|
3260
|
+
} from "kysely";
|
|
3261
|
+
|
|
3262
|
+
class FsMigrationProvider {
|
|
3263
|
+
async getMigrations() {
|
|
3264
|
+
const files = readdirSync(migrationsFolder)
|
|
3265
|
+
.filter((f) => f.endsWith(".ts") || f.endsWith(".js"))
|
|
3266
|
+
.sort();
|
|
3267
|
+
|
|
3268
|
+
const migrations = {};
|
|
3269
|
+
for (const file of files) {
|
|
3270
|
+
const name = file.replace(/\\.(ts|js)$/, "");
|
|
3271
|
+
const mod = await import(join(migrationsFolder, file));
|
|
3272
|
+
migrations[name] = {
|
|
3273
|
+
up: mod.up,
|
|
3274
|
+
down: mod.down,
|
|
3275
|
+
};
|
|
3276
|
+
}
|
|
3277
|
+
return migrations;
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3281
|
+
const db = new Kysely({ dialect });
|
|
3282
|
+
|
|
3283
|
+
const migrator = new Migrator({
|
|
3284
|
+
db,
|
|
3285
|
+
provider: new FsMigrationProvider(),
|
|
3286
|
+
migrationTableName: ${JSON.stringify(tableName)},
|
|
3287
|
+
});
|
|
3288
|
+
|
|
3289
|
+
${statusOnly ? `
|
|
3290
|
+
const { results } = await migrator.getMigrations();
|
|
3291
|
+
console.log("Migration status:");
|
|
3292
|
+
for (const r of results ?? []) {
|
|
3293
|
+
console.log(\` \${r.name}: \${r.status}\`);
|
|
3294
|
+
}
|
|
3295
|
+
` : `
|
|
3296
|
+
const { results, error } = await migrator.migrateToLatest();
|
|
3297
|
+
if (error) {
|
|
3298
|
+
console.error("Migration failed:", error);
|
|
3299
|
+
process.exit(1);
|
|
3300
|
+
}
|
|
3301
|
+
const applied = (results ?? []).filter((r) => r.status === "Success" || r.status === "MigratedAbove");
|
|
3302
|
+
console.log(\`Applied \${applied.length} migration(s)\`);
|
|
3303
|
+
for (const r of applied) {
|
|
3304
|
+
console.log(\` \u2713 \${r.migrationName}\`);
|
|
3305
|
+
}
|
|
3306
|
+
`}
|
|
3307
|
+
|
|
3308
|
+
await db.destroy();
|
|
3309
|
+
`;
|
|
3310
|
+
}
|
|
3311
|
+
function buildDialectSetup(dialect) {
|
|
3312
|
+
switch (dialect) {
|
|
3313
|
+
case "postgres":
|
|
3314
|
+
return `
|
|
3315
|
+
import { Pool } from "pg";
|
|
3316
|
+
import { PostgresDialect } from "kysely";
|
|
3317
|
+
const dialect = new PostgresDialect({
|
|
3318
|
+
pool: new Pool({ connectionString: process.env.DATABASE_URL ?? "" }),
|
|
3319
|
+
});
|
|
3320
|
+
`;
|
|
3321
|
+
case "mysql":
|
|
3322
|
+
return `
|
|
3323
|
+
import { createPool } from "mysql2";
|
|
3324
|
+
import { MysqlDialect } from "kysely";
|
|
3325
|
+
const dialect = new MysqlDialect({
|
|
3326
|
+
pool: createPool({ uri: process.env.DATABASE_URL ?? "" }),
|
|
3327
|
+
});
|
|
3328
|
+
`;
|
|
3329
|
+
default:
|
|
3330
|
+
return `
|
|
3331
|
+
import { Database } from "bun:sqlite";
|
|
3332
|
+
import { SqliteDialect } from "kysely";
|
|
3333
|
+
|
|
3334
|
+
// Patch .reader property for bun:sqlite compatibility with Kysely.
|
|
3335
|
+
const _db = new Database(process.env.DATABASE_URL ?? "app.db");
|
|
3336
|
+
const proto = Object.getPrototypeOf(_db);
|
|
3337
|
+
const _prepare = proto.prepare.bind(_db);
|
|
3338
|
+
_db.prepare = function(sql) {
|
|
3339
|
+
const stmt = _prepare(sql);
|
|
3340
|
+
Object.defineProperty(stmt, "reader", { value: /^\\s*(select|pragma|with|explain)\\b/i.test(sql) });
|
|
3341
|
+
return stmt;
|
|
3342
|
+
};
|
|
3343
|
+
const dialect = new SqliteDialect({ database: _db });
|
|
3344
|
+
`;
|
|
3345
|
+
}
|
|
3346
|
+
}
|
|
3194
3347
|
function runDrizzleKit(cwd, args2) {
|
|
3195
3348
|
return new Promise((resolveP) => {
|
|
3196
3349
|
const cmd = "bunx";
|
|
@@ -3249,7 +3402,7 @@ await svc.close();
|
|
|
3249
3402
|
}
|
|
3250
3403
|
}
|
|
3251
3404
|
function readEnvUrl(dialect) {
|
|
3252
|
-
const url = process.env
|
|
3405
|
+
const url = process.env.DATABASE_URL ?? process.env.NEXUS_DB_URL ?? (dialect === "postgres" ? process.env.POSTGRES_URL : dialect === "mysql" ? process.env.MYSQL_URL : dialect.includes("sqlite") ? process.env.SQLITE_FILENAME : null);
|
|
3253
3406
|
return url ?? null;
|
|
3254
3407
|
}
|
|
3255
3408
|
var db_migrate_default = dbMigrateCommand;
|
|
@@ -3260,7 +3413,7 @@ var dbGenerateCommand = {
|
|
|
3260
3413
|
name: "db:generate",
|
|
3261
3414
|
aliases: ["db:g", "db-generate", "generate-migration"],
|
|
3262
3415
|
summary: "Generate a new migration from schema changes",
|
|
3263
|
-
description: "Generates a new migration file
|
|
3416
|
+
description: "Generates a new migration file. For drizzle: runs drizzle-kit generate. " + "For kysely: generates a .ts file with up/down functions. " + "Use --sql for a plain SQL file. " + "Run after editing your schema files, then apply with `nx db:migrate`.",
|
|
3264
3417
|
examples: [
|
|
3265
3418
|
"nx db:generate",
|
|
3266
3419
|
"nx db:generate add_users_table",
|
|
@@ -3274,12 +3427,17 @@ var dbGenerateCommand = {
|
|
|
3274
3427
|
{
|
|
3275
3428
|
name: "sql",
|
|
3276
3429
|
description: "Generate a raw SQL file instead of using drizzle-kit"
|
|
3430
|
+
},
|
|
3431
|
+
{
|
|
3432
|
+
name: "orm",
|
|
3433
|
+
description: "Override ORM driver (drizzle|kysely)"
|
|
3277
3434
|
}
|
|
3278
3435
|
],
|
|
3279
3436
|
async run(ctx) {
|
|
3280
3437
|
const name = ctx.positional[0];
|
|
3281
|
-
const
|
|
3282
|
-
const
|
|
3438
|
+
const orm = ctx.flags.orm ?? ctx.config.orm;
|
|
3439
|
+
const dialect = ctx.flags.dialect ?? ctx.config.dialect ?? "bun-sqlite";
|
|
3440
|
+
const isSql = ctx.flags.sql === true;
|
|
3283
3441
|
if (isSql) {
|
|
3284
3442
|
if (!name) {
|
|
3285
3443
|
logger.error("Usage: nx db:generate <name> --sql");
|
|
@@ -3288,6 +3446,14 @@ var dbGenerateCommand = {
|
|
|
3288
3446
|
logger.info(`Generating raw SQL migration: ${name} (dialect=${dialect})`);
|
|
3289
3447
|
return runSqlTemplate(ctx.cwd, name, dialect);
|
|
3290
3448
|
}
|
|
3449
|
+
if (orm === "kysely") {
|
|
3450
|
+
if (!name) {
|
|
3451
|
+
logger.error("Usage: nx db:generate <name> (name is required for Kysely)");
|
|
3452
|
+
return 1;
|
|
3453
|
+
}
|
|
3454
|
+
logger.info(`Generating Kysely migration: ${name}`);
|
|
3455
|
+
return runKyselyTemplate(ctx.cwd, name, dialect);
|
|
3456
|
+
}
|
|
3291
3457
|
const configPath = resolve22(ctx.cwd, "drizzle.config.ts");
|
|
3292
3458
|
const args2 = ["generate", "--config", configPath];
|
|
3293
3459
|
if (name)
|
|
@@ -3296,6 +3462,28 @@ var dbGenerateCommand = {
|
|
|
3296
3462
|
return runDrizzleKit(ctx.cwd, args2);
|
|
3297
3463
|
}
|
|
3298
3464
|
};
|
|
3465
|
+
async function runKyselyTemplate(cwd, name, _dialect) {
|
|
3466
|
+
const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync4 } = await import("fs");
|
|
3467
|
+
const { join } = await import("path");
|
|
3468
|
+
const migrationsDir = join(cwd, "app", "database", "migrations");
|
|
3469
|
+
mkdirSync5(migrationsDir, { recursive: true });
|
|
3470
|
+
const variants = nameVariants(name);
|
|
3471
|
+
const timestamp = formatTimestamp2(new Date);
|
|
3472
|
+
const filename = `${timestamp}_${variants.snake}.ts`;
|
|
3473
|
+
const filepath = join(migrationsDir, filename);
|
|
3474
|
+
const tpl = templates.migration.kysely;
|
|
3475
|
+
const code = render(tpl, {
|
|
3476
|
+
name: variants.pascal,
|
|
3477
|
+
snake: variants.snake,
|
|
3478
|
+
tableName: inferTableName2(name),
|
|
3479
|
+
columns: "",
|
|
3480
|
+
timestamp
|
|
3481
|
+
});
|
|
3482
|
+
writeFileSync4(filepath, code);
|
|
3483
|
+
logger.success(`created ${filepath}`);
|
|
3484
|
+
logger.info("Edit the migration, then run `nx db:migrate` to apply it.");
|
|
3485
|
+
return 0;
|
|
3486
|
+
}
|
|
3299
3487
|
async function runSqlTemplate(cwd, name, dialect) {
|
|
3300
3488
|
const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync4 } = await import("fs");
|
|
3301
3489
|
const { join } = await import("path");
|
|
@@ -3318,6 +3506,19 @@ async function runSqlTemplate(cwd, name, dialect) {
|
|
|
3318
3506
|
logger.info("Edit the SQL file, then run `nx db:migrate` to apply it.");
|
|
3319
3507
|
return 0;
|
|
3320
3508
|
}
|
|
3509
|
+
function inferTableName2(input) {
|
|
3510
|
+
const m = /^create_(\w+)_table$/.exec(input);
|
|
3511
|
+
if (m)
|
|
3512
|
+
return m[1] ?? "";
|
|
3513
|
+
const m2 = /^(?:add|remove|drop|alter)_(\w+)_to_(\w+)$/.exec(input);
|
|
3514
|
+
if (m2)
|
|
3515
|
+
return m2[2] ?? "";
|
|
3516
|
+
return `${input.toLowerCase().replace(/s$/, "")}s`;
|
|
3517
|
+
}
|
|
3518
|
+
function formatTimestamp2(d) {
|
|
3519
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
3520
|
+
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}_${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
|
3521
|
+
}
|
|
3321
3522
|
var db_generate_default = dbGenerateCommand;
|
|
3322
3523
|
|
|
3323
3524
|
// packages/cli/src/commands/db-seed.ts
|
|
@@ -3394,11 +3595,11 @@ var dbSeedCommand = {
|
|
|
3394
3595
|
}
|
|
3395
3596
|
],
|
|
3396
3597
|
async run(ctx) {
|
|
3397
|
-
const folder = resolve23(ctx.cwd, ctx.flags
|
|
3398
|
-
const dialect = ctx.flags
|
|
3399
|
-
const createName = ctx.flags
|
|
3400
|
-
const fileName = ctx.flags
|
|
3401
|
-
const reset = Boolean(ctx.flags
|
|
3598
|
+
const folder = resolve23(ctx.cwd, ctx.flags.folder ?? ctx.config.paths?.seeds ?? "db/seeds");
|
|
3599
|
+
const dialect = ctx.flags.dialect ?? ctx.config.dialect ?? "bun-sqlite";
|
|
3600
|
+
const createName = ctx.flags.create;
|
|
3601
|
+
const fileName = ctx.flags.file;
|
|
3602
|
+
const reset = Boolean(ctx.flags.reset);
|
|
3402
3603
|
if (createName) {
|
|
3403
3604
|
return await createSeedFile(folder, createName);
|
|
3404
3605
|
}
|
|
@@ -3515,7 +3716,7 @@ async function createSeedFile(folder, name) {
|
|
|
3515
3716
|
return 0;
|
|
3516
3717
|
}
|
|
3517
3718
|
function readEnvUrl2(dialect) {
|
|
3518
|
-
const url = process.env
|
|
3719
|
+
const url = process.env.DATABASE_URL ?? process.env.NEXUS_DB_URL ?? (dialect === "postgres" ? process.env.POSTGRES_URL : dialect === "mysql" ? process.env.MYSQL_URL : dialect.includes("sqlite") ? process.env.SQLITE_FILENAME : null);
|
|
3519
3720
|
return url ?? null;
|
|
3520
3721
|
}
|
|
3521
3722
|
var db_seed_default = dbSeedCommand;
|
|
@@ -3526,7 +3727,7 @@ import { resolve as resolve24 } from "path";
|
|
|
3526
3727
|
var VALID_OPTIONS2 = {
|
|
3527
3728
|
style: ["nest", "adonis", "functional"],
|
|
3528
3729
|
view: ["rendu", "edge", "eta", "inertia", "none"],
|
|
3529
|
-
orm: ["drizzle", "
|
|
3730
|
+
orm: ["drizzle", "kysely", "none"],
|
|
3530
3731
|
db: ["bun-sqlite", "node-sqlite", "libsql", "postgres", "mysql", "none"],
|
|
3531
3732
|
frontend: ["react", "vue", "svelte", "solid"]
|
|
3532
3733
|
};
|
|
@@ -3561,7 +3762,7 @@ var newCommand = {
|
|
|
3561
3762
|
flags: [
|
|
3562
3763
|
{ name: "style", description: "Routing style (nest|adonis|functional)" },
|
|
3563
3764
|
{ name: "view", description: "View engine (rendu|edge|eta|inertia|none)" },
|
|
3564
|
-
{ name: "orm", description: "ORM driver (drizzle|
|
|
3765
|
+
{ name: "orm", description: "ORM driver (drizzle|kysely|none)" },
|
|
3565
3766
|
{ name: "db", description: "Database driver" },
|
|
3566
3767
|
{ name: "frontend", description: "Inertia frontend (react|vue|svelte|solid)" },
|
|
3567
3768
|
{ name: "no-ssr", description: "Disable SSR" }
|
|
@@ -3720,7 +3921,7 @@ var configCommand = {
|
|
|
3720
3921
|
name: "view-paths",
|
|
3721
3922
|
description: "Comma-separated directories searched for view files (e.g. resources/views)"
|
|
3722
3923
|
},
|
|
3723
|
-
{ name: "orm", description: "ORM driver (drizzle|
|
|
3924
|
+
{ name: "orm", description: "ORM driver (drizzle|kysely|none)" },
|
|
3724
3925
|
{
|
|
3725
3926
|
name: "db",
|
|
3726
3927
|
description: "Database driver (bun-sqlite|node-sqlite|libsql|postgres|mysql|none)"
|
|
@@ -3741,7 +3942,7 @@ var configCommand = {
|
|
|
3741
3942
|
async run(ctx) {
|
|
3742
3943
|
const interactive = !flagBool(ctx.flags, "no-interaction", false);
|
|
3743
3944
|
const force = flagBool(ctx.flags, "force", false);
|
|
3744
|
-
const target = resolve25(ctx.cwd, ctx.flags
|
|
3945
|
+
const target = resolve25(ctx.cwd, ctx.flags.target ?? ".");
|
|
3745
3946
|
if (!existsSync8(target)) {
|
|
3746
3947
|
logger.error(`Target directory does not exist: ${target}`);
|
|
3747
3948
|
return 1;
|
|
@@ -3750,21 +3951,27 @@ var configCommand = {
|
|
|
3750
3951
|
const values = parseExistingConfig(nxConfigPath);
|
|
3751
3952
|
const flag = (k) => ctx.flags[k];
|
|
3752
3953
|
const flagBoolStrict = (k, def) => flagBool(ctx.flags, k, def);
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
if (
|
|
3758
|
-
values.
|
|
3759
|
-
|
|
3760
|
-
if (
|
|
3761
|
-
values.
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
if (
|
|
3767
|
-
values.
|
|
3954
|
+
const style = flag("style");
|
|
3955
|
+
if (style)
|
|
3956
|
+
values.routing = style;
|
|
3957
|
+
const view = flag("view");
|
|
3958
|
+
if (view)
|
|
3959
|
+
values.view = view;
|
|
3960
|
+
const viewPaths = flag("view-paths");
|
|
3961
|
+
if (viewPaths)
|
|
3962
|
+
values.viewPaths = viewPaths;
|
|
3963
|
+
const orm = flag("orm");
|
|
3964
|
+
if (orm)
|
|
3965
|
+
values.orm = orm;
|
|
3966
|
+
const db = flag("db");
|
|
3967
|
+
if (db)
|
|
3968
|
+
values.dbDriver = db;
|
|
3969
|
+
const dbUrl = flag("db-url");
|
|
3970
|
+
if (dbUrl !== undefined)
|
|
3971
|
+
values.dbUrl = dbUrl;
|
|
3972
|
+
const frontend = flag("frontend");
|
|
3973
|
+
if (frontend)
|
|
3974
|
+
values.inertiaFrontend = frontend;
|
|
3768
3975
|
if (flagBoolStrict("ssr", false))
|
|
3769
3976
|
values.inertiaSSR = true;
|
|
3770
3977
|
if (flagBoolStrict("no-ssr", false))
|
|
@@ -3779,7 +3986,7 @@ var configCommand = {
|
|
|
3779
3986
|
interactive,
|
|
3780
3987
|
default: values.view
|
|
3781
3988
|
}) ?? values.view;
|
|
3782
|
-
values.orm = await select("ORM driver", ["drizzle", "
|
|
3989
|
+
values.orm = await select("ORM driver", ["drizzle", "kysely", "none"], {
|
|
3783
3990
|
interactive,
|
|
3784
3991
|
default: values.orm
|
|
3785
3992
|
}) ?? values.orm;
|
|
@@ -3804,12 +4011,12 @@ var configCommand = {
|
|
|
3804
4011
|
const drizzleConfigPath = resolve25(target, "drizzle.config.ts");
|
|
3805
4012
|
if (values.orm === "drizzle") {
|
|
3806
4013
|
const dialect = driverToDialect(values.dbDriver);
|
|
3807
|
-
const
|
|
4014
|
+
const dbUrl2 = values.dbUrl;
|
|
3808
4015
|
const existedDrizzle = existsSync8(drizzleConfigPath);
|
|
3809
4016
|
if (existedDrizzle && !force && !anyFlag) {
|
|
3810
4017
|
logger.info(` - drizzle.config.ts (unchanged; pass --force or a flag to update)`);
|
|
3811
4018
|
} else {
|
|
3812
|
-
writeDrizzleConfig(target, { dialect, dbUrl });
|
|
4019
|
+
writeDrizzleConfig(target, { dialect, dbUrl: dbUrl2 });
|
|
3813
4020
|
logger.info(` ${existedDrizzle ? "~" : "+"} drizzle.config.ts`);
|
|
3814
4021
|
}
|
|
3815
4022
|
} else if (existsSync8(drizzleConfigPath)) {
|
|
@@ -3924,9 +4131,9 @@ var replCommand = {
|
|
|
3924
4131
|
}
|
|
3925
4132
|
],
|
|
3926
4133
|
async run(ctx) {
|
|
3927
|
-
const mod = ctx.flags
|
|
4134
|
+
const mod = ctx.flags.module;
|
|
3928
4135
|
const noBoot = Boolean(ctx.flags["no-boot"]);
|
|
3929
|
-
const histPath = resolve26(ctx.cwd, ctx.flags
|
|
4136
|
+
const histPath = resolve26(ctx.cwd, ctx.flags.history ?? ".nx-repl-history");
|
|
3930
4137
|
const env = { console };
|
|
3931
4138
|
if (!noBoot) {
|
|
3932
4139
|
const modPath = resolve26(ctx.cwd, mod ?? "app/app.module.ts");
|
|
@@ -4037,7 +4244,7 @@ var replCommand = {
|
|
|
4037
4244
|
case ".routes": {
|
|
4038
4245
|
const app = env.app;
|
|
4039
4246
|
const getRoutes = app?.server?.router?.getRoutes;
|
|
4040
|
-
const raw = typeof getRoutes === "function" ? getRoutes.call(app
|
|
4247
|
+
const raw = typeof getRoutes === "function" ? getRoutes.call(app?.server?.router) : [];
|
|
4041
4248
|
const seen = new Set;
|
|
4042
4249
|
const routes = raw.filter((r) => {
|
|
4043
4250
|
const key = `${r.method}:${r.path}:${r.target?.name ?? ""}:${typeof r.propertyKey === "symbol" ? r.propertyKey.description ?? "" : String(r.propertyKey)}`;
|
|
@@ -4087,7 +4294,7 @@ var replCommand = {
|
|
|
4087
4294
|
if (trimmed.startsWith(".")) {
|
|
4088
4295
|
await handleDotCommand(trimmed);
|
|
4089
4296
|
} else {
|
|
4090
|
-
buffer += line
|
|
4297
|
+
buffer += `${line}
|
|
4091
4298
|
`;
|
|
4092
4299
|
if (isIncomplete(buffer)) {
|
|
4093
4300
|
rl.setPrompt("... ");
|
|
@@ -4300,14 +4507,14 @@ var routeListCommand = {
|
|
|
4300
4507
|
}
|
|
4301
4508
|
}
|
|
4302
4509
|
} catch (err) {
|
|
4303
|
-
logger.warn(`could not parse ${file}: ${err.message
|
|
4510
|
+
logger.warn(`could not parse ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
4304
4511
|
}
|
|
4305
4512
|
}
|
|
4306
4513
|
if (routes.length === 0) {
|
|
4307
4514
|
logger.info("No routes discovered via metadata. " + "This usually means the controllers use the Adonis or functional style \u2014 see nx.config.ts:routing.");
|
|
4308
4515
|
return 0;
|
|
4309
4516
|
}
|
|
4310
|
-
const format = ctx.flags
|
|
4517
|
+
const format = ctx.flags.format ?? "table";
|
|
4311
4518
|
if (format === "json") {
|
|
4312
4519
|
console.log(JSON.stringify(routes, null, 2));
|
|
4313
4520
|
return 0;
|
|
@@ -4378,11 +4585,11 @@ async function main() {
|
|
|
4378
4585
|
const parsed = parseArgs(process.argv.slice(2));
|
|
4379
4586
|
const verbose = flagBool(parsed.flags, "verbose", false);
|
|
4380
4587
|
logger.setVerbose(verbose);
|
|
4381
|
-
if (parsed.flags
|
|
4588
|
+
if (parsed.flags.version === true) {
|
|
4382
4589
|
console.log(PKG_VERSION);
|
|
4383
4590
|
return 0;
|
|
4384
4591
|
}
|
|
4385
|
-
if (parsed.flags
|
|
4592
|
+
if (parsed.flags.help === true || parsed.command === "help") {
|
|
4386
4593
|
return renderHelp(parsed.positional[0]);
|
|
4387
4594
|
}
|
|
4388
4595
|
const command = parsed.command ? findCommand(parsed.command) : undefined;
|
|
@@ -4476,11 +4683,11 @@ Examples`));
|
|
|
4476
4683
|
var PKG_VERSION = "0.1.0";
|
|
4477
4684
|
main().then((code) => process.exit(code)).catch((err) => {
|
|
4478
4685
|
logger.error(err?.message ?? String(err));
|
|
4479
|
-
if (process.env
|
|
4686
|
+
if (process.env.NX_DEBUG === "1" && err?.stack) {
|
|
4480
4687
|
console.error(err.stack);
|
|
4481
4688
|
}
|
|
4482
4689
|
process.exit(1);
|
|
4483
4690
|
});
|
|
4484
4691
|
|
|
4485
|
-
//# debugId=
|
|
4692
|
+
//# debugId=B4CDEF95B1BE869264756E2164756E21
|
|
4486
4693
|
//# sourceMappingURL=index.js.map
|