@wordrhyme/auto-crud-server 0.6.0 → 0.6.2

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/index.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import { z } from "zod";
2
2
  import { SQL } from "drizzle-orm";
3
- import * as _trpc_server5 from "@trpc/server";
3
+ import * as _trpc_server2 from "@trpc/server";
4
4
  import superjson from "superjson";
5
5
  import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
6
- import * as node_modules__trpc_server_dist_unstable_core_do_not_import_d_CjQPvBRI_mjs0 from "node_modules/@trpc/server/dist/unstable-core-do-not-import.d-CjQPvBRI.mjs";
7
6
  import { PgTable } from "drizzle-orm/pg-core";
8
7
 
9
8
  //#region src/trpc.d.ts
@@ -14,16 +13,16 @@ import { PgTable } from "drizzle-orm/pg-core";
14
13
  interface Context {
15
14
  db: PostgresJsDatabase<Record<string, never>>;
16
15
  }
17
- declare const router: _trpc_server5.TRPCRouterBuilder<{
16
+ declare const router: _trpc_server2.TRPCRouterBuilder<{
18
17
  ctx: Context;
19
18
  meta: object;
20
- errorShape: _trpc_server5.TRPCDefaultErrorShape;
19
+ errorShape: _trpc_server2.TRPCDefaultErrorShape;
21
20
  transformer: true;
22
21
  }>;
23
- declare const publicProcedure: _trpc_server5.TRPCProcedureBuilder<Context, object, object, _trpc_server5.TRPCUnsetMarker, _trpc_server5.TRPCUnsetMarker, _trpc_server5.TRPCUnsetMarker, _trpc_server5.TRPCUnsetMarker, false>;
22
+ declare const publicProcedure: _trpc_server2.TRPCProcedureBuilder<Context, object, object, _trpc_server2.TRPCUnsetMarker, _trpc_server2.TRPCUnsetMarker, _trpc_server2.TRPCUnsetMarker, _trpc_server2.TRPCUnsetMarker, false>;
24
23
  //#endregion
25
24
  //#region src/types/config.d.ts
26
- type CrudOperation = "list" | "get" | "create" | "update" | "delete" | "deleteMany" | "updateMany";
25
+ type CrudOperation = "list" | "get" | "create" | "update" | "delete" | "deleteMany" | "updateMany" | "upsert";
27
26
  type WriteOperation = "create" | "update";
28
27
  type AnyProcedure = any;
29
28
  interface SoftDeleteConfig {
@@ -72,6 +71,57 @@ interface ListResult<TSelect> {
72
71
  perPage: number;
73
72
  pageCount: number;
74
73
  }
74
+ interface ListMiddlewareParams<TContext, TSelect> {
75
+ ctx: TContext;
76
+ input: ListInput;
77
+ next: (input?: ListInput) => Promise<ListResult<TSelect>>;
78
+ }
79
+ interface GetMiddlewareParams<TContext, TSelect> {
80
+ ctx: TContext;
81
+ id: string;
82
+ next: () => Promise<TSelect | null>;
83
+ }
84
+ interface CreateMiddlewareParams<TContext, TSelect, TInsert> {
85
+ ctx: TContext;
86
+ input: TInsert;
87
+ next: (input?: TInsert) => Promise<TSelect>;
88
+ }
89
+ interface UpdateMiddlewareParams<TContext, TSelect, TUpdate> {
90
+ ctx: TContext;
91
+ id: string;
92
+ data: TUpdate;
93
+ existing: TSelect;
94
+ next: (data?: TUpdate) => Promise<TSelect>;
95
+ }
96
+ interface DeleteMiddlewareParams<TContext, TSelect> {
97
+ ctx: TContext;
98
+ id: string;
99
+ existing: TSelect;
100
+ next: () => Promise<TSelect>;
101
+ }
102
+ interface DeleteManyMiddlewareParams<TContext> {
103
+ ctx: TContext;
104
+ ids: string[];
105
+ next: () => Promise<{
106
+ deleted: number;
107
+ }>;
108
+ }
109
+ interface UpdateManyMiddlewareParams<TContext, TUpdate> {
110
+ ctx: TContext;
111
+ ids: string[];
112
+ data: TUpdate;
113
+ next: (data?: TUpdate) => Promise<{
114
+ updated: number;
115
+ }>;
116
+ }
117
+ interface UpsertMiddlewareParams<TContext, TSelect, TInsert> {
118
+ ctx: TContext;
119
+ input: TInsert;
120
+ next: (input?: TInsert) => Promise<{
121
+ data: TSelect;
122
+ isNew: boolean;
123
+ }>;
124
+ }
75
125
  /**
76
126
  * 操作包装器 - 类似 tRPC middleware 的 next 模式
77
127
  *
@@ -82,6 +132,11 @@ interface ListResult<TSelect> {
82
132
  * - 条件拦截(不调用 next 直接返回/抛错)
83
133
  * - 包装事务(try/catch 包裹 next)
84
134
  *
135
+ * @typeParam TContext - 上下文类型
136
+ * @typeParam TSelect - 查询返回类型(从 selectSchema 推断)
137
+ * @typeParam TInsert - 创建输入类型(从 insertSchema 推断)
138
+ * @typeParam TUpdate - 更新输入类型(从 updateSchema 推断)
139
+ *
85
140
  * @example
86
141
  * // 修改输入 + 执行副作用
87
142
  * middleware: {
@@ -92,98 +147,60 @@ interface ListResult<TSelect> {
92
147
  * return result;
93
148
  * },
94
149
  * }
95
- *
96
- * @example
97
- * // 简单副作用 - 使用工具函数
98
- * import { afterMiddleware } from "@wordrhyme/auto-crud-server";
99
- *
100
- * middleware: {
101
- * create: afterMiddleware(async (ctx, result) => {
102
- * await sendEmail(result);
103
- * }),
104
- * }
105
150
  */
106
- interface CrudMiddleware<TContext = unknown> {
151
+ interface CrudMiddleware<TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown> {
107
152
  /**
108
153
  * 列表查询包装器
109
154
  */
110
- list?: (params: {
111
- ctx: TContext;
112
- input: ListInput;
113
- next: (input?: ListInput) => Promise<ListResult<unknown>>;
114
- }) => Promise<ListResult<unknown>>;
155
+ list?: (params: ListMiddlewareParams<TContext, TSelect>) => Promise<ListResult<TSelect>>;
115
156
  /**
116
157
  * 单条查询包装器
117
158
  */
118
- get?: (params: {
119
- ctx: TContext;
120
- id: string;
121
- next: () => Promise<unknown | null>;
122
- }) => Promise<unknown | null>;
159
+ get?: (params: GetMiddlewareParams<TContext, TSelect>) => Promise<TSelect | null>;
123
160
  /**
124
161
  * 创建包装器
125
162
  */
126
- create?: (params: {
127
- ctx: TContext;
128
- input: unknown;
129
- next: (input?: unknown) => Promise<unknown>;
130
- }) => Promise<unknown>;
163
+ create?: (params: CreateMiddlewareParams<TContext, TSelect, TInsert>) => Promise<TSelect>;
131
164
  /**
132
165
  * 更新包装器
133
166
  * existing: 更新前的记录
134
167
  */
135
- update?: (params: {
136
- ctx: TContext;
137
- id: string;
138
- data: unknown;
139
- existing: unknown;
140
- next: (data?: unknown) => Promise<unknown>;
141
- }) => Promise<unknown>;
168
+ update?: (params: UpdateMiddlewareParams<TContext, TSelect, TUpdate>) => Promise<TSelect>;
142
169
  /**
143
170
  * 删除包装器
144
171
  * existing: 删除前的记录
145
172
  */
146
- delete?: (params: {
147
- ctx: TContext;
148
- id: string;
149
- existing: unknown;
150
- next: () => Promise<unknown>;
151
- }) => Promise<unknown>;
173
+ delete?: (params: DeleteMiddlewareParams<TContext, TSelect>) => Promise<TSelect>;
152
174
  /**
153
175
  * 批量删除包装器
154
176
  */
155
- deleteMany?: (params: {
156
- ctx: TContext;
157
- ids: string[];
158
- next: () => Promise<{
159
- deleted: number;
160
- }>;
161
- }) => Promise<{
177
+ deleteMany?: (params: DeleteManyMiddlewareParams<TContext>) => Promise<{
162
178
  deleted: number;
163
179
  }>;
164
180
  /**
165
181
  * 批量更新包装器
166
182
  */
167
- updateMany?: (params: {
168
- ctx: TContext;
169
- ids: string[];
170
- data: unknown;
171
- next: (data?: unknown) => Promise<{
172
- updated: number;
173
- }>;
174
- }) => Promise<{
183
+ updateMany?: (params: UpdateManyMiddlewareParams<TContext, TUpdate>) => Promise<{
175
184
  updated: number;
176
185
  }>;
186
+ /**
187
+ * Upsert 包装器
188
+ * isNew: 是否为新建(冲突检测后)
189
+ */
190
+ upsert?: (params: UpsertMiddlewareParams<TContext, TSelect, TInsert>) => Promise<{
191
+ data: TSelect;
192
+ isNew: boolean;
193
+ }>;
177
194
  }
178
- interface CrudRouterConfigBase<TContext = unknown> {
195
+ interface CrudRouterConfigBase<TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown> {
179
196
  /** Drizzle 表定义 */
180
197
  table: PgTable;
181
198
  /** 查询返回 Schema */
182
- selectSchema?: z.ZodType;
199
+ selectSchema?: z.ZodType<TSelect>;
183
200
  /** 创建输入 Schema */
184
- insertSchema: z.ZodType;
201
+ insertSchema: z.ZodType<TInsert>;
185
202
  /** 更新输入 Schema */
186
- updateSchema: z.ZodType;
203
+ updateSchema: z.ZodType<TUpdate>;
187
204
  /** ID 字段名,默认 "id" */
188
205
  idField?: string;
189
206
  /** 可过滤的列白名单 */
@@ -238,9 +255,9 @@ interface CrudRouterConfigBase<TContext = unknown> {
238
255
  * }),
239
256
  * }
240
257
  */
241
- middleware?: CrudMiddleware<TContext>;
258
+ middleware?: CrudMiddleware<TContext, TSelect, TInsert, TUpdate>;
242
259
  }
243
- interface DeclarativeConfig<TContext = unknown> extends CrudRouterConfigBase<TContext> {
260
+ interface DeclarativeConfig<TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown> extends CrudRouterConfigBase<TContext, TSelect, TInsert, TUpdate> {
244
261
  mode?: "declarative";
245
262
  /**
246
263
  * 基础 procedure(认证)
@@ -278,9 +295,9 @@ interface DeclarativeConfig<TContext = unknown> extends CrudRouterConfigBase<TCo
278
295
  * @example
279
296
  * authorize: (ctx, resource, op) => resource.ownerId === ctx.user.id
280
297
  */
281
- authorize?: (ctx: TContext, resource: Record<string, unknown>, operation: CrudOperation) => boolean | Promise<boolean>;
298
+ authorize?: (ctx: TContext, resource: TSelect, operation: CrudOperation) => boolean | Promise<boolean>;
282
299
  }
283
- interface FactoryConfig<TContext = unknown> extends CrudRouterConfigBase<TContext> {
300
+ interface FactoryConfig<TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown> extends CrudRouterConfigBase<TContext, TSelect, TInsert, TUpdate> {
284
301
  mode: "factory";
285
302
  /**
286
303
  * Procedure 工厂函数
@@ -299,7 +316,7 @@ interface FactoryConfig<TContext = unknown> extends CrudRouterConfigBase<TContex
299
316
  */
300
317
  inject?: (ctx: TContext, operation: WriteOperation) => Record<string, unknown>;
301
318
  }
302
- interface ProceduresConfig<TContext = unknown> extends CrudRouterConfigBase<TContext> {
319
+ interface ProceduresConfig<TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown> extends CrudRouterConfigBase<TContext, TSelect, TInsert, TUpdate> {
303
320
  mode: "procedures";
304
321
  /**
305
322
  * 按操作指定不同的 procedure
@@ -323,49 +340,36 @@ interface ProceduresConfig<TContext = unknown> extends CrudRouterConfigBase<TCon
323
340
  */
324
341
  inject?: (ctx: TContext, operation: WriteOperation) => Record<string, unknown>;
325
342
  }
326
- type CrudRouterConfig<TContext = unknown> = DeclarativeConfig<TContext> | FactoryConfig<TContext> | ProceduresConfig<TContext>;
343
+ type CrudRouterConfig<TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown> = DeclarativeConfig<TContext, TSelect, TInsert, TUpdate> | FactoryConfig<TContext, TSelect, TInsert, TUpdate> | ProceduresConfig<TContext, TSelect, TInsert, TUpdate>;
344
+ interface CrudProcedures<TSelect, TInsert, TUpdate> {
345
+ list: AnyProcedure;
346
+ get: AnyProcedure;
347
+ create: AnyProcedure;
348
+ update: AnyProcedure;
349
+ delete: AnyProcedure;
350
+ deleteMany: AnyProcedure;
351
+ updateMany: AnyProcedure;
352
+ upsert: AnyProcedure;
353
+ }
327
354
  //#endregion
328
355
  //#region src/routers/_factory.d.ts
329
- declare function createCrudRouter<TContext = unknown>(config: CrudRouterConfig<TContext>): node_modules__trpc_server_dist_unstable_core_do_not_import_d_CjQPvBRI_mjs0.Router<{
330
- ctx: Context;
331
- meta: object;
332
- errorShape: _trpc_server5.TRPCDefaultErrorShape;
333
- transformer: true;
334
- }, _trpc_server5.TRPCDecorateCreateRouterOptions<{
335
- list: any;
336
- getById: any;
337
- create: any;
338
- update: any;
339
- delete: any;
340
- deleteMany: any;
341
- updateMany: any;
342
- }>> & _trpc_server5.TRPCDecorateCreateRouterOptions<{
343
- list: any;
344
- getById: any;
345
- create: any;
346
- update: any;
347
- delete: any;
348
- deleteMany: any;
349
- updateMany: any;
350
- }> & {
351
- procedures: {
352
- list: any;
353
- getById: any;
354
- create: any;
355
- update: any;
356
- delete: any;
357
- deleteMany: any;
358
- updateMany: any;
359
- };
356
+ /**
357
+ * 创建 CRUD Router
358
+ *
359
+ * @typeParam TContext - 上下文类型(包含 db)
360
+ * @typeParam TSelect - 查询返回类型(从 selectSchema 或 insertSchema 推断)
361
+ * @typeParam TInsert - 创建输入类型(从 insertSchema 推断)
362
+ * @typeParam TUpdate - 更新输入类型(从 updateSchema 推断)
363
+ */
364
+ declare function createCrudRouter<TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown>(config: CrudRouterConfig<TContext, TSelect, TInsert, TUpdate>): ReturnType<typeof router> & {
365
+ procedures: CrudProcedures<TSelect, TInsert, TUpdate>;
360
366
  };
361
367
  //#endregion
362
368
  //#region src/lib/middleware-helpers.d.ts
363
- type NextFn<TInput, TResult> = (input?: TInput) => Promise<TResult>;
364
- interface MiddlewareParams<TContext, TInput, TResult> {
365
- ctx: TContext;
366
- input?: TInput;
367
- next: NextFn<TInput, TResult>;
368
- }
369
+ /**
370
+ * Middleware 便捷工具函数
371
+ * 简化常见场景的 middleware 创建
372
+ */
369
373
  /**
370
374
  * 创建 after-only 的 middleware(最常见场景)
371
375
  * 在操作完成后执行副作用,不修改返回值
@@ -378,29 +382,10 @@ interface MiddlewareParams<TContext, TInput, TResult> {
378
382
  * }),
379
383
  * }
380
384
  */
381
- declare function afterMiddleware<TContext, TResult>(fn: (ctx: TContext, result: TResult) => void | Promise<void>): ({
382
- ctx,
383
- next
384
- }: {
385
- ctx: TContext;
386
- next: () => Promise<TResult>;
387
- }) => Promise<TResult>;
388
- /**
389
- * 创建 after-only 的 middleware,可修改返回值
390
- *
391
- * @example
392
- * middleware: {
393
- * get: afterMiddlewareTransform(async (ctx, result) => {
394
- * return { ...result, computed: calculateSomething(result) };
395
- * }),
396
- * }
397
- */
398
- declare function afterMiddlewareTransform<TContext, TResult>(fn: (ctx: TContext, result: TResult) => TResult | Promise<TResult>): ({
399
- ctx,
400
- next
401
- }: {
385
+ declare function afterMiddleware<TContext, TResult>(fn: (ctx: TContext, result: TResult) => void | Promise<void>): (params: {
402
386
  ctx: TContext;
403
387
  next: () => Promise<TResult>;
388
+ [key: string]: any;
404
389
  }) => Promise<TResult>;
405
390
  /**
406
391
  * 创建 before-only 的 middleware
@@ -413,11 +398,17 @@ declare function afterMiddlewareTransform<TContext, TResult>(fn: (ctx: TContext,
413
398
  * }),
414
399
  * }
415
400
  */
416
- declare function beforeMiddleware<TContext, TInput>(fn: (ctx: TContext, input: TInput) => TInput | Promise<TInput>): <TResult>({
417
- ctx,
418
- input,
419
- next
420
- }: MiddlewareParams<TContext, TInput, TResult>) => Promise<TResult>;
401
+ declare function beforeMiddleware<TContext, TInput>(fn: (ctx: TContext, input: TInput) => TInput | Promise<TInput>): <TResult>(params: {
402
+ ctx: TContext;
403
+ input: TInput;
404
+ next: (input?: TInput) => Promise<TResult>;
405
+ [key: string]: any;
406
+ }) => Promise<TResult>;
407
+ type AnyMiddlewareParams<TContext> = {
408
+ ctx: TContext;
409
+ next: (...args: any[]) => Promise<any>;
410
+ [key: string]: any;
411
+ };
421
412
  /**
422
413
  * 组合多个 middleware 为一个
423
414
  *
@@ -429,71 +420,15 @@ declare function beforeMiddleware<TContext, TInput>(fn: (ctx: TContext, input: T
429
420
  * ),
430
421
  * }
431
422
  */
432
- declare function composeMiddleware<TContext, TInput, TResult>(...middlewares: Array<(params: MiddlewareParams<TContext, TInput, TResult>) => Promise<TResult>>): (params: MiddlewareParams<TContext, TInput, TResult>) => Promise<TResult>;
433
- /**
434
- * 创建 list 操作的 after middleware
435
- */
436
- declare function afterList<TContext, TSelect>(fn: (ctx: TContext, result: ListResult<TSelect>) => void | Promise<void>): ({
437
- ctx,
438
- next
439
- }: {
440
- ctx: TContext;
441
- next: () => Promise<ListResult<TSelect>>;
442
- }) => Promise<ListResult<TSelect>>;
443
- /**
444
- * 创建 list 操作的 before middleware
445
- */
446
- declare function beforeList<TContext>(fn: (ctx: TContext, input: ListInput) => ListInput | Promise<ListInput>): <TResult>({
447
- ctx,
448
- input,
449
- next
450
- }: MiddlewareParams<TContext, ListInput, TResult>) => Promise<TResult>;
451
- /**
452
- * 创建 create 操作的 after middleware
453
- */
454
- declare function afterCreate<TContext, TSelect>(fn: (ctx: TContext, created: TSelect) => void | Promise<void>): ({
455
- ctx,
456
- next
457
- }: {
458
- ctx: TContext;
459
- next: () => Promise<TSelect>;
460
- }) => Promise<TSelect>;
461
- /**
462
- * 创建 create 操作的 before middleware
463
- */
464
- declare function beforeCreate<TContext, TInsert>(fn: (ctx: TContext, input: TInsert) => TInsert | Promise<TInsert>): <TResult>({
465
- ctx,
466
- input,
467
- next
468
- }: MiddlewareParams<TContext, TInsert, TResult>) => Promise<TResult>;
469
- /**
470
- * 创建 update 操作的 after middleware
471
- */
472
- declare function afterUpdate<TContext, TSelect>(fn: (ctx: TContext, updated: TSelect) => void | Promise<void>): ({
473
- ctx,
474
- next
475
- }: {
476
- ctx: TContext;
477
- next: () => Promise<TSelect>;
478
- }) => Promise<TSelect>;
479
- /**
480
- * 创建 delete 操作的 after middleware
481
- */
482
- declare function afterDelete<TContext, TSelect>(fn: (ctx: TContext, deleted: TSelect) => void | Promise<void>): ({
483
- ctx,
484
- next
485
- }: {
486
- ctx: TContext;
487
- next: () => Promise<TSelect>;
488
- }) => Promise<TSelect>;
423
+ declare function composeMiddleware<TContext, TResult>(...middlewares: Array<(params: AnyMiddlewareParams<TContext>) => Promise<any>>): (params: AnyMiddlewareParams<TContext>) => Promise<TResult>;
489
424
  //#endregion
490
425
  //#region src/routers/index.d.ts
491
- declare const appRouter: _trpc_server5.TRPCBuiltRouter<{
426
+ declare const appRouter: _trpc_server2.TRPCBuiltRouter<{
492
427
  ctx: Context;
493
428
  meta: object;
494
- errorShape: _trpc_server5.TRPCDefaultErrorShape;
429
+ errorShape: _trpc_server2.TRPCDefaultErrorShape;
495
430
  transformer: true;
496
- }, _trpc_server5.TRPCDecorateCreateRouterOptions<{}>>;
431
+ }, _trpc_server2.TRPCDecorateCreateRouterOptions<{}>>;
497
432
  type AppRouter = typeof appRouter;
498
433
  //#endregion
499
- export { type AnyProcedure, type AppRouter, type CrudMiddleware, type CrudOperation, type CrudRouterConfig, type DeclarativeConfig, type FactoryConfig, type ListInput, type ListResult, type ProceduresConfig, type SoftDeleteConfig, type SoftDeleteOption, type WriteOperation, afterCreate, afterDelete, afterList, afterMiddleware, afterMiddlewareTransform, afterUpdate, appRouter, beforeCreate, beforeList, beforeMiddleware, composeMiddleware, createCrudRouter, publicProcedure, router };
434
+ export { type AnyProcedure, type AppRouter, type CreateMiddlewareParams, type CrudMiddleware, type CrudOperation, type CrudProcedures, type CrudRouterConfig, type CrudRouterConfigBase, type DeclarativeConfig, type DeleteManyMiddlewareParams, type DeleteMiddlewareParams, type FactoryConfig, type GetMiddlewareParams, type ListInput, type ListMiddlewareParams, type ListResult, type ProceduresConfig, type SoftDeleteConfig, type SoftDeleteOption, type UpdateManyMiddlewareParams, type UpdateMiddlewareParams, type UpsertMiddlewareParams, type WriteOperation, afterMiddleware, appRouter, beforeMiddleware, composeMiddleware, createCrudRouter, publicProcedure, router };