@ghentcdh/crouton-api 0.0.1-alpha.2 → 0.0.1-alpha.21
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/index.cjs +1397 -742
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1069 -276
- package/dist/index.d.ts +1069 -276
- package/dist/index.js +1372 -729
- package/dist/index.js.map +1 -1
- package/package.json +13 -8
package/dist/index.js
CHANGED
|
@@ -5,17 +5,33 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
5
5
|
import { Module } from "@nestjs/common";
|
|
6
6
|
import { APP_FILTER } from "@nestjs/core";
|
|
7
7
|
|
|
8
|
-
// src/lib/crud/app-layout.
|
|
9
|
-
import {
|
|
10
|
-
|
|
8
|
+
// src/lib/crud/app-layout/app-layout.types.ts
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
var SidebarLeafSchema = z.object({
|
|
11
|
+
kind: z.literal("item").default("item"),
|
|
12
|
+
id: z.string(),
|
|
13
|
+
label: z.string(),
|
|
14
|
+
position: z.number().optional()
|
|
15
|
+
});
|
|
16
|
+
var SidebarGroupSchema = z.object({
|
|
17
|
+
kind: z.literal("group").default("group"),
|
|
18
|
+
id: z.string(),
|
|
19
|
+
label: z.string(),
|
|
20
|
+
position: z.number().optional(),
|
|
21
|
+
children: z.array(SidebarLeafSchema).default([])
|
|
22
|
+
});
|
|
23
|
+
var SidebarNodeSchema = z.discriminatedUnion("kind", [
|
|
24
|
+
SidebarLeafSchema,
|
|
25
|
+
SidebarGroupSchema
|
|
26
|
+
]);
|
|
11
27
|
|
|
12
28
|
// ../crouton-core/src/lib/request.model.ts
|
|
13
|
-
import { z as
|
|
29
|
+
import { z as z3 } from "zod";
|
|
14
30
|
|
|
15
31
|
// ../crouton-core/src/lib/zod.types.ts
|
|
16
|
-
import { z } from "zod";
|
|
17
|
-
var PositiveRequestNumber = /* @__PURE__ */ __name(() =>
|
|
18
|
-
var StringOrArray = /* @__PURE__ */ __name(() =>
|
|
32
|
+
import { z as z2 } from "zod";
|
|
33
|
+
var PositiveRequestNumber = /* @__PURE__ */ __name(() => z2.coerce.number().int().positive().nonnegative(), "PositiveRequestNumber");
|
|
34
|
+
var StringOrArray = /* @__PURE__ */ __name(() => z2.string().or(z2.array(z2.string())).transform((val) => {
|
|
19
35
|
if (Array.isArray(val)) return val;
|
|
20
36
|
return [
|
|
21
37
|
val
|
|
@@ -23,14 +39,14 @@ var StringOrArray = /* @__PURE__ */ __name(() => z.string().or(z.array(z.string(
|
|
|
23
39
|
}), "StringOrArray");
|
|
24
40
|
|
|
25
41
|
// ../crouton-core/src/lib/request.model.ts
|
|
26
|
-
var SortDirEnum =
|
|
42
|
+
var SortDirEnum = z3.enum([
|
|
27
43
|
"asc",
|
|
28
44
|
"desc"
|
|
29
45
|
]);
|
|
30
|
-
var RequestSchema =
|
|
46
|
+
var RequestSchema = z3.object({
|
|
31
47
|
page: PositiveRequestNumber().optional().default(1),
|
|
32
48
|
pageSize: PositiveRequestNumber().optional().default(20),
|
|
33
|
-
sort:
|
|
49
|
+
sort: z3.string().optional().default("id"),
|
|
34
50
|
sortDir: SortDirEnum.optional().default("asc"),
|
|
35
51
|
// Filter is of the format key:value:operator (e.g. name:john:eq) operator is optional
|
|
36
52
|
filter: StringOrArray().optional().default([])
|
|
@@ -81,13 +97,13 @@ var buildSortKey = /* @__PURE__ */ __name((keys, sortDir) => {
|
|
|
81
97
|
}, "buildSortKey");
|
|
82
98
|
|
|
83
99
|
// ../crouton-core/src/lib/response.model.ts
|
|
84
|
-
import { z as
|
|
100
|
+
import { z as z4 } from "zod";
|
|
85
101
|
var ResponseRequestSchema = RequestSchema.extend({
|
|
86
102
|
count: PositiveRequestNumber(),
|
|
87
103
|
totalPages: PositiveRequestNumber()
|
|
88
104
|
});
|
|
89
|
-
var ResponseSchema =
|
|
90
|
-
data:
|
|
105
|
+
var ResponseSchema = z4.object({
|
|
106
|
+
data: z4.array(z4.unknown()),
|
|
91
107
|
request: ResponseRequestSchema
|
|
92
108
|
});
|
|
93
109
|
|
|
@@ -350,23 +366,6 @@ var LayoutBuilder = class _LayoutBuilder extends BuilderWithElements {
|
|
|
350
366
|
}
|
|
351
367
|
};
|
|
352
368
|
|
|
353
|
-
// ../crouton-core/src/lib/json-config.types.ts
|
|
354
|
-
var labelFromId = /* @__PURE__ */ __name((id) => {
|
|
355
|
-
const words = id.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
|
|
356
|
-
return words.charAt(0).toUpperCase() + words.slice(1).toLowerCase();
|
|
357
|
-
}, "labelFromId");
|
|
358
|
-
var normalizeColumns = /* @__PURE__ */ __name((columns) => {
|
|
359
|
-
if (!columns) return void 0;
|
|
360
|
-
const raw = Array.isArray(columns) ? columns : Object.entries(columns).map(([id, col]) => ({
|
|
361
|
-
id,
|
|
362
|
-
...col
|
|
363
|
-
}));
|
|
364
|
-
return raw.map((col) => ({
|
|
365
|
-
...col,
|
|
366
|
-
label: col.label ?? labelFromId(col.id)
|
|
367
|
-
}));
|
|
368
|
-
}, "normalizeColumns");
|
|
369
|
-
|
|
370
369
|
// ../crouton-core/src/lib/value-label.ts
|
|
371
370
|
var wrapOne = /* @__PURE__ */ __name((value, values) => {
|
|
372
371
|
const match = values.find((o) => o.value === value);
|
|
@@ -460,6 +459,515 @@ var TableBuilder = class _TableBuilder {
|
|
|
460
459
|
}
|
|
461
460
|
};
|
|
462
461
|
|
|
462
|
+
// ../crouton-core/src/lib/data-source/DataSourceSchema.ts
|
|
463
|
+
import z5 from "zod";
|
|
464
|
+
var DataSourceShape = z5.object({
|
|
465
|
+
/** Datasource name (folder + `name` in data-source.json). */
|
|
466
|
+
name: z5.string(),
|
|
467
|
+
/** Env var holding the connection URL. */
|
|
468
|
+
urlEnv: z5.string(),
|
|
469
|
+
/** Import path for this datasource's generated Zod types (for resource `schema.ts`). */
|
|
470
|
+
generatedTypesImport: z5.string().optional(),
|
|
471
|
+
/** Datasource type tag. Default `postgres`. */
|
|
472
|
+
type: z5.string().default("postgres"),
|
|
473
|
+
/** Mark this as the default datasource. Default `false`. */
|
|
474
|
+
default: z5.boolean().default(false),
|
|
475
|
+
/** Prisma schema path, relative to project root. Default `prisma/<name>/schema.prisma`. */
|
|
476
|
+
prismaSchema: z5.string().optional(),
|
|
477
|
+
/** Prisma config path, relative to project root. Default `prisma/<name>/prisma.config.ts`. */
|
|
478
|
+
prismaConfig: z5.string().optional(),
|
|
479
|
+
/** zod-prisma-types output dir, relative to project root. Default `generated/<name>/src`. */
|
|
480
|
+
zodOutput: z5.string().optional(),
|
|
481
|
+
/** Prisma client output dir, relative to project root. Default `generated/<name>/client`. */
|
|
482
|
+
clientOutput: z5.string().optional()
|
|
483
|
+
});
|
|
484
|
+
var transformDataSource = /* @__PURE__ */ __name((data) => {
|
|
485
|
+
const name = data.name ?? "name";
|
|
486
|
+
return {
|
|
487
|
+
...data,
|
|
488
|
+
generatedTypesImport: data.generatedTypesImport ?? `@your-scope/generated/${name}`,
|
|
489
|
+
prismaSchema: data.prismaSchema ?? `prisma/${name}/schema.prisma`,
|
|
490
|
+
prismaConfig: data.prismaConfig ?? `prisma/${name}/prisma.config.ts`,
|
|
491
|
+
zodOutput: data.zodOutput ?? `generated/${name}/src`,
|
|
492
|
+
clientOutput: data.clientOutput ?? `generated/${name}/client`
|
|
493
|
+
};
|
|
494
|
+
}, "transformDataSource");
|
|
495
|
+
var DataSourceSchema = DataSourceShape.transform(transformDataSource);
|
|
496
|
+
|
|
497
|
+
// ../crouton-core/src/lib/data-source/Operations.schema.ts
|
|
498
|
+
import { z as z6 } from "zod";
|
|
499
|
+
var BoolOrUpsertSchema = z6.union([
|
|
500
|
+
z6.boolean(),
|
|
501
|
+
z6.object({
|
|
502
|
+
upsertOn: z6.union([
|
|
503
|
+
z6.string(),
|
|
504
|
+
z6.array(z6.string())
|
|
505
|
+
])
|
|
506
|
+
})
|
|
507
|
+
]);
|
|
508
|
+
var JsonOperationsSchema = z6.object({
|
|
509
|
+
findAll: z6.boolean().default(true),
|
|
510
|
+
findOne: z6.boolean().default(true),
|
|
511
|
+
create: z6.boolean().default(true),
|
|
512
|
+
update: z6.boolean().default(true),
|
|
513
|
+
upsert: BoolOrUpsertSchema.default(false),
|
|
514
|
+
delete: z6.boolean().default(true)
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
// ../crouton-core/src/lib/resource/ResourceJson.schema.ts
|
|
518
|
+
import { z as z13 } from "zod";
|
|
519
|
+
|
|
520
|
+
// ../crouton-core/src/lib/resource/CalculatedColumn.schema.ts
|
|
521
|
+
import { z as z8 } from "zod";
|
|
522
|
+
|
|
523
|
+
// ../crouton-core/src/lib/resource/FieldInput.schema.ts
|
|
524
|
+
import { z as z7 } from "zod";
|
|
525
|
+
var RelationType = z7.enum([
|
|
526
|
+
"oneToOne",
|
|
527
|
+
"manyToOne",
|
|
528
|
+
"oneToMany",
|
|
529
|
+
"manyToMany"
|
|
530
|
+
]);
|
|
531
|
+
var DetailControlSchema = z7.object({
|
|
532
|
+
property: z7.string(),
|
|
533
|
+
type: z7.string().optional(),
|
|
534
|
+
options: z7.record(z7.string(), z7.unknown()).optional(),
|
|
535
|
+
hideLabel: z7.boolean().optional(),
|
|
536
|
+
width: z7.string().optional()
|
|
537
|
+
});
|
|
538
|
+
var DetailConfigSchema = z7.object({
|
|
539
|
+
layout: z7.enum([
|
|
540
|
+
"collapse",
|
|
541
|
+
"row"
|
|
542
|
+
]),
|
|
543
|
+
titleKey: z7.string().optional(),
|
|
544
|
+
controls: z7.array(DetailControlSchema)
|
|
545
|
+
});
|
|
546
|
+
var RelationFieldInputOptionsSchema = z7.object({
|
|
547
|
+
/** Field to sort related records by, e.g. `"title"` or `"author.name"`. */
|
|
548
|
+
sort: z7.string().optional(),
|
|
549
|
+
/** Sort direction. Defaults to `"asc"` when omitted. */
|
|
550
|
+
sortDir: z7.enum([
|
|
551
|
+
"asc",
|
|
552
|
+
"desc"
|
|
553
|
+
]).optional(),
|
|
554
|
+
/** CSS flex direction for the relation control button layout. */
|
|
555
|
+
direction: z7.string().optional(),
|
|
556
|
+
/** Key used as the display label in the relation control. */
|
|
557
|
+
displayKey: z7.string().optional(),
|
|
558
|
+
/** Path to the related resource (resolved to a URI at load time). */
|
|
559
|
+
resource: z7.string().optional()
|
|
560
|
+
}).catchall(z7.unknown());
|
|
561
|
+
var FieldInputSchema = z7.object({
|
|
562
|
+
type: z7.string().optional(),
|
|
563
|
+
customRender: z7.string().optional(),
|
|
564
|
+
/**
|
|
565
|
+
* Render format hint for the frontend (e.g. `"relation"` for sub-resource
|
|
566
|
+
* relations). When `format` is `"relation"`, `resource` must also be set.
|
|
567
|
+
*/
|
|
568
|
+
format: z7.string().optional(),
|
|
569
|
+
/**
|
|
570
|
+
* Relative path to the child resource definition, e.g. `"./author.resource"`.
|
|
571
|
+
* Only used when `format` is `"relation"`. Resolved at load time to inject
|
|
572
|
+
* sub-resource URIs into `options`.
|
|
573
|
+
*/
|
|
574
|
+
resource: z7.string().optional(),
|
|
575
|
+
/**
|
|
576
|
+
* Cardinality of the relation. Used by the frontend to determine the correct
|
|
577
|
+
* renderer and behaviour (e.g. single-select vs multi-select).
|
|
578
|
+
* - `manyToOne` / `oneToOne` — single FK reference (autocomplete / relation control)
|
|
579
|
+
* - `oneToMany` / `manyToMany` — collection (sub-resource table / multi-select)
|
|
580
|
+
*/
|
|
581
|
+
relationType: RelationType.optional(),
|
|
582
|
+
/** Override the display order in form views. Lower values come first. */
|
|
583
|
+
position: z7.number().optional(),
|
|
584
|
+
options: z7.union([
|
|
585
|
+
RelationFieldInputOptionsSchema,
|
|
586
|
+
z7.unknown()
|
|
587
|
+
]).optional(),
|
|
588
|
+
/** Nested array detail layout (renders via `detailFixed`). */
|
|
589
|
+
detail: DetailConfigSchema.optional()
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// ../crouton-core/src/lib/schema/label.helper.ts
|
|
593
|
+
var labelFromId = /* @__PURE__ */ __name((id) => {
|
|
594
|
+
const words = id.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
|
|
595
|
+
return words.charAt(0).toUpperCase() + words.slice(1).toLowerCase();
|
|
596
|
+
}, "labelFromId");
|
|
597
|
+
var normalizeLabel = /* @__PURE__ */ __name((obj) => {
|
|
598
|
+
return {
|
|
599
|
+
label: labelFromId(obj.id),
|
|
600
|
+
...obj
|
|
601
|
+
};
|
|
602
|
+
}, "normalizeLabel");
|
|
603
|
+
|
|
604
|
+
// ../crouton-core/src/lib/resource/CalculatedColumn.schema.ts
|
|
605
|
+
var CalculatedColumnSchema = z8.object({
|
|
606
|
+
/** Column identifier used in the response payload and UI schema. */
|
|
607
|
+
id: z8.string(),
|
|
608
|
+
/** SQL alias — must match `id`. */
|
|
609
|
+
alias: z8.string(),
|
|
610
|
+
/** Human-readable label shown in the table header. */
|
|
611
|
+
label: z8.string().optional(),
|
|
612
|
+
sqlExpression: z8.string(),
|
|
613
|
+
/** JSON schema / cast type for the computed value. Defaults to `"number"`. `"string"` skips CAST. */
|
|
614
|
+
type: z8.enum([
|
|
615
|
+
"number",
|
|
616
|
+
"boolean",
|
|
617
|
+
"string"
|
|
618
|
+
]).optional(),
|
|
619
|
+
/**
|
|
620
|
+
* Insertion position relative to the other visible columns.
|
|
621
|
+
* Uses the same semantics as `fieldInput.position` on regular columns:
|
|
622
|
+
* `position: N` places this column before the element currently at index N.
|
|
623
|
+
* Can also be set via `fieldInput.position` (takes precedence).
|
|
624
|
+
*/
|
|
625
|
+
position: z8.number().optional(),
|
|
626
|
+
hiddenInTable: z8.boolean().optional(),
|
|
627
|
+
hiddenInView: z8.boolean().optional(),
|
|
628
|
+
/**
|
|
629
|
+
* Field input options for rendering in form / view schemas.
|
|
630
|
+
* Supports `colspan`, `format`, and any other options passed to the Control renderer.
|
|
631
|
+
* `position` here takes precedence over the top-level `position`.
|
|
632
|
+
*/
|
|
633
|
+
fieldInput: FieldInputSchema.optional()
|
|
634
|
+
}).transform(normalizeLabel);
|
|
635
|
+
|
|
636
|
+
// ../crouton-core/src/lib/resource/Column.ts
|
|
637
|
+
import { z as z9 } from "zod";
|
|
638
|
+
var WhenConditionSchema = z9.object({
|
|
639
|
+
field: z9.string(),
|
|
640
|
+
eq: z9.unknown().optional(),
|
|
641
|
+
neq: z9.unknown().optional(),
|
|
642
|
+
exists: z9.boolean().optional(),
|
|
643
|
+
notExists: z9.boolean().optional()
|
|
644
|
+
});
|
|
645
|
+
var JsonColumnSchema = z9.object({
|
|
646
|
+
id: z9.string(),
|
|
647
|
+
column: z9.string().optional(),
|
|
648
|
+
label: z9.string().optional(),
|
|
649
|
+
hiddenInTable: z9.boolean().default(false),
|
|
650
|
+
hiddenInForm: z9.boolean().default(false),
|
|
651
|
+
hiddenInView: z9.boolean().default(false),
|
|
652
|
+
sortable: z9.boolean().default(false),
|
|
653
|
+
defaultSort: z9.boolean().default(false),
|
|
654
|
+
searchable: z9.boolean().default(false),
|
|
655
|
+
filterable: z9.boolean().default(false),
|
|
656
|
+
createable: z9.boolean().default(true),
|
|
657
|
+
updateable: z9.boolean().default(true),
|
|
658
|
+
hideLabel: z9.boolean().default(false),
|
|
659
|
+
showWhen: WhenConditionSchema.optional(),
|
|
660
|
+
hideWhen: WhenConditionSchema.optional(),
|
|
661
|
+
disabledWhen: WhenConditionSchema.optional(),
|
|
662
|
+
displayKey: z9.string().optional(),
|
|
663
|
+
sortId: z9.string().optional(),
|
|
664
|
+
/**
|
|
665
|
+
* Name of a shared enum in the project enum registry (`crouton.enums.json`).
|
|
666
|
+
* At load time the loader injects that enum's `{ value, label }[]` into
|
|
667
|
+
* `fieldInput.options.values`, so columns don't duplicate the option list.
|
|
668
|
+
*/
|
|
669
|
+
enum: z9.string().optional(),
|
|
670
|
+
idField: z9.boolean().default(false),
|
|
671
|
+
showInLookup: z9.boolean().default(false),
|
|
672
|
+
columnType: z9.string().default("string"),
|
|
673
|
+
fieldInput: FieldInputSchema.optional(),
|
|
674
|
+
/**
|
|
675
|
+
* Path to another `resource.json` whose columns are expanded as nested sub-columns
|
|
676
|
+
* under this column's object key.
|
|
677
|
+
*
|
|
678
|
+
* Example: `"extend": "../internalAuthor/resource.json"` on a column `author`
|
|
679
|
+
* auto-generates virtual sub-columns like `author_name` (column: "author", displayKey: "name").
|
|
680
|
+
*
|
|
681
|
+
* Visibility (`hiddenInTable/Form/View`) on this column is inherited by all sub-columns as a
|
|
682
|
+
* default; the referenced resource's own column visibility further restricts it.
|
|
683
|
+
*/
|
|
684
|
+
extend: z9.string().optional(),
|
|
685
|
+
/**
|
|
686
|
+
* Per-sub-column overrides when using `extend`.
|
|
687
|
+
* Key: the virtual column id (`"{extendId}_{refColId}"`) or just the referenced column id.
|
|
688
|
+
* Value: any `JsonColumn` fields to merge over the generated virtual column.
|
|
689
|
+
*/
|
|
690
|
+
columns: z9.record(z9.string(), z9.record(z9.string(), z9.unknown())).optional()
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
// ../crouton-core/src/lib/resource/Sidebar.schema.ts
|
|
694
|
+
import z10 from "zod";
|
|
695
|
+
var SidebarGroupSchema2 = z10.object({
|
|
696
|
+
/** Human-readable heading shown in the sidebar. Defaults to a title-cased version of the slug. */
|
|
697
|
+
label: z10.string().optional(),
|
|
698
|
+
/** Controls the order of this group among top-level sidebar items. */
|
|
699
|
+
position: z10.string().optional()
|
|
700
|
+
});
|
|
701
|
+
var SidebarSchema = z10.object({
|
|
702
|
+
hide: z10.boolean().default(false),
|
|
703
|
+
position: z10.number().optional(),
|
|
704
|
+
label: z10.string().optional(),
|
|
705
|
+
/**
|
|
706
|
+
* Slug of the group this resource belongs to.
|
|
707
|
+
* Must match a key in `sidebarGroups` in `crouton.json`.
|
|
708
|
+
* Resources with the same `group` are nested under a shared collapsible section.
|
|
709
|
+
*/
|
|
710
|
+
group: z10.string().optional()
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
// ../crouton-core/src/lib/resource/TableAction.schema.ts
|
|
714
|
+
import { z as z11 } from "zod";
|
|
715
|
+
var ActionConditionSchema = z11.object({
|
|
716
|
+
/** Row field to evaluate. */
|
|
717
|
+
field: z11.string(),
|
|
718
|
+
/**
|
|
719
|
+
* Comparison operator. Defaults to `"eq"`.
|
|
720
|
+
* - `eq` / `neq` — strict equality
|
|
721
|
+
* - `gt` / `gte` / `lt` / `lte` — numeric or date comparison
|
|
722
|
+
* - `exists` — field is not null / undefined / empty string
|
|
723
|
+
* - `notExists` — field is null / undefined / empty string
|
|
724
|
+
*/
|
|
725
|
+
op: z11.enum([
|
|
726
|
+
"eq",
|
|
727
|
+
"neq",
|
|
728
|
+
"gt",
|
|
729
|
+
"gte",
|
|
730
|
+
"lt",
|
|
731
|
+
"lte",
|
|
732
|
+
"exists",
|
|
733
|
+
"notExists"
|
|
734
|
+
]).default("eq"),
|
|
735
|
+
/** Comparison value. Not required for `exists` / `notExists`. */
|
|
736
|
+
value: z11.unknown().optional()
|
|
737
|
+
});
|
|
738
|
+
var ActionSchema = z11.object({
|
|
739
|
+
type: z11.string(),
|
|
740
|
+
/** Unique identifier for the action. */
|
|
741
|
+
id: z11.string(),
|
|
742
|
+
/** Human-readable button label. */
|
|
743
|
+
label: z11.string(),
|
|
744
|
+
/** MDI icon name, e.g. `"mdi:open-in-new"`. */
|
|
745
|
+
icon: z11.string().optional(),
|
|
746
|
+
/** Tooltip text. Falls back to `label` when omitted. */
|
|
747
|
+
tooltip: z11.string().optional(),
|
|
748
|
+
condition: ActionConditionSchema.optional()
|
|
749
|
+
});
|
|
750
|
+
var JsonProcedureActionSchema = ActionSchema.extend({
|
|
751
|
+
type: z11.literal("procedure").default("procedure"),
|
|
752
|
+
/**
|
|
753
|
+
* Filename (without extension) inside the resource's `actions/` directory
|
|
754
|
+
* that exports the table-action procedure, e.g. `"syncZotero"`.
|
|
755
|
+
*/
|
|
756
|
+
procedure: z11.string(),
|
|
757
|
+
/** HTTP method for the frontend. Defaults to `"post"`. */
|
|
758
|
+
method: z11.string().optional().default("post"),
|
|
759
|
+
/** Static query / body params passed to the endpoint. */
|
|
760
|
+
data: z11.record(z11.string(), z11.unknown()).optional()
|
|
761
|
+
});
|
|
762
|
+
var JsonLinkActionSchema = ActionSchema.extend({
|
|
763
|
+
/** Optional condition evaluated per row. Button is hidden when the condition is false. */
|
|
764
|
+
type: z11.literal("link").default("link"),
|
|
765
|
+
/** URL to open. May contain `{env.VAR}` placeholders. */
|
|
766
|
+
href: z11.string()
|
|
767
|
+
});
|
|
768
|
+
var transformAction = /* @__PURE__ */ __name((action) => {
|
|
769
|
+
const label = action.label;
|
|
770
|
+
return {
|
|
771
|
+
tooltip: label,
|
|
772
|
+
...action
|
|
773
|
+
};
|
|
774
|
+
}, "transformAction");
|
|
775
|
+
var JsonActionSchema = z11.union([
|
|
776
|
+
JsonProcedureActionSchema,
|
|
777
|
+
JsonLinkActionSchema
|
|
778
|
+
]).transform(transformAction);
|
|
779
|
+
|
|
780
|
+
// ../crouton-core/src/lib/resource/include.schema.ts
|
|
781
|
+
import { z as z12 } from "zod";
|
|
782
|
+
var JsonIncludeEntrySchema = z12.lazy(() => z12.union([
|
|
783
|
+
z12.string(),
|
|
784
|
+
z12.object({
|
|
785
|
+
relation: z12.string(),
|
|
786
|
+
include: z12.array(JsonIncludeEntrySchema).optional(),
|
|
787
|
+
/** Prisma-format orderBy clause applied to the included records. */
|
|
788
|
+
orderBy: z12.record(z12.string(), z12.unknown()).optional()
|
|
789
|
+
})
|
|
790
|
+
]));
|
|
791
|
+
|
|
792
|
+
// ../crouton-core/src/lib/resource/ResourceJson.schema.ts
|
|
793
|
+
var JsonColumnsMapSchema = z13.record(z13.string(), JsonColumnSchema.omit({
|
|
794
|
+
id: true
|
|
795
|
+
}).catchall(z13.unknown()));
|
|
796
|
+
var ColumnsSchema = JsonColumnsMapSchema;
|
|
797
|
+
var JsonDisplaySchema = z13.object({
|
|
798
|
+
mode: z13.enum([
|
|
799
|
+
"page",
|
|
800
|
+
"modal"
|
|
801
|
+
]).default("modal"),
|
|
802
|
+
customComponent: z13.string().nullable().optional().default(null)
|
|
803
|
+
});
|
|
804
|
+
var normalizeColumns = /* @__PURE__ */ __name((columns) => {
|
|
805
|
+
if (!columns) return void 0;
|
|
806
|
+
const raw = Array.isArray(columns) ? columns : Object.entries(columns).map(([id, col]) => ({
|
|
807
|
+
id,
|
|
808
|
+
...col
|
|
809
|
+
}));
|
|
810
|
+
return raw.map((col) => ({
|
|
811
|
+
...col,
|
|
812
|
+
label: col.label ?? labelFromId(col.id)
|
|
813
|
+
}));
|
|
814
|
+
}, "normalizeColumns");
|
|
815
|
+
var ResourceJsonShape = z13.object({
|
|
816
|
+
name: z13.string(),
|
|
817
|
+
route: z13.string(),
|
|
818
|
+
model: z13.string(),
|
|
819
|
+
tag: z13.string(),
|
|
820
|
+
title: z13.string().optional(),
|
|
821
|
+
table: z13.string().optional(),
|
|
822
|
+
database: z13.string().optional(),
|
|
823
|
+
sidebar: SidebarSchema.default(SidebarSchema.parse({})),
|
|
824
|
+
display: JsonDisplaySchema.default(JsonDisplaySchema.parse({})),
|
|
825
|
+
operations: JsonOperationsSchema,
|
|
826
|
+
columns: ColumnsSchema.default(ColumnsSchema.parse({})),
|
|
827
|
+
calculatedColumns: z13.array(CalculatedColumnSchema).default([]),
|
|
828
|
+
actions: z13.array(JsonActionSchema).default([]),
|
|
829
|
+
/** Global table-level actions (no record id). Shown as toolbar buttons. */
|
|
830
|
+
tableActions: z13.array(JsonActionSchema).default([]),
|
|
831
|
+
/** Modal width when opening a form for this resource. */
|
|
832
|
+
modalSize: z13.enum([
|
|
833
|
+
"xs",
|
|
834
|
+
"sm",
|
|
835
|
+
"lg",
|
|
836
|
+
"xl"
|
|
837
|
+
]).default("sm"),
|
|
838
|
+
/**
|
|
839
|
+
* Relations to include when querying this resource.
|
|
840
|
+
* Each entry is either a plain relation name (`"author"` → `include: { author: true }`)
|
|
841
|
+
* or an object for nested includes:
|
|
842
|
+
* `{ "relation": "text_author", "include": ["author"] }` →
|
|
843
|
+
* `include: { text_author: { include: { author: true } } }`
|
|
844
|
+
*/
|
|
845
|
+
include: z13.array(JsonIncludeEntrySchema).default([])
|
|
846
|
+
});
|
|
847
|
+
var ResourceJsonSchema = ResourceJsonShape.transform((obj) => {
|
|
848
|
+
const title = obj.title ?? labelFromId(obj.name);
|
|
849
|
+
return {
|
|
850
|
+
title,
|
|
851
|
+
...obj,
|
|
852
|
+
columns: normalizeColumns(obj.columns)
|
|
853
|
+
};
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
// ../crouton-core/src/lib/config/CroutonConfig.schema.ts
|
|
857
|
+
import { z as z14 } from "zod";
|
|
858
|
+
var RulesetSchema = z14.object({
|
|
859
|
+
hideIdInTable: z14.boolean().default(true),
|
|
860
|
+
hideIdInForm: z14.boolean().default(true),
|
|
861
|
+
hideIdInView: z14.boolean().default(true),
|
|
862
|
+
hideTimestamps: z14.boolean().default(true),
|
|
863
|
+
hideForeignKeys: z14.boolean().default(true),
|
|
864
|
+
includeRelations: z14.boolean().default(false),
|
|
865
|
+
hideRelationsInTable: z14.boolean().default(true),
|
|
866
|
+
showRelationsInForm: z14.boolean().default(true),
|
|
867
|
+
enumValueLabel: z14.boolean().default(true),
|
|
868
|
+
sharedEnums: z14.boolean().default(true),
|
|
869
|
+
defaultOperations: JsonOperationsSchema.default(JsonOperationsSchema.parse({}))
|
|
870
|
+
});
|
|
871
|
+
var CroutonConfigSchema = z14.object({
|
|
872
|
+
/**
|
|
873
|
+
* Application title served to the frontend via `GET /_app/layout`.
|
|
874
|
+
* Displayed in the admin sidebar header.
|
|
875
|
+
*/
|
|
876
|
+
title: z14.string(),
|
|
877
|
+
/** Where resource directories live, relative to the project root. */
|
|
878
|
+
resourcesDir: z14.string(),
|
|
879
|
+
/** Where datasource folders live (each with a `data-source.json`). */
|
|
880
|
+
dataSourcesDir: z14.string(),
|
|
881
|
+
/**
|
|
882
|
+
* Template for a model's Zod export name. `{Model}` → Prisma model name.
|
|
883
|
+
* Defaults to `{Model}WithRelationsSchema` (the relations-aware schema
|
|
884
|
+
* emitted by zod-prisma-types when `createRelationValuesTypes` is on).
|
|
885
|
+
*/
|
|
886
|
+
schemaExportName: z14.string().default("{Model}WithRelationsSchema"),
|
|
887
|
+
/** Path to the shared enum registry, relative to project root. Default `crouton.enums.json`. */
|
|
888
|
+
enumsFile: z14.string().default("croutons.enums.json"),
|
|
889
|
+
/** Optional overrides of the default visibility ruleset. */
|
|
890
|
+
rules: RulesetSchema.default(RulesetSchema.parse({})),
|
|
891
|
+
/**
|
|
892
|
+
* Sidebar group definitions, keyed by group slug (e.g. `"metadata"`).
|
|
893
|
+
* Resources reference a group via `sidebar.group` in their `resource.json`.
|
|
894
|
+
*/
|
|
895
|
+
sidebarGroups: z14.record(z14.string(), SidebarGroupSchema2).default({}),
|
|
896
|
+
/**
|
|
897
|
+
* Whether form fields are saved automatically as the user edits them.
|
|
898
|
+
* @default true
|
|
899
|
+
*/
|
|
900
|
+
autoSave: z14.boolean().default(true)
|
|
901
|
+
});
|
|
902
|
+
|
|
903
|
+
// ../crouton-core/src/lib/config/readConfig.ts
|
|
904
|
+
var CONFIG_FILES = [
|
|
905
|
+
"crouton.json",
|
|
906
|
+
"crouton.mjs",
|
|
907
|
+
"crouton.js"
|
|
908
|
+
];
|
|
909
|
+
|
|
910
|
+
// src/lib/crud/app-layout/app-layout.builder.ts
|
|
911
|
+
var byPosition = /* @__PURE__ */ __name((a, b) => {
|
|
912
|
+
if (a.position != null && b.position != null) return a.position - b.position;
|
|
913
|
+
if (a.position != null) return -1;
|
|
914
|
+
if (b.position != null) return 1;
|
|
915
|
+
return a.label.localeCompare(b.label);
|
|
916
|
+
}, "byPosition");
|
|
917
|
+
var buildLayoutPayload = /* @__PURE__ */ __name((configs, sidebarGroups = {}, title, autoSave = true) => {
|
|
918
|
+
const visible = configs.filter((c) => c.sidebar?.hide !== true && c.views?.["table"]);
|
|
919
|
+
const topLevel = [];
|
|
920
|
+
const groupMap = new Map(Object.entries(sidebarGroups).map(([slug, cfg]) => [
|
|
921
|
+
slug,
|
|
922
|
+
{
|
|
923
|
+
label: cfg.label ?? labelFromId(slug),
|
|
924
|
+
position: cfg.position,
|
|
925
|
+
children: []
|
|
926
|
+
}
|
|
927
|
+
]));
|
|
928
|
+
for (const c of visible) {
|
|
929
|
+
const leaf = SidebarLeafSchema.parse({
|
|
930
|
+
id: c.name,
|
|
931
|
+
label: c.sidebar?.label ?? c.title ?? c.tag,
|
|
932
|
+
position: c.sidebar?.position
|
|
933
|
+
});
|
|
934
|
+
const groupSlug = c.sidebar?.group;
|
|
935
|
+
if (groupSlug) {
|
|
936
|
+
if (!groupMap.has(groupSlug)) {
|
|
937
|
+
groupMap.set(groupSlug, {
|
|
938
|
+
label: labelFromId(groupSlug),
|
|
939
|
+
children: []
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
groupMap.get(groupSlug).children.push(leaf);
|
|
943
|
+
} else {
|
|
944
|
+
topLevel.push(leaf);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
const groups = [
|
|
948
|
+
...groupMap.entries()
|
|
949
|
+
].filter(([, g]) => g.children.length > 0).map(([id, g]) => ({
|
|
950
|
+
kind: "group",
|
|
951
|
+
id,
|
|
952
|
+
label: g.label,
|
|
953
|
+
position: g.position,
|
|
954
|
+
children: g.children.sort(byPosition)
|
|
955
|
+
}));
|
|
956
|
+
const sidebar = [
|
|
957
|
+
...topLevel,
|
|
958
|
+
...groups
|
|
959
|
+
].sort(byPosition);
|
|
960
|
+
return {
|
|
961
|
+
sidebar,
|
|
962
|
+
title,
|
|
963
|
+
autoSave
|
|
964
|
+
};
|
|
965
|
+
}, "buildLayoutPayload");
|
|
966
|
+
|
|
967
|
+
// src/lib/crud/app-layout/app-layout.controller.ts
|
|
968
|
+
import { Controller, Get } from "@nestjs/common";
|
|
969
|
+
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
|
|
970
|
+
|
|
463
971
|
// src/lib/crud/dev-mode.ts
|
|
464
972
|
var IS_DEV = process.env["NODE_ENV"] !== "production";
|
|
465
973
|
|
|
@@ -508,7 +1016,7 @@ ResourceConfigRegistry = _ts_decorate([
|
|
|
508
1016
|
])
|
|
509
1017
|
], ResourceConfigRegistry);
|
|
510
1018
|
|
|
511
|
-
// src/lib/crud/app-layout.controller.ts
|
|
1019
|
+
// src/lib/crud/app-layout/app-layout.controller.ts
|
|
512
1020
|
function _ts_decorate2(decorators, target, key, desc2) {
|
|
513
1021
|
var c = arguments.length, r = c < 3 ? target : desc2 === null ? desc2 = Object.getOwnPropertyDescriptor(target, key) : desc2, d;
|
|
514
1022
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc2);
|
|
@@ -520,62 +1028,6 @@ function _ts_metadata2(k, v) {
|
|
|
520
1028
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
521
1029
|
}
|
|
522
1030
|
__name(_ts_metadata2, "_ts_metadata");
|
|
523
|
-
var byPosition = /* @__PURE__ */ __name((a, b) => {
|
|
524
|
-
if (a.position != null && b.position != null) return a.position - b.position;
|
|
525
|
-
if (a.position != null) return -1;
|
|
526
|
-
if (b.position != null) return 1;
|
|
527
|
-
return a.label.localeCompare(b.label);
|
|
528
|
-
}, "byPosition");
|
|
529
|
-
var buildLayoutPayload = /* @__PURE__ */ __name((configs, sidebarGroups = {}, title, autoSave = true) => {
|
|
530
|
-
const visible = configs.filter((c) => c.sidebar?.hide !== true && c.views?.["table"]);
|
|
531
|
-
const topLevel = [];
|
|
532
|
-
const groupMap = new Map(Object.entries(sidebarGroups).map(([slug, cfg]) => [
|
|
533
|
-
slug,
|
|
534
|
-
{
|
|
535
|
-
label: cfg.label ?? labelFromId(slug),
|
|
536
|
-
position: cfg.position,
|
|
537
|
-
children: []
|
|
538
|
-
}
|
|
539
|
-
]));
|
|
540
|
-
for (const c of visible) {
|
|
541
|
-
const leaf = {
|
|
542
|
-
kind: "item",
|
|
543
|
-
id: c.name,
|
|
544
|
-
label: c.sidebar?.label ?? c.title ?? c.tag,
|
|
545
|
-
position: c.sidebar?.position
|
|
546
|
-
};
|
|
547
|
-
const groupSlug = c.sidebar?.group;
|
|
548
|
-
if (groupSlug) {
|
|
549
|
-
if (!groupMap.has(groupSlug)) {
|
|
550
|
-
groupMap.set(groupSlug, {
|
|
551
|
-
label: labelFromId(groupSlug),
|
|
552
|
-
children: []
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
groupMap.get(groupSlug).children.push(leaf);
|
|
556
|
-
} else {
|
|
557
|
-
topLevel.push(leaf);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
const groups = [
|
|
561
|
-
...groupMap.entries()
|
|
562
|
-
].filter(([, g]) => g.children.length > 0).map(([id, g]) => ({
|
|
563
|
-
kind: "group",
|
|
564
|
-
id,
|
|
565
|
-
label: g.label,
|
|
566
|
-
position: g.position,
|
|
567
|
-
children: g.children.sort(byPosition)
|
|
568
|
-
}));
|
|
569
|
-
const sidebar = [
|
|
570
|
-
...topLevel,
|
|
571
|
-
...groups
|
|
572
|
-
].sort(byPosition);
|
|
573
|
-
return {
|
|
574
|
-
sidebar,
|
|
575
|
-
title,
|
|
576
|
-
autoSave
|
|
577
|
-
};
|
|
578
|
-
}, "buildLayoutPayload");
|
|
579
1031
|
var createAppLayoutController = /* @__PURE__ */ __name((configs, sidebarGroups = {}, title, autoSave = true) => {
|
|
580
1032
|
const layoutPayload = buildLayoutPayload(configs, sidebarGroups, title, autoSave);
|
|
581
1033
|
let AppLayoutController = class AppLayoutController {
|
|
@@ -621,6 +1073,45 @@ var createAppLayoutController = /* @__PURE__ */ __name((configs, sidebarGroups =
|
|
|
621
1073
|
return AppLayoutController;
|
|
622
1074
|
}, "createAppLayoutController");
|
|
623
1075
|
|
|
1076
|
+
// src/lib/crud/config/read.ts
|
|
1077
|
+
import { access, readFile } from "fs/promises";
|
|
1078
|
+
import { dirname, join, resolve, resolve as pathResolve } from "path";
|
|
1079
|
+
var fileExists = /* @__PURE__ */ __name(async (p) => {
|
|
1080
|
+
try {
|
|
1081
|
+
await access(p);
|
|
1082
|
+
return true;
|
|
1083
|
+
} catch {
|
|
1084
|
+
return false;
|
|
1085
|
+
}
|
|
1086
|
+
}, "fileExists");
|
|
1087
|
+
var findConfigPath = /* @__PURE__ */ __name(async (cwd) => {
|
|
1088
|
+
let dir = resolve(cwd);
|
|
1089
|
+
while (true) {
|
|
1090
|
+
for (const name of CONFIG_FILES) {
|
|
1091
|
+
const candidate = join(dir, name);
|
|
1092
|
+
if (await fileExists(candidate)) return candidate;
|
|
1093
|
+
}
|
|
1094
|
+
const parent = dirname(dir);
|
|
1095
|
+
if (parent === dir) return void 0;
|
|
1096
|
+
dir = parent;
|
|
1097
|
+
}
|
|
1098
|
+
}, "findConfigPath");
|
|
1099
|
+
var loadConfig = /* @__PURE__ */ __name(async () => {
|
|
1100
|
+
const cwd = pathResolve(process.cwd());
|
|
1101
|
+
const path = await findConfigPath(cwd);
|
|
1102
|
+
if (!path) {
|
|
1103
|
+
throw new Error(`No crouton config found (looked for ${CONFIG_FILES.join(", ")} up from ${cwd}).`);
|
|
1104
|
+
}
|
|
1105
|
+
let config;
|
|
1106
|
+
if (path.endsWith(".json")) {
|
|
1107
|
+
config = JSON.parse(await readFile(path, "utf-8"));
|
|
1108
|
+
} else {
|
|
1109
|
+
const mod = await import(path);
|
|
1110
|
+
config = mod.default ?? mod;
|
|
1111
|
+
}
|
|
1112
|
+
return CroutonConfigSchema.parse(config);
|
|
1113
|
+
}, "loadConfig");
|
|
1114
|
+
|
|
624
1115
|
// src/lib/crud/crouton-validation.filter.ts
|
|
625
1116
|
import { Catch } from "@nestjs/common";
|
|
626
1117
|
|
|
@@ -662,24 +1153,156 @@ CroutonValidationExceptionFilter = _ts_decorate3([
|
|
|
662
1153
|
], CroutonValidationExceptionFilter);
|
|
663
1154
|
|
|
664
1155
|
// src/lib/crud/crud-controller.factory.ts
|
|
665
|
-
import { Controller as Controller2 } from "@nestjs/common";
|
|
666
|
-
import { Body as Body2 } from "@nestjs/common";
|
|
1156
|
+
import { Body as Body2, Controller as Controller2 } from "@nestjs/common";
|
|
667
1157
|
import { ApiTags as ApiTags2 } from "@nestjs/swagger";
|
|
668
1158
|
|
|
669
|
-
// src/lib/crud/
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
1159
|
+
// src/lib/crud/action/action.types.ts
|
|
1160
|
+
import { z as z15 } from "zod";
|
|
1161
|
+
var ActionMetadataSchema = z15.object({
|
|
1162
|
+
/** URL segment used in the endpoint. */
|
|
1163
|
+
id: z15.string(),
|
|
1164
|
+
/** Human-readable label shown as a button. */
|
|
1165
|
+
label: z15.string().optional(),
|
|
1166
|
+
/** MDI icon name, e.g. `"mdi:open-in-new"`. */
|
|
1167
|
+
icon: z15.string().optional(),
|
|
1168
|
+
/** Tooltip text. Falls back to `label` when omitted. */
|
|
1169
|
+
tooltip: z15.string().optional(),
|
|
1170
|
+
/** Per-row condition — button is hidden when false. */
|
|
1171
|
+
condition: z15.custom().optional()
|
|
1172
|
+
});
|
|
1173
|
+
var ResourceLinkActionSchema = ActionMetadataSchema.extend({
|
|
1174
|
+
type: z15.literal("link"),
|
|
1175
|
+
/** URL to open. May contain `{id}` or `{env.VAR}` placeholders. */
|
|
1176
|
+
href: z15.string()
|
|
1177
|
+
});
|
|
1178
|
+
var ResourceRowProcedureActionSchema = ActionMetadataSchema.extend({
|
|
1179
|
+
type: z15.literal("procedure").optional(),
|
|
1180
|
+
/** HTTP method for the endpoint. Defaults to `"post"`. */
|
|
1181
|
+
method: z15.string().optional(),
|
|
1182
|
+
/** Static data payload merged into the request body by the frontend. */
|
|
1183
|
+
data: z15.record(z15.string(), z15.unknown()).optional(),
|
|
1184
|
+
/** Procedure called with `(prisma, recordId)`. */
|
|
1185
|
+
procedure: z15.custom((v) => typeof v === "function")
|
|
1186
|
+
});
|
|
1187
|
+
var ResourceTableProcedureActionSchema = ActionMetadataSchema.extend({
|
|
1188
|
+
type: z15.literal("procedure").optional(),
|
|
1189
|
+
/** HTTP method for the endpoint. Defaults to `"post"`. */
|
|
1190
|
+
method: z15.string().optional(),
|
|
1191
|
+
/** Static data payload merged into the request body by the frontend. */
|
|
1192
|
+
data: z15.record(z15.string(), z15.unknown()).optional(),
|
|
1193
|
+
/** Procedure called with `(prisma)` — no record id. */
|
|
1194
|
+
procedure: z15.custom((v) => typeof v === "function")
|
|
1195
|
+
});
|
|
1196
|
+
var ResourceRowActionSchema = z15.union([
|
|
1197
|
+
ResourceRowProcedureActionSchema,
|
|
1198
|
+
ResourceLinkActionSchema
|
|
1199
|
+
]);
|
|
1200
|
+
var ResourceTableActionSchema = z15.union([
|
|
1201
|
+
ResourceTableProcedureActionSchema,
|
|
1202
|
+
ResourceLinkActionSchema
|
|
1203
|
+
]);
|
|
1204
|
+
var isRowProcedureAction = /* @__PURE__ */ __name((action) => action.type !== "link", "isRowProcedureAction");
|
|
1205
|
+
var isTableProcedureAction = /* @__PURE__ */ __name((action) => action.type !== "link", "isTableProcedureAction");
|
|
681
1206
|
|
|
682
|
-
// src/lib/crud/
|
|
1207
|
+
// src/lib/crud/loader/module.loader.ts
|
|
1208
|
+
import { existsSync } from "fs";
|
|
1209
|
+
import { createRequire } from "module";
|
|
1210
|
+
import { join as join2 } from "path";
|
|
1211
|
+
var _require = createRequire(import.meta.url ?? __filename);
|
|
1212
|
+
var findModule = /* @__PURE__ */ __name((dir, name) => {
|
|
1213
|
+
for (const ext of [
|
|
1214
|
+
".ts",
|
|
1215
|
+
".js"
|
|
1216
|
+
]) {
|
|
1217
|
+
const p = join2(dir, `${name}${ext}`);
|
|
1218
|
+
if (existsSync(p)) return p;
|
|
1219
|
+
}
|
|
1220
|
+
return void 0;
|
|
1221
|
+
}, "findModule");
|
|
1222
|
+
var IS_VITE = typeof globalThis.__vite_ssr_import__ === "function";
|
|
1223
|
+
var importDefault = /* @__PURE__ */ __name(async (filePath) => {
|
|
1224
|
+
try {
|
|
1225
|
+
if (IS_VITE) {
|
|
1226
|
+
const importPath = IS_DEV ? `${filePath}?t=${Date.now()}` : filePath;
|
|
1227
|
+
const mod = await import(importPath);
|
|
1228
|
+
return mod.default ?? mod;
|
|
1229
|
+
} else {
|
|
1230
|
+
const mod = _require(filePath);
|
|
1231
|
+
return mod.default;
|
|
1232
|
+
}
|
|
1233
|
+
} catch {
|
|
1234
|
+
return void 0;
|
|
1235
|
+
}
|
|
1236
|
+
}, "importDefault");
|
|
1237
|
+
|
|
1238
|
+
// src/lib/crud/action/action.loader.ts
|
|
1239
|
+
import { join as join3 } from "path";
|
|
1240
|
+
var loadActions = /* @__PURE__ */ __name(async (jsonActions, basePath, scope) => {
|
|
1241
|
+
const tag = scope === "row" ? "actions" : "tableActions";
|
|
1242
|
+
const results = [];
|
|
1243
|
+
for (const action of jsonActions) {
|
|
1244
|
+
if (action.type === "link") {
|
|
1245
|
+
results.push({
|
|
1246
|
+
type: "link",
|
|
1247
|
+
id: action.id,
|
|
1248
|
+
label: action.label,
|
|
1249
|
+
href: action.href,
|
|
1250
|
+
...action.icon && {
|
|
1251
|
+
icon: action.icon
|
|
1252
|
+
},
|
|
1253
|
+
...action.tooltip && {
|
|
1254
|
+
tooltip: action.tooltip
|
|
1255
|
+
},
|
|
1256
|
+
...action.condition && {
|
|
1257
|
+
condition: action.condition
|
|
1258
|
+
}
|
|
1259
|
+
});
|
|
1260
|
+
continue;
|
|
1261
|
+
}
|
|
1262
|
+
const file = findModule(join3(basePath, "actions"), action.procedure);
|
|
1263
|
+
if (!file) {
|
|
1264
|
+
console.warn(`[${tag}] Procedure file not found for "${action.id}" in ${basePath}/actions/`);
|
|
1265
|
+
continue;
|
|
1266
|
+
}
|
|
1267
|
+
const mod = await importDefault(file);
|
|
1268
|
+
if (!mod) {
|
|
1269
|
+
console.warn(`[${tag}] No default export in ${file}`);
|
|
1270
|
+
continue;
|
|
1271
|
+
}
|
|
1272
|
+
results.push({
|
|
1273
|
+
id: action.id,
|
|
1274
|
+
label: action.label,
|
|
1275
|
+
method: action.method,
|
|
1276
|
+
data: action.data,
|
|
1277
|
+
...action.icon && {
|
|
1278
|
+
icon: action.icon
|
|
1279
|
+
},
|
|
1280
|
+
...action.tooltip && {
|
|
1281
|
+
tooltip: action.tooltip
|
|
1282
|
+
},
|
|
1283
|
+
...action.condition && {
|
|
1284
|
+
condition: action.condition
|
|
1285
|
+
},
|
|
1286
|
+
procedure: mod
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
return results;
|
|
1290
|
+
}, "loadActions");
|
|
1291
|
+
|
|
1292
|
+
// src/lib/crud/crud.config.ts
|
|
1293
|
+
var resolveDefinition = /* @__PURE__ */ __name((config) => {
|
|
1294
|
+
const def2 = config.definition;
|
|
1295
|
+
return typeof def2 === "function" ? def2() : def2;
|
|
1296
|
+
}, "resolveDefinition");
|
|
1297
|
+
var isOperationEnabled = /* @__PURE__ */ __name((def2, op) => def2[op] != null, "isOperationEnabled");
|
|
1298
|
+
var schemaFor = /* @__PURE__ */ __name((def2, op) => {
|
|
1299
|
+
const entry = def2[op];
|
|
1300
|
+
if (!entry || entry === true) return void 0;
|
|
1301
|
+
return entry.schema;
|
|
1302
|
+
}, "schemaFor");
|
|
1303
|
+
var upsertOnFor = /* @__PURE__ */ __name((def2) => def2.upsert?.upsertOn, "upsertOnFor");
|
|
1304
|
+
|
|
1305
|
+
// src/lib/crud/read.repository.ts
|
|
683
1306
|
import { NotFoundException } from "@nestjs/common";
|
|
684
1307
|
|
|
685
1308
|
// src/lib/crud/sql.helpers.ts
|
|
@@ -1165,9 +1788,9 @@ var ReadRepository = class {
|
|
|
1165
1788
|
};
|
|
1166
1789
|
|
|
1167
1790
|
// src/lib/crud/schema.utils.ts
|
|
1168
|
-
import { ZodObject, toJSONSchema as toJSONSchema2, z as
|
|
1791
|
+
import { ZodObject, toJSONSchema as toJSONSchema2, z as z16 } from "zod";
|
|
1169
1792
|
var dateOverride = /* @__PURE__ */ __name(({ zodSchema, jsonSchema }) => {
|
|
1170
|
-
if (zodSchema instanceof
|
|
1793
|
+
if (zodSchema instanceof z16.ZodDate) {
|
|
1171
1794
|
jsonSchema.type = "string";
|
|
1172
1795
|
jsonSchema.format = "date-time";
|
|
1173
1796
|
}
|
|
@@ -1566,21 +2189,27 @@ DataSourceRegistry = _ts_decorate4([
|
|
|
1566
2189
|
], DataSourceRegistry);
|
|
1567
2190
|
|
|
1568
2191
|
// src/lib/crud/data-source/data-source.loader.ts
|
|
1569
|
-
import { existsSync, readFileSync, readdirSync } from "fs";
|
|
1570
|
-
import { join } from "path";
|
|
2192
|
+
import { existsSync as existsSync2, readFileSync, readdirSync } from "fs";
|
|
2193
|
+
import { join as join4 } from "path";
|
|
1571
2194
|
var loadDataSourcesFromDir = /* @__PURE__ */ __name(async (dirPath) => {
|
|
1572
|
-
if (!
|
|
2195
|
+
if (!existsSync2(dirPath)) return [];
|
|
1573
2196
|
const entries = readdirSync(dirPath, {
|
|
1574
2197
|
withFileTypes: true
|
|
1575
2198
|
});
|
|
1576
2199
|
const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
1577
2200
|
const results = [];
|
|
1578
2201
|
for (const dir of dirs) {
|
|
1579
|
-
const basePath =
|
|
1580
|
-
const jsonFile =
|
|
1581
|
-
if (!
|
|
1582
|
-
const
|
|
1583
|
-
const
|
|
2202
|
+
const basePath = join4(dirPath, dir);
|
|
2203
|
+
const jsonFile = join4(basePath, "data-source.json");
|
|
2204
|
+
if (!existsSync2(jsonFile)) continue;
|
|
2205
|
+
const _config = JSON.parse(readFileSync(jsonFile, "utf-8"));
|
|
2206
|
+
const datasource = DataSourceSchema.safeParse(_config);
|
|
2207
|
+
if (!datasource.success) {
|
|
2208
|
+
console.error(datasource.error);
|
|
2209
|
+
throw new Error(`Invalid datasource schema: ${jsonFile}`);
|
|
2210
|
+
}
|
|
2211
|
+
const config = datasource.data;
|
|
2212
|
+
const indexFile = findModule2(basePath, "index");
|
|
1584
2213
|
if (!indexFile) continue;
|
|
1585
2214
|
const mod = await import(indexFile);
|
|
1586
2215
|
const client = mod.default;
|
|
@@ -1592,13 +2221,13 @@ var loadDataSourcesFromDir = /* @__PURE__ */ __name(async (dirPath) => {
|
|
|
1592
2221
|
}
|
|
1593
2222
|
return results;
|
|
1594
2223
|
}, "loadDataSourcesFromDir");
|
|
1595
|
-
var
|
|
2224
|
+
var findModule2 = /* @__PURE__ */ __name((dir, name) => {
|
|
1596
2225
|
for (const ext of [
|
|
1597
2226
|
".ts",
|
|
1598
2227
|
".js"
|
|
1599
2228
|
]) {
|
|
1600
|
-
const p =
|
|
1601
|
-
if (
|
|
2229
|
+
const p = join4(dir, `${name}${ext}`);
|
|
2230
|
+
if (existsSync2(p)) return p;
|
|
1602
2231
|
}
|
|
1603
2232
|
return void 0;
|
|
1604
2233
|
}, "findModule");
|
|
@@ -1621,7 +2250,7 @@ var desc = /* @__PURE__ */ __name((cls, method) => Object.getOwnPropertyDescript
|
|
|
1621
2250
|
var registerActionRoutes = /* @__PURE__ */ __name((ctx) => {
|
|
1622
2251
|
const { cls, config } = ctx;
|
|
1623
2252
|
const { name } = config;
|
|
1624
|
-
const procedureActions = (config.actions ?? []).filter(
|
|
2253
|
+
const procedureActions = (config.actions ?? []).filter(isRowProcedureAction);
|
|
1625
2254
|
for (const action of procedureActions) {
|
|
1626
2255
|
const methodName = `procedure_${action.id}`;
|
|
1627
2256
|
def(cls, methodName, async function(recordId) {
|
|
@@ -1646,7 +2275,7 @@ var registerActionRoutes = /* @__PURE__ */ __name((ctx) => {
|
|
|
1646
2275
|
var registerTableActionRoutes = /* @__PURE__ */ __name((ctx) => {
|
|
1647
2276
|
const { cls, config } = ctx;
|
|
1648
2277
|
const { name } = config;
|
|
1649
|
-
const procedureActions = (config.tableActions ?? []).filter(
|
|
2278
|
+
const procedureActions = (config.tableActions ?? []).filter(isTableProcedureAction);
|
|
1650
2279
|
for (const action of procedureActions) {
|
|
1651
2280
|
const methodName = `tableAction_${action.id}`;
|
|
1652
2281
|
def(cls, methodName, async function() {
|
|
@@ -1748,38 +2377,56 @@ var ZodValidationPipe = class {
|
|
|
1748
2377
|
};
|
|
1749
2378
|
|
|
1750
2379
|
// src/lib/crud/operations/register-crud.ts
|
|
2380
|
+
var findAll = /* @__PURE__ */ __name(async (repo, params, q, lookupLabel) => {
|
|
2381
|
+
const effectiveParams = {
|
|
2382
|
+
...params
|
|
2383
|
+
};
|
|
2384
|
+
if (q && lookupLabel) {
|
|
2385
|
+
effectiveParams.filter = [
|
|
2386
|
+
...params.filter ?? [],
|
|
2387
|
+
`${lookupLabel}:${q}`
|
|
2388
|
+
];
|
|
2389
|
+
}
|
|
2390
|
+
const [data, count] = await Promise.all([
|
|
2391
|
+
repo.findAll(effectiveParams),
|
|
2392
|
+
repo.count(effectiveParams.filter)
|
|
2393
|
+
]);
|
|
2394
|
+
const totalPages = Math.max(1, Math.ceil(count / params.pageSize));
|
|
2395
|
+
return {
|
|
2396
|
+
data,
|
|
2397
|
+
request: {
|
|
2398
|
+
count,
|
|
2399
|
+
page: params.page,
|
|
2400
|
+
pageSize: params.pageSize,
|
|
2401
|
+
totalPages,
|
|
2402
|
+
sort: params.sort,
|
|
2403
|
+
sortDir: params.sortDir,
|
|
2404
|
+
filter: params.filter
|
|
2405
|
+
}
|
|
2406
|
+
};
|
|
2407
|
+
}, "findAll");
|
|
2408
|
+
var findOne = /* @__PURE__ */ __name(async (repo, id) => {
|
|
2409
|
+
return repo.findOne(id);
|
|
2410
|
+
}, "findOne");
|
|
2411
|
+
var create = /* @__PURE__ */ __name(async (repo, body) => {
|
|
2412
|
+
return repo.create(body);
|
|
2413
|
+
}, "create");
|
|
2414
|
+
var update = /* @__PURE__ */ __name(async (repo, id, body) => {
|
|
2415
|
+
return repo.update(id, body);
|
|
2416
|
+
}, "update");
|
|
2417
|
+
var upsert = /* @__PURE__ */ __name(async (repo, body) => {
|
|
2418
|
+
return repo.upsert(body);
|
|
2419
|
+
}, "upsert");
|
|
2420
|
+
var del = /* @__PURE__ */ __name(async (repo, id) => {
|
|
2421
|
+
return repo.delete(id);
|
|
2422
|
+
}, "del");
|
|
1751
2423
|
var registerFindAll = /* @__PURE__ */ __name((ctx) => {
|
|
1752
2424
|
if (!isOperationEnabled(ctx.definition, "findAll")) return;
|
|
1753
2425
|
const { cls, config, listSchema } = ctx;
|
|
1754
2426
|
const { name } = config;
|
|
1755
2427
|
const lookupLabel = config.lookup?.label;
|
|
1756
2428
|
def(cls, "findAll", async function(params, q) {
|
|
1757
|
-
|
|
1758
|
-
...params
|
|
1759
|
-
};
|
|
1760
|
-
if (q && lookupLabel) {
|
|
1761
|
-
effectiveParams.filter = [
|
|
1762
|
-
...params.filter ?? [],
|
|
1763
|
-
`${lookupLabel}:${q}`
|
|
1764
|
-
];
|
|
1765
|
-
}
|
|
1766
|
-
const [data, count] = await Promise.all([
|
|
1767
|
-
this.repo.findAll(effectiveParams),
|
|
1768
|
-
this.repo.count(effectiveParams.filter)
|
|
1769
|
-
]);
|
|
1770
|
-
const totalPages = Math.max(1, Math.ceil(count / params.pageSize));
|
|
1771
|
-
return {
|
|
1772
|
-
data,
|
|
1773
|
-
request: {
|
|
1774
|
-
count,
|
|
1775
|
-
page: params.page,
|
|
1776
|
-
pageSize: params.pageSize,
|
|
1777
|
-
totalPages,
|
|
1778
|
-
sort: params.sort,
|
|
1779
|
-
sortDir: params.sortDir,
|
|
1780
|
-
filter: params.filter
|
|
1781
|
-
}
|
|
1782
|
-
};
|
|
2429
|
+
return findAll(this.repo, params, q, lookupLabel);
|
|
1783
2430
|
});
|
|
1784
2431
|
const d = desc(cls, "findAll");
|
|
1785
2432
|
Get2()(cls.prototype, "findAll", d);
|
|
@@ -1804,7 +2451,7 @@ var registerFindOne = /* @__PURE__ */ __name((ctx) => {
|
|
|
1804
2451
|
const { cls, config, oneSchema, idParamMeta } = ctx;
|
|
1805
2452
|
const { name } = config;
|
|
1806
2453
|
def(cls, "findOne", function(id) {
|
|
1807
|
-
return this.repo
|
|
2454
|
+
return findOne(this.repo, id);
|
|
1808
2455
|
});
|
|
1809
2456
|
const d = desc(cls, "findOne");
|
|
1810
2457
|
Get2(":id")(cls.prototype, "findOne", d);
|
|
@@ -1829,7 +2476,7 @@ var registerCreate = /* @__PURE__ */ __name((ctx) => {
|
|
|
1829
2476
|
const { cls, config, createSchema, bodyDecorator } = ctx;
|
|
1830
2477
|
const { name } = config;
|
|
1831
2478
|
def(cls, "create", function(body) {
|
|
1832
|
-
return this.repo
|
|
2479
|
+
return create(this.repo, body);
|
|
1833
2480
|
});
|
|
1834
2481
|
const d = desc(cls, "create");
|
|
1835
2482
|
Post2()(cls.prototype, "create", d);
|
|
@@ -1852,7 +2499,7 @@ var registerUpdate = /* @__PURE__ */ __name((ctx) => {
|
|
|
1852
2499
|
const { cls, config, updateSchema, idParamMeta, bodyDecorator } = ctx;
|
|
1853
2500
|
const { name } = config;
|
|
1854
2501
|
def(cls, "update", function(id, body) {
|
|
1855
|
-
return this.repo
|
|
2502
|
+
return update(this.repo, id, body);
|
|
1856
2503
|
});
|
|
1857
2504
|
const d = desc(cls, "update");
|
|
1858
2505
|
Patch(":id")(cls.prototype, "update", d);
|
|
@@ -1878,7 +2525,7 @@ var registerUpsert = /* @__PURE__ */ __name((ctx) => {
|
|
|
1878
2525
|
const { cls, config, upsertSchema, bodyDecorator } = ctx;
|
|
1879
2526
|
const { name } = config;
|
|
1880
2527
|
def(cls, "upsert", function(body) {
|
|
1881
|
-
return this.repo
|
|
2528
|
+
return upsert(this.repo, body);
|
|
1882
2529
|
});
|
|
1883
2530
|
const d = desc(cls, "upsert");
|
|
1884
2531
|
Put()(cls.prototype, "upsert", d);
|
|
@@ -1901,7 +2548,7 @@ var registerDelete = /* @__PURE__ */ __name((ctx) => {
|
|
|
1901
2548
|
const { cls, config, idParamMeta } = ctx;
|
|
1902
2549
|
const { name } = config;
|
|
1903
2550
|
def(cls, "delete", function(id) {
|
|
1904
|
-
return this.repo
|
|
2551
|
+
return del(this.repo, id);
|
|
1905
2552
|
});
|
|
1906
2553
|
const d = desc(cls, "delete");
|
|
1907
2554
|
Delete(":id")(cls.prototype, "delete", d);
|
|
@@ -2090,6 +2737,12 @@ var buildViewsPayload = /* @__PURE__ */ __name((config, baseUrl) => {
|
|
|
2090
2737
|
id: a.id,
|
|
2091
2738
|
label: a.label,
|
|
2092
2739
|
href: resolveEnvPlaceholders(a.href),
|
|
2740
|
+
...a.icon && {
|
|
2741
|
+
icon: a.icon
|
|
2742
|
+
},
|
|
2743
|
+
...a.tooltip && {
|
|
2744
|
+
tooltip: a.tooltip
|
|
2745
|
+
},
|
|
2093
2746
|
...a.condition && {
|
|
2094
2747
|
condition: a.condition
|
|
2095
2748
|
}
|
|
@@ -2101,6 +2754,12 @@ var buildViewsPayload = /* @__PURE__ */ __name((config, baseUrl) => {
|
|
|
2101
2754
|
...a.data && {
|
|
2102
2755
|
data: a.data
|
|
2103
2756
|
},
|
|
2757
|
+
...a.icon && {
|
|
2758
|
+
icon: a.icon
|
|
2759
|
+
},
|
|
2760
|
+
...a.tooltip && {
|
|
2761
|
+
tooltip: a.tooltip
|
|
2762
|
+
},
|
|
2104
2763
|
...a.condition && {
|
|
2105
2764
|
condition: a.condition
|
|
2106
2765
|
}
|
|
@@ -2113,7 +2772,10 @@ var buildViewsPayload = /* @__PURE__ */ __name((config, baseUrl) => {
|
|
|
2113
2772
|
label: a.label,
|
|
2114
2773
|
icon: a.icon,
|
|
2115
2774
|
tooltip: a.tooltip,
|
|
2116
|
-
href: resolveEnvPlaceholders(a.href)
|
|
2775
|
+
href: resolveEnvPlaceholders(a.href),
|
|
2776
|
+
...a.condition && {
|
|
2777
|
+
condition: a.condition
|
|
2778
|
+
}
|
|
2117
2779
|
} : {
|
|
2118
2780
|
id: a.id,
|
|
2119
2781
|
label: a.label,
|
|
@@ -2123,6 +2785,9 @@ var buildViewsPayload = /* @__PURE__ */ __name((config, baseUrl) => {
|
|
|
2123
2785
|
method: a.method ?? "post",
|
|
2124
2786
|
...a.data && {
|
|
2125
2787
|
data: a.data
|
|
2788
|
+
},
|
|
2789
|
+
...a.condition && {
|
|
2790
|
+
condition: a.condition
|
|
2126
2791
|
}
|
|
2127
2792
|
})
|
|
2128
2793
|
}
|
|
@@ -2197,6 +2862,34 @@ var registerResourceJsonEndpoint = /* @__PURE__ */ __name((ctx) => {
|
|
|
2197
2862
|
// src/lib/crud/operations/register-sub-resources.ts
|
|
2198
2863
|
import { Body, Delete as Delete2, Get as Get4, Param as Param3, Patch as Patch2, Post as Post3, Query as Query2 } from "@nestjs/common";
|
|
2199
2864
|
import { ApiOperation as ApiOperation5, ApiParam as ApiParam3, ApiResponse as ApiResponse5 } from "@nestjs/swagger";
|
|
2865
|
+
var findAllByParent = /* @__PURE__ */ __name(async (repo, id, childRoute, params) => {
|
|
2866
|
+
const { data, count } = await repo.findAllByParent(id, childRoute, params);
|
|
2867
|
+
const totalPages = Math.max(1, Math.ceil(count / params.pageSize));
|
|
2868
|
+
return {
|
|
2869
|
+
data,
|
|
2870
|
+
request: {
|
|
2871
|
+
count,
|
|
2872
|
+
page: params.page,
|
|
2873
|
+
pageSize: params.pageSize,
|
|
2874
|
+
totalPages,
|
|
2875
|
+
sort: params.sort,
|
|
2876
|
+
sortDir: params.sortDir,
|
|
2877
|
+
filter: params.filter
|
|
2878
|
+
}
|
|
2879
|
+
};
|
|
2880
|
+
}, "findAllByParent");
|
|
2881
|
+
var createChild = /* @__PURE__ */ __name(async (repo, id, sub, body) => {
|
|
2882
|
+
return repo.createChild(id, sub, body);
|
|
2883
|
+
}, "createChild");
|
|
2884
|
+
var findOneChild = /* @__PURE__ */ __name(async (repo, sub, childId, parentId) => {
|
|
2885
|
+
return repo.findOneChild(sub, childId, parentId);
|
|
2886
|
+
}, "findOneChild");
|
|
2887
|
+
var updateChild = /* @__PURE__ */ __name(async (repo, sub, childId, body) => {
|
|
2888
|
+
return repo.updateChild(sub, childId, body);
|
|
2889
|
+
}, "updateChild");
|
|
2890
|
+
var deleteChild = /* @__PURE__ */ __name(async (repo, sub, childId, parentId) => {
|
|
2891
|
+
return repo.deleteChild(sub, childId, parentId);
|
|
2892
|
+
}, "deleteChild");
|
|
2200
2893
|
var registerSubResourceSchemas = /* @__PURE__ */ __name((ctx, sub) => {
|
|
2201
2894
|
if (!sub.views) return;
|
|
2202
2895
|
const { cls, config, baseUrl } = ctx;
|
|
@@ -2268,20 +2961,7 @@ var registerSubResourceFindAll = /* @__PURE__ */ __name((ctx, sub) => {
|
|
|
2268
2961
|
const idParamMeta = ctx.idParamMeta;
|
|
2269
2962
|
const methodName = `findAllBy_${sub.childRoute}`;
|
|
2270
2963
|
def(cls, methodName, async function(id, params) {
|
|
2271
|
-
|
|
2272
|
-
const totalPages = Math.max(1, Math.ceil(count / params.pageSize));
|
|
2273
|
-
return {
|
|
2274
|
-
data,
|
|
2275
|
-
request: {
|
|
2276
|
-
count,
|
|
2277
|
-
page: params.page,
|
|
2278
|
-
pageSize: params.pageSize,
|
|
2279
|
-
totalPages,
|
|
2280
|
-
sort: params.sort,
|
|
2281
|
-
sortDir: params.sortDir,
|
|
2282
|
-
filter: params.filter
|
|
2283
|
-
}
|
|
2284
|
-
};
|
|
2964
|
+
return findAllByParent(this.repo, id, sub.childRoute, params);
|
|
2285
2965
|
});
|
|
2286
2966
|
const d = desc(cls, methodName);
|
|
2287
2967
|
Get4(`:id/${sub.childRoute}`)(cls.prototype, methodName, d);
|
|
@@ -2302,7 +2982,7 @@ var registerSubResourceCreate = /* @__PURE__ */ __name((ctx, sub) => {
|
|
|
2302
2982
|
const { name } = config;
|
|
2303
2983
|
const methodName = `createChild_${sub.childRoute}`;
|
|
2304
2984
|
def(cls, methodName, async function(id, body) {
|
|
2305
|
-
return this.repo
|
|
2985
|
+
return createChild(this.repo, id, sub, body);
|
|
2306
2986
|
});
|
|
2307
2987
|
const d = desc(cls, methodName);
|
|
2308
2988
|
Post3(`:id/${sub.childRoute}`)(cls.prototype, methodName, d);
|
|
@@ -2322,7 +3002,7 @@ var registerSubResourceFindOne = /* @__PURE__ */ __name((ctx, sub) => {
|
|
|
2322
3002
|
const { cls } = ctx;
|
|
2323
3003
|
const methodName = `findOneChild_${sub.childRoute}`;
|
|
2324
3004
|
def(cls, methodName, async function(parentId, childId) {
|
|
2325
|
-
return this.repo
|
|
3005
|
+
return findOneChild(this.repo, sub, childId, parentId);
|
|
2326
3006
|
});
|
|
2327
3007
|
const d = desc(cls, methodName);
|
|
2328
3008
|
Get4(`:id/${sub.childRoute}/:childId`)(cls.prototype, methodName, d);
|
|
@@ -2342,7 +3022,7 @@ var registerSubResourceUpdate = /* @__PURE__ */ __name((ctx, sub) => {
|
|
|
2342
3022
|
const { cls } = ctx;
|
|
2343
3023
|
const methodName = `updateChild_${sub.childRoute}`;
|
|
2344
3024
|
def(cls, methodName, async function(_id, childId, body) {
|
|
2345
|
-
return this.repo
|
|
3025
|
+
return updateChild(this.repo, sub, childId, body);
|
|
2346
3026
|
});
|
|
2347
3027
|
const d = desc(cls, methodName);
|
|
2348
3028
|
Patch2(`:id/${sub.childRoute}/:childId`)(cls.prototype, methodName, d);
|
|
@@ -2363,7 +3043,7 @@ var registerSubResourceDelete = /* @__PURE__ */ __name((ctx, sub) => {
|
|
|
2363
3043
|
const { cls } = ctx;
|
|
2364
3044
|
const methodName = `deleteChild_${sub.childRoute}`;
|
|
2365
3045
|
def(cls, methodName, async function(parentId, childId) {
|
|
2366
|
-
return this.repo
|
|
3046
|
+
return deleteChild(this.repo, sub, childId, parentId);
|
|
2367
3047
|
});
|
|
2368
3048
|
const d = desc(cls, methodName);
|
|
2369
3049
|
Delete2(`:id/${sub.childRoute}/:childId`)(cls.prototype, methodName, d);
|
|
@@ -2459,164 +3139,115 @@ function createCrudController(config, baseUrl) {
|
|
|
2459
3139
|
}
|
|
2460
3140
|
__name(createCrudController, "createCrudController");
|
|
2461
3141
|
|
|
2462
|
-
// src/lib/crud/
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
var
|
|
2467
|
-
var
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
3142
|
+
// src/lib/crud/builder/column-predicates.ts
|
|
3143
|
+
var isBoolean = /* @__PURE__ */ __name((col) => col.fieldInput?.type === "boolean" || col.columnType === "boolean", "isBoolean");
|
|
3144
|
+
var isRelation = /* @__PURE__ */ __name((col) => col.fieldInput?.format === "relation", "isRelation");
|
|
3145
|
+
var isAutocomplete = /* @__PURE__ */ __name((col) => col.fieldInput?.type === "autocomplete", "isAutocomplete");
|
|
3146
|
+
var isRecordCell = /* @__PURE__ */ __name((col) => isRelation(col) || isAutocomplete(col), "isRecordCell");
|
|
3147
|
+
var isDateRange = /* @__PURE__ */ __name((col) => col.fieldInput?.format === "date-range", "isDateRange");
|
|
3148
|
+
|
|
3149
|
+
// src/lib/crud/builder/column.utils.ts
|
|
3150
|
+
var colPosition = /* @__PURE__ */ __name((col, i) => col.fieldInput?.position ?? i, "colPosition");
|
|
3151
|
+
var sortByPosition = /* @__PURE__ */ __name((cols) => cols.map((col, i) => ({
|
|
3152
|
+
col,
|
|
3153
|
+
i
|
|
3154
|
+
})).sort((a, b) => colPosition(a.col, a.i) - colPosition(b.col, b.i)).map(({ col }) => col), "sortByPosition");
|
|
3155
|
+
var toViewColumn = /* @__PURE__ */ __name((col) => ({
|
|
3156
|
+
id: col.id,
|
|
3157
|
+
...col.label && {
|
|
3158
|
+
label: col.label
|
|
3159
|
+
},
|
|
3160
|
+
...col.sortable != null && {
|
|
3161
|
+
sortable: col.sortable
|
|
3162
|
+
},
|
|
3163
|
+
...col.searchable != null && {
|
|
3164
|
+
searchable: col.searchable
|
|
3165
|
+
},
|
|
3166
|
+
...col.fieldInput && {
|
|
3167
|
+
fieldInput: col.fieldInput
|
|
2474
3168
|
}
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
var
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
return
|
|
3169
|
+
}), "toViewColumn");
|
|
3170
|
+
|
|
3171
|
+
// src/lib/crud/builder/sort.helpers.ts
|
|
3172
|
+
var deriveSortId = /* @__PURE__ */ __name((col) => {
|
|
3173
|
+
if (col.sortable === false) return null;
|
|
3174
|
+
if (col.sortId) return col.sortId;
|
|
3175
|
+
const base = col.column ?? col.id;
|
|
3176
|
+
const fi = col.fieldInput;
|
|
3177
|
+
const opts = fi?.options ?? {};
|
|
3178
|
+
const isRelation2 = fi?.format === "relation" || !!fi?.relationType || fi?.type === "autocomplete" || typeof opts.resource === "string";
|
|
3179
|
+
if (isRelation2) {
|
|
3180
|
+
const key = (typeof col.displayKey === "string" ? col.displayKey : void 0) ?? (typeof opts.displayKey === "string" ? opts.displayKey : void 0) ?? (typeof opts.labelKey === "string" ? opts.labelKey : void 0);
|
|
3181
|
+
if (!key) return null;
|
|
3182
|
+
const path2 = key.includes(".") ? key : `${base}.${key}`;
|
|
3183
|
+
return path2.endsWith(".label") ? path2.slice(0, -".label".length) : path2;
|
|
2490
3184
|
}
|
|
2491
|
-
|
|
3185
|
+
if (!col.displayKey) return base;
|
|
3186
|
+
const path = `${base}.${col.displayKey}`;
|
|
3187
|
+
const isValueLabel = !!col.enum || opts.emitObject === true;
|
|
3188
|
+
if (isValueLabel && path.endsWith(".label")) return path.slice(0, -".label".length);
|
|
3189
|
+
return path;
|
|
3190
|
+
}, "deriveSortId");
|
|
3191
|
+
var resolveDefaultSort = /* @__PURE__ */ __name((tableCols, allColumns) => {
|
|
3192
|
+
const isSortable = /* @__PURE__ */ __name((c) => c.sortable !== false, "isSortable");
|
|
3193
|
+
const sortCol = tableCols.find((c) => c.defaultSort && isSortable(c)) ?? tableCols.find(isSortable) ?? allColumns?.find((c) => c.idField);
|
|
3194
|
+
return sortCol ? deriveSortId(sortCol) ?? sortCol.id : void 0;
|
|
3195
|
+
}, "resolveDefaultSort");
|
|
2492
3196
|
|
|
2493
|
-
// src/lib/crud/
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
if (
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
label: action.label,
|
|
2503
|
-
href: action.href,
|
|
2504
|
-
...action.condition && {
|
|
2505
|
-
condition: action.condition
|
|
2506
|
-
}
|
|
2507
|
-
});
|
|
2508
|
-
continue;
|
|
2509
|
-
}
|
|
2510
|
-
const file = findModule2(join3(basePath, "actions"), action.procedure);
|
|
2511
|
-
if (!file) {
|
|
2512
|
-
console.warn(`[actions] Procedure file not found for "${action.id}" in ${basePath}/actions/`);
|
|
2513
|
-
continue;
|
|
2514
|
-
}
|
|
2515
|
-
const mod = await importDefault(file);
|
|
2516
|
-
if (!mod) {
|
|
2517
|
-
console.warn(`[actions] No default export in ${file}`);
|
|
2518
|
-
continue;
|
|
3197
|
+
// src/lib/crud/builder/schema-transforms.ts
|
|
3198
|
+
var allowAdditionalProperties = /* @__PURE__ */ __name((schema) => {
|
|
3199
|
+
if (schema["type"] === "object") {
|
|
3200
|
+
schema["additionalProperties"] = true;
|
|
3201
|
+
const props = schema["properties"];
|
|
3202
|
+
if (props) {
|
|
3203
|
+
for (const value of Object.values(props)) {
|
|
3204
|
+
allowAdditionalProperties(value);
|
|
3205
|
+
}
|
|
2519
3206
|
}
|
|
2520
|
-
results.push({
|
|
2521
|
-
id: action.id,
|
|
2522
|
-
label: action.label,
|
|
2523
|
-
method: action.method,
|
|
2524
|
-
data: action.data,
|
|
2525
|
-
...action.condition && {
|
|
2526
|
-
condition: action.condition
|
|
2527
|
-
},
|
|
2528
|
-
procedure: mod
|
|
2529
|
-
});
|
|
2530
3207
|
}
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
var loadTableActions = /* @__PURE__ */ __name(async (jsonActions, basePath) => {
|
|
2534
|
-
const results = [];
|
|
2535
|
-
for (const action of jsonActions) {
|
|
2536
|
-
if (action.type === "link") {
|
|
2537
|
-
results.push({
|
|
2538
|
-
type: "link",
|
|
2539
|
-
id: action.id,
|
|
2540
|
-
label: action.label,
|
|
2541
|
-
icon: action.icon,
|
|
2542
|
-
tooltip: action.tooltip,
|
|
2543
|
-
href: action.href
|
|
2544
|
-
});
|
|
2545
|
-
continue;
|
|
2546
|
-
}
|
|
2547
|
-
const file = findModule2(join3(basePath, "actions"), action.procedure);
|
|
2548
|
-
if (!file) {
|
|
2549
|
-
console.warn(`[tableActions] Procedure file not found for "${action.id}" in ${basePath}/actions/`);
|
|
2550
|
-
continue;
|
|
2551
|
-
}
|
|
2552
|
-
const mod = await importDefault(file);
|
|
2553
|
-
if (!mod) {
|
|
2554
|
-
console.warn(`[tableActions] No default export in ${file}`);
|
|
2555
|
-
continue;
|
|
2556
|
-
}
|
|
2557
|
-
results.push({
|
|
2558
|
-
id: action.id,
|
|
2559
|
-
label: action.label,
|
|
2560
|
-
icon: action.icon,
|
|
2561
|
-
tooltip: action.tooltip,
|
|
2562
|
-
method: action.method,
|
|
2563
|
-
data: action.data,
|
|
2564
|
-
procedure: mod
|
|
2565
|
-
});
|
|
3208
|
+
if (schema["type"] === "array" && schema["items"]) {
|
|
3209
|
+
allowAdditionalProperties(schema["items"]);
|
|
2566
3210
|
}
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
const candidate = join4(dir, ENUMS_FILE);
|
|
2580
|
-
if (existsSync3(candidate)) {
|
|
2581
|
-
file = candidate;
|
|
2582
|
-
break;
|
|
2583
|
-
}
|
|
2584
|
-
const parent = dirname(dir);
|
|
2585
|
-
if (parent === dir) break;
|
|
2586
|
-
dir = parent;
|
|
2587
|
-
}
|
|
3211
|
+
}, "allowAdditionalProperties");
|
|
3212
|
+
var isNullableProperty2 = /* @__PURE__ */ __name((prop) => {
|
|
3213
|
+
const anyOf = prop?.["anyOf"];
|
|
3214
|
+
return Array.isArray(anyOf) && anyOf.some((s) => s?.["type"] === "null");
|
|
3215
|
+
}, "isNullableProperty");
|
|
3216
|
+
var dropNullableFromRequired2 = /* @__PURE__ */ __name((schema) => {
|
|
3217
|
+
if (schema["type"] !== "object") return;
|
|
3218
|
+
const props = schema["properties"];
|
|
3219
|
+
if (!props) return;
|
|
3220
|
+
const required = schema["required"];
|
|
3221
|
+
if (Array.isArray(required)) {
|
|
3222
|
+
schema["required"] = required.filter((key) => !isNullableProperty2(props[key]));
|
|
2588
3223
|
}
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
return JSON.parse(readFileSync2(file, "utf-8"));
|
|
2592
|
-
} catch {
|
|
2593
|
-
return {};
|
|
3224
|
+
for (const value of Object.values(props)) {
|
|
3225
|
+
dropNullableFromRequired2(value);
|
|
2594
3226
|
}
|
|
2595
|
-
}, "
|
|
2596
|
-
var
|
|
2597
|
-
if (
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
if (!
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
if (!("values" in options)) options.values = values;
|
|
2607
|
-
col.fieldInput.options = options;
|
|
3227
|
+
}, "dropNullableFromRequired");
|
|
3228
|
+
var enforceRequiredMinLength = /* @__PURE__ */ __name((schema) => {
|
|
3229
|
+
if (schema["type"] !== "object") return;
|
|
3230
|
+
const props = schema["properties"];
|
|
3231
|
+
if (!props) return;
|
|
3232
|
+
for (const prop of Object.values(props)) {
|
|
3233
|
+
if (prop?.["type"] === "string" && !("minLength" in prop)) {
|
|
3234
|
+
prop["minLength"] = 1;
|
|
3235
|
+
} else if (prop?.["type"] === "object") {
|
|
3236
|
+
enforceRequiredMinLength(prop);
|
|
3237
|
+
}
|
|
2608
3238
|
}
|
|
2609
|
-
}, "
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
3239
|
+
}, "enforceRequiredMinLength");
|
|
3240
|
+
var applySchemaTransforms = /* @__PURE__ */ __name((schema) => {
|
|
3241
|
+
allowAdditionalProperties(schema);
|
|
3242
|
+
dropNullableFromRequired2(schema);
|
|
3243
|
+
enforceRequiredMinLength(schema);
|
|
3244
|
+
}, "applySchemaTransforms");
|
|
2613
3245
|
|
|
2614
|
-
// src/lib/crud/
|
|
3246
|
+
// src/lib/crud/builder/schema.helpers.ts
|
|
2615
3247
|
var pickByColumns = /* @__PURE__ */ __name((schema, columns, filter) => {
|
|
2616
3248
|
if (!schema) return void 0;
|
|
2617
3249
|
if (!columns?.length) return schema;
|
|
2618
|
-
const
|
|
2619
|
-
const baseFilter = /* @__PURE__ */ __name((c) => !isRelation2(c) && (filter ? filter(c) : true), "baseFilter");
|
|
3250
|
+
const baseFilter = /* @__PURE__ */ __name((c) => !isRelation(c) && (filter ? filter(c) : true), "baseFilter");
|
|
2620
3251
|
const filtered = columns.filter(baseFilter);
|
|
2621
3252
|
if (!filtered.length) return void 0;
|
|
2622
3253
|
const mask = Object.fromEntries(filtered.map((c) => [
|
|
@@ -2647,10 +3278,75 @@ var upsertOp = /* @__PURE__ */ __name((entry, schema) => {
|
|
|
2647
3278
|
return void 0;
|
|
2648
3279
|
}, "upsertOp");
|
|
2649
3280
|
|
|
2650
|
-
// src/lib/crud/
|
|
2651
|
-
|
|
3281
|
+
// src/lib/crud/builder/table-schema.builder.ts
|
|
3282
|
+
var SHARED_CELL_OPTION_KEYS = [
|
|
3283
|
+
"values",
|
|
3284
|
+
"storeValue",
|
|
3285
|
+
"uri",
|
|
3286
|
+
"resourceUri",
|
|
3287
|
+
"schemasUri"
|
|
3288
|
+
];
|
|
3289
|
+
var pickSharedCellOptions = /* @__PURE__ */ __name((col) => {
|
|
3290
|
+
const options = col.fieldInput?.options ?? {};
|
|
3291
|
+
return Object.fromEntries(SHARED_CELL_OPTION_KEYS.filter((key) => options[key] !== void 0).map((key) => [
|
|
3292
|
+
key,
|
|
3293
|
+
options[key]
|
|
3294
|
+
]));
|
|
3295
|
+
}, "pickSharedCellOptions");
|
|
3296
|
+
var buildTableUiSchema = /* @__PURE__ */ __name((cols) => {
|
|
3297
|
+
const layout = TableBuilder.init().addControls(...cols.map((col) => {
|
|
3298
|
+
const cellBuilder = isBoolean(col) ? BooleanCellBuilder : TextCellBuilder;
|
|
3299
|
+
let builder = cellBuilder.properties(col.id);
|
|
3300
|
+
if (col.displayKey) builder = builder.key(col.displayKey);
|
|
3301
|
+
if (col.sortId) builder = builder.setSortId(col.sortId);
|
|
3302
|
+
return builder;
|
|
3303
|
+
})).build();
|
|
3304
|
+
const colMap = Object.fromEntries(cols.map((c) => [
|
|
3305
|
+
c.id,
|
|
3306
|
+
c
|
|
3307
|
+
]));
|
|
3308
|
+
layout.elements = layout.elements.map((el) => {
|
|
3309
|
+
const id = el.scope?.replace("#/properties/", "");
|
|
3310
|
+
const col = id ? colMap[id] : void 0;
|
|
3311
|
+
if (!col) return el;
|
|
3312
|
+
const fieldInputOptions = isRecordCell(col) || isDateRange(col) ? col.fieldInput?.options ?? {} : pickSharedCellOptions(col);
|
|
3313
|
+
const dataPathOption = col.column ? {
|
|
3314
|
+
dataPath: col.column
|
|
3315
|
+
} : {};
|
|
3316
|
+
const derivedSortId = isRecordCell(col) || isDateRange(col) ? null : deriveSortId(col);
|
|
3317
|
+
const sortOptions = derivedSortId ? {
|
|
3318
|
+
sortId: derivedSortId
|
|
3319
|
+
} : {
|
|
3320
|
+
sortable: false
|
|
3321
|
+
};
|
|
3322
|
+
const relationTypeOption = col.fieldInput?.relationType ? {
|
|
3323
|
+
relationType: col.fieldInput.relationType
|
|
3324
|
+
} : {};
|
|
3325
|
+
return {
|
|
3326
|
+
...el,
|
|
3327
|
+
options: {
|
|
3328
|
+
...el.options ?? {},
|
|
3329
|
+
...fieldInputOptions,
|
|
3330
|
+
...dataPathOption,
|
|
3331
|
+
...sortOptions,
|
|
3332
|
+
...relationTypeOption,
|
|
3333
|
+
...isDateRange(col) && {
|
|
3334
|
+
format: "date-range"
|
|
3335
|
+
},
|
|
3336
|
+
label: col.label
|
|
3337
|
+
},
|
|
3338
|
+
...isRecordCell(col) && {
|
|
3339
|
+
type: "RecordCell"
|
|
3340
|
+
},
|
|
3341
|
+
...isDateRange(col) && {
|
|
3342
|
+
type: "Control"
|
|
3343
|
+
}
|
|
3344
|
+
};
|
|
3345
|
+
});
|
|
3346
|
+
return layout;
|
|
3347
|
+
}, "buildTableUiSchema");
|
|
2652
3348
|
|
|
2653
|
-
// src/lib/crud/
|
|
3349
|
+
// src/lib/crud/builder/form-schema.builder.ts
|
|
2654
3350
|
var buildConditionSchema = /* @__PURE__ */ __name((when) => {
|
|
2655
3351
|
if (when.notExists) return {
|
|
2656
3352
|
not: {
|
|
@@ -2770,232 +3466,7 @@ var buildFormUiSchema = /* @__PURE__ */ __name((cols) => {
|
|
|
2770
3466
|
return layout;
|
|
2771
3467
|
}, "buildFormUiSchema");
|
|
2772
3468
|
|
|
2773
|
-
// src/lib/crud/
|
|
2774
|
-
var allowAdditionalProperties = /* @__PURE__ */ __name((schema) => {
|
|
2775
|
-
if (schema["type"] === "object") {
|
|
2776
|
-
schema["additionalProperties"] = true;
|
|
2777
|
-
const props = schema["properties"];
|
|
2778
|
-
if (props) {
|
|
2779
|
-
for (const value of Object.values(props)) {
|
|
2780
|
-
allowAdditionalProperties(value);
|
|
2781
|
-
}
|
|
2782
|
-
}
|
|
2783
|
-
}
|
|
2784
|
-
if (schema["type"] === "array" && schema["items"]) {
|
|
2785
|
-
allowAdditionalProperties(schema["items"]);
|
|
2786
|
-
}
|
|
2787
|
-
}, "allowAdditionalProperties");
|
|
2788
|
-
var isNullableProperty2 = /* @__PURE__ */ __name((prop) => {
|
|
2789
|
-
const anyOf = prop?.["anyOf"];
|
|
2790
|
-
return Array.isArray(anyOf) && anyOf.some((s) => s?.["type"] === "null");
|
|
2791
|
-
}, "isNullableProperty");
|
|
2792
|
-
var dropNullableFromRequired2 = /* @__PURE__ */ __name((schema) => {
|
|
2793
|
-
if (schema["type"] !== "object") return;
|
|
2794
|
-
const props = schema["properties"];
|
|
2795
|
-
if (!props) return;
|
|
2796
|
-
const required = schema["required"];
|
|
2797
|
-
if (Array.isArray(required)) {
|
|
2798
|
-
schema["required"] = required.filter((key) => !isNullableProperty2(props[key]));
|
|
2799
|
-
}
|
|
2800
|
-
for (const value of Object.values(props)) {
|
|
2801
|
-
dropNullableFromRequired2(value);
|
|
2802
|
-
}
|
|
2803
|
-
}, "dropNullableFromRequired");
|
|
2804
|
-
var enforceRequiredMinLength = /* @__PURE__ */ __name((schema) => {
|
|
2805
|
-
if (schema["type"] !== "object") return;
|
|
2806
|
-
const props = schema["properties"];
|
|
2807
|
-
if (!props) return;
|
|
2808
|
-
for (const prop of Object.values(props)) {
|
|
2809
|
-
if (prop?.["type"] === "string" && !("minLength" in prop)) {
|
|
2810
|
-
prop["minLength"] = 1;
|
|
2811
|
-
} else if (prop?.["type"] === "object") {
|
|
2812
|
-
enforceRequiredMinLength(prop);
|
|
2813
|
-
}
|
|
2814
|
-
}
|
|
2815
|
-
}, "enforceRequiredMinLength");
|
|
2816
|
-
|
|
2817
|
-
// src/lib/crud/loader/table-schema.builder.ts
|
|
2818
|
-
var isBoolean = /* @__PURE__ */ __name((col) => col.fieldInput?.type === "boolean" || col.columnType === "boolean", "isBoolean");
|
|
2819
|
-
var isRelation = /* @__PURE__ */ __name((col) => col.fieldInput?.format === "relation", "isRelation");
|
|
2820
|
-
var isAutocomplete = /* @__PURE__ */ __name((col) => col.fieldInput?.type === "autocomplete", "isAutocomplete");
|
|
2821
|
-
var isRecordCell = /* @__PURE__ */ __name((col) => isRelation(col) || isAutocomplete(col), "isRecordCell");
|
|
2822
|
-
var isDateRange = /* @__PURE__ */ __name((col) => col.fieldInput?.format === "date-range", "isDateRange");
|
|
2823
|
-
var deriveSortId = /* @__PURE__ */ __name((col) => {
|
|
2824
|
-
if (col.sortable === false) return null;
|
|
2825
|
-
if (col.sortId) return col.sortId;
|
|
2826
|
-
const base = col.column ?? col.id;
|
|
2827
|
-
const fi = col.fieldInput;
|
|
2828
|
-
const opts = fi?.options ?? {};
|
|
2829
|
-
const isRelation2 = fi?.format === "relation" || !!fi?.relationType || fi?.type === "autocomplete" || typeof opts.resource === "string";
|
|
2830
|
-
if (isRelation2) {
|
|
2831
|
-
const key = (typeof col.displayKey === "string" ? col.displayKey : void 0) ?? (typeof opts.displayKey === "string" ? opts.displayKey : void 0) ?? (typeof opts.labelKey === "string" ? opts.labelKey : void 0);
|
|
2832
|
-
if (!key) return null;
|
|
2833
|
-
const path2 = key.includes(".") ? key : `${base}.${key}`;
|
|
2834
|
-
return path2.endsWith(".label") ? path2.slice(0, -".label".length) : path2;
|
|
2835
|
-
}
|
|
2836
|
-
if (!col.displayKey) return base;
|
|
2837
|
-
const path = `${base}.${col.displayKey}`;
|
|
2838
|
-
const isValueLabel = !!col.enum || opts.emitObject === true;
|
|
2839
|
-
if (isValueLabel && path.endsWith(".label")) return path.slice(0, -".label".length);
|
|
2840
|
-
return path;
|
|
2841
|
-
}, "deriveSortId");
|
|
2842
|
-
var resolveDefaultSort = /* @__PURE__ */ __name((tableCols, allColumns) => {
|
|
2843
|
-
const isSortable = /* @__PURE__ */ __name((c) => c.sortable !== false, "isSortable");
|
|
2844
|
-
const sortCol = tableCols.find((c) => c.defaultSort && isSortable(c)) ?? tableCols.find(isSortable) ?? allColumns?.find((c) => c.idField);
|
|
2845
|
-
return sortCol ? deriveSortId(sortCol) ?? sortCol.id : void 0;
|
|
2846
|
-
}, "resolveDefaultSort");
|
|
2847
|
-
var SHARED_CELL_OPTION_KEYS = [
|
|
2848
|
-
"values",
|
|
2849
|
-
"storeValue",
|
|
2850
|
-
"uri",
|
|
2851
|
-
"resourceUri",
|
|
2852
|
-
"schemasUri"
|
|
2853
|
-
];
|
|
2854
|
-
var pickSharedCellOptions = /* @__PURE__ */ __name((col) => {
|
|
2855
|
-
const options = col.fieldInput?.options ?? {};
|
|
2856
|
-
return Object.fromEntries(SHARED_CELL_OPTION_KEYS.filter((key) => options[key] !== void 0).map((key) => [
|
|
2857
|
-
key,
|
|
2858
|
-
options[key]
|
|
2859
|
-
]));
|
|
2860
|
-
}, "pickSharedCellOptions");
|
|
2861
|
-
var buildTableUiSchema = /* @__PURE__ */ __name((cols) => {
|
|
2862
|
-
const layout = TableBuilder.init().addControls(...cols.map((col) => {
|
|
2863
|
-
const cellBuilder = isBoolean(col) ? BooleanCellBuilder : TextCellBuilder;
|
|
2864
|
-
let builder = cellBuilder.properties(col.id);
|
|
2865
|
-
if (col.displayKey) builder = builder.key(col.displayKey);
|
|
2866
|
-
if (col.sortId) builder = builder.setSortId(col.sortId);
|
|
2867
|
-
return builder;
|
|
2868
|
-
})).build();
|
|
2869
|
-
const colMap = Object.fromEntries(cols.map((c) => [
|
|
2870
|
-
c.id,
|
|
2871
|
-
c
|
|
2872
|
-
]));
|
|
2873
|
-
layout.elements = layout.elements.map((el) => {
|
|
2874
|
-
const id = el.scope?.replace("#/properties/", "");
|
|
2875
|
-
const col = id ? colMap[id] : void 0;
|
|
2876
|
-
if (!col) return el;
|
|
2877
|
-
const fieldInputOptions = isRecordCell(col) || isDateRange(col) ? col.fieldInput?.options ?? {} : pickSharedCellOptions(col);
|
|
2878
|
-
const dataPathOption = col.column ? {
|
|
2879
|
-
dataPath: col.column
|
|
2880
|
-
} : {};
|
|
2881
|
-
const derivedSortId = isRecordCell(col) || isDateRange(col) ? null : deriveSortId(col);
|
|
2882
|
-
const sortOptions = derivedSortId ? {
|
|
2883
|
-
sortId: derivedSortId
|
|
2884
|
-
} : {
|
|
2885
|
-
sortable: false
|
|
2886
|
-
};
|
|
2887
|
-
const relationTypeOption = col.fieldInput?.relationType ? {
|
|
2888
|
-
relationType: col.fieldInput.relationType
|
|
2889
|
-
} : {};
|
|
2890
|
-
return {
|
|
2891
|
-
...el,
|
|
2892
|
-
options: {
|
|
2893
|
-
...el.options ?? {},
|
|
2894
|
-
...fieldInputOptions,
|
|
2895
|
-
...dataPathOption,
|
|
2896
|
-
...sortOptions,
|
|
2897
|
-
...relationTypeOption,
|
|
2898
|
-
...isDateRange(col) && {
|
|
2899
|
-
format: "date-range"
|
|
2900
|
-
},
|
|
2901
|
-
label: col.label
|
|
2902
|
-
},
|
|
2903
|
-
...isRecordCell(col) && {
|
|
2904
|
-
type: "RecordCell"
|
|
2905
|
-
},
|
|
2906
|
-
...isDateRange(col) && {
|
|
2907
|
-
type: "Control"
|
|
2908
|
-
}
|
|
2909
|
-
};
|
|
2910
|
-
});
|
|
2911
|
-
return layout;
|
|
2912
|
-
}, "buildTableUiSchema");
|
|
2913
|
-
|
|
2914
|
-
// src/lib/crud/loader/view.builders.ts
|
|
2915
|
-
var patchFilterProperties = /* @__PURE__ */ __name((jsonSchema, columns) => {
|
|
2916
|
-
if (!columns?.length) return;
|
|
2917
|
-
const properties = jsonSchema.properties;
|
|
2918
|
-
if (!properties) return;
|
|
2919
|
-
for (const col of columns) {
|
|
2920
|
-
if (col.fieldInput?.format === "date-range") {
|
|
2921
|
-
delete properties[col.id];
|
|
2922
|
-
const opts = col.fieldInput?.options ?? {};
|
|
2923
|
-
const base = col.label ?? col.id;
|
|
2924
|
-
const fromField = opts["fromField"] ?? "from";
|
|
2925
|
-
const toField = opts["toField"] ?? "to";
|
|
2926
|
-
const dateProp = /* @__PURE__ */ __name((title) => ({
|
|
2927
|
-
type: "string",
|
|
2928
|
-
format: "date",
|
|
2929
|
-
title,
|
|
2930
|
-
"x-field-type": "date"
|
|
2931
|
-
}), "dateProp");
|
|
2932
|
-
properties[`${col.id}->${fromField}`] = dateProp(opts["fromLabel"] ?? `${base} (from)`);
|
|
2933
|
-
properties[`${col.id}->${toField}`] = dateProp(opts["toLabel"] ?? `${base} (to)`);
|
|
2934
|
-
continue;
|
|
2935
|
-
}
|
|
2936
|
-
const prop = properties[col.id];
|
|
2937
|
-
if (!prop) continue;
|
|
2938
|
-
prop.title = col.label ?? col.id;
|
|
2939
|
-
const values = col.fieldInput?.options?.["values"];
|
|
2940
|
-
if (values) {
|
|
2941
|
-
prop["x-values"] = values;
|
|
2942
|
-
}
|
|
2943
|
-
const ft = col.fieldInput?.type;
|
|
2944
|
-
if (ft === "select" || col.enum) {
|
|
2945
|
-
prop["x-field-type"] = "enum";
|
|
2946
|
-
} else if (ft === "number" || prop.type === "number" || prop.type === "integer") {
|
|
2947
|
-
prop["x-field-type"] = "number";
|
|
2948
|
-
} else if (prop.format === "date-time" || prop.format === "date") {
|
|
2949
|
-
prop["x-field-type"] = "date";
|
|
2950
|
-
} else if (prop.type === "boolean") {
|
|
2951
|
-
prop["x-field-type"] = "boolean";
|
|
2952
|
-
}
|
|
2953
|
-
}
|
|
2954
|
-
}, "patchFilterProperties");
|
|
2955
|
-
var colPosition = /* @__PURE__ */ __name((col, i) => col.fieldInput?.position ?? i, "colPosition");
|
|
2956
|
-
var sortByPosition = /* @__PURE__ */ __name((cols) => cols.map((col, i) => ({
|
|
2957
|
-
col,
|
|
2958
|
-
i
|
|
2959
|
-
})).sort((a, b) => colPosition(a.col, a.i) - colPosition(b.col, b.i)).map(({ col }) => col), "sortByPosition");
|
|
2960
|
-
var toViewColumn = /* @__PURE__ */ __name((col) => ({
|
|
2961
|
-
id: col.id,
|
|
2962
|
-
...col.label && {
|
|
2963
|
-
label: col.label
|
|
2964
|
-
},
|
|
2965
|
-
...col.sortable != null && {
|
|
2966
|
-
sortable: col.sortable
|
|
2967
|
-
},
|
|
2968
|
-
...col.searchable != null && {
|
|
2969
|
-
searchable: col.searchable
|
|
2970
|
-
},
|
|
2971
|
-
...col.fieldInput && {
|
|
2972
|
-
fieldInput: col.fieldInput
|
|
2973
|
-
}
|
|
2974
|
-
}), "toViewColumn");
|
|
2975
|
-
var buildView = /* @__PURE__ */ __name((schema, columns, visible, buildUiSchema, sort = false, schemaVisible) => {
|
|
2976
|
-
if (!schema || !columns?.length) return void 0;
|
|
2977
|
-
const visibleCols = sort ? sortByPosition(columns.filter(visible)) : columns.filter(visible);
|
|
2978
|
-
if (!visibleCols.length) return void 0;
|
|
2979
|
-
const schemaCols = schemaVisible ? columns.filter((c) => visible(c) || schemaVisible(c)) : visibleCols;
|
|
2980
|
-
const schemaIds = schemaCols.map((c) => c.id);
|
|
2981
|
-
const mask = Object.fromEntries(schemaIds.map((id) => [
|
|
2982
|
-
id,
|
|
2983
|
-
true
|
|
2984
|
-
]));
|
|
2985
|
-
const picked = schema.pick(mask);
|
|
2986
|
-
const jsonSchema = toJSONSchema3(picked, {
|
|
2987
|
-
target: "draft-07",
|
|
2988
|
-
...jsonSchemaOpts
|
|
2989
|
-
});
|
|
2990
|
-
allowAdditionalProperties(jsonSchema);
|
|
2991
|
-
dropNullableFromRequired2(jsonSchema);
|
|
2992
|
-
enforceRequiredMinLength(jsonSchema);
|
|
2993
|
-
return {
|
|
2994
|
-
json_schema: jsonSchema,
|
|
2995
|
-
ui_schema: buildUiSchema(visibleCols),
|
|
2996
|
-
columns: visibleCols.map(toViewColumn)
|
|
2997
|
-
};
|
|
2998
|
-
}, "buildView");
|
|
3469
|
+
// src/lib/crud/builder/calculated-columns.builder.ts
|
|
2999
3470
|
var isVisibleInMode = /* @__PURE__ */ __name((c, mode) => mode === "table" ? !c.hiddenInTable : !c.hiddenInView, "isVisibleInMode");
|
|
3000
3471
|
var buildCalculatedElement = /* @__PURE__ */ __name((c, mode) => mode === "table" ? {
|
|
3001
3472
|
type: c.type === "boolean" ? "BooleanCell" : "TextCell",
|
|
@@ -3074,6 +3545,78 @@ var injectCalculatedColumnsIntoView = /* @__PURE__ */ __name((viewConfig, calcul
|
|
|
3074
3545
|
}, "injectCalculatedColumnsIntoView");
|
|
3075
3546
|
var injectCalculatedColumns = /* @__PURE__ */ __name((tableView, calculated) => injectCalculatedColumnsIntoView(tableView, calculated, "table"), "injectCalculatedColumns");
|
|
3076
3547
|
var injectCalculatedColumnsToView = /* @__PURE__ */ __name((viewConfig, calculated) => injectCalculatedColumnsIntoView(viewConfig, calculated, "view"), "injectCalculatedColumnsToView");
|
|
3548
|
+
|
|
3549
|
+
// src/lib/crud/builder/view.builder.ts
|
|
3550
|
+
import { toJSONSchema as toJSONSchema3 } from "zod";
|
|
3551
|
+
var patchFilterProperties = /* @__PURE__ */ __name((jsonSchema, columns) => {
|
|
3552
|
+
if (!columns?.length) return;
|
|
3553
|
+
const properties = jsonSchema.properties;
|
|
3554
|
+
if (!properties) return;
|
|
3555
|
+
for (const col of columns) {
|
|
3556
|
+
if (col.fieldInput?.format === "date-range") {
|
|
3557
|
+
delete properties[col.id];
|
|
3558
|
+
const opts = col.fieldInput?.options ?? {};
|
|
3559
|
+
const base = col.label ?? col.id;
|
|
3560
|
+
const fromField = opts["fromField"] ?? "from";
|
|
3561
|
+
const toField = opts["toField"] ?? "to";
|
|
3562
|
+
const dateProp = /* @__PURE__ */ __name((title) => ({
|
|
3563
|
+
type: "string",
|
|
3564
|
+
format: "date",
|
|
3565
|
+
title,
|
|
3566
|
+
"x-field-type": "date"
|
|
3567
|
+
}), "dateProp");
|
|
3568
|
+
properties[`${col.id}->${fromField}`] = dateProp(opts["fromLabel"] ?? `${base} (from)`);
|
|
3569
|
+
properties[`${col.id}->${toField}`] = dateProp(opts["toLabel"] ?? `${base} (to)`);
|
|
3570
|
+
continue;
|
|
3571
|
+
}
|
|
3572
|
+
const prop = properties[col.id];
|
|
3573
|
+
if (!prop) continue;
|
|
3574
|
+
prop.title = col.label ?? col.id;
|
|
3575
|
+
const values = col.fieldInput?.options?.["values"];
|
|
3576
|
+
if (values) {
|
|
3577
|
+
prop["x-values"] = values;
|
|
3578
|
+
}
|
|
3579
|
+
const ft = col.fieldInput?.type;
|
|
3580
|
+
if (ft === "select" || col.enum) {
|
|
3581
|
+
prop["x-field-type"] = "enum";
|
|
3582
|
+
} else if (ft === "number" || prop.type === "number" || prop.type === "integer") {
|
|
3583
|
+
prop["x-field-type"] = "number";
|
|
3584
|
+
} else if (prop.format === "date-time" || prop.format === "date") {
|
|
3585
|
+
prop["x-field-type"] = "date";
|
|
3586
|
+
} else if (prop.type === "boolean") {
|
|
3587
|
+
prop["x-field-type"] = "boolean";
|
|
3588
|
+
}
|
|
3589
|
+
}
|
|
3590
|
+
}, "patchFilterProperties");
|
|
3591
|
+
var buildView = /* @__PURE__ */ __name((schema, columns, visible, buildUiSchema, sort = false, schemaVisible) => {
|
|
3592
|
+
if (!schema || !columns?.length) return void 0;
|
|
3593
|
+
const visibleCols = sort ? sortByPosition(columns.filter(visible)) : columns.filter(visible);
|
|
3594
|
+
if (!visibleCols.length) return void 0;
|
|
3595
|
+
const schemaCols = (schemaVisible ? columns.filter((c) => visible(c) || schemaVisible(c)) : visibleCols).filter((c) => !isRelation(c));
|
|
3596
|
+
const schemaIds = schemaCols.map((c) => c.id);
|
|
3597
|
+
const mask = Object.fromEntries(schemaIds.map((id) => [
|
|
3598
|
+
id,
|
|
3599
|
+
true
|
|
3600
|
+
]));
|
|
3601
|
+
const picked = schema.pick(mask);
|
|
3602
|
+
const jsonSchema = toJSONSchema3(picked, {
|
|
3603
|
+
target: "draft-07",
|
|
3604
|
+
...jsonSchemaOpts
|
|
3605
|
+
});
|
|
3606
|
+
applySchemaTransforms(jsonSchema);
|
|
3607
|
+
if (schemaVisible) {
|
|
3608
|
+
const nonEditableIds = new Set(schemaCols.filter((c) => c.idField || c.createable === false && c.updateable === false).map((c) => c.id));
|
|
3609
|
+
const required = jsonSchema["required"];
|
|
3610
|
+
if (Array.isArray(required) && nonEditableIds.size) {
|
|
3611
|
+
jsonSchema["required"] = required.filter((k) => !nonEditableIds.has(k));
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
return {
|
|
3615
|
+
json_schema: jsonSchema,
|
|
3616
|
+
ui_schema: buildUiSchema(visibleCols),
|
|
3617
|
+
columns: visibleCols.map(toViewColumn)
|
|
3618
|
+
};
|
|
3619
|
+
}, "buildView");
|
|
3077
3620
|
var emptyTableView = /* @__PURE__ */ __name(() => ({
|
|
3078
3621
|
json_schema: {
|
|
3079
3622
|
type: "object",
|
|
@@ -3092,7 +3635,7 @@ var buildViews = /* @__PURE__ */ __name((schema, columns) => {
|
|
|
3092
3635
|
} else if (columns?.length) {
|
|
3093
3636
|
views.table = emptyTableView();
|
|
3094
3637
|
}
|
|
3095
|
-
const form = buildView(schema, columns, (c) => !c.hiddenInForm, buildFormUiSchema, true, (c) => c.createable === true || c.updateable === true);
|
|
3638
|
+
const form = buildView(schema, columns, (c) => !c.hiddenInForm, buildFormUiSchema, true, (c) => !c.idField && (c.createable === true || c.updateable === true));
|
|
3096
3639
|
if (form) views.form = form;
|
|
3097
3640
|
const filter = buildView(schema, columns, (c) => !!c.filterable, buildFormUiSchema, true);
|
|
3098
3641
|
if (filter) {
|
|
@@ -3112,7 +3655,6 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
3112
3655
|
if (!properties[c.column]) {
|
|
3113
3656
|
properties[c.column] = {
|
|
3114
3657
|
type: "object",
|
|
3115
|
-
additionalProperties: true,
|
|
3116
3658
|
properties: {}
|
|
3117
3659
|
};
|
|
3118
3660
|
}
|
|
@@ -3123,7 +3665,6 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
3123
3665
|
if (!target[segment]) {
|
|
3124
3666
|
target[segment] = {
|
|
3125
3667
|
type: "object",
|
|
3126
|
-
additionalProperties: true,
|
|
3127
3668
|
properties: {}
|
|
3128
3669
|
};
|
|
3129
3670
|
}
|
|
@@ -3134,17 +3675,22 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
3134
3675
|
title: c.label ?? c.id
|
|
3135
3676
|
};
|
|
3136
3677
|
} else {
|
|
3678
|
+
const opts = c.fieldInput?.options;
|
|
3679
|
+
const isObject = opts?.emitObject === true || c.fieldInput?.type === "autocomplete";
|
|
3137
3680
|
properties[c.id] = {
|
|
3138
|
-
|
|
3681
|
+
...isObject ? {} : {
|
|
3682
|
+
type: c.columnType ?? "string"
|
|
3683
|
+
},
|
|
3139
3684
|
title: c.label ?? c.id
|
|
3140
3685
|
};
|
|
3141
3686
|
}
|
|
3142
3687
|
}
|
|
3143
|
-
|
|
3688
|
+
const schema = {
|
|
3144
3689
|
type: "object",
|
|
3145
|
-
additionalProperties: true,
|
|
3146
3690
|
properties
|
|
3147
3691
|
};
|
|
3692
|
+
applySchemaTransforms(schema);
|
|
3693
|
+
return schema;
|
|
3148
3694
|
}, "buildJsonSchema");
|
|
3149
3695
|
const fixNestedScopes = /* @__PURE__ */ __name((uiSchema, cols) => {
|
|
3150
3696
|
const colMap = Object.fromEntries(cols.map((c) => [
|
|
@@ -3194,33 +3740,223 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
3194
3740
|
return Object.keys(views).length ? views : void 0;
|
|
3195
3741
|
}, "buildViewsFromColumns");
|
|
3196
3742
|
|
|
3197
|
-
// src/lib/crud/
|
|
3743
|
+
// src/lib/crud/enum-registry/enum-registry.types.ts
|
|
3744
|
+
import { z as z17 } from "zod";
|
|
3745
|
+
var EnumEntrySchema = z17.object({
|
|
3746
|
+
value: z17.unknown(),
|
|
3747
|
+
label: z17.string()
|
|
3748
|
+
});
|
|
3749
|
+
var EnumRegistrySchema = z17.record(z17.string(), z17.array(EnumEntrySchema)).default({});
|
|
3750
|
+
|
|
3751
|
+
// src/lib/crud/enum-registry/enum-registry.loader.ts
|
|
3752
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
3753
|
+
import { dirname as dirname2, join as join5 } from "path";
|
|
3754
|
+
var ENUMS_FILE = "crouton.enums.json";
|
|
3755
|
+
var loadEnumRegistry = /* @__PURE__ */ __name((startDir, enumsFile) => {
|
|
3756
|
+
let file = enumsFile;
|
|
3757
|
+
if (!file) {
|
|
3758
|
+
let dir = startDir;
|
|
3759
|
+
while (true) {
|
|
3760
|
+
const candidate = join5(dir, ENUMS_FILE);
|
|
3761
|
+
if (existsSync3(candidate)) {
|
|
3762
|
+
file = candidate;
|
|
3763
|
+
break;
|
|
3764
|
+
}
|
|
3765
|
+
const parent = dirname2(dir);
|
|
3766
|
+
if (parent === dir) break;
|
|
3767
|
+
dir = parent;
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3770
|
+
if (!file || !existsSync3(file)) return EnumRegistrySchema.parse(void 0);
|
|
3771
|
+
try {
|
|
3772
|
+
return EnumRegistrySchema.parse(JSON.parse(readFileSync2(file, "utf-8")));
|
|
3773
|
+
} catch {
|
|
3774
|
+
return EnumRegistrySchema.parse(void 0);
|
|
3775
|
+
}
|
|
3776
|
+
}, "loadEnumRegistry");
|
|
3777
|
+
|
|
3778
|
+
// src/lib/crud/enum-registry/enum-registry.injector.ts
|
|
3779
|
+
var injectEnumValues = /* @__PURE__ */ __name((columns, enums) => {
|
|
3780
|
+
if (!columns) return;
|
|
3781
|
+
for (const col of columns) {
|
|
3782
|
+
if (!col.enum) continue;
|
|
3783
|
+
const values = enums[col.enum];
|
|
3784
|
+
if (!values) continue;
|
|
3785
|
+
col.fieldInput = col.fieldInput ?? {
|
|
3786
|
+
type: "select"
|
|
3787
|
+
};
|
|
3788
|
+
const options = col.fieldInput.options ?? {};
|
|
3789
|
+
if (!("values" in options)) options.values = values;
|
|
3790
|
+
col.fieldInput.options = options;
|
|
3791
|
+
}
|
|
3792
|
+
}, "injectEnumValues");
|
|
3793
|
+
|
|
3794
|
+
// src/lib/crud/adapter/relation-type.ts
|
|
3795
|
+
import { ZodArray, ZodNullable, ZodOptional } from "zod";
|
|
3796
|
+
var unwrapZodType = /* @__PURE__ */ __name((type) => {
|
|
3797
|
+
if (type instanceof ZodOptional || type instanceof ZodNullable) {
|
|
3798
|
+
return unwrapZodType(type.unwrap());
|
|
3799
|
+
}
|
|
3800
|
+
return type;
|
|
3801
|
+
}, "unwrapZodType");
|
|
3802
|
+
var deriveRelationType = /* @__PURE__ */ __name((schema, columnId) => {
|
|
3803
|
+
if (!schema) return void 0;
|
|
3804
|
+
const field = schema.shape[columnId];
|
|
3805
|
+
if (!field) return void 0;
|
|
3806
|
+
const inner = unwrapZodType(field);
|
|
3807
|
+
return inner instanceof ZodArray ? "oneToMany" : "manyToOne";
|
|
3808
|
+
}, "deriveRelationType");
|
|
3809
|
+
var deriveRelationTypeFromColumns = /* @__PURE__ */ __name((col, cols) => {
|
|
3810
|
+
const base = col.column ?? col.id;
|
|
3811
|
+
const fkNames = /* @__PURE__ */ new Set([
|
|
3812
|
+
`${base}_id`,
|
|
3813
|
+
`${col.id}_id`
|
|
3814
|
+
]);
|
|
3815
|
+
return cols.some((c) => fkNames.has(c.id)) ? "manyToOne" : "oneToMany";
|
|
3816
|
+
}, "deriveRelationTypeFromColumns");
|
|
3817
|
+
var enrichRelationTypes = /* @__PURE__ */ __name((columns, schema) => {
|
|
3818
|
+
if (!schema) return columns;
|
|
3819
|
+
return columns.map((col) => {
|
|
3820
|
+
const fi = col.fieldInput;
|
|
3821
|
+
if (!fi) return col;
|
|
3822
|
+
const isRelationField = fi.type === "autocomplete" || fi.format === "relation";
|
|
3823
|
+
if (!isRelationField) return col;
|
|
3824
|
+
if (fi.relationType) return col;
|
|
3825
|
+
const derived = deriveRelationType(schema, col.id) ?? deriveRelationTypeFromColumns(col, columns);
|
|
3826
|
+
if (!derived) return col;
|
|
3827
|
+
return {
|
|
3828
|
+
...col,
|
|
3829
|
+
fieldInput: {
|
|
3830
|
+
...fi,
|
|
3831
|
+
relationType: derived
|
|
3832
|
+
}
|
|
3833
|
+
};
|
|
3834
|
+
});
|
|
3835
|
+
}, "enrichRelationTypes");
|
|
3836
|
+
|
|
3837
|
+
// src/lib/crud/resource/ReadResourceJson.ts
|
|
3198
3838
|
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
3199
|
-
import { dirname as
|
|
3200
|
-
var
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
};
|
|
3208
|
-
} catch {
|
|
3209
|
-
return void 0;
|
|
3210
|
-
}
|
|
3839
|
+
import { dirname as dirname3, resolve as resolve2 } from "path";
|
|
3840
|
+
var readResourceJson = /* @__PURE__ */ __name((jsonPath) => {
|
|
3841
|
+
if (!existsSync4(jsonPath)) return void 0;
|
|
3842
|
+
const fileContent = JSON.parse(readFileSync3(jsonPath, "utf-8"));
|
|
3843
|
+
const resource = ResourceJsonSchema.safeParse(fileContent);
|
|
3844
|
+
if (resource.error) {
|
|
3845
|
+
console.error(resource.error);
|
|
3846
|
+
throw new Error(`Resource cannot be parsed ${jsonPath}`);
|
|
3211
3847
|
}
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3848
|
+
return {
|
|
3849
|
+
json: resource.data,
|
|
3850
|
+
dir: dirname3(jsonPath)
|
|
3851
|
+
};
|
|
3852
|
+
}, "readResourceJson");
|
|
3853
|
+
|
|
3854
|
+
// src/lib/crud/adapter/resource-resolver.ts
|
|
3855
|
+
import { existsSync as existsSync5 } from "fs";
|
|
3856
|
+
import { dirname as dirname4, resolve as resolve3 } from "path";
|
|
3857
|
+
var resolveChildResource = /* @__PURE__ */ __name((resourcePath, parentDir) => {
|
|
3858
|
+
const directPath = resolve3(parentDir, resourcePath);
|
|
3215
3859
|
try {
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3860
|
+
if (resourcePath.endsWith(".json") && existsSync5(directPath)) {
|
|
3861
|
+
return readResourceJson(directPath);
|
|
3862
|
+
}
|
|
3863
|
+
const childName = resourcePath.replace(/^\.\//, "").replace(/\.resource$/, "");
|
|
3864
|
+
const childJsonPath = resolve3(dirname4(parentDir), childName, "resource.json");
|
|
3865
|
+
return readResourceJson(childJsonPath);
|
|
3220
3866
|
} catch {
|
|
3221
3867
|
return void 0;
|
|
3222
3868
|
}
|
|
3223
3869
|
}, "resolveChildResource");
|
|
3870
|
+
|
|
3871
|
+
// src/lib/crud/adapter/column-enrichment.ts
|
|
3872
|
+
var enrichActionColumns = /* @__PURE__ */ __name((columns, parentRoute, subResources, baseUrl) => {
|
|
3873
|
+
if (!columns) return columns;
|
|
3874
|
+
const base = baseUrl ?? "";
|
|
3875
|
+
return columns.map((col) => {
|
|
3876
|
+
if (col.fieldInput?.format !== "relation") return col;
|
|
3877
|
+
const sub = subResources.find((s) => s.column === col.id);
|
|
3878
|
+
if (!sub) return col;
|
|
3879
|
+
return {
|
|
3880
|
+
...col,
|
|
3881
|
+
fieldInput: {
|
|
3882
|
+
...col.fieldInput,
|
|
3883
|
+
options: {
|
|
3884
|
+
...col.fieldInput.options,
|
|
3885
|
+
uri: `${base}/${parentRoute}/{id}/${sub.childRoute}`,
|
|
3886
|
+
resourceUri: `${base}/${sub.childRoute}`,
|
|
3887
|
+
...sub.views && {
|
|
3888
|
+
resource: `${base}/${parentRoute}/${sub.childRoute}/schemas`
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
}
|
|
3892
|
+
};
|
|
3893
|
+
});
|
|
3894
|
+
}, "enrichActionColumns");
|
|
3895
|
+
var enrichResourceRefColumns = /* @__PURE__ */ __name((columns, parentDir, baseUrl) => {
|
|
3896
|
+
if (!columns || !parentDir) return columns;
|
|
3897
|
+
const base = baseUrl ?? "";
|
|
3898
|
+
return columns.map((col) => {
|
|
3899
|
+
if (!col.fieldInput?.resource || col.fieldInput.format === "relation") return col;
|
|
3900
|
+
const childResolved = resolveChildResource(col.fieldInput.resource, parentDir);
|
|
3901
|
+
const childRoute = childResolved?.json?.route ?? col.fieldInput.resource.replace(/^\.\//, "").replace(/\.resource$/, "");
|
|
3902
|
+
return {
|
|
3903
|
+
...col,
|
|
3904
|
+
fieldInput: {
|
|
3905
|
+
...col.fieldInput,
|
|
3906
|
+
options: {
|
|
3907
|
+
...col.fieldInput.options,
|
|
3908
|
+
resourceUri: `${base}/${childRoute}`,
|
|
3909
|
+
schemasUri: `${base}/${childRoute}/schemas`
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
};
|
|
3913
|
+
});
|
|
3914
|
+
}, "enrichResourceRefColumns");
|
|
3915
|
+
var enrichNestedRelationColumns = /* @__PURE__ */ __name((cols, dir, baseUrl) => {
|
|
3916
|
+
if (!cols || !dir) return cols;
|
|
3917
|
+
const base = baseUrl ?? "";
|
|
3918
|
+
return cols.map((col) => {
|
|
3919
|
+
if (col.fieldInput?.format !== "relation" || !col.fieldInput.resource) return col;
|
|
3920
|
+
const resolved = resolveChildResource(col.fieldInput.resource, dir);
|
|
3921
|
+
const targetRoute = resolved?.json?.route ?? col.fieldInput.resource.replace(/^\.\//, "").replace(/\/resource\.json$/, "").replace(/\.resource$/, "");
|
|
3922
|
+
const relationType = col.fieldInput.relationType ?? deriveRelationTypeFromColumns(col, cols);
|
|
3923
|
+
return {
|
|
3924
|
+
...col,
|
|
3925
|
+
fieldInput: {
|
|
3926
|
+
...col.fieldInput,
|
|
3927
|
+
relationType,
|
|
3928
|
+
options: {
|
|
3929
|
+
...col.fieldInput.options,
|
|
3930
|
+
uri: `${base}/${targetRoute}`,
|
|
3931
|
+
resourceUri: `${base}/${targetRoute}`,
|
|
3932
|
+
resource: `${base}/${targetRoute}/schemas`
|
|
3933
|
+
}
|
|
3934
|
+
}
|
|
3935
|
+
};
|
|
3936
|
+
});
|
|
3937
|
+
}, "enrichNestedRelationColumns");
|
|
3938
|
+
var enrichIncludeWithSort = /* @__PURE__ */ __name((include, columns) => {
|
|
3939
|
+
if (!include?.length) return include;
|
|
3940
|
+
return include.map((entry) => {
|
|
3941
|
+
const relationName = typeof entry === "string" ? entry : entry.relation;
|
|
3942
|
+
const col = columns.find((c) => {
|
|
3943
|
+
const opts2 = c.fieldInput?.options;
|
|
3944
|
+
return (c.column ?? c.id) === relationName && opts2?.sort;
|
|
3945
|
+
});
|
|
3946
|
+
if (!col) return entry;
|
|
3947
|
+
const opts = col.fieldInput.options;
|
|
3948
|
+
const orderBy = buildChildSortClause(opts.sort, opts.sortDir ?? "asc");
|
|
3949
|
+
return typeof entry === "string" ? {
|
|
3950
|
+
relation: entry,
|
|
3951
|
+
orderBy
|
|
3952
|
+
} : {
|
|
3953
|
+
...entry,
|
|
3954
|
+
orderBy
|
|
3955
|
+
};
|
|
3956
|
+
});
|
|
3957
|
+
}, "enrichIncludeWithSort");
|
|
3958
|
+
|
|
3959
|
+
// src/lib/crud/adapter/column-transforms.ts
|
|
3224
3960
|
var expandExtendColumns = /* @__PURE__ */ __name((columns, dirPath) => {
|
|
3225
3961
|
if (!dirPath) return columns;
|
|
3226
3962
|
const result = [];
|
|
@@ -3235,7 +3971,7 @@ var expandExtendColumns = /* @__PURE__ */ __name((columns, dirPath) => {
|
|
|
3235
3971
|
result.push(col);
|
|
3236
3972
|
continue;
|
|
3237
3973
|
}
|
|
3238
|
-
const refColumns =
|
|
3974
|
+
const refColumns = resolved.json.columns;
|
|
3239
3975
|
const parentColumnKey = col.column ?? col.id;
|
|
3240
3976
|
for (const refCol of refColumns) {
|
|
3241
3977
|
if (refCol.idField) continue;
|
|
@@ -3296,37 +4032,8 @@ var applyRelationFormatDefault = /* @__PURE__ */ __name((cols) => cols?.map((col
|
|
|
3296
4032
|
}
|
|
3297
4033
|
return col;
|
|
3298
4034
|
}), "applyRelationFormatDefault");
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
const fkNames = /* @__PURE__ */ new Set([
|
|
3302
|
-
`${base}_id`,
|
|
3303
|
-
`${col.id}_id`
|
|
3304
|
-
]);
|
|
3305
|
-
return cols.some((c) => fkNames.has(c.id)) ? "manyToOne" : "oneToMany";
|
|
3306
|
-
}, "deriveRelationTypeFromColumns");
|
|
3307
|
-
var enrichNestedRelationColumns = /* @__PURE__ */ __name((cols, dir, baseUrl) => {
|
|
3308
|
-
if (!cols || !dir) return cols;
|
|
3309
|
-
const base = baseUrl ?? "";
|
|
3310
|
-
return cols.map((col) => {
|
|
3311
|
-
if (col.fieldInput?.format !== "relation" || !col.fieldInput.resource) return col;
|
|
3312
|
-
const resolved = resolveChildResource(col.fieldInput.resource, dir);
|
|
3313
|
-
const targetRoute = resolved?.json?.route ?? col.fieldInput.resource.replace(/^\.\//, "").replace(/\/resource\.json$/, "").replace(/\.resource$/, "");
|
|
3314
|
-
const relationType = col.fieldInput.relationType ?? deriveRelationTypeFromColumns(col, cols);
|
|
3315
|
-
return {
|
|
3316
|
-
...col,
|
|
3317
|
-
fieldInput: {
|
|
3318
|
-
...col.fieldInput,
|
|
3319
|
-
relationType,
|
|
3320
|
-
options: {
|
|
3321
|
-
...col.fieldInput.options,
|
|
3322
|
-
uri: `${base}/${targetRoute}`,
|
|
3323
|
-
resourceUri: `${base}/${targetRoute}`,
|
|
3324
|
-
resource: `${base}/${targetRoute}/schemas`
|
|
3325
|
-
}
|
|
3326
|
-
}
|
|
3327
|
-
};
|
|
3328
|
-
});
|
|
3329
|
-
}, "enrichNestedRelationColumns");
|
|
4035
|
+
|
|
4036
|
+
// src/lib/crud/adapter/sub-resource.builder.ts
|
|
3330
4037
|
var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentModel, parentDir, enums = {}, baseUrl) => {
|
|
3331
4038
|
if (!columns || !parentDir) return [];
|
|
3332
4039
|
return columns.filter((c) => c.fieldInput?.format === "relation" && c.fieldInput?.resource).map((c) => {
|
|
@@ -3334,7 +4041,7 @@ var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentMode
|
|
|
3334
4041
|
const childJson = childResolved?.json;
|
|
3335
4042
|
const childDir = childResolved?.dir;
|
|
3336
4043
|
const childRoute = childJson?.route ?? c.fieldInput.resource.replace(/^\.\//, "").replace(/\.resource$/, "");
|
|
3337
|
-
const rawChildColumns = childJson
|
|
4044
|
+
const rawChildColumns = childJson?.columns;
|
|
3338
4045
|
const expandedChildColumns = rawChildColumns ? expandExtendColumns(rawChildColumns, childDir) : void 0;
|
|
3339
4046
|
const childColumns = applyRelationFormatDefault(expandedChildColumns) ?? expandedChildColumns;
|
|
3340
4047
|
injectEnumValues(childColumns, enums);
|
|
@@ -3396,71 +4103,10 @@ var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentMode
|
|
|
3396
4103
|
};
|
|
3397
4104
|
});
|
|
3398
4105
|
}, "buildSubResources");
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
const base = baseUrl ?? "";
|
|
3402
|
-
return columns.map((col) => {
|
|
3403
|
-
if (col.fieldInput?.format !== "relation") return col;
|
|
3404
|
-
const sub = subResources.find((s) => s.column === col.id);
|
|
3405
|
-
if (!sub) return col;
|
|
3406
|
-
return {
|
|
3407
|
-
...col,
|
|
3408
|
-
fieldInput: {
|
|
3409
|
-
...col.fieldInput,
|
|
3410
|
-
options: {
|
|
3411
|
-
...col.fieldInput.options,
|
|
3412
|
-
uri: `${base}/${parentRoute}/{id}/${sub.childRoute}`,
|
|
3413
|
-
resourceUri: `${base}/${sub.childRoute}`,
|
|
3414
|
-
...sub.views && {
|
|
3415
|
-
resource: `${base}/${parentRoute}/${sub.childRoute}/schemas`
|
|
3416
|
-
}
|
|
3417
|
-
}
|
|
3418
|
-
}
|
|
3419
|
-
};
|
|
3420
|
-
});
|
|
3421
|
-
}, "enrichActionColumns");
|
|
3422
|
-
var enrichResourceRefColumns = /* @__PURE__ */ __name((columns, parentDir, baseUrl) => {
|
|
3423
|
-
if (!columns || !parentDir) return columns;
|
|
3424
|
-
const base = baseUrl ?? "";
|
|
3425
|
-
return columns.map((col) => {
|
|
3426
|
-
if (!col.fieldInput?.resource || col.fieldInput.format === "relation") return col;
|
|
3427
|
-
const childResolved = resolveChildResource(col.fieldInput.resource, parentDir);
|
|
3428
|
-
const childRoute = childResolved?.json?.route ?? col.fieldInput.resource.replace(/^\.\//, "").replace(/\.resource$/, "");
|
|
3429
|
-
return {
|
|
3430
|
-
...col,
|
|
3431
|
-
fieldInput: {
|
|
3432
|
-
...col.fieldInput,
|
|
3433
|
-
options: {
|
|
3434
|
-
...col.fieldInput.options,
|
|
3435
|
-
resourceUri: `${base}/${childRoute}`,
|
|
3436
|
-
schemasUri: `${base}/${childRoute}/schemas`
|
|
3437
|
-
}
|
|
3438
|
-
}
|
|
3439
|
-
};
|
|
3440
|
-
});
|
|
3441
|
-
}, "enrichResourceRefColumns");
|
|
3442
|
-
var enrichIncludeWithSort = /* @__PURE__ */ __name((include, columns) => {
|
|
3443
|
-
if (!include?.length) return include;
|
|
3444
|
-
return include.map((entry) => {
|
|
3445
|
-
const relationName = typeof entry === "string" ? entry : entry.relation;
|
|
3446
|
-
const col = columns.find((c) => {
|
|
3447
|
-
const opts2 = c.fieldInput?.options;
|
|
3448
|
-
return (c.column ?? c.id) === relationName && opts2?.sort;
|
|
3449
|
-
});
|
|
3450
|
-
if (!col) return entry;
|
|
3451
|
-
const opts = col.fieldInput.options;
|
|
3452
|
-
const orderBy = buildChildSortClause(opts.sort, opts.sortDir ?? "asc");
|
|
3453
|
-
return typeof entry === "string" ? {
|
|
3454
|
-
relation: entry,
|
|
3455
|
-
orderBy
|
|
3456
|
-
} : {
|
|
3457
|
-
...entry,
|
|
3458
|
-
orderBy
|
|
3459
|
-
};
|
|
3460
|
-
});
|
|
3461
|
-
}, "enrichIncludeWithSort");
|
|
4106
|
+
|
|
4107
|
+
// src/lib/crud/adapter/json-adapter.ts
|
|
3462
4108
|
var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, actions, tableActions, enums = {}) => {
|
|
3463
|
-
const rawColumns = expandExtendColumns(
|
|
4109
|
+
const rawColumns = expandExtendColumns(json.columns, dirPath);
|
|
3464
4110
|
const columns = enrichRelationTypes(applyRelationFormatDefault(rawColumns) ?? rawColumns, schema);
|
|
3465
4111
|
injectEnumValues(columns, enums);
|
|
3466
4112
|
const subResources = buildSubResources(columns, json.route, json.model, dirPath, enums, baseUrl);
|
|
@@ -3504,22 +4150,14 @@ var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, ac
|
|
|
3504
4150
|
delete: true
|
|
3505
4151
|
}
|
|
3506
4152
|
};
|
|
3507
|
-
const display = {
|
|
3508
|
-
mode: json.display?.mode === "page" ? "page" : "modal",
|
|
3509
|
-
customComponent: json.display?.customComponent ?? null
|
|
3510
|
-
};
|
|
3511
4153
|
return {
|
|
4154
|
+
...json,
|
|
3512
4155
|
name: json.name,
|
|
3513
4156
|
route: json.route,
|
|
3514
4157
|
model: json.model,
|
|
3515
4158
|
tag: json.tag,
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
title: json.title
|
|
3519
|
-
},
|
|
3520
|
-
...json.sidebar && {
|
|
3521
|
-
sidebar: json.sidebar
|
|
3522
|
-
},
|
|
4159
|
+
sidebar: json.sidebar,
|
|
4160
|
+
display: json.display,
|
|
3523
4161
|
...json.idType && {
|
|
3524
4162
|
idType: json.idType
|
|
3525
4163
|
},
|
|
@@ -3562,38 +4200,6 @@ var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, ac
|
|
|
3562
4200
|
}
|
|
3563
4201
|
};
|
|
3564
4202
|
}, "fromJson");
|
|
3565
|
-
var unwrapZodType = /* @__PURE__ */ __name((type) => {
|
|
3566
|
-
if (type instanceof ZodOptional || type instanceof ZodNullable) {
|
|
3567
|
-
return unwrapZodType(type.unwrap());
|
|
3568
|
-
}
|
|
3569
|
-
return type;
|
|
3570
|
-
}, "unwrapZodType");
|
|
3571
|
-
var deriveRelationType = /* @__PURE__ */ __name((schema, columnId) => {
|
|
3572
|
-
if (!schema) return void 0;
|
|
3573
|
-
const field = schema.shape[columnId];
|
|
3574
|
-
if (!field) return void 0;
|
|
3575
|
-
const inner = unwrapZodType(field);
|
|
3576
|
-
return inner instanceof ZodArray ? "oneToMany" : "manyToOne";
|
|
3577
|
-
}, "deriveRelationType");
|
|
3578
|
-
var enrichRelationTypes = /* @__PURE__ */ __name((columns, schema) => {
|
|
3579
|
-
if (!schema) return columns;
|
|
3580
|
-
return columns.map((col) => {
|
|
3581
|
-
const fi = col.fieldInput;
|
|
3582
|
-
if (!fi) return col;
|
|
3583
|
-
const isRelationField = fi.type === "autocomplete" || fi.format === "relation";
|
|
3584
|
-
if (!isRelationField) return col;
|
|
3585
|
-
if (fi.relationType) return col;
|
|
3586
|
-
const derived = deriveRelationType(schema, col.id) ?? deriveRelationTypeFromColumns(col, columns);
|
|
3587
|
-
if (!derived) return col;
|
|
3588
|
-
return {
|
|
3589
|
-
...col,
|
|
3590
|
-
fieldInput: {
|
|
3591
|
-
...fi,
|
|
3592
|
-
relationType: derived
|
|
3593
|
-
}
|
|
3594
|
-
};
|
|
3595
|
-
});
|
|
3596
|
-
}, "enrichRelationTypes");
|
|
3597
4203
|
var buildLookup = /* @__PURE__ */ __name((columns) => {
|
|
3598
4204
|
if (!columns) return void 0;
|
|
3599
4205
|
const keyCol = columns.find((c) => c.idField);
|
|
@@ -3607,17 +4213,42 @@ var buildLookup = /* @__PURE__ */ __name((columns) => {
|
|
|
3607
4213
|
};
|
|
3608
4214
|
}, "buildLookup");
|
|
3609
4215
|
|
|
3610
|
-
// src/lib/crud/
|
|
3611
|
-
import {
|
|
3612
|
-
|
|
4216
|
+
// src/lib/crud/hooks/hooks.types.ts
|
|
4217
|
+
import { z as z18 } from "zod";
|
|
4218
|
+
var WriteOpSchema = z18.enum([
|
|
4219
|
+
"create",
|
|
4220
|
+
"update",
|
|
4221
|
+
"upsert",
|
|
4222
|
+
"delete"
|
|
4223
|
+
]);
|
|
4224
|
+
var ReadOpSchema = z18.enum([
|
|
4225
|
+
"findAll",
|
|
4226
|
+
"findOne"
|
|
4227
|
+
]);
|
|
4228
|
+
var ResourceHooksSchema = z18.object({
|
|
4229
|
+
beforeWrite: z18.custom().optional(),
|
|
4230
|
+
afterWrite: z18.custom().optional(),
|
|
4231
|
+
afterRead: z18.custom().optional()
|
|
4232
|
+
});
|
|
4233
|
+
|
|
4234
|
+
// src/lib/crud/hooks/hooks.loader.ts
|
|
4235
|
+
import { join as join6 } from "path";
|
|
4236
|
+
var loadResourceHooks = /* @__PURE__ */ __name(async (basePath) => {
|
|
4237
|
+
const file = findModule(basePath, "hooks");
|
|
4238
|
+
return file ? importDefault(file) : void 0;
|
|
4239
|
+
}, "loadResourceHooks");
|
|
3613
4240
|
var loadSubResourceHooks = /* @__PURE__ */ __name(async (subResources, basePath) => {
|
|
3614
4241
|
for (const sub of subResources) {
|
|
3615
|
-
const file = sub.name ?
|
|
4242
|
+
const file = sub.name ? findModule(join6(basePath, "hooks"), sub.name) : void 0;
|
|
3616
4243
|
if (!file) continue;
|
|
3617
4244
|
const hooks = await importDefault(file);
|
|
3618
4245
|
if (hooks) sub.hooks = hooks;
|
|
3619
4246
|
}
|
|
3620
4247
|
}, "loadSubResourceHooks");
|
|
4248
|
+
|
|
4249
|
+
// src/lib/crud/loader/index.ts
|
|
4250
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2 } from "fs";
|
|
4251
|
+
import { join as join7 } from "path";
|
|
3621
4252
|
var loadResourceConfigsFromDir = /* @__PURE__ */ __name(async (dirPath, baseUrl, enumsFile) => {
|
|
3622
4253
|
const enums = loadEnumRegistry(dirPath, enumsFile);
|
|
3623
4254
|
const entries = readdirSync2(dirPath, {
|
|
@@ -3626,22 +4257,21 @@ var loadResourceConfigsFromDir = /* @__PURE__ */ __name(async (dirPath, baseUrl,
|
|
|
3626
4257
|
const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
3627
4258
|
const configs = [];
|
|
3628
4259
|
for (const dir of dirs) {
|
|
3629
|
-
const basePath =
|
|
3630
|
-
const schemaFile =
|
|
4260
|
+
const basePath = join7(dirPath, dir);
|
|
4261
|
+
const schemaFile = findModule(basePath, "schema");
|
|
3631
4262
|
const schema = schemaFile ? await importDefault(schemaFile) : void 0;
|
|
3632
|
-
const
|
|
3633
|
-
const
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
const
|
|
3637
|
-
const
|
|
3638
|
-
const tableActions = await loadTableActions(json.tableActions ?? [], basePath);
|
|
4263
|
+
const hooks = await loadResourceHooks(basePath);
|
|
4264
|
+
const jsonFile = join7(basePath, "resource.json");
|
|
4265
|
+
if (existsSync6(jsonFile)) {
|
|
4266
|
+
const json = readResourceJson(jsonFile).json;
|
|
4267
|
+
const actions = await loadActions(json.actions ?? [], basePath, "row");
|
|
4268
|
+
const tableActions = await loadActions(json.tableActions ?? [], basePath, "table");
|
|
3639
4269
|
const config = fromJson(json, schema, hooks, basePath, baseUrl, actions, tableActions, enums);
|
|
3640
4270
|
await loadSubResourceHooks(config.subResources ?? [], basePath);
|
|
3641
4271
|
configs.push(config);
|
|
3642
4272
|
continue;
|
|
3643
4273
|
}
|
|
3644
|
-
const tsFile =
|
|
4274
|
+
const tsFile = findModule(basePath, "resource");
|
|
3645
4275
|
if (tsFile) {
|
|
3646
4276
|
const config = await importDefault(tsFile);
|
|
3647
4277
|
if (config) configs.push(hooks ? {
|
|
@@ -3692,11 +4322,18 @@ var CroutonApiModule = class _CroutonApiModule {
|
|
|
3692
4322
|
static {
|
|
3693
4323
|
__name(this, "CroutonApiModule");
|
|
3694
4324
|
}
|
|
3695
|
-
|
|
4325
|
+
onModuleInit() {
|
|
4326
|
+
if (!BigInt.prototype.toJSON) {
|
|
4327
|
+
BigInt.prototype.toJSON = function() {
|
|
4328
|
+
return Number(this);
|
|
4329
|
+
};
|
|
4330
|
+
}
|
|
4331
|
+
}
|
|
4332
|
+
static forResources(configs, dataSources, loader, { baseUrl }, config) {
|
|
3696
4333
|
const dataSourceRegistry = new DataSourceRegistry(dataSources);
|
|
3697
4334
|
const configRegistry = new ResourceConfigRegistry(loader, configs);
|
|
3698
4335
|
const controllers = [
|
|
3699
|
-
...configs.map((c) => createCrudController(c,
|
|
4336
|
+
...configs.map((c) => createCrudController(c, baseUrl)),
|
|
3700
4337
|
createAppLayoutController(configs, config.sidebarGroups, config.title, config.autoSave ?? true)
|
|
3701
4338
|
];
|
|
3702
4339
|
return {
|
|
@@ -3718,14 +4355,18 @@ var CroutonApiModule = class _CroutonApiModule {
|
|
|
3718
4355
|
]
|
|
3719
4356
|
};
|
|
3720
4357
|
}
|
|
3721
|
-
static async forResourceDir(dirPath, dataSourcesPath,
|
|
3722
|
-
const
|
|
3723
|
-
const
|
|
4358
|
+
static async forResourceDir(dirPath, dataSourcesPath, { baseUrl }) {
|
|
4359
|
+
const config = await loadConfig();
|
|
4360
|
+
const loader = new FileSystemResourceConfigLoader(dirPath, baseUrl, config.enumsFile);
|
|
4361
|
+
const configs = await loadResourceConfigsFromDir(dirPath, baseUrl, config.enumsFile);
|
|
3724
4362
|
const dataSources = await loadDataSourcesFromDir(dataSourcesPath);
|
|
3725
|
-
return _CroutonApiModule.forResources(configs, dataSources, loader,
|
|
4363
|
+
return _CroutonApiModule.forResources(configs, dataSources, loader, {
|
|
4364
|
+
baseUrl
|
|
4365
|
+
}, config);
|
|
3726
4366
|
}
|
|
3727
|
-
static forLoader(loader, configs, dataSources,
|
|
3728
|
-
|
|
4367
|
+
static async forLoader(loader, configs, dataSources, appConfig) {
|
|
4368
|
+
const config = await loadConfig();
|
|
4369
|
+
return _CroutonApiModule.forResources(configs, dataSources, loader, appConfig, config);
|
|
3729
4370
|
}
|
|
3730
4371
|
};
|
|
3731
4372
|
CroutonApiModule = _ts_decorate5([
|
|
@@ -3742,6 +4383,8 @@ export {
|
|
|
3742
4383
|
ResourceConfigLoader2 as ResourceConfigLoader,
|
|
3743
4384
|
ResourceConfigRegistry,
|
|
3744
4385
|
isOperationEnabled,
|
|
4386
|
+
isRowProcedureAction,
|
|
4387
|
+
isTableProcedureAction,
|
|
3745
4388
|
loadDataSourcesFromDir,
|
|
3746
4389
|
loadResourceConfigsFromDir,
|
|
3747
4390
|
resolveDefinition,
|