@ai0x0/utils 0.0.26 → 0.0.29

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 (28) hide show
  1. package/README.md +2 -2
  2. package/es/backend/route-operation/delete-operation.d.ts +1 -8
  3. package/es/backend/route-operation/get-list-operation.d.ts +1 -8
  4. package/es/backend/route-operation/get-operation.d.ts +1 -8
  5. package/es/backend/route-operation/post-operation.d.ts +1 -8
  6. package/es/backend/route-operation/post-operation.js +40 -41
  7. package/es/backend/route-operation/put-operation.d.ts +1 -9
  8. package/es/backend/route-operation/put-operation.js +40 -41
  9. package/eslint-rules/index.js +40 -0
  10. package/eslint-rules/no-antd-space.js +63 -0
  11. package/eslint-rules/no-consecutive-setstate.js +87 -0
  12. package/eslint-rules/no-hardcoded-style.js +437 -0
  13. package/eslint-rules/no-one-letter-vars.js +111 -0
  14. package/eslint-rules/no-then.js +40 -0
  15. package/eslint-rules/no-use-request-run.js +54 -0
  16. package/eslint-rules/require-form-convention.js +200 -0
  17. package/eslint-rules/require-pro-components.js +131 -0
  18. package/eslint-rules/require-section-divider.js +116 -0
  19. package/eslint-rules/require-use-form.js +77 -0
  20. package/lib/backend/route-operation/delete-operation.d.ts +1 -8
  21. package/lib/backend/route-operation/get-list-operation.d.ts +1 -8
  22. package/lib/backend/route-operation/get-operation.d.ts +1 -8
  23. package/lib/backend/route-operation/get-operation.js +3 -1
  24. package/lib/backend/route-operation/post-operation.d.ts +1 -8
  25. package/lib/backend/route-operation/post-operation.js +9 -8
  26. package/lib/backend/route-operation/put-operation.d.ts +1 -9
  27. package/lib/backend/route-operation/put-operation.js +9 -14
  28. package/package.json +2 -1
