@simple-auth-kit/cli 1.4.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/registry/combos/express-drizzle/shared/src/{auth-core-error.middleware.ts → middleware/auth-core-error.middleware.ts} +17 -4
- package/registry/combos/express-drizzle/shared/src/{auth.middleware.ts → middleware/auth.middleware.ts} +23 -7
- package/registry/combos/{express-prisma/shared/src → express-drizzle/shared/src/middleware}/response-envelope.middleware.ts +15 -3
- package/registry/combos/express-drizzle/shared/src/{oauth.repository.ts → repositories/oauth.repository.ts} +32 -9
- package/registry/combos/express-drizzle/shared/src/repositories/password-reset.repository.ts +59 -0
- package/registry/combos/express-drizzle/shared/src/{session.repository.ts → repositories/session.repository.ts} +52 -14
- package/registry/combos/express-drizzle/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +20 -6
- package/registry/combos/express-drizzle/shared/src/request-context.ts +1 -1
- package/registry/combos/express-drizzle/shared/src/routers/auth.router.ts +395 -0
- package/registry/combos/express-drizzle/variants/base/src/create-auth-app.ts +52 -19
- package/registry/combos/express-drizzle/variants/base/src/{authz.middleware.ts → middleware/authz.middleware.ts} +15 -7
- package/registry/combos/express-drizzle/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +28 -10
- package/registry/combos/express-drizzle/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +239 -48
- package/registry/combos/express-drizzle/variants/base/src/routers/admin.router.ts +497 -0
- package/registry/combos/express-drizzle/variants/base/src/{auth.service.ts → services/auth.service.ts} +480 -109
- package/registry/combos/express-drizzle/variants/workspaces/src/create-auth-app.ts +69 -23
- package/registry/combos/express-drizzle/variants/workspaces/src/{authz.middleware.ts → middleware/authz.middleware.ts} +32 -12
- package/registry/combos/express-drizzle/variants/workspaces/src/openapi-workspace.ts +147 -28
- package/registry/combos/express-drizzle/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +30 -11
- package/registry/combos/express-drizzle/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +319 -70
- package/registry/combos/express-drizzle/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +127 -30
- package/registry/combos/express-drizzle/variants/workspaces/src/routers/admin.router.ts +534 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/routers/workspace.router.ts +194 -0
- package/registry/combos/express-drizzle/variants/workspaces/src/{auth.service.ts → services/auth.service.ts} +544 -122
- package/registry/combos/express-prisma/shared/src/{auth-core-error.middleware.ts → middleware/auth-core-error.middleware.ts} +17 -4
- package/registry/combos/express-prisma/shared/src/{auth.middleware.ts → middleware/auth.middleware.ts} +19 -6
- package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/middleware}/response-envelope.middleware.ts +15 -3
- package/registry/combos/express-prisma/shared/src/{oauth.repository.ts → repositories/oauth.repository.ts} +27 -9
- package/registry/combos/express-prisma/shared/src/repositories/password-reset.repository.ts +55 -0
- package/registry/combos/express-prisma/shared/src/{session.repository.ts → repositories/session.repository.ts} +30 -9
- package/registry/combos/express-prisma/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +11 -4
- package/registry/combos/express-prisma/shared/src/request-context.ts +1 -1
- package/registry/combos/express-prisma/shared/src/routers/auth.router.ts +398 -0
- package/registry/combos/express-prisma/variants/base/src/create-auth-app.ts +57 -22
- package/registry/combos/express-prisma/variants/base/src/{authz.middleware.ts → middleware/authz.middleware.ts} +15 -7
- package/registry/combos/express-prisma/variants/base/src/rbac.defaults.ts +67 -19
- package/registry/combos/express-prisma/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
- package/registry/combos/express-prisma/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +199 -48
- package/registry/combos/express-prisma/variants/base/src/routers/admin.router.ts +508 -0
- package/registry/combos/express-prisma/variants/base/src/seed.ts +78 -20
- package/registry/combos/express-prisma/variants/base/src/{auth.service.ts → services/auth.service.ts} +454 -105
- package/registry/combos/express-prisma/variants/workspaces/src/create-auth-app.ts +81 -26
- package/registry/combos/express-prisma/variants/workspaces/src/{authz.middleware.ts → middleware/authz.middleware.ts} +32 -12
- package/registry/combos/express-prisma/variants/workspaces/src/openapi-workspace.ts +147 -28
- package/registry/combos/express-prisma/variants/workspaces/src/rbac.defaults.ts +73 -21
- package/registry/combos/express-prisma/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
- package/registry/combos/express-prisma/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +272 -64
- package/registry/combos/express-prisma/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +86 -23
- package/registry/combos/express-prisma/variants/workspaces/src/routers/admin.router.ts +545 -0
- package/registry/combos/express-prisma/variants/workspaces/src/routers/workspace.router.ts +194 -0
- package/registry/combos/express-prisma/variants/workspaces/src/seed.ts +109 -29
- package/registry/combos/express-prisma/variants/workspaces/src/{auth.service.ts → services/auth.service.ts} +518 -119
- package/registry/combos/nestjs-drizzle/shared/src/{auth.controller.ts → controllers/auth.controller.ts} +6 -6
- package/registry/combos/nestjs-drizzle/shared/src/{auth-core-error.filter.ts → filters/auth-core-error.filter.ts} +29 -5
- package/registry/combos/nestjs-drizzle/shared/src/{ability.guard.ts → guards/ability.guard.ts} +20 -7
- package/registry/combos/nestjs-drizzle/shared/src/{auth.guard.ts → guards/auth.guard.ts} +19 -7
- package/registry/combos/{nestjs-prisma/shared/src → nestjs-drizzle/shared/src/interceptors}/response.interceptor.ts +10 -2
- package/registry/combos/nestjs-drizzle/shared/src/repositories/oauth.repository.ts +63 -0
- package/registry/combos/nestjs-drizzle/shared/src/repositories/password-reset.repository.ts +59 -0
- package/registry/combos/nestjs-drizzle/shared/src/{session.repository.ts → repositories/session.repository.ts} +52 -14
- package/registry/combos/nestjs-drizzle/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +21 -7
- package/registry/combos/nestjs-drizzle/shared/src/request-context.ts +1 -1
- package/registry/combos/nestjs-drizzle/test/prove-cycle.ts +1097 -307
- package/registry/combos/nestjs-drizzle/variants/base/src/auth.module.ts +44 -20
- package/registry/combos/nestjs-drizzle/variants/base/src/{admin.controller.ts → controllers/admin.controller.ts} +228 -62
- package/registry/combos/nestjs-drizzle/variants/base/src/{authz.guard.ts → guards/authz.guard.ts} +12 -5
- package/registry/combos/nestjs-drizzle/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +27 -10
- package/registry/combos/nestjs-drizzle/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +249 -51
- package/registry/combos/nestjs-drizzle/variants/base/src/{auth.service.ts → services/auth.service.ts} +499 -116
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.module.ts +48 -22
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/{admin.controller.ts → controllers/admin.controller.ts} +269 -70
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/{workspace.controller.ts → controllers/workspace.controller.ts} +93 -26
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/{authz.guard.ts → guards/authz.guard.ts} +26 -8
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +29 -11
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +323 -71
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +131 -30
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/services/auth.service.ts +988 -0
- package/registry/combos/nestjs-prisma/shared/src/{auth.controller.ts → controllers/auth.controller.ts} +6 -6
- package/registry/combos/nestjs-prisma/shared/src/{auth-core-error.filter.ts → filters/auth-core-error.filter.ts} +29 -5
- package/registry/combos/nestjs-prisma/shared/src/{ability.guard.ts → guards/ability.guard.ts} +20 -7
- package/registry/combos/nestjs-prisma/shared/src/{auth.guard.ts → guards/auth.guard.ts} +19 -7
- package/registry/combos/{nestjs-drizzle/shared/src → nestjs-prisma/shared/src/interceptors}/response.interceptor.ts +10 -2
- package/registry/combos/nestjs-prisma/shared/src/{oauth.repository.ts → repositories/oauth.repository.ts} +25 -8
- package/registry/combos/nestjs-prisma/shared/src/repositories/password-reset.repository.ts +55 -0
- package/registry/combos/nestjs-prisma/shared/src/{session.repository.ts → repositories/session.repository.ts} +30 -9
- package/registry/combos/nestjs-prisma/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +11 -4
- package/registry/combos/nestjs-prisma/shared/src/request-context.ts +1 -1
- package/registry/combos/nestjs-prisma/test/prove-cycle.ts +1097 -307
- package/registry/combos/nestjs-prisma/variants/base/src/auth.module.ts +59 -28
- package/registry/combos/nestjs-prisma/variants/base/src/{admin.controller.ts → controllers/admin.controller.ts} +469 -110
- package/registry/combos/nestjs-prisma/variants/base/src/{audit-log.gateway.ts → gateways/audit-log.gateway.ts} +22 -6
- package/registry/combos/nestjs-prisma/variants/base/src/{authz.guard.ts → guards/authz.guard.ts} +12 -5
- package/registry/combos/nestjs-prisma/variants/base/src/rbac.defaults.ts +98 -27
- package/registry/combos/nestjs-prisma/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
- package/registry/combos/nestjs-prisma/variants/base/src/{country.repository.ts → repositories/country.repository.ts} +98 -25
- package/registry/combos/nestjs-prisma/variants/base/src/{customer.repository.ts → repositories/customer.repository.ts} +106 -27
- package/registry/combos/nestjs-prisma/variants/base/src/{language.repository.ts → repositories/language.repository.ts} +93 -25
- package/registry/combos/nestjs-prisma/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +229 -55
- package/registry/combos/nestjs-prisma/variants/base/src/seed.ts +78 -20
- package/registry/combos/nestjs-prisma/variants/base/src/services/auth.service.ts +1064 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.module.ts +55 -27
- package/registry/combos/nestjs-prisma/variants/workspaces/src/{admin.controller.ts → controllers/admin.controller.ts} +544 -128
- package/registry/combos/nestjs-prisma/variants/workspaces/src/{workspace.controller.ts → controllers/workspace.controller.ts} +93 -26
- package/registry/combos/nestjs-prisma/variants/workspaces/src/{authz.guard.ts → guards/authz.guard.ts} +26 -8
- package/registry/combos/nestjs-prisma/variants/workspaces/src/rbac.defaults.ts +104 -29
- package/registry/combos/nestjs-prisma/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
- package/registry/combos/nestjs-prisma/variants/workspaces/src/{country.repository.ts → repositories/country.repository.ts} +127 -26
- package/registry/combos/nestjs-prisma/variants/workspaces/src/{customer.repository.ts → repositories/customer.repository.ts} +137 -28
- package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/language.repository.ts +243 -0
- package/registry/combos/nestjs-prisma/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +314 -74
- package/registry/combos/nestjs-prisma/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +94 -24
- package/registry/combos/nestjs-prisma/variants/workspaces/src/seed.ts +109 -29
- package/registry/combos/nestjs-prisma/variants/workspaces/src/services/auth.service.ts +961 -0
- package/registry.json +6 -4
- package/simple-auth-kit.ts +582 -124
- package/registry/combos/express-drizzle/shared/src/auth.router.ts +0 -266
- package/registry/combos/express-drizzle/shared/src/password-reset.repository.ts +0 -35
- package/registry/combos/express-drizzle/variants/base/src/admin.router.ts +0 -307
- package/registry/combos/express-drizzle/variants/workspaces/src/admin.router.ts +0 -323
- package/registry/combos/express-drizzle/variants/workspaces/src/workspace.router.ts +0 -123
- package/registry/combos/express-prisma/shared/src/auth.router.ts +0 -269
- package/registry/combos/express-prisma/shared/src/password-reset.repository.ts +0 -29
- package/registry/combos/express-prisma/variants/base/src/admin.router.ts +0 -314
- package/registry/combos/express-prisma/variants/workspaces/src/admin.router.ts +0 -330
- package/registry/combos/express-prisma/variants/workspaces/src/workspace.router.ts +0 -123
- package/registry/combos/nestjs-drizzle/shared/src/oauth.repository.ts +0 -36
- package/registry/combos/nestjs-drizzle/shared/src/password-reset.repository.ts +0 -29
- package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.service.ts +0 -553
- package/registry/combos/nestjs-prisma/shared/src/password-reset.repository.ts +0 -29
- package/registry/combos/nestjs-prisma/variants/base/src/auth.service.ts +0 -618
- package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.service.ts +0 -509
- package/registry/combos/nestjs-prisma/variants/workspaces/src/language.repository.ts +0 -143
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
ConflictException,
|
|
3
|
+
Inject,
|
|
4
|
+
Injectable,
|
|
5
|
+
NotFoundException,
|
|
6
|
+
} from "@nestjs/common";
|
|
7
|
+
import { Prisma, PrismaClient } from "../../generated/prisma/client.js";
|
|
8
|
+
import { toId, toIdOrNull } from "../id.helper.js";
|
|
9
|
+
import {
|
|
10
|
+
buildPageMeta,
|
|
11
|
+
normalizeLimit,
|
|
12
|
+
normalizePage,
|
|
13
|
+
type Paginated,
|
|
14
|
+
} from "../pagination.js";
|
|
5
15
|
|
|
6
16
|
/** A `Customer` row as `findUnique`/`findMany` return it. */
|
|
7
17
|
export type CustomerRow = Prisma.CustomerGetPayload<object>;
|
|
@@ -78,11 +88,22 @@ export interface CustomerInput {
|
|
|
78
88
|
isActive?: boolean;
|
|
79
89
|
}
|
|
80
90
|
|
|
81
|
-
function toPrismaInput(
|
|
91
|
+
function toPrismaInput(
|
|
92
|
+
input: Partial<CustomerInput>,
|
|
93
|
+
): Omit<Partial<CustomerInput>, "dob" | "joinedDate"> & {
|
|
94
|
+
dob?: Date | null;
|
|
95
|
+
joinedDate?: Date;
|
|
96
|
+
} {
|
|
82
97
|
return {
|
|
83
98
|
...input,
|
|
84
|
-
dob:
|
|
85
|
-
|
|
99
|
+
dob:
|
|
100
|
+
input.dob === undefined
|
|
101
|
+
? undefined
|
|
102
|
+
: input.dob === null
|
|
103
|
+
? null
|
|
104
|
+
: new Date(input.dob),
|
|
105
|
+
joinedDate:
|
|
106
|
+
input.joinedDate === undefined ? undefined : new Date(input.joinedDate),
|
|
86
107
|
};
|
|
87
108
|
}
|
|
88
109
|
|
|
@@ -109,37 +130,71 @@ export class CustomerRepository {
|
|
|
109
130
|
};
|
|
110
131
|
|
|
111
132
|
const [rows, total] = await this.prisma.$transaction([
|
|
112
|
-
this.prisma.customer.findMany({
|
|
133
|
+
this.prisma.customer.findMany({
|
|
134
|
+
where,
|
|
135
|
+
orderBy: [{ createdAt: "desc" }, { id: "desc" }],
|
|
136
|
+
take: limit,
|
|
137
|
+
skip: (page - 1) * limit,
|
|
138
|
+
}),
|
|
113
139
|
this.prisma.customer.count({ where }),
|
|
114
140
|
]);
|
|
115
141
|
|
|
116
|
-
return {
|
|
142
|
+
return {
|
|
143
|
+
items: rows.map(toCustomerSummary),
|
|
144
|
+
meta: buildPageMeta(page, limit, total),
|
|
145
|
+
};
|
|
117
146
|
}
|
|
118
147
|
|
|
119
148
|
async get(customerId: string): Promise<CustomerSummary> {
|
|
120
|
-
const row = await this.prisma.customer.findUnique({
|
|
149
|
+
const row = await this.prisma.customer.findUnique({
|
|
150
|
+
where: { id: toId(customerId), isDeleted: false },
|
|
151
|
+
});
|
|
121
152
|
if (!row) throw new NotFoundException(`customer "${customerId}" not found`);
|
|
122
153
|
return toCustomerSummary(row);
|
|
123
154
|
}
|
|
124
155
|
|
|
125
|
-
async create(
|
|
126
|
-
|
|
127
|
-
|
|
156
|
+
async create(
|
|
157
|
+
input: CustomerInput,
|
|
158
|
+
actorUserId: string | null,
|
|
159
|
+
): Promise<CustomerSummary> {
|
|
160
|
+
const existing = await this.prisma.customer.findUnique({
|
|
161
|
+
where: { email: input.email },
|
|
162
|
+
});
|
|
163
|
+
if (existing)
|
|
164
|
+
throw new ConflictException("a customer with this email already exists");
|
|
128
165
|
|
|
129
166
|
const row = await this.prisma.customer.create({
|
|
130
|
-
data: {
|
|
167
|
+
data: {
|
|
168
|
+
...toPrismaInput(input),
|
|
169
|
+
email: input.email,
|
|
170
|
+
createdBy: toIdOrNull(actorUserId),
|
|
171
|
+
updatedBy: toIdOrNull(actorUserId),
|
|
172
|
+
},
|
|
131
173
|
});
|
|
132
174
|
return toCustomerSummary(row);
|
|
133
175
|
}
|
|
134
176
|
|
|
135
|
-
async update(
|
|
177
|
+
async update(
|
|
178
|
+
customerId: string,
|
|
179
|
+
input: Partial<CustomerInput>,
|
|
180
|
+
actorUserId: string | null,
|
|
181
|
+
): Promise<CustomerSummary> {
|
|
136
182
|
const customerIdBig = toId(customerId);
|
|
137
|
-
const existing = await this.prisma.customer.findUnique({
|
|
138
|
-
|
|
183
|
+
const existing = await this.prisma.customer.findUnique({
|
|
184
|
+
where: { id: customerIdBig, isDeleted: false },
|
|
185
|
+
select: { id: true },
|
|
186
|
+
});
|
|
187
|
+
if (!existing)
|
|
188
|
+
throw new NotFoundException(`customer "${customerId}" not found`);
|
|
139
189
|
|
|
140
190
|
if (input.email !== undefined) {
|
|
141
|
-
const clash = await this.prisma.customer.findFirst({
|
|
142
|
-
|
|
191
|
+
const clash = await this.prisma.customer.findFirst({
|
|
192
|
+
where: { NOT: { id: customerIdBig }, email: input.email },
|
|
193
|
+
});
|
|
194
|
+
if (clash)
|
|
195
|
+
throw new ConflictException(
|
|
196
|
+
"a customer with this email already exists",
|
|
197
|
+
);
|
|
143
198
|
}
|
|
144
199
|
|
|
145
200
|
const row = await this.prisma.customer.update({
|
|
@@ -150,20 +205,44 @@ export class CustomerRepository {
|
|
|
150
205
|
}
|
|
151
206
|
|
|
152
207
|
// Soft-delete, matching every other table's isDeleted/deletedAt/deletedBy/deletedReason pattern.
|
|
153
|
-
async delete(
|
|
208
|
+
async delete(
|
|
209
|
+
customerId: string,
|
|
210
|
+
actorUserId: string | null,
|
|
211
|
+
reason?: string,
|
|
212
|
+
): Promise<void> {
|
|
154
213
|
const customerIdBig = toId(customerId);
|
|
155
|
-
const existing = await this.prisma.customer.findUnique({
|
|
156
|
-
|
|
214
|
+
const existing = await this.prisma.customer.findUnique({
|
|
215
|
+
where: { id: customerIdBig, isDeleted: false },
|
|
216
|
+
select: { id: true },
|
|
217
|
+
});
|
|
218
|
+
if (!existing)
|
|
219
|
+
throw new NotFoundException(`customer "${customerId}" not found`);
|
|
157
220
|
await this.prisma.customer.update({
|
|
158
221
|
where: { id: customerIdBig },
|
|
159
|
-
data: {
|
|
222
|
+
data: {
|
|
223
|
+
isDeleted: true,
|
|
224
|
+
deletedAt: new Date(),
|
|
225
|
+
deletedBy: toIdOrNull(actorUserId),
|
|
226
|
+
deletedReason: reason ?? null,
|
|
227
|
+
},
|
|
160
228
|
});
|
|
161
229
|
}
|
|
162
230
|
|
|
163
|
-
async setActive(
|
|
231
|
+
async setActive(
|
|
232
|
+
customerId: string,
|
|
233
|
+
isActive: boolean,
|
|
234
|
+
actorUserId: string | null,
|
|
235
|
+
): Promise<void> {
|
|
164
236
|
const customerIdBig = toId(customerId);
|
|
165
|
-
const existing = await this.prisma.customer.findUnique({
|
|
166
|
-
|
|
167
|
-
|
|
237
|
+
const existing = await this.prisma.customer.findUnique({
|
|
238
|
+
where: { id: customerIdBig, isDeleted: false },
|
|
239
|
+
select: { id: true },
|
|
240
|
+
});
|
|
241
|
+
if (!existing)
|
|
242
|
+
throw new NotFoundException(`customer "${customerId}" not found`);
|
|
243
|
+
await this.prisma.customer.update({
|
|
244
|
+
where: { id: customerIdBig },
|
|
245
|
+
data: { isActive, updatedBy: toIdOrNull(actorUserId) },
|
|
246
|
+
});
|
|
168
247
|
}
|
|
169
248
|
}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import {
|
|
2
|
+
ConflictException,
|
|
3
|
+
Inject,
|
|
4
|
+
Injectable,
|
|
5
|
+
NotFoundException,
|
|
6
|
+
} from "@nestjs/common";
|
|
7
|
+
import { Prisma, PrismaClient } from "../../generated/prisma/client.js";
|
|
8
|
+
import { toId, toIdOrNull } from "../id.helper.js";
|
|
9
|
+
import {
|
|
10
|
+
buildPageMeta,
|
|
11
|
+
normalizeLimit,
|
|
12
|
+
normalizePage,
|
|
13
|
+
type Paginated,
|
|
14
|
+
} from "../pagination.js";
|
|
5
15
|
|
|
6
16
|
/** A `Language` row as `findUnique`/`findMany` return it. */
|
|
7
17
|
export type LanguageRow = Prisma.LanguageGetPayload<object>;
|
|
@@ -78,58 +88,116 @@ export class LanguageRepository {
|
|
|
78
88
|
};
|
|
79
89
|
|
|
80
90
|
const [rows, total] = await this.prisma.$transaction([
|
|
81
|
-
this.prisma.language.findMany({
|
|
91
|
+
this.prisma.language.findMany({
|
|
92
|
+
where,
|
|
93
|
+
orderBy: [{ createdAt: "desc" }, { id: "desc" }],
|
|
94
|
+
take: limit,
|
|
95
|
+
skip: (page - 1) * limit,
|
|
96
|
+
}),
|
|
82
97
|
this.prisma.language.count({ where }),
|
|
83
98
|
]);
|
|
84
99
|
|
|
85
|
-
return {
|
|
100
|
+
return {
|
|
101
|
+
items: rows.map(toLanguageSummary),
|
|
102
|
+
meta: buildPageMeta(page, limit, total),
|
|
103
|
+
};
|
|
86
104
|
}
|
|
87
105
|
|
|
88
106
|
async get(languageId: string): Promise<LanguageSummary> {
|
|
89
|
-
const row = await this.prisma.language.findUnique({
|
|
107
|
+
const row = await this.prisma.language.findUnique({
|
|
108
|
+
where: { id: toId(languageId), isDeleted: false },
|
|
109
|
+
});
|
|
90
110
|
if (!row) throw new NotFoundException(`language "${languageId}" not found`);
|
|
91
111
|
return toLanguageSummary(row);
|
|
92
112
|
}
|
|
93
113
|
|
|
94
|
-
async create(
|
|
95
|
-
|
|
96
|
-
|
|
114
|
+
async create(
|
|
115
|
+
input: LanguageInput,
|
|
116
|
+
actorUserId: string | null,
|
|
117
|
+
): Promise<LanguageSummary> {
|
|
118
|
+
const existing = await this.prisma.language.findUnique({
|
|
119
|
+
where: { code: input.code },
|
|
120
|
+
});
|
|
121
|
+
if (existing)
|
|
122
|
+
throw new ConflictException("a language with this code already exists");
|
|
97
123
|
|
|
98
124
|
const row = await this.prisma.language.create({
|
|
99
|
-
data: {
|
|
125
|
+
data: {
|
|
126
|
+
...input,
|
|
127
|
+
createdBy: toIdOrNull(actorUserId),
|
|
128
|
+
updatedBy: toIdOrNull(actorUserId),
|
|
129
|
+
},
|
|
100
130
|
});
|
|
101
131
|
return toLanguageSummary(row);
|
|
102
132
|
}
|
|
103
133
|
|
|
104
|
-
async update(
|
|
134
|
+
async update(
|
|
135
|
+
languageId: string,
|
|
136
|
+
input: Partial<LanguageInput>,
|
|
137
|
+
actorUserId: string | null,
|
|
138
|
+
): Promise<LanguageSummary> {
|
|
105
139
|
const languageIdBig = toId(languageId);
|
|
106
|
-
const existing = await this.prisma.language.findUnique({
|
|
107
|
-
|
|
140
|
+
const existing = await this.prisma.language.findUnique({
|
|
141
|
+
where: { id: languageIdBig, isDeleted: false },
|
|
142
|
+
select: { id: true },
|
|
143
|
+
});
|
|
144
|
+
if (!existing)
|
|
145
|
+
throw new NotFoundException(`language "${languageId}" not found`);
|
|
108
146
|
|
|
109
147
|
if (input.code !== undefined) {
|
|
110
|
-
const clash = await this.prisma.language.findFirst({
|
|
111
|
-
|
|
148
|
+
const clash = await this.prisma.language.findFirst({
|
|
149
|
+
where: { NOT: { id: languageIdBig }, code: input.code },
|
|
150
|
+
});
|
|
151
|
+
if (clash)
|
|
152
|
+
throw new ConflictException("a language with this code already exists");
|
|
112
153
|
}
|
|
113
154
|
|
|
114
|
-
const row = await this.prisma.language.update({
|
|
155
|
+
const row = await this.prisma.language.update({
|
|
156
|
+
where: { id: languageIdBig },
|
|
157
|
+
data: { ...input, updatedBy: toIdOrNull(actorUserId) },
|
|
158
|
+
});
|
|
115
159
|
return toLanguageSummary(row);
|
|
116
160
|
}
|
|
117
161
|
|
|
118
162
|
// Soft-delete, matching every other table's isDeleted/deletedAt/deletedBy/deletedReason pattern.
|
|
119
|
-
async delete(
|
|
163
|
+
async delete(
|
|
164
|
+
languageId: string,
|
|
165
|
+
actorUserId: string | null,
|
|
166
|
+
reason?: string,
|
|
167
|
+
): Promise<void> {
|
|
120
168
|
const languageIdBig = toId(languageId);
|
|
121
|
-
const existing = await this.prisma.language.findUnique({
|
|
122
|
-
|
|
169
|
+
const existing = await this.prisma.language.findUnique({
|
|
170
|
+
where: { id: languageIdBig, isDeleted: false },
|
|
171
|
+
select: { id: true },
|
|
172
|
+
});
|
|
173
|
+
if (!existing)
|
|
174
|
+
throw new NotFoundException(`language "${languageId}" not found`);
|
|
123
175
|
await this.prisma.language.update({
|
|
124
176
|
where: { id: languageIdBig },
|
|
125
|
-
data: {
|
|
177
|
+
data: {
|
|
178
|
+
isDeleted: true,
|
|
179
|
+
deletedAt: new Date(),
|
|
180
|
+
deletedBy: toIdOrNull(actorUserId),
|
|
181
|
+
deletedReason: reason ?? null,
|
|
182
|
+
},
|
|
126
183
|
});
|
|
127
184
|
}
|
|
128
185
|
|
|
129
|
-
async setActive(
|
|
186
|
+
async setActive(
|
|
187
|
+
languageId: string,
|
|
188
|
+
isActive: boolean,
|
|
189
|
+
actorUserId: string | null,
|
|
190
|
+
): Promise<void> {
|
|
130
191
|
const languageIdBig = toId(languageId);
|
|
131
|
-
const existing = await this.prisma.language.findUnique({
|
|
132
|
-
|
|
133
|
-
|
|
192
|
+
const existing = await this.prisma.language.findUnique({
|
|
193
|
+
where: { id: languageIdBig, isDeleted: false },
|
|
194
|
+
select: { id: true },
|
|
195
|
+
});
|
|
196
|
+
if (!existing)
|
|
197
|
+
throw new NotFoundException(`language "${languageId}" not found`);
|
|
198
|
+
await this.prisma.language.update({
|
|
199
|
+
where: { id: languageIdBig },
|
|
200
|
+
data: { isActive, updatedBy: toIdOrNull(actorUserId) },
|
|
201
|
+
});
|
|
134
202
|
}
|
|
135
203
|
}
|