dn-react-router-toolkit 0.7.15 → 0.8.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 (67) hide show
  1. package/dist/api/create_api_handler.d.mts +5 -4
  2. package/dist/api/create_api_handler.d.ts +5 -4
  3. package/dist/api/create_api_handler.js +0 -1
  4. package/dist/api/create_api_handler.mjs +0 -1
  5. package/dist/api/index.d.mts +1 -0
  6. package/dist/api/index.d.ts +1 -0
  7. package/dist/api/index.js +13 -6
  8. package/dist/api/index.mjs +14 -7
  9. package/dist/api/item_api_handler.d.mts +8 -5
  10. package/dist/api/item_api_handler.d.ts +8 -5
  11. package/dist/api/item_api_handler.js +13 -5
  12. package/dist/api/item_api_handler.mjs +14 -6
  13. package/dist/crud/crud_loader.d.mts +6 -5
  14. package/dist/crud/crud_loader.d.ts +6 -5
  15. package/dist/crud/crud_loader.js +79 -38
  16. package/dist/crud/crud_loader.mjs +81 -39
  17. package/dist/crud/crud_page.d.mts +3 -2
  18. package/dist/crud/crud_page.d.ts +3 -2
  19. package/dist/crud/crud_page.js +279 -201
  20. package/dist/crud/crud_page.mjs +277 -205
  21. package/dist/crud/generate_handlers.d.mts +3 -2
  22. package/dist/crud/generate_handlers.d.ts +3 -2
  23. package/dist/crud/generate_pages.d.mts +2 -1
  24. package/dist/crud/generate_pages.d.ts +2 -1
  25. package/dist/crud/index.d.mts +5 -3
  26. package/dist/crud/index.d.ts +5 -3
  27. package/dist/crud/index.js +338 -219
  28. package/dist/crud/index.mjs +346 -232
  29. package/dist/post/index.js +71 -64
  30. package/dist/post/index.mjs +76 -74
  31. package/dist/post/post_form_page.js +71 -64
  32. package/dist/post/post_form_page.mjs +76 -74
  33. package/dist/table/index.d.mts +7 -3
  34. package/dist/table/index.d.ts +7 -3
  35. package/dist/table/index.js +233 -111
  36. package/dist/table/index.mjs +230 -116
  37. package/dist/table/item_loader.d.mts +5 -4
  38. package/dist/table/item_loader.d.ts +5 -4
  39. package/dist/table/load_table.d.mts +36 -0
  40. package/dist/table/load_table.d.ts +36 -0
  41. package/dist/table/load_table.js +87 -0
  42. package/dist/table/load_table.mjs +66 -0
  43. package/dist/table/loader.d.mts +10 -15
  44. package/dist/table/loader.d.ts +10 -15
  45. package/dist/table/loader.js +67 -31
  46. package/dist/table/loader.mjs +67 -32
  47. package/dist/table/page.d.mts +6 -16
  48. package/dist/table/page.d.ts +6 -16
  49. package/dist/table/page.js +247 -169
  50. package/dist/table/page.mjs +248 -176
  51. package/dist/table/repository.d.mts +14 -10
  52. package/dist/table/repository.d.ts +14 -10
  53. package/dist/table/repository.js +5 -1
  54. package/dist/table/repository.mjs +5 -1
  55. package/dist/table/table.d.mts +4 -1
  56. package/dist/table/table.d.ts +4 -1
  57. package/dist/table/table.js +55 -6
  58. package/dist/table/table.mjs +55 -6
  59. package/dist/table/table_form.d.mts +13 -0
  60. package/dist/table/table_form.d.ts +13 -0
  61. package/dist/table/table_form.js +345 -0
  62. package/dist/table/table_form.mjs +320 -0
  63. package/dist/table/use_table.d.mts +4 -0
  64. package/dist/table/use_table.d.ts +4 -0
  65. package/dist/table/use_table.js +34 -0
  66. package/dist/table/use_table.mjs +9 -0
  67. package/package.json +2 -2
