dn-react-router-toolkit 0.9.3 → 0.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api/index.js CHANGED
@@ -255,7 +255,7 @@ var defaultAPIHandler = ({
255
255
  };
256
256
 
257
257
  // src/api/resource_handler.ts
258
- var import_gw_response3 = require("gw-response");
258
+ var import_gw_response4 = require("gw-response");
259
259
  var import_gw_result = require("gw-result");
260
260
 
261
261
  // src/api/put_resource_handler.ts
@@ -435,6 +435,36 @@ function putResourceHandler({
435
435
  };
436
436
  }
437
437
 
438
+ // src/api/patch_resource_handler.ts
439
+ var import_gw_response3 = require("gw-response");
440
+ var import_drizzle_orm2 = require("drizzle-orm");
441
+ function patchResourceHandler({ repository, validators }) {
442
+ return async (existing, request) => {
443
+ const serilaizedParams = await request.json();
444
+ const params = deserialize(serilaizedParams) || {};
445
+ if (validators) {
446
+ const paramsForValidation = Object.keys(validators).filter(
447
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
448
+ );
449
+ for (const paramKey of paramsForValidation) {
450
+ const value = params[paramKey];
451
+ const validator = validators[paramKey];
452
+ if (validator?.validate && !validator.validate(value)) {
453
+ return (0, import_gw_response3.httpBadRequest)({
454
+ code: "BAD_REQUEST",
455
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
456
+ });
457
+ }
458
+ }
459
+ }
460
+ const item = await repository.save({
461
+ ...existing,
462
+ ...params
463
+ });
464
+ return (0, import_gw_response3.httpCreated)(item);
465
+ };
466
+ }
467
+
438
468
  // src/api/resource_handler.ts
439
469
  function resourceHandler({
440
470
  withAuthAction,
@@ -450,7 +480,7 @@ function resourceHandler({
450
480
  };
451
481
  const action = withAuthAction((auth) => async ({ request, params }) => {
452
482
  if (roles && roles.length > 0 && (!auth || !roles.includes(auth.role))) {
453
- return (0, import_gw_response3.httpForbidden)({
483
+ return (0, import_gw_response4.httpForbidden)({
454
484
  code: "FORBIDDEN",
455
485
  message: "\uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
456
486
  });
@@ -459,18 +489,25 @@ function resourceHandler({
459
489
  if (itemId) {
460
490
  const existing = await repository.find(itemId);
461
491
  if (!existing) {
462
- return (0, import_gw_response3.httpNotFound)();
492
+ return (0, import_gw_response4.httpNotFound)();
463
493
  }
464
494
  if (isOwnedBy && (!auth || !isOwnedBy(auth, existing))) {
465
- return (0, import_gw_response3.httpForbidden)();
495
+ return (0, import_gw_response4.httpForbidden)();
466
496
  }
467
497
  switch (request.method) {
498
+ case "PATCH": {
499
+ const handler = patchResourceHandler({
500
+ repository,
501
+ validators
502
+ });
503
+ return handler(existing, request);
504
+ }
468
505
  case "DELETE": {
469
506
  await repository.delete(itemId);
470
- return (0, import_gw_response3.httpNoContent)();
507
+ return (0, import_gw_response4.httpNoContent)();
471
508
  }
472
509
  default: {
473
- return (0, import_gw_response3.httpMethodNotAllowed)();
510
+ return (0, import_gw_response4.httpMethodNotAllowed)();
474
511
  }
475
512
  }
476
513
  }
@@ -487,7 +524,7 @@ function resourceHandler({
487
524
  return handler(auth, request);
488
525
  }
489
526
  default: {
490
- return (0, import_gw_response3.httpMethodNotAllowed)();
527
+ return (0, import_gw_response4.httpMethodNotAllowed)();
491
528
  }
492
529
  }
493
530
  });
@@ -431,6 +431,36 @@ function putResourceHandler({
431
431
  };
432
432
  }
433
433
 
434
+ // src/api/patch_resource_handler.ts
435
+ import { httpBadRequest as httpBadRequest2, httpCreated as httpCreated2 } from "gw-response";
436
+ import "drizzle-orm";
437
+ function patchResourceHandler({ repository, validators }) {
438
+ return async (existing, request) => {
439
+ const serilaizedParams = await request.json();
440
+ const params = deserialize(serilaizedParams) || {};
441
+ if (validators) {
442
+ const paramsForValidation = Object.keys(validators).filter(
443
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
444
+ );
445
+ for (const paramKey of paramsForValidation) {
446
+ const value = params[paramKey];
447
+ const validator = validators[paramKey];
448
+ if (validator?.validate && !validator.validate(value)) {
449
+ return httpBadRequest2({
450
+ code: "BAD_REQUEST",
451
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
452
+ });
453
+ }
454
+ }
455
+ }
456
+ const item = await repository.save({
457
+ ...existing,
458
+ ...params
459
+ });
460
+ return httpCreated2(item);
461
+ };
462
+ }
463
+
434
464
  // src/api/resource_handler.ts
435
465
  function resourceHandler({
436
466
  withAuthAction,
@@ -461,6 +491,13 @@ function resourceHandler({
461
491
  return httpForbidden2();
462
492
  }
463
493
  switch (request.method) {
494
+ case "PATCH": {
495
+ const handler = patchResourceHandler({
496
+ repository,
497
+ validators
498
+ });
499
+ return handler(existing, request);
500
+ }
464
501
  case "DELETE": {
465
502
  await repository.delete(itemId);
466
503
  return httpNoContent();
@@ -0,0 +1,21 @@
1
+ import { InferSelectModel, SQLWrapper } from 'drizzle-orm';
2
+ import { PgTableWithColumns } from 'drizzle-orm/pg-core';
3
+ import { TableRepository } from '../table/repository.mjs';
4
+ import 'drizzle-orm/node-postgres';
5
+
6
+ type PatchResourceValidators<T extends PgTableWithColumns<any>> = {
7
+ [K in keyof InferSelectModel<T>]?: {
8
+ validate?: (value?: InferSelectModel<T>[K]) => boolean;
9
+ message?: (value?: InferSelectModel<T>[K]) => string;
10
+ };
11
+ };
12
+ type PatchResourceExistingConditions<T extends PgTableWithColumns<any>> = {
13
+ [K in keyof InferSelectModel<T>]?: (value: InferSelectModel<T>[K]) => SQLWrapper;
14
+ };
15
+ type PatchResourceHandlerOptions<T extends PgTableWithColumns<any>, TSelect> = {
16
+ repository: TableRepository<T, TSelect>;
17
+ validators?: PatchResourceValidators<T>;
18
+ };
19
+ declare function patchResourceHandler<T extends PgTableWithColumns<any>, TSelect>({ repository, validators }: PatchResourceHandlerOptions<T, TSelect>): (existing: TSelect, request: Request) => Promise<Response>;
20
+
21
+ export { type PatchResourceExistingConditions, type PatchResourceHandlerOptions, type PatchResourceValidators, patchResourceHandler };
@@ -0,0 +1,21 @@
1
+ import { InferSelectModel, SQLWrapper } from 'drizzle-orm';
2
+ import { PgTableWithColumns } from 'drizzle-orm/pg-core';
3
+ import { TableRepository } from '../table/repository.js';
4
+ import 'drizzle-orm/node-postgres';
5
+
6
+ type PatchResourceValidators<T extends PgTableWithColumns<any>> = {
7
+ [K in keyof InferSelectModel<T>]?: {
8
+ validate?: (value?: InferSelectModel<T>[K]) => boolean;
9
+ message?: (value?: InferSelectModel<T>[K]) => string;
10
+ };
11
+ };
12
+ type PatchResourceExistingConditions<T extends PgTableWithColumns<any>> = {
13
+ [K in keyof InferSelectModel<T>]?: (value: InferSelectModel<T>[K]) => SQLWrapper;
14
+ };
15
+ type PatchResourceHandlerOptions<T extends PgTableWithColumns<any>, TSelect> = {
16
+ repository: TableRepository<T, TSelect>;
17
+ validators?: PatchResourceValidators<T>;
18
+ };
19
+ declare function patchResourceHandler<T extends PgTableWithColumns<any>, TSelect>({ repository, validators }: PatchResourceHandlerOptions<T, TSelect>): (existing: TSelect, request: Request) => Promise<Response>;
20
+
21
+ export { type PatchResourceExistingConditions, type PatchResourceHandlerOptions, type PatchResourceValidators, patchResourceHandler };
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/api/patch_resource_handler.ts
31
+ var patch_resource_handler_exports = {};
32
+ __export(patch_resource_handler_exports, {
33
+ patchResourceHandler: () => patchResourceHandler
34
+ });
35
+ module.exports = __toCommonJS(patch_resource_handler_exports);
36
+ var import_gw_response = require("gw-response");
37
+
38
+ // src/crud/crud_form_provider.tsx
39
+ var import_react_router = require("react-router");
40
+ var import_react_store_input = require("react-store-input");
41
+ var import_react = require("react");
42
+
43
+ // src/crud/serialize.ts
44
+ function deserialize(data) {
45
+ if (data === void 0) {
46
+ return void 0;
47
+ }
48
+ if (typeof data === "object" && data !== null && "type" in data && "value" in data) {
49
+ const { type, value } = data;
50
+ switch (type) {
51
+ case "null":
52
+ return null;
53
+ case "string":
54
+ return value;
55
+ case "number":
56
+ return value;
57
+ case "boolean":
58
+ return value;
59
+ case "date":
60
+ return new Date(value);
61
+ case "array":
62
+ return value.map((item) => deserialize(item));
63
+ case "object":
64
+ return Object.entries(value).reduce(
65
+ (acc, [key, value2]) => {
66
+ return {
67
+ ...acc,
68
+ [key]: deserialize(value2)
69
+ };
70
+ },
71
+ {}
72
+ );
73
+ default:
74
+ return void 0;
75
+ }
76
+ }
77
+ return void 0;
78
+ }
79
+
80
+ // src/crud/crud_form_provider.tsx
81
+ var import_jsx_runtime = require("react/jsx-runtime");
82
+ var FormContext = (0, import_react.createContext)({});
83
+
84
+ // src/form/create_form_component.tsx
85
+ var import_react2 = require("react");
86
+
87
+ // src/utils/cn.ts
88
+ function cn(...classes) {
89
+ return classes.filter(Boolean).join(" ").trim();
90
+ }
91
+
92
+ // src/utils/date.ts
93
+ var import_moment_timezone = __toESM(require("moment-timezone"));
94
+
95
+ // src/form/create_form_component.tsx
96
+ var import_jsx_runtime2 = require("react/jsx-runtime");
97
+ function createComponent(tag, options) {
98
+ return function FormComponent({ className, ...props }) {
99
+ const Tag = tag;
100
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Tag, { ...props, className: cn(options.className, className) });
101
+ };
102
+ }
103
+
104
+ // src/form/form_components.tsx
105
+ var FormEntry = createComponent("div", {
106
+ className: "flex-1"
107
+ });
108
+ var FormRow = createComponent("div", {
109
+ className: "flex-1 flex gap-4 mb-6"
110
+ });
111
+ var FormLabel = createComponent("label", {
112
+ className: "flex-1 font-semibold mb-2.5 block"
113
+ });
114
+
115
+ // src/crud/crud_form.tsx
116
+ var import_react_store_input3 = require("react-store-input");
117
+
118
+ // src/client/env_loader.tsx
119
+ var import_react_router2 = require("react-router");
120
+ var import_jsx_runtime3 = require("react/jsx-runtime");
121
+
122
+ // src/client/file_input.tsx
123
+ var import_react3 = require("react");
124
+ var import_jsx_runtime4 = require("react/jsx-runtime");
125
+
126
+ // src/client/use_user_agent.tsx
127
+ var import_react_router3 = require("react-router");
128
+
129
+ // src/client/store_text_editor.tsx
130
+ var import_dn_react_text_editor = require("dn-react-text-editor");
131
+ var import_react_store_input2 = require("react-store-input");
132
+ var import_react4 = require("react");
133
+ var import_jsx_runtime5 = require("react/jsx-runtime");
134
+
135
+ // src/client/editor.tsx
136
+ var import_client = require("gw-file/client");
137
+
138
+ // src/crud/crud_form.tsx
139
+ var import_jsx_runtime6 = require("react/jsx-runtime");
140
+
141
+ // src/api/patch_resource_handler.ts
142
+ var import_drizzle_orm = require("drizzle-orm");
143
+ function patchResourceHandler({ repository, validators }) {
144
+ return async (existing, request) => {
145
+ const serilaizedParams = await request.json();
146
+ const params = deserialize(serilaizedParams) || {};
147
+ if (validators) {
148
+ const paramsForValidation = Object.keys(validators).filter(
149
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
150
+ );
151
+ for (const paramKey of paramsForValidation) {
152
+ const value = params[paramKey];
153
+ const validator = validators[paramKey];
154
+ if (validator?.validate && !validator.validate(value)) {
155
+ return (0, import_gw_response.httpBadRequest)({
156
+ code: "BAD_REQUEST",
157
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
158
+ });
159
+ }
160
+ }
161
+ }
162
+ const item = await repository.save({
163
+ ...existing,
164
+ ...params
165
+ });
166
+ return (0, import_gw_response.httpCreated)(item);
167
+ };
168
+ }
169
+ // Annotate the CommonJS export names for ESM import in node:
170
+ 0 && (module.exports = {
171
+ patchResourceHandler
172
+ });
@@ -0,0 +1,144 @@
1
+ // src/api/patch_resource_handler.ts
2
+ import { httpBadRequest, httpCreated } from "gw-response";
3
+
4
+ // src/crud/crud_form_provider.tsx
5
+ import { useNavigate } from "react-router";
6
+ import { useStore } from "react-store-input";
7
+ import {
8
+ createContext,
9
+ useContext
10
+ } from "react";
11
+
12
+ // src/crud/serialize.ts
13
+ function deserialize(data) {
14
+ if (data === void 0) {
15
+ return void 0;
16
+ }
17
+ if (typeof data === "object" && data !== null && "type" in data && "value" in data) {
18
+ const { type, value } = data;
19
+ switch (type) {
20
+ case "null":
21
+ return null;
22
+ case "string":
23
+ return value;
24
+ case "number":
25
+ return value;
26
+ case "boolean":
27
+ return value;
28
+ case "date":
29
+ return new Date(value);
30
+ case "array":
31
+ return value.map((item) => deserialize(item));
32
+ case "object":
33
+ return Object.entries(value).reduce(
34
+ (acc, [key, value2]) => {
35
+ return {
36
+ ...acc,
37
+ [key]: deserialize(value2)
38
+ };
39
+ },
40
+ {}
41
+ );
42
+ default:
43
+ return void 0;
44
+ }
45
+ }
46
+ return void 0;
47
+ }
48
+
49
+ // src/crud/crud_form_provider.tsx
50
+ import { jsx } from "react/jsx-runtime";
51
+ var FormContext = createContext({});
52
+
53
+ // src/form/create_form_component.tsx
54
+ import "react";
55
+
56
+ // src/utils/cn.ts
57
+ function cn(...classes) {
58
+ return classes.filter(Boolean).join(" ").trim();
59
+ }
60
+
61
+ // src/utils/date.ts
62
+ import moment from "moment-timezone";
63
+
64
+ // src/form/create_form_component.tsx
65
+ import { jsx as jsx2 } from "react/jsx-runtime";
66
+ function createComponent(tag, options) {
67
+ return function FormComponent({ className, ...props }) {
68
+ const Tag = tag;
69
+ return /* @__PURE__ */ jsx2(Tag, { ...props, className: cn(options.className, className) });
70
+ };
71
+ }
72
+
73
+ // src/form/form_components.tsx
74
+ var FormEntry = createComponent("div", {
75
+ className: "flex-1"
76
+ });
77
+ var FormRow = createComponent("div", {
78
+ className: "flex-1 flex gap-4 mb-6"
79
+ });
80
+ var FormLabel = createComponent("label", {
81
+ className: "flex-1 font-semibold mb-2.5 block"
82
+ });
83
+
84
+ // src/crud/crud_form.tsx
85
+ import { useStoreComponent } from "react-store-input";
86
+
87
+ // src/client/env_loader.tsx
88
+ import { useRouteLoaderData } from "react-router";
89
+ import { jsx as jsx3 } from "react/jsx-runtime";
90
+
91
+ // src/client/file_input.tsx
92
+ import {
93
+ useRef
94
+ } from "react";
95
+ import { Fragment, jsx as jsx4, jsxs } from "react/jsx-runtime";
96
+
97
+ // src/client/use_user_agent.tsx
98
+ import { useRouteLoaderData as useRouteLoaderData2 } from "react-router";
99
+
100
+ // src/client/store_text_editor.tsx
101
+ import {
102
+ TextEditor
103
+ } from "dn-react-text-editor";
104
+ import { useStoreController } from "react-store-input";
105
+ import { useImperativeHandle, useRef as useRef2 } from "react";
106
+ import { jsx as jsx5 } from "react/jsx-runtime";
107
+
108
+ // src/client/editor.tsx
109
+ import { generateMetadata } from "gw-file/client";
110
+
111
+ // src/crud/crud_form.tsx
112
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
113
+
114
+ // src/api/patch_resource_handler.ts
115
+ import "drizzle-orm";
116
+ function patchResourceHandler({ repository, validators }) {
117
+ return async (existing, request) => {
118
+ const serilaizedParams = await request.json();
119
+ const params = deserialize(serilaizedParams) || {};
120
+ if (validators) {
121
+ const paramsForValidation = Object.keys(validators).filter(
122
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
123
+ );
124
+ for (const paramKey of paramsForValidation) {
125
+ const value = params[paramKey];
126
+ const validator = validators[paramKey];
127
+ if (validator?.validate && !validator.validate(value)) {
128
+ return httpBadRequest({
129
+ code: "BAD_REQUEST",
130
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
131
+ });
132
+ }
133
+ }
134
+ }
135
+ const item = await repository.save({
136
+ ...existing,
137
+ ...params
138
+ });
139
+ return httpCreated(item);
140
+ };
141
+ }
142
+ export {
143
+ patchResourceHandler
144
+ };
@@ -33,7 +33,7 @@ __export(resource_handler_exports, {
33
33
  resourceHandler: () => resourceHandler
34
34
  });
35
35
  module.exports = __toCommonJS(resource_handler_exports);
36
- var import_gw_response2 = require("gw-response");
36
+ var import_gw_response3 = require("gw-response");
37
37
  var import_gw_result = require("gw-result");
38
38
 
39
39
  // src/api/put_resource_handler.ts
@@ -213,6 +213,36 @@ function putResourceHandler({
213
213
  };
214
214
  }
215
215
 
216
+ // src/api/patch_resource_handler.ts
217
+ var import_gw_response2 = require("gw-response");
218
+ var import_drizzle_orm2 = require("drizzle-orm");
219
+ function patchResourceHandler({ repository, validators }) {
220
+ return async (existing, request) => {
221
+ const serilaizedParams = await request.json();
222
+ const params = deserialize(serilaizedParams) || {};
223
+ if (validators) {
224
+ const paramsForValidation = Object.keys(validators).filter(
225
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
226
+ );
227
+ for (const paramKey of paramsForValidation) {
228
+ const value = params[paramKey];
229
+ const validator = validators[paramKey];
230
+ if (validator?.validate && !validator.validate(value)) {
231
+ return (0, import_gw_response2.httpBadRequest)({
232
+ code: "BAD_REQUEST",
233
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
234
+ });
235
+ }
236
+ }
237
+ }
238
+ const item = await repository.save({
239
+ ...existing,
240
+ ...params
241
+ });
242
+ return (0, import_gw_response2.httpCreated)(item);
243
+ };
244
+ }
245
+
216
246
  // src/api/resource_handler.ts
217
247
  function resourceHandler({
218
248
  withAuthAction,
@@ -228,7 +258,7 @@ function resourceHandler({
228
258
  };
229
259
  const action = withAuthAction((auth) => async ({ request, params }) => {
230
260
  if (roles && roles.length > 0 && (!auth || !roles.includes(auth.role))) {
231
- return (0, import_gw_response2.httpForbidden)({
261
+ return (0, import_gw_response3.httpForbidden)({
232
262
  code: "FORBIDDEN",
233
263
  message: "\uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
234
264
  });
@@ -237,18 +267,25 @@ function resourceHandler({
237
267
  if (itemId) {
238
268
  const existing = await repository.find(itemId);
239
269
  if (!existing) {
240
- return (0, import_gw_response2.httpNotFound)();
270
+ return (0, import_gw_response3.httpNotFound)();
241
271
  }
242
272
  if (isOwnedBy && (!auth || !isOwnedBy(auth, existing))) {
243
- return (0, import_gw_response2.httpForbidden)();
273
+ return (0, import_gw_response3.httpForbidden)();
244
274
  }
245
275
  switch (request.method) {
276
+ case "PATCH": {
277
+ const handler = patchResourceHandler({
278
+ repository,
279
+ validators
280
+ });
281
+ return handler(existing, request);
282
+ }
246
283
  case "DELETE": {
247
284
  await repository.delete(itemId);
248
- return (0, import_gw_response2.httpNoContent)();
285
+ return (0, import_gw_response3.httpNoContent)();
249
286
  }
250
287
  default: {
251
- return (0, import_gw_response2.httpMethodNotAllowed)();
288
+ return (0, import_gw_response3.httpMethodNotAllowed)();
252
289
  }
253
290
  }
254
291
  }
@@ -265,7 +302,7 @@ function resourceHandler({
265
302
  return handler(auth, request);
266
303
  }
267
304
  default: {
268
- return (0, import_gw_response2.httpMethodNotAllowed)();
305
+ return (0, import_gw_response3.httpMethodNotAllowed)();
269
306
  }
270
307
  }
271
308
  });
@@ -199,6 +199,36 @@ function putResourceHandler({
199
199
  };
200
200
  }
201
201
 
202
+ // src/api/patch_resource_handler.ts
203
+ import { httpBadRequest as httpBadRequest2, httpCreated as httpCreated2 } from "gw-response";
204
+ import "drizzle-orm";
205
+ function patchResourceHandler({ repository, validators }) {
206
+ return async (existing, request) => {
207
+ const serilaizedParams = await request.json();
208
+ const params = deserialize(serilaizedParams) || {};
209
+ if (validators) {
210
+ const paramsForValidation = Object.keys(validators).filter(
211
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
212
+ );
213
+ for (const paramKey of paramsForValidation) {
214
+ const value = params[paramKey];
215
+ const validator = validators[paramKey];
216
+ if (validator?.validate && !validator.validate(value)) {
217
+ return httpBadRequest2({
218
+ code: "BAD_REQUEST",
219
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
220
+ });
221
+ }
222
+ }
223
+ }
224
+ const item = await repository.save({
225
+ ...existing,
226
+ ...params
227
+ });
228
+ return httpCreated2(item);
229
+ };
230
+ }
231
+
202
232
  // src/api/resource_handler.ts
203
233
  function resourceHandler({
204
234
  withAuthAction,
@@ -229,6 +259,13 @@ function resourceHandler({
229
259
  return httpForbidden2();
230
260
  }
231
261
  switch (request.method) {
262
+ case "PATCH": {
263
+ const handler = patchResourceHandler({
264
+ repository,
265
+ validators
266
+ });
267
+ return handler(existing, request);
268
+ }
232
269
  case "DELETE": {
233
270
  await repository.delete(itemId);
234
271
  return httpNoContent();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dn-react-router-toolkit",
3
- "version": "0.9.3",
3
+ "version": "0.9.4",
4
4
  "types": "./dist/index.d.ts",
5
5
  "main": "./dist/index.mjs",
6
6
  "module": "./dist/index.js",
@@ -91,7 +91,7 @@
91
91
  "gw-auth": "^0.1.2",
92
92
  "gw-file": "^0.1.1",
93
93
  "gw-response": "^0.1.8",
94
- "gw-result": "^0.1.7",
94
+ "gw-result": "^0.1.8",
95
95
  "moment-timezone": "^0.6.1",
96
96
  "pg": "^8.19.0",
97
97
  "react-icons": "^5.5.0",