@ai0x0/utils 0.0.14 → 0.0.16

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 (48) hide show
  1. package/SKILL.md +336 -0
  2. package/es/__shims__/next-rest-framework.d.ts +48 -0
  3. package/es/backend/actions/create-delete-action.d.ts +1 -1
  4. package/es/backend/actions/create-get-action.d.ts +2 -2
  5. package/es/backend/actions/create-get-action.js +1 -1
  6. package/es/backend/actions/create-get-list-action.d.ts +3 -3
  7. package/es/backend/actions/create-get-list-action.js +3 -3
  8. package/es/backend/actions/create-post-action.d.ts +2 -2
  9. package/es/backend/actions/create-post-action.js +8 -2
  10. package/es/backend/actions/create-put-action.d.ts +3 -3
  11. package/es/backend/actions/get-list-data.d.ts +3 -15
  12. package/es/backend/actions/get-list-query.d.ts +5 -7
  13. package/es/backend/actions/transform-body.d.ts +1 -1
  14. package/es/backend/actions/transform-body.js +0 -2
  15. package/es/backend/route-operation/delete-operation.d.ts +2 -2
  16. package/es/backend/route-operation/get-list-operation.d.ts +2 -2
  17. package/es/backend/route-operation/get-operation.d.ts +3 -3
  18. package/es/backend/route-operation/get-operation.js +18 -24
  19. package/es/backend/route-operation/post-operation.d.ts +2 -2
  20. package/es/backend/route-operation/post-operation.js +21 -16
  21. package/es/backend/route-operation/put-operation.d.ts +2 -2
  22. package/es/backend/route-operation/put-operation.js +21 -16
  23. package/es/backend/schemas/index.d.ts +76 -1249
  24. package/es/backend/schemas/index.js +1 -6
  25. package/lib/__shims__/next-rest-framework.d.ts +48 -0
  26. package/lib/backend/actions/create-delete-action.d.ts +1 -1
  27. package/lib/backend/actions/create-get-action.d.ts +2 -2
  28. package/lib/backend/actions/create-get-list-action.d.ts +3 -3
  29. package/lib/backend/actions/create-post-action.d.ts +2 -2
  30. package/lib/backend/actions/create-post-action.js +3 -1
  31. package/lib/backend/actions/create-put-action.d.ts +3 -3
  32. package/lib/backend/actions/create-put-action.js +4 -1
  33. package/lib/backend/actions/get-list-data.d.ts +3 -15
  34. package/lib/backend/actions/get-list-query.d.ts +5 -7
  35. package/lib/backend/actions/transform-body.d.ts +1 -1
  36. package/lib/backend/actions/transform-body.js +3 -1
  37. package/lib/backend/route-operation/delete-operation.d.ts +2 -2
  38. package/lib/backend/route-operation/get-list-operation.d.ts +2 -2
  39. package/lib/backend/route-operation/get-list-operation.js +7 -2
  40. package/lib/backend/route-operation/get-operation.d.ts +3 -3
  41. package/lib/backend/route-operation/get-operation.js +6 -3
  42. package/lib/backend/route-operation/post-operation.d.ts +2 -2
  43. package/lib/backend/route-operation/post-operation.js +5 -5
  44. package/lib/backend/route-operation/put-operation.d.ts +2 -2
  45. package/lib/backend/route-operation/put-operation.js +5 -5
  46. package/lib/backend/schemas/index.d.ts +76 -1249
  47. package/lib/backend/schemas/index.js +12 -14
  48. package/package.json +39 -35
