@nexusts/cli 0.9.3 → 0.9.5
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 -260
- 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,13 @@ function renderColumns(cols, orm, dialect) {
|
|
|
2649
2692
|
const tsType = colType === "text" ? "string" : colType;
|
|
2650
2693
|
return ` ${colName}: ${tsType},`;
|
|
2651
2694
|
}
|
|
2652
|
-
case "prisma":
|
|
2653
|
-
default:
|
|
2654
|
-
return ` ${colName} ${colType},`;
|
|
2655
2695
|
}
|
|
2656
2696
|
}).join(`
|
|
2657
2697
|
`);
|
|
2658
2698
|
}
|
|
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
2699
|
function toCamel2(s) {
|
|
2675
2700
|
return s.replace(/_([a-z])/g, (_, c2) => c2.toUpperCase());
|
|
2676
2701
|
}
|
|
2677
|
-
function capitalize(s) {
|
|
2678
|
-
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
2679
|
-
}
|
|
2680
2702
|
var make_model_default = makeModelCommand;
|
|
2681
2703
|
|
|
2682
2704
|
// packages/cli/src/commands/make-module.ts
|
|
@@ -2702,7 +2724,7 @@ var makeModuleCommand = {
|
|
|
2702
2724
|
return 1;
|
|
2703
2725
|
}
|
|
2704
2726
|
const variants = nameVariants(name);
|
|
2705
|
-
const
|
|
2727
|
+
const _hasController = !flagBool(ctx.flags, "no-controller", false);
|
|
2706
2728
|
const hasService = !flagBool(ctx.flags, "no-service", false);
|
|
2707
2729
|
const hasRepo = !flagBool(ctx.flags, "no-repo", false) && ctx.config.orm !== "none";
|
|
2708
2730
|
const code = render(templates.module, {
|
|
@@ -2841,7 +2863,7 @@ var makeQueueCommand = {
|
|
|
2841
2863
|
return 1;
|
|
2842
2864
|
}
|
|
2843
2865
|
const variants = nameVariants(name);
|
|
2844
|
-
const backend = ctx.flags
|
|
2866
|
+
const backend = ctx.flags.backend ?? ctx.config.queue?.backend ?? "memory";
|
|
2845
2867
|
if (!["bullmq", "cloudflare", "memory"].includes(backend)) {
|
|
2846
2868
|
logger.error(`Unknown backend: ${backend}. Allowed: bullmq, cloudflare, memory.`);
|
|
2847
2869
|
return 1;
|
|
@@ -2877,7 +2899,7 @@ var makeQueueCommand = {
|
|
|
2877
2899
|
logger.info(` QueueModule.forRoot({ backend: '${backend}', ... })`);
|
|
2878
2900
|
logger.info(`2. Wire the worker + helper as providers:`);
|
|
2879
2901
|
logger.info(render(WIRE_HINT, { name: variants.pascal, kebab: variants.kebab }).split(`
|
|
2880
|
-
`).map((l) =>
|
|
2902
|
+
`).map((l) => ` ${l}`).join(`
|
|
2881
2903
|
`));
|
|
2882
2904
|
logger.info(`3. Replace the TODO in ${variants.pascal}Worker.handle() with your logic.`);
|
|
2883
2905
|
logger.blank();
|
|
@@ -2893,24 +2915,33 @@ var makeRepositoryCommand = {
|
|
|
2893
2915
|
name: "make:repository",
|
|
2894
2916
|
aliases: ["mr", "make-repository", "make:repo"],
|
|
2895
2917
|
summary: "Generate a repository class",
|
|
2896
|
-
description: "Generates a
|
|
2918
|
+
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
2919
|
examples: [
|
|
2898
2920
|
"nx make:repository User",
|
|
2899
2921
|
"nx make:repository Post"
|
|
2900
2922
|
],
|
|
2923
|
+
flags: [
|
|
2924
|
+
{
|
|
2925
|
+
name: "orm",
|
|
2926
|
+
description: "Override ORM driver (drizzle|kysely)"
|
|
2927
|
+
}
|
|
2928
|
+
],
|
|
2901
2929
|
async run(ctx) {
|
|
2902
2930
|
const name = ctx.positional[0];
|
|
2903
2931
|
if (!name) {
|
|
2904
2932
|
logger.error("Usage: nx make:repository <Name>");
|
|
2905
2933
|
return 1;
|
|
2906
2934
|
}
|
|
2935
|
+
const orm = ctx.flags.orm ?? ctx.config.orm;
|
|
2907
2936
|
const variants = nameVariants(name);
|
|
2908
2937
|
const repository = `${variants.pascal}Repository`;
|
|
2909
|
-
const
|
|
2938
|
+
const tpl = orm === "kysely" ? templates.repository.kysely : templates.repository.drizzle;
|
|
2939
|
+
const code = render(tpl, {
|
|
2910
2940
|
name: variants.pascal,
|
|
2911
2941
|
camel: variants.camel,
|
|
2912
2942
|
kebab: variants.kebab,
|
|
2913
2943
|
snake: variants.snake,
|
|
2944
|
+
tableName: variants.pluralSnake,
|
|
2914
2945
|
repository
|
|
2915
2946
|
});
|
|
2916
2947
|
const out = resolve16(ctx.cwd, `${ctx.config.paths.app}/repositories`, `${variants.kebab}.repository.ts`);
|
|
@@ -3007,7 +3038,7 @@ var makeServiceCommand = {
|
|
|
3007
3038
|
const variants = nameVariants(name);
|
|
3008
3039
|
const hasRepo = ctx.flags["no-repo"] !== true && ctx.config.orm !== "none";
|
|
3009
3040
|
const repository = `${variants.pascal}Repository`;
|
|
3010
|
-
const repositoryCamel = variants.camel
|
|
3041
|
+
const repositoryCamel = `${variants.camel}Repository`;
|
|
3011
3042
|
const code = render(templates.service, {
|
|
3012
3043
|
name: variants.pascal,
|
|
3013
3044
|
camel: variants.camel,
|
|
@@ -3139,11 +3170,10 @@ var dbMigrateCommand = {
|
|
|
3139
3170
|
name: "db:migrate",
|
|
3140
3171
|
aliases: ["db:m", "migrate"],
|
|
3141
3172
|
summary: "Apply pending database migrations",
|
|
3142
|
-
description: "Runs the
|
|
3173
|
+
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
3174
|
examples: [
|
|
3144
3175
|
"nx db:migrate",
|
|
3145
3176
|
"nx db:migrate --status",
|
|
3146
|
-
"nx db:migrate --generate 'add_email_to_users'",
|
|
3147
3177
|
"nx db:migrate --folder ./drizzle"
|
|
3148
3178
|
],
|
|
3149
3179
|
flags: [
|
|
@@ -3151,39 +3181,34 @@ var dbMigrateCommand = {
|
|
|
3151
3181
|
name: "status",
|
|
3152
3182
|
description: "List applied migrations and exit (no apply)."
|
|
3153
3183
|
},
|
|
3154
|
-
{
|
|
3155
|
-
name: "generate",
|
|
3156
|
-
description: "Run `drizzle-kit generate` with the given migration name."
|
|
3157
|
-
},
|
|
3158
3184
|
{
|
|
3159
3185
|
name: "folder",
|
|
3160
3186
|
description: "Override migrations folder (default: from nx.config.ts)."
|
|
3161
3187
|
},
|
|
3162
3188
|
{
|
|
3163
3189
|
name: "dialect",
|
|
3164
|
-
description: "
|
|
3190
|
+
description: "Database dialect (postgres|mysql|sqlite|bun-sqlite). Default: bun-sqlite."
|
|
3165
3191
|
},
|
|
3166
3192
|
{
|
|
3167
3193
|
name: "config",
|
|
3168
3194
|
description: "Path to drizzle.config.ts. Default: ./drizzle.config.ts."
|
|
3195
|
+
},
|
|
3196
|
+
{
|
|
3197
|
+
name: "orm",
|
|
3198
|
+
description: "Override ORM driver (drizzle|kysely)"
|
|
3169
3199
|
}
|
|
3170
3200
|
],
|
|
3171
3201
|
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
|
-
]);
|
|
3202
|
+
const orm = ctx.flags.orm ?? ctx.config.orm;
|
|
3203
|
+
const folder = ctx.flags.folder ?? resolve21(ctx.cwd, ctx.config.paths.migrations);
|
|
3204
|
+
const dialect = ctx.flags.dialect ?? ctx.config.dialect ?? "bun-sqlite";
|
|
3205
|
+
const configPath = ctx.flags.config ?? resolve21(ctx.cwd, "drizzle.config.ts");
|
|
3206
|
+
const wantStatus = Boolean(ctx.flags.status);
|
|
3207
|
+
if (orm === "kysely") {
|
|
3208
|
+
return runKyselyMigrate(ctx.cwd, folder, dialect, wantStatus);
|
|
3184
3209
|
}
|
|
3185
3210
|
if (wantStatus) {
|
|
3186
|
-
return await runStatus(ctx.cwd, folder, dialect, ctx.config.database
|
|
3211
|
+
return await runStatus(ctx.cwd, folder, dialect, ctx.config.database.url);
|
|
3187
3212
|
}
|
|
3188
3213
|
return runDrizzleKit(ctx.cwd, [
|
|
3189
3214
|
"migrate",
|
|
@@ -3191,6 +3216,133 @@ var dbMigrateCommand = {
|
|
|
3191
3216
|
]);
|
|
3192
3217
|
}
|
|
3193
3218
|
};
|
|
3219
|
+
async function runKyselyMigrate(cwd, folder, dialect, statusOnly) {
|
|
3220
|
+
if (!existsSync5(folder)) {
|
|
3221
|
+
logger.warn(`migrations folder not found: ${folder}`);
|
|
3222
|
+
return 0;
|
|
3223
|
+
}
|
|
3224
|
+
const script = buildKyselyMigrateScript(folder, dialect, statusOnly);
|
|
3225
|
+
const tmpFile = resolve21(cwd, ".nx-kysely-migrate.mjs");
|
|
3226
|
+
const { writeFile: writeFile2, unlink } = await import("fs/promises");
|
|
3227
|
+
await writeFile2(tmpFile, script, "utf-8");
|
|
3228
|
+
try {
|
|
3229
|
+
const code = await new Promise((resP) => {
|
|
3230
|
+
const child = spawn("bun", [tmpFile], {
|
|
3231
|
+
cwd,
|
|
3232
|
+
stdio: "inherit",
|
|
3233
|
+
shell: process.platform === "win32"
|
|
3234
|
+
});
|
|
3235
|
+
child.on("exit", (c2) => resP(c2 ?? 0));
|
|
3236
|
+
child.on("error", () => resP(1));
|
|
3237
|
+
});
|
|
3238
|
+
return code;
|
|
3239
|
+
} finally {
|
|
3240
|
+
await unlink(tmpFile).catch(() => {});
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
function buildKyselyMigrateScript(folder, dialect, statusOnly) {
|
|
3244
|
+
const dialectSetup = buildDialectSetup(dialect);
|
|
3245
|
+
const tableName = "kysely_migration";
|
|
3246
|
+
return `
|
|
3247
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
3248
|
+
import { dirname, join } from "node:path";
|
|
3249
|
+
|
|
3250
|
+
const migrationsFolder = ${JSON.stringify(folder)};
|
|
3251
|
+
|
|
3252
|
+
// Build the Kysely instance with the configured dialect.
|
|
3253
|
+
${dialectSetup}
|
|
3254
|
+
|
|
3255
|
+
import {
|
|
3256
|
+
Kysely,
|
|
3257
|
+
Migrator,
|
|
3258
|
+
} from "kysely";
|
|
3259
|
+
|
|
3260
|
+
class FsMigrationProvider {
|
|
3261
|
+
async getMigrations() {
|
|
3262
|
+
const files = readdirSync(migrationsFolder)
|
|
3263
|
+
.filter((f) => f.endsWith(".ts") || f.endsWith(".js"))
|
|
3264
|
+
.sort();
|
|
3265
|
+
|
|
3266
|
+
const migrations = {};
|
|
3267
|
+
for (const file of files) {
|
|
3268
|
+
const name = file.replace(/\\.(ts|js)$/, "");
|
|
3269
|
+
const mod = await import(join(migrationsFolder, file));
|
|
3270
|
+
migrations[name] = {
|
|
3271
|
+
up: mod.up,
|
|
3272
|
+
down: mod.down,
|
|
3273
|
+
};
|
|
3274
|
+
}
|
|
3275
|
+
return migrations;
|
|
3276
|
+
}
|
|
3277
|
+
}
|
|
3278
|
+
|
|
3279
|
+
const db = new Kysely({ dialect });
|
|
3280
|
+
|
|
3281
|
+
const migrator = new Migrator({
|
|
3282
|
+
db,
|
|
3283
|
+
provider: new FsMigrationProvider(),
|
|
3284
|
+
migrationTableName: ${JSON.stringify(tableName)},
|
|
3285
|
+
});
|
|
3286
|
+
|
|
3287
|
+
${statusOnly ? `
|
|
3288
|
+
const { results } = await migrator.getMigrations();
|
|
3289
|
+
console.log("Migration status:");
|
|
3290
|
+
for (const r of results ?? []) {
|
|
3291
|
+
console.log(\` \${r.name}: \${r.status}\`);
|
|
3292
|
+
}
|
|
3293
|
+
` : `
|
|
3294
|
+
const { results, error } = await migrator.migrateToLatest();
|
|
3295
|
+
if (error) {
|
|
3296
|
+
console.error("Migration failed:", error);
|
|
3297
|
+
process.exit(1);
|
|
3298
|
+
}
|
|
3299
|
+
const applied = (results ?? []).filter((r) => r.status === "Success" || r.status === "MigratedAbove");
|
|
3300
|
+
console.log(\`Applied \${applied.length} migration(s)\`);
|
|
3301
|
+
for (const r of applied) {
|
|
3302
|
+
console.log(\` \u2713 \${r.migrationName}\`);
|
|
3303
|
+
}
|
|
3304
|
+
`}
|
|
3305
|
+
|
|
3306
|
+
await db.destroy();
|
|
3307
|
+
`;
|
|
3308
|
+
}
|
|
3309
|
+
function buildDialectSetup(dialect) {
|
|
3310
|
+
switch (dialect) {
|
|
3311
|
+
case "postgres":
|
|
3312
|
+
return `
|
|
3313
|
+
import { Pool } from "pg";
|
|
3314
|
+
import { PostgresDialect } from "kysely";
|
|
3315
|
+
const dialect = new PostgresDialect({
|
|
3316
|
+
pool: new Pool({ connectionString: process.env.DATABASE_URL ?? "" }),
|
|
3317
|
+
});
|
|
3318
|
+
`;
|
|
3319
|
+
case "mysql":
|
|
3320
|
+
return `
|
|
3321
|
+
import { createPool } from "mysql2";
|
|
3322
|
+
import { MysqlDialect } from "kysely";
|
|
3323
|
+
const dialect = new MysqlDialect({
|
|
3324
|
+
pool: createPool({ uri: process.env.DATABASE_URL ?? "" }),
|
|
3325
|
+
});
|
|
3326
|
+
`;
|
|
3327
|
+
case "bun-sqlite":
|
|
3328
|
+
default:
|
|
3329
|
+
return `
|
|
3330
|
+
import { Database } from "bun:sqlite";
|
|
3331
|
+
import { SqliteDialect } from "kysely";
|
|
3332
|
+
|
|
3333
|
+
// Patch .reader property for bun:sqlite compatibility with Kysely.
|
|
3334
|
+
const _db = new Database(process.env.DATABASE_URL ?? "app.db");
|
|
3335
|
+
const proto = Object.getPrototypeOf(_db);
|
|
3336
|
+
const _prepare = proto.prepare.bind(_db);
|
|
3337
|
+
_db.prepare = function(sql) {
|
|
3338
|
+
const stmt = _prepare(sql);
|
|
3339
|
+
Object.defineProperty(stmt, "reader", { value: /^\\s*(select|pragma|with|explain)\\b/i.test(sql) });
|
|
3340
|
+
return stmt;
|
|
3341
|
+
};
|
|
3342
|
+
const dialect = new SqliteDialect({ database: _db });
|
|
3343
|
+
`;
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3194
3346
|
function runDrizzleKit(cwd, args2) {
|
|
3195
3347
|
return new Promise((resolveP) => {
|
|
3196
3348
|
const cmd = "bunx";
|
|
@@ -3249,7 +3401,7 @@ await svc.close();
|
|
|
3249
3401
|
}
|
|
3250
3402
|
}
|
|
3251
3403
|
function readEnvUrl(dialect) {
|
|
3252
|
-
const url = process.env
|
|
3404
|
+
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
3405
|
return url ?? null;
|
|
3254
3406
|
}
|
|
3255
3407
|
var db_migrate_default = dbMigrateCommand;
|
|
@@ -3260,7 +3412,7 @@ var dbGenerateCommand = {
|
|
|
3260
3412
|
name: "db:generate",
|
|
3261
3413
|
aliases: ["db:g", "db-generate", "generate-migration"],
|
|
3262
3414
|
summary: "Generate a new migration from schema changes",
|
|
3263
|
-
description: "Generates a new migration file
|
|
3415
|
+
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
3416
|
examples: [
|
|
3265
3417
|
"nx db:generate",
|
|
3266
3418
|
"nx db:generate add_users_table",
|
|
@@ -3274,12 +3426,17 @@ var dbGenerateCommand = {
|
|
|
3274
3426
|
{
|
|
3275
3427
|
name: "sql",
|
|
3276
3428
|
description: "Generate a raw SQL file instead of using drizzle-kit"
|
|
3429
|
+
},
|
|
3430
|
+
{
|
|
3431
|
+
name: "orm",
|
|
3432
|
+
description: "Override ORM driver (drizzle|kysely)"
|
|
3277
3433
|
}
|
|
3278
3434
|
],
|
|
3279
3435
|
async run(ctx) {
|
|
3280
3436
|
const name = ctx.positional[0];
|
|
3281
|
-
const
|
|
3282
|
-
const
|
|
3437
|
+
const orm = ctx.flags.orm ?? ctx.config.orm;
|
|
3438
|
+
const dialect = ctx.flags.dialect ?? ctx.config.dialect ?? "bun-sqlite";
|
|
3439
|
+
const isSql = ctx.flags.sql === true;
|
|
3283
3440
|
if (isSql) {
|
|
3284
3441
|
if (!name) {
|
|
3285
3442
|
logger.error("Usage: nx db:generate <name> --sql");
|
|
@@ -3288,6 +3445,14 @@ var dbGenerateCommand = {
|
|
|
3288
3445
|
logger.info(`Generating raw SQL migration: ${name} (dialect=${dialect})`);
|
|
3289
3446
|
return runSqlTemplate(ctx.cwd, name, dialect);
|
|
3290
3447
|
}
|
|
3448
|
+
if (orm === "kysely") {
|
|
3449
|
+
if (!name) {
|
|
3450
|
+
logger.error("Usage: nx db:generate <name> (name is required for Kysely)");
|
|
3451
|
+
return 1;
|
|
3452
|
+
}
|
|
3453
|
+
logger.info(`Generating Kysely migration: ${name}`);
|
|
3454
|
+
return runKyselyTemplate(ctx.cwd, name, dialect);
|
|
3455
|
+
}
|
|
3291
3456
|
const configPath = resolve22(ctx.cwd, "drizzle.config.ts");
|
|
3292
3457
|
const args2 = ["generate", "--config", configPath];
|
|
3293
3458
|
if (name)
|
|
@@ -3296,6 +3461,28 @@ var dbGenerateCommand = {
|
|
|
3296
3461
|
return runDrizzleKit(ctx.cwd, args2);
|
|
3297
3462
|
}
|
|
3298
3463
|
};
|
|
3464
|
+
async function runKyselyTemplate(cwd, name, _dialect) {
|
|
3465
|
+
const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync4 } = await import("fs");
|
|
3466
|
+
const { join } = await import("path");
|
|
3467
|
+
const migrationsDir = join(cwd, "app", "database", "migrations");
|
|
3468
|
+
mkdirSync5(migrationsDir, { recursive: true });
|
|
3469
|
+
const variants = nameVariants(name);
|
|
3470
|
+
const timestamp = formatTimestamp2(new Date);
|
|
3471
|
+
const filename = `${timestamp}_${variants.snake}.ts`;
|
|
3472
|
+
const filepath = join(migrationsDir, filename);
|
|
3473
|
+
const tpl = templates.migration.kysely;
|
|
3474
|
+
const code = render(tpl, {
|
|
3475
|
+
name: variants.pascal,
|
|
3476
|
+
snake: variants.snake,
|
|
3477
|
+
tableName: inferTableName2(name),
|
|
3478
|
+
columns: "",
|
|
3479
|
+
timestamp
|
|
3480
|
+
});
|
|
3481
|
+
writeFileSync4(filepath, code);
|
|
3482
|
+
logger.success(`created ${filepath}`);
|
|
3483
|
+
logger.info("Edit the migration, then run `nx db:migrate` to apply it.");
|
|
3484
|
+
return 0;
|
|
3485
|
+
}
|
|
3299
3486
|
async function runSqlTemplate(cwd, name, dialect) {
|
|
3300
3487
|
const { mkdirSync: mkdirSync5, writeFileSync: writeFileSync4 } = await import("fs");
|
|
3301
3488
|
const { join } = await import("path");
|
|
@@ -3318,6 +3505,19 @@ async function runSqlTemplate(cwd, name, dialect) {
|
|
|
3318
3505
|
logger.info("Edit the SQL file, then run `nx db:migrate` to apply it.");
|
|
3319
3506
|
return 0;
|
|
3320
3507
|
}
|
|
3508
|
+
function inferTableName2(input) {
|
|
3509
|
+
const m = /^create_(\w+)_table$/.exec(input);
|
|
3510
|
+
if (m)
|
|
3511
|
+
return m[1] ?? "";
|
|
3512
|
+
const m2 = /^(?:add|remove|drop|alter)_(\w+)_to_(\w+)$/.exec(input);
|
|
3513
|
+
if (m2)
|
|
3514
|
+
return m2[2] ?? "";
|
|
3515
|
+
return `${input.toLowerCase().replace(/s$/, "")}s`;
|
|
3516
|
+
}
|
|
3517
|
+
function formatTimestamp2(d) {
|
|
3518
|
+
const pad = (n) => String(n).padStart(2, "0");
|
|
3519
|
+
return `${d.getFullYear()}${pad(d.getMonth() + 1)}${pad(d.getDate())}_${pad(d.getHours())}${pad(d.getMinutes())}${pad(d.getSeconds())}`;
|
|
3520
|
+
}
|
|
3321
3521
|
var db_generate_default = dbGenerateCommand;
|
|
3322
3522
|
|
|
3323
3523
|
// packages/cli/src/commands/db-seed.ts
|
|
@@ -3394,11 +3594,11 @@ var dbSeedCommand = {
|
|
|
3394
3594
|
}
|
|
3395
3595
|
],
|
|
3396
3596
|
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
|
|
3597
|
+
const folder = resolve23(ctx.cwd, ctx.flags.folder ?? ctx.config.paths?.seeds ?? "db/seeds");
|
|
3598
|
+
const dialect = ctx.flags.dialect ?? ctx.config.dialect ?? "bun-sqlite";
|
|
3599
|
+
const createName = ctx.flags.create;
|
|
3600
|
+
const fileName = ctx.flags.file;
|
|
3601
|
+
const reset = Boolean(ctx.flags.reset);
|
|
3402
3602
|
if (createName) {
|
|
3403
3603
|
return await createSeedFile(folder, createName);
|
|
3404
3604
|
}
|
|
@@ -3515,7 +3715,7 @@ async function createSeedFile(folder, name) {
|
|
|
3515
3715
|
return 0;
|
|
3516
3716
|
}
|
|
3517
3717
|
function readEnvUrl2(dialect) {
|
|
3518
|
-
const url = process.env
|
|
3718
|
+
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
3719
|
return url ?? null;
|
|
3520
3720
|
}
|
|
3521
3721
|
var db_seed_default = dbSeedCommand;
|
|
@@ -3526,7 +3726,7 @@ import { resolve as resolve24 } from "path";
|
|
|
3526
3726
|
var VALID_OPTIONS2 = {
|
|
3527
3727
|
style: ["nest", "adonis", "functional"],
|
|
3528
3728
|
view: ["rendu", "edge", "eta", "inertia", "none"],
|
|
3529
|
-
orm: ["drizzle", "
|
|
3729
|
+
orm: ["drizzle", "kysely", "none"],
|
|
3530
3730
|
db: ["bun-sqlite", "node-sqlite", "libsql", "postgres", "mysql", "none"],
|
|
3531
3731
|
frontend: ["react", "vue", "svelte", "solid"]
|
|
3532
3732
|
};
|
|
@@ -3561,7 +3761,7 @@ var newCommand = {
|
|
|
3561
3761
|
flags: [
|
|
3562
3762
|
{ name: "style", description: "Routing style (nest|adonis|functional)" },
|
|
3563
3763
|
{ name: "view", description: "View engine (rendu|edge|eta|inertia|none)" },
|
|
3564
|
-
{ name: "orm", description: "ORM driver (drizzle|
|
|
3764
|
+
{ name: "orm", description: "ORM driver (drizzle|kysely|none)" },
|
|
3565
3765
|
{ name: "db", description: "Database driver" },
|
|
3566
3766
|
{ name: "frontend", description: "Inertia frontend (react|vue|svelte|solid)" },
|
|
3567
3767
|
{ name: "no-ssr", description: "Disable SSR" }
|
|
@@ -3720,7 +3920,7 @@ var configCommand = {
|
|
|
3720
3920
|
name: "view-paths",
|
|
3721
3921
|
description: "Comma-separated directories searched for view files (e.g. resources/views)"
|
|
3722
3922
|
},
|
|
3723
|
-
{ name: "orm", description: "ORM driver (drizzle|
|
|
3923
|
+
{ name: "orm", description: "ORM driver (drizzle|kysely|none)" },
|
|
3724
3924
|
{
|
|
3725
3925
|
name: "db",
|
|
3726
3926
|
description: "Database driver (bun-sqlite|node-sqlite|libsql|postgres|mysql|none)"
|
|
@@ -3741,7 +3941,7 @@ var configCommand = {
|
|
|
3741
3941
|
async run(ctx) {
|
|
3742
3942
|
const interactive = !flagBool(ctx.flags, "no-interaction", false);
|
|
3743
3943
|
const force = flagBool(ctx.flags, "force", false);
|
|
3744
|
-
const target = resolve25(ctx.cwd, ctx.flags
|
|
3944
|
+
const target = resolve25(ctx.cwd, ctx.flags.target ?? ".");
|
|
3745
3945
|
if (!existsSync8(target)) {
|
|
3746
3946
|
logger.error(`Target directory does not exist: ${target}`);
|
|
3747
3947
|
return 1;
|
|
@@ -3750,21 +3950,27 @@ var configCommand = {
|
|
|
3750
3950
|
const values = parseExistingConfig(nxConfigPath);
|
|
3751
3951
|
const flag = (k) => ctx.flags[k];
|
|
3752
3952
|
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.
|
|
3953
|
+
const style = flag("style");
|
|
3954
|
+
if (style)
|
|
3955
|
+
values.routing = style;
|
|
3956
|
+
const view = flag("view");
|
|
3957
|
+
if (view)
|
|
3958
|
+
values.view = view;
|
|
3959
|
+
const viewPaths = flag("view-paths");
|
|
3960
|
+
if (viewPaths)
|
|
3961
|
+
values.viewPaths = viewPaths;
|
|
3962
|
+
const orm = flag("orm");
|
|
3963
|
+
if (orm)
|
|
3964
|
+
values.orm = orm;
|
|
3965
|
+
const db = flag("db");
|
|
3966
|
+
if (db)
|
|
3967
|
+
values.dbDriver = db;
|
|
3968
|
+
const dbUrl = flag("db-url");
|
|
3969
|
+
if (dbUrl !== undefined)
|
|
3970
|
+
values.dbUrl = dbUrl;
|
|
3971
|
+
const frontend = flag("frontend");
|
|
3972
|
+
if (frontend)
|
|
3973
|
+
values.inertiaFrontend = frontend;
|
|
3768
3974
|
if (flagBoolStrict("ssr", false))
|
|
3769
3975
|
values.inertiaSSR = true;
|
|
3770
3976
|
if (flagBoolStrict("no-ssr", false))
|
|
@@ -3779,7 +3985,7 @@ var configCommand = {
|
|
|
3779
3985
|
interactive,
|
|
3780
3986
|
default: values.view
|
|
3781
3987
|
}) ?? values.view;
|
|
3782
|
-
values.orm = await select("ORM driver", ["drizzle", "
|
|
3988
|
+
values.orm = await select("ORM driver", ["drizzle", "kysely", "none"], {
|
|
3783
3989
|
interactive,
|
|
3784
3990
|
default: values.orm
|
|
3785
3991
|
}) ?? values.orm;
|
|
@@ -3804,12 +4010,12 @@ var configCommand = {
|
|
|
3804
4010
|
const drizzleConfigPath = resolve25(target, "drizzle.config.ts");
|
|
3805
4011
|
if (values.orm === "drizzle") {
|
|
3806
4012
|
const dialect = driverToDialect(values.dbDriver);
|
|
3807
|
-
const
|
|
4013
|
+
const dbUrl2 = values.dbUrl;
|
|
3808
4014
|
const existedDrizzle = existsSync8(drizzleConfigPath);
|
|
3809
4015
|
if (existedDrizzle && !force && !anyFlag) {
|
|
3810
4016
|
logger.info(` - drizzle.config.ts (unchanged; pass --force or a flag to update)`);
|
|
3811
4017
|
} else {
|
|
3812
|
-
writeDrizzleConfig(target, { dialect, dbUrl });
|
|
4018
|
+
writeDrizzleConfig(target, { dialect, dbUrl: dbUrl2 });
|
|
3813
4019
|
logger.info(` ${existedDrizzle ? "~" : "+"} drizzle.config.ts`);
|
|
3814
4020
|
}
|
|
3815
4021
|
} else if (existsSync8(drizzleConfigPath)) {
|
|
@@ -3924,9 +4130,9 @@ var replCommand = {
|
|
|
3924
4130
|
}
|
|
3925
4131
|
],
|
|
3926
4132
|
async run(ctx) {
|
|
3927
|
-
const mod = ctx.flags
|
|
4133
|
+
const mod = ctx.flags.module;
|
|
3928
4134
|
const noBoot = Boolean(ctx.flags["no-boot"]);
|
|
3929
|
-
const histPath = resolve26(ctx.cwd, ctx.flags
|
|
4135
|
+
const histPath = resolve26(ctx.cwd, ctx.flags.history ?? ".nx-repl-history");
|
|
3930
4136
|
const env = { console };
|
|
3931
4137
|
if (!noBoot) {
|
|
3932
4138
|
const modPath = resolve26(ctx.cwd, mod ?? "app/app.module.ts");
|
|
@@ -4037,7 +4243,7 @@ var replCommand = {
|
|
|
4037
4243
|
case ".routes": {
|
|
4038
4244
|
const app = env.app;
|
|
4039
4245
|
const getRoutes = app?.server?.router?.getRoutes;
|
|
4040
|
-
const raw = typeof getRoutes === "function" ? getRoutes.call(app
|
|
4246
|
+
const raw = typeof getRoutes === "function" ? getRoutes.call(app?.server?.router) : [];
|
|
4041
4247
|
const seen = new Set;
|
|
4042
4248
|
const routes = raw.filter((r) => {
|
|
4043
4249
|
const key = `${r.method}:${r.path}:${r.target?.name ?? ""}:${typeof r.propertyKey === "symbol" ? r.propertyKey.description ?? "" : String(r.propertyKey)}`;
|
|
@@ -4087,7 +4293,7 @@ var replCommand = {
|
|
|
4087
4293
|
if (trimmed.startsWith(".")) {
|
|
4088
4294
|
await handleDotCommand(trimmed);
|
|
4089
4295
|
} else {
|
|
4090
|
-
buffer += line
|
|
4296
|
+
buffer += `${line}
|
|
4091
4297
|
`;
|
|
4092
4298
|
if (isIncomplete(buffer)) {
|
|
4093
4299
|
rl.setPrompt("... ");
|
|
@@ -4300,14 +4506,14 @@ var routeListCommand = {
|
|
|
4300
4506
|
}
|
|
4301
4507
|
}
|
|
4302
4508
|
} catch (err) {
|
|
4303
|
-
logger.warn(`could not parse ${file}: ${err.message
|
|
4509
|
+
logger.warn(`could not parse ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
4304
4510
|
}
|
|
4305
4511
|
}
|
|
4306
4512
|
if (routes.length === 0) {
|
|
4307
4513
|
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
4514
|
return 0;
|
|
4309
4515
|
}
|
|
4310
|
-
const format = ctx.flags
|
|
4516
|
+
const format = ctx.flags.format ?? "table";
|
|
4311
4517
|
if (format === "json") {
|
|
4312
4518
|
console.log(JSON.stringify(routes, null, 2));
|
|
4313
4519
|
return 0;
|
|
@@ -4378,11 +4584,11 @@ async function main() {
|
|
|
4378
4584
|
const parsed = parseArgs(process.argv.slice(2));
|
|
4379
4585
|
const verbose = flagBool(parsed.flags, "verbose", false);
|
|
4380
4586
|
logger.setVerbose(verbose);
|
|
4381
|
-
if (parsed.flags
|
|
4587
|
+
if (parsed.flags.version === true) {
|
|
4382
4588
|
console.log(PKG_VERSION);
|
|
4383
4589
|
return 0;
|
|
4384
4590
|
}
|
|
4385
|
-
if (parsed.flags
|
|
4591
|
+
if (parsed.flags.help === true || parsed.command === "help") {
|
|
4386
4592
|
return renderHelp(parsed.positional[0]);
|
|
4387
4593
|
}
|
|
4388
4594
|
const command = parsed.command ? findCommand(parsed.command) : undefined;
|
|
@@ -4476,11 +4682,11 @@ Examples`));
|
|
|
4476
4682
|
var PKG_VERSION = "0.1.0";
|
|
4477
4683
|
main().then((code) => process.exit(code)).catch((err) => {
|
|
4478
4684
|
logger.error(err?.message ?? String(err));
|
|
4479
|
-
if (process.env
|
|
4685
|
+
if (process.env.NX_DEBUG === "1" && err?.stack) {
|
|
4480
4686
|
console.error(err.stack);
|
|
4481
4687
|
}
|
|
4482
4688
|
process.exit(1);
|
|
4483
4689
|
});
|
|
4484
4690
|
|
|
4485
|
-
//# debugId=
|
|
4691
|
+
//# debugId=DCF6821370D4409A64756E2164756E21
|
|
4486
4692
|
//# sourceMappingURL=index.js.map
|