@simple-auth-kit/cli 1.4.3 → 1.5.1

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.
Files changed (134) hide show
  1. package/lib/copy.ts +1 -1
  2. package/package.json +1 -1
  3. package/registry/combos/express-drizzle/shared/src/{auth-core-error.middleware.ts → middleware/auth-core-error.middleware.ts} +17 -4
  4. package/registry/combos/express-drizzle/shared/src/{auth.middleware.ts → middleware/auth.middleware.ts} +23 -7
  5. package/registry/combos/{express-prisma/shared/src → express-drizzle/shared/src/middleware}/response-envelope.middleware.ts +15 -3
  6. package/registry/combos/express-drizzle/shared/src/{oauth.repository.ts → repositories/oauth.repository.ts} +32 -9
  7. package/registry/combos/express-drizzle/shared/src/repositories/password-reset.repository.ts +59 -0
  8. package/registry/combos/express-drizzle/shared/src/{session.repository.ts → repositories/session.repository.ts} +52 -14
  9. package/registry/combos/express-drizzle/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +20 -6
  10. package/registry/combos/express-drizzle/shared/src/request-context.ts +1 -1
  11. package/registry/combos/express-drizzle/shared/src/routers/auth.router.ts +395 -0
  12. package/registry/combos/express-drizzle/variants/base/src/create-auth-app.ts +52 -19
  13. package/registry/combos/express-drizzle/variants/base/src/{authz.middleware.ts → middleware/authz.middleware.ts} +15 -7
  14. package/registry/combos/express-drizzle/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +28 -10
  15. package/registry/combos/express-drizzle/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +239 -48
  16. package/registry/combos/express-drizzle/variants/base/src/routers/admin.router.ts +497 -0
  17. package/registry/combos/express-drizzle/variants/base/src/{auth.service.ts → services/auth.service.ts} +480 -109
  18. package/registry/combos/express-drizzle/variants/workspaces/src/create-auth-app.ts +69 -23
  19. package/registry/combos/express-drizzle/variants/workspaces/src/{authz.middleware.ts → middleware/authz.middleware.ts} +32 -12
  20. package/registry/combos/express-drizzle/variants/workspaces/src/openapi-workspace.ts +147 -28
  21. package/registry/combos/express-drizzle/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +30 -11
  22. package/registry/combos/express-drizzle/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +319 -70
  23. package/registry/combos/express-drizzle/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +127 -30
  24. package/registry/combos/express-drizzle/variants/workspaces/src/routers/admin.router.ts +534 -0
  25. package/registry/combos/express-drizzle/variants/workspaces/src/routers/workspace.router.ts +194 -0
  26. package/registry/combos/express-drizzle/variants/workspaces/src/{auth.service.ts → services/auth.service.ts} +544 -122
  27. package/registry/combos/express-prisma/shared/src/{auth-core-error.middleware.ts → middleware/auth-core-error.middleware.ts} +17 -4
  28. package/registry/combos/express-prisma/shared/src/{auth.middleware.ts → middleware/auth.middleware.ts} +19 -6
  29. package/registry/combos/{express-drizzle/shared/src → express-prisma/shared/src/middleware}/response-envelope.middleware.ts +15 -3
  30. package/registry/combos/express-prisma/shared/src/{oauth.repository.ts → repositories/oauth.repository.ts} +27 -9
  31. package/registry/combos/express-prisma/shared/src/repositories/password-reset.repository.ts +55 -0
  32. package/registry/combos/express-prisma/shared/src/{session.repository.ts → repositories/session.repository.ts} +30 -9
  33. package/registry/combos/express-prisma/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +11 -4
  34. package/registry/combos/express-prisma/shared/src/request-context.ts +1 -1
  35. package/registry/combos/express-prisma/shared/src/routers/auth.router.ts +398 -0
  36. package/registry/combos/express-prisma/variants/base/src/create-auth-app.ts +56 -21
  37. package/registry/combos/express-prisma/variants/base/src/{authz.middleware.ts → middleware/authz.middleware.ts} +15 -7
  38. package/registry/combos/express-prisma/variants/base/src/rbac.defaults.ts +66 -18
  39. package/registry/combos/express-prisma/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
  40. package/registry/combos/express-prisma/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +199 -48
  41. package/registry/combos/express-prisma/variants/base/src/routers/admin.router.ts +508 -0
  42. package/registry/combos/express-prisma/variants/base/src/seed.ts +77 -19
  43. package/registry/combos/express-prisma/variants/base/src/{auth.service.ts → services/auth.service.ts} +454 -105
  44. package/registry/combos/express-prisma/variants/workspaces/src/create-auth-app.ts +80 -25
  45. package/registry/combos/express-prisma/variants/workspaces/src/{authz.middleware.ts → middleware/authz.middleware.ts} +32 -12
  46. package/registry/combos/express-prisma/variants/workspaces/src/openapi-workspace.ts +147 -28
  47. package/registry/combos/express-prisma/variants/workspaces/src/rbac.defaults.ts +72 -20
  48. package/registry/combos/express-prisma/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
  49. package/registry/combos/express-prisma/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +272 -64
  50. package/registry/combos/express-prisma/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +86 -23
  51. package/registry/combos/express-prisma/variants/workspaces/src/routers/admin.router.ts +545 -0
  52. package/registry/combos/express-prisma/variants/workspaces/src/routers/workspace.router.ts +194 -0
  53. package/registry/combos/express-prisma/variants/workspaces/src/seed.ts +108 -28
  54. package/registry/combos/express-prisma/variants/workspaces/src/{auth.service.ts → services/auth.service.ts} +518 -119
  55. package/registry/combos/nestjs-drizzle/shared/src/{auth.controller.ts → controllers/auth.controller.ts} +6 -6
  56. package/registry/combos/nestjs-drizzle/shared/src/{auth-core-error.filter.ts → filters/auth-core-error.filter.ts} +29 -5
  57. package/registry/combos/nestjs-drizzle/shared/src/{ability.guard.ts → guards/ability.guard.ts} +20 -7
  58. package/registry/combos/nestjs-drizzle/shared/src/{auth.guard.ts → guards/auth.guard.ts} +19 -7
  59. package/registry/combos/{nestjs-prisma/shared/src → nestjs-drizzle/shared/src/interceptors}/response.interceptor.ts +10 -2
  60. package/registry/combos/nestjs-drizzle/shared/src/repositories/oauth.repository.ts +63 -0
  61. package/registry/combos/nestjs-drizzle/shared/src/repositories/password-reset.repository.ts +59 -0
  62. package/registry/combos/nestjs-drizzle/shared/src/{session.repository.ts → repositories/session.repository.ts} +52 -14
  63. package/registry/combos/nestjs-drizzle/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +21 -7
  64. package/registry/combos/nestjs-drizzle/shared/src/request-context.ts +1 -1
  65. package/registry/combos/nestjs-drizzle/test/prove-cycle.ts +1097 -307
  66. package/registry/combos/nestjs-drizzle/variants/base/src/auth.module.ts +44 -20
  67. package/registry/combos/nestjs-drizzle/variants/base/src/{admin.controller.ts → controllers/admin.controller.ts} +228 -62
  68. package/registry/combos/nestjs-drizzle/variants/base/src/{authz.guard.ts → guards/authz.guard.ts} +12 -5
  69. package/registry/combos/nestjs-drizzle/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +27 -10
  70. package/registry/combos/nestjs-drizzle/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +249 -51
  71. package/registry/combos/nestjs-drizzle/variants/base/src/{auth.service.ts → services/auth.service.ts} +499 -116
  72. package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.module.ts +48 -22
  73. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{admin.controller.ts → controllers/admin.controller.ts} +269 -70
  74. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{workspace.controller.ts → controllers/workspace.controller.ts} +93 -26
  75. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{authz.guard.ts → guards/authz.guard.ts} +26 -8
  76. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +29 -11
  77. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +323 -71
  78. package/registry/combos/nestjs-drizzle/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +131 -30
  79. package/registry/combos/nestjs-drizzle/variants/workspaces/src/services/auth.service.ts +988 -0
  80. package/registry/combos/nestjs-prisma/shared/src/{auth.controller.ts → controllers/auth.controller.ts} +6 -6
  81. package/registry/combos/nestjs-prisma/shared/src/{auth-core-error.filter.ts → filters/auth-core-error.filter.ts} +29 -5
  82. package/registry/combos/nestjs-prisma/shared/src/{ability.guard.ts → guards/ability.guard.ts} +20 -7
  83. package/registry/combos/nestjs-prisma/shared/src/{auth.guard.ts → guards/auth.guard.ts} +19 -7
  84. package/registry/combos/{nestjs-drizzle/shared/src → nestjs-prisma/shared/src/interceptors}/response.interceptor.ts +10 -2
  85. package/registry/combos/nestjs-prisma/shared/src/{oauth.repository.ts → repositories/oauth.repository.ts} +25 -8
  86. package/registry/combos/nestjs-prisma/shared/src/repositories/password-reset.repository.ts +55 -0
  87. package/registry/combos/nestjs-prisma/shared/src/{session.repository.ts → repositories/session.repository.ts} +30 -9
  88. package/registry/combos/nestjs-prisma/shared/src/{two-factor.repository.ts → repositories/two-factor.repository.ts} +11 -4
  89. package/registry/combos/nestjs-prisma/shared/src/request-context.ts +1 -1
  90. package/registry/combos/nestjs-prisma/test/prove-cycle.ts +1097 -307
  91. package/registry/combos/nestjs-prisma/variants/base/src/auth.module.ts +58 -27
  92. package/registry/combos/nestjs-prisma/variants/base/src/{admin.controller.ts → controllers/admin.controller.ts} +469 -110
  93. package/registry/combos/nestjs-prisma/variants/base/src/{audit-log.gateway.ts → gateways/audit-log.gateway.ts} +22 -6
  94. package/registry/combos/nestjs-prisma/variants/base/src/{authz.guard.ts → guards/authz.guard.ts} +12 -5
  95. package/registry/combos/nestjs-prisma/variants/base/src/rbac.defaults.ts +97 -26
  96. package/registry/combos/nestjs-prisma/variants/base/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
  97. package/registry/combos/nestjs-prisma/variants/base/src/{country.repository.ts → repositories/country.repository.ts} +98 -25
  98. package/registry/combos/nestjs-prisma/variants/base/src/{customer.repository.ts → repositories/customer.repository.ts} +106 -27
  99. package/registry/combos/nestjs-prisma/variants/base/src/{language.repository.ts → repositories/language.repository.ts} +93 -25
  100. package/registry/combos/nestjs-prisma/variants/base/src/{rbac.repository.ts → repositories/rbac.repository.ts} +229 -55
  101. package/registry/combos/nestjs-prisma/variants/base/src/seed.ts +77 -19
  102. package/registry/combos/nestjs-prisma/variants/base/src/services/auth.service.ts +1064 -0
  103. package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.module.ts +54 -26
  104. package/registry/combos/nestjs-prisma/variants/workspaces/src/{admin.controller.ts → controllers/admin.controller.ts} +544 -128
  105. package/registry/combos/nestjs-prisma/variants/workspaces/src/{workspace.controller.ts → controllers/workspace.controller.ts} +93 -26
  106. package/registry/combos/nestjs-prisma/variants/workspaces/src/{authz.guard.ts → guards/authz.guard.ts} +26 -8
  107. package/registry/combos/nestjs-prisma/variants/workspaces/src/rbac.defaults.ts +103 -28
  108. package/registry/combos/nestjs-prisma/variants/workspaces/src/{audit-log.repository.ts → repositories/audit-log.repository.ts} +16 -5
  109. package/registry/combos/nestjs-prisma/variants/workspaces/src/{country.repository.ts → repositories/country.repository.ts} +127 -26
  110. package/registry/combos/nestjs-prisma/variants/workspaces/src/{customer.repository.ts → repositories/customer.repository.ts} +137 -28
  111. package/registry/combos/nestjs-prisma/variants/workspaces/src/repositories/language.repository.ts +243 -0
  112. package/registry/combos/nestjs-prisma/variants/workspaces/src/{rbac.repository.ts → repositories/rbac.repository.ts} +314 -74
  113. package/registry/combos/nestjs-prisma/variants/workspaces/src/{workspace.repository.ts → repositories/workspace.repository.ts} +94 -24
  114. package/registry/combos/nestjs-prisma/variants/workspaces/src/seed.ts +108 -28
  115. package/registry/combos/nestjs-prisma/variants/workspaces/src/services/auth.service.ts +961 -0
  116. package/registry.json +4 -4
  117. package/simple-auth-kit.ts +42 -11
  118. package/registry/combos/express-drizzle/shared/src/auth.router.ts +0 -266
  119. package/registry/combos/express-drizzle/shared/src/password-reset.repository.ts +0 -35
  120. package/registry/combos/express-drizzle/variants/base/src/admin.router.ts +0 -307
  121. package/registry/combos/express-drizzle/variants/workspaces/src/admin.router.ts +0 -323
  122. package/registry/combos/express-drizzle/variants/workspaces/src/workspace.router.ts +0 -123
  123. package/registry/combos/express-prisma/shared/src/auth.router.ts +0 -269
  124. package/registry/combos/express-prisma/shared/src/password-reset.repository.ts +0 -29
  125. package/registry/combos/express-prisma/variants/base/src/admin.router.ts +0 -314
  126. package/registry/combos/express-prisma/variants/workspaces/src/admin.router.ts +0 -330
  127. package/registry/combos/express-prisma/variants/workspaces/src/workspace.router.ts +0 -123
  128. package/registry/combos/nestjs-drizzle/shared/src/oauth.repository.ts +0 -36
  129. package/registry/combos/nestjs-drizzle/shared/src/password-reset.repository.ts +0 -29
  130. package/registry/combos/nestjs-drizzle/variants/workspaces/src/auth.service.ts +0 -553
  131. package/registry/combos/nestjs-prisma/shared/src/password-reset.repository.ts +0 -29
  132. package/registry/combos/nestjs-prisma/variants/base/src/auth.service.ts +0 -618
  133. package/registry/combos/nestjs-prisma/variants/workspaces/src/auth.service.ts +0 -509
  134. package/registry/combos/nestjs-prisma/variants/workspaces/src/language.repository.ts +0 -143
