dn-react-router-toolkit 0.9.3 → 0.9.5

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,39 @@ 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({
442
+ repository,
443
+ validators,
444
+ primaryKey
445
+ }) {
446
+ return async (existing, request) => {
447
+ const serilaizedParams = await request.json();
448
+ const params = deserialize(serilaizedParams) || {};
449
+ if (validators) {
450
+ const paramsForValidation = Object.keys(validators).filter(
451
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
452
+ );
453
+ for (const paramKey of paramsForValidation) {
454
+ const value = params[paramKey];
455
+ const validator = validators[paramKey];
456
+ if (validator?.validate && !validator.validate(value)) {
457
+ return (0, import_gw_response3.httpBadRequest)({
458
+ code: "BAD_REQUEST",
459
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
460
+ });
461
+ }
462
+ }
463
+ }
464
+ const item = await repository.update(existing[primaryKey], {
465
+ ...params
466
+ });
467
+ return (0, import_gw_response3.httpCreated)(item);
468
+ };
469
+ }
470
+
438
471
  // src/api/resource_handler.ts
439
472
  function resourceHandler({
440
473
  withAuthAction,
@@ -443,34 +476,44 @@ function resourceHandler({
443
476
  existingConditions,
444
477
  injectUserId,
445
478
  roles,
446
- isOwnedBy
479
+ isOwnedBy,
480
+ primaryKey
447
481
  }) {
448
482
  const loader = async ({ request }) => {
449
483
  return (0, import_gw_result.ok)({});
450
484
  };
451
485
  const action = withAuthAction((auth) => async ({ request, params }) => {
452
486
  if (roles && roles.length > 0 && (!auth || !roles.includes(auth.role))) {
453
- return (0, import_gw_response3.httpForbidden)({
487
+ return (0, import_gw_response4.httpForbidden)({
454
488
  code: "FORBIDDEN",
455
489
  message: "\uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
456
490
  });
457
491
  }
458
- const itemId = params.itemId;
492
+ const pathname = new URL(request.url).pathname;
493
+ const itemId = pathname.split("/").filter(Boolean).at(-1);
459
494
  if (itemId) {
460
495
  const existing = await repository.find(itemId);
461
496
  if (!existing) {
462
- return (0, import_gw_response3.httpNotFound)();
497
+ return (0, import_gw_response4.httpNotFound)();
463
498
  }
464
499
  if (isOwnedBy && (!auth || !isOwnedBy(auth, existing))) {
465
- return (0, import_gw_response3.httpForbidden)();
500
+ return (0, import_gw_response4.httpForbidden)();
466
501
  }
467
502
  switch (request.method) {
503
+ case "PATCH": {
504
+ const handler = patchResourceHandler({
505
+ repository,
506
+ validators,
507
+ primaryKey
508
+ });
509
+ return handler(existing, request);
510
+ }
468
511
  case "DELETE": {
469
512
  await repository.delete(itemId);
470
- return (0, import_gw_response3.httpNoContent)();
513
+ return (0, import_gw_response4.httpNoContent)();
471
514
  }
472
515
  default: {
473
- return (0, import_gw_response3.httpMethodNotAllowed)();
516
+ return (0, import_gw_response4.httpMethodNotAllowed)();
474
517
  }
475
518
  }
476
519
  }
@@ -487,7 +530,7 @@ function resourceHandler({
487
530
  return handler(auth, request);
488
531
  }
489
532
  default: {
490
- return (0, import_gw_response3.httpMethodNotAllowed)();
533
+ return (0, import_gw_response4.httpMethodNotAllowed)();
491
534
  }
492
535
  }
493
536
  });
@@ -431,6 +431,39 @@ 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({
438
+ repository,
439
+ validators,
440
+ primaryKey
441
+ }) {
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 httpBadRequest2({
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.update(existing[primaryKey], {
461
+ ...params
462
+ });
463
+ return httpCreated2(item);
464
+ };
465
+ }
466
+
434
467
  // src/api/resource_handler.ts
435
468
  function resourceHandler({
436
469
  withAuthAction,
@@ -439,7 +472,8 @@ function resourceHandler({
439
472
  existingConditions,
440
473
  injectUserId,
441
474
  roles,
442
- isOwnedBy
475
+ isOwnedBy,
476
+ primaryKey
443
477
  }) {
444
478
  const loader = async ({ request }) => {
445
479
  return ok({});
@@ -451,7 +485,8 @@ function resourceHandler({
451
485
  message: "\uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
452
486
  });
453
487
  }
454
- const itemId = params.itemId;
488
+ const pathname = new URL(request.url).pathname;
489
+ const itemId = pathname.split("/").filter(Boolean).at(-1);
455
490
  if (itemId) {
456
491
  const existing = await repository.find(itemId);
457
492
  if (!existing) {
@@ -461,6 +496,14 @@ function resourceHandler({
461
496
  return httpForbidden2();
462
497
  }
463
498
  switch (request.method) {
499
+ case "PATCH": {
500
+ const handler = patchResourceHandler({
501
+ repository,
502
+ validators,
503
+ primaryKey
504
+ });
505
+ return handler(existing, request);
506
+ }
464
507
  case "DELETE": {
465
508
  await repository.delete(itemId);
466
509
  return httpNoContent();
@@ -0,0 +1,22 @@
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, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> = {
16
+ repository: TableRepository<T, TSelect, TPrimaryKey>;
17
+ validators?: PatchResourceValidators<T>;
18
+ primaryKey: TPrimaryKey;
19
+ };
20
+ declare function patchResourceHandler<T extends PgTableWithColumns<any>, TSelect, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never>({ repository, validators, primaryKey, }: PatchResourceHandlerOptions<T, TSelect, TPrimaryKey>): (existing: TSelect, request: Request) => Promise<Response>;
21
+
22
+ export { type PatchResourceExistingConditions, type PatchResourceHandlerOptions, type PatchResourceValidators, patchResourceHandler };
@@ -0,0 +1,22 @@
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, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> = {
16
+ repository: TableRepository<T, TSelect, TPrimaryKey>;
17
+ validators?: PatchResourceValidators<T>;
18
+ primaryKey: TPrimaryKey;
19
+ };
20
+ declare function patchResourceHandler<T extends PgTableWithColumns<any>, TSelect, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never>({ repository, validators, primaryKey, }: PatchResourceHandlerOptions<T, TSelect, TPrimaryKey>): (existing: TSelect, request: Request) => Promise<Response>;
21
+
22
+ export { type PatchResourceExistingConditions, type PatchResourceHandlerOptions, type PatchResourceValidators, patchResourceHandler };
@@ -0,0 +1,175 @@
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({
144
+ repository,
145
+ validators,
146
+ primaryKey
147
+ }) {
148
+ return async (existing, request) => {
149
+ const serilaizedParams = await request.json();
150
+ const params = deserialize(serilaizedParams) || {};
151
+ if (validators) {
152
+ const paramsForValidation = Object.keys(validators).filter(
153
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
154
+ );
155
+ for (const paramKey of paramsForValidation) {
156
+ const value = params[paramKey];
157
+ const validator = validators[paramKey];
158
+ if (validator?.validate && !validator.validate(value)) {
159
+ return (0, import_gw_response.httpBadRequest)({
160
+ code: "BAD_REQUEST",
161
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
162
+ });
163
+ }
164
+ }
165
+ }
166
+ const item = await repository.update(existing[primaryKey], {
167
+ ...params
168
+ });
169
+ return (0, import_gw_response.httpCreated)(item);
170
+ };
171
+ }
172
+ // Annotate the CommonJS export names for ESM import in node:
173
+ 0 && (module.exports = {
174
+ patchResourceHandler
175
+ });
@@ -0,0 +1,147 @@
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({
117
+ repository,
118
+ validators,
119
+ primaryKey
120
+ }) {
121
+ return async (existing, request) => {
122
+ const serilaizedParams = await request.json();
123
+ const params = deserialize(serilaizedParams) || {};
124
+ if (validators) {
125
+ const paramsForValidation = Object.keys(validators).filter(
126
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
127
+ );
128
+ for (const paramKey of paramsForValidation) {
129
+ const value = params[paramKey];
130
+ const validator = validators[paramKey];
131
+ if (validator?.validate && !validator.validate(value)) {
132
+ return httpBadRequest({
133
+ code: "BAD_REQUEST",
134
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
135
+ });
136
+ }
137
+ }
138
+ }
139
+ const item = await repository.update(existing[primaryKey], {
140
+ ...params
141
+ });
142
+ return httpCreated(item);
143
+ };
144
+ }
145
+ export {
146
+ patchResourceHandler
147
+ };
@@ -13,13 +13,13 @@ type PutResourceValidators<T extends PgTableWithColumns<any>> = {
13
13
  type PutResourceExistingConditions<T extends PgTableWithColumns<any>> = {
14
14
  [K in keyof InferSelectModel<T>]?: (value: InferSelectModel<T>[K]) => SQLWrapper;
15
15
  };
16
- type PutResourceHandlerOptions<T extends PgTableWithColumns<any>, TSelect> = {
17
- repository: TableRepository<T, TSelect>;
16
+ type PutResourceHandlerOptions<T extends PgTableWithColumns<any>, TSelect, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> = {
17
+ repository: TableRepository<T, TSelect, TPrimaryKey>;
18
18
  validators?: PutResourceValidators<T>;
19
19
  existingConditions?: PutResourceExistingConditions<T>;
20
20
  injectUserId?: boolean;
21
21
  isOwnedBy?: (auth: AccessTokenPayload, item: TSelect) => boolean;
22
22
  };
23
- declare function putResourceHandler<T extends PgTableWithColumns<any>, TSelect>({ repository, validators, existingConditions, injectUserId, isOwnedBy, }: PutResourceHandlerOptions<T, TSelect>): (auth: AccessTokenPayload | undefined, request: Request) => Promise<Response>;
23
+ declare function putResourceHandler<T extends PgTableWithColumns<any>, TSelect, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never>({ repository, validators, existingConditions, injectUserId, isOwnedBy, }: PutResourceHandlerOptions<T, TSelect, TPrimaryKey>): (auth: AccessTokenPayload | undefined, request: Request) => Promise<Response>;
24
24
 
25
25
  export { type PutResourceExistingConditions, type PutResourceHandlerOptions, type PutResourceValidators, putResourceHandler };
@@ -13,13 +13,13 @@ type PutResourceValidators<T extends PgTableWithColumns<any>> = {
13
13
  type PutResourceExistingConditions<T extends PgTableWithColumns<any>> = {
14
14
  [K in keyof InferSelectModel<T>]?: (value: InferSelectModel<T>[K]) => SQLWrapper;
15
15
  };
16
- type PutResourceHandlerOptions<T extends PgTableWithColumns<any>, TSelect> = {
17
- repository: TableRepository<T, TSelect>;
16
+ type PutResourceHandlerOptions<T extends PgTableWithColumns<any>, TSelect, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> = {
17
+ repository: TableRepository<T, TSelect, TPrimaryKey>;
18
18
  validators?: PutResourceValidators<T>;
19
19
  existingConditions?: PutResourceExistingConditions<T>;
20
20
  injectUserId?: boolean;
21
21
  isOwnedBy?: (auth: AccessTokenPayload, item: TSelect) => boolean;
22
22
  };
23
- declare function putResourceHandler<T extends PgTableWithColumns<any>, TSelect>({ repository, validators, existingConditions, injectUserId, isOwnedBy, }: PutResourceHandlerOptions<T, TSelect>): (auth: AccessTokenPayload | undefined, request: Request) => Promise<Response>;
23
+ declare function putResourceHandler<T extends PgTableWithColumns<any>, TSelect, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never>({ repository, validators, existingConditions, injectUserId, isOwnedBy, }: PutResourceHandlerOptions<T, TSelect, TPrimaryKey>): (auth: AccessTokenPayload | undefined, request: Request) => Promise<Response>;
24
24
 
25
25
  export { type PutResourceExistingConditions, type PutResourceHandlerOptions, type PutResourceValidators, putResourceHandler };
@@ -9,16 +9,17 @@ import 'drizzle-orm';
9
9
  import 'drizzle-orm/node-postgres';
10
10
  import 'gw-auth/server';
11
11
 
12
- type APIHandlerOptions<T extends PgTableWithColumns<any>, TSelect> = {
12
+ type APIHandlerOptions<T extends PgTableWithColumns<any>, TSelect, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> = {
13
13
  withAuthAction: WithAuthHandler<ActionFunctionArgs>;
14
- repository: TableRepository<T, TSelect>;
14
+ repository: TableRepository<T, TSelect, TPrimaryKey>;
15
+ primaryKey: TPrimaryKey;
15
16
  validators?: PutResourceValidators<T>;
16
17
  existingConditions?: PutResourceExistingConditions<T>;
17
18
  injectUserId?: boolean;
18
19
  roles?: string[];
19
20
  isOwnedBy?: (auth: AccessTokenPayload, item: TSelect) => boolean;
20
21
  };
21
- declare function resourceHandler<T extends PgTableWithColumns<any>, TSelect>({ withAuthAction, repository, validators, existingConditions, injectUserId, roles, isOwnedBy, }: APIHandlerOptions<T, TSelect>): {
22
+ declare function resourceHandler<T extends PgTableWithColumns<any>, TSelect, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never>({ withAuthAction, repository, validators, existingConditions, injectUserId, roles, isOwnedBy, primaryKey, }: APIHandlerOptions<T, TSelect, TPrimaryKey>): {
22
23
  loader: ({ request }: LoaderFunctionArgs) => Promise<gw_result.Ok<{}>>;
23
24
  action: (arg: ActionFunctionArgs<any>) => Promise<unknown> | unknown;
24
25
  };
@@ -9,16 +9,17 @@ import 'drizzle-orm';
9
9
  import 'drizzle-orm/node-postgres';
10
10
  import 'gw-auth/server';
11
11
 
12
- type APIHandlerOptions<T extends PgTableWithColumns<any>, TSelect> = {
12
+ type APIHandlerOptions<T extends PgTableWithColumns<any>, TSelect, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> = {
13
13
  withAuthAction: WithAuthHandler<ActionFunctionArgs>;
14
- repository: TableRepository<T, TSelect>;
14
+ repository: TableRepository<T, TSelect, TPrimaryKey>;
15
+ primaryKey: TPrimaryKey;
15
16
  validators?: PutResourceValidators<T>;
16
17
  existingConditions?: PutResourceExistingConditions<T>;
17
18
  injectUserId?: boolean;
18
19
  roles?: string[];
19
20
  isOwnedBy?: (auth: AccessTokenPayload, item: TSelect) => boolean;
20
21
  };
21
- declare function resourceHandler<T extends PgTableWithColumns<any>, TSelect>({ withAuthAction, repository, validators, existingConditions, injectUserId, roles, isOwnedBy, }: APIHandlerOptions<T, TSelect>): {
22
+ declare function resourceHandler<T extends PgTableWithColumns<any>, TSelect, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never>({ withAuthAction, repository, validators, existingConditions, injectUserId, roles, isOwnedBy, primaryKey, }: APIHandlerOptions<T, TSelect, TPrimaryKey>): {
22
23
  loader: ({ request }: LoaderFunctionArgs) => Promise<gw_result.Ok<{}>>;
23
24
  action: (arg: ActionFunctionArgs<any>) => Promise<unknown> | unknown;
24
25
  };
@@ -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,39 @@ 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({
220
+ repository,
221
+ validators,
222
+ primaryKey
223
+ }) {
224
+ return async (existing, request) => {
225
+ const serilaizedParams = await request.json();
226
+ const params = deserialize(serilaizedParams) || {};
227
+ if (validators) {
228
+ const paramsForValidation = Object.keys(validators).filter(
229
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
230
+ );
231
+ for (const paramKey of paramsForValidation) {
232
+ const value = params[paramKey];
233
+ const validator = validators[paramKey];
234
+ if (validator?.validate && !validator.validate(value)) {
235
+ return (0, import_gw_response2.httpBadRequest)({
236
+ code: "BAD_REQUEST",
237
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
238
+ });
239
+ }
240
+ }
241
+ }
242
+ const item = await repository.update(existing[primaryKey], {
243
+ ...params
244
+ });
245
+ return (0, import_gw_response2.httpCreated)(item);
246
+ };
247
+ }
248
+
216
249
  // src/api/resource_handler.ts
217
250
  function resourceHandler({
218
251
  withAuthAction,
@@ -221,34 +254,44 @@ function resourceHandler({
221
254
  existingConditions,
222
255
  injectUserId,
223
256
  roles,
224
- isOwnedBy
257
+ isOwnedBy,
258
+ primaryKey
225
259
  }) {
226
260
  const loader = async ({ request }) => {
227
261
  return (0, import_gw_result.ok)({});
228
262
  };
229
263
  const action = withAuthAction((auth) => async ({ request, params }) => {
230
264
  if (roles && roles.length > 0 && (!auth || !roles.includes(auth.role))) {
231
- return (0, import_gw_response2.httpForbidden)({
265
+ return (0, import_gw_response3.httpForbidden)({
232
266
  code: "FORBIDDEN",
233
267
  message: "\uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
234
268
  });
235
269
  }
236
- const itemId = params.itemId;
270
+ const pathname = new URL(request.url).pathname;
271
+ const itemId = pathname.split("/").filter(Boolean).at(-1);
237
272
  if (itemId) {
238
273
  const existing = await repository.find(itemId);
239
274
  if (!existing) {
240
- return (0, import_gw_response2.httpNotFound)();
275
+ return (0, import_gw_response3.httpNotFound)();
241
276
  }
242
277
  if (isOwnedBy && (!auth || !isOwnedBy(auth, existing))) {
243
- return (0, import_gw_response2.httpForbidden)();
278
+ return (0, import_gw_response3.httpForbidden)();
244
279
  }
245
280
  switch (request.method) {
281
+ case "PATCH": {
282
+ const handler = patchResourceHandler({
283
+ repository,
284
+ validators,
285
+ primaryKey
286
+ });
287
+ return handler(existing, request);
288
+ }
246
289
  case "DELETE": {
247
290
  await repository.delete(itemId);
248
- return (0, import_gw_response2.httpNoContent)();
291
+ return (0, import_gw_response3.httpNoContent)();
249
292
  }
250
293
  default: {
251
- return (0, import_gw_response2.httpMethodNotAllowed)();
294
+ return (0, import_gw_response3.httpMethodNotAllowed)();
252
295
  }
253
296
  }
254
297
  }
@@ -265,7 +308,7 @@ function resourceHandler({
265
308
  return handler(auth, request);
266
309
  }
267
310
  default: {
268
- return (0, import_gw_response2.httpMethodNotAllowed)();
311
+ return (0, import_gw_response3.httpMethodNotAllowed)();
269
312
  }
270
313
  }
271
314
  });
@@ -199,6 +199,39 @@ 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({
206
+ repository,
207
+ validators,
208
+ primaryKey
209
+ }) {
210
+ return async (existing, request) => {
211
+ const serilaizedParams = await request.json();
212
+ const params = deserialize(serilaizedParams) || {};
213
+ if (validators) {
214
+ const paramsForValidation = Object.keys(validators).filter(
215
+ (key) => Object.prototype.hasOwnProperty.call(validators, key)
216
+ );
217
+ for (const paramKey of paramsForValidation) {
218
+ const value = params[paramKey];
219
+ const validator = validators[paramKey];
220
+ if (validator?.validate && !validator.validate(value)) {
221
+ return httpBadRequest2({
222
+ code: "BAD_REQUEST",
223
+ message: validator.message ? validator.message(value) : "\uC798\uBABB\uB41C \uC694\uCCAD\uC785\uB2C8\uB2E4."
224
+ });
225
+ }
226
+ }
227
+ }
228
+ const item = await repository.update(existing[primaryKey], {
229
+ ...params
230
+ });
231
+ return httpCreated2(item);
232
+ };
233
+ }
234
+
202
235
  // src/api/resource_handler.ts
203
236
  function resourceHandler({
204
237
  withAuthAction,
@@ -207,7 +240,8 @@ function resourceHandler({
207
240
  existingConditions,
208
241
  injectUserId,
209
242
  roles,
210
- isOwnedBy
243
+ isOwnedBy,
244
+ primaryKey
211
245
  }) {
212
246
  const loader = async ({ request }) => {
213
247
  return ok({});
@@ -219,7 +253,8 @@ function resourceHandler({
219
253
  message: "\uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
220
254
  });
221
255
  }
222
- const itemId = params.itemId;
256
+ const pathname = new URL(request.url).pathname;
257
+ const itemId = pathname.split("/").filter(Boolean).at(-1);
223
258
  if (itemId) {
224
259
  const existing = await repository.find(itemId);
225
260
  if (!existing) {
@@ -229,6 +264,14 @@ function resourceHandler({
229
264
  return httpForbidden2();
230
265
  }
231
266
  switch (request.method) {
267
+ case "PATCH": {
268
+ const handler = patchResourceHandler({
269
+ repository,
270
+ validators,
271
+ primaryKey
272
+ });
273
+ return handler(existing, request);
274
+ }
232
275
  case "DELETE": {
233
276
  await repository.delete(itemId);
234
277
  return httpNoContent();
@@ -41,8 +41,8 @@ var BaseTableRepository = class {
41
41
  this.schema = db._.fullSchema[schema];
42
42
  this.pk = pk;
43
43
  }
44
- async find(id) {
45
- return await this.db.select().from(this.schema).where((0, import_drizzle_orm.eq)(this.schema[this.pk], id)).limit(1).then((res) => res[0]);
44
+ async find(pk) {
45
+ return await this.db.select().from(this.schema).where((0, import_drizzle_orm.eq)(this.schema[this.pk], pk)).limit(1).then((res) => res[0]);
46
46
  }
47
47
  async countTotal({ where }) {
48
48
  const [{ total }] = await this.db.select({ total: (0, import_drizzle_orm.count)() }).from(this.schema).where(where);
@@ -77,6 +77,10 @@ var BaseTableRepository = class {
77
77
  async delete(pk) {
78
78
  await this.db.delete(this.schema).where((0, import_drizzle_orm.eq)(this.schema[this.pk], pk));
79
79
  }
80
+ async update(pk, values) {
81
+ const [item] = await this.db.update(this.schema).set(values).where((0, import_drizzle_orm.eq)(this.schema[this.pk], pk)).returning();
82
+ return item;
83
+ }
80
84
  async select(key) {
81
85
  const rows = await this.db.select({ value: this.schema[key] }).from(this.schema).groupBy(this.schema[key]);
82
86
  return rows.map((row) => row.value);
@@ -14,8 +14,8 @@ var BaseTableRepository = class {
14
14
  this.schema = db._.fullSchema[schema];
15
15
  this.pk = pk;
16
16
  }
17
- async find(id) {
18
- return await this.db.select().from(this.schema).where(eq(this.schema[this.pk], id)).limit(1).then((res) => res[0]);
17
+ async find(pk) {
18
+ return await this.db.select().from(this.schema).where(eq(this.schema[this.pk], pk)).limit(1).then((res) => res[0]);
19
19
  }
20
20
  async countTotal({ where }) {
21
21
  const [{ total }] = await this.db.select({ total: count() }).from(this.schema).where(where);
@@ -50,6 +50,10 @@ var BaseTableRepository = class {
50
50
  async delete(pk) {
51
51
  await this.db.delete(this.schema).where(eq(this.schema[this.pk], pk));
52
52
  }
53
+ async update(pk, values) {
54
+ const [item] = await this.db.update(this.schema).set(values).where(eq(this.schema[this.pk], pk)).returning();
55
+ return item;
56
+ }
53
57
  async select(key) {
54
58
  const rows = await this.db.select({ value: this.schema[key] }).from(this.schema).groupBy(this.schema[key]);
55
59
  return rows.map((row) => row.value);
@@ -12,30 +12,32 @@ type FindAllOptions<T extends PgTableWithColumns<any>> = {
12
12
  type ColumnOf<T> = T extends PgTableWithColumns<infer TConfig> ? keyof TConfig["columns"] : never;
13
13
  type SelectModelOf<T> = T extends TableRepository<infer TSelect, any> ? TSelect : never;
14
14
  type InsertModelOf<T> = T extends TableRepository<any, infer TInsert> ? TInsert : never;
15
- interface TableRepository<T extends PgTableWithColumns<any>, TSelect = InferSelectModel<T>> {
15
+ interface TableRepository<T extends PgTableWithColumns<any>, TSelect = InferSelectModel<T>, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> {
16
16
  schema: T;
17
- find: (id: string) => Promise<TSelect | undefined>;
17
+ find: (pk: TSelect[TPrimaryKey]) => Promise<TSelect | undefined>;
18
18
  countTotal: (options: {
19
19
  where?: SQL<unknown>;
20
20
  }) => Promise<number>;
21
21
  findAll: (options: FindAllOptions<T>) => Promise<TSelect[]>;
22
22
  save: (values: InferInsertModel<T>) => Promise<TSelect>;
23
- delete: (id: string) => Promise<void>;
23
+ update: (pk: TSelect[TPrimaryKey], values: Partial<InferInsertModel<T>>) => Promise<TSelect>;
24
+ delete: (pk: TSelect[TPrimaryKey]) => Promise<void>;
24
25
  select(key: keyof InferSelectModel<T>): Promise<InferSelectModel<T>[typeof key][]>;
25
26
  }
26
27
  type SchemaOf<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"]> = TDatabase["_"]["fullSchema"][TSchemaKey];
27
- declare class BaseTableRepository<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"], TSelect = InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> implements TableRepository<SchemaOf<TDatabase, TSchemaKey>> {
28
+ declare class BaseTableRepository<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"], TSelect = InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> implements TableRepository<SchemaOf<TDatabase, TSchemaKey>, TSelect, TPrimaryKey> {
28
29
  db: TDatabase;
29
30
  schema: SchemaOf<TDatabase, TSchemaKey>;
30
31
  pk: TPrimaryKey;
31
32
  constructor(db: TDatabase, schema: TSchemaKey, pk?: TPrimaryKey);
32
- find(id: string): Promise<TSelect | undefined>;
33
+ find(pk: TSelect[TPrimaryKey]): Promise<TSelect | undefined>;
33
34
  countTotal({ where }: {
34
35
  where?: SQL<unknown>;
35
36
  }): Promise<number>;
36
37
  findAll(options: FindAllOptions<SchemaOf<TDatabase, TSchemaKey>>): Promise<TSelect[]>;
37
38
  save(values: InferInsertModel<SchemaOf<TDatabase, TSchemaKey>>): Promise<TSelect>;
38
- delete(pk: string): Promise<void>;
39
+ delete(pk: TSelect[TPrimaryKey]): Promise<void>;
40
+ update(pk: TSelect[TPrimaryKey], values: Partial<InferInsertModel<SchemaOf<TDatabase, TSchemaKey>>>): Promise<TSelect>;
39
41
  select(key: keyof InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>): Promise<InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>[typeof key][]>;
40
42
  }
41
43
 
@@ -12,30 +12,32 @@ type FindAllOptions<T extends PgTableWithColumns<any>> = {
12
12
  type ColumnOf<T> = T extends PgTableWithColumns<infer TConfig> ? keyof TConfig["columns"] : never;
13
13
  type SelectModelOf<T> = T extends TableRepository<infer TSelect, any> ? TSelect : never;
14
14
  type InsertModelOf<T> = T extends TableRepository<any, infer TInsert> ? TInsert : never;
15
- interface TableRepository<T extends PgTableWithColumns<any>, TSelect = InferSelectModel<T>> {
15
+ interface TableRepository<T extends PgTableWithColumns<any>, TSelect = InferSelectModel<T>, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> {
16
16
  schema: T;
17
- find: (id: string) => Promise<TSelect | undefined>;
17
+ find: (pk: TSelect[TPrimaryKey]) => Promise<TSelect | undefined>;
18
18
  countTotal: (options: {
19
19
  where?: SQL<unknown>;
20
20
  }) => Promise<number>;
21
21
  findAll: (options: FindAllOptions<T>) => Promise<TSelect[]>;
22
22
  save: (values: InferInsertModel<T>) => Promise<TSelect>;
23
- delete: (id: string) => Promise<void>;
23
+ update: (pk: TSelect[TPrimaryKey], values: Partial<InferInsertModel<T>>) => Promise<TSelect>;
24
+ delete: (pk: TSelect[TPrimaryKey]) => Promise<void>;
24
25
  select(key: keyof InferSelectModel<T>): Promise<InferSelectModel<T>[typeof key][]>;
25
26
  }
26
27
  type SchemaOf<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"]> = TDatabase["_"]["fullSchema"][TSchemaKey];
27
- declare class BaseTableRepository<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"], TSelect = InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> implements TableRepository<SchemaOf<TDatabase, TSchemaKey>> {
28
+ declare class BaseTableRepository<TDatabase extends NodePgDatabase<any>, TSchemaKey extends keyof TDatabase["_"]["fullSchema"], TSelect = InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>, TPrimaryKey extends keyof TSelect = "id" extends keyof TSelect ? "id" : never> implements TableRepository<SchemaOf<TDatabase, TSchemaKey>, TSelect, TPrimaryKey> {
28
29
  db: TDatabase;
29
30
  schema: SchemaOf<TDatabase, TSchemaKey>;
30
31
  pk: TPrimaryKey;
31
32
  constructor(db: TDatabase, schema: TSchemaKey, pk?: TPrimaryKey);
32
- find(id: string): Promise<TSelect | undefined>;
33
+ find(pk: TSelect[TPrimaryKey]): Promise<TSelect | undefined>;
33
34
  countTotal({ where }: {
34
35
  where?: SQL<unknown>;
35
36
  }): Promise<number>;
36
37
  findAll(options: FindAllOptions<SchemaOf<TDatabase, TSchemaKey>>): Promise<TSelect[]>;
37
38
  save(values: InferInsertModel<SchemaOf<TDatabase, TSchemaKey>>): Promise<TSelect>;
38
- delete(pk: string): Promise<void>;
39
+ delete(pk: TSelect[TPrimaryKey]): Promise<void>;
40
+ update(pk: TSelect[TPrimaryKey], values: Partial<InferInsertModel<SchemaOf<TDatabase, TSchemaKey>>>): Promise<TSelect>;
39
41
  select(key: keyof InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>): Promise<InferSelectModel<SchemaOf<TDatabase, TSchemaKey>>[typeof key][]>;
40
42
  }
41
43
 
@@ -33,8 +33,8 @@ var BaseTableRepository = class {
33
33
  this.schema = db._.fullSchema[schema];
34
34
  this.pk = pk;
35
35
  }
36
- async find(id) {
37
- return await this.db.select().from(this.schema).where((0, import_drizzle_orm.eq)(this.schema[this.pk], id)).limit(1).then((res) => res[0]);
36
+ async find(pk) {
37
+ return await this.db.select().from(this.schema).where((0, import_drizzle_orm.eq)(this.schema[this.pk], pk)).limit(1).then((res) => res[0]);
38
38
  }
39
39
  async countTotal({ where }) {
40
40
  const [{ total }] = await this.db.select({ total: (0, import_drizzle_orm.count)() }).from(this.schema).where(where);
@@ -69,6 +69,10 @@ var BaseTableRepository = class {
69
69
  async delete(pk) {
70
70
  await this.db.delete(this.schema).where((0, import_drizzle_orm.eq)(this.schema[this.pk], pk));
71
71
  }
72
+ async update(pk, values) {
73
+ const [item] = await this.db.update(this.schema).set(values).where((0, import_drizzle_orm.eq)(this.schema[this.pk], pk)).returning();
74
+ return item;
75
+ }
72
76
  async select(key) {
73
77
  const rows = await this.db.select({ value: this.schema[key] }).from(this.schema).groupBy(this.schema[key]);
74
78
  return rows.map((row) => row.value);
@@ -14,8 +14,8 @@ var BaseTableRepository = class {
14
14
  this.schema = db._.fullSchema[schema];
15
15
  this.pk = pk;
16
16
  }
17
- async find(id) {
18
- return await this.db.select().from(this.schema).where(eq(this.schema[this.pk], id)).limit(1).then((res) => res[0]);
17
+ async find(pk) {
18
+ return await this.db.select().from(this.schema).where(eq(this.schema[this.pk], pk)).limit(1).then((res) => res[0]);
19
19
  }
20
20
  async countTotal({ where }) {
21
21
  const [{ total }] = await this.db.select({ total: count() }).from(this.schema).where(where);
@@ -50,6 +50,10 @@ var BaseTableRepository = class {
50
50
  async delete(pk) {
51
51
  await this.db.delete(this.schema).where(eq(this.schema[this.pk], pk));
52
52
  }
53
+ async update(pk, values) {
54
+ const [item] = await this.db.update(this.schema).set(values).where(eq(this.schema[this.pk], pk)).returning();
55
+ return item;
56
+ }
53
57
  async select(key) {
54
58
  const rows = await this.db.select({ value: this.schema[key] }).from(this.schema).groupBy(this.schema[key]);
55
59
  return rows.map((row) => row.value);
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.5",
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",