@ghentcdh/crouton-api 0.0.1-alpha.20 → 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 +1400 -756
- 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 +1367 -735
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
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,239 +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
|
-
if (schemaVisible) {
|
|
2994
|
-
const nonEditableIds = new Set(schemaCols.filter((c) => c.createable === false && c.updateable === false).map((c) => c.id));
|
|
2995
|
-
const required = jsonSchema["required"];
|
|
2996
|
-
if (Array.isArray(required) && nonEditableIds.size) {
|
|
2997
|
-
jsonSchema["required"] = required.filter((k) => !nonEditableIds.has(k));
|
|
2998
|
-
}
|
|
2999
|
-
}
|
|
3000
|
-
return {
|
|
3001
|
-
json_schema: jsonSchema,
|
|
3002
|
-
ui_schema: buildUiSchema(visibleCols),
|
|
3003
|
-
columns: visibleCols.map(toViewColumn)
|
|
3004
|
-
};
|
|
3005
|
-
}, "buildView");
|
|
3469
|
+
// src/lib/crud/builder/calculated-columns.builder.ts
|
|
3006
3470
|
var isVisibleInMode = /* @__PURE__ */ __name((c, mode) => mode === "table" ? !c.hiddenInTable : !c.hiddenInView, "isVisibleInMode");
|
|
3007
3471
|
var buildCalculatedElement = /* @__PURE__ */ __name((c, mode) => mode === "table" ? {
|
|
3008
3472
|
type: c.type === "boolean" ? "BooleanCell" : "TextCell",
|
|
@@ -3081,6 +3545,78 @@ var injectCalculatedColumnsIntoView = /* @__PURE__ */ __name((viewConfig, calcul
|
|
|
3081
3545
|
}, "injectCalculatedColumnsIntoView");
|
|
3082
3546
|
var injectCalculatedColumns = /* @__PURE__ */ __name((tableView, calculated) => injectCalculatedColumnsIntoView(tableView, calculated, "table"), "injectCalculatedColumns");
|
|
3083
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");
|
|
3084
3620
|
var emptyTableView = /* @__PURE__ */ __name(() => ({
|
|
3085
3621
|
json_schema: {
|
|
3086
3622
|
type: "object",
|
|
@@ -3099,7 +3635,7 @@ var buildViews = /* @__PURE__ */ __name((schema, columns) => {
|
|
|
3099
3635
|
} else if (columns?.length) {
|
|
3100
3636
|
views.table = emptyTableView();
|
|
3101
3637
|
}
|
|
3102
|
-
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));
|
|
3103
3639
|
if (form) views.form = form;
|
|
3104
3640
|
const filter = buildView(schema, columns, (c) => !!c.filterable, buildFormUiSchema, true);
|
|
3105
3641
|
if (filter) {
|
|
@@ -3119,7 +3655,6 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
3119
3655
|
if (!properties[c.column]) {
|
|
3120
3656
|
properties[c.column] = {
|
|
3121
3657
|
type: "object",
|
|
3122
|
-
additionalProperties: true,
|
|
3123
3658
|
properties: {}
|
|
3124
3659
|
};
|
|
3125
3660
|
}
|
|
@@ -3130,7 +3665,6 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
3130
3665
|
if (!target[segment]) {
|
|
3131
3666
|
target[segment] = {
|
|
3132
3667
|
type: "object",
|
|
3133
|
-
additionalProperties: true,
|
|
3134
3668
|
properties: {}
|
|
3135
3669
|
};
|
|
3136
3670
|
}
|
|
@@ -3151,11 +3685,12 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
3151
3685
|
};
|
|
3152
3686
|
}
|
|
3153
3687
|
}
|
|
3154
|
-
|
|
3688
|
+
const schema = {
|
|
3155
3689
|
type: "object",
|
|
3156
|
-
additionalProperties: true,
|
|
3157
3690
|
properties
|
|
3158
3691
|
};
|
|
3692
|
+
applySchemaTransforms(schema);
|
|
3693
|
+
return schema;
|
|
3159
3694
|
}, "buildJsonSchema");
|
|
3160
3695
|
const fixNestedScopes = /* @__PURE__ */ __name((uiSchema, cols) => {
|
|
3161
3696
|
const colMap = Object.fromEntries(cols.map((c) => [
|
|
@@ -3205,33 +3740,223 @@ var buildViewsFromColumns = /* @__PURE__ */ __name((columns) => {
|
|
|
3205
3740
|
return Object.keys(views).length ? views : void 0;
|
|
3206
3741
|
}, "buildViewsFromColumns");
|
|
3207
3742
|
|
|
3208
|
-
// 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
|
|
3209
3838
|
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
3210
|
-
import { dirname as
|
|
3211
|
-
var
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
};
|
|
3219
|
-
} catch {
|
|
3220
|
-
return void 0;
|
|
3221
|
-
}
|
|
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}`);
|
|
3222
3847
|
}
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
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);
|
|
3226
3859
|
try {
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
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);
|
|
3231
3866
|
} catch {
|
|
3232
3867
|
return void 0;
|
|
3233
3868
|
}
|
|
3234
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
|
|
3235
3960
|
var expandExtendColumns = /* @__PURE__ */ __name((columns, dirPath) => {
|
|
3236
3961
|
if (!dirPath) return columns;
|
|
3237
3962
|
const result = [];
|
|
@@ -3246,7 +3971,7 @@ var expandExtendColumns = /* @__PURE__ */ __name((columns, dirPath) => {
|
|
|
3246
3971
|
result.push(col);
|
|
3247
3972
|
continue;
|
|
3248
3973
|
}
|
|
3249
|
-
const refColumns =
|
|
3974
|
+
const refColumns = resolved.json.columns;
|
|
3250
3975
|
const parentColumnKey = col.column ?? col.id;
|
|
3251
3976
|
for (const refCol of refColumns) {
|
|
3252
3977
|
if (refCol.idField) continue;
|
|
@@ -3307,37 +4032,8 @@ var applyRelationFormatDefault = /* @__PURE__ */ __name((cols) => cols?.map((col
|
|
|
3307
4032
|
}
|
|
3308
4033
|
return col;
|
|
3309
4034
|
}), "applyRelationFormatDefault");
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
const fkNames = /* @__PURE__ */ new Set([
|
|
3313
|
-
`${base}_id`,
|
|
3314
|
-
`${col.id}_id`
|
|
3315
|
-
]);
|
|
3316
|
-
return cols.some((c) => fkNames.has(c.id)) ? "manyToOne" : "oneToMany";
|
|
3317
|
-
}, "deriveRelationTypeFromColumns");
|
|
3318
|
-
var enrichNestedRelationColumns = /* @__PURE__ */ __name((cols, dir, baseUrl) => {
|
|
3319
|
-
if (!cols || !dir) return cols;
|
|
3320
|
-
const base = baseUrl ?? "";
|
|
3321
|
-
return cols.map((col) => {
|
|
3322
|
-
if (col.fieldInput?.format !== "relation" || !col.fieldInput.resource) return col;
|
|
3323
|
-
const resolved = resolveChildResource(col.fieldInput.resource, dir);
|
|
3324
|
-
const targetRoute = resolved?.json?.route ?? col.fieldInput.resource.replace(/^\.\//, "").replace(/\/resource\.json$/, "").replace(/\.resource$/, "");
|
|
3325
|
-
const relationType = col.fieldInput.relationType ?? deriveRelationTypeFromColumns(col, cols);
|
|
3326
|
-
return {
|
|
3327
|
-
...col,
|
|
3328
|
-
fieldInput: {
|
|
3329
|
-
...col.fieldInput,
|
|
3330
|
-
relationType,
|
|
3331
|
-
options: {
|
|
3332
|
-
...col.fieldInput.options,
|
|
3333
|
-
uri: `${base}/${targetRoute}`,
|
|
3334
|
-
resourceUri: `${base}/${targetRoute}`,
|
|
3335
|
-
resource: `${base}/${targetRoute}/schemas`
|
|
3336
|
-
}
|
|
3337
|
-
}
|
|
3338
|
-
};
|
|
3339
|
-
});
|
|
3340
|
-
}, "enrichNestedRelationColumns");
|
|
4035
|
+
|
|
4036
|
+
// src/lib/crud/adapter/sub-resource.builder.ts
|
|
3341
4037
|
var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentModel, parentDir, enums = {}, baseUrl) => {
|
|
3342
4038
|
if (!columns || !parentDir) return [];
|
|
3343
4039
|
return columns.filter((c) => c.fieldInput?.format === "relation" && c.fieldInput?.resource).map((c) => {
|
|
@@ -3345,7 +4041,7 @@ var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentMode
|
|
|
3345
4041
|
const childJson = childResolved?.json;
|
|
3346
4042
|
const childDir = childResolved?.dir;
|
|
3347
4043
|
const childRoute = childJson?.route ?? c.fieldInput.resource.replace(/^\.\//, "").replace(/\.resource$/, "");
|
|
3348
|
-
const rawChildColumns = childJson
|
|
4044
|
+
const rawChildColumns = childJson?.columns;
|
|
3349
4045
|
const expandedChildColumns = rawChildColumns ? expandExtendColumns(rawChildColumns, childDir) : void 0;
|
|
3350
4046
|
const childColumns = applyRelationFormatDefault(expandedChildColumns) ?? expandedChildColumns;
|
|
3351
4047
|
injectEnumValues(childColumns, enums);
|
|
@@ -3407,71 +4103,10 @@ var buildSubResources = /* @__PURE__ */ __name((columns, parentRoute, parentMode
|
|
|
3407
4103
|
};
|
|
3408
4104
|
});
|
|
3409
4105
|
}, "buildSubResources");
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
const base = baseUrl ?? "";
|
|
3413
|
-
return columns.map((col) => {
|
|
3414
|
-
if (col.fieldInput?.format !== "relation") return col;
|
|
3415
|
-
const sub = subResources.find((s) => s.column === col.id);
|
|
3416
|
-
if (!sub) return col;
|
|
3417
|
-
return {
|
|
3418
|
-
...col,
|
|
3419
|
-
fieldInput: {
|
|
3420
|
-
...col.fieldInput,
|
|
3421
|
-
options: {
|
|
3422
|
-
...col.fieldInput.options,
|
|
3423
|
-
uri: `${base}/${parentRoute}/{id}/${sub.childRoute}`,
|
|
3424
|
-
resourceUri: `${base}/${sub.childRoute}`,
|
|
3425
|
-
...sub.views && {
|
|
3426
|
-
resource: `${base}/${parentRoute}/${sub.childRoute}/schemas`
|
|
3427
|
-
}
|
|
3428
|
-
}
|
|
3429
|
-
}
|
|
3430
|
-
};
|
|
3431
|
-
});
|
|
3432
|
-
}, "enrichActionColumns");
|
|
3433
|
-
var enrichResourceRefColumns = /* @__PURE__ */ __name((columns, parentDir, baseUrl) => {
|
|
3434
|
-
if (!columns || !parentDir) return columns;
|
|
3435
|
-
const base = baseUrl ?? "";
|
|
3436
|
-
return columns.map((col) => {
|
|
3437
|
-
if (!col.fieldInput?.resource || col.fieldInput.format === "relation") return col;
|
|
3438
|
-
const childResolved = resolveChildResource(col.fieldInput.resource, parentDir);
|
|
3439
|
-
const childRoute = childResolved?.json?.route ?? col.fieldInput.resource.replace(/^\.\//, "").replace(/\.resource$/, "");
|
|
3440
|
-
return {
|
|
3441
|
-
...col,
|
|
3442
|
-
fieldInput: {
|
|
3443
|
-
...col.fieldInput,
|
|
3444
|
-
options: {
|
|
3445
|
-
...col.fieldInput.options,
|
|
3446
|
-
resourceUri: `${base}/${childRoute}`,
|
|
3447
|
-
schemasUri: `${base}/${childRoute}/schemas`
|
|
3448
|
-
}
|
|
3449
|
-
}
|
|
3450
|
-
};
|
|
3451
|
-
});
|
|
3452
|
-
}, "enrichResourceRefColumns");
|
|
3453
|
-
var enrichIncludeWithSort = /* @__PURE__ */ __name((include, columns) => {
|
|
3454
|
-
if (!include?.length) return include;
|
|
3455
|
-
return include.map((entry) => {
|
|
3456
|
-
const relationName = typeof entry === "string" ? entry : entry.relation;
|
|
3457
|
-
const col = columns.find((c) => {
|
|
3458
|
-
const opts2 = c.fieldInput?.options;
|
|
3459
|
-
return (c.column ?? c.id) === relationName && opts2?.sort;
|
|
3460
|
-
});
|
|
3461
|
-
if (!col) return entry;
|
|
3462
|
-
const opts = col.fieldInput.options;
|
|
3463
|
-
const orderBy = buildChildSortClause(opts.sort, opts.sortDir ?? "asc");
|
|
3464
|
-
return typeof entry === "string" ? {
|
|
3465
|
-
relation: entry,
|
|
3466
|
-
orderBy
|
|
3467
|
-
} : {
|
|
3468
|
-
...entry,
|
|
3469
|
-
orderBy
|
|
3470
|
-
};
|
|
3471
|
-
});
|
|
3472
|
-
}, "enrichIncludeWithSort");
|
|
4106
|
+
|
|
4107
|
+
// src/lib/crud/adapter/json-adapter.ts
|
|
3473
4108
|
var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, actions, tableActions, enums = {}) => {
|
|
3474
|
-
const rawColumns = expandExtendColumns(
|
|
4109
|
+
const rawColumns = expandExtendColumns(json.columns, dirPath);
|
|
3475
4110
|
const columns = enrichRelationTypes(applyRelationFormatDefault(rawColumns) ?? rawColumns, schema);
|
|
3476
4111
|
injectEnumValues(columns, enums);
|
|
3477
4112
|
const subResources = buildSubResources(columns, json.route, json.model, dirPath, enums, baseUrl);
|
|
@@ -3515,22 +4150,14 @@ var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, ac
|
|
|
3515
4150
|
delete: true
|
|
3516
4151
|
}
|
|
3517
4152
|
};
|
|
3518
|
-
const display = {
|
|
3519
|
-
mode: json.display?.mode === "page" ? "page" : "modal",
|
|
3520
|
-
customComponent: json.display?.customComponent ?? null
|
|
3521
|
-
};
|
|
3522
4153
|
return {
|
|
4154
|
+
...json,
|
|
3523
4155
|
name: json.name,
|
|
3524
4156
|
route: json.route,
|
|
3525
4157
|
model: json.model,
|
|
3526
4158
|
tag: json.tag,
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
title: json.title
|
|
3530
|
-
},
|
|
3531
|
-
...json.sidebar && {
|
|
3532
|
-
sidebar: json.sidebar
|
|
3533
|
-
},
|
|
4159
|
+
sidebar: json.sidebar,
|
|
4160
|
+
display: json.display,
|
|
3534
4161
|
...json.idType && {
|
|
3535
4162
|
idType: json.idType
|
|
3536
4163
|
},
|
|
@@ -3573,38 +4200,6 @@ var fromJson = /* @__PURE__ */ __name((json, schema, hooks, dirPath, baseUrl, ac
|
|
|
3573
4200
|
}
|
|
3574
4201
|
};
|
|
3575
4202
|
}, "fromJson");
|
|
3576
|
-
var unwrapZodType = /* @__PURE__ */ __name((type) => {
|
|
3577
|
-
if (type instanceof ZodOptional || type instanceof ZodNullable) {
|
|
3578
|
-
return unwrapZodType(type.unwrap());
|
|
3579
|
-
}
|
|
3580
|
-
return type;
|
|
3581
|
-
}, "unwrapZodType");
|
|
3582
|
-
var deriveRelationType = /* @__PURE__ */ __name((schema, columnId) => {
|
|
3583
|
-
if (!schema) return void 0;
|
|
3584
|
-
const field = schema.shape[columnId];
|
|
3585
|
-
if (!field) return void 0;
|
|
3586
|
-
const inner = unwrapZodType(field);
|
|
3587
|
-
return inner instanceof ZodArray ? "oneToMany" : "manyToOne";
|
|
3588
|
-
}, "deriveRelationType");
|
|
3589
|
-
var enrichRelationTypes = /* @__PURE__ */ __name((columns, schema) => {
|
|
3590
|
-
if (!schema) return columns;
|
|
3591
|
-
return columns.map((col) => {
|
|
3592
|
-
const fi = col.fieldInput;
|
|
3593
|
-
if (!fi) return col;
|
|
3594
|
-
const isRelationField = fi.type === "autocomplete" || fi.format === "relation";
|
|
3595
|
-
if (!isRelationField) return col;
|
|
3596
|
-
if (fi.relationType) return col;
|
|
3597
|
-
const derived = deriveRelationType(schema, col.id) ?? deriveRelationTypeFromColumns(col, columns);
|
|
3598
|
-
if (!derived) return col;
|
|
3599
|
-
return {
|
|
3600
|
-
...col,
|
|
3601
|
-
fieldInput: {
|
|
3602
|
-
...fi,
|
|
3603
|
-
relationType: derived
|
|
3604
|
-
}
|
|
3605
|
-
};
|
|
3606
|
-
});
|
|
3607
|
-
}, "enrichRelationTypes");
|
|
3608
4203
|
var buildLookup = /* @__PURE__ */ __name((columns) => {
|
|
3609
4204
|
if (!columns) return void 0;
|
|
3610
4205
|
const keyCol = columns.find((c) => c.idField);
|
|
@@ -3618,17 +4213,42 @@ var buildLookup = /* @__PURE__ */ __name((columns) => {
|
|
|
3618
4213
|
};
|
|
3619
4214
|
}, "buildLookup");
|
|
3620
4215
|
|
|
3621
|
-
// src/lib/crud/
|
|
3622
|
-
import {
|
|
3623
|
-
|
|
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");
|
|
3624
4240
|
var loadSubResourceHooks = /* @__PURE__ */ __name(async (subResources, basePath) => {
|
|
3625
4241
|
for (const sub of subResources) {
|
|
3626
|
-
const file = sub.name ?
|
|
4242
|
+
const file = sub.name ? findModule(join6(basePath, "hooks"), sub.name) : void 0;
|
|
3627
4243
|
if (!file) continue;
|
|
3628
4244
|
const hooks = await importDefault(file);
|
|
3629
4245
|
if (hooks) sub.hooks = hooks;
|
|
3630
4246
|
}
|
|
3631
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";
|
|
3632
4252
|
var loadResourceConfigsFromDir = /* @__PURE__ */ __name(async (dirPath, baseUrl, enumsFile) => {
|
|
3633
4253
|
const enums = loadEnumRegistry(dirPath, enumsFile);
|
|
3634
4254
|
const entries = readdirSync2(dirPath, {
|
|
@@ -3637,22 +4257,21 @@ var loadResourceConfigsFromDir = /* @__PURE__ */ __name(async (dirPath, baseUrl,
|
|
|
3637
4257
|
const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
3638
4258
|
const configs = [];
|
|
3639
4259
|
for (const dir of dirs) {
|
|
3640
|
-
const basePath =
|
|
3641
|
-
const schemaFile =
|
|
4260
|
+
const basePath = join7(dirPath, dir);
|
|
4261
|
+
const schemaFile = findModule(basePath, "schema");
|
|
3642
4262
|
const schema = schemaFile ? await importDefault(schemaFile) : void 0;
|
|
3643
|
-
const
|
|
3644
|
-
const
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
const
|
|
3648
|
-
const
|
|
3649
|
-
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");
|
|
3650
4269
|
const config = fromJson(json, schema, hooks, basePath, baseUrl, actions, tableActions, enums);
|
|
3651
4270
|
await loadSubResourceHooks(config.subResources ?? [], basePath);
|
|
3652
4271
|
configs.push(config);
|
|
3653
4272
|
continue;
|
|
3654
4273
|
}
|
|
3655
|
-
const tsFile =
|
|
4274
|
+
const tsFile = findModule(basePath, "resource");
|
|
3656
4275
|
if (tsFile) {
|
|
3657
4276
|
const config = await importDefault(tsFile);
|
|
3658
4277
|
if (config) configs.push(hooks ? {
|
|
@@ -3703,11 +4322,18 @@ var CroutonApiModule = class _CroutonApiModule {
|
|
|
3703
4322
|
static {
|
|
3704
4323
|
__name(this, "CroutonApiModule");
|
|
3705
4324
|
}
|
|
3706
|
-
|
|
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) {
|
|
3707
4333
|
const dataSourceRegistry = new DataSourceRegistry(dataSources);
|
|
3708
4334
|
const configRegistry = new ResourceConfigRegistry(loader, configs);
|
|
3709
4335
|
const controllers = [
|
|
3710
|
-
...configs.map((c) => createCrudController(c,
|
|
4336
|
+
...configs.map((c) => createCrudController(c, baseUrl)),
|
|
3711
4337
|
createAppLayoutController(configs, config.sidebarGroups, config.title, config.autoSave ?? true)
|
|
3712
4338
|
];
|
|
3713
4339
|
return {
|
|
@@ -3729,14 +4355,18 @@ var CroutonApiModule = class _CroutonApiModule {
|
|
|
3729
4355
|
]
|
|
3730
4356
|
};
|
|
3731
4357
|
}
|
|
3732
|
-
static async forResourceDir(dirPath, dataSourcesPath,
|
|
3733
|
-
const
|
|
3734
|
-
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);
|
|
3735
4362
|
const dataSources = await loadDataSourcesFromDir(dataSourcesPath);
|
|
3736
|
-
return _CroutonApiModule.forResources(configs, dataSources, loader,
|
|
4363
|
+
return _CroutonApiModule.forResources(configs, dataSources, loader, {
|
|
4364
|
+
baseUrl
|
|
4365
|
+
}, config);
|
|
3737
4366
|
}
|
|
3738
|
-
static forLoader(loader, configs, dataSources,
|
|
3739
|
-
|
|
4367
|
+
static async forLoader(loader, configs, dataSources, appConfig) {
|
|
4368
|
+
const config = await loadConfig();
|
|
4369
|
+
return _CroutonApiModule.forResources(configs, dataSources, loader, appConfig, config);
|
|
3740
4370
|
}
|
|
3741
4371
|
};
|
|
3742
4372
|
CroutonApiModule = _ts_decorate5([
|
|
@@ -3753,6 +4383,8 @@ export {
|
|
|
3753
4383
|
ResourceConfigLoader2 as ResourceConfigLoader,
|
|
3754
4384
|
ResourceConfigRegistry,
|
|
3755
4385
|
isOperationEnabled,
|
|
4386
|
+
isRowProcedureAction,
|
|
4387
|
+
isTableProcedureAction,
|
|
3756
4388
|
loadDataSourcesFromDir,
|
|
3757
4389
|
loadResourceConfigsFromDir,
|
|
3758
4390
|
resolveDefinition,
|