@@ -1,10 +1,14 @@
1
- export { BaseTableRepository, ColumnOf, FindAllOptions, InsertModelOf, SelectModelOf, TableRepository } from './repository.js';
1
+ export { BaseTableRepository, ColumnOf, FindAllOptions, InsertModelOf, SchemaOf, SelectModelOf, TableRepository } from './repository.js';
2
2
  export { TablePageButtons } from './buttons.js';
3
3
  export { TableItemLoaderOptions, tableItemloader } from './item_loader.js';
4
- export { TableLoaderOptions, tableLoader } from './loader.js';
5
- export { TablePageOptions, TableProps, createTablePage } from './page.js';
4
+ export { tableLoader } from './loader.js';
5
+ export { createTablePage } from './page.js';
6
6
  export { OrderedTableProps, Table, TableColumnOptions, TableColumnProps } from './table.js';
7
+ export { TableLoaderOptions, loadTable } from './load_table.js';
8
+ export { LoadedModel, TableForm, TablePageOptions } from './table_form.js';
9
+ export { TableLoaderData, useTable } from './use_table.js';
7
10
  import 'drizzle-orm';
11
+ import 'drizzle-orm/node-postgres';
8
12
  import 'drizzle-orm/pg-core';
9
13
  import 'react/jsx-runtime';
10
14
  import 'react-router';
@@ -22,10 +22,13 @@ var table_exports = {};
22
22
  __export(table_exports, {
23
23
  BaseTableRepository: () => BaseTableRepository,
24
24
  Table: () => Table,
25
+ TableForm: () => TableForm,
25
26
  TablePageButtons: () => TablePageButtons,
26
27
  createTablePage: () => createTablePage,
28
+ loadTable: () => loadTable,
27
29
  tableItemloader: () => tableItemloader,
28
- tableLoader: () => tableLoader
30
+ tableLoader: () => tableLoader,
31
+ useTable: () => useTable
29
32
  });
30
33
  module.exports = __toCommonJS(table_exports);
31
34
 
