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,970 @@
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/crud/index.ts
31
+ var crud_exports = {};
32
+ __export(crud_exports, {
33
+ FormContext: () => FormContext,
34
+ crudHandler: () => crudHandler,
35
+ crudPage: () => crudPage,
36
+ generateCrudRoutes: () => generateCrudRoutes,
37
+ generateHandlers: () => generateHandlers,
38
+ generatePages: () => generatePages,
39
+ useFormContext: () => useFormContext
40
+ });
41
+ module.exports = __toCommonJS(crud_exports);
42
+
43
+ // src/crud/crud_form_provider.tsx
44
+ var import_react_router = require("react-router");
45
+ var import_store = require("dn-react-toolkit/store");
46
+ var import_react = require("react");
47
+ var import_react2 = __toESM(require("react"));
48
+ var FormContext = (0, import_react.createContext)({});
49
+ function useFormContext() {
50
+ return (0, import_react.useContext)(FormContext);
51
+ }
52
+ function CrudFormProvider({
53
+ primaryKey = "id",
54
+ name,
55
+ prefix: prefix2,
56
+ item,
57
+ columns = {},
58
+ children
59
+ }) {
60
+ const apiPrefix = `/api${prefix2}`;
61
+ const store = (0, import_store.useStore)({
62
+ ...item || {}
63
+ });
64
+ const navigate = (0, import_react_router.useNavigate)();
65
+ const submit = async () => {
66
+ const res = await fetch(apiPrefix, {
67
+ method: "POST",
68
+ headers: {
69
+ "Content-Type": "application/json"
70
+ },
71
+ body: JSON.stringify(
72
+ Object.entries(store.state).reduce(
73
+ function reducer(acc, [key, value]) {
74
+ const converter = (value2) => {
75
+ if (value2 === void 0) {
76
+ return void 0;
77
+ }
78
+ if (value2 === null) {
79
+ return {
80
+ type: "null",
81
+ value: null
82
+ };
83
+ }
84
+ if (typeof value2 === "string") {
85
+ return {
86
+ type: "string",
87
+ value: value2
88
+ };
89
+ }
90
+ if (typeof value2 === "number") {
91
+ return {
92
+ type: "number",
93
+ value: value2
94
+ };
95
+ }
96
+ if (typeof value2 === "boolean") {
97
+ return {
98
+ type: "boolean",
99
+ value: value2
100
+ };
101
+ }
102
+ if (value2 instanceof Date) {
103
+ return {
104
+ type: "date",
105
+ value: value2.toISOString()
106
+ };
107
+ }
108
+ if (Array.isArray(value2)) {
109
+ return value2.map((v) => converter(v));
110
+ }
111
+ if (typeof value2 === "object") {
112
+ return Object.entries(
113
+ value2
114
+ ).reduce(reducer, {});
115
+ }
116
+ };
117
+ return {
118
+ ...acc,
119
+ [key]: converter(value)
120
+ };
121
+ },
122
+ {}
123
+ )
124
+ )
125
+ });
126
+ if (!res.ok) {
127
+ const { message } = await res.json();
128
+ alert(message);
129
+ return;
130
+ }
131
+ alert(`${name}\uB97C \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4.`);
132
+ const { id } = await res.json();
133
+ navigate(`${prefix2}/${id}`);
134
+ };
135
+ const deleteItem = async () => {
136
+ if (!item || !primaryKey) {
137
+ return;
138
+ }
139
+ const ok = confirm("\uC815\uB9D0\uB85C \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?");
140
+ if (!ok) {
141
+ return;
142
+ }
143
+ const res = await fetch(`${apiPrefix}/${item[primaryKey]}`, {
144
+ method: "DELETE"
145
+ });
146
+ if (!res.ok) {
147
+ const { message } = await res.json();
148
+ alert(message);
149
+ return;
150
+ }
151
+ alert(`${name}\uB97C \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4.`);
152
+ navigate(`${prefix2}`);
153
+ };
154
+ return /* @__PURE__ */ import_react2.default.createElement(
155
+ FormContext.Provider,
156
+ {
157
+ value: { name, item, store, submit, delete: deleteItem, columns }
158
+ },
159
+ children
160
+ );
161
+ }
162
+
163
+ // src/crud/crud_form.tsx
164
+ var import_store2 = require("dn-react-toolkit/store");
165
+ var import_react3 = __toESM(require("react"));
166
+ function CrudForm({ AdminLayout }) {
167
+ const form = useFormContext();
168
+ return /* @__PURE__ */ import_react3.default.createElement(
169
+ AdminLayout,
170
+ {
171
+ title: `${form.name} ${form.item ? "\uC218\uC815" : "\uCD94\uAC00"}`,
172
+ actions: /* @__PURE__ */ import_react3.default.createElement(
173
+ "button",
174
+ {
175
+ type: "button",
176
+ className: "button-primary",
177
+ onClick: form.submit
178
+ },
179
+ "\uC800\uC7A5\uD558\uAE30"
180
+ ),
181
+ className: "max-w-3xl mx-auto"
182
+ },
183
+ Object.keys(form.columns).length > 0 && /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, Object.entries(form.columns).map(
184
+ ([key, value]) => /* @__PURE__ */ import_react3.default.createElement("label", { key }, value.label, value.component ? /* @__PURE__ */ import_react3.default.createElement(value.component, null) : /* @__PURE__ */ import_react3.default.createElement(
185
+ import_store2.SyncInput,
186
+ {
187
+ store: form.store,
188
+ property: key,
189
+ className: "input-form"
190
+ }
191
+ ))
192
+ )),
193
+ form.item && /* @__PURE__ */ import_react3.default.createElement(
194
+ "button",
195
+ {
196
+ className: "button-dangerous mt-8",
197
+ onClick: () => {
198
+ form.delete();
199
+ }
200
+ },
201
+ "\uC0AD\uC81C\uD558\uAE30"
202
+ )
203
+ );
204
+ }
205
+
206
+ // src/table/loader.tsx
207
+ var import_drizzle_orm = require("drizzle-orm");
208
+ function tableLoader({
209
+ repository,
210
+ tableOptions
211
+ }) {
212
+ return async ({ request }) => {
213
+ const searchParams = new URL(request.url).searchParams;
214
+ const { where, searchKey, defaultOrderBy, defaultDirection } = tableOptions;
215
+ const query = searchParams.get("query") ?? void 0;
216
+ const limit = Number(searchParams.get("limit") ?? "10");
217
+ const offset = Number(searchParams.get("offset") ?? "0");
218
+ const orderBy = searchParams.get("orderBy") ?? defaultOrderBy;
219
+ const direction = searchParams.get("direction") ?? defaultDirection;
220
+ const whereClauses = (0, import_drizzle_orm.and)(
221
+ searchKey && query ? (0, import_drizzle_orm.ilike)(
222
+ repository.schema[searchKey],
223
+ `%${query}%`
224
+ ) : void 0,
225
+ ...where ?? []
226
+ );
227
+ const total = await repository.countTotal({ where: whereClauses });
228
+ const items = await repository.findAll({
229
+ orderBy,
230
+ direction,
231
+ limit,
232
+ offset,
233
+ where: whereClauses
234
+ });
235
+ return {
236
+ table: {
237
+ items,
238
+ total,
239
+ limit,
240
+ offset,
241
+ orderBy,
242
+ direction,
243
+ searchKey
244
+ }
245
+ };
246
+ };
247
+ }
248
+
249
+ // src/table/item_loader.tsx
250
+ var tableItemloader = ({
251
+ loader,
252
+ repository
253
+ }) => {
254
+ return async ({ params }) => {
255
+ const body = loader ? await (async () => {
256
+ const result = await loader({ params });
257
+ if (result instanceof Response) {
258
+ return result.json();
259
+ }
260
+ return result;
261
+ })() : {};
262
+ if (params["itemId"] === "new") {
263
+ return { item: void 0, ...body };
264
+ }
265
+ const item = params["itemId"] ? await repository.find(params["itemId"]) : void 0;
266
+ return {
267
+ item,
268
+ ...body
269
+ };
270
+ };
271
+ };
272
+
273
+ // src/api/create_api_handler.ts
274
+ var import_http = require("dn-react-toolkit/http");
275
+ var import_drizzle_orm2 = require("drizzle-orm");
276
+ var import_react_router2 = require("react-router");
277
+ var import_uuid = require("uuid");
278
+ function apiHandler({
279
+ withAuthAction,
280
+ repository,
281
+ validators,
282
+ existingConditions,
283
+ injectUserId
284
+ }) {
285
+ const loader = async ({ request }) => {
286
+ return {};
287
+ };
288
+ const action = withAuthAction((auth) => async ({ request }) => {
289
+ if (!auth || auth.role !== "admin") {
290
+ return (0, import_react_router2.redirect)("/login");
291
+ }
292
+ switch (request.method) {
293
+ case "POST":
294
+ case "PUT": {
295
+ const serilaizedParams = await request.json();
296
+ const params = Object.entries(serilaizedParams).reduce(
297
+ function reducer(acc, [key, value]) {
298
+ const converter = (value2) => {
299
+ if (value2.type === "null") {
300
+ return null;
301
+ }
302
+ if (value2.type === "string") {
303
+ return value2.value;
304
+ }
305
+ if (value2.type === "number") {
306
+ return value2.value;
307
+ }
308
+ if (value2.type === "boolean") {
309
+ return value2.value;
310
+ }
311
+ if (value2.type === "date") {
312
+ return new Date(value2.value);
313
+ }
314
+ if (Array.isArray(value2)) {
315
+ return value2.map((v) => converter(v));
316
+ }
317
+ if (typeof value2 === "object") {
318
+ return Object.entries(value2).reduce(
319
+ reducer,
320
+ {}
321
+ );
322
+ }
323
+ };
324
+ const result = converter(value);
325
+ if (result === void 0) {
326
+ return acc;
327
+ }
328
+ return {
329
+ ...acc,
330
+ [key]: result
331
+ };
332
+ },
333
+ {}
334
+ );
335
+ if (validators) {
336
+ const paramsForValidation = Object.keys(validators).filter(
337
+ (key) => Object.prototype.hasOwnProperty.call(
338
+ validators,
339
+ key
340
+ )
341
+ );
342
+ for (const paramKey of paramsForValidation) {
343
+ const value = params[paramKey];
344
+ const validator = validators[paramKey];
345
+ if (validator?.validate && !validator.validate(value)) {
346
+ throw (0, import_http.BAD_REQUEST)(
347
+ validator.message ? validator.message(value) : void 0
348
+ );
349
+ }
350
+ }
351
+ }
352
+ const itemId = params.id || (0, import_uuid.v4)();
353
+ if (!params.id && existingConditions) {
354
+ const paramsForExistenceCheck = Object.keys(
355
+ existingConditions
356
+ ).filter(
357
+ (key) => Object.prototype.hasOwnProperty.call(params, key)
358
+ );
359
+ const where = (0, import_drizzle_orm2.and)(
360
+ ...paramsForExistenceCheck.reduce((acc, key) => {
361
+ const condition = existingConditions[key];
362
+ if (condition) {
363
+ acc.push(condition(params[key]));
364
+ }
365
+ return acc;
366
+ }, [])
367
+ );
368
+ const existing = await repository.findAll({
369
+ limit: 1,
370
+ where
371
+ });
372
+ if (existing.length > 0) {
373
+ throw (0, import_http.CONFLICT)("\uC790\uB8CC\uAC00 \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4.");
374
+ }
375
+ }
376
+ const values = {
377
+ id: itemId,
378
+ userId: injectUserId ? auth.userId : void 0,
379
+ ...params
380
+ };
381
+ const item = await repository.save(values);
382
+ return (0, import_http.CREATED)(item);
383
+ }
384
+ default:
385
+ throw (0, import_http.METHOD_NOT_ALLOWED)();
386
+ }
387
+ });
388
+ return {
389
+ loader,
390
+ action
391
+ };
392
+ }
393
+
394
+ // src/api/item_api_handler.ts
395
+ var import_http2 = require("dn-react-toolkit/http");
396
+ var import_react_router3 = require("react-router");
397
+ function itemApiHandler({
398
+ withAuthAction,
399
+ repository
400
+ }) {
401
+ const loader = async ({ request }) => {
402
+ return {};
403
+ };
404
+ const action = withAuthAction((auth) => async ({ params, request }) => {
405
+ if (!auth || auth.role !== "admin") {
406
+ return (0, import_http2.UNAUTHORIZED)();
407
+ }
408
+ switch (request.method) {
409
+ case "DELETE": {
410
+ const itemId = params.itemId;
411
+ await repository.delete(itemId);
412
+ return {};
413
+ }
414
+ }
415
+ });
416
+ return {
417
+ loader,
418
+ action
419
+ };
420
+ }
421
+
422
+ // src/crud/crud_loader.tsx
423
+ function crudHandler({
424
+ repository,
425
+ apiHandlerOptions,
426
+ loaderOptions,
427
+ itemLoaderOptions
428
+ }) {
429
+ return (prefix2) => async (args) => {
430
+ const pattern = args.unstable_pattern;
431
+ if (pattern === `/api${prefix2}`) {
432
+ const { loader, action } = apiHandler({
433
+ repository,
434
+ ...apiHandlerOptions
435
+ });
436
+ if (args.request.method === "GET") {
437
+ return loader(args);
438
+ } else {
439
+ return action(args);
440
+ }
441
+ }
442
+ if (pattern.startsWith(`/api${prefix2}`)) {
443
+ const { loader, action } = itemApiHandler({
444
+ repository,
445
+ ...apiHandlerOptions
446
+ });
447
+ if (args.request.method === "GET") {
448
+ return loader(args);
449
+ } else {
450
+ return action(args);
451
+ }
452
+ }
453
+ if (pattern === prefix2) {
454
+ return tableLoader({
455
+ ...loaderOptions,
456
+ repository
457
+ })(args);
458
+ }
459
+ if (pattern.startsWith(prefix2)) {
460
+ return tableItemloader({ ...itemLoaderOptions, repository })(args);
461
+ }
462
+ };
463
+ }
464
+
465
+ // src/crud/crud_page.tsx
466
+ var import_react_router7 = require("react-router");
467
+
468
+ // src/table/page.tsx
469
+ var import_react_router6 = require("react-router");
470
+
471
+ // node_modules/react-icons/lib/iconBase.mjs
472
+ var import_react5 = __toESM(require("react"), 1);
473
+
474
+ // node_modules/react-icons/lib/iconContext.mjs
475
+ var import_react4 = __toESM(require("react"), 1);
476
+ var DefaultContext = {
477
+ color: void 0,
478
+ size: void 0,
479
+ className: void 0,
480
+ style: void 0,
481
+ attr: void 0
482
+ };
483
+ var IconContext = import_react4.default.createContext && /* @__PURE__ */ import_react4.default.createContext(DefaultContext);
484
+
485
+ // node_modules/react-icons/lib/iconBase.mjs
486
+ var _excluded = ["attr", "size", "title"];
487
+ function _objectWithoutProperties(source, excluded) {
488
+ if (source == null) return {};
489
+ var target = _objectWithoutPropertiesLoose(source, excluded);
490
+ var key, i;
491
+ if (Object.getOwnPropertySymbols) {
492
+ var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
493
+ for (i = 0; i < sourceSymbolKeys.length; i++) {
494
+ key = sourceSymbolKeys[i];
495
+ if (excluded.indexOf(key) >= 0) continue;
496
+ if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
497
+ target[key] = source[key];
498
+ }
499
+ }
500
+ return target;
501
+ }
502
+ function _objectWithoutPropertiesLoose(source, excluded) {
503
+ if (source == null) return {};
504
+ var target = {};
505
+ for (var key in source) {
506
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
507
+ if (excluded.indexOf(key) >= 0) continue;
508
+ target[key] = source[key];
509
+ }
510
+ }
511
+ return target;
512
+ }
513
+ function _extends() {
514
+ _extends = Object.assign ? Object.assign.bind() : function(target) {
515
+ for (var i = 1; i < arguments.length; i++) {
516
+ var source = arguments[i];
517
+ for (var key in source) {
518
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
519
+ target[key] = source[key];
520
+ }
521
+ }
522
+ }
523
+ return target;
524
+ };
525
+ return _extends.apply(this, arguments);
526
+ }
527
+ function ownKeys(e, r) {
528
+ var t = Object.keys(e);
529
+ if (Object.getOwnPropertySymbols) {
530
+ var o = Object.getOwnPropertySymbols(e);
531
+ r && (o = o.filter(function(r2) {
532
+ return Object.getOwnPropertyDescriptor(e, r2).enumerable;
533
+ })), t.push.apply(t, o);
534
+ }
535
+ return t;
536
+ }
537
+ function _objectSpread(e) {
538
+ for (var r = 1; r < arguments.length; r++) {
539
+ var t = null != arguments[r] ? arguments[r] : {};
540
+ r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
541
+ _defineProperty(e, r2, t[r2]);
542
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
543
+ Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
544
+ });
545
+ }
546
+ return e;
547
+ }
548
+ function _defineProperty(obj, key, value) {
549
+ key = _toPropertyKey(key);
550
+ if (key in obj) {
551
+ Object.defineProperty(obj, key, { value, enumerable: true, configurable: true, writable: true });
552
+ } else {
553
+ obj[key] = value;
554
+ }
555
+ return obj;
556
+ }
557
+ function _toPropertyKey(t) {
558
+ var i = _toPrimitive(t, "string");
559
+ return "symbol" == typeof i ? i : i + "";
560
+ }
561
+ function _toPrimitive(t, r) {
562
+ if ("object" != typeof t || !t) return t;
563
+ var e = t[Symbol.toPrimitive];
564
+ if (void 0 !== e) {
565
+ var i = e.call(t, r || "default");
566
+ if ("object" != typeof i) return i;
567
+ throw new TypeError("@@toPrimitive must return a primitive value.");
568
+ }
569
+ return ("string" === r ? String : Number)(t);
570
+ }
571
+ function Tree2Element(tree) {
572
+ return tree && tree.map((node, i) => /* @__PURE__ */ import_react5.default.createElement(node.tag, _objectSpread({
573
+ key: i
574
+ }, node.attr), Tree2Element(node.child)));
575
+ }
576
+ function GenIcon(data) {
577
+ return (props) => /* @__PURE__ */ import_react5.default.createElement(IconBase, _extends({
578
+ attr: _objectSpread({}, data.attr)
579
+ }, props), Tree2Element(data.child));
580
+ }
581
+ function IconBase(props) {
582
+ var elem = (conf) => {
583
+ var {
584
+ attr,
585
+ size,
586
+ title
587
+ } = props, svgProps = _objectWithoutProperties(props, _excluded);
588
+ var computedSize = size || conf.size || "1em";
589
+ var className;
590
+ if (conf.className) className = conf.className;
591
+ if (props.className) className = (className ? className + " " : "") + props.className;
592
+ return /* @__PURE__ */ import_react5.default.createElement("svg", _extends({
593
+ stroke: "currentColor",
594
+ fill: "currentColor",
595
+ strokeWidth: "0"
596
+ }, conf.attr, attr, svgProps, {
597
+ className,
598
+ style: _objectSpread(_objectSpread({
599
+ color: props.color || conf.color
600
+ }, conf.style), props.style),
601
+ height: computedSize,
602
+ width: computedSize,
603
+ xmlns: "http://www.w3.org/2000/svg"
604
+ }), title && /* @__PURE__ */ import_react5.default.createElement("title", null, title), props.children);
605
+ };
606
+ return IconContext !== void 0 ? /* @__PURE__ */ import_react5.default.createElement(IconContext.Consumer, null, (conf) => elem(conf)) : elem(DefaultContext);
607
+ }
608
+
609
+ // node_modules/react-icons/go/index.mjs
610
+ function GoArrowDown(props) {
611
+ 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);
612
+ }
613
+ function GoArrowUp(props) {
614
+ 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);
615
+ }
616
+ function GoSearch(props) {
617
+ 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);
618
+ }
619
+
620
+ // src/table/buttons.tsx
621
+ var import_utils = require("dn-react-toolkit/utils");
622
+ var import_react_router4 = require("react-router");
623
+ var import_react6 = __toESM(require("react"));
624
+ function TablePageButtons({
625
+ MAX_PAGES_TO_SHOW,
626
+ total,
627
+ limit,
628
+ offset
629
+ }) {
630
+ const pages = Math.ceil(total / limit);
631
+ const { pathname } = (0, import_react_router4.useLocation)();
632
+ const [searchParams] = (0, import_react_router4.useSearchParams)();
633
+ const currentPage = Math.floor(offset / limit) + 1;
634
+ const startButton = (Math.ceil(currentPage / MAX_PAGES_TO_SHOW) - 1) * MAX_PAGES_TO_SHOW;
635
+ const endButton = Math.min(startButton + MAX_PAGES_TO_SHOW - 1, pages);
636
+ return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, pages > 1 && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex justify-center items-center my-8 gap-4 text-neutral-400" }, startButton > 1 && /* @__PURE__ */ import_react6.default.createElement(
637
+ import_react_router4.Link,
638
+ {
639
+ to: (() => {
640
+ searchParams.set(
641
+ "offset",
642
+ String((startButton - 1) * limit)
643
+ );
644
+ return `${pathname}?${searchParams.toString()}`;
645
+ })(),
646
+ className: "w-10 block text-center transition-colors hover:text-primary"
647
+ },
648
+ "\uC774\uC804"
649
+ ), Array.from({
650
+ length: Math.min(
651
+ MAX_PAGES_TO_SHOW,
652
+ pages - startButton
653
+ )
654
+ }).map((_, index2) => {
655
+ return /* @__PURE__ */ import_react6.default.createElement(
656
+ import_react_router4.Link,
657
+ {
658
+ key: index2,
659
+ to: (() => {
660
+ searchParams.set(
661
+ "offset",
662
+ String((startButton + index2) * limit)
663
+ );
664
+ return `${pathname}?${searchParams.toString()}`;
665
+ })(),
666
+ className: (0, import_utils.cn)(
667
+ "w-6 block text-center transition-colors",
668
+ currentPage === startButton + index2 + 1 ? "font-bold text-primary" : "hover:text-primary"
669
+ )
670
+ },
671
+ startButton + index2 + 1
672
+ );
673
+ }), endButton < pages && /* @__PURE__ */ import_react6.default.createElement(
674
+ import_react_router4.Link,
675
+ {
676
+ to: (() => {
677
+ searchParams.set(
678
+ "offset",
679
+ String((endButton + 1) * limit)
680
+ );
681
+ return `${pathname}?${searchParams.toString()}`;
682
+ })(),
683
+ className: "w-10 block text-center transition-colors hover:text-primary"
684
+ },
685
+ "\uB2E4\uC74C"
686
+ )));
687
+ }
688
+
689
+ // src/table/table.tsx
690
+ var import_utils2 = require("dn-react-toolkit/utils");
691
+ var import_react_router5 = require("react-router");
692
+ var import_react7 = __toESM(require("react"));
693
+ function Table({
694
+ className = "min-w-full whitespace-nowrap",
695
+ data,
696
+ columns,
697
+ mapper: Mapper,
698
+ getLink,
699
+ limit,
700
+ offset,
701
+ orderBy,
702
+ direction
703
+ }) {
704
+ const keys = Object.entries(columns).filter((entry) => entry[1]).map(([key]) => key);
705
+ const sortedArray = [...data];
706
+ const [_, setSearchParams] = (0, import_react_router5.useSearchParams)();
707
+ return /* @__PURE__ */ import_react7.default.createElement(
708
+ "table",
709
+ {
710
+ className: (0, import_utils2.cn)(
711
+ className,
712
+ "text-[15px] border-separate border-spacing-0"
713
+ )
714
+ },
715
+ /* @__PURE__ */ import_react7.default.createElement("thead", null, /* @__PURE__ */ import_react7.default.createElement("tr", null, keys.map((key) => {
716
+ const value = columns[key];
717
+ function getReactNode() {
718
+ if (value && typeof value === "object" && "label" in value) {
719
+ return value.label;
720
+ }
721
+ return value;
722
+ }
723
+ function Head() {
724
+ const reactNode = getReactNode();
725
+ if (typeof reactNode === "string") {
726
+ return /* @__PURE__ */ import_react7.default.createElement(
727
+ "button",
728
+ {
729
+ className: (0, import_utils2.cn)(
730
+ orderBy === key ? "text-neutral-900 font-medium" : "text-neutral-500",
731
+ "px-4 h-14 flex items-center w-full"
732
+ ),
733
+ onClick: () => {
734
+ let newDirection = "asc";
735
+ if (orderBy === key) {
736
+ newDirection = direction === "asc" ? "desc" : "asc";
737
+ }
738
+ setSearchParams({
739
+ orderBy: key,
740
+ direction: newDirection
741
+ });
742
+ }
743
+ },
744
+ reactNode,
745
+ orderBy === key && /* @__PURE__ */ import_react7.default.createElement("div", { className: "ml-0.5" }, direction === "asc" ? /* @__PURE__ */ import_react7.default.createElement(GoArrowUp, null) : /* @__PURE__ */ import_react7.default.createElement(GoArrowDown, null))
746
+ );
747
+ }
748
+ return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, reactNode);
749
+ }
750
+ return /* @__PURE__ */ import_react7.default.createElement(
751
+ "th",
752
+ {
753
+ key,
754
+ className: (0, import_utils2.cn)("border-y font-normal")
755
+ },
756
+ /* @__PURE__ */ import_react7.default.createElement(Head, null)
757
+ );
758
+ }))),
759
+ /* @__PURE__ */ import_react7.default.createElement("tbody", null, sortedArray.length === 0 && /* @__PURE__ */ import_react7.default.createElement("tr", null, /* @__PURE__ */ import_react7.default.createElement(
760
+ "td",
761
+ {
762
+ colSpan: keys.length,
763
+ className: "px-4 h-14 text-neutral-400 text-center"
764
+ },
765
+ "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
766
+ )), sortedArray.map((item, i) => /* @__PURE__ */ import_react7.default.createElement("tr", { key: i, className: "hover:bg-gray-50 transition-colors" }, keys.map((key, i2) => {
767
+ const value = item[key];
768
+ function Content() {
769
+ if (key in columns) {
770
+ const column = columns[key];
771
+ if (column && typeof column === "object" && "mapper" in column) {
772
+ const mapper = column.mapper;
773
+ if (mapper) {
774
+ return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, mapper(item));
775
+ }
776
+ }
777
+ }
778
+ return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, String(value));
779
+ }
780
+ const linkedContent = getLink ? /* @__PURE__ */ import_react7.default.createElement(
781
+ import_react_router5.Link,
782
+ {
783
+ to: getLink(item),
784
+ className: "block content-center px-4 w-full h-full"
785
+ },
786
+ /* @__PURE__ */ import_react7.default.createElement(Content, null)
787
+ ) : /* @__PURE__ */ import_react7.default.createElement(Content, null);
788
+ const cell = Mapper ? /* @__PURE__ */ import_react7.default.createElement(Mapper, { item, index: i2 }, linkedContent) : linkedContent;
789
+ return /* @__PURE__ */ import_react7.default.createElement("td", { key, className: "px-0 h-14 border-b" }, cell);
790
+ }))))
791
+ );
792
+ }
793
+
794
+ // src/table/page.tsx
795
+ var import_react8 = __toESM(require("react"));
796
+ function createTablePage({
797
+ name,
798
+ columns,
799
+ primaryKey = "id"
800
+ }) {
801
+ return function TablePage({
802
+ AdminLayout
803
+ }) {
804
+ const { pathname } = (0, import_react_router6.useLocation)();
805
+ const { table } = (0, import_react_router6.useLoaderData)();
806
+ const { items, total, limit, offset, orderBy, direction, searchKey } = table;
807
+ const navigate = (0, import_react_router6.useNavigate)();
808
+ const search = (query) => {
809
+ const searchParams2 = new URLSearchParams(window.location.search);
810
+ searchParams2.set("query", query);
811
+ searchParams2.set("offset", "0");
812
+ navigate(`${pathname}?${searchParams2.toString()}`);
813
+ };
814
+ const [searchParams] = (0, import_react_router6.useSearchParams)();
815
+ return /* @__PURE__ */ import_react8.default.createElement(
816
+ AdminLayout,
817
+ {
818
+ title: name,
819
+ actions: /* @__PURE__ */ import_react8.default.createElement(import_react_router6.Link, { to: `${pathname}/new`, className: "button-primary" }, name, " \uCD94\uAC00")
820
+ },
821
+ searchKey && /* @__PURE__ */ import_react8.default.createElement(
822
+ "form",
823
+ {
824
+ className: "h-18 px-4 flex items-center border-t",
825
+ onSubmit: (e) => {
826
+ e.preventDefault();
827
+ const formData = new FormData(e.currentTarget);
828
+ const query = formData.get("query");
829
+ search(query);
830
+ }
831
+ },
832
+ /* @__PURE__ */ import_react8.default.createElement(
833
+ "button",
834
+ {
835
+ type: "submit",
836
+ className: "w-10 h-10 flex justify-center items-center"
837
+ },
838
+ /* @__PURE__ */ import_react8.default.createElement(GoSearch, { className: "text-xl mr-4" })
839
+ ),
840
+ /* @__PURE__ */ import_react8.default.createElement(
841
+ "input",
842
+ {
843
+ className: "outline-none h-full flex-1",
844
+ placeholder: "\uC5EC\uAE30\uC5D0 \uAC80\uC0C9\uD558\uC138\uC694...",
845
+ name: "query",
846
+ defaultValue: searchParams.get("query") ?? ""
847
+ }
848
+ )
849
+ ),
850
+ /* @__PURE__ */ import_react8.default.createElement(
851
+ Table,
852
+ {
853
+ data: items,
854
+ columns,
855
+ getLink: primaryKey ? (item) => `${pathname}/${item[primaryKey]}` : void 0,
856
+ limit,
857
+ offset,
858
+ orderBy,
859
+ direction
860
+ }
861
+ ),
862
+ /* @__PURE__ */ import_react8.default.createElement(
863
+ TablePageButtons,
864
+ {
865
+ total,
866
+ limit,
867
+ offset,
868
+ MAX_PAGES_TO_SHOW: 10
869
+ }
870
+ )
871
+ );
872
+ };
873
+ }
874
+
875
+ // src/crud/crud_page.tsx
876
+ var import_react9 = __toESM(require("react"));
877
+ function crudPage({
878
+ name,
879
+ tablePageOptions,
880
+ formOptions,
881
+ AdminLayout
882
+ }) {
883
+ return (prefix2) => {
884
+ return function Page() {
885
+ const data = (0, import_react_router7.useLoaderData)();
886
+ const { pathname } = (0, import_react_router7.useLocation)();
887
+ if (pathname === prefix2) {
888
+ const Component = createTablePage({
889
+ ...tablePageOptions,
890
+ name
891
+ });
892
+ return /* @__PURE__ */ import_react9.default.createElement(Component, { AdminLayout });
893
+ }
894
+ if (pathname.startsWith(prefix2)) {
895
+ return /* @__PURE__ */ import_react9.default.createElement(
896
+ CrudFormProvider,
897
+ {
898
+ item: data?.item,
899
+ prefix: prefix2,
900
+ name,
901
+ columns: formOptions.columns
902
+ },
903
+ formOptions.form ? /* @__PURE__ */ import_react9.default.createElement(formOptions.form, null) : /* @__PURE__ */ import_react9.default.createElement(CrudForm, { AdminLayout })
904
+ );
905
+ }
906
+ };
907
+ };
908
+ }
909
+
910
+ // src/crud/generate_handlers.ts
911
+ var generateHandlers = (handlers) => {
912
+ return async (args) => {
913
+ const pattern = args.unstable_pattern;
914
+ for (const route2 of Object.keys(handlers)) {
915
+ if (pattern.startsWith(route2) || pattern.startsWith(`/api${route2}`)) {
916
+ return handlers[route2](route2)(args);
917
+ }
918
+ }
919
+ };
920
+ };
921
+
922
+ // src/crud/generate_pages.tsx
923
+ var import_react_router8 = require("react-router");
924
+ var import_react10 = __toESM(require("react"));
925
+ var generatePages = (pages) => {
926
+ return function Page() {
927
+ const { pathname } = (0, import_react_router8.useLocation)();
928
+ for (const route2 of Object.keys(pages)) {
929
+ if (pathname.startsWith(route2)) {
930
+ const Page2 = pages[route2](route2);
931
+ return /* @__PURE__ */ import_react10.default.createElement(Page2, null);
932
+ }
933
+ }
934
+ };
935
+ };
936
+
937
+ // src/crud/generate_routes.tsx
938
+ var Routes = __toESM(require("@react-router/dev/routes"));
939
+ function generateCrudRoutes(routes, apiFile, file) {
940
+ return routes.flatMap((prefix2) => {
941
+ return [
942
+ ...Routes.prefix(`/api${prefix2}`, [
943
+ Routes.index(apiFile, {
944
+ id: `api_${prefix2}_list`
945
+ }),
946
+ Routes.route(`:itemId`, apiFile, {
947
+ id: `api_${prefix2}_item`
948
+ })
949
+ ]),
950
+ ...Routes.prefix(prefix2, [
951
+ Routes.index(file, {
952
+ id: `${prefix2}_list`
953
+ }),
954
+ Routes.route(`:itemId`, file, {
955
+ id: `${prefix2}_item`
956
+ })
957
+ ])
958
+ ];
959
+ });
960
+ }
961
+ // Annotate the CommonJS export names for ESM import in node:
962
+ 0 && (module.exports = {
963
+ FormContext,
964
+ crudHandler,
965
+ crudPage,
966
+ generateCrudRoutes,
967
+ generateHandlers,
968
+ generatePages,
969
+ useFormContext
970
+ });