@@ -0,0 +1,200 @@
1
+ /**
2
+ * require-form-convention
3
+ * -----------------------
4
+ * 约束表单组件必须遵守以下规范:
5
+ *
6
+ * 1. <Form> 必须使用 onFinish 提交
7
+ * 2. <Form.Item> 必须使用 rules 进行表单校验
8
+ * 3. 禁止在 useRequest 中使用 message.error 报错
9
+ * 4. Modal + Form 组合时,禁止用 Modal.onOk 提交
10
+ *
11
+ * 例外通过文件路径 overrides 处理(utils、hooks、theme 等已豁免)。
12
+ */
13
+
14
+ /** @type {import('eslint').Rule.RuleModule} */
15
+
16
+ // ==============================================================================
17
+ // 规则实现
18
+ // ==============================================================================
19
+
20
+ const rule = {
21
+ meta: {
22
+ type: "suggestion",
23
+ docs: {
24
+ description:
25
+ "表单组件必须使用 Form.onFinish,Form.Item 必须使用 rules,禁止 useRequest 内 message.error,禁止 Modal.onOk 提交表单。",
26
+ },
27
+ schema: [],
28
+ messages: {
29
+ needOnFinish:
30
+ "<Form> 必须使用 onFinish 属性提交表单,禁止用 form.validateFields() 或 Modal.onOk 手动提交。",
31
+ needItemRules:
32
+ "<Form.Item> 必须设置 rules 进行校验。如果确实不需要校验,请用 // eslint-disable-next-line 注明原因。",
33
+ noMessageError:
34
+ "禁止在 useRequest 的 onSuccess/onError 回调中使用 message.error。错误提示应通过 antd Form.Item 的 rules 或 Form onFinish 的错误处理来展示。",
35
+ noModalOnOk:
36
+ "Modal + Form 组合时,禁止使用 Modal.onOk 提交。请使用 Form.onFinish。",
37
+ noMessageErrorAny:
38
+ "禁止使用 app?.message.error 报错,请求拦截器已统一处理。请移除该行。",
39
+ },
40
+ },
41
+ create(context) {
42
+ const sourceCode = context.getSourceCode();
43
+
44
+ let hasFormTag = false;
45
+ let hasFormOnFinish = false;
46
+ const formItemNoRules = [];
47
+ const useRequestCalls = [];
48
+ const modalOnOkAttrs = [];
49
+ const validateFieldsCalls = [];
50
+
51
+ const getTagName = (name) => {
52
+ if (name.type === "JSXIdentifier") return name.name;
53
+ if (
54
+ name.type === "JSXMemberExpression" &&
55
+ name.object.type === "JSXIdentifier" &&
56
+ name.property.type === "JSXIdentifier"
57
+ ) {
58
+ return `${name.object.name}.${name.property.name}`;
59
+ }
60
+ return "";
61
+ };
62
+
63
+ return {
64
+ JSXOpeningElement(node) {
65
+ const tagName = getTagName(node.name);
66
+
67
+ // <Form>
68
+ if (tagName === "Form") {
69
+ hasFormTag = true;
70
+ for (const attr of node.attributes) {
71
+ if (attr.type !== "JSXAttribute" || !attr.name) continue;
72
+ if (attr.name.name === "onFinish") {
73
+ hasFormOnFinish = true;
74
+ }
75
+ }
76
+ if (!hasFormOnFinish) {
77
+ context.report({
78
+ node: node,
79
+ messageId: "needOnFinish",
80
+ });
81
+ }
82
+ }
83
+
84
+ // <Form.Item>
85
+ if (tagName === "Form.Item") {
86
+ let hasRules = false;
87
+ let isNoStyle = false;
88
+ let hasName = false;
89
+ for (const attr of node.attributes) {
90
+ if (attr.type !== "JSXAttribute" || !attr.name) continue;
91
+ if (attr.name.name === "rules") hasRules = true;
92
+ if (attr.name.name === "noStyle") isNoStyle = true;
93
+ if (attr.name.name === "name") hasName = true;
94
+ }
95
+ // noStyle 或 <Form.List> 内的 Item 不需要 rules
96
+ if (!hasRules && !isNoStyle && hasName) {
97
+ formItemNoRules.push(node);
98
+ }
99
+ }
100
+
101
+ // <Modal onOk={...}>
102
+ if (tagName === "Modal") {
103
+ for (const attr of node.attributes) {
104
+ if (attr.type !== "JSXAttribute" || !attr.name) continue;
105
+ if (attr.name.name === "onOk") {
106
+ modalOnOkAttrs.push(attr);
107
+ }
108
+ }
109
+ }
110
+ },
111
+
112
+ CallExpression(node) {
113
+ // app?.message.error() — 请求拦截器已统一处理,禁止手动调用
114
+ // app?.message.error() — 请求拦截器已统一处理,禁止手动调用
115
+ const callText = sourceCode.getText(node);
116
+ if (
117
+ callText.includes("message.error") &&
118
+ callText.startsWith("app") &&
119
+ callText.includes(".error(")
120
+ ) {
121
+ context.report({
122
+ node: node,
123
+ messageId: "noMessageErrorAny",
124
+ });
125
+ return;
126
+ }
127
+ // useRequest()
128
+ if (
129
+ node.callee.type === "Identifier" &&
130
+ node.callee.name === "useRequest"
131
+ ) {
132
+ useRequestCalls.push(node);
133
+ }
134
+
135
+ // .validateFields()
136
+ if (
137
+ node.callee.type === "MemberExpression" &&
138
+ node.callee.property.type === "Identifier" &&
139
+ node.callee.property.name === "validateFields"
140
+ ) {
141
+ validateFieldsCalls.push(node);
142
+ }
143
+ },
144
+
145
+ "Program:exit"() {
146
+ // 1. Form.Item without rules
147
+ for (const item of formItemNoRules) {
148
+ context.report({
149
+ node: item,
150
+ messageId: "needItemRules",
151
+ });
152
+ }
153
+
154
+ // 2. message.error in useRequest callbacks
155
+ for (const call of useRequestCalls) {
156
+ const options = call.arguments[1];
157
+ if (!options || options.type !== "ObjectExpression") continue;
158
+ for (const prop of options.properties) {
159
+ if (prop.type !== "Property") continue;
160
+ const key = prop.key;
161
+ if (
162
+ key.type !== "Identifier" ||
163
+ (key.name !== "onSuccess" &&
164
+ key.name !== "onError" &&
165
+ key.name !== "onFinally")
166
+ )
167
+ continue;
168
+ const text = sourceCode.getText(prop.value);
169
+ if (text.includes("message.error")) {
170
+ context.report({
171
+ node: prop,
172
+ messageId: "noMessageError",
173
+ });
174
+ }
175
+ }
176
+ }
177
+
178
+ // 3. Modal.onOk
179
+ for (const attr of modalOnOkAttrs) {
180
+ context.report({
181
+ node: attr,
182
+ messageId: "noModalOnOk",
183
+ });
184
+ }
185
+
186
+ // 4. form.validateFields()
187
+ if (hasFormTag && !hasFormOnFinish) {
188
+ for (const call of validateFieldsCalls) {
189
+ context.report({
190
+ node: call,
191
+ messageId: "needOnFinish",
192
+ });
193
+ }
194
+ }
195
+ },
196
+ };
197
+ },
198
+ };
199
+
200
+ export default rule;
@@ -0,0 +1,131 @@
1
+ /**
2
+ * require-pro-components
3
+ * ----------------------
4
+ * 约束前端业务代码:
5
+ * 1. 禁止直接使用 antd <Modal>,必须用 @ant-design/pro-components 的 <ModalForm>
6
+ * 2. 禁止直接使用 <Form.Item>,必须用 @ant-design/pro-components 的 ProForm* 组件
7
+ * 3. ProForm* 组件必须设置 rules 进行校验,否则需要 eslint-disable 注明原因
8
+ *
9
+ * 例外场景:
10
+ * - noStyle 的 Form.Item(仅作布局容器)
11
+ * - ProForm 容器本身(不是字段组件)
12
+ * - ProFormDependency、ProFormFieldSet、ProFormList 等非字段组件
13
+ */
14
+
15
+ const PROFORM_CONTAINER_COMPONENTS = new Set([
16
+ "ProForm",
17
+ "ProFormDependency",
18
+ "ProFormFieldSet",
19
+ "ProFormList",
20
+ "ProFormGrid",
21
+ "ProFormGroup",
22
+ ]);
23
+
24
+ /** @type {import('eslint').Rule.RuleModule} */
25
+ const rule = {
26
+ meta: {
27
+ type: "suggestion",
28
+ docs: {
29
+ description:
30
+ "禁止直接使用 antd <Modal>(用 ModalForm 代替),禁止直接使用 <Form.Item>(用 ProForm* 代替),ProForm* 必须设置 rules",
31
+ },
32
+ schema: [],
33
+ messages: {
34
+ useModalForm:
35
+ "禁止直接使用 antd <Modal>,请使用 @ant-design/pro-components 的 <ModalForm> 代替。",
36
+ useProFormItem:
37
+ "禁止直接使用 <Form.Item>,请使用 @ant-design/pro-components 的 ProFormText / ProFormSelect / ProFormItem 等组件代替。",
38
+ needProFormRules:
39
+ "<{{tag}}> 必须设置 rules 进行校验。如果确实不需要校验,请用 // eslint-disable-next-line 注明原因。",
40
+ noSubmitHtmlType:
41
+ '禁止使用 <Button htmlType="submit">,请使用 ProForm 的 submitter 属性提交表单。',
42
+ },
43
+ },
44
+ create(context) {
45
+ const getTagName = (name) => {
46
+ if (name.type === "JSXIdentifier") return name.name;
47
+ if (
48
+ name.type === "JSXMemberExpression" &&
49
+ name.object.type === "JSXIdentifier" &&
50
+ name.property.type === "JSXIdentifier"
51
+ ) {
52
+ return `${name.object.name}.${name.property.name}`;
53
+ }
54
+ return "";
55
+ };
56
+
57
+ return {
58
+ JSXOpeningElement(node) {
59
+ const tagName = getTagName(node.name);
60
+
61
+ // <Modal>
62
+ if (tagName === "Modal") {
63
+ context.report({
64
+ node: node,
65
+ messageId: "useModalForm",
66
+ });
67
+ }
68
+
69
+ // <Form.Item>
70
+ if (tagName === "Form.Item") {
71
+ let isNoStyle = false;
72
+ for (const attr of node.attributes) {
73
+ if (attr.type !== "JSXAttribute" || !attr.name) continue;
74
+ if (attr.name.name === "noStyle") {
75
+ isNoStyle = true;
76
+ break;
77
+ }
78
+ }
79
+ if (!isNoStyle) {
80
+ context.report({
81
+ node: node,
82
+ messageId: "useProFormItem",
83
+ });
84
+ }
85
+ }
86
+
87
+ // <Button htmlType="submit">
88
+ if (tagName === "Button") {
89
+ for (const attr of node.attributes) {
90
+ if (attr.type !== "JSXAttribute" || !attr.name) continue;
91
+ if (
92
+ attr.name.name === "htmlType" &&
93
+ attr.value &&
94
+ attr.value.type === "Literal" &&
95
+ attr.value.value === "submit"
96
+ ) {
97
+ context.report({
98
+ node: attr,
99
+ messageId: "noSubmitHtmlType",
100
+ });
101
+ }
102
+ }
103
+ }
104
+
105
+ // ProForm* field components must have rules
106
+ if (
107
+ tagName.startsWith("ProForm") &&
108
+ !PROFORM_CONTAINER_COMPONENTS.has(tagName)
109
+ ) {
110
+ let hasRules = false;
111
+ for (const attr of node.attributes) {
112
+ if (attr.type !== "JSXAttribute" || !attr.name) continue;
113
+ if (attr.name.name === "rules") {
114
+ hasRules = true;
115
+ break;
116
+ }
117
+ }
118
+ if (!hasRules) {
119
+ context.report({
120
+ node: node,
121
+ messageId: "needProFormRules",
122
+ data: { tag: tagName },
123
+ });
124
+ }
125
+ }
126
+ },
127
+ };
128
+ },
129
+ };
130
+
131
+ export default rule;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * require-section-divider
3
+ * ------------------------
4
+ * 约束:大文件必须在顶层用 `=====` 等号注释块做分区。
5
+ *
6
+ * 分区要求(按行数):
7
+ * - 150 ~ 349 行:至少 1 个分区块
8
+ * - 350 ~ 549 行:至少 2 个分区块
9
+ * - 550 ~ 749 行:至少 3 个分区块
10
+ * 以此类推,每 200 行增加 1 个分区块。
11
+ *
12
+ * 分隔注释块格式(见 .agents/skills/dev-style/SKILL.md):
13
+ *
14
+ * // ==============================================================================
15
+ * // <中文标题>
16
+ * // ==============================================================================
17
+ *
18
+ * 本规则检查文件中所有 ==== 三行注释块的数量是否达到要求。
19
+ */
20
+
21
+ const DIVIDER_EQ = /^\s*={4,}\s*$/;
22
+
23
+ /** 相邻两行注释 + 之间中间一行文字:判定一个三行注释块为分隔块。 */
24
+ function isDividerBlock(commentA, commentB, commentC) {
25
+ if (!commentA || !commentB || !commentC) return false;
26
+ if (
27
+ commentA.type !== "Line" ||
28
+ commentB.type !== "Line" ||
29
+ commentC.type !== "Line"
30
+ )
31
+ return false;
32
+ if (!DIVIDER_EQ.test(commentA.value)) return false;
33
+ if (!DIVIDER_EQ.test(commentC.value)) return false;
34
+ if (!commentB.value.trim()) return false;
35
+ if (commentA.loc.end.line + 1 !== commentB.loc.start.line) return false;
36
+ if (commentB.loc.end.line + 1 !== commentC.loc.start.line) return false;
37
+ return true;
38
+ }
39
+
40
+ /** 计算文件需要多少个分区块(每 150 行 1 个,从 150 行起)。 */
41
+ function requiredDividers(totalLines, minLines) {
42
+ if (totalLines < minLines) return 0;
43
+ // 150-299: 1个, 300-449: 2个, 依此类推
44
+ return Math.floor(totalLines / minLines);
45
+ }
46
+
47
+ /** @type {import('eslint').Rule.RuleModule} */
48
+ const rule = {
49
+ meta: {
50
+ type: "suggestion",
51
+ docs: {
52
+ description:
53
+ "大文件(≥ 150 行)必须按行数用适当数量的 `===` 等号注释块分区。",
54
+ },
55
+ schema: [
56
+ {
57
+ type: "object",
58
+ properties: {
59
+ minLines: { type: "number" },
60
+ },
61
+ additionalProperties: false,
62
+ },
63
+ ],
64
+ messages: {
65
+ missing:
66
+ "大文件需要更多 `===` 等号注释块分区。当前需要 {{required}} 个,实际只有 {{actual}} 个。每约 150 行至少应有一个分区块。",
67
+ },
68
+ },
69
+ create(context) {
70
+ const options = context.options[0] || {};
71
+ const minLines = options.minLines ?? 150;
72
+ const sourceCode = context.sourceCode ?? context.getSourceCode();
73
+
74
+ return {
75
+ Program(program) {
76
+ const totalLines = program.loc.end.line;
77
+ if (totalLines < minLines) return;
78
+
79
+ const required = requiredDividers(totalLines, minLines);
80
+ if (required <= 0) return;
81
+
82
+ const allComments = sourceCode.getAllComments();
83
+
84
+ let dividerCount = 0;
85
+ for (let i = 0; i + 2 < allComments.length; i += 1) {
86
+ if (
87
+ isDividerBlock(
88
+ allComments[i],
89
+ allComments[i + 1],
90
+ allComments[i + 2],
91
+ )
92
+ ) {
93
+ dividerCount += 1;
94
+ i += 2;
95
+ }
96
+ }
97
+
98
+ if (dividerCount < required) {
99
+ context.report({
100
+ loc: {
101
+ start: { line: 1, column: 0 },
102
+ end: { line: 1, column: 0 },
103
+ },
104
+ messageId: "missing",
105
+ data: {
106
+ required: String(required),
107
+ actual: String(dividerCount),
108
+ },
109
+ });
110
+ }
111
+ },
112
+ };
113
+ },
114
+ };
115
+
116
+ export default rule;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * require-use-form
3
+ * ----------------
4
+ * 约束:前端业务代码中,表单组件禁止用 useState/useSetState 管理字段值。
5
+ * 必须使用 Form.useForm() 或 rc-field-form 的 useForm。
6
+ *
7
+ * 检测方式:
8
+ * - 文件中出现 JSX 元素且同时包含 value 和 onChange props
9
+ * - 同时该文件在顶层使用了 useState 或 useSetState
10
+ * → 报错提示改用 useForm
11
+ *
12
+ * 例外通过文件路径 overrides 处理(utils、hooks、theme 等已豁免)。
13
+ */
14
+
15
+ /** @type {import('eslint').Rule.RuleModule} */
16
+ const rule = {
17
+ meta: {
18
+ type: "suggestion",
19
+ docs: {
20
+ description:
21
+ "表单组件必须使用 Form.useForm() 或 rc-field-form useForm 管理状态,禁止用 useState/useSetState 管理字段值。",
22
+ },
23
+ schema: [],
24
+ messages: {
25
+ useFormRequired:
26
+ "检测到表单场景使用了 useState/useSetState 管理字段值。请改用 Form.useForm() 或 rc-field-form 的 useForm。详见 .agents/skills/form-convention/SKILL.md。",
27
+ },
28
+ },
29
+ create(context) {
30
+ // sourceCode available via context if needed for future enhancement
31
+
32
+ // 1. 检测 JSX 元素是否同时包含 value 和 onChange props → 认为是表单组件
33
+ let hasFormPattern = false;
34
+
35
+ // 2. 检测是否有 useState / useSetState 调用
36
+ let hasStateHook = false;
37
+
38
+ const stateHooks = new Set(["useState", "useSetState"]);
39
+
40
+ return {
41
+ JSXOpeningElement(node) {
42
+ if (hasFormPattern) return;
43
+
44
+ let hasValue = false;
45
+ let hasOnChange = false;
46
+
47
+ for (const attr of node.attributes) {
48
+ if (attr.type !== "JSXAttribute" || !attr.name) continue;
49
+ const attrName = attr.name.name;
50
+ if (attrName === "value") hasValue = true;
51
+ else if (attrName === "onChange") hasOnChange = true;
52
+
53
+ if (hasValue && hasOnChange) {
54
+ hasFormPattern = true;
55
+ break;
56
+ }
57
+ }
58
+ },
59
+ CallExpression(node) {
60
+ const callee = node.callee;
61
+ if (callee.type === "Identifier" && stateHooks.has(callee.name)) {
62
+ hasStateHook = true;
63
+ }
64
+ },
65
+ "Program:exit"() {
66
+ if (hasFormPattern && hasStateHook) {
67
+ context.report({
68
+ loc: { line: 1, column: 0 },
69
+ messageId: "useFormRequired",
70
+ });
71
+ }
72
+ },
73
+ };
74
+ },
75
+ };
76
+
77
+ export default rule;
@@ -1,7 +1,5 @@
1
1
  import { TypedNextResponse } from "next-rest-framework";
