@wordrhyme/auto-crud-server 0.8.0 → 0.10.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/README.md +161 -95
- package/dist/index.cjs +204 -11
- package/dist/index.d.cts +178 -19
- package/dist/index.d.ts +177 -18
- package/dist/index.js +203 -11
- package/package.json +7 -7
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { InferInsertModel, InferSelectModel, SQL } from "drizzle-orm";
|
|
3
|
+
import { PgTable } from "drizzle-orm/pg-core";
|
|
1
4
|
import * as _trpc_server2 from "@trpc/server";
|
|
2
5
|
import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
3
|
-
import { SQL } from "drizzle-orm";
|
|
4
|
-
import { PgTable } from "drizzle-orm/pg-core";
|
|
5
|
-
import { z } from "zod";
|
|
6
6
|
|
|
7
7
|
//#region src/trpc.d.ts
|
|
8
8
|
/**
|
|
@@ -21,8 +21,13 @@ declare const router: _trpc_server2.TRPCRouterBuilder<{
|
|
|
21
21
|
declare const publicProcedure: _trpc_server2.TRPCProcedureBuilder<Context, object, object, _trpc_server2.TRPCUnsetMarker, _trpc_server2.TRPCUnsetMarker, _trpc_server2.TRPCUnsetMarker, _trpc_server2.TRPCUnsetMarker, false>;
|
|
22
22
|
//#endregion
|
|
23
23
|
//#region src/types/config.d.ts
|
|
24
|
-
type CrudOperation = "list" | "get" | "create" | "update" | "delete" | "deleteMany" | "updateMany" | "upsert";
|
|
24
|
+
type CrudOperation = "list" | "get" | "create" | "update" | "delete" | "deleteMany" | "updateMany" | "upsert" | "export" | "import" | "createMany";
|
|
25
25
|
type WriteOperation = "create" | "update";
|
|
26
|
+
/**
|
|
27
|
+
* 表字段键类型提取
|
|
28
|
+
* 用于 omitFields 的强类型支持
|
|
29
|
+
*/
|
|
30
|
+
type TableColumnKeys<T extends PgTable> = keyof T["_"]["columns"];
|
|
26
31
|
type AnyProcedure = any;
|
|
27
32
|
interface SoftDeleteConfig {
|
|
28
33
|
/** 软删除标记列名 */
|
|
@@ -70,6 +75,70 @@ interface ListResult<TSelect> {
|
|
|
70
75
|
perPage: number;
|
|
71
76
|
pageCount: number;
|
|
72
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* 导出查询输入类型(复用 ListInput 的筛选/排序,无分页)
|
|
80
|
+
*/
|
|
81
|
+
interface ExportInput {
|
|
82
|
+
sort?: Array<{
|
|
83
|
+
id: string;
|
|
84
|
+
desc: boolean;
|
|
85
|
+
}>;
|
|
86
|
+
filters?: Array<{
|
|
87
|
+
id: string;
|
|
88
|
+
value: string | string[];
|
|
89
|
+
variant: string;
|
|
90
|
+
operator: string;
|
|
91
|
+
filterId: string;
|
|
92
|
+
}>;
|
|
93
|
+
joinOperator?: "and" | "or";
|
|
94
|
+
/** 导出数量限制,会被 clamp 到 [1, maxExportSize] */
|
|
95
|
+
limit?: number;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 导出查询结果类型
|
|
99
|
+
*/
|
|
100
|
+
interface ExportResult<TSelect> {
|
|
101
|
+
data: TSelect[];
|
|
102
|
+
total: number;
|
|
103
|
+
/** 是否还有更多数据未导出(total > data.length) */
|
|
104
|
+
hasMore: boolean;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* 导入行失败详情
|
|
108
|
+
*/
|
|
109
|
+
interface ImportFailedRow {
|
|
110
|
+
/** 行号(0-indexed) */
|
|
111
|
+
row: number;
|
|
112
|
+
/** 验证错误信息列表 */
|
|
113
|
+
errors: string[];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 导入结果类型
|
|
117
|
+
*/
|
|
118
|
+
interface ImportResult {
|
|
119
|
+
/** 成功新建的行数 */
|
|
120
|
+
success: number;
|
|
121
|
+
/** 更新的行数(onConflict="upsert" 时) */
|
|
122
|
+
updated: number;
|
|
123
|
+
/** 跳过的行数(如重复 ID,onConflict="skip" 时) */
|
|
124
|
+
skipped: number;
|
|
125
|
+
/** 失败的行详情 */
|
|
126
|
+
failed: ImportFailedRow[];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 导入输入类型
|
|
130
|
+
*/
|
|
131
|
+
interface ImportInput {
|
|
132
|
+
/** 待导入的数据行(客户端已解析为对象数组) */
|
|
133
|
+
rows: unknown[];
|
|
134
|
+
/**
|
|
135
|
+
* 冲突处理策略
|
|
136
|
+
* - "skip": 跳过冲突行(默认)
|
|
137
|
+
* - "upsert": 存在则更新,不存在则新建
|
|
138
|
+
* - "error": 冲突行计入失败
|
|
139
|
+
*/
|
|
140
|
+
onConflict?: "skip" | "upsert" | "error";
|
|
141
|
+
}
|
|
73
142
|
interface ListMiddlewareParams<TContext, TSelect> {
|
|
74
143
|
ctx: TContext;
|
|
75
144
|
input: ListInput;
|
|
@@ -121,6 +190,24 @@ interface UpsertMiddlewareParams<TContext, TSelect, TInsert> {
|
|
|
121
190
|
isNew: boolean;
|
|
122
191
|
}>;
|
|
123
192
|
}
|
|
193
|
+
interface ExportMiddlewareParams<TContext, TSelect> {
|
|
194
|
+
ctx: TContext;
|
|
195
|
+
input: ExportInput;
|
|
196
|
+
next: (input?: ExportInput) => Promise<ExportResult<TSelect>>;
|
|
197
|
+
}
|
|
198
|
+
interface ImportMiddlewareParams<TContext> {
|
|
199
|
+
ctx: TContext;
|
|
200
|
+
input: ImportInput;
|
|
201
|
+
next: (input?: ImportInput) => Promise<ImportResult>;
|
|
202
|
+
}
|
|
203
|
+
interface CreateManyMiddlewareParams<TContext, TSelect, TInsert> {
|
|
204
|
+
ctx: TContext;
|
|
205
|
+
input: TInsert[];
|
|
206
|
+
next: (input?: TInsert[]) => Promise<{
|
|
207
|
+
created: TSelect[];
|
|
208
|
+
count: number;
|
|
209
|
+
}>;
|
|
210
|
+
}
|
|
124
211
|
/**
|
|
125
212
|
* 操作包装器 - 类似 tRPC middleware 的 next 模式
|
|
126
213
|
*
|
|
@@ -190,6 +277,23 @@ interface CrudMiddleware<TContext = unknown, TSelect = unknown, TInsert = unknow
|
|
|
190
277
|
data: TSelect;
|
|
191
278
|
isNew: boolean;
|
|
192
279
|
}>;
|
|
280
|
+
/**
|
|
281
|
+
* 导出包装器
|
|
282
|
+
* 可用于审计日志、限流、异步队列调度
|
|
283
|
+
*/
|
|
284
|
+
export?: (params: ExportMiddlewareParams<TContext, TSelect>) => Promise<ExportResult<TSelect>>;
|
|
285
|
+
/**
|
|
286
|
+
* 导入包装器
|
|
287
|
+
* 可用于审计日志、限流、异步队列调度
|
|
288
|
+
*/
|
|
289
|
+
import?: (params: ImportMiddlewareParams<TContext>) => Promise<ImportResult>;
|
|
290
|
+
/**
|
|
291
|
+
* 批量创建包装器
|
|
292
|
+
*/
|
|
293
|
+
createMany?: (params: CreateManyMiddlewareParams<TContext, TSelect, TInsert>) => Promise<{
|
|
294
|
+
created: TSelect[];
|
|
295
|
+
count: number;
|
|
296
|
+
}>;
|
|
193
297
|
}
|
|
194
298
|
/**
|
|
195
299
|
* Procedure 映射对象
|
|
@@ -204,6 +308,9 @@ interface ProcedureMap {
|
|
|
204
308
|
deleteMany?: AnyProcedure;
|
|
205
309
|
updateMany?: AnyProcedure;
|
|
206
310
|
upsert?: AnyProcedure;
|
|
311
|
+
export?: AnyProcedure;
|
|
312
|
+
import?: AnyProcedure;
|
|
313
|
+
createMany?: AnyProcedure;
|
|
207
314
|
/** 未指定操作时的默认 procedure */
|
|
208
315
|
default?: AnyProcedure;
|
|
209
316
|
}
|
|
@@ -270,13 +377,37 @@ type ProcedureConfig = AnyProcedure | ProcedureMap | ProcedureFactory;
|
|
|
270
377
|
* authorize: (ctx, resource) => resource.ownerId === ctx.user.id,
|
|
271
378
|
* })
|
|
272
379
|
*/
|
|
273
|
-
interface CrudRouterConfig<TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown> {
|
|
380
|
+
interface CrudRouterConfig<TTable extends PgTable = PgTable, TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown> {
|
|
274
381
|
/** Drizzle 表定义 */
|
|
275
|
-
table:
|
|
276
|
-
/**
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
382
|
+
table: TTable;
|
|
383
|
+
/**
|
|
384
|
+
* 主 Schema(用于 create/upsert 输入验证)
|
|
385
|
+
* - 如果不传,自动从 table 派生并排除 omitFields
|
|
386
|
+
* - updateSchema 默认为 schema.partial().refine(nonEmpty)
|
|
387
|
+
*
|
|
388
|
+
* @example
|
|
389
|
+
* // 自动派生
|
|
390
|
+
* createCrudRouter({ table: tasks })
|
|
391
|
+
*
|
|
392
|
+
* // 显式传入
|
|
393
|
+
* createCrudRouter({ table: tasks, schema: taskSchema })
|
|
394
|
+
*/
|
|
395
|
+
schema?: z.ZodType<TInsert>;
|
|
396
|
+
/**
|
|
397
|
+
* 更新输入 Schema(可选)
|
|
398
|
+
* - 如果不传,自动从 schema.partial() 派生
|
|
399
|
+
* - 传入时覆盖自动派生
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* createCrudRouter({
|
|
403
|
+
* table: tasks,
|
|
404
|
+
* schema: taskSchema,
|
|
405
|
+
* updateSchema: customUpdateSchema, // 覆盖自动派生
|
|
406
|
+
* })
|
|
407
|
+
*/
|
|
408
|
+
updateSchema?: z.ZodType<TUpdate>;
|
|
409
|
+
/** 查询返回 Schema */
|
|
410
|
+
selectSchema?: z.ZodType<TSelect>;
|
|
280
411
|
/**
|
|
281
412
|
* Procedure 配置(统一字段)
|
|
282
413
|
*
|
|
@@ -320,8 +451,11 @@ interface CrudRouterConfig<TContext = unknown, TSelect = unknown, TInsert = unkn
|
|
|
320
451
|
* authorize: (ctx, resource, op) => resource.ownerId === ctx.user.id
|
|
321
452
|
*/
|
|
322
453
|
authorize?: (ctx: TContext, resource: TSelect, operation: CrudOperation) => boolean | Promise<boolean>;
|
|
323
|
-
/**
|
|
324
|
-
|
|
454
|
+
/**
|
|
455
|
+
* 要从 schema 排除的字段(自动派生时使用)
|
|
456
|
+
* @default ["id", "createdAt", "updatedAt"]
|
|
457
|
+
*/
|
|
458
|
+
omitFields?: TableColumnKeys<TTable>[];
|
|
325
459
|
/** ID 字段名,默认 "id" */
|
|
326
460
|
idField?: string;
|
|
327
461
|
/** 可过滤的列白名单 */
|
|
@@ -330,6 +464,12 @@ interface CrudRouterConfig<TContext = unknown, TSelect = unknown, TInsert = unkn
|
|
|
330
464
|
sortableColumns?: string[];
|
|
331
465
|
/** 批量操作的最大数量限制,默认 100 */
|
|
332
466
|
maxBatchSize?: number;
|
|
467
|
+
/**
|
|
468
|
+
* 导出数量上限,默认 5000
|
|
469
|
+
* 超过此数量时 export 路由返回 hasMore=true
|
|
470
|
+
* 消费端可通过 middleware.export 接入异步队列处理大量数据
|
|
471
|
+
*/
|
|
472
|
+
maxExportSize?: number;
|
|
333
473
|
/**
|
|
334
474
|
* 软删除配置
|
|
335
475
|
* 开启后:
|
|
@@ -387,20 +527,39 @@ interface CrudProcedures<TSelect, TInsert, TUpdate> {
|
|
|
387
527
|
deleteMany: AnyProcedure;
|
|
388
528
|
updateMany: AnyProcedure;
|
|
389
529
|
upsert: AnyProcedure;
|
|
530
|
+
export: AnyProcedure;
|
|
531
|
+
import: AnyProcedure;
|
|
532
|
+
createMany: AnyProcedure;
|
|
390
533
|
}
|
|
391
534
|
//#endregion
|
|
392
535
|
//#region src/routers/_factory.d.ts
|
|
536
|
+
/**
|
|
537
|
+
* createCrudRouter 返回类型
|
|
538
|
+
*/
|
|
539
|
+
type CrudRouterReturn<TSelect, TInsert, TUpdate> = ReturnType<typeof router> & {
|
|
540
|
+
procedures: CrudProcedures<TSelect, TInsert, TUpdate>;
|
|
541
|
+
};
|
|
393
542
|
/**
|
|
394
543
|
* 创建 CRUD Router
|
|
395
544
|
*
|
|
396
545
|
* @typeParam TContext - 上下文类型(包含 db)
|
|
397
|
-
* @typeParam TSelect -
|
|
398
|
-
* @typeParam TInsert - 创建输入类型(从
|
|
399
|
-
* @typeParam TUpdate - 更新输入类型(从 updateSchema 推断)
|
|
546
|
+
* @typeParam TSelect - 查询返回类型
|
|
547
|
+
* @typeParam TInsert - 创建输入类型(从 schema 推断)
|
|
548
|
+
* @typeParam TUpdate - 更新输入类型(从 updateSchema 或 schema.partial() 推断)
|
|
400
549
|
*/
|
|
401
|
-
declare function createCrudRouter<
|
|
402
|
-
|
|
403
|
-
|
|
550
|
+
declare function createCrudRouter<TTable extends PgTable, TContext, TSelect, TInsert, TUpdate>(config: CrudRouterConfig<TTable, TContext, TSelect, TInsert, TUpdate> & {
|
|
551
|
+
schema: z.ZodType<TInsert>;
|
|
552
|
+
updateSchema: z.ZodType<TUpdate>;
|
|
553
|
+
}): CrudRouterReturn<TSelect, TInsert, TUpdate>;
|
|
554
|
+
declare function createCrudRouter<TTable extends PgTable, TContext = unknown>(config: Omit<CrudRouterConfig<TTable, TContext>, "schema" | "updateSchema"> & {
|
|
555
|
+
schema?: undefined;
|
|
556
|
+
updateSchema?: undefined;
|
|
557
|
+
}): CrudRouterReturn<InferSelectModel<TTable>, InferInsertModel<TTable>, Partial<InferInsertModel<TTable>>>;
|
|
558
|
+
declare function createCrudRouter<TTable extends PgTable, TContext, TInsert>(config: Omit<CrudRouterConfig<TTable, TContext, unknown, TInsert, unknown>, "updateSchema"> & {
|
|
559
|
+
schema: z.ZodType<TInsert>;
|
|
560
|
+
updateSchema?: undefined;
|
|
561
|
+
}): CrudRouterReturn<unknown, TInsert, Partial<TInsert>>;
|
|
562
|
+
declare function createCrudRouter<TTable extends PgTable, TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown>(config: CrudRouterConfig<TTable, TContext, TSelect, TInsert, TUpdate>): CrudRouterReturn<TSelect, TInsert, TUpdate>;
|
|
404
563
|
//#endregion
|
|
405
564
|
//#region src/lib/middleware-helpers.d.ts
|
|
406
565
|
/**
|
|
@@ -468,4 +627,4 @@ declare const appRouter: _trpc_server2.TRPCBuiltRouter<{
|
|
|
468
627
|
}, _trpc_server2.TRPCDecorateCreateRouterOptions<{}>>;
|
|
469
628
|
type AppRouter = typeof appRouter;
|
|
470
629
|
//#endregion
|
|
471
|
-
export { type AnyProcedure, type AppRouter, type CreateMiddlewareParams, type CrudMiddleware, type CrudOperation, type CrudProcedures, type CrudRouterConfig, type DeleteManyMiddlewareParams, type DeleteMiddlewareParams, type GetMiddlewareParams, type ListInput, type ListMiddlewareParams, type ListResult, type ProcedureConfig, type ProcedureFactory, type ProcedureMap, type SoftDeleteConfig, type SoftDeleteOption, type UpdateManyMiddlewareParams, type UpdateMiddlewareParams, type UpsertMiddlewareParams, type WriteOperation, afterMiddleware, appRouter, beforeMiddleware, composeMiddleware, createCrudRouter, publicProcedure, router };
|
|
630
|
+
export { type AnyProcedure, type AppRouter, type CreateManyMiddlewareParams, type CreateMiddlewareParams, type CrudMiddleware, type CrudOperation, type CrudProcedures, type CrudRouterConfig, type DeleteManyMiddlewareParams, type DeleteMiddlewareParams, type ExportInput, type ExportMiddlewareParams, type ExportResult, type GetMiddlewareParams, type ImportFailedRow, type ImportInput, type ImportMiddlewareParams, type ImportResult, type ListInput, type ListMiddlewareParams, type ListResult, type ProcedureConfig, type ProcedureFactory, type ProcedureMap, type SoftDeleteConfig, type SoftDeleteOption, type UpdateManyMiddlewareParams, type UpdateMiddlewareParams, type UpsertMiddlewareParams, type WriteOperation, afterMiddleware, appRouter, beforeMiddleware, composeMiddleware, createCrudRouter, publicProcedure, router };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { SQL } from "drizzle-orm";
|
|
2
|
+
import { InferInsertModel, InferSelectModel, SQL } from "drizzle-orm";
|
|
3
3
|
import * as _trpc_server2 from "@trpc/server";
|
|
4
4
|
import superjson from "superjson";
|
|
5
|
-
import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
6
5
|
import { PgTable } from "drizzle-orm/pg-core";
|
|
6
|
+
import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
7
7
|
|
|
8
8
|
//#region src/trpc.d.ts
|
|
9
9
|
/**
|
|
@@ -22,8 +22,13 @@ declare const router: _trpc_server2.TRPCRouterBuilder<{
|
|
|
22
22
|
declare const publicProcedure: _trpc_server2.TRPCProcedureBuilder<Context, object, object, _trpc_server2.TRPCUnsetMarker, _trpc_server2.TRPCUnsetMarker, _trpc_server2.TRPCUnsetMarker, _trpc_server2.TRPCUnsetMarker, false>;
|
|
23
23
|
//#endregion
|
|
24
24
|
//#region src/types/config.d.ts
|
|
25
|
-
type CrudOperation = "list" | "get" | "create" | "update" | "delete" | "deleteMany" | "updateMany" | "upsert";
|
|
25
|
+
type CrudOperation = "list" | "get" | "create" | "update" | "delete" | "deleteMany" | "updateMany" | "upsert" | "export" | "import" | "createMany";
|
|
26
26
|
type WriteOperation = "create" | "update";
|
|
27
|
+
/**
|
|
28
|
+
* 表字段键类型提取
|
|
29
|
+
* 用于 omitFields 的强类型支持
|
|
30
|
+
*/
|
|
31
|
+
type TableColumnKeys<T extends PgTable> = keyof T["_"]["columns"];
|
|
27
32
|
type AnyProcedure = any;
|
|
28
33
|
interface SoftDeleteConfig {
|
|
29
34
|
/** 软删除标记列名 */
|
|
@@ -71,6 +76,70 @@ interface ListResult<TSelect> {
|
|
|
71
76
|
perPage: number;
|
|
72
77
|
pageCount: number;
|
|
73
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* 导出查询输入类型(复用 ListInput 的筛选/排序,无分页)
|
|
81
|
+
*/
|
|
82
|
+
interface ExportInput {
|
|
83
|
+
sort?: Array<{
|
|
84
|
+
id: string;
|
|
85
|
+
desc: boolean;
|
|
86
|
+
}>;
|
|
87
|
+
filters?: Array<{
|
|
88
|
+
id: string;
|
|
89
|
+
value: string | string[];
|
|
90
|
+
variant: string;
|
|
91
|
+
operator: string;
|
|
92
|
+
filterId: string;
|
|
93
|
+
}>;
|
|
94
|
+
joinOperator?: "and" | "or";
|
|
95
|
+
/** 导出数量限制,会被 clamp 到 [1, maxExportSize] */
|
|
96
|
+
limit?: number;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 导出查询结果类型
|
|
100
|
+
*/
|
|
101
|
+
interface ExportResult<TSelect> {
|
|
102
|
+
data: TSelect[];
|
|
103
|
+
total: number;
|
|
104
|
+
/** 是否还有更多数据未导出(total > data.length) */
|
|
105
|
+
hasMore: boolean;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 导入行失败详情
|
|
109
|
+
*/
|
|
110
|
+
interface ImportFailedRow {
|
|
111
|
+
/** 行号(0-indexed) */
|
|
112
|
+
row: number;
|
|
113
|
+
/** 验证错误信息列表 */
|
|
114
|
+
errors: string[];
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* 导入结果类型
|
|
118
|
+
*/
|
|
119
|
+
interface ImportResult {
|
|
120
|
+
/** 成功新建的行数 */
|
|
121
|
+
success: number;
|
|
122
|
+
/** 更新的行数(onConflict="upsert" 时) */
|
|
123
|
+
updated: number;
|
|
124
|
+
/** 跳过的行数(如重复 ID,onConflict="skip" 时) */
|
|
125
|
+
skipped: number;
|
|
126
|
+
/** 失败的行详情 */
|
|
127
|
+
failed: ImportFailedRow[];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 导入输入类型
|
|
131
|
+
*/
|
|
132
|
+
interface ImportInput {
|
|
133
|
+
/** 待导入的数据行(客户端已解析为对象数组) */
|
|
134
|
+
rows: unknown[];
|
|
135
|
+
/**
|
|
136
|
+
* 冲突处理策略
|
|
137
|
+
* - "skip": 跳过冲突行(默认)
|
|
138
|
+
* - "upsert": 存在则更新,不存在则新建
|
|
139
|
+
* - "error": 冲突行计入失败
|
|
140
|
+
*/
|
|
141
|
+
onConflict?: "skip" | "upsert" | "error";
|
|
142
|
+
}
|
|
74
143
|
interface ListMiddlewareParams<TContext, TSelect> {
|
|
75
144
|
ctx: TContext;
|
|
76
145
|
input: ListInput;
|
|
@@ -122,6 +191,24 @@ interface UpsertMiddlewareParams<TContext, TSelect, TInsert> {
|
|
|
122
191
|
isNew: boolean;
|
|
123
192
|
}>;
|
|
124
193
|
}
|
|
194
|
+
interface ExportMiddlewareParams<TContext, TSelect> {
|
|
195
|
+
ctx: TContext;
|
|
196
|
+
input: ExportInput;
|
|
197
|
+
next: (input?: ExportInput) => Promise<ExportResult<TSelect>>;
|
|
198
|
+
}
|
|
199
|
+
interface ImportMiddlewareParams<TContext> {
|
|
200
|
+
ctx: TContext;
|
|
201
|
+
input: ImportInput;
|
|
202
|
+
next: (input?: ImportInput) => Promise<ImportResult>;
|
|
203
|
+
}
|
|
204
|
+
interface CreateManyMiddlewareParams<TContext, TSelect, TInsert> {
|
|
205
|
+
ctx: TContext;
|
|
206
|
+
input: TInsert[];
|
|
207
|
+
next: (input?: TInsert[]) => Promise<{
|
|
208
|
+
created: TSelect[];
|
|
209
|
+
count: number;
|
|
210
|
+
}>;
|
|
211
|
+
}
|
|
125
212
|
/**
|
|
126
213
|
* 操作包装器 - 类似 tRPC middleware 的 next 模式
|
|
127
214
|
*
|
|
@@ -191,6 +278,23 @@ interface CrudMiddleware<TContext = unknown, TSelect = unknown, TInsert = unknow
|
|
|
191
278
|
data: TSelect;
|
|
192
279
|
isNew: boolean;
|
|
193
280
|
}>;
|
|
281
|
+
/**
|
|
282
|
+
* 导出包装器
|
|
283
|
+
* 可用于审计日志、限流、异步队列调度
|
|
284
|
+
*/
|
|
285
|
+
export?: (params: ExportMiddlewareParams<TContext, TSelect>) => Promise<ExportResult<TSelect>>;
|
|
286
|
+
/**
|
|
287
|
+
* 导入包装器
|
|
288
|
+
* 可用于审计日志、限流、异步队列调度
|
|
289
|
+
*/
|
|
290
|
+
import?: (params: ImportMiddlewareParams<TContext>) => Promise<ImportResult>;
|
|
291
|
+
/**
|
|
292
|
+
* 批量创建包装器
|
|
293
|
+
*/
|
|
294
|
+
createMany?: (params: CreateManyMiddlewareParams<TContext, TSelect, TInsert>) => Promise<{
|
|
295
|
+
created: TSelect[];
|
|
296
|
+
count: number;
|
|
297
|
+
}>;
|
|
194
298
|
}
|
|
195
299
|
/**
|
|
196
300
|
* Procedure 映射对象
|
|
@@ -205,6 +309,9 @@ interface ProcedureMap {
|
|
|
205
309
|
deleteMany?: AnyProcedure;
|
|
206
310
|
updateMany?: AnyProcedure;
|
|
207
311
|
upsert?: AnyProcedure;
|
|
312
|
+
export?: AnyProcedure;
|
|
313
|
+
import?: AnyProcedure;
|
|
314
|
+
createMany?: AnyProcedure;
|
|
208
315
|
/** 未指定操作时的默认 procedure */
|
|
209
316
|
default?: AnyProcedure;
|
|
210
317
|
}
|
|
@@ -271,13 +378,37 @@ type ProcedureConfig = AnyProcedure | ProcedureMap | ProcedureFactory;
|
|
|
271
378
|
* authorize: (ctx, resource) => resource.ownerId === ctx.user.id,
|
|
272
379
|
* })
|
|
273
380
|
*/
|
|
274
|
-
interface CrudRouterConfig<TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown> {
|
|
381
|
+
interface CrudRouterConfig<TTable extends PgTable = PgTable, TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown> {
|
|
275
382
|
/** Drizzle 表定义 */
|
|
276
|
-
table:
|
|
277
|
-
/**
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
383
|
+
table: TTable;
|
|
384
|
+
/**
|
|
385
|
+
* 主 Schema(用于 create/upsert 输入验证)
|
|
386
|
+
* - 如果不传,自动从 table 派生并排除 omitFields
|
|
387
|
+
* - updateSchema 默认为 schema.partial().refine(nonEmpty)
|
|
388
|
+
*
|
|
389
|
+
* @example
|
|
390
|
+
* // 自动派生
|
|
391
|
+
* createCrudRouter({ table: tasks })
|
|
392
|
+
*
|
|
393
|
+
* // 显式传入
|
|
394
|
+
* createCrudRouter({ table: tasks, schema: taskSchema })
|
|
395
|
+
*/
|
|
396
|
+
schema?: z.ZodType<TInsert>;
|
|
397
|
+
/**
|
|
398
|
+
* 更新输入 Schema(可选)
|
|
399
|
+
* - 如果不传,自动从 schema.partial() 派生
|
|
400
|
+
* - 传入时覆盖自动派生
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* createCrudRouter({
|
|
404
|
+
* table: tasks,
|
|
405
|
+
* schema: taskSchema,
|
|
406
|
+
* updateSchema: customUpdateSchema, // 覆盖自动派生
|
|
407
|
+
* })
|
|
408
|
+
*/
|
|
409
|
+
updateSchema?: z.ZodType<TUpdate>;
|
|
410
|
+
/** 查询返回 Schema */
|
|
411
|
+
selectSchema?: z.ZodType<TSelect>;
|
|
281
412
|
/**
|
|
282
413
|
* Procedure 配置(统一字段)
|
|
283
414
|
*
|
|
@@ -321,8 +452,11 @@ interface CrudRouterConfig<TContext = unknown, TSelect = unknown, TInsert = unkn
|
|
|
321
452
|
* authorize: (ctx, resource, op) => resource.ownerId === ctx.user.id
|
|
322
453
|
*/
|
|
323
454
|
authorize?: (ctx: TContext, resource: TSelect, operation: CrudOperation) => boolean | Promise<boolean>;
|
|
324
|
-
/**
|
|
325
|
-
|
|
455
|
+
/**
|
|
456
|
+
* 要从 schema 排除的字段(自动派生时使用)
|
|
457
|
+
* @default ["id", "createdAt", "updatedAt"]
|
|
458
|
+
*/
|
|
459
|
+
omitFields?: TableColumnKeys<TTable>[];
|
|
326
460
|
/** ID 字段名,默认 "id" */
|
|
327
461
|
idField?: string;
|
|
328
462
|
/** 可过滤的列白名单 */
|
|
@@ -331,6 +465,12 @@ interface CrudRouterConfig<TContext = unknown, TSelect = unknown, TInsert = unkn
|
|
|
331
465
|
sortableColumns?: string[];
|
|
332
466
|
/** 批量操作的最大数量限制,默认 100 */
|
|
333
467
|
maxBatchSize?: number;
|
|
468
|
+
/**
|
|
469
|
+
* 导出数量上限,默认 5000
|
|
470
|
+
* 超过此数量时 export 路由返回 hasMore=true
|
|
471
|
+
* 消费端可通过 middleware.export 接入异步队列处理大量数据
|
|
472
|
+
*/
|
|
473
|
+
maxExportSize?: number;
|
|
334
474
|
/**
|
|
335
475
|
* 软删除配置
|
|
336
476
|
* 开启后:
|
|
@@ -388,20 +528,39 @@ interface CrudProcedures<TSelect, TInsert, TUpdate> {
|
|
|
388
528
|
deleteMany: AnyProcedure;
|
|
389
529
|
updateMany: AnyProcedure;
|
|
390
530
|
upsert: AnyProcedure;
|
|
531
|
+
export: AnyProcedure;
|
|
532
|
+
import: AnyProcedure;
|
|
533
|
+
createMany: AnyProcedure;
|
|
391
534
|
}
|
|
392
535
|
//#endregion
|
|
393
536
|
//#region src/routers/_factory.d.ts
|
|
537
|
+
/**
|
|
538
|
+
* createCrudRouter 返回类型
|
|
539
|
+
*/
|
|
540
|
+
type CrudRouterReturn<TSelect, TInsert, TUpdate> = ReturnType<typeof router> & {
|
|
541
|
+
procedures: CrudProcedures<TSelect, TInsert, TUpdate>;
|
|
542
|
+
};
|
|
394
543
|
/**
|
|
395
544
|
* 创建 CRUD Router
|
|
396
545
|
*
|
|
397
546
|
* @typeParam TContext - 上下文类型(包含 db)
|
|
398
|
-
* @typeParam TSelect -
|
|
399
|
-
* @typeParam TInsert - 创建输入类型(从
|
|
400
|
-
* @typeParam TUpdate - 更新输入类型(从 updateSchema 推断)
|
|
547
|
+
* @typeParam TSelect - 查询返回类型
|
|
548
|
+
* @typeParam TInsert - 创建输入类型(从 schema 推断)
|
|
549
|
+
* @typeParam TUpdate - 更新输入类型(从 updateSchema 或 schema.partial() 推断)
|
|
401
550
|
*/
|
|
402
|
-
declare function createCrudRouter<
|
|
403
|
-
|
|
404
|
-
|
|
551
|
+
declare function createCrudRouter<TTable extends PgTable, TContext, TSelect, TInsert, TUpdate>(config: CrudRouterConfig<TTable, TContext, TSelect, TInsert, TUpdate> & {
|
|
552
|
+
schema: z.ZodType<TInsert>;
|
|
553
|
+
updateSchema: z.ZodType<TUpdate>;
|
|
554
|
+
}): CrudRouterReturn<TSelect, TInsert, TUpdate>;
|
|
555
|
+
declare function createCrudRouter<TTable extends PgTable, TContext = unknown>(config: Omit<CrudRouterConfig<TTable, TContext>, "schema" | "updateSchema"> & {
|
|
556
|
+
schema?: undefined;
|
|
557
|
+
updateSchema?: undefined;
|
|
558
|
+
}): CrudRouterReturn<InferSelectModel<TTable>, InferInsertModel<TTable>, Partial<InferInsertModel<TTable>>>;
|
|
559
|
+
declare function createCrudRouter<TTable extends PgTable, TContext, TInsert>(config: Omit<CrudRouterConfig<TTable, TContext, unknown, TInsert, unknown>, "updateSchema"> & {
|
|
560
|
+
schema: z.ZodType<TInsert>;
|
|
561
|
+
updateSchema?: undefined;
|
|
562
|
+
}): CrudRouterReturn<unknown, TInsert, Partial<TInsert>>;
|
|
563
|
+
declare function createCrudRouter<TTable extends PgTable, TContext = unknown, TSelect = unknown, TInsert = unknown, TUpdate = unknown>(config: CrudRouterConfig<TTable, TContext, TSelect, TInsert, TUpdate>): CrudRouterReturn<TSelect, TInsert, TUpdate>;
|
|
405
564
|
//#endregion
|
|
406
565
|
//#region src/lib/middleware-helpers.d.ts
|
|
407
566
|
/**
|
|
@@ -469,4 +628,4 @@ declare const appRouter: _trpc_server2.TRPCBuiltRouter<{
|
|
|
469
628
|
}, _trpc_server2.TRPCDecorateCreateRouterOptions<{}>>;
|
|
470
629
|
type AppRouter = typeof appRouter;
|
|
471
630
|
//#endregion
|
|
472
|
-
export { type AnyProcedure, type AppRouter, type CreateMiddlewareParams, type CrudMiddleware, type CrudOperation, type CrudProcedures, type CrudRouterConfig, type DeleteManyMiddlewareParams, type DeleteMiddlewareParams, type GetMiddlewareParams, type ListInput, type ListMiddlewareParams, type ListResult, type ProcedureConfig, type ProcedureFactory, type ProcedureMap, type SoftDeleteConfig, type SoftDeleteOption, type UpdateManyMiddlewareParams, type UpdateMiddlewareParams, type UpsertMiddlewareParams, type WriteOperation, afterMiddleware, appRouter, beforeMiddleware, composeMiddleware, createCrudRouter, publicProcedure, router };
|
|
631
|
+
export { type AnyProcedure, type AppRouter, type CreateManyMiddlewareParams, type CreateMiddlewareParams, type CrudMiddleware, type CrudOperation, type CrudProcedures, type CrudRouterConfig, type DeleteManyMiddlewareParams, type DeleteMiddlewareParams, type ExportInput, type ExportMiddlewareParams, type ExportResult, type GetMiddlewareParams, type ImportFailedRow, type ImportInput, type ImportMiddlewareParams, type ImportResult, type ListInput, type ListMiddlewareParams, type ListResult, type ProcedureConfig, type ProcedureFactory, type ProcedureMap, type SoftDeleteConfig, type SoftDeleteOption, type UpdateManyMiddlewareParams, type UpdateMiddlewareParams, type UpsertMiddlewareParams, type WriteOperation, afterMiddleware, appRouter, beforeMiddleware, composeMiddleware, createCrudRouter, publicProcedure, router };
|