package/SKILL.md ADDED
@@ -0,0 +1,336 @@
1
+ ---
2
+ name: ai0x0-utils-backend
3
+ description: Scaffold Next.js App Router CRUD endpoints and drizzle-orm(pg) tables with `@ai0x0/utils`. Use when a project needs standard list/get/create/update/delete routes backed by drizzle-orm + zod + next-rest-framework, auto-injected base fields (id / creatorId / createdAt…), paginated list queries with joins, or ready-to-use select/insert/update Zod schemas. Pair with the `create-next-rest-framework-api` skill — this skill replaces hand-written `routeOperation(...).input(...).outputs(...).handler(...)` chains with a declarative factory API exposed inside `next-rest-framework`'s `route({...})`.
4
+ ---
5
+
6
+ # @ai0x0/utils Backend
7
+
8
+ Declarative CRUD factory on top of `next-rest-framework` v6, `drizzle-orm/pg-core`, `drizzle-zod`, and `zod` v4. Each factory returns a `RouteOperationDefinition<Method>` so it plugs directly into `route({ … })` from next-rest-framework.
9
+
10
+ ## Workflow
11
+
12
+ 1. Create a shared options module (once per project) that pre-binds `{ db, getSession }` to every operation factory (see "Project Setup" below). Route files never import `db`/`getSession` directly.
13
+ 2. For each domain entity, place a `table.ts` next to an `index.ts`:
14
+ - `table.ts` — call `createTableSchema({ name, columns })` and re-export `table` only.
15
+ - `index.ts` — compose the zod schemas (`insertXxxSchema`, `selectXxxSchema`, `updateXxxSchema`, `queryXxxSchema`, `queryListXxxSchema`, `queryListSelectXxxSchema`). Extend with `.merge(z.object(...))` when the business exposes non-column fields (tags, computed columns).
16
+ 3. Author the CRUD `route.ts` by wrapping the pre-bound operations inside next-rest-framework's `route({...})`. Name each operation key descriptively — it is the OpenAPI `operationId`.
17
+ 4. Drop down to raw `routeOperation(...)` (via the `create-next-rest-framework-api` skill) when the endpoint is non-CRUD (auth, webhooks, streaming, multi-status) or needs custom `TypedNextResponse` unions.
18
+ 5. Reuse action-level helpers (`createGetAction`, `createGetListAction`, etc.) inside server actions, cron jobs, queue consumers, or the raw-`routeOperation` handlers — same API, no request wrapping.
19
+
20
+ ## Project Setup
21
+
22
+ Create three files once and reuse everywhere:
23
+
24
+ ```ts
25
+ // app/(backend)/db/schemas/_helper.ts — re-export + lock import path
26
+ export {
27
+ createTableSchema,
28
+ queryListSchema,
29
+ listBodySchema,
30
+ } from "@ai0x0/utils/lib/backend/schemas";
31
+ ```
32
+
33
+ ```ts
34
+ // app/(backend)/utils/actions/_helper.ts — action-level helpers
35
+ export {
36
+ createDeleteAction,
37
+ createGetAction,
38
+ createGetListAction,
39
+ createPostAction,
40
+ createPutAction,
41
+ } from "@ai0x0/utils/lib/backend/actions";
42
+ ```
43
+
44
+ ```ts
45
+ // app/(backend)/utils/route-operation/index.ts — pre-bind db + getSession
46
+ import {
47
+ createGetOperation,
48
+ createPutOperation,
49
+ createPostOperation,
50
+ createDeleteOperation,
51
+ createGetListOperation,
52
+ } from "@ai0x0/utils/lib/backend";
53
+ import { db } from "@backend/db";
54
+ import getSession from "@backend/utils/get-session";
55
+
56
+ export const postOperation = createPostOperation({ db, getSession });
57
+ export const deleteOperation = createDeleteOperation({ db, getSession });
58
+ export const putOperation = createPutOperation({ db, getSession });
59
+ export const getOperation = createGetOperation({ db, getSession });
60
+ export const getListOperation = createGetListOperation({ db, getSession });
61
+ ```
62
+
63
+ `getSession(req)` **must** return `{ userId?: string } | undefined` (a Promise is fine). Throwing rejects the request; returning `undefined` disables ownership checks for that call.
64
+
65
+ ## Factory Catalog
66
+
67
+ | Export | Purpose | Required options | Notable optional options |
68
+ | ------------------- | -------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------- |
69
+ | `createTableSchema` | pg `Table` + 5 zod schemas | `name`, `columns` | `refineSchema`, `extraConfig` |
70
+ | `getOperation` | GET one by filters | `table`, `bodySchema`, `querySchema` | `setParams`, `relations`, `jsonArrayFields`, `byCreator`, `onSuccess`, `onError`, `summary` |
71
+ | `getListOperation` | GET paginated list | `table`, `bodySchema`, `querySchema` | `setParams`, `relations`, `jsonArrayFields`, `onSuccess`, `onError`, `summary` |
72
+ | `postOperation` | POST create | `table`, `bodySchema` | `outputBodySchema`, `setBody`, `onSuccess`, `onError`, `summary` |
73
+ | `putOperation` | PUT update | `table`, `bodySchema` | `outputBodySchema`, `setBody`, `byCreator`, `onSuccess`, `onError`, `summary` |
74
+ | `deleteOperation` | DELETE | `table` | `byCreator`, `onSuccess`, `onError`, `summary` |
75
+
76
+ ## Canonical Examples
77
+
78
+ ### 1. Table + schemas (`table.ts` + `index.ts`)
79
+
80
+ ```ts
81
+ // app/(backend)/db/schemas/agent/table.ts
82
+ import { jsonb, text } from "drizzle-orm/pg-core";
83
+ import { createTableSchema } from "@backend/db/schemas/_helper";
84
+
85
+ export const agentColumns = {
86
+ name: text("name"),
87
+ modelId: text("model_id"),
88
+ tags: jsonb("tags"),
89
+ mcpIds: jsonb("mcp_ids"),
90
+ };
91
+
92
+ export const { table: agents } = createTableSchema({
93
+ name: "agents",
94
+ columns: agentColumns,
95
+ });
96
+ ```
97
+
98
+ ```ts
99
+ // app/(backend)/db/schemas/agent/index.ts
100
+ import { createInsertSchema, createSelectSchema } from "drizzle-zod";
101
+ import { z } from "zod";
102
+ import { queryListSchema } from "@backend/db/schemas";
103
+ import { agents } from "./table";
104
+
105
+ export { agents, agentColumns } from "./table";
106
+
107
+ export const insertAgentSchema = createInsertSchema(agents).merge(
108
+ z.object({
109
+ mcpIds: z.array(z.string()).optional(),
110
+ tags: z.array(z.string()).optional(),
111
+ }),
112
+ );
113
+ export const selectAgentSchema = createSelectSchema(agents).merge(
114
+ z.object({
115
+ mcpIds: z.array(z.string()).optional(),
116
+ tags: z.array(z.string()).optional(),
117
+ }),
118
+ );
119
+ export const updateAgentSchema = insertAgentSchema.required({ id: true });
120
+ export const queryAgentSchema = insertAgentSchema.partial();
121
+ export const queryListAgentSchema = queryListSchema(
122
+ selectAgentSchema.partial().merge(
123
+ z.object({ tags: z.string().optional() }), // 列表里 jsonArray 以逗号分隔字符串传入
124
+ ),
125
+ );
126
+ export const queryListSelectAgentSchema = selectAgentSchema;
127
+ ```
128
+
129
+ Note the two-layer shape: `queryListSchema(...)` input is the **partial of the select schema** (optionally merged with extra querystring-only fields); `bodySchema` in `getListOperation` stays as the full select schema (`queryListSelectAgentSchema`).
130
+
131
+ ### 2. Detail CRUD route
132
+
133
+ ```ts
134
+ // app/(backend)/api/agent/route.ts
135
+ import { route } from "next-rest-framework";
136
+ import {
137
+ agents,
138
+ insertAgentSchema,
139
+ queryAgentSchema,
140
+ selectAgentSchema,
141
+ updateAgentSchema,
142
+ } from "@backend/db/schemas";
143
+ import {
144
+ deleteOperation,
145
+ getOperation,
146
+ postOperation,
147
+ putOperation,
148
+ } from "@backend/utils/route-operation";
149
+ import getSession from "@backend/utils/get-session";
150
+ import { seedAgentData } from "@backend/utils/actions";
151
+
152
+ export const { POST, GET, DELETE, PUT } = route({
153
+ getAgent: getOperation({
154
+ querySchema: queryAgentSchema,
155
+ bodySchema: selectAgentSchema,
156
+ table: agents,
157
+ summary: "助手详情",
158
+ setParams: async (req) => {
159
+ const { userId } = (await getSession(req)) || {};
160
+ await seedAgentData(userId as string);
161
+ return {};
162
+ },
163
+ }),
164
+ postAgent: postOperation({
165
+ bodySchema: insertAgentSchema,
166
+ table: agents,
167
+ summary: "添加助手",
168
+ setBody: async () => ({ tags: ["my"] }),
169
+ }),
170
+ putAgent: putOperation({
171
+ bodySchema: updateAgentSchema,
172
+ table: agents,
173
+ summary: "编辑助手",
174
+ }),
175
+ deleteAgent: deleteOperation({
176
+ table: agents,
177
+ summary: "删除助手",
178
+ }),
179
+ });
180
+ ```
181
+
182
+ ### 3. List route with relations + `onSuccess` tree building
183
+
184
+ ```ts
185
+ // app/(backend)/api/channel/list/route.ts
186
+ import { route } from "next-rest-framework";
187
+ import { eq, sql } from "drizzle-orm";
188
+ import {
189
+ channels,
190
+ models,
191
+ queryListChannelSchema,
192
+ queryListSelectChannelSchema,
193
+ } from "@backend/db/schemas";
194
+ import { getListOperation } from "@backend/utils/route-operation";
195
+ import getSession from "@backend/utils/get-session";
196
+ import { seedChannelData } from "@backend/utils/actions/channel";
197
+
198
+ export const { GET } = route({
199
+ getChannelList: getListOperation({
200
+ querySchema: queryListChannelSchema,
201
+ bodySchema: queryListSelectChannelSchema,
202
+ table: channels,
203
+ summary: "获取渠道列表",
204
+ relations: [
205
+ {
206
+ table: models,
207
+ sql: eq(models.channelId, channels.id),
208
+ select: {
209
+ models: sql`(
210
+ SELECT array_agg(DISTINCT jsonb_strip_nulls(to_jsonb(models.*)))
211
+ FROM ${models}
212
+ WHERE ${models.channelId} = ${channels.id}
213
+ )`,
214
+ },
215
+ },
216
+ ],
217
+ setParams: async (req) => {
218
+ const { userId } = (await getSession(req)) || {};
219
+ await seedChannelData(userId as string);
220
+ return {};
221
+ },
222
+ onSuccess: async (result) => {
223
+ // 内部字段过滤 / 映射 / 树化都写在这里
224
+ return result;
225
+ },
226
+ }),
227
+ });
228
+ ```
229
+
230
+ For list routes that consume `jsonb` arrays as comma-separated querystring values, add `jsonArrayFields: ["tags"]`.
231
+
232
+ ### 4. Escape hatch — drop to raw `routeOperation` but reuse actions
233
+
234
+ When the endpoint returns multiple status shapes (e.g. 200 success + 401 unauthorized), do **not** use the CRUD factories. Call `routeOperation` directly and reuse the action helpers for the database side:
235
+
236
+ ```ts
237
+ // app/(backend)/api/user/me/route.ts
238
+ import { TypedNextResponse, route, routeOperation } from "next-rest-framework";
239
+ import { eq } from "drizzle-orm";
240
+ import { z } from "zod";
241
+ import { db } from "@backend/db";
242
+ import { members, selectUserSchema, teams, users } from "@backend/db/schemas";
243
+ import { createGetAction } from "@backend/utils/actions";
244
+ import getSession from "@backend/utils/get-session";
245
+
246
+ export const { GET } = route({
247
+ getUserMe: routeOperation({
248
+ method: "GET",
249
+ openApiOperation: { tags: ["users"], summary: "我的信息" },
250
+ })
251
+ .outputs([
252
+ { status: 200, contentType: "application/json", body: selectUserSchema },
253
+ {
254
+ status: 401,
255
+ contentType: "application/json",
256
+ body: z.object({ message: z.string() }),
257
+ },
258
+ ])
259
+ .handler(async (req) => {
260
+ const { userId } = (await getSession(req)) || {};
261
+ const user = await createGetAction({
262
+ db,
263
+ table: users,
264
+ bodySchema: selectUserSchema,
265
+ relations: [
266
+ { table: members, sql: eq(members.userId, users.id) },
267
+ {
268
+ groupBy: true,
269
+ table: teams,
270
+ select: { team: teams },
271
+ sql: eq(teams.id, members.teamId),
272
+ },
273
+ ],
274
+ })({ id: userId });
275
+ if (!user) {
276
+ return TypedNextResponse.json(
277
+ { message: "用户不存在" },
278
+ { status: 401 },
279
+ );
280
+ }
281
+ return TypedNextResponse.json(user, { status: 200 });
282
+ }),
283
+ });
284
+ ```
285
+
286
+ ## Built-in Conventions
287
+
288
+ - **Base fields** auto-added by `createTableSchema`: `id` (uuid, pk, default random) / `creatorId` / `editorId` / `accessedAt` / `createdAt` / `updatedAt`.
289
+ - **Ownership check**: with `byCreator: true` (default on PUT/DELETE/GET), PUT/DELETE pre-fetch the row filtered by `creatorId = session.userId` and throw `"未找到…对象,或没有权限"` if missing. Set `byCreator: false` to skip (e.g. admin endpoints).
290
+ - **Auto injection**: POST writes `creatorId = session.userId`; PUT writes `editorId = session.userId`; GET/GET_LIST append `creatorId = session.userId` to the filter when `byCreator` is on.
291
+ - **Date coercion**: any body field ending in `At` is passed through `dayjs(value).toDate()` before write — accept ISO strings from clients.
292
+ - **List filtering** (all querystring values are strings):
293
+ - `key=a,b,c` → `IN (...)` when key ends with `Id`; otherwise `OR ILIKE %a% OR ILIKE %b%`
294
+ - `key=foo` where key ends with `Id` → `eq`; otherwise `ILIKE %foo%`
295
+ - `${anything}AtFrom` / `${anything}AtTo` → `gte` / `lte` against the matching `${anything}At` column
296
+ - `jsonArrayFields: ["tags"]` → `EXISTS (SELECT 1 FROM jsonb_array_elements_text(col) t WHERE t LIKE %v%)`
297
+ - **Pagination / sort**: `current` (default `"1"`), `pageSize` (default `"10"`), `orderBy` (default `createdAt`), `orderDir` (`asc|desc`, default `desc`).
298
+ - **Relations**: `relations: [{ table, sql, select, groupBy? }]` drives `leftJoin` + optional `groupBy(root.id, relation.id)`; `select` merges into the final `SELECT` projection and can contain raw `sql\`…\`` correlated sub-queries.
299
+
300
+ ## Guardrails
301
+
302
+ - Always pass `insertXxxSchema` to POST, `updateXxxSchema` (has `.required({ id: true })`) to PUT, `selectXxxSchema` to GET body, `queryListSchema(selectXxxSchema.partial())` to GET_LIST query.
303
+ - Query-string schemas stay `z.string()` — numbers / arrays from querystrings must stay strings and be parsed inside `onSuccess` or `setParams`.
304
+ - Do not reuse `insertSchema` for PUT — missing `id` silently dispatches an update without a where clause.
305
+ - `bodySchema` on list/get is the **response item** schema, not the query shape. Query shape goes in `querySchema`.
306
+ - Do not inline `{ db, getSession }` into individual route files — always import the pre-bound `postOperation` / `getListOperation` / … from `@backend/utils/route-operation` so session/DB swaps are one-file changes.
307
+ - `jsonb` columns declared with `jsonb(...)` carry no zod info — extend the matching insert/select schema with `.merge(z.object({ field: z.array(z.string()).optional() }))` to keep typing accurate.
308
+ - Swallowing errors: an unhandled throw in a handler propagates to next-rest-framework as a 500. Provide `onError` for any operation exposed to untrusted clients.
309
+ - For non-CRUD behavior (middleware chains, streaming, multipart, `TypedNextResponse` unions, RPC) stop using these factories and switch to the `create-next-rest-framework-api` skill.
310
+
311
+ ## Escape Hatches
312
+
313
+ - Extra server-side filters — `setParams(req) => Promise<Record<string, unknown>>` on GET/GET_LIST; returned keys are merged into the filter.
314
+ - Extra columns on write — `setBody(req) => Promise<Partial<infer<IB>>>` on POST/PUT; returned fields are merged into the body before validation runs against `bodySchema`.
315
+ - Post-processing output — `onSuccess(data) => Promise<data>`; on GET_LIST the payload is `{ data, total }`.
316
+ - Error rewriting — `onError(err) => Promise<Response | undefined>`. Return `undefined` to rethrow.
317
+
318
+ ## Imports
319
+
320
+ ```
321
+ @ai0x0/utils/lib/backend // actions + route-operation + schemas (CJS, used by Next.js server bundle)
322
+ @ai0x0/utils/lib/backend/actions
323
+ @ai0x0/utils/lib/backend/route-operation
324
+ @ai0x0/utils/lib/backend/schemas
325
+ ```
326
+
327
+ ESM consumers can substitute `/es/backend/...` instead of `/lib/backend/...` when Next.js resolves the `exports` map that way; prefer `/lib/backend` in Next.js projects because the server bundle is CommonJS.
328
+
329
+ ## Done Criteria
330
+
331
+ - Route files contain zero hand-written `{ db, getSession }` wiring; all operations come from `@backend/utils/route-operation`.
332
+ - Each domain has a `table.ts` (columns + `createTableSchema`) and an `index.ts` (five zod schemas + re-exports).
333
+ - Every list endpoint accepts `current / pageSize / orderBy / orderDir / *AtFrom / *AtTo` and — where applicable — `jsonArrayFields` is declared.
334
+ - `byCreator` is explicitly set when the endpoint is admin-facing or otherwise crosses ownership boundaries.
335
+ - Non-CRUD endpoints are implemented via raw `routeOperation` + action helpers, not by forcing a CRUD factory.
336
+ - `next-rest-framework validate` / `generate` (from the partner skill) still pass — the factory values are plain `RouteOperationDefinition` and participate in OpenAPI generation.
@@ -0,0 +1,48 @@
1
+ import type { NextRequest } from "next/server";
2
+ import type { ZodType } from "zod";
3
+
4
+ declare module "next-rest-framework" {
5
+ export interface RouteOperationDefinition<M extends string = string> {
6
+ _method: M;
7
+ }
8
+
9
+ interface RouteOperationBuilder<M extends string> {
10
+ input: (opts: {
11
+ body?: ZodType;
12
+ query?: ZodType;
13
+ contentType?: string;
14
+ }) => RouteOperationBuilder<M>;
15
+ outputs: (
16
+ opts: { body?: ZodType; status?: number; contentType?: string }[],
17
+ ) => RouteOperationBuilder<M>;
18
+ handler: (
19
+ fn: (req: NextRequest) => Promise<Response>,
20
+ ) => RouteOperationDefinition<M>;
21
+ }
22
+
23
+ export const routeOperation: <M extends string>(opts: {
24
+ method: M;
25
+ openApiOperation?: { summary?: string; tags?: string[] };
26
+ }) => RouteOperationBuilder<M>;
27
+
28
+ export const rpcOperation: () => {
29
+ outputs: (opts: { body?: ZodType; contentType?: string }[]) => {
30
+ handler: <T>(fn: () => Promise<T>) => () => Promise<T>;
31
+ };
32
+ };
33
+
34
+ export const TypedNextResponse: {
35
+ json: <T>(body: T, init?: { status?: number }) => Response;
36
+ };
37
+
38
+ export type TypedNextRequest<
39
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
40
+ M = string,
41
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
42
+ C = string,
43
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
44
+ B = unknown,
45
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
46
+ Q = Record<string, string>,
47
+ > = NextRequest;
48
+ }
@@ -1,7 +1,7 @@
1
1
  import { NodePgDatabase } from "drizzle-orm/node-postgres";
