dn-react-router-toolkit 0.4.4 → 0.5.1

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 (95) hide show
  1. package/dist/api/create_api_handler.d.mts +28 -0
  2. package/dist/api/create_api_handler.d.ts +28 -0
  3. package/dist/api/create_api_handler.js +148 -0
  4. package/dist/api/create_api_handler.mjs +132 -0
  5. package/dist/api/create_handler.js +27 -25
  6. package/dist/api/create_handler.mjs +27 -25
  7. package/dist/api/index.js +27 -25
  8. package/dist/api/index.mjs +27 -25
  9. package/dist/api/item_api_handler.d.mts +18 -0
  10. package/dist/api/item_api_handler.d.ts +18 -0
  11. package/dist/api/item_api_handler.js +55 -0
  12. package/dist/api/item_api_handler.mjs +30 -0
  13. package/dist/auth/index.d.mts +1 -2
  14. package/dist/auth/index.d.ts +1 -2
  15. package/dist/auth/index.js +13 -21
  16. package/dist/auth/index.mjs +12 -20
  17. package/dist/auth/with_auth.d.mts +3 -3
  18. package/dist/auth/with_auth.d.ts +3 -3
  19. package/dist/auth/with_auth.js +13 -21
  20. package/dist/auth/with_auth.mjs +12 -20
  21. package/dist/crud/crud_form.d.mts +13 -0
  22. package/dist/crud/crud_form.d.ts +13 -0
  23. package/dist/crud/crud_form.js +88 -0
  24. package/dist/crud/crud_form.mjs +55 -0
  25. package/dist/crud/crud_form_provider.d.mts +34 -0
  26. package/dist/crud/crud_form_provider.d.ts +34 -0
  27. package/dist/crud/crud_form_provider.js +160 -0
  28. package/dist/crud/crud_form_provider.mjs +124 -0
  29. package/dist/crud/crud_loader.d.mts +21 -0
  30. package/dist/crud/crud_loader.d.ts +21 -0
  31. package/dist/crud/crud_loader.js +288 -0
  32. package/dist/crud/crud_loader.mjs +273 -0
  33. package/dist/crud/crud_page.d.mts +25 -0
  34. package/dist/crud/crud_page.d.ts +25 -0
  35. package/dist/crud/crud_page.js +645 -0
  36. package/dist/crud/crud_page.mjs +616 -0
  37. package/dist/crud/generate_handlers.d.mts +15 -0
  38. package/dist/crud/generate_handlers.d.ts +15 -0
  39. package/dist/crud/generate_handlers.js +39 -0
  40. package/dist/crud/generate_handlers.mjs +14 -0
  41. package/dist/crud/generate_pages.d.mts +11 -0
  42. package/dist/crud/generate_pages.d.ts +11 -0
  43. package/dist/crud/generate_pages.js +52 -0
  44. package/dist/crud/generate_pages.mjs +17 -0
  45. package/dist/crud/generate_routes.d.mts +5 -0
  46. package/dist/crud/generate_routes.d.ts +5 -0
  47. package/dist/crud/generate_routes.js +62 -0
  48. package/dist/crud/generate_routes.mjs +27 -0
  49. package/dist/crud/index.d.mts +21 -0
  50. package/dist/crud/index.d.ts +21 -0
  51. package/dist/crud/index.js +970 -0
  52. package/dist/crud/index.mjs +945 -0
  53. package/dist/db/index.d.mts +4 -0
  54. package/dist/db/index.d.ts +4 -0
  55. package/dist/db/index.js +46 -0
  56. package/dist/db/index.mjs +8 -0
  57. package/dist/index.d.mts +3 -2
  58. package/dist/index.d.ts +3 -2
  59. package/dist/seo/index.js +26 -25
  60. package/dist/seo/index.mjs +27 -26
  61. package/dist/seo/seo.js +26 -25
  62. package/dist/seo/seo.mjs +27 -26
  63. package/dist/table/buttons.d.mts +10 -0
  64. package/dist/table/buttons.d.ts +10 -0
  65. package/dist/table/buttons.js +102 -0
  66. package/dist/table/buttons.mjs +71 -0
  67. package/dist/table/index.d.mts +9 -0
  68. package/dist/table/index.d.ts +9 -0
  69. package/dist/table/index.js +570 -0
  70. package/dist/table/index.mjs +543 -0
  71. package/dist/table/item_loader.d.mts +12 -0
  72. package/dist/table/item_loader.d.ts +12 -0
  73. package/dist/table/item_loader.js +51 -0
  74. package/dist/table/item_loader.mjs +26 -0
  75. package/dist/table/loader.d.mts +28 -0
  76. package/dist/table/loader.d.ts +28 -0
  77. package/dist/table/loader.js +70 -0
  78. package/dist/table/loader.mjs +48 -0
  79. package/dist/table/page.d.mts +27 -0
  80. package/dist/table/page.d.ts +27 -0
  81. package/dist/table/page.js +444 -0
  82. package/dist/table/page.mjs +415 -0
  83. package/dist/table/repository.d.mts +38 -0
  84. package/dist/table/repository.d.ts +38 -0
  85. package/dist/table/repository.js +76 -0
  86. package/dist/table/repository.mjs +56 -0
  87. package/dist/table/table.d.mts +27 -0
  88. package/dist/table/table.d.ts +27 -0
  89. package/dist/table/table.js +290 -0
  90. package/dist/table/table.mjs +255 -0
  91. package/package.json +21 -3
  92. package/dist/auth/temp_user.d.mts +0 -5
  93. package/dist/auth/temp_user.d.ts +0 -5
  94. package/dist/auth/temp_user.js +0 -18
  95. package/dist/auth/temp_user.mjs +0 -0