2
2
  import { BaseTable } from "../types.js";
3
- import { NodePgDatabase } from "drizzle-orm/node-postgres";
4
- import { NextRequest } from "next/server";
5
3
  export interface DeleteOperationOptions<TTable extends BaseTable> {
6
4
  table: TTable;
7
5
  summary?: string;
@@ -9,9 +7,4 @@ export interface DeleteOperationOptions<TTable extends BaseTable> {
9
7
  onError?: (error: Error) => Promise<ReturnType<(typeof TypedNextResponse)["json"]> | undefined>;
10
8
  byCreator?: boolean;
11
9
  }
12
- export declare const createDeleteOperation: ({ db, getSession, }: {
13
- db: NodePgDatabase<Record<string, unknown>>;
14
- getSession: (req: NextRequest) => Promise<{
15
- userId?: string;
16
- } | undefined>;
17
- }) => <TTable extends BaseTable>({ table, summary, onSuccess, onError, byCreator, }: DeleteOperationOptions<TTable>) => import("next-rest-framework").RouteOperationDefinition<"DELETE">;
10
+ export declare const createDeleteOperation: any;
@@ -1,7 +1,5 @@
1
1
  import { z, ZodSchema } from "zod";
2
- import { NextRequest } from "next/server";
3
2
  import { TypedNextRequest, TypedNextResponse } from "next-rest-framework";
4
- import { NodePgDatabase } from "drizzle-orm/node-postgres";
5
3
  import { BaseTable, GetListRelations } from "../types.js";
6
4
  export interface GetListOperationOptions<T extends ZodSchema, Q extends ZodSchema, TTable extends BaseTable> {
7
5
  bodySchema: T;
@@ -21,9 +19,4 @@ export interface GetListOperationOptions<T extends ZodSchema, Q extends ZodSchem
21
19
  }>;
22
20
  onError?: (error: Error) => Promise<ReturnType<(typeof TypedNextResponse)["json"]> | undefined>;
23
21
  }