2
2
  import { BaseTable } from "../types";
3
3
  export declare function createDeleteAction<TTable extends BaseTable>({ table, db, }: {
4
- db: NodePgDatabase<any>;
4
+ db: NodePgDatabase<Record<string, unknown>>;
5
5
  table: TTable;
6
6
  }): ({ id, creatorId }: {
7
7
  id: string;
@@ -3,8 +3,8 @@ import { NodePgDatabase } from "drizzle-orm/node-postgres";
3
3
  import { BaseTable, GetListRelations } from "../types";
4
4
  export declare function createGetAction<T extends ZodSchema, TTable extends BaseTable>({ bodySchema, db, jsonArrayFields, relations, table, }: {
5
5
  bodySchema: T;
6
- db: NodePgDatabase<any>;
6
+ db: NodePgDatabase<Record<string, unknown>>;
7
7
  jsonArrayFields?: string[];
8
8
  relations?: GetListRelations;
9
9
  table: TTable;
10
- }): (params: Partial<z.infer<T>>) => Promise<T["_output"]>;
10
+ }): (params: Partial<z.infer<T>> & Record<string, unknown>) => Promise<z.core.output<T> | undefined>;
@@ -40,7 +40,7 @@ export function createGetAction(_ref) {
40
40
  params: params,
41
41
  relations: relations,
42
42
  table: table
43
- }), query = _getListQuery.query, countQuery = _getListQuery.countQuery; // 执行查询
43
+ }), query = _getListQuery.query, countQuery = _getListQuery.countQuery;
44
44
  _context.next = 5;
