@ai0x0/utils 0.0.41 → 0.0.42

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.
@@ -87,17 +87,19 @@ export const getListOperation = createGetListOperation({ db, getSession });
87
87
 
88
88
  ## Factory Catalog
89
89
 
90
- | Export | Purpose | Required options | Notable optional options |
91
- | ------------------- | -------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------ |
92
- | `createTableSchema` | pg `Table` + 5 zod schemas | `name`, `columns` | `refineSchema`, `extraConfig` |
93
- | `getOperation` | GET one by filters | `bodySchema`, `querySchema` | `table`, `setParams`, `relations`, `jsonArrayFields`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
94
- | `getListOperation` | GET paginated list | `bodySchema`, `querySchema` | `table`, `setParams`, `relations`, `jsonArrayFields`, `onSuccess`, `onError`, `summary`, `tags` |
95
- | `postOperation` | POST create | `bodySchema` | `table`, `outputBodySchema`, `setBody`, `onSuccess`, `onError`, `summary`, `tags` |
96
- | `putOperation` | PUT update | `bodySchema` | `table`, `outputBodySchema`, `setBody`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
97
- | `deleteOperation` | DELETE | — | `table`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
90
+ | Export | Purpose | Required options | Notable optional options |
91
+ | ------------------- | -------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------- |
92
+ | `createTableSchema` | pg `Table` + 5 zod schemas | `name`, `columns` | `refineSchema`, `extraConfig` |
93
+ | `getOperation` | GET one by filters | `bodySchema`, `querySchema` | `table`, `setParams`, `relations`, `jsonArrayFields`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
94
+ | `getListOperation` | GET paginated list | `bodySchema`, `querySchema` | `table`, `setParams`, `relations`, `jsonArrayFields`, `onSuccess`, `onError`, `summary`, `tags` |
95
+ | `postOperation` | POST create | `bodySchema` | `table`, `contentType`, `parseBody`, `outputBodySchema`, `setBody`, `onSuccess`, `onError`, `summary`, `tags` |
96
+ | `putOperation` | PUT update | `bodySchema` | `table`, `outputBodySchema`, `setBody`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
97
+ | `deleteOperation` | DELETE | — | `table`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
98
98
 
99
99
  `tags` can be passed manually to override the default OpenAPI tag inferred from `table`.
100
100
 
101
+ `postOperation` defaults to `contentType: "application/json"`. Pass `contentType: "multipart/form-data"` to read `await req.formData()` as body, or pass both a custom `contentType` and `parseBody(req)` for custom payload parsing.
102
+
101
103
  `table` and factory-level `db` are optional for route operations. When `table` is omitted or `db` is not provided, the operation still parses input, applies `setParams` / `setBody`, session-derived fields, and `onSuccess`, but skips the built-in table action (`select` / `insert` / `update` / `delete`). Use this for custom endpoints that want the same OpenAPI and response wiring without a direct table operation.
102
104
 
103
105
  ## Canonical Examples