24
- export declare const createGetListOperation: ({ db, getSession, }: {
25
- db: NodePgDatabase<Record<string, unknown>>;
26
- getSession: (req: NextRequest) => Promise<{
27
- userId?: string;
28
- } | undefined>;
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">;
22
+ export declare const createGetListOperation: any;
@@ -1,7 +1,5 @@
1
1
  import { z, ZodSchema } from "zod";
2
- import { NextRequest } from "next/server";
3
2
  import { TypedNextRequest, TypedNextResponse } from "next-rest-framework";
4
- import { NodePgDatabase } from "drizzle-orm/node-postgres";
5
3
  import { BaseTable, GetListRelations } from "../types.js";
6
4
  export interface GetOperationOptions<T extends ZodSchema, Q extends ZodSchema, TTable extends BaseTable> {
7
5
  bodySchema: T;
@@ -15,9 +13,4 @@ export interface GetOperationOptions<T extends ZodSchema, Q extends ZodSchema, T
15
13
  table: TTable;
16
14
  byCreator?: boolean;
17
15
  }
18
- export declare const createGetOperation: ({ getSession, db, }: {
19
- db: NodePgDatabase<Record<string, unknown>>;
20
- getSession: (req: NextRequest) => Promise<{
21
- userId?: string;
22
- } | undefined>;
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">;
16
+ export declare const createGetOperation: any;
@@ -88,7 +88,9 @@ var createGetOperation = ({
88
88
  if (onSuccess) {
89
89
  result = await onSuccess(result);
90
90
  }
91
- return import_next_rest_framework.TypedNextResponse.json(result, { status: 200 });
91
+ return import_next_rest_framework.TypedNextResponse.json(result, {
92
+ status: 200
93
+ });
92
94
  } catch (e) {
93
95
  console.error(e);
94
96
  const response = await (onError == null ? void 0 : onError(e));
@@ -1,8 +1,6 @@
1
1
  import { z, ZodSchema } from "zod";
2
2
  import { PgTable } from "drizzle-orm/pg-core";
3
- import { NextRequest } from "next/server";
4
3
  import { TypedNextRequest, TypedNextResponse } from "next-rest-framework";
5
- import { NodePgDatabase } from "drizzle-orm/node-postgres";
6
4
  export interface PostOperationOptions<IB extends ZodSchema, OB extends ZodSchema, TTable extends PgTable> {
7
5
  bodySchema: IB;
8
6
  outputBodySchema?: IB;
@@ -12,9 +10,4 @@ export interface PostOperationOptions<IB extends ZodSchema, OB extends ZodSchema
12
10
  onError?: (error: Error) => Promise<ReturnType<(typeof TypedNextResponse)["json"]> | undefined>;
13
11
  table: TTable;
14
12
  }
15
- export declare const createPostOperation: ({ getSession, db, }: {
16
- db: NodePgDatabase<Record<string, unknown>>;
17
- getSession: (req: NextRequest) => Promise<{
18
- userId?: string;
19
- } | undefined>;
20
- }) => <IB extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, OB extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, TTable extends PgTable<import("drizzle-orm/pg-core").TableConfig>>({ bodySchema, outputBodySchema, setBody, summary, table, onSuccess, onError, }: PostOperationOptions<IB, OB, TTable>) => import("next-rest-framework").RouteOperationDefinition<"POST">;
13
+ export declare const createPostOperation: any;
@@ -65,18 +65,19 @@ var createPostOperation = ({
65
65
  ]).handler(async (req) => {
66
66
  try {
67
67
  const { userId } = await getSession(req) || {};
68
- const body = Object.assign(
69
- await req.json(),
70
- await (setBody == null ? void 0 : setBody(
71
- req
72
- )) || {}
73
- );
68
+ const body = await req.json();
69
+ const extraBody = await (setBody == null ? void 0 : setBody(
70
+ req
71
+ )) || {};
72
+ const mergedBody = { ...body, ...extraBody };
74
73
  const [raw] = await (0, import_actions.createPostAction)({ bodySchema, db, table })({
75
74
  creatorId: userId,
76
- ...body
75
+ ...mergedBody
77
76
  });
78
77
  const data = onSuccess ? await onSuccess(raw) : raw;
79
- return import_next_rest_framework.TypedNextResponse.json(data, { status: 200 });
78
+ return import_next_rest_framework.TypedNextResponse.json(data, {
79
+ status: 200
80
+ });
80
81
  } catch (e) {
81
82
  console.error(e);
82
83
  const response = await (onError == null ? void 0 : onError(e));
@@ -1,9 +1,6 @@
1
1
  import { z, ZodSchema } from "zod";
2
2
  import { PgTable } from "drizzle-orm/pg-core";
3
3
  import { TypedNextRequest, TypedNextResponse } from "next-rest-framework";
4
- import { NodePgDatabase } from "drizzle-orm/node-postgres";
5
- import { NextRequest } from "next/server";
6
- import { BaseTable } from "../types.js";
7
4
  export interface PutOperationOptions<IB extends ZodSchema, OB extends ZodSchema, TTable extends PgTable> {
8
5
  bodySchema: IB;
9
6
  outputBodySchema?: OB;
@@ -14,9 +11,4 @@ export interface PutOperationOptions<IB extends ZodSchema, OB extends ZodSchema,
14
11
  onError?: (error: Error) => Promise<ReturnType<(typeof TypedNextResponse)["json"]> | undefined>;
15
12
  byCreator?: boolean;
16
13
  }
17
- export declare const createPutOperation: ({ getSession, db, }: {
18
- getSession: (req: NextRequest) => Promise<{
19
- userId?: string;
20
- } | undefined>;
21
- db: NodePgDatabase<Record<string, unknown>>;
22
- }) => <IB extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, OB extends z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, TTable extends BaseTable>({ bodySchema, outputBodySchema, table, summary, setBody, onSuccess, byCreator, onError, }: PutOperationOptions<IB, OB, TTable>) => import("next-rest-framework").RouteOperationDefinition<"PUT">;
14
+ export declare const createPutOperation: any;