45
45
  return getListData({
46
46
  bodySchema: bodySchema,
@@ -3,11 +3,11 @@ import { BaseTable, GetListRelations } from "../types";
3
3
  import { NodePgDatabase } from "drizzle-orm/node-postgres";
4
4
  export declare function createGetListAction<T extends ZodSchema, TTable extends BaseTable>({ bodySchema, db, jsonArrayFields, relations, table, }: {
5
5
  bodySchema: T;
6
- db: NodePgDatabase<any>;
6
+ db: NodePgDatabase<Record<string, unknown>>;
7
7
  jsonArrayFields?: string[];
8
8
  relations?: GetListRelations;
9
9
  table: TTable;
10
- }): (params: Partial<z.infer<T>>) => Promise<{
11
- data: T["_output"][];
10
+ }): (params: Partial<z.infer<T>> & Record<string, unknown>) => Promise<{
11
+ data: any;
12
12
  total: number;
13
13
  }>;
@@ -15,11 +15,11 @@ export function createGetListAction(_ref) {
15
15
  table = _ref.table;
16
16
  return /*#__PURE__*/function () {
17
17
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(params) {
18
- var current, pageSize, other, fields, _i, _Object$keys, key, field, _getListQuery, query, countQuery;
18
+ var _ref3, current, pageSize, other, fields, _i, _Object$keys, key, field, _getListQuery, query, countQuery;
19
19
  return _regeneratorRuntime().wrap(function _callee$(_context) {
20
20
  while (1) switch (_context.prev = _context.next) {
21
21
  case 0:
22
- current = params.current, pageSize = params.pageSize, other = _objectWithoutProperties(params, _excluded);
22
+ _ref3 = params, current = _ref3.current, pageSize = _ref3.pageSize, other = _objectWithoutProperties(_ref3, _excluded);
23
23
  fields = {}; // eslint-disable-next-line @typescript-eslint/ban-ts-comment
24
24
  // @ts-ignore
25
25
  for (_i = 0, _Object$keys = Object.keys(bodySchema.shape); _i < _Object$keys.length; _i++) {
@@ -38,7 +38,7 @@ export function createGetListAction(_ref) {
38
38
  params: other,
39
39
  relations: relations,
40
40
  table: table
41
- }), query = _getListQuery.query, countQuery = _getListQuery.countQuery; // 执行查询
41
+ }), query = _getListQuery.query, countQuery = _getListQuery.countQuery;
42
42
  return _context.abrupt("return", getListData({
43
43
  bodySchema: bodySchema,
44
44
  countQuery: countQuery,
@@ -3,6 +3,6 @@ import { PgTable } from "drizzle-orm/pg-core";
3
3
  import { NodePgDatabase } from "drizzle-orm/node-postgres";
4
4
  export declare function createPostAction<T extends ZodSchema, TTable extends PgTable>({ table, db, }: {
5
5
  bodySchema: T;
6
- db: NodePgDatabase<any>;
6
+ db: NodePgDatabase<Record<string, unknown>>;
7
7
  table: TTable;
8
- }): (body: z.infer<T>) => Promise<T["_output"][]>;
8
+ }): (body: z.infer<T>) => Promise<z.infer<T>[]>;
@@ -8,11 +8,17 @@ export function createPostAction(_ref) {
8
8
  db = _ref.db;
9
9
  return /*#__PURE__*/function () {
10
10
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(body) {
11
+ var values, result;
11
12
  return _regeneratorRuntime().wrap(function _callee$(_context) {
12
13
  while (1) switch (_context.prev = _context.next) {
13
14
  case 0:
14
- return _context.abrupt("return", db.insert(table).values(transformBody(body)).returning());
15
- case 1:
15
+ values = transformBody(body);
16
+ _context.next = 3;
17
+ return db.insert(table).values(values).returning();
18
+ case 3:
19
+ result = _context.sent;
20
+ return _context.abrupt("return", result);
21
+ case 5:
16
22
  case "end":
17
23
  return _context.stop();
18
24
  }
@@ -3,8 +3,8 @@ import { NodePgDatabase } from "drizzle-orm/node-postgres";
3
3
  import { BaseTable } from "../types";
4
4
  export declare function createPutAction<T extends ZodSchema, TTable extends BaseTable>({ db, table, }: {
5
5
  bodySchema: T;
6
- db: NodePgDatabase<any>;
6
+ db: NodePgDatabase<Record<string, unknown>>;
7
7
  table: TTable;
8
- }): (body: Partial<z.infer<T>>, { byCreator, }?: {
8
+ }): (body: Partial<z.infer<T>> & Record<string, unknown>, { byCreator, }?: {
9
9
  byCreator?: boolean | undefined;
10
- }) => Promise<T["_output"]>;
10
+ }) => Promise<z.infer<T>>;
@@ -4,19 +4,7 @@ export declare function getListData<B extends ZodSchema>({ query, countQuery, pa
4
4
  bodySchema: B;
5
5
  current?: number;
6
6
  pageSize?: number;
7
- } & ReturnType<typeof getListQuery>): import("next-rest-framework/dist/index-Xbs7wi4f").R<"application/json" | "application/x-www-form-urlencoded" | "multipart/form-data", unknown, {
8
- body: import("zod").ZodObject<{
9
- total: import("zod").ZodNumber;
10
- data: import("zod").ZodArray<B, "many">;
11
- }, "strip", import("zod").ZodTypeAny, {
12
- data: B["_output"][];
13
- total: number;
14
- }, {
15
- data: B["_input"][];
16
- total: number;
17
- }>;
18
- contentType: "application/json";
19
- }[], false, Promise<{
20
- data: B["_output"][];
7
+ } & ReturnType<typeof getListQuery>): () => Promise<{
8
+ data: any;
21
9
  total: number;
22
- }>>;
10
+ }>;
@@ -3,11 +3,11 @@ import { SelectedFields } from "drizzle-orm/pg-core/query-builders/select.types"
3
3
  import { SQL } from "drizzle-orm";
4
4
  import { NodePgDatabase } from "drizzle-orm/node-postgres";
5
5
  export declare function getListQuery<TTable extends BaseTable, TSelection extends SelectedFields>({ db, fields, jsonArrayFields, params, relations, table, }: {
6
- db: NodePgDatabase<any>;
6
+ db: NodePgDatabase<Record<string, unknown>>;
7
7
  fields: TSelection;
8
8
  jsonArrayFields?: string[];
9
9
  params: {
10
- [field: string]: any;
10
+ [field: string]: unknown;
11
11
  orderBy?: keyof BaseTable;
12
12
  orderDir?: "asc" | "desc";
13
13
  page?: number;
@@ -16,13 +16,11 @@ export declare function getListQuery<TTable extends BaseTable, TSelection extend
16
16
  relations?: GetListRelations;
17
17
  table: TTable;
18
18
  }): {
19
- countQuery: Omit<import("drizzle-orm/pg-core").PgSelectBase<any, {
19
+ countQuery: Omit<import("drizzle-orm/pg-core").PgSelectBase<string, {
20
20
  count: SQL<unknown>;
21
- }, "partial", {} | Record<any, "not-null">, false, "where", ({
21
+ }, "partial", Record<string, "not-null">, false, "where", {
22
22
  count: unknown;
23
- } | {
24
- count: unknown;
25
- })[], {
23
+ }[], {
26
24
  count: import("drizzle-orm").DrizzleTypeError<"You cannot reference this field without assigning it an alias first - use `.as(<alias>)`">;
27
25
  }>, "where">;
28
26
  query: any;
@@ -1 +1 @@
1
- export declare const transformBody: (body: Record<string, any>) => any;
1
+ export declare const transformBody: <T extends Record<string, unknown>>(body: T) => T;
@@ -1,9 +1,7 @@
1
1
  import dayjs from "dayjs";
2
2
  export var transformBody = function transformBody(body) {
3
- // 遍历 body 中的每个字段
4
3
  for (var key in body) {
5
4
  if (key.endsWith("At")) {
6
- // 使用 dayjs 将值转换为 Date 对象
7
5
  body[key] = dayjs(body[key]).toDate();
8
6
  }
9
7
  }
@@ -10,8 +10,8 @@ export interface DeleteOperationOptions<TTable extends BaseTable> {
10
10
  byCreator?: boolean;
11
11
  }
12
12
  export declare const createDeleteOperation: ({ db, getSession, }: {
13
- db: NodePgDatabase<any>;
13
+ db: NodePgDatabase<Record<string, unknown>>;
14
14
  getSession: (req: NextRequest) => Promise<{
15
15
  userId?: string;
16
16
  } | undefined>;
17
- }) => <TTable extends BaseTable>({ table, summary, onSuccess, onError, byCreator, }: DeleteOperationOptions<TTable>) => any;
17
+ }) => <TTable extends BaseTable>({ table, summary, onSuccess, onError, byCreator, }: DeleteOperationOptions<TTable>) => import("next-rest-framework").RouteOperationDefinition<"DELETE">;
@@ -22,8 +22,8 @@ export interface GetListOperationOptions<T extends ZodSchema, Q extends ZodSchem
22
22
  onError?: (error: Error) => Promise<ReturnType<(typeof TypedNextResponse)["json"]> | undefined>;
23
23
  }
24
24
  export declare const createGetListOperation: ({ db, getSession, }: {
25
- db: NodePgDatabase<any>;
25
+ db: NodePgDatabase<Record<string, unknown>>;
26
26
  getSession: (req: NextRequest) => Promise<{
27
27
  userId?: string;
28
28
  } | undefined>;
29
- }) => <T extends z.ZodType<any, z.ZodTypeDef, any>, Q extends z.ZodType<any, z.ZodTypeDef, any>, TTable extends BaseTable>({ querySchema, bodySchema, table, summary, relations, jsonArrayFields, setParams, onSuccess, onError, byCreator, }: GetListOperationOptions<T, Q, TTable>) => any;
29
+ }) => <T extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, Q extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, TTable extends BaseTable>({ querySchema, bodySchema, table, summary, relations, jsonArrayFields, setParams, onSuccess, onError, byCreator, }: GetListOperationOptions<T, Q, TTable>) => import("next-rest-framework").RouteOperationDefinition<"GET">;
@@ -8,7 +8,7 @@ export interface GetOperationOptions<T extends ZodSchema, Q extends ZodSchema, T
8
8
  jsonArrayFields?: string[];
9
9
  querySchema: Q;
10
10
  relations?: GetListRelations;
11
- setParams?: (req: TypedNextRequest<"GET", "application/json", unknown, z.infer<Q>>) => Promise<Record<string, any>>;
11
+ setParams?: (req: TypedNextRequest<"GET", "application/json", unknown, z.infer<Q>>) => Promise<Record<string, unknown>>;
12
12
  onSuccess?: (data: z.infer<T>) => Promise<z.infer<T>>;
13
13
  onError?: (error: Error) => Promise<ReturnType<(typeof TypedNextResponse)["json"]> | undefined>;
14
14
  summary?: string;
@@ -16,8 +16,8 @@ export interface GetOperationOptions<T extends ZodSchema, Q extends ZodSchema, T
16
16
  byCreator?: boolean;
17
17
  }
18
18
  export declare const createGetOperation: ({ getSession, db, }: {
19
- db: NodePgDatabase<any>;
19
+ db: NodePgDatabase<Record<string, unknown>>;
20
20
  getSession: (req: NextRequest) => Promise<{
21
21
  userId?: string;
22
22
  } | undefined>;
23
- }) => <T extends z.ZodType<any, z.ZodTypeDef, any>, Q extends z.ZodType<any, z.ZodTypeDef, any>, TTable extends BaseTable>({ querySchema, bodySchema, table, summary, relations, setParams, jsonArrayFields, onSuccess, onError, byCreator, }: GetOperationOptions<T, Q, TTable>) => any;
23
+ }) => <T extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, Q extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, TTable extends BaseTable>({ querySchema, bodySchema, table, summary, relations, setParams, jsonArrayFields, onSuccess, onError, byCreator, }: GetOperationOptions<T, Q, TTable>) => import("next-rest-framework").RouteOperationDefinition<"GET">;