@@ -37,7 +40,7 @@ var BaseTableRepository = class {
37
40
  pk;
38
41
  constructor(db, schema, pk = "id") {
39
42
  this.db = db;
40
- this.schema = schema;
43
+ this.schema = db._.fullSchema[schema];
41
44
  this.pk = pk;
42
45
  }
43
46
  async find(id) {
@@ -76,6 +79,10 @@ var BaseTableRepository = class {
76
79
  async delete(pk) {
77
80
  await this.db.delete(this.schema).where((0, import_drizzle_orm.eq)(this.schema[this.pk], pk));
78
81
  }
82
+ async select(key) {
83
+ const rows = await this.db.select({ value: this.schema[key] }).from(this.schema).groupBy(this.schema[key]);
84
+ return rows.map((row) => row.value);
85
+ }
79
86
  };
80
87
 
81
88
  // src/table/buttons.tsx
@@ -167,51 +174,88 @@ var tableItemloader = ({
167
174
  };
168
175
  };
169
176
 
170
- // src/table/loader.tsx
177
+ // src/table/load_table.tsx
171
178
  var import_drizzle_orm2 = require("drizzle-orm");
179
+ async function loadTable({
180
+ request,
181
+ repository,
182
+ options
183
+ }) {
184
+ const searchParams = new URL(request.url).searchParams;
185
+ const { where, searchKey, defaultOrderBy, defaultDirection } = options;
186
+ const query = searchParams.get("query") ?? void 0;
187
+ const limit = Number(searchParams.get("limit") ?? "20");
188
+ const offset = Number(searchParams.get("offset") ?? "0");
189
+ const orderBy = searchParams.get("orderBy") ?? defaultOrderBy;
190
+ const direction = searchParams.get("direction") ?? defaultDirection;
191
+ const filterWhere = Object.entries(options.filters ?? {}).map(([key, value]) => {
192
+ const param = searchParams.get(key);
193
+ if (param) {
194
+ return (0, import_drizzle_orm2.eq)(
195
+ repository.schema[key],
196
+ decodeURIComponent(param)
197
+ );
198
+ }
199
+ return void 0;
200
+ }).filter(Boolean);
201
+ const whereClauses = (0, import_drizzle_orm2.and)(
202
+ searchKey && query ? (0, import_drizzle_orm2.ilike)(
203
+ repository.schema[searchKey],
204
+ `%${query}%`
205
+ ) : void 0,
206
+ ...filterWhere,
207
+ ...where ?? []
208
+ );
209
+ const total = await repository.countTotal({ where: whereClauses });
210
+ const items = await repository.findAll({
211
+ orderBy,
212
+ direction,
213
+ limit,
214
+ offset,
215
+ where: whereClauses
216
+ });
217
+ const filters = Object.fromEntries(
218
+ await Promise.all(
219
+ Object.keys(options.filters ?? {}).map(async (key) => {
220
+ const values = await repository.select(key);
221
+ return [key, values.filter(Boolean)];
222
+ })
223
+ )
224
+ );
225
+ return {
226
+ items,
227
+ total,
228
+ limit,
229
+ offset,
230
+ orderBy,
231
+ direction,
232
+ searchKey,
233
+ filters
234
+ };
235
+ }
236
+
237
+ // src/table/loader.tsx
172
238
  function tableLoader({
173
239
  repository,
174
- tableOptions
240
+ options
175
241
  }) {
176
242
  return async ({ request }) => {
177
- const searchParams = new URL(request.url).searchParams;
178
- const { where, searchKey, defaultOrderBy, defaultDirection } = tableOptions;
179
- const query = searchParams.get("query") ?? void 0;
180
- const limit = Number(searchParams.get("limit") ?? "10");
181
- const offset = Number(searchParams.get("offset") ?? "0");
182
- const orderBy = searchParams.get("orderBy") ?? defaultOrderBy;
183
- const direction = searchParams.get("direction") ?? defaultDirection;
184
- const whereClauses = (0, import_drizzle_orm2.and)(
185
- searchKey && query ? (0, import_drizzle_orm2.ilike)(
186
- repository.schema[searchKey],
187
- `%${query}%`
188
- ) : void 0,
189
- ...where ?? []
190
- );
191
- const total = await repository.countTotal({ where: whereClauses });
192
- const items = await repository.findAll({
193
- orderBy,
194
- direction,
195
- limit,
196
- offset,
197
- where: whereClauses
243
+ const table = await loadTable({
244
+ request,
245
+ repository,
246
+ options
198
247
  });
199
248
  return {
200
- table: {
201
- items,
202
- total,
203
- limit,
204
- offset,
205
- orderBy,
206
- direction,
207
- searchKey
208
- }
249
+ table
209
250
  };
210
251
  };
211
252
  }
212
253
 
213
254
  // src/table/page.tsx
214
- var import_react_router3 = require("react-router");
255
+ var import_react_router5 = require("react-router");
256
+
257
+ // src/table/table_form.tsx
258
+ var import_react_router4 = require("react-router");
215
259
  var import_go2 = require("react-icons/go");
216
260
 
217
261
  // src/table/table.tsx
@@ -228,7 +272,8 @@ function Table({
228
272
  limit,
229
273
  offset,
230
274
  orderBy,
231
- direction
275
+ direction,
276
+ filters
232
277
  }) {
233
278
  const keys = Object.entries(columns).filter((entry) => entry[1]).map(([key]) => key);
234
279
  const sortedArray = [...data];
@@ -236,7 +281,10 @@ function Table({
236
281
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
237
282
  "table",
238
283
  {
239
- className: (0, import_utils2.cn)(className, "text-[15px] border-separate border-spacing-0"),
284
+ className: (0, import_utils2.cn)(
285
+ className,
286
+ "text-[15px] border-separate border-spacing-0"
287
+ ),
240
288
  children: [
241
289
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: keys.map((key) => {
242
290
  const value = columns[key];
@@ -253,8 +301,8 @@ function Table({
253
301
  "button",
254
302
  {
255
303
  className: (0, import_utils2.cn)(
256
- orderBy === key ? "text-neutral-900 font-medium" : "text-neutral-500",
257
- "px-4 h-14 flex items-center w-full"
304
+ orderBy === key ? "text-gray-900 font-medium" : "text-gray-500 font-medium",
305
+ "px-4 flex items-center w-full"
258
306
  ),
259
307
  onClick: () => {
260
308
  let newDirection = "asc";
@@ -275,14 +323,59 @@ function Table({
275
323
  }
276
324
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: reactNode });
277
325
  }
278
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { className: (0, import_utils2.cn)("border-y font-normal"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Head, {}) }, key);
326
+ const filter = filters[key];
327
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
328
+ "th",
329
+ {
330
+ className: (0, import_utils2.cn)(
331
+ "py-4 border-y font-normal align-top"
332
+ ),
333
+ children: [
334
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Head, {}),
335
+ filter && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "px-3 mt-4", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
336
+ "select",
337
+ {
338
+ className: "w-full h-10 px-1.5 border rounded-full outline-none",
339
+ onChange: (e) => {
340
+ const value2 = e.target.value;
341
+ setSearchParams((prev) => {
342
+ if (value2) {
343
+ prev.set(
344
+ key,
345
+ encodeURIComponent(
346
+ value2
347
+ )
348
+ );
349
+ } else {
350
+ prev.delete(key);
351
+ }
352
+ return prev;
353
+ });
354
+ },
355
+ children: [
356
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "", children: "\uC804\uCCB4" }),
357
+ filter.map((option) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
358
+ "option",
359
+ {
360
+ value: option,
361
+ children: option
362
+ },
363
+ option
364
+ ))
365
+ ]
366
+ }
367
+ ) })
368
+ ]
369
+ },
370
+ key
371
+ );
279
372
  }) }) }),