@@ -0,0 +1,415 @@
1
+ // src/table/page.tsx
2
+ import {
3
+ Link as Link3,
4
+ useLoaderData,
5
+ useLocation as useLocation2,
6
+ useNavigate,
7
+ useSearchParams as useSearchParams3
8
+ } from "react-router";
9
+
10
+ // node_modules/react-icons/lib/iconBase.mjs
11
+ import React2 from "react";
12
+
13
+ // node_modules/react-icons/lib/iconContext.mjs
14
+ import React from "react";
15
+ var DefaultContext = {
16
+ color: void 0,
17
+ size: void 0,
18
+ className: void 0,
19
+ style: void 0,
20
+ attr: void 0
21
+ };
22
+ var IconContext = React.createContext && /* @__PURE__ */ React.createContext(DefaultContext);
23
+
24
+ // node_modules/react-icons/lib/iconBase.mjs
25
+ var _excluded = ["attr", "size", "title"];
26
+ function _objectWithoutProperties(source, excluded) {
27
+ if (source == null) return {};
28
+ var target = _objectWithoutPropertiesLoose(source, excluded);
29
+ var key, i;
30
+ if (Object.getOwnPropertySymbols) {
31
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
32
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
33
+ key = sourceSymbolKeys[i];
34
+ if (excluded.indexOf(key) >= 0) continue;
35
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
36
+ target[key] = source[key];
37
+ }
38
+ }
39
+ return target;
40
+ }
41
+ function _objectWithoutPropertiesLoose(source, excluded) {
42
+ if (source == null) return {};
43
+ var target = {};
44
+ for (var key in source) {
45
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
46
+ if (excluded.indexOf(key) >= 0) continue;
47
+ target[key] = source[key];
48
+ }
49
+ }
50
+ return target;
51
+ }
52
+ function _extends() {
53
+ _extends = Object.assign ? Object.assign.bind() : function(target) {
54
+ for (var i = 1; i < arguments.length; i++) {
55
+ var source = arguments[i];
56
+ for (var key in source) {
57
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
58
+ target[key] = source[key];
59
+ }
60
+ }
61
+ }
62
+ return target;
63
+ };
64
+ return _extends.apply(this, arguments);
65
+ }
66
+ function ownKeys(e, r) {
67
+ var t = Object.keys(e);
68
+ if (Object.getOwnPropertySymbols) {
69
+ var o = Object.getOwnPropertySymbols(e);
70
+ r && (o = o.filter(function(r2) {
71
+ return Object.getOwnPropertyDescriptor(e, r2).enumerable;
72
+ })), t.push.apply(t, o);
73
+ }
74
+ return t;
75
+ }
76
+ function _objectSpread(e) {
77
+ for (var r = 1; r < arguments.length; r++) {
78
+ var t = null != arguments[r] ? arguments[r] : {};
79
+ r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
80
+ _defineProperty(e, r2, t[r2]);
81
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
82
+ Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
83
+ });
84
+ }
85
+ return e;
86
+ }
87
+ function _defineProperty(obj, key, value) {
88
+ key = _toPropertyKey(key);
89
+ if (key in obj) {
90
+ Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });
91
+ } else {
92
+ obj[key] = value;
93
+ }
94
+ return obj;
95
+ }
96
+ function _toPropertyKey(t) {
97
+ var i = _toPrimitive(t, "string");
98
+ return "symbol" == typeof i ? i : i + "";
99
+ }
100
+ function _toPrimitive(t, r) {
101
+ if ("object" != typeof t || !t) return t;
102
+ var e = t[Symbol.toPrimitive];
103
+ if (void 0 !== e) {
104
+ var i = e.call(t, r || "default");
105
+ if ("object" != typeof i) return i;
106
+ throw new TypeError("@@toPrimitive must return a primitive value.");
107
+ }
108
+ return ("string" === r ? String : Number)(t);
109
+ }
110
+ function Tree2Element(tree) {
111
+ return tree && tree.map((node, i) => /* @__PURE__ */ React2.createElement(node.tag, _objectSpread({
112
+ key: i
113
+ }, node.attr), Tree2Element(node.child)));
114
+ }
115
+ function GenIcon(data) {
116
+ return (props) => /* @__PURE__ */ React2.createElement(IconBase, _extends({
117
+ attr: _objectSpread({}, data.attr)
118
+ }, props), Tree2Element(data.child));
119
+ }
120
+ function IconBase(props) {
121
+ var elem = (conf) => {
122
+ var {
123
+ attr,
124
+ size,
125
+ title
126
+ } = props, svgProps = _objectWithoutProperties(props, _excluded);
127
+ var computedSize = size || conf.size || "1em";
128
+ var className;
129
+ if (conf.className) className = conf.className;
130
+ if (props.className) className = (className ? className + " " : "") + props.className;
131
+ return /* @__PURE__ */ React2.createElement("svg", _extends({
132
+ stroke: "currentColor",
133
+ fill: "currentColor",
134
+ strokeWidth: "0"
135
+ }, conf.attr, attr, svgProps, {
136
+ className,
137
+ style: _objectSpread(_objectSpread({
138
+ color: props.color || conf.color
139
+ }, conf.style), props.style),
140
+ height: computedSize,
141
+ width: computedSize,
142
+ xmlns: "http://www.w3.org/2000/svg"
143
+ }), title && /* @__PURE__ */ React2.createElement("title", null, title), props.children);
144
+ };
145
+ return IconContext !== void 0 ? /* @__PURE__ */ React2.createElement(IconContext.Consumer, null, (conf) => elem(conf)) : elem(DefaultContext);
146
+ }
147
+
148
+ // node_modules/react-icons/go/index.mjs
149
+ function GoArrowDown(props) {
150
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M4.97 13.22a.75.75 0 0 1 1.06 0L11 18.19V3.75a.75.75 0 0 1 1.5 0v14.44l4.97-4.97a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734l-6.25 6.25a.75.75 0 0 1-1.06 0l-6.25-6.25a.75.75 0 0 1 0-1.06Z" }, "child": [] }] })(props);
151
+ }
152
+ function GoArrowUp(props) {
153
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M18.655 10.405a.75.75 0 0 1-1.06 0l-4.97-4.97v14.44a.75.75 0 0 1-1.5 0V5.435l-4.97 4.97a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734l6.25-6.25a.75.75 0 0 1 1.06 0l6.25 6.25a.75.75 0 0 1 0 1.06Z" }, "child": [] }] })(props);
154
+ }
155
+ function GoSearch(props) {
156
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M10.25 2a8.25 8.25 0 0 1 6.34 13.53l5.69 5.69a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-5.69-5.69A8.25 8.25 0 1 1 10.25 2ZM3.5 10.25a6.75 6.75 0 1 0 13.5 0 6.75 6.75 0 0 0-13.5 0Z" }, "child": [] }] })(props);
157
+ }
158
+
159
+ // src/table/buttons.tsx
160
+ import { cn } from "dn-react-toolkit/utils";
161
+ import { Link, useLocation, useSearchParams } from "react-router";
162
+ import React3 from "react";
163
+ function TablePageButtons({
164
+ MAX_PAGES_TO_SHOW,
165
+ total,
166
+ limit,
167
+ offset
168
+ }) {
169
+ const pages = Math.ceil(total / limit);
170
+ const { pathname } = useLocation();
171
+ const [searchParams] = useSearchParams();
172
+ const currentPage = Math.floor(offset / limit) + 1;
173
+ const startButton = (Math.ceil(currentPage / MAX_PAGES_TO_SHOW) - 1) * MAX_PAGES_TO_SHOW;
174
+ const endButton = Math.min(startButton + MAX_PAGES_TO_SHOW - 1, pages);
175
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, pages > 1 && /* @__PURE__ */ React3.createElement("div", { className: "flex justify-center items-center my-8 gap-4 text-neutral-400" }, startButton > 1 && /* @__PURE__ */ React3.createElement(
176
+ Link,
177
+ {
178
+ to: (() => {
179
+ searchParams.set(
180
+ "offset",
181
+ String((startButton - 1) * limit)
182
+ );
183
+ return `${pathname}?${searchParams.toString()}`;
184
+ })(),
185
+ className: "w-10 block text-center transition-colors hover:text-primary"
186
+ },
187
+ "\uC774\uC804"
188
+ ), Array.from({
189
+ length: Math.min(
190
+ MAX_PAGES_TO_SHOW,
191
+ pages - startButton
192
+ )
193
+ }).map((_, index) => {
194
+ return /* @__PURE__ */ React3.createElement(
195
+ Link,
196
+ {
197
+ key: index,
198
+ to: (() => {
199
+ searchParams.set(
200
+ "offset",
201
+ String((startButton + index) * limit)
202
+ );
203
+ return `${pathname}?${searchParams.toString()}`;
204
+ })(),
205
+ className: cn(
206
+ "w-6 block text-center transition-colors",
207
+ currentPage === startButton + index + 1 ? "font-bold text-primary" : "hover:text-primary"
208
+ )
209
+ },
210
+ startButton + index + 1
211
+ );
212
+ }), endButton < pages && /* @__PURE__ */ React3.createElement(
213
+ Link,
214
+ {
215
+ to: (() => {
216
+ searchParams.set(
217
+ "offset",
218
+ String((endButton + 1) * limit)
219
+ );
220
+ return `${pathname}?${searchParams.toString()}`;
221
+ })(),
222
+ className: "w-10 block text-center transition-colors hover:text-primary"
223
+ },
224
+ "\uB2E4\uC74C"
225
+ )));
226
+ }
227
+
228
+ // src/table/table.tsx
229
+ import { cn as cn2 } from "dn-react-toolkit/utils";
230
+ import { Link as Link2, useSearchParams as useSearchParams2 } from "react-router";
231
+ import React4 from "react";
232
+ function Table({
233
+ className = "min-w-full whitespace-nowrap",
234
+ data,
235
+ columns,
236
+ mapper: Mapper,
237
+ getLink,
238
+ limit,
239
+ offset,
240
+ orderBy,
241
+ direction
242
+ }) {
243
+ const keys = Object.entries(columns).filter((entry) => entry[1]).map(([key]) => key);
244
+ const sortedArray = [...data];
245
+ const [_, setSearchParams] = useSearchParams2();
246
+ return /* @__PURE__ */ React4.createElement(
247
+ "table",
248
+ {
249
+ className: cn2(
250
+ className,
251
+ "text-[15px] border-separate border-spacing-0"
252
+ )
253
+ },
254
+ /* @__PURE__ */ React4.createElement("thead", null, /* @__PURE__ */ React4.createElement("tr", null, keys.map((key) => {
255
+ const value = columns[key];
256
+ function getReactNode() {
257
+ if (value && typeof value === "object" && "label" in value) {
258
+ return value.label;
259
+ }
260
+ return value;
261
+ }
262
+ function Head() {
263
+ const reactNode = getReactNode();
264
+ if (typeof reactNode === "string") {
265
+ return /* @__PURE__ */ React4.createElement(
266
+ "button",
267
+ {
268
+ className: cn2(
269
+ orderBy === key ? "text-neutral-900 font-medium" : "text-neutral-500",
270
+ "px-4 h-14 flex items-center w-full"
271
+ ),
272
+ onClick: () => {
273
+ let newDirection = "asc";
274
+ if (orderBy === key) {
275
+ newDirection = direction === "asc" ? "desc" : "asc";
276
+ }
277
+ setSearchParams({
278
+ orderBy: key,
279
+ direction: newDirection
280
+ });
281
+ }
282
+ },
283
+ reactNode,
284
+ orderBy === key && /* @__PURE__ */ React4.createElement("div", { className: "ml-0.5" }, direction === "asc" ? /* @__PURE__ */ React4.createElement(GoArrowUp, null) : /* @__PURE__ */ React4.createElement(GoArrowDown, null))
285
+ );
286
+ }
287
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, reactNode);
288
+ }
289
+ return /* @__PURE__ */ React4.createElement(
290
+ "th",
291
+ {
292
+ key,
293
+ className: cn2("border-y font-normal")
294
+ },
295
+ /* @__PURE__ */ React4.createElement(Head, null)
296
+ );
297
+ }))),
298
+ /* @__PURE__ */ React4.createElement("tbody", null, sortedArray.length === 0 && /* @__PURE__ */ React4.createElement("tr", null, /* @__PURE__ */ React4.createElement(
299
+ "td",
300
+ {
301
+ colSpan: keys.length,
302
+ className: "px-4 h-14 text-neutral-400 text-center"
303
+ },
304
+ "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
305
+ )), sortedArray.map((item, i) => /* @__PURE__ */ React4.createElement("tr", { key: i, className: "hover:bg-gray-50 transition-colors" }, keys.map((key, i2) => {
306
+ const value = item[key];
307
+ function Content() {
308
+ if (key in columns) {
309
+ const column = columns[key];
310
+ if (column && typeof column === "object" && "mapper" in column) {
311
+ const mapper = column.mapper;
312
+ if (mapper) {
313
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, mapper(item));
314
+ }
315
+ }
316
+ }
317
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, String(value));
318
+ }
319
+ const linkedContent = getLink ? /* @__PURE__ */ React4.createElement(
320
+ Link2,
321
+ {
322
+ to: getLink(item),
323
+ className: "block content-center px-4 w-full h-full"
324
+ },
325
+ /* @__PURE__ */ React4.createElement(Content, null)
326
+ ) : /* @__PURE__ */ React4.createElement(Content, null);
327
+ const cell = Mapper ? /* @__PURE__ */ React4.createElement(Mapper, { item, index: i2 }, linkedContent) : linkedContent;
328
+ return /* @__PURE__ */ React4.createElement("td", { key, className: "px-0 h-14 border-b" }, cell);
329
+ }))))
330
+ );
331
+ }
332
+
333
+ // src/table/page.tsx
334
+ import React5 from "react";
335
+ function createTablePage({
336
+ name,
337
+ columns,
338
+ primaryKey = "id"
339
+ }) {
340
+ return function TablePage({
341
+ AdminLayout
342
+ }) {
343
+ const { pathname } = useLocation2();
344
+ const { table } = useLoaderData();
345
+ const { items, total, limit, offset, orderBy, direction, searchKey } = table;
346
+ const navigate = useNavigate();
347
+ const search = (query) => {
348
+ const searchParams2 = new URLSearchParams(window.location.search);
349
+ searchParams2.set("query", query);
350
+ searchParams2.set("offset", "0");
351
+ navigate(`${pathname}?${searchParams2.toString()}`);
352
+ };
353
+ const [searchParams] = useSearchParams3();
354
+ return /* @__PURE__ */ React5.createElement(
355
+ AdminLayout,
356
+ {
357
+ title: name,
358
+ actions: /* @__PURE__ */ React5.createElement(Link3, { to: `${pathname}/new`, className: "button-primary" }, name, " \uCD94\uAC00")
359
+ },
360
+ searchKey && /* @__PURE__ */ React5.createElement(
361
+ "form",
362
+ {
363
+ className: "h-18 px-4 flex items-center border-t",
364
+ onSubmit: (e) => {
365
+ e.preventDefault();
366
+ const formData = new FormData(e.currentTarget);
367
+ const query = formData.get("query");
368
+ search(query);
369
+ }
370
+ },
371
+ /* @__PURE__ */ React5.createElement(
372
+ "button",
373
+ {
374
+ type: "submit",
375
+ className: "w-10 h-10 flex justify-center items-center"
376
+ },
377
+ /* @__PURE__ */ React5.createElement(GoSearch, { className: "text-xl mr-4" })
378
+ ),
379
+ /* @__PURE__ */ React5.createElement(
380
+ "input",
381
+ {
382
+ className: "outline-none h-full flex-1",
383
+ placeholder: "\uC5EC\uAE30\uC5D0 \uAC80\uC0C9\uD558\uC138\uC694...",
384
+ name: "query",
385
+ defaultValue: searchParams.get("query") ?? ""
386
+ }
387
+ )
388
+ ),
389
+ /* @__PURE__ */ React5.createElement(
390
+ Table,
391
+ {
392
+ data: items,
393
+ columns,
394
+ getLink: primaryKey ? (item) => `${pathname}/${item[primaryKey]}` : void 0,
395
+ limit,
396
+ offset,
397
+ orderBy,
398
+ direction
399
+ }
400
+ ),
401
+ /* @__PURE__ */ React5.createElement(
402
+ TablePageButtons,
403
+ {
404
+ total,
405
+ limit,
406
+ offset,
407
+ MAX_PAGES_TO_SHOW: 10
408
+ }
409
+ )
410
+ );
411
+ };
412
+ }
413
+ export {
414
+ createTablePage
415
+ };
@@ -0,0 +1,38 @@
1
+ import { Table, SQL, InferSelectModel, InferInsertModel } from 'drizzle-orm';
2
+ import { PgTableWithColumns } from 'drizzle-orm/pg-core';
3
+
4
+ type FindAllOptions<T extends Table> = {
5
+ orderBy?: keyof InferSelectModel<T>;
6
+ direction?: "asc" | "desc";
7
+ limit?: number;
8
+ offset?: number;
9
+ where?: SQL<unknown>;
10
+ };
11
+ type ColumnOf<T> = T extends PgTableWithColumns<infer TConfig> ? keyof TConfig["columns"] : never;
12
+ type SelectModelOf<T> = T extends TableRepository<infer TSelect, any> ? TSelect : never;
13
+ type InsertModelOf<T> = T extends TableRepository<any, infer TInsert> ? TInsert : never;
14
+ interface TableRepository<T extends Table, TSelect = any> {
15
+ schema: T;
16
+ find: (id: string) => Promise<TSelect | undefined>;
17
+ countTotal: (options: {
18
+ where?: SQL<unknown>;
19
+ }) => Promise<number>;
20
+ findAll: (options: FindAllOptions<T>) => Promise<TSelect[]>;
21
+ save: (values: InferInsertModel<T>) => Promise<TSelect>;
22
+ delete: (id: string) => Promise<void>;
23
+ }
24
+ declare class BaseTableRepository<T extends PgTableWithColumns<any>, TSelect = InferSelectModel<T>, TPrimaryKey extends keyof T = "id" extends keyof T ? "id" : never> implements TableRepository<T, TSelect> {
25
+ db: any;
26
+ schema: T;
27
+ pk: TPrimaryKey;
28
+ constructor(db: any, schema: T, pk?: TPrimaryKey);
29
+ find(id: string): Promise<TSelect | undefined>;
30
+ countTotal({ where }: {
31
+ where?: SQL<unknown>;
32
+ }): Promise<number>;
33
+ findAll(options: FindAllOptions<T>): Promise<TSelect[]>;
34
+ save(values: InferInsertModel<T>): Promise<TSelect>;
35
+ delete(pk: string): Promise<void>;
36
+ }
37
+
38
+ export { BaseTableRepository, type ColumnOf, type FindAllOptions, type InsertModelOf, type SelectModelOf, type TableRepository };
@@ -0,0 +1,38 @@
1
+ import { Table, SQL, InferSelectModel, InferInsertModel } from 'drizzle-orm';
2
+ import { PgTableWithColumns } from 'drizzle-orm/pg-core';
3
+
4
+ type FindAllOptions<T extends Table> = {
5
+ orderBy?: keyof InferSelectModel<T>;
6
+ direction?: "asc" | "desc";
7
+ limit?: number;
8
+ offset?: number;
9
+ where?: SQL<unknown>;
10
+ };
11
+ type ColumnOf<T> = T extends PgTableWithColumns<infer TConfig> ? keyof TConfig["columns"] : never;
12
+ type SelectModelOf<T> = T extends TableRepository<infer TSelect, any> ? TSelect : never;
13
+ type InsertModelOf<T> = T extends TableRepository<any, infer TInsert> ? TInsert : never;
14
+ interface TableRepository<T extends Table, TSelect = any> {
15
+ schema: T;
16
+ find: (id: string) => Promise<TSelect | undefined>;
17
+ countTotal: (options: {
18
+ where?: SQL<unknown>;
19
+ }) => Promise<number>;
20
+ findAll: (options: FindAllOptions<T>) => Promise<TSelect[]>;
21
+ save: (values: InferInsertModel<T>) => Promise<TSelect>;
22
+ delete: (id: string) => Promise<void>;
23
+ }
24
+ declare class BaseTableRepository<T extends PgTableWithColumns<any>, TSelect = InferSelectModel<T>, TPrimaryKey extends keyof T = "id" extends keyof T ? "id" : never> implements TableRepository<T, TSelect> {
25
+ db: any;
26
+ schema: T;
27
+ pk: TPrimaryKey;
28
+ constructor(db: any, schema: T, pk?: TPrimaryKey);
29
+ find(id: string): Promise<TSelect | undefined>;
30
+ countTotal({ where }: {
31
+ where?: SQL<unknown>;
32
+ }): Promise<number>;
33
+ findAll(options: FindAllOptions<T>): Promise<TSelect[]>;
34
+ save(values: InferInsertModel<T>): Promise<TSelect>;
35
+ delete(pk: string): Promise<void>;
36
+ }
37
+
38
+ export { BaseTableRepository, type ColumnOf, type FindAllOptions, type InsertModelOf, type SelectModelOf, type TableRepository };
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc2) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc2 = __getOwnPropDesc(from, key)) || desc2.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/table/repository.ts
21
+ var repository_exports = {};
22
+ __export(repository_exports, {
23
+ BaseTableRepository: () => BaseTableRepository
24
+ });
25
+ module.exports = __toCommonJS(repository_exports);
26
+ var import_drizzle_orm = require("drizzle-orm");
27
+ var BaseTableRepository = class {
28
+ db;
29
+ schema;
30
+ pk;
31
+ constructor(db, schema, pk = "id") {
32
+ this.db = db;
33
+ this.schema = schema;
34
+ this.pk = pk;
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]);
38
+ }
39
+ async countTotal({ where }) {
40
+ const [{ total }] = await this.db.select({ total: (0, import_drizzle_orm.count)() }).from(this.schema).where(where);
41
+ return total;
42
+ }
43
+ async findAll(options) {
44
+ const { orderBy, direction, limit, offset, where } = options;
45
+ let builder = this.db.select().from(this.schema);
46
+ if (where) {
47
+ builder = builder.where(where);
48
+ }
49
+ if (orderBy) {
50
+ builder = builder.orderBy(
51
+ direction === "desc" ? (0, import_drizzle_orm.desc)(this.schema[orderBy]) : (0, import_drizzle_orm.asc)(this.schema[orderBy])
52
+ );
53
+ }
54
+ if (limit) {
55
+ builder = builder.limit(limit);
56
+ }
57
+ if (offset) {
58
+ builder = builder.offset(offset);
59
+ }
60
+ return await builder;
61
+ }
62
+ async save(values) {
63
+ const [item] = await this.db.insert(this.schema).values(values).onConflictDoUpdate({
64
+ target: this.schema[this.pk],
65
+ set: values
66
+ }).returning();
67
+ return item;
68
+ }
69
+ async delete(pk) {
70
+ await this.db.delete(this.schema).where((0, import_drizzle_orm.eq)(this.schema[this.pk], pk));
71
+ }
72
+ };
73
+ // Annotate the CommonJS export names for ESM import in node:
74
+ 0 && (module.exports = {
75
+ BaseTableRepository
76
+ });
@@ -0,0 +1,56 @@
1
+ // src/table/repository.ts
2
+ import {
3
+ count,
4
+ eq,
5
+ desc,
6
+ asc
7
+ } from "drizzle-orm";
8
+ var BaseTableRepository = class {
9
+ db;
10
+ schema;
11
+ pk;
12
+ constructor(db, schema, pk = "id") {
13
+ this.db = db;
14
+ this.schema = schema;
15
+ this.pk = pk;
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]);
19
+ }
20
+ async countTotal({ where }) {
21
+ const [{ total }] = await this.db.select({ total: count() }).from(this.schema).where(where);
22
+ return total;
23
+ }
24
+ async findAll(options) {
25
+ const { orderBy, direction, limit, offset, where } = options;
26
+ let builder = this.db.select().from(this.schema);
27
+ if (where) {
28
+ builder = builder.where(where);
29
+ }
30
+ if (orderBy) {
31
+ builder = builder.orderBy(
32
+ direction === "desc" ? desc(this.schema[orderBy]) : asc(this.schema[orderBy])
33
+ );
34
+ }
35
+ if (limit) {
36
+ builder = builder.limit(limit);
37
+ }
38
+ if (offset) {
39
+ builder = builder.offset(offset);
40
+ }
41
+ return await builder;
42
+ }
43
+ async save(values) {
44
+ const [item] = await this.db.insert(this.schema).values(values).onConflictDoUpdate({
45
+ target: this.schema[this.pk],
46
+ set: values
47
+ }).returning();
48
+ return item;
49
+ }
50
+ async delete(pk) {
51
+ await this.db.delete(this.schema).where(eq(this.schema[this.pk], pk));
52
+ }
53
+ };
54
+ export {
55
+ BaseTableRepository
56
+ };
@@ -0,0 +1,27 @@
1
+ import React, { ReactNode } from 'react';
2
+
3
+ type TableColumnProps<T> = ReactNode | {
4
+ label: ReactNode;
5
+ mapper?: (item: T) => ReactNode;
6
+ sort?: (a: T, b: T) => number;
7
+ };
8
+ type TableColumnOptions<T> = {
9
+ [key in string]?: TableColumnProps<T>;
10
+ };
11
+ type OrderedTableProps<T> = React.DetailedHTMLProps<React.TableHTMLAttributes<HTMLTableElement>, HTMLTableElement> & {
12
+ data: T[];
13
+ columns: TableColumnOptions<T>;
14
+ mapper?: React.FC<{
15
+ item: T;
16
+ index: number;
17
+ children: ReactNode;
18
+ }>;
19
+ getLink?: (item: T) => string;
20
+ limit?: number;
21
+ offset?: number;
22
+ orderBy?: string;
23
+ direction?: string;
24
+ };
25
+ declare function Table<T>({ className, data, columns, mapper: Mapper, getLink, limit, offset, orderBy, direction, }: OrderedTableProps<T>): React.JSX.Element;
26
+
27
+ export { type OrderedTableProps, Table, type TableColumnOptions, type TableColumnProps };
@@ -0,0 +1,27 @@
1
+ import React, { ReactNode } from 'react';
2
+
3
+ type TableColumnProps<T> = ReactNode | {
4
+ label: ReactNode;
5
+ mapper?: (item: T) => ReactNode;
6
+ sort?: (a: T, b: T) => number;
7
+ };
8
+ type TableColumnOptions<T> = {
9
+ [key in string]?: TableColumnProps<T>;
10
+ };
11
+ type OrderedTableProps<T> = React.DetailedHTMLProps<React.TableHTMLAttributes<HTMLTableElement>, HTMLTableElement> & {
12
+ data: T[];
13
+ columns: TableColumnOptions<T>;
14
+ mapper?: React.FC<{
15
+ item: T;
16
+ index: number;
17
+ children: ReactNode;
18
+ }>;
19
+ getLink?: (item: T) => string;
20
+ limit?: number;
21
+ offset?: number;
22
+ orderBy?: string;
23
+ direction?: string;
24
+ };
25
+ declare function Table<T>({ className, data, columns, mapper: Mapper, getLink, limit, offset, orderBy, direction, }: OrderedTableProps<T>): React.JSX.Element;
26
+
27
+ export { type OrderedTableProps, Table, type TableColumnOptions, type TableColumnProps };