@@ -342,13 +344,13 @@ export const { GET } = route({
342
344
  - 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.
343
345
  - `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.
344
346
  - 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.
345
- - 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.
347
+ - For non-CRUD behavior (middleware chains, streaming, custom `TypedNextResponse` unions, RPC) stop using these factories and switch to the `create-next-rest-framework-api` skill.
346
348
 
347
349
  ## Escape Hatches
348
350
 
349
351
  - Extra server-side filters — `setParams(req) => Promise<Record<string, unknown>>` on GET/GET_LIST; returned keys are merged into the filter.
350
352
  - 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`.
351
- - Post-processing output — `onSuccess({ params, data }) => Promise<data>`; on GET_LIST `data` is `{ data, total }`.
353
+ - Post-processing output — `onSuccess({ params, data, req }) => Promise<data>`; on GET_LIST `data` is `{ data, total }`.
352
354
  - Error rewriting — `onError(err) => Promise<Response | undefined>`. Return `undefined` to rethrow.
353
355
 
354
356
  ## Imports
package/SKILL.md CHANGED
@@ -66,17 +66,19 @@ export const getListOperation = createGetListOperation({ db, getSession });
66
66
 
67
67
  ## Factory Catalog
68
68
 
69
- | Export | Purpose | Required options | Notable optional options |
70
- | ------------------- | -------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------ |
71
- | `createTableSchema` | pg `Table` + 5 zod schemas | `name`, `columns` | `refineSchema`, `extraConfig` |
72
- | `getOperation` | GET one by filters | `bodySchema`, `querySchema` | `table`, `setParams`, `relations`, `jsonArrayFields`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
73
- | `getListOperation` | GET paginated list | `bodySchema`, `querySchema` | `table`, `setParams`, `relations`, `jsonArrayFields`, `onSuccess`, `onError`, `summary`, `tags` |
74
- | `postOperation` | POST create | `bodySchema` | `table`, `outputBodySchema`, `setBody`, `onSuccess`, `onError`, `summary`, `tags` |
75
- | `putOperation` | PUT update | `bodySchema` | `table`, `outputBodySchema`, `setBody`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
76
- | `deleteOperation` | DELETE | — | `table`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
69
+ | Export | Purpose | Required options | Notable optional options |
70
+ | ------------------- | -------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------- |
71
+ | `createTableSchema` | pg `Table` + 5 zod schemas | `name`, `columns` | `refineSchema`, `extraConfig` |
72
+ | `getOperation` | GET one by filters | `bodySchema`, `querySchema` | `table`, `setParams`, `relations`, `jsonArrayFields`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
73
+ | `getListOperation` | GET paginated list | `bodySchema`, `querySchema` | `table`, `setParams`, `relations`, `jsonArrayFields`, `onSuccess`, `onError`, `summary`, `tags` |
74
+ | `postOperation` | POST create | `bodySchema` | `table`, `contentType`, `parseBody`, `outputBodySchema`, `setBody`, `onSuccess`, `onError`, `summary`, `tags` |
75
+ | `putOperation` | PUT update | `bodySchema` | `table`, `outputBodySchema`, `setBody`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
76
+ | `deleteOperation` | DELETE | — | `table`, `byCreator`, `onSuccess`, `onError`, `summary`, `tags` |
77
77
 
78
78
  `tags` can be passed manually to override the default OpenAPI tag inferred from `table`.
79
79
 
80
+ `postOperation` defaults to `contentType: "application/json"`. Pass `contentType: "multipart/form-data"` to read `await req.formData()` as body, or pass both a custom `contentType` and `parseBody(req)` for custom payload parsing.
81
+
80
82
  `table` and factory-level `db` are optional for route operations. When `table` is omitted or `db` is not provided, the operation still parses input, applies `setParams` / `setBody`, session-derived fields, and `onSuccess`, but skips the built-in table action (`select` / `insert` / `update` / `delete`). Use this for custom endpoints that want the same OpenAPI and response wiring without a direct table operation.
81
83
 
82
84
  ## Canonical Examples
@@ -321,13 +323,13 @@ export const { GET } = route({
321
323
  - 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.
322
324
  - `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.
323
325
  - 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.
324
- - 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.
326
+ - For non-CRUD behavior (middleware chains, streaming, custom `TypedNextResponse` unions, RPC) stop using these factories and switch to the `create-next-rest-framework-api` skill.
325
327
 
326
328
  ## Escape Hatches
327
329
 
328
330
  - Extra server-side filters — `setParams(req) => Promise<Record<string, unknown>>` on GET/GET_LIST; returned keys are merged into the filter.
329
331
  - 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`.
330
- - Post-processing output — `onSuccess({ params, data }) => Promise<data>`; on GET_LIST `data` is `{ data, total }`.
332
+ - Post-processing output — `onSuccess({ params, data, req }) => Promise<data>`; on GET_LIST `data` is `{ data, total }`.
331
333
  - Error rewriting — `onError(err) => Promise<Response | undefined>`. Return `undefined` to rethrow.
332
334
 
333
335
  ## Imports
@@ -1,15 +1,19 @@
1
1
  import { z, ZodSchema } from "zod";
2
2
  import { PgTable } from "drizzle-orm/pg-core";
3
- import { TypedNextRequest, TypedNextResponse } from "next-rest-framework";
3
+ import { NextRequest } from "next/server";
4
+ import { TypedNextResponse } from "next-rest-framework";
4
5
  export interface PostOperationOptions<IB extends ZodSchema, OB extends ZodSchema, TTable extends PgTable> {
5
6
  bodySchema: IB;
7
+ contentType?: string;
6
8
  outputBodySchema?: IB;
7
- setBody?(req: TypedNextRequest<"POST", "application/json", z.infer<IB>>): Promise<Partial<z.infer<IB>>>;
9
+ parseBody?(req: NextRequest): Promise<Record<string, unknown>>;
10
+ setBody?(req: NextRequest): Promise<Partial<z.infer<IB>>>;
8
11
  summary?: string;
9
12
  tags?: string[];
10
13
  onSuccess?(payload: {
11
14
  params: Record<string, unknown>;
12
15
  data: z.infer<OB>;
16
+ req: NextRequest;
13
17
  }): Promise<z.infer<OB>>;
14
18
  onError?(error: Error): Promise<ReturnType<(typeof TypedNextResponse)["json"]> | undefined>;
15
19
  table?: TTable;
@@ -11,18 +11,60 @@ import { z } from "zod";
11
11
  import { routeOperation, TypedNextResponse } from "next-rest-framework";
12
12
  import getTableName from "./get-table-name.js";
13
13
  import { createPostAction } from "../actions/index.js";
14
- export var createPostOperation = function createPostOperation(_ref) {
15
- var getSession = _ref.getSession,
16
- db = _ref.db;
17
- return function (_ref2) {
18
- var bodySchema = _ref2.bodySchema,
19
- outputBodySchema = _ref2.outputBodySchema,
20
- setBody = _ref2.setBody,
21
- summary = _ref2.summary,
22
- tags = _ref2.tags,
23
- table = _ref2.table,
24
- onSuccess = _ref2.onSuccess,
25
- onError = _ref2.onError;
14
+ function readPostBody(_x, _x2) {
15
+ return _readPostBody.apply(this, arguments);
16
+ }
17
+ function _readPostBody() {
18
+ _readPostBody = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(req, _ref) {
19
+ var contentType, parseBody;
20
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
21
+ while (1) switch (_context2.prev = _context2.next) {
22
+ case 0:
23
+ contentType = _ref.contentType, parseBody = _ref.parseBody;
24
+ if (!parseBody) {
25
+ _context2.next = 3;
26
+ break;
27
+ }
28
+ return _context2.abrupt("return", parseBody(req));
29
+ case 3:
30
+ if (!(contentType === "multipart/form-data")) {
31
+ _context2.next = 9;
32
+ break;
33
+ }
34
+ _context2.t0 = Object;
35
+ _context2.next = 7;
36
+ return req.formData();
37
+ case 7:
38
+ _context2.t1 = _context2.sent;
39
+ return _context2.abrupt("return", _context2.t0.fromEntries.call(_context2.t0, _context2.t1));
40
+ case 9:
41
+ _context2.next = 11;
42
+ return req.json();
43
+ case 11:
44
+ return _context2.abrupt("return", _context2.sent);
45
+ case 12:
46
+ case "end":
47
+ return _context2.stop();
48
+ }
49
+ }, _callee2);
50
+ }));
51
+ return _readPostBody.apply(this, arguments);
52
+ }
53
+ export var createPostOperation = function createPostOperation(_ref2) {
54
+ var getSession = _ref2.getSession,
55
+ db = _ref2.db;
56
+ return function (_ref3) {
57
+ var bodySchema = _ref3.bodySchema,
58
+ _ref3$contentType = _ref3.contentType,
59
+ contentType = _ref3$contentType === void 0 ? "application/json" : _ref3$contentType,
60
+ outputBodySchema = _ref3.outputBodySchema,
61
+ parseBody = _ref3.parseBody,
62
+ setBody = _ref3.setBody,
63
+ summary = _ref3.summary,
64
+ tags = _ref3.tags,
65
+ table = _ref3.table,
66
+ onSuccess = _ref3.onSuccess,
67
+ onError = _ref3.onError;
26
68
  return routeOperation({
27
69
  method: "POST",
28
70
  openApiOperation: {
@@ -31,7 +73,7 @@ export var createPostOperation = function createPostOperation(_ref) {
31
73
  }
32
74
  }).input({
33
75
  body: bodySchema,
34
- contentType: "application/json"
76
+ contentType: contentType
35
77
  }).outputs([{
36
78
  body: outputBodySchema || z.object({
37
79
  id: z.string()
@@ -39,8 +81,8 @@ export var createPostOperation = function createPostOperation(_ref) {
39
81
  contentType: "application/json",
40
82
  status: 200
41
83
  }]).handler( /*#__PURE__*/function () {
42
- var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(req) {
43
- var _ref4, userId, body, extraBody, mergedBody, params, raw, data, response;
84
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(req) {
85
+ var _ref5, userId, body, extraBody, mergedBody, params, raw, data, response;
44
86
  return _regeneratorRuntime().wrap(function _callee$(_context) {
45
87
  while (1) switch (_context.prev = _context.next) {
46
88
  case 0:
@@ -55,10 +97,13 @@ export var createPostOperation = function createPostOperation(_ref) {
55
97
  }
56
98
  _context.t0 = {};
57
99
  case 6:
58
- _ref4 = _context.t0;
59
- userId = _ref4.userId;
100
+ _ref5 = _context.t0;
101
+ userId = _ref5.userId;
60
102
  _context.next = 10;
61
- return req.json();
103
+ return readPostBody(req, {
104
+ contentType: contentType,
105
+ parseBody: parseBody
106
+ });
62
107
  case 10:
63
108
  body = _context.sent;
64
109
  _context.next = 13;
@@ -101,7 +146,8 @@ export var createPostOperation = function createPostOperation(_ref) {
101
146
  _context.next = 30;
102
147
  return onSuccess({
103
148
  data: raw,
104
- params: params
149
+ params: params,
150
+ req: req
105
151
  });
106
152
  case 30:
107
153
  _context.t3 = _context.sent;
@@ -135,8 +181,8 @@ export var createPostOperation = function createPostOperation(_ref) {
135
181
  }
136
182
  }, _callee, null, [[0, 38]]);
137
183
  }));
138
- return function (_x) {
139
- return _ref3.apply(this, arguments);
184
+ return function (_x3) {
185
+ return _ref4.apply(this, arguments);
140
186
  };
141
187
  }());
142
188
  };
@@ -1,15 +1,19 @@
1
1
  import { z, ZodSchema } from "zod";
2
2
  import { SQLiteTable } from "drizzle-orm/sqlite-core";
3
- import { TypedNextRequest, TypedNextResponse } from "next-rest-framework";
3
+ import { NextRequest } from "next/server";
4
+ import { TypedNextResponse } from "next-rest-framework";
4
5
  export interface PostOperationOptions<IB extends ZodSchema, OB extends ZodSchema, TTable extends SQLiteTable> {
5
6
  bodySchema: IB;
7
+ contentType?: string;
6
8
  outputBodySchema?: IB;
7
- setBody?: (_req: TypedNextRequest<"POST", "application/json", z.infer<IB>>) => Promise<Partial<z.infer<IB>>>;
9
+ parseBody?: (_req: NextRequest) => Promise<Record<string, unknown>>;
10
+ setBody?: (_req: NextRequest) => Promise<Partial<z.infer<IB>>>;
8
11
  summary?: string;
9
12
  tags?: string[];
10
13
  onSuccess?: (_payload: {
11
14
  params: Record<string, unknown>;
12
15
  data: z.infer<OB>;
16
+ req: NextRequest;
13
17
  }) => Promise<z.infer<OB>>;
14
18
  onError?: (_error: Error) => Promise<ReturnType<(typeof TypedNextResponse)["json"]> | undefined>;
15
19
  table?: TTable;
@@ -11,18 +11,60 @@ import { z } from "zod";
11
11
  import { routeOperation, TypedNextResponse } from "next-rest-framework";
12
12
  import getTableName from "./get-table-name.js";
13
13
  import { createPostAction } from "../actions/index.js";
14
- export var createPostOperation = function createPostOperation(_ref) {
15
- var getSession = _ref.getSession,
16
- db = _ref.db;
17
- return function (_ref2) {
18
- var bodySchema = _ref2.bodySchema,
19
- outputBodySchema = _ref2.outputBodySchema,
20
- setBody = _ref2.setBody,
21
- summary = _ref2.summary,
22
- tags = _ref2.tags,
23
- table = _ref2.table,
24
- onSuccess = _ref2.onSuccess,
25
- onError = _ref2.onError;
14
+ function readPostBody(_x, _x2) {
15
+ return _readPostBody.apply(this, arguments);
16
+ }
17
+ function _readPostBody() {
18
+ _readPostBody = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(req, _ref) {
19
+ var contentType, parseBody;
20
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
21
+ while (1) switch (_context2.prev = _context2.next) {
22
+ case 0:
23
+ contentType = _ref.contentType, parseBody = _ref.parseBody;
24
+ if (!parseBody) {
25
+ _context2.next = 3;
26
+ break;
27
+ }
28
+ return _context2.abrupt("return", parseBody(req));
29
+ case 3:
30
+ if (!(contentType === "multipart/form-data")) {
31
+ _context2.next = 9;
32
+ break;
33
+ }
34
+ _context2.t0 = Object;
35
+ _context2.next = 7;
36
+ return req.formData();
37
+ case 7:
38
+ _context2.t1 = _context2.sent;
39
+ return _context2.abrupt("return", _context2.t0.fromEntries.call(_context2.t0, _context2.t1));
40
+ case 9:
41
+ _context2.next = 11;
42
+ return req.json();
43
+ case 11:
44
+ return _context2.abrupt("return", _context2.sent);
45
+ case 12:
46
+ case "end":
47
+ return _context2.stop();
48
+ }
49
+ }, _callee2);
50
+ }));
51
+ return _readPostBody.apply(this, arguments);
52
+ }
53
+ export var createPostOperation = function createPostOperation(_ref2) {
54
+ var getSession = _ref2.getSession,
55
+ db = _ref2.db;
56
+ return function (_ref3) {
57
+ var bodySchema = _ref3.bodySchema,
58
+ _ref3$contentType = _ref3.contentType,
59
+ contentType = _ref3$contentType === void 0 ? "application/json" : _ref3$contentType,
60
+ outputBodySchema = _ref3.outputBodySchema,
61
+ parseBody = _ref3.parseBody,
62
+ setBody = _ref3.setBody,
63
+ summary = _ref3.summary,
64
+ tags = _ref3.tags,
65
+ table = _ref3.table,
66
+ onSuccess = _ref3.onSuccess,
67
+ onError = _ref3.onError;
26
68
  return routeOperation({
27
69
  method: "POST",
28
70
  openApiOperation: {
@@ -31,7 +73,7 @@ export var createPostOperation = function createPostOperation(_ref) {
31
73
  }
32
74
  }).input({
33
75
  body: bodySchema,
34
- contentType: "application/json"
76
+ contentType: contentType
35
77
  }).outputs([{
36
78
  body: outputBodySchema || z.object({
37
79
  id: z.string()
@@ -39,8 +81,8 @@ export var createPostOperation = function createPostOperation(_ref) {
39
81
  contentType: "application/json",
40
82
  status: 200
41
83
  }]).handler( /*#__PURE__*/function () {
42
- var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(req) {
43
- var _ref4, userId, body, extraBody, mergedBody, params, raw, data, response;
84
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(req) {
85
+ var _ref5, userId, body, extraBody, mergedBody, params, raw, data, response;
44
86
  return _regeneratorRuntime().wrap(function _callee$(_context) {
45
87
  while (1) switch (_context.prev = _context.next) {
46
88
  case 0:
@@ -55,10 +97,13 @@ export var createPostOperation = function createPostOperation(_ref) {
55
97
  }
56
98
  _context.t0 = {};
57
99
  case 6:
58
- _ref4 = _context.t0;
59
- userId = _ref4.userId;
100
+ _ref5 = _context.t0;
101
+ userId = _ref5.userId;
60
102
  _context.next = 10;
61
- return req.json();
103
+ return readPostBody(req, {
104
+ contentType: contentType,
105
+ parseBody: parseBody
106
+ });
62
107
  case 10:
63
108
  body = _context.sent;
64
109
  _context.next = 13;
@@ -101,7 +146,8 @@ export var createPostOperation = function createPostOperation(_ref) {
101
146
  _context.next = 30;
102
147
  return onSuccess({
103
148
  data: raw,
104
- params: params
149
+ params: params,
150
+ req: req
105
151
  });
106
152
  case 30:
107
153
  _context.t3 = _context.sent;
@@ -135,8 +181,8 @@ export var createPostOperation = function createPostOperation(_ref) {
135
181
  }
136
182
  }, _callee, null, [[0, 38]]);
137
183
  }));
138
- return function (_x) {
139
- return _ref3.apply(this, arguments);
184
+ return function (_x3) {
185
+ return _ref4.apply(this, arguments);
140
186
  };
141
187
  }());
142
188
  };
@@ -1,15 +1,19 @@
1
1
  import { z, ZodSchema } from "zod";
2
2
  import { PgTable } from "drizzle-orm/pg-core";
3
- import { TypedNextRequest, TypedNextResponse } from "next-rest-framework";
3
+ import { NextRequest } from "next/server";
4
+ import { TypedNextResponse } from "next-rest-framework";
4
5
  export interface PostOperationOptions<IB extends ZodSchema, OB extends ZodSchema, TTable extends PgTable> {
5
6
  bodySchema: IB;
7
+ contentType?: string;
6
8
  outputBodySchema?: IB;
7
- setBody?(req: TypedNextRequest<"POST", "application/json", z.infer<IB>>): Promise<Partial<z.infer<IB>>>;
9
+ parseBody?(req: NextRequest): Promise<Record<string, unknown>>;
10
+ setBody?(req: NextRequest): Promise<Partial<z.infer<IB>>>;
8
11
  summary?: string;
9
12
  tags?: string[];
10
13
  onSuccess?(payload: {
11
14
  params: Record<string, unknown>;
12
15
  data: z.infer<OB>;
16
+ req: NextRequest;
13
17
  }): Promise<z.infer<OB>>;
14
18
  onError?(error: Error): Promise<ReturnType<(typeof TypedNextResponse)["json"]> | undefined>;
15
19
  table?: TTable;
@@ -36,12 +36,26 @@ var import_zod = require("zod");
36
36
  var import_next_rest_framework = require("next-rest-framework");
37
37
  var import_get_table_name = __toESM(require("./get-table-name"));
38
38
  var import_actions = require("../actions");
39
+ async function readPostBody(req, {
40
+ contentType,
41
+ parseBody
42
+ }) {
43
+ if (parseBody) {
44
+ return parseBody(req);
45
+ }
46
+ if (contentType === "multipart/form-data") {
47
+ return Object.fromEntries(await req.formData());
48
+ }
49
+ return await req.json();
50
+ }
39
51
  var createPostOperation = ({
40
52
  getSession,
41
53
  db
42
54
  }) => ({
43
55
  bodySchema,
56
+ contentType = "application/json",
44
57
  outputBodySchema,
58
+ parseBody,
45
59
  setBody,
46
60
  summary,
47
61
  tags,
@@ -56,7 +70,7 @@ var createPostOperation = ({
56
70
  }
57
71
  }).input({
58
72
  body: bodySchema,
59
- contentType: "application/json"
73
+ contentType
60
74
  }).outputs([
61
75
  {
62
76
  body: outputBodySchema || import_zod.z.object({ id: import_zod.z.string() }),
@@ -66,10 +80,8 @@ var createPostOperation = ({
66
80
  ]).handler(async (req) => {
67
81
  try {
68
82
  const { userId } = await getSession(req) || {};
69
- const body = await req.json();
70
- const extraBody = await (setBody == null ? void 0 : setBody(
71
- req
72
- )) || {};
83
+ const body = await readPostBody(req, { contentType, parseBody });
84
+ const extraBody = await (setBody == null ? void 0 : setBody(req)) || {};
73
85
  const mergedBody = { ...body, ...extraBody };
74
86
  const params = { creatorId: userId, ...mergedBody };
75
87
  const raw = table && db ? (await (0, import_actions.createPostAction)({ bodySchema, db, table })(
@@ -77,7 +89,8 @@ var createPostOperation = ({
77
89
  ))[0] : params;
78
90
  const data = onSuccess ? await onSuccess({
79
91
  data: raw,
80
- params
92
+ params,
93
+ req
81
94
  }) : raw;
82
95
  return import_next_rest_framework.TypedNextResponse.json(data, {
83
96
  status: 200
@@ -1,15 +1,19 @@
1
1
  import { z, ZodSchema } from "zod";
2
2
  import { SQLiteTable } from "drizzle-orm/sqlite-core";
3
- import { TypedNextRequest, TypedNextResponse } from "next-rest-framework";
3
+ import { NextRequest } from "next/server";
4
+ import { TypedNextResponse } from "next-rest-framework";
4
5
  export interface PostOperationOptions<IB extends ZodSchema, OB extends ZodSchema, TTable extends SQLiteTable> {
5
6
  bodySchema: IB;
7
+ contentType?: string;
6
8
  outputBodySchema?: IB;
7
- setBody?: (_req: TypedNextRequest<"POST", "application/json", z.infer<IB>>) => Promise<Partial<z.infer<IB>>>;
9
+ parseBody?: (_req: NextRequest) => Promise<Record<string, unknown>>;
10
+ setBody?: (_req: NextRequest) => Promise<Partial<z.infer<IB>>>;
8
11
  summary?: string;
9
12
  tags?: string[];
10
13
  onSuccess?: (_payload: {
11
14
  params: Record<string, unknown>;
12
15
  data: z.infer<OB>;
16
+ req: NextRequest;
13
17
  }) => Promise<z.infer<OB>>;
14
18
  onError?: (_error: Error) => Promise<ReturnType<(typeof TypedNextResponse)["json"]> | undefined>;
15
19
  table?: TTable;
@@ -36,12 +36,26 @@ var import_zod = require("zod");
36
36
  var import_next_rest_framework = require("next-rest-framework");
37
37
  var import_get_table_name = __toESM(require("./get-table-name"));
38
38
  var import_actions = require("../actions");
39
+ async function readPostBody(req, {
40
+ contentType,
41
+ parseBody
42
+ }) {
43
+ if (parseBody) {
44
+ return parseBody(req);
45
+ }
46
+ if (contentType === "multipart/form-data") {
47
+ return Object.fromEntries(await req.formData());
48
+ }
49
+ return await req.json();
50
+ }
39
51
  var createPostOperation = ({
40
52
  getSession,
41
53
  db
42
54
  }) => ({
43
55
  bodySchema,
56
+ contentType = "application/json",
44
57
  outputBodySchema,
58
+ parseBody,
45
59
  setBody,
46
60
  summary,
47
61
  tags,
@@ -56,7 +70,7 @@ var createPostOperation = ({
56
70
  }
57
71
  }).input({
58
72
  body: bodySchema,
59
- contentType: "application/json"
73
+ contentType
60
74
  }).outputs([
61
75
  {
62
76
  body: outputBodySchema || import_zod.z.object({ id: import_zod.z.string() }),
@@ -66,10 +80,8 @@ var createPostOperation = ({
66
80
  ]).handler(async (req) => {
67
81
  try {
68
82
  const { userId } = await getSession(req) || {};
69
- const body = await req.json();
70
- const extraBody = await (setBody == null ? void 0 : setBody(
71
- req
72
- )) || {};
83
+ const body = await readPostBody(req, { contentType, parseBody });
84
+ const extraBody = await (setBody == null ? void 0 : setBody(req)) || {};
73
85
  const mergedBody = { ...body, ...extraBody };
74
86
  const params = { creatorId: userId, ...mergedBody };
75
87
  const raw = table && db ? (await (0, import_actions.createPostAction)({ bodySchema, db, table })(
@@ -77,7 +89,8 @@ var createPostOperation = ({
77
89
  ))[0] : params;
78
90
  const data = onSuccess ? await onSuccess({
79
91
  data: raw,
80
- params
92
+ params,
93
+ req
81
94
  }) : raw;
82
95
  return import_next_rest_framework.TypedNextResponse.json(data, {
83
96
  status: 200
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai0x0/utils",
3
- "version": "0.0.41",
3
+ "version": "0.0.42",
4
4
  "description": "AI0x0 utils",
5
5
  "keywords": [
6
6
  "ai0x0"