280
373
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("tbody", { children: [
281
374
  sortedArray.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
282
375
  "td",
283
376
  {
284
377
  colSpan: keys.length,
285
- className: "px-4 h-14 text-neutral-400 text-center",
378
+ className: "px-4 h-20 text-gray-400 text-center",
286
379
  children: "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
287
380
  }
288
381
  ) }),
@@ -317,8 +410,97 @@ function Table({
317
410
  );
318
411
  }
319
412
 
320
- // src/table/page.tsx
413
+ // src/table/use_table.tsx
414
+ var import_react_router3 = require("react-router");
415
+ function useTable() {
416
+ const { table } = (0, import_react_router3.useLoaderData)();
417
+ return table;
418
+ }
419
+
420
+ // src/table/table_form.tsx
321
421
  var import_jsx_runtime3 = require("react/jsx-runtime");
422
+ function TableForm({
423
+ columns,
424
+ primaryKey = "id"
425
+ }) {
426
+ const { pathname } = (0, import_react_router4.useLocation)();
427
+ const {
428
+ items,
429
+ total,
430
+ limit,
431
+ offset,
432
+ orderBy,
433
+ direction,
434
+ searchKey,
435
+ filters
436
+ } = useTable();
437
+ const navigate = (0, import_react_router4.useNavigate)();
438
+ const search = (query) => {
439
+ const searchParams2 = new URLSearchParams(window.location.search);
440
+ searchParams2.set("query", query);
441
+ searchParams2.set("offset", "0");
442
+ navigate(`${pathname}?${searchParams2.toString()}`);
443
+ };
444
+ const [searchParams] = (0, import_react_router4.useSearchParams)();
445
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
446
+ searchKey && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
447
+ "form",
448
+ {
449
+ className: "h-20 px-4 flex items-center border-t",
450
+ onSubmit: (e) => {
451
+ e.preventDefault();
452
+ const formData = new FormData(e.currentTarget);
453
+ const query = formData.get("query");
454
+ search(query);
455
+ },
456
+ children: [
457
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
458
+ "button",
459
+ {
460
+ type: "submit",
461
+ className: "w-10 h-10 flex justify-center items-center",
462
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_go2.GoSearch, { className: "text-xl mr-4" })
463
+ }
464
+ ),
465
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
466
+ "input",
467
+ {
468
+ className: "outline-none h-full flex-1",
469
+ placeholder: "\uC5EC\uAE30\uC5D0 \uAC80\uC0C9\uD558\uC138\uC694...",
470
+ name: "query",
471
+ defaultValue: searchParams.get("query") ?? ""
472
+ }
473
+ )
474
+ ]
475
+ }
476
+ ),
477
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
478
+ Table,
479
+ {
480
+ data: items,
481
+ columns,
482
+ getLink: primaryKey ? (item) => `${pathname}/${item[primaryKey]}` : void 0,
483
+ limit,
484
+ offset,
485
+ orderBy,
486
+ direction,
487
+ filters
488
+ }
489
+ ),
490
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
491
+ TablePageButtons,
492
+ {
493
+ total,
494
+ limit,
495
+ offset,
496
+ MAX_PAGES_TO_SHOW: 10
497
+ }
498
+ )
499
+ ] });
500
+ }
501
+
502
+ // src/table/page.tsx
503
+ var import_jsx_runtime4 = require("react/jsx-runtime");
322
504
  function createTablePage({
323
505
  name,
324
506
  columns,
@@ -327,82 +509,19 @@ function createTablePage({
327
509
  return function TablePage({
328
510
  header: Header
329
511
  }) {
330
- const { pathname } = (0, import_react_router3.useLocation)();
331
- const { table } = (0, import_react_router3.useLoaderData)();
332
- const { items, total, limit, offset, orderBy, direction, searchKey } = table;
333
- const navigate = (0, import_react_router3.useNavigate)();
334
- const search = (query) => {
335
- const searchParams2 = new URLSearchParams(window.location.search);
336
- searchParams2.set("query", query);
337
- searchParams2.set("offset", "0");
338
- navigate(`${pathname}?${searchParams2.toString()}`);
339
- };
340
- const [searchParams] = (0, import_react_router3.useSearchParams)();
341
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
342
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
512
+ const { pathname } = (0, import_react_router5.useLocation)();
513
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
514
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
343
515
  Header,
344
516
  {
345
517
  title: name,
346
- actions: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_router3.Link, { to: `${pathname}/new`, className: "button-primary", children: [
518
+ actions: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_react_router5.Link, { to: `${pathname}/new`, className: "button-primary", children: [
347
519
  name,
348
520
  " \uCD94\uAC00"
349
521
  ] })
350
522
  }
351
523
  ),
352
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "max-w-7xl mx-auto w-full overflow-auto", children: [
353
- searchKey && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
354
- "form",
355
- {
356
- className: "h-18 px-4 flex items-center border-t",
357
- onSubmit: (e) => {
358
- e.preventDefault();
359
- const formData = new FormData(e.currentTarget);
360
- const query = formData.get("query");
361
- search(query);
362
- },
363
- children: [
364
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
365
- "button",
366
- {
367
- type: "submit",
368
- className: "w-10 h-10 flex justify-center items-center",
369
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_go2.GoSearch, { className: "text-xl mr-4" })
370
- }
371
- ),
372
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
373
- "input",
374
- {
375
- className: "outline-none h-full flex-1",
376
- placeholder: "\uC5EC\uAE30\uC5D0 \uAC80\uC0C9\uD558\uC138\uC694...",
377
- name: "query",
378
- defaultValue: searchParams.get("query") ?? ""
379
- }
380
- )
381
- ]
382
- }
383
- ),
384
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
385
- Table,
386
- {
387
- data: items,
388
- columns,
389
- getLink: primaryKey ? (item) => `${pathname}/${item[primaryKey]}` : void 0,
390
- limit,
391
- offset,
392
- orderBy,
393
- direction
394
- }
395
- ),
396
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
397
- TablePageButtons,
398
- {
399
- total,
400
- limit,
401
- offset,
402
- MAX_PAGES_TO_SHOW: 10
403
- }
404
- )
405
- ] })
524
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "max-w-7xl mx-auto w-full overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TableForm, { columns, primaryKey }) })
406
525
  ] });
407
526
  };
408
527
  }
@@ -410,8 +529,11 @@ function createTablePage({
410
529
  0 && (module.exports = {
411
530
  BaseTableRepository,
412
531
  Table,
532
+ TableForm,
413
533
  TablePageButtons,
414
534
  createTablePage,
535
+ loadTable,
415
536
  tableItemloader,
416
- tableLoader
537
+ tableLoader,
538
+ useTable
417
539
  });