@@ -1,7 +1,17 @@
1
- import { ConflictException, Inject, Injectable, NotFoundException } from "@nestjs/common";
2
- import { Prisma, PrismaClient } from "../generated/prisma/client.js";
3
- import { toId, toIdOrNull } from "./id.helper.js";
4
- import { buildPageMeta, normalizeLimit, normalizePage, type Paginated } from "./pagination.js";
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(input: Partial<CustomerInput>): Omit<Partial<CustomerInput>, "dob" | "joinedDate"> & { dob?: Date | null; joinedDate?: Date } {
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: input.dob === undefined ? undefined : input.dob === null ? null : new Date(input.dob),
85
- joinedDate: input.joinedDate === undefined ? undefined : new Date(input.joinedDate),
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({ where, orderBy: [{ createdAt: "desc" }, { id: "desc" }], take: limit, skip: (page - 1) * limit }),
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 { items: rows.map(toCustomerSummary), meta: buildPageMeta(page, limit, total) };
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({ where: { id: toId(customerId), isDeleted: false } });
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(input: CustomerInput, actorUserId: string | null): Promise<CustomerSummary> {
126
- const existing = await this.prisma.customer.findUnique({ where: { email: input.email } });
127
- if (existing) throw new ConflictException("a customer with this email already exists");
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: { ...toPrismaInput(input), email: input.email, createdBy: toIdOrNull(actorUserId), updatedBy: toIdOrNull(actorUserId) },
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(customerId: string, input: Partial<CustomerInput>, actorUserId: string | null): Promise<CustomerSummary> {
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({ where: { id: customerIdBig, isDeleted: false }, select: { id: true } });
138
- if (!existing) throw new NotFoundException(`customer "${customerId}" not found`);
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({ where: { NOT: { id: customerIdBig }, email: input.email } });
142
- if (clash) throw new ConflictException("a customer with this email already exists");
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(customerId: string, actorUserId: string | null, reason?: string): Promise<void> {
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({ where: { id: customerIdBig, isDeleted: false }, select: { id: true } });
156
- if (!existing) throw new NotFoundException(`customer "${customerId}" not found`);
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: { isDeleted: true, deletedAt: new Date(), deletedBy: toIdOrNull(actorUserId), deletedReason: reason ?? null },
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(customerId: string, isActive: boolean, actorUserId: string | null): Promise<void> {
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({ where: { id: customerIdBig, isDeleted: false }, select: { id: true } });
166
- if (!existing) throw new NotFoundException(`customer "${customerId}" not found`);
167
- await this.prisma.customer.update({ where: { id: customerIdBig }, data: { isActive, updatedBy: toIdOrNull(actorUserId) } });
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 { ConflictException, Inject, Injectable, NotFoundException } from "@nestjs/common";
2
- import { Prisma, PrismaClient } from "../generated/prisma/client.js";
3
- import { toId, toIdOrNull } from "./id.helper.js";
4
- import { buildPageMeta, normalizeLimit, normalizePage, type Paginated } from "./pagination.js";
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({ where, orderBy: [{ createdAt: "desc" }, { id: "desc" }], take: limit, skip: (page - 1) * limit }),
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 { items: rows.map(toLanguageSummary), meta: buildPageMeta(page, limit, total) };
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({ where: { id: toId(languageId), isDeleted: false } });
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(input: LanguageInput, actorUserId: string | null): Promise<LanguageSummary> {
95
- const existing = await this.prisma.language.findUnique({ where: { code: input.code } });
96
- if (existing) throw new ConflictException("a language with this code already exists");
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: { ...input, createdBy: toIdOrNull(actorUserId), updatedBy: toIdOrNull(actorUserId) },
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(languageId: string, input: Partial<LanguageInput>, actorUserId: string | null): Promise<LanguageSummary> {
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({ where: { id: languageIdBig, isDeleted: false }, select: { id: true } });
107
- if (!existing) throw new NotFoundException(`language "${languageId}" not found`);
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({ where: { NOT: { id: languageIdBig }, code: input.code } });
111
- if (clash) throw new ConflictException("a language with this code already exists");
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({ where: { id: languageIdBig }, data: { ...input, updatedBy: toIdOrNull(actorUserId) } });
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(languageId: string, actorUserId: string | null, reason?: string): Promise<void> {
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({ where: { id: languageIdBig, isDeleted: false }, select: { id: true } });
122
- if (!existing) throw new NotFoundException(`language "${languageId}" not found`);
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: { isDeleted: true, deletedAt: new Date(), deletedBy: toIdOrNull(actorUserId), deletedReason: reason ?? null },
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(languageId: string, isActive: boolean, actorUserId: string | null): Promise<void> {
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({ where: { id: languageIdBig, isDeleted: false }, select: { id: true } });
132
- if (!existing) throw new NotFoundException(`language "${languageId}" not found`);
133
- await this.prisma.language.update({ where: { id: languageIdBig }, data: { isActive, updatedBy: toIdOrNull(actorUserId) } });
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
  }