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.
- package/dist/api/create_api_handler.d.mts +5 -4
- package/dist/api/create_api_handler.d.ts +5 -4
- package/dist/api/create_api_handler.js +0 -1
- package/dist/api/create_api_handler.mjs +0 -1
- package/dist/api/index.d.mts +1 -0
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +13 -6
- package/dist/api/index.mjs +14 -7
- package/dist/api/item_api_handler.d.mts +8 -5
- package/dist/api/item_api_handler.d.ts +8 -5
- package/dist/api/item_api_handler.js +13 -5
- package/dist/api/item_api_handler.mjs +14 -6
- package/dist/crud/crud_loader.d.mts +6 -5
- package/dist/crud/crud_loader.d.ts +6 -5
- package/dist/crud/crud_loader.js +79 -38
- package/dist/crud/crud_loader.mjs +81 -39
- package/dist/crud/crud_page.d.mts +3 -2
- package/dist/crud/crud_page.d.ts +3 -2
- package/dist/crud/crud_page.js +279 -201
- package/dist/crud/crud_page.mjs +277 -205
- package/dist/crud/generate_handlers.d.mts +3 -2
- package/dist/crud/generate_handlers.d.ts +3 -2
- package/dist/crud/generate_pages.d.mts +2 -1
- package/dist/crud/generate_pages.d.ts +2 -1
- package/dist/crud/index.d.mts +5 -3
- package/dist/crud/index.d.ts +5 -3
- package/dist/crud/index.js +338 -219
- package/dist/crud/index.mjs +346 -232
- package/dist/post/index.js +71 -64
- package/dist/post/index.mjs +76 -74
- package/dist/post/post_form_page.js +71 -64
- package/dist/post/post_form_page.mjs +76 -74
- package/dist/table/index.d.mts +7 -3
- package/dist/table/index.d.ts +7 -3
- package/dist/table/index.js +233 -111
- package/dist/table/index.mjs +230 -116
- package/dist/table/item_loader.d.mts +5 -4
- package/dist/table/item_loader.d.ts +5 -4
- package/dist/table/load_table.d.mts +36 -0
- package/dist/table/load_table.d.ts +36 -0
- package/dist/table/load_table.js +87 -0
- package/dist/table/load_table.mjs +66 -0
- package/dist/table/loader.d.mts +10 -15
- package/dist/table/loader.d.ts +10 -15
- package/dist/table/loader.js +67 -31
- package/dist/table/loader.mjs +67 -32
- package/dist/table/page.d.mts +6 -16
- package/dist/table/page.d.ts +6 -16
- package/dist/table/page.js +247 -169
- package/dist/table/page.mjs +248 -176
- package/dist/table/repository.d.mts +14 -10
- package/dist/table/repository.d.ts +14 -10
- package/dist/table/repository.js +5 -1
- package/dist/table/repository.mjs +5 -1
- package/dist/table/table.d.mts +4 -1
- package/dist/table/table.d.ts +4 -1
- package/dist/table/table.js +55 -6
- package/dist/table/table.mjs +55 -6
- package/dist/table/table_form.d.mts +13 -0
- package/dist/table/table_form.d.ts +13 -0
- package/dist/table/table_form.js +345 -0
- package/dist/table/table_form.mjs +320 -0
- package/dist/table/use_table.d.mts +4 -0
- package/dist/table/use_table.d.ts +4 -0
- package/dist/table/use_table.js +34 -0
- package/dist/table/use_table.mjs +9 -0
- package/package.json +2 -2
package/dist/table/index.mjs
CHANGED
|
@@ -11,7 +11,7 @@ var BaseTableRepository = class {
|
|
|
11
11
|
pk;
|
|
12
12
|
constructor(db, schema, pk = "id") {
|
|
13
13
|
this.db = db;
|
|
14
|
-
this.schema = schema;
|
|
14
|
+
this.schema = db._.fullSchema[schema];
|
|
15
15
|
this.pk = pk;
|
|
16
16
|
}
|
|
17
17
|
async find(id) {
|
|
@@ -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 select(key) {
|
|
54
|
+
const rows = await this.db.select({ value: this.schema[key] }).from(this.schema).groupBy(this.schema[key]);
|
|
55
|
+
return rows.map((row) => row.value);
|
|
56
|
+
}
|
|
53
57
|
};
|
|
54
58
|
|
|
55
59
|
// src/table/buttons.tsx
|
|
@@ -141,60 +145,92 @@ var tableItemloader = ({
|
|
|
141
145
|
};
|
|
142
146
|
};
|
|
143
147
|
|
|
144
|
-
// src/table/
|
|
148
|
+
// src/table/load_table.tsx
|
|
145
149
|
import {
|
|
146
150
|
and,
|
|
151
|
+
eq as eq2,
|
|
147
152
|
ilike
|
|
148
153
|
} from "drizzle-orm";
|
|
154
|
+
async function loadTable({
|
|
155
|
+
request,
|
|
156
|
+
repository,
|
|
157
|
+
options
|
|
158
|
+
}) {
|
|
159
|
+
const searchParams = new URL(request.url).searchParams;
|
|
160
|
+
const { where, searchKey, defaultOrderBy, defaultDirection } = options;
|
|
161
|
+
const query = searchParams.get("query") ?? void 0;
|
|
162
|
+
const limit = Number(searchParams.get("limit") ?? "20");
|
|
163
|
+
const offset = Number(searchParams.get("offset") ?? "0");
|
|
164
|
+
const orderBy = searchParams.get("orderBy") ?? defaultOrderBy;
|
|
165
|
+
const direction = searchParams.get("direction") ?? defaultDirection;
|
|
166
|
+
const filterWhere = Object.entries(options.filters ?? {}).map(([key, value]) => {
|
|
167
|
+
const param = searchParams.get(key);
|
|
168
|
+
if (param) {
|
|
169
|
+
return eq2(
|
|
170
|
+
repository.schema[key],
|
|
171
|
+
decodeURIComponent(param)
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
return void 0;
|
|
175
|
+
}).filter(Boolean);
|
|
176
|
+
const whereClauses = and(
|
|
177
|
+
searchKey && query ? ilike(
|
|
178
|
+
repository.schema[searchKey],
|
|
179
|
+
`%${query}%`
|
|
180
|
+
) : void 0,
|
|
181
|
+
...filterWhere,
|
|
182
|
+
...where ?? []
|
|
183
|
+
);
|
|
184
|
+
const total = await repository.countTotal({ where: whereClauses });
|
|
185
|
+
const items = await repository.findAll({
|
|
186
|
+
orderBy,
|
|
187
|
+
direction,
|
|
188
|
+
limit,
|
|
189
|
+
offset,
|
|
190
|
+
where: whereClauses
|
|
191
|
+
});
|
|
192
|
+
const filters = Object.fromEntries(
|
|
193
|
+
await Promise.all(
|
|
194
|
+
Object.keys(options.filters ?? {}).map(async (key) => {
|
|
195
|
+
const values = await repository.select(key);
|
|
196
|
+
return [key, values.filter(Boolean)];
|
|
197
|
+
})
|
|
198
|
+
)
|
|
199
|
+
);
|
|
200
|
+
return {
|
|
201
|
+
items,
|
|
202
|
+
total,
|
|
203
|
+
limit,
|
|
204
|
+
offset,
|
|
205
|
+
orderBy,
|
|
206
|
+
direction,
|
|
207
|
+
searchKey,
|
|
208
|
+
filters
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// src/table/loader.tsx
|
|
149
213
|
function tableLoader({
|
|
150
214
|
repository,
|
|
151
|
-
|
|
215
|
+
options
|
|
152
216
|
}) {
|
|
153
217
|
return async ({ request }) => {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const offset = Number(searchParams.get("offset") ?? "0");
|
|
159
|
-
const orderBy = searchParams.get("orderBy") ?? defaultOrderBy;
|
|
160
|
-
const direction = searchParams.get("direction") ?? defaultDirection;
|
|
161
|
-
const whereClauses = and(
|
|
162
|
-
searchKey && query ? ilike(
|
|
163
|
-
repository.schema[searchKey],
|
|
164
|
-
`%${query}%`
|
|
165
|
-
) : void 0,
|
|
166
|
-
...where ?? []
|
|
167
|
-
);
|
|
168
|
-
const total = await repository.countTotal({ where: whereClauses });
|
|
169
|
-
const items = await repository.findAll({
|
|
170
|
-
orderBy,
|
|
171
|
-
direction,
|
|
172
|
-
limit,
|
|
173
|
-
offset,
|
|
174
|
-
where: whereClauses
|
|
218
|
+
const table = await loadTable({
|
|
219
|
+
request,
|
|
220
|
+
repository,
|
|
221
|
+
options
|
|
175
222
|
});
|
|
176
223
|
return {
|
|
177
|
-
table
|
|
178
|
-
items,
|
|
179
|
-
total,
|
|
180
|
-
limit,
|
|
181
|
-
offset,
|
|
182
|
-
orderBy,
|
|
183
|
-
direction,
|
|
184
|
-
searchKey
|
|
185
|
-
}
|
|
224
|
+
table
|
|
186
225
|
};
|
|
187
226
|
};
|
|
188
227
|
}
|
|
189
228
|
|
|
190
229
|
// src/table/page.tsx
|
|
191
|
-
import {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
useNavigate,
|
|
196
|
-
useSearchParams as useSearchParams3
|
|
197
|
-
} from "react-router";
|
|
230
|
+
import { Link as Link3, useLocation as useLocation3 } from "react-router";
|
|
231
|
+
|
|
232
|
+
// src/table/table_form.tsx
|
|
233
|
+
import { useLocation as useLocation2, useNavigate, useSearchParams as useSearchParams3 } from "react-router";
|
|
198
234
|
import { GoSearch } from "react-icons/go";
|
|
199
235
|
|
|
200
236
|
// src/table/table.tsx
|
|
@@ -211,7 +247,8 @@ function Table({
|
|
|
211
247
|
limit,
|
|
212
248
|
offset,
|
|
213
249
|
orderBy,
|
|
214
|
-
direction
|
|
250
|
+
direction,
|
|
251
|
+
filters
|
|
215
252
|
}) {
|
|
216
253
|
const keys = Object.entries(columns).filter((entry) => entry[1]).map(([key]) => key);
|
|
217
254
|
const sortedArray = [...data];
|
|
@@ -219,7 +256,10 @@ function Table({
|
|
|
219
256
|
return /* @__PURE__ */ jsxs2(
|
|
220
257
|
"table",
|
|
221
258
|
{
|
|
222
|
-
className: cn2(
|
|
259
|
+
className: cn2(
|
|
260
|
+
className,
|
|
261
|
+
"text-[15px] border-separate border-spacing-0"
|
|
262
|
+
),
|
|
223
263
|
children: [
|
|
224
264
|
/* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsx2("tr", { children: keys.map((key) => {
|
|
225
265
|
const value = columns[key];
|
|
@@ -236,8 +276,8 @@ function Table({
|
|
|
236
276
|
"button",
|
|
237
277
|
{
|
|
238
278
|
className: cn2(
|
|
239
|
-
orderBy === key ? "text-
|
|
240
|
-
"px-4
|
|
279
|
+
orderBy === key ? "text-gray-900 font-medium" : "text-gray-500 font-medium",
|
|
280
|
+
"px-4 flex items-center w-full"
|
|
241
281
|
),
|
|
242
282
|
onClick: () => {
|
|
243
283
|
let newDirection = "asc";
|
|
@@ -258,14 +298,59 @@ function Table({
|
|
|
258
298
|
}
|
|
259
299
|
return /* @__PURE__ */ jsx2(Fragment2, { children: reactNode });
|
|
260
300
|
}
|
|
261
|
-
|
|
301
|
+
const filter = filters[key];
|
|
302
|
+
return /* @__PURE__ */ jsxs2(
|
|
303
|
+
"th",
|
|
304
|
+
{
|
|
305
|
+
className: cn2(
|
|
306
|
+
"py-4 border-y font-normal align-top"
|
|
307
|
+
),
|
|
308
|
+
children: [
|
|
309
|
+
/* @__PURE__ */ jsx2(Head, {}),
|
|
310
|
+
filter && /* @__PURE__ */ jsx2("div", { className: "px-3 mt-4", children: /* @__PURE__ */ jsxs2(
|
|
311
|
+
"select",
|
|
312
|
+
{
|
|
313
|
+
className: "w-full h-10 px-1.5 border rounded-full outline-none",
|
|
314
|
+
onChange: (e) => {
|
|
315
|
+
const value2 = e.target.value;
|
|
316
|
+
setSearchParams((prev) => {
|
|
317
|
+
if (value2) {
|
|
318
|
+
prev.set(
|
|
319
|
+
key,
|
|
320
|
+
encodeURIComponent(
|
|
321
|
+
value2
|
|
322
|
+
)
|
|
323
|
+
);
|
|
324
|
+
} else {
|
|
325
|
+
prev.delete(key);
|
|
326
|
+
}
|
|
327
|
+
return prev;
|
|
328
|
+
});
|
|
329
|
+
},
|
|
330
|
+
children: [
|
|
331
|
+
/* @__PURE__ */ jsx2("option", { value: "", children: "\uC804\uCCB4" }),
|
|
332
|
+
filter.map((option) => /* @__PURE__ */ jsx2(
|
|
333
|
+
"option",
|
|
334
|
+
{
|
|
335
|
+
value: option,
|
|
336
|
+
children: option
|
|
337
|
+
},
|
|
338
|
+
option
|
|
339
|
+
))
|
|
340
|
+
]
|
|
341
|
+
}
|
|
342
|
+
) })
|
|
343
|
+
]
|
|
344
|
+
},
|
|
345
|
+
key
|
|
346
|
+
);
|
|
262
347
|
}) }) }),
|
|
263
348
|
/* @__PURE__ */ jsxs2("tbody", { children: [
|
|
264
349
|
sortedArray.length === 0 && /* @__PURE__ */ jsx2("tr", { children: /* @__PURE__ */ jsx2(
|
|
265
350
|
"td",
|
|
266
351
|
{
|
|
267
352
|
colSpan: keys.length,
|
|
268
|
-
className: "px-4 h-
|
|
353
|
+
className: "px-4 h-20 text-gray-400 text-center",
|
|
269
354
|
children: "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."
|
|
270
355
|
}
|
|
271
356
|
) }),
|
|
@@ -300,8 +385,97 @@ function Table({
|
|
|
300
385
|
);
|
|
301
386
|
}
|
|
302
387
|
|
|
303
|
-
// src/table/
|
|
388
|
+
// src/table/use_table.tsx
|
|
389
|
+
import { useLoaderData } from "react-router";
|
|
390
|
+
function useTable() {
|
|
391
|
+
const { table } = useLoaderData();
|
|
392
|
+
return table;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// src/table/table_form.tsx
|
|
304
396
|
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
397
|
+
function TableForm({
|
|
398
|
+
columns,
|
|
399
|
+
primaryKey = "id"
|
|
400
|
+
}) {
|
|
401
|
+
const { pathname } = useLocation2();
|
|
402
|
+
const {
|
|
403
|
+
items,
|
|
404
|
+
total,
|
|
405
|
+
limit,
|
|
406
|
+
offset,
|
|
407
|
+
orderBy,
|
|
408
|
+
direction,
|
|
409
|
+
searchKey,
|
|
410
|
+
filters
|
|
411
|
+
} = useTable();
|
|
412
|
+
const navigate = useNavigate();
|
|
413
|
+
const search = (query) => {
|
|
414
|
+
const searchParams2 = new URLSearchParams(window.location.search);
|
|
415
|
+
searchParams2.set("query", query);
|
|
416
|
+
searchParams2.set("offset", "0");
|
|
417
|
+
navigate(`${pathname}?${searchParams2.toString()}`);
|
|
418
|
+
};
|
|
419
|
+
const [searchParams] = useSearchParams3();
|
|
420
|
+
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
421
|
+
searchKey && /* @__PURE__ */ jsxs3(
|
|
422
|
+
"form",
|
|
423
|
+
{
|
|
424
|
+
className: "h-20 px-4 flex items-center border-t",
|
|
425
|
+
onSubmit: (e) => {
|
|
426
|
+
e.preventDefault();
|
|
427
|
+
const formData = new FormData(e.currentTarget);
|
|
428
|
+
const query = formData.get("query");
|
|
429
|
+
search(query);
|
|
430
|
+
},
|
|
431
|
+
children: [
|
|
432
|
+
/* @__PURE__ */ jsx3(
|
|
433
|
+
"button",
|
|
434
|
+
{
|
|
435
|
+
type: "submit",
|
|
436
|
+
className: "w-10 h-10 flex justify-center items-center",
|
|
437
|
+
children: /* @__PURE__ */ jsx3(GoSearch, { className: "text-xl mr-4" })
|
|
438
|
+
}
|
|
439
|
+
),
|
|
440
|
+
/* @__PURE__ */ jsx3(
|
|
441
|
+
"input",
|
|
442
|
+
{
|
|
443
|
+
className: "outline-none h-full flex-1",
|
|
444
|
+
placeholder: "\uC5EC\uAE30\uC5D0 \uAC80\uC0C9\uD558\uC138\uC694...",
|
|
445
|
+
name: "query",
|
|
446
|
+
defaultValue: searchParams.get("query") ?? ""
|
|
447
|
+
}
|
|
448
|
+
)
|
|
449
|
+
]
|
|
450
|
+
}
|
|
451
|
+
),
|
|
452
|
+
/* @__PURE__ */ jsx3(
|
|
453
|
+
Table,
|
|
454
|
+
{
|
|
455
|
+
data: items,
|
|
456
|
+
columns,
|
|
457
|
+
getLink: primaryKey ? (item) => `${pathname}/${item[primaryKey]}` : void 0,
|
|
458
|
+
limit,
|
|
459
|
+
offset,
|
|
460
|
+
orderBy,
|
|
461
|
+
direction,
|
|
462
|
+
filters
|
|
463
|
+
}
|
|
464
|
+
),
|
|
465
|
+
/* @__PURE__ */ jsx3(
|
|
466
|
+
TablePageButtons,
|
|
467
|
+
{
|
|
468
|
+
total,
|
|
469
|
+
limit,
|
|
470
|
+
offset,
|
|
471
|
+
MAX_PAGES_TO_SHOW: 10
|
|
472
|
+
}
|
|
473
|
+
)
|
|
474
|
+
] });
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// src/table/page.tsx
|
|
478
|
+
import { Fragment as Fragment4, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
305
479
|
function createTablePage({
|
|
306
480
|
name,
|
|
307
481
|
columns,
|
|
@@ -310,90 +484,30 @@ function createTablePage({
|
|
|
310
484
|
return function TablePage({
|
|
311
485
|
header: Header
|
|
312
486
|
}) {
|
|
313
|
-
const { pathname } =
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const navigate = useNavigate();
|
|
317
|
-
const search = (query) => {
|
|
318
|
-
const searchParams2 = new URLSearchParams(window.location.search);
|
|
319
|
-
searchParams2.set("query", query);
|
|
320
|
-
searchParams2.set("offset", "0");
|
|
321
|
-
navigate(`${pathname}?${searchParams2.toString()}`);
|
|
322
|
-
};
|
|
323
|
-
const [searchParams] = useSearchParams3();
|
|
324
|
-
return /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
325
|
-
/* @__PURE__ */ jsx3(
|
|
487
|
+
const { pathname } = useLocation3();
|
|
488
|
+
return /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
489
|
+
/* @__PURE__ */ jsx4(
|
|
326
490
|
Header,
|
|
327
491
|
{
|
|
328
492
|
title: name,
|
|
329
|
-
actions: /* @__PURE__ */
|
|
493
|
+
actions: /* @__PURE__ */ jsxs4(Link3, { to: `${pathname}/new`, className: "button-primary", children: [
|
|
330
494
|
name,
|
|
331
495
|
" \uCD94\uAC00"
|
|
332
496
|
] })
|
|
333
497
|
}
|
|
334
498
|
),
|
|
335
|
-
/* @__PURE__ */
|
|
336
|
-
searchKey && /* @__PURE__ */ jsxs3(
|
|
337
|
-
"form",
|
|
338
|
-
{
|
|
339
|
-
className: "h-18 px-4 flex items-center border-t",
|
|
340
|
-
onSubmit: (e) => {
|
|
341
|
-
e.preventDefault();
|
|
342
|
-
const formData = new FormData(e.currentTarget);
|
|
343
|
-
const query = formData.get("query");
|
|
344
|
-
search(query);
|
|
345
|
-
},
|
|
346
|
-
children: [
|
|
347
|
-
/* @__PURE__ */ jsx3(
|
|
348
|
-
"button",
|
|
349
|
-
{
|
|
350
|
-
type: "submit",
|
|
351
|
-
className: "w-10 h-10 flex justify-center items-center",
|
|
352
|
-
children: /* @__PURE__ */ jsx3(GoSearch, { className: "text-xl mr-4" })
|
|
353
|
-
}
|
|
354
|
-
),
|
|
355
|
-
/* @__PURE__ */ jsx3(
|
|
356
|
-
"input",
|
|
357
|
-
{
|
|
358
|
-
className: "outline-none h-full flex-1",
|
|
359
|
-
placeholder: "\uC5EC\uAE30\uC5D0 \uAC80\uC0C9\uD558\uC138\uC694...",
|
|
360
|
-
name: "query",
|
|
361
|
-
defaultValue: searchParams.get("query") ?? ""
|
|
362
|
-
}
|
|
363
|
-
)
|
|
364
|
-
]
|
|
365
|
-
}
|
|
366
|
-
),
|
|
367
|
-
/* @__PURE__ */ jsx3(
|
|
368
|
-
Table,
|
|
369
|
-
{
|
|
370
|
-
data: items,
|
|
371
|
-
columns,
|
|
372
|
-
getLink: primaryKey ? (item) => `${pathname}/${item[primaryKey]}` : void 0,
|
|
373
|
-
limit,
|
|
374
|
-
offset,
|
|
375
|
-
orderBy,
|
|
376
|
-
direction
|
|
377
|
-
}
|
|
378
|
-
),
|
|
379
|
-
/* @__PURE__ */ jsx3(
|
|
380
|
-
TablePageButtons,
|
|
381
|
-
{
|
|
382
|
-
total,
|
|
383
|
-
limit,
|
|
384
|
-
offset,
|
|
385
|
-
MAX_PAGES_TO_SHOW: 10
|
|
386
|
-
}
|
|
387
|
-
)
|
|
388
|
-
] })
|
|
499
|
+
/* @__PURE__ */ jsx4("div", { className: "max-w-7xl mx-auto w-full overflow-auto", children: /* @__PURE__ */ jsx4(TableForm, { columns, primaryKey }) })
|
|
389
500
|
] });
|
|
390
501
|
};
|
|
391
502
|
}
|
|
392
503
|
export {
|
|
393
504
|
BaseTableRepository,
|
|
394
505
|
Table,
|
|
506
|
+
TableForm,
|
|
395
507
|
TablePageButtons,
|
|
396
508
|
createTablePage,
|
|
509
|
+
loadTable,
|
|
397
510
|
tableItemloader,
|
|
398
|
-
tableLoader
|
|
511
|
+
tableLoader,
|
|
512
|
+
useTable
|
|
399
513
|
};
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { Table } from 'drizzle-orm';
|
|
2
1
|
import { TableRepository } from './repository.mjs';
|
|
3
2
|
import { LoaderFunctionArgs } from 'react-router';
|
|
4
|
-
import 'drizzle-orm/pg-core';
|
|
3
|
+
import { PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
4
|
+
import 'drizzle-orm';
|
|
5
|
+
import 'drizzle-orm/node-postgres';
|
|
5
6
|
|
|
6
|
-
type TableItemLoaderOptions<T extends
|
|
7
|
+
type TableItemLoaderOptions<T extends PgTableWithColumns<any>, TSelect> = {
|
|
7
8
|
repository: TableRepository<T, TSelect>;
|
|
8
9
|
};
|
|
9
|
-
declare const tableItemloader: <T extends
|
|
10
|
+
declare const tableItemloader: <T extends PgTableWithColumns<any>, TSelect>({ repository, }: TableItemLoaderOptions<T, TSelect>) => (args: LoaderFunctionArgs) => Promise<{
|
|
10
11
|
item: Awaited<TSelect> | undefined;
|
|
11
12
|
}>;
|
|
12
13
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import { Table } from 'drizzle-orm';
|
|
2
1
|
import { TableRepository } from './repository.js';
|
|
3
2
|
import { LoaderFunctionArgs } from 'react-router';
|
|
4
|
-
import 'drizzle-orm/pg-core';
|
|
3
|
+
import { PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
4
|
+
import 'drizzle-orm';
|
|
5
|
+
import 'drizzle-orm/node-postgres';
|
|
5
6
|
|
|
6
|
-
type TableItemLoaderOptions<T extends
|
|
7
|
+
type TableItemLoaderOptions<T extends PgTableWithColumns<any>, TSelect> = {
|
|
7
8
|
repository: TableRepository<T, TSelect>;
|
|
8
9
|
};
|
|
9
|
-
declare const tableItemloader: <T extends
|
|
10
|
+
declare const tableItemloader: <T extends PgTableWithColumns<any>, TSelect>({ repository, }: TableItemLoaderOptions<T, TSelect>) => (args: LoaderFunctionArgs) => Promise<{
|
|
10
11
|
item: Awaited<TSelect> | undefined;
|
|
11
12
|
}>;
|
|
12
13
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SQLWrapper, InferSelectModel } from 'drizzle-orm';
|
|
2
|
+
import { PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
3
|
+
import { TableRepository, ColumnOf } from './repository.mjs';
|
|
4
|
+
import 'drizzle-orm/node-postgres';
|
|
5
|
+
|
|
6
|
+
type TableOptions<T extends PgTableWithColumns<any>> = {
|
|
7
|
+
where?: SQLWrapper[];
|
|
8
|
+
searchKey?: ColumnOf<T>;
|
|
9
|
+
defaultOrderBy: keyof InferSelectModel<T>;
|
|
10
|
+
defaultDirection: "asc" | "desc";
|
|
11
|
+
filters?: {
|
|
12
|
+
[key in keyof InferSelectModel<T>]?: "auto";
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
type TableLoaderOptions<T extends PgTableWithColumns<any>, TSelect> = {
|
|
16
|
+
repository: TableRepository<T, TSelect>;
|
|
17
|
+
options: TableOptions<T>;
|
|
18
|
+
};
|
|
19
|
+
declare function loadTable<T extends PgTableWithColumns<any>, TSelect>({ request, repository, options, }: {
|
|
20
|
+
request: Request;
|
|
21
|
+
repository: TableRepository<T, TSelect>;
|
|
22
|
+
options: TableOptions<T>;
|
|
23
|
+
}): Promise<{
|
|
24
|
+
items: TSelect[];
|
|
25
|
+
total: number;
|
|
26
|
+
limit: number;
|
|
27
|
+
offset: number;
|
|
28
|
+
orderBy: keyof T["_"]["columns"] & string;
|
|
29
|
+
direction: "asc" | "desc";
|
|
30
|
+
searchKey: ColumnOf<T> | undefined;
|
|
31
|
+
filters: {
|
|
32
|
+
[k: string]: unknown[];
|
|
33
|
+
};
|
|
34
|
+
}>;
|
|
35
|
+
|
|
36
|
+
export { type TableLoaderOptions, loadTable };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SQLWrapper, InferSelectModel } from 'drizzle-orm';
|
|
2
|
+
import { PgTableWithColumns } from 'drizzle-orm/pg-core';
|
|
3
|
+
import { TableRepository, ColumnOf } from './repository.js';
|
|
4
|
+
import 'drizzle-orm/node-postgres';
|
|
5
|
+
|
|
6
|
+
type TableOptions<T extends PgTableWithColumns<any>> = {
|
|
7
|
+
where?: SQLWrapper[];
|
|
8
|
+
searchKey?: ColumnOf<T>;
|
|
9
|
+
defaultOrderBy: keyof InferSelectModel<T>;
|
|
10
|
+
defaultDirection: "asc" | "desc";
|
|
11
|
+
filters?: {
|
|
12
|
+
[key in keyof InferSelectModel<T>]?: "auto";
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
type TableLoaderOptions<T extends PgTableWithColumns<any>, TSelect> = {
|
|
16
|
+
repository: TableRepository<T, TSelect>;
|
|
17
|
+
options: TableOptions<T>;
|
|
18
|
+
};
|
|
19
|
+
declare function loadTable<T extends PgTableWithColumns<any>, TSelect>({ request, repository, options, }: {
|
|
20
|
+
request: Request;
|
|
21
|
+
repository: TableRepository<T, TSelect>;
|
|
22
|
+
options: TableOptions<T>;
|
|
23
|
+
}): Promise<{
|
|
24
|
+
items: TSelect[];
|
|
25
|
+
total: number;
|
|
26
|
+
limit: number;
|
|
27
|
+
offset: number;
|
|
28
|
+
orderBy: keyof T["_"]["columns"] & string;
|
|
29
|
+
direction: "asc" | "desc";
|
|
30
|
+
searchKey: ColumnOf<T> | undefined;
|
|
31
|
+
filters: {
|
|
32
|
+
[k: string]: unknown[];
|
|
33
|
+
};
|
|
34
|
+
}>;
|
|
35
|
+
|
|
36
|
+
export { type TableLoaderOptions, loadTable };
|
|
@@ -0,0 +1,87 @@
|
|
|
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, desc) => {
|
|
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: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/table/load_table.tsx
|
|
21
|
+
var load_table_exports = {};
|
|
22
|
+
__export(load_table_exports, {
|
|
23
|
+
loadTable: () => loadTable
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(load_table_exports);
|
|
26
|
+
var import_drizzle_orm = require("drizzle-orm");
|
|
27
|
+
async function loadTable({
|
|
28
|
+
request,
|
|
29
|
+
repository,
|
|
30
|
+
options
|
|
31
|
+
}) {
|
|
32
|
+
const searchParams = new URL(request.url).searchParams;
|
|
33
|
+
const { where, searchKey, defaultOrderBy, defaultDirection } = options;
|
|
34
|
+
const query = searchParams.get("query") ?? void 0;
|
|
35
|
+
const limit = Number(searchParams.get("limit") ?? "20");
|
|
36
|
+
const offset = Number(searchParams.get("offset") ?? "0");
|
|
37
|
+
const orderBy = searchParams.get("orderBy") ?? defaultOrderBy;
|
|
38
|
+
const direction = searchParams.get("direction") ?? defaultDirection;
|
|
39
|
+
const filterWhere = Object.entries(options.filters ?? {}).map(([key, value]) => {
|
|
40
|
+
const param = searchParams.get(key);
|
|
41
|
+
if (param) {
|
|
42
|
+
return (0, import_drizzle_orm.eq)(
|
|
43
|
+
repository.schema[key],
|
|
44
|
+
decodeURIComponent(param)
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return void 0;
|
|
48
|
+
}).filter(Boolean);
|
|
49
|
+
const whereClauses = (0, import_drizzle_orm.and)(
|
|
50
|
+
searchKey && query ? (0, import_drizzle_orm.ilike)(
|
|
51
|
+
repository.schema[searchKey],
|
|
52
|
+
`%${query}%`
|
|
53
|
+
) : void 0,
|
|
54
|
+
...filterWhere,
|
|
55
|
+
...where ?? []
|
|
56
|
+
);
|
|
57
|
+
const total = await repository.countTotal({ where: whereClauses });
|
|
58
|
+
const items = await repository.findAll({
|
|
59
|
+
orderBy,
|
|
60
|
+
direction,
|
|
61
|
+
limit,
|
|
62
|
+
offset,
|
|
63
|
+
where: whereClauses
|
|
64
|
+
});
|
|
65
|
+
const filters = Object.fromEntries(
|
|
66
|
+
await Promise.all(
|
|
67
|
+
Object.keys(options.filters ?? {}).map(async (key) => {
|
|
68
|
+
const values = await repository.select(key);
|
|
69
|
+
return [key, values.filter(Boolean)];
|
|
70
|
+
})
|
|
71
|
+
)
|
|
72
|
+
);
|
|
73
|
+
return {
|
|
74
|
+
items,
|
|
75
|
+
total,
|
|
76
|
+
limit,
|
|
77
|
+
offset,
|
|
78
|
+
orderBy,
|
|
79
|
+
direction,
|
|
80
|
+
searchKey,
|
|
81
|
+
filters
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
85
|
+
0 && (module.exports = {
|
|
86
|
+
loadTable
|
|
87
|
+
});
|