@postxl/schema 1.6.0 → 1.8.0
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/field/discriminated-union.js +7 -0
- package/dist/field/field.d.ts +41 -7
- package/dist/field/field.js +6 -0
- package/dist/field/index.d.ts +1 -0
- package/dist/field/index.js +1 -0
- package/dist/field/json.d.ts +61 -0
- package/dist/field/json.js +92 -0
- package/dist/field/scalar.d.ts +3 -3
- package/dist/field/scalar.js +5 -7
- package/dist/field/shared/utils.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/model/model.json-decoder.d.ts +24 -0
- package/dist/model/model.json-decoder.js +5 -0
- package/dist/model/model.transformer.d.ts +97 -1
- package/dist/model/model.transformer.js +2 -1
- package/dist/model/model.types.d.ts +7 -0
- package/dist/project-schema/project-schema.auth.d.ts +50 -0
- package/dist/project-schema/project-schema.auth.js +59 -0
- package/dist/project-schema/project-schema.json-decoder.d.ts +86 -1
- package/dist/project-schema/project-schema.json-decoder.js +10 -2
- package/dist/project-schema/project-schema.transformer.d.ts +120 -2
- package/dist/project-schema/project-schema.transformer.js +91 -9
- package/dist/project-schema/project-schema.types.d.ts +9 -0
- package/package.json +2 -2
|
@@ -65,7 +65,7 @@ function addDefaults({ description, fields, standardFields, seed, faker, ...inpu
|
|
|
65
65
|
},
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
|
-
function brandModel({ name, schema, databaseName, standardFields, defaultField, labelField, keyField, ...input }) {
|
|
68
|
+
function brandModel({ name, schema, databaseName, standardFields, defaultField, labelField, keyField, defaultSort, ...input }) {
|
|
69
69
|
return {
|
|
70
70
|
...input,
|
|
71
71
|
name: (0, model_brands_1.toModelName)(name),
|
|
@@ -75,6 +75,7 @@ function brandModel({ name, schema, databaseName, standardFields, defaultField,
|
|
|
75
75
|
defaultFieldName: defaultField ? Field.toFieldName(defaultField) : undefined,
|
|
76
76
|
labelFieldName: labelField ? Field.toFieldName(labelField) : undefined,
|
|
77
77
|
keyFieldName: keyField ? Field.toFieldName(keyField) : undefined,
|
|
78
|
+
defaultSort: defaultSort?.map((fieldName) => Field.toFieldName(fieldName)),
|
|
78
79
|
};
|
|
79
80
|
}
|
|
80
81
|
function combineFields({ fields, standardFields, ...model }, ctx) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as Field from '../field';
|
|
2
|
+
import { AuthRuleSet } from '../project-schema/project-schema.auth';
|
|
2
3
|
import { DatabaseSchemaName } from '../project-schema/project-schema.brands';
|
|
3
4
|
import * as Branded from './model.brands';
|
|
4
5
|
export type Models = Map<Branded.ModelName, Model>;
|
|
@@ -20,6 +21,11 @@ export type Model = {
|
|
|
20
21
|
* Always defined since id field is always present.
|
|
21
22
|
*/
|
|
22
23
|
keyField: Field.FieldDatabaseNative;
|
|
24
|
+
/**
|
|
25
|
+
* Default sort order used by generated admin views when no explicit sort is provided.
|
|
26
|
+
* Entries are field names sorted ascending in the given order.
|
|
27
|
+
*/
|
|
28
|
+
defaultSort: Field.FieldName[];
|
|
23
29
|
indexes: ModelIndex[];
|
|
24
30
|
seed: Seed[];
|
|
25
31
|
/**
|
|
@@ -39,6 +45,7 @@ export type Model = {
|
|
|
39
45
|
*/
|
|
40
46
|
items: number;
|
|
41
47
|
};
|
|
48
|
+
auth?: AuthRuleSet;
|
|
42
49
|
};
|
|
43
50
|
export type ModelIndex = Field.FieldName[];
|
|
44
51
|
export type Seed = Record<string, unknown>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const zAuthRoleRuleJSON: z.ZodObject<{
|
|
3
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
4
|
+
}, z.core.$strip>;
|
|
5
|
+
export declare const zAuthRuleSetJSON: z.ZodObject<{
|
|
6
|
+
read: z.ZodOptional<z.ZodObject<{
|
|
7
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
8
|
+
}, z.core.$strip>>;
|
|
9
|
+
write: z.ZodOptional<z.ZodObject<{
|
|
10
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
11
|
+
}, z.core.$strip>>;
|
|
12
|
+
create: z.ZodOptional<z.ZodObject<{
|
|
13
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
14
|
+
}, z.core.$strip>>;
|
|
15
|
+
update: z.ZodOptional<z.ZodObject<{
|
|
16
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
17
|
+
}, z.core.$strip>>;
|
|
18
|
+
delete: z.ZodOptional<z.ZodObject<{
|
|
19
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
20
|
+
}, z.core.$strip>>;
|
|
21
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
22
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
23
|
+
}, z.core.$strip>>>;
|
|
24
|
+
adminUi: z.ZodOptional<z.ZodObject<{
|
|
25
|
+
visibleFor: z.ZodArray<z.ZodString>;
|
|
26
|
+
}, z.core.$strip>>;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
export declare const zAuthScopeRuleSetJSON: z.ZodObject<{
|
|
29
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
30
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
31
|
+
}, z.core.$strip>>>;
|
|
32
|
+
}, z.core.$strip>;
|
|
33
|
+
export declare const zProjectAuthJSON: z.ZodObject<{
|
|
34
|
+
provider: z.ZodDefault<z.ZodOptional<z.ZodLiteral<"keycloak">>>;
|
|
35
|
+
roleClaimPath: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
36
|
+
defaultDeny: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
37
|
+
scopes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
38
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
39
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
40
|
+
}, z.core.$strip>>>;
|
|
41
|
+
}, z.core.$strip>>>;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
export type AuthRoleRuleJSON = z.infer<typeof zAuthRoleRuleJSON>;
|
|
44
|
+
export type AuthRuleSetJSON = z.infer<typeof zAuthRuleSetJSON>;
|
|
45
|
+
export type AuthScopeRuleSetJSON = z.infer<typeof zAuthScopeRuleSetJSON>;
|
|
46
|
+
export type ProjectAuthJSON = z.infer<typeof zProjectAuthJSON>;
|
|
47
|
+
export type AuthRoleRule = AuthRoleRuleJSON;
|
|
48
|
+
export type AuthRuleSet = AuthRuleSetJSON;
|
|
49
|
+
export type AuthScopeRuleSet = AuthScopeRuleSetJSON;
|
|
50
|
+
export type ProjectAuth = ProjectAuthJSON;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.zProjectAuthJSON = exports.zAuthScopeRuleSetJSON = exports.zAuthRuleSetJSON = exports.zAuthRoleRuleJSON = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const zNonEmptyRole = zod_1.z.string().min(1, { error: 'Role must not be empty.' });
|
|
6
|
+
exports.zAuthRoleRuleJSON = zod_1.z.object({
|
|
7
|
+
anyRole: zod_1.z
|
|
8
|
+
.array(zNonEmptyRole)
|
|
9
|
+
.min(1, { error: 'anyRole must contain at least one role.' })
|
|
10
|
+
.describe('Allow access when the user has at least one of the listed roles.'),
|
|
11
|
+
});
|
|
12
|
+
exports.zAuthRuleSetJSON = zod_1.z.object({
|
|
13
|
+
read: exports.zAuthRoleRuleJSON.optional().describe('Role rule for read access to model data.'),
|
|
14
|
+
write: exports.zAuthRoleRuleJSON.optional().describe('Role rule for write access shorthand (create, update, delete).'),
|
|
15
|
+
create: exports.zAuthRoleRuleJSON.optional().describe('Role rule for create access.'),
|
|
16
|
+
update: exports.zAuthRoleRuleJSON.optional().describe('Role rule for update access.'),
|
|
17
|
+
delete: exports.zAuthRoleRuleJSON.optional().describe('Role rule for delete access.'),
|
|
18
|
+
actions: zod_1.z
|
|
19
|
+
.record(zod_1.z.string().min(1), exports.zAuthRoleRuleJSON)
|
|
20
|
+
.optional()
|
|
21
|
+
.describe('Role rules for model actions. Keys are action names, e.g. "publish".'),
|
|
22
|
+
adminUi: zod_1.z
|
|
23
|
+
.object({
|
|
24
|
+
visibleFor: zod_1.z
|
|
25
|
+
.array(zNonEmptyRole)
|
|
26
|
+
.min(1, { error: 'visibleFor must contain at least one role.' })
|
|
27
|
+
.describe('Roles that can see and access this model in the Admin UI.'),
|
|
28
|
+
})
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('Admin UI visibility settings for this schema/model.'),
|
|
31
|
+
});
|
|
32
|
+
exports.zAuthScopeRuleSetJSON = zod_1.z.object({
|
|
33
|
+
actions: zod_1.z
|
|
34
|
+
.record(zod_1.z.string().min(1), exports.zAuthRoleRuleJSON)
|
|
35
|
+
.optional()
|
|
36
|
+
.describe('Role rules for actions within this scope. Keys are action names or "*".'),
|
|
37
|
+
});
|
|
38
|
+
exports.zProjectAuthJSON = zod_1.z.object({
|
|
39
|
+
provider: zod_1.z
|
|
40
|
+
.literal('keycloak')
|
|
41
|
+
.optional()
|
|
42
|
+
.default('keycloak')
|
|
43
|
+
.describe('Authentication/authorization provider used by generated projects.'),
|
|
44
|
+
roleClaimPath: zod_1.z
|
|
45
|
+
.string()
|
|
46
|
+
.min(1)
|
|
47
|
+
.optional()
|
|
48
|
+
.default('realm_access.roles')
|
|
49
|
+
.describe('JWT claim path that contains roles, e.g. "realm_access.roles".'),
|
|
50
|
+
defaultDeny: zod_1.z
|
|
51
|
+
.boolean()
|
|
52
|
+
.optional()
|
|
53
|
+
.default(true)
|
|
54
|
+
.describe('If true, access is denied when no matching auth rule is configured.'),
|
|
55
|
+
scopes: zod_1.z
|
|
56
|
+
.record(zod_1.z.string().min(1), exports.zAuthScopeRuleSetJSON)
|
|
57
|
+
.optional()
|
|
58
|
+
.describe('Authorization rules for non-model action scopes (for example "import").'),
|
|
59
|
+
});
|
|
@@ -1,19 +1,103 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
export declare const zSchemaName: z.ZodString;
|
|
3
|
+
export declare const zSchemaJSON: z.ZodObject<{
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
6
|
+
read: z.ZodOptional<z.ZodObject<{
|
|
7
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
8
|
+
}, z.core.$strip>>;
|
|
9
|
+
write: z.ZodOptional<z.ZodObject<{
|
|
10
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
11
|
+
}, z.core.$strip>>;
|
|
12
|
+
create: z.ZodOptional<z.ZodObject<{
|
|
13
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
14
|
+
}, z.core.$strip>>;
|
|
15
|
+
update: z.ZodOptional<z.ZodObject<{
|
|
16
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
17
|
+
}, z.core.$strip>>;
|
|
18
|
+
delete: z.ZodOptional<z.ZodObject<{
|
|
19
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
20
|
+
}, z.core.$strip>>;
|
|
21
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
22
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
23
|
+
}, z.core.$strip>>>;
|
|
24
|
+
adminUi: z.ZodOptional<z.ZodObject<{
|
|
25
|
+
visibleFor: z.ZodArray<z.ZodString>;
|
|
26
|
+
}, z.core.$strip>>;
|
|
27
|
+
}, z.core.$strip>>;
|
|
28
|
+
}, z.core.$strip>;
|
|
3
29
|
export declare const zProjectSchemaJSON: z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodObject<{
|
|
4
30
|
name: z.ZodString;
|
|
5
31
|
slug: z.ZodString;
|
|
6
32
|
description: z.ZodOptional<z.ZodString>;
|
|
7
33
|
projectType: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"standalone">, z.ZodLiteral<"workspace">]>>>;
|
|
8
34
|
version: z.ZodOptional<z.ZodString>;
|
|
9
|
-
schemas: z.ZodOptional<z.ZodArray<z.ZodString
|
|
35
|
+
schemas: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
36
|
+
name: z.ZodString;
|
|
37
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
38
|
+
read: z.ZodOptional<z.ZodObject<{
|
|
39
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
40
|
+
}, z.core.$strip>>;
|
|
41
|
+
write: z.ZodOptional<z.ZodObject<{
|
|
42
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
43
|
+
}, z.core.$strip>>;
|
|
44
|
+
create: z.ZodOptional<z.ZodObject<{
|
|
45
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
46
|
+
}, z.core.$strip>>;
|
|
47
|
+
update: z.ZodOptional<z.ZodObject<{
|
|
48
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
49
|
+
}, z.core.$strip>>;
|
|
50
|
+
delete: z.ZodOptional<z.ZodObject<{
|
|
51
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
52
|
+
}, z.core.$strip>>;
|
|
53
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
54
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
55
|
+
}, z.core.$strip>>>;
|
|
56
|
+
adminUi: z.ZodOptional<z.ZodObject<{
|
|
57
|
+
visibleFor: z.ZodArray<z.ZodString>;
|
|
58
|
+
}, z.core.$strip>>;
|
|
59
|
+
}, z.core.$strip>>;
|
|
60
|
+
}, z.core.$strip>]>>>;
|
|
10
61
|
defaultSchema: z.ZodOptional<z.ZodString>;
|
|
62
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
63
|
+
provider: z.ZodDefault<z.ZodOptional<z.ZodLiteral<"keycloak">>>;
|
|
64
|
+
roleClaimPath: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
65
|
+
defaultDeny: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
66
|
+
scopes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
67
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
68
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
69
|
+
}, z.core.$strip>>>;
|
|
70
|
+
}, z.core.$strip>>>;
|
|
71
|
+
}, z.core.$strip>>;
|
|
11
72
|
systemUser: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
12
73
|
standardModels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
13
74
|
models: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodObject<{
|
|
14
75
|
name: z.ZodString;
|
|
15
76
|
description: z.ZodOptional<z.ZodString>;
|
|
16
77
|
isReadonly: z.ZodOptional<z.ZodBoolean>;
|
|
78
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
79
|
+
read: z.ZodOptional<z.ZodObject<{
|
|
80
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
81
|
+
}, z.core.$strip>>;
|
|
82
|
+
write: z.ZodOptional<z.ZodObject<{
|
|
83
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
84
|
+
}, z.core.$strip>>;
|
|
85
|
+
create: z.ZodOptional<z.ZodObject<{
|
|
86
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
87
|
+
}, z.core.$strip>>;
|
|
88
|
+
update: z.ZodOptional<z.ZodObject<{
|
|
89
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
90
|
+
}, z.core.$strip>>;
|
|
91
|
+
delete: z.ZodOptional<z.ZodObject<{
|
|
92
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
93
|
+
}, z.core.$strip>>;
|
|
94
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
95
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
96
|
+
}, z.core.$strip>>>;
|
|
97
|
+
adminUi: z.ZodOptional<z.ZodObject<{
|
|
98
|
+
visibleFor: z.ZodArray<z.ZodString>;
|
|
99
|
+
}, z.core.$strip>>;
|
|
100
|
+
}, z.core.$strip>>;
|
|
17
101
|
schema: z.ZodOptional<z.ZodString>;
|
|
18
102
|
databaseName: z.ZodOptional<z.ZodString>;
|
|
19
103
|
excelName: z.ZodOptional<z.ZodString>;
|
|
@@ -24,6 +108,7 @@ export declare const zProjectSchemaJSON: z.ZodPipe<z.ZodTransform<unknown, unkno
|
|
|
24
108
|
defaultField: z.ZodOptional<z.ZodString>;
|
|
25
109
|
labelField: z.ZodOptional<z.ZodString>;
|
|
26
110
|
keyField: z.ZodOptional<z.ZodString>;
|
|
111
|
+
defaultSort: z.ZodOptional<z.ZodArray<z.core.$ZodBranded<z.ZodString, "PXL.FieldName", "out">>>;
|
|
27
112
|
indexes: z.ZodOptional<z.ZodArray<z.ZodArray<z.core.$ZodBranded<z.ZodString, "PXL.FieldName", "out">>>>;
|
|
28
113
|
seed: z.ZodOptional<z.ZodArray<z.ZodAny>>;
|
|
29
114
|
source: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
@@ -33,19 +33,24 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.zProjectSchemaJSON = exports.zSchemaName = void 0;
|
|
36
|
+
exports.zProjectSchemaJSON = exports.zSchemaJSON = exports.zSchemaName = void 0;
|
|
37
37
|
const zod_1 = require("zod");
|
|
38
38
|
const utils_1 = require("@postxl/utils");
|
|
39
39
|
const Enum = __importStar(require("../enum"));
|
|
40
40
|
const extract_inline_enums_1 = require("../extract-inline-enums");
|
|
41
41
|
const Model = __importStar(require("../model"));
|
|
42
42
|
const normalize_named_collection_1 = require("../normalize-named-collection");
|
|
43
|
+
const project_schema_auth_1 = require("./project-schema.auth");
|
|
43
44
|
exports.zSchemaName = zod_1.z
|
|
44
45
|
//
|
|
45
46
|
.string()
|
|
46
47
|
.min(1, { error: 'Schema name must not be empty' })
|
|
47
48
|
.regex(/^\w+$/, { error: 'Schema name can only contain letters, numbers and underscores.' })
|
|
48
49
|
.describe('Name of the database schema.');
|
|
50
|
+
exports.zSchemaJSON = zod_1.z.object({
|
|
51
|
+
name: exports.zSchemaName,
|
|
52
|
+
auth: project_schema_auth_1.zAuthRuleSetJSON.optional(),
|
|
53
|
+
});
|
|
49
54
|
exports.zProjectSchemaJSON = zod_1.z
|
|
50
55
|
// We want to keep any extra fields that are not defined in the schema. However, these fields should
|
|
51
56
|
// not really be exposed as "main fields" of the parsed schema - instead, they should be nested under
|
|
@@ -101,7 +106,7 @@ exports.zProjectSchemaJSON = zod_1.z
|
|
|
101
106
|
.describe('The version of the project/schema. Should follow semantic versioning, see https://semver.org/.'),
|
|
102
107
|
schemas: zod_1.z
|
|
103
108
|
//
|
|
104
|
-
.array(exports.zSchemaName)
|
|
109
|
+
.array(zod_1.z.union([exports.zSchemaName, exports.zSchemaJSON]))
|
|
105
110
|
.min(1, {
|
|
106
111
|
error: 'Schemas of the project must not be empty! If you want to use the default schemas, omit this field.',
|
|
107
112
|
})
|
|
@@ -111,6 +116,9 @@ exports.zProjectSchemaJSON = zod_1.z
|
|
|
111
116
|
//
|
|
112
117
|
.optional()
|
|
113
118
|
.describe(`The default database schema that is used if model/enum does not specify a schema. If not provided, the default schema "Data" is used.`),
|
|
119
|
+
auth: project_schema_auth_1.zProjectAuthJSON
|
|
120
|
+
.optional()
|
|
121
|
+
.describe('Project-level authentication settings (provider, role claim path, and default behavior).'),
|
|
114
122
|
systemUser: zod_1.z
|
|
115
123
|
//
|
|
116
124
|
.record(zod_1.z.string(), zod_1.z.any())
|
|
@@ -11,14 +11,72 @@ export declare const zProjectSchema: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown,
|
|
|
11
11
|
description: z.ZodOptional<z.ZodString>;
|
|
12
12
|
projectType: z.ZodDefault<z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"standalone">, z.ZodLiteral<"workspace">]>>>;
|
|
13
13
|
version: z.ZodOptional<z.ZodString>;
|
|
14
|
-
schemas: z.ZodOptional<z.ZodArray<z.ZodString
|
|
14
|
+
schemas: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
15
|
+
name: z.ZodString;
|
|
16
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
17
|
+
read: z.ZodOptional<z.ZodObject<{
|
|
18
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
19
|
+
}, z.core.$strip>>;
|
|
20
|
+
write: z.ZodOptional<z.ZodObject<{
|
|
21
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
22
|
+
}, z.core.$strip>>;
|
|
23
|
+
create: z.ZodOptional<z.ZodObject<{
|
|
24
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
25
|
+
}, z.core.$strip>>;
|
|
26
|
+
update: z.ZodOptional<z.ZodObject<{
|
|
27
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
28
|
+
}, z.core.$strip>>;
|
|
29
|
+
delete: z.ZodOptional<z.ZodObject<{
|
|
30
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
31
|
+
}, z.core.$strip>>;
|
|
32
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
33
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
34
|
+
}, z.core.$strip>>>;
|
|
35
|
+
adminUi: z.ZodOptional<z.ZodObject<{
|
|
36
|
+
visibleFor: z.ZodArray<z.ZodString>;
|
|
37
|
+
}, z.core.$strip>>;
|
|
38
|
+
}, z.core.$strip>>;
|
|
39
|
+
}, z.core.$strip>]>>>;
|
|
15
40
|
defaultSchema: z.ZodOptional<z.ZodString>;
|
|
41
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
42
|
+
provider: z.ZodDefault<z.ZodOptional<z.ZodLiteral<"keycloak">>>;
|
|
43
|
+
roleClaimPath: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
44
|
+
defaultDeny: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
45
|
+
scopes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
46
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
47
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
48
|
+
}, z.core.$strip>>>;
|
|
49
|
+
}, z.core.$strip>>>;
|
|
50
|
+
}, z.core.$strip>>;
|
|
16
51
|
systemUser: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
17
52
|
standardModels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
18
53
|
models: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodObject<{
|
|
19
54
|
name: z.ZodString;
|
|
20
55
|
description: z.ZodOptional<z.ZodString>;
|
|
21
56
|
isReadonly: z.ZodOptional<z.ZodBoolean>;
|
|
57
|
+
auth: z.ZodOptional<z.ZodObject<{
|
|
58
|
+
read: z.ZodOptional<z.ZodObject<{
|
|
59
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
60
|
+
}, z.core.$strip>>;
|
|
61
|
+
write: z.ZodOptional<z.ZodObject<{
|
|
62
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
63
|
+
}, z.core.$strip>>;
|
|
64
|
+
create: z.ZodOptional<z.ZodObject<{
|
|
65
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
66
|
+
}, z.core.$strip>>;
|
|
67
|
+
update: z.ZodOptional<z.ZodObject<{
|
|
68
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
69
|
+
}, z.core.$strip>>;
|
|
70
|
+
delete: z.ZodOptional<z.ZodObject<{
|
|
71
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
72
|
+
}, z.core.$strip>>;
|
|
73
|
+
actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
74
|
+
anyRole: z.ZodArray<z.ZodString>;
|
|
75
|
+
}, z.core.$strip>>>;
|
|
76
|
+
adminUi: z.ZodOptional<z.ZodObject<{
|
|
77
|
+
visibleFor: z.ZodArray<z.ZodString>;
|
|
78
|
+
}, z.core.$strip>>;
|
|
79
|
+
}, z.core.$strip>>;
|
|
22
80
|
schema: z.ZodOptional<z.ZodString>;
|
|
23
81
|
databaseName: z.ZodOptional<z.ZodString>;
|
|
24
82
|
excelName: z.ZodOptional<z.ZodString>;
|
|
@@ -29,6 +87,7 @@ export declare const zProjectSchema: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown,
|
|
|
29
87
|
defaultField: z.ZodOptional<z.ZodString>;
|
|
30
88
|
labelField: z.ZodOptional<z.ZodString>;
|
|
31
89
|
keyField: z.ZodOptional<z.ZodString>;
|
|
90
|
+
defaultSort: z.ZodOptional<z.ZodArray<z.core.$ZodBranded<z.ZodString, "PXL.FieldName", "out">>>;
|
|
32
91
|
indexes: z.ZodOptional<z.ZodArray<z.ZodArray<z.core.$ZodBranded<z.ZodString, "PXL.FieldName", "out">>>>;
|
|
33
92
|
seed: z.ZodOptional<z.ZodArray<z.ZodAny>>;
|
|
34
93
|
source: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
@@ -56,14 +115,72 @@ export declare const zProjectSchema: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown,
|
|
|
56
115
|
source: Record<string, unknown>;
|
|
57
116
|
description?: string | undefined;
|
|
58
117
|
version?: string | undefined;
|
|
59
|
-
schemas?: string
|
|
118
|
+
schemas?: (string | {
|
|
119
|
+
name: string;
|
|
120
|
+
auth?: {
|
|
121
|
+
read?: {
|
|
122
|
+
anyRole: string[];
|
|
123
|
+
} | undefined;
|
|
124
|
+
write?: {
|
|
125
|
+
anyRole: string[];
|
|
126
|
+
} | undefined;
|
|
127
|
+
create?: {
|
|
128
|
+
anyRole: string[];
|
|
129
|
+
} | undefined;
|
|
130
|
+
update?: {
|
|
131
|
+
anyRole: string[];
|
|
132
|
+
} | undefined;
|
|
133
|
+
delete?: {
|
|
134
|
+
anyRole: string[];
|
|
135
|
+
} | undefined;
|
|
136
|
+
actions?: Record<string, {
|
|
137
|
+
anyRole: string[];
|
|
138
|
+
}> | undefined;
|
|
139
|
+
adminUi?: {
|
|
140
|
+
visibleFor: string[];
|
|
141
|
+
} | undefined;
|
|
142
|
+
} | undefined;
|
|
143
|
+
})[] | undefined;
|
|
60
144
|
defaultSchema?: string | undefined;
|
|
145
|
+
auth?: {
|
|
146
|
+
provider: "keycloak";
|
|
147
|
+
roleClaimPath: string;
|
|
148
|
+
defaultDeny: boolean;
|
|
149
|
+
scopes?: Record<string, {
|
|
150
|
+
actions?: Record<string, {
|
|
151
|
+
anyRole: string[];
|
|
152
|
+
}> | undefined;
|
|
153
|
+
}> | undefined;
|
|
154
|
+
} | undefined;
|
|
61
155
|
systemUser?: Record<string, any> | undefined;
|
|
62
156
|
standardModels?: string[] | undefined;
|
|
63
157
|
models?: {
|
|
64
158
|
name: string;
|
|
65
159
|
description?: string | undefined;
|
|
66
160
|
isReadonly?: boolean | undefined;
|
|
161
|
+
auth?: {
|
|
162
|
+
read?: {
|
|
163
|
+
anyRole: string[];
|
|
164
|
+
} | undefined;
|
|
165
|
+
write?: {
|
|
166
|
+
anyRole: string[];
|
|
167
|
+
} | undefined;
|
|
168
|
+
create?: {
|
|
169
|
+
anyRole: string[];
|
|
170
|
+
} | undefined;
|
|
171
|
+
update?: {
|
|
172
|
+
anyRole: string[];
|
|
173
|
+
} | undefined;
|
|
174
|
+
delete?: {
|
|
175
|
+
anyRole: string[];
|
|
176
|
+
} | undefined;
|
|
177
|
+
actions?: Record<string, {
|
|
178
|
+
anyRole: string[];
|
|
179
|
+
}> | undefined;
|
|
180
|
+
adminUi?: {
|
|
181
|
+
visibleFor: string[];
|
|
182
|
+
} | undefined;
|
|
183
|
+
} | undefined;
|
|
67
184
|
schema?: string | undefined;
|
|
68
185
|
databaseName?: string | undefined;
|
|
69
186
|
excelName?: string | undefined;
|
|
@@ -75,6 +192,7 @@ export declare const zProjectSchema: z.ZodPipe<z.ZodPipe<z.ZodTransform<unknown,
|
|
|
75
192
|
defaultField?: string | undefined;
|
|
76
193
|
labelField?: string | undefined;
|
|
77
194
|
keyField?: string | undefined;
|
|
195
|
+
defaultSort?: (string & z.core.$brand<"PXL.FieldName">)[] | undefined;
|
|
78
196
|
indexes?: (string & z.core.$brand<"PXL.FieldName">)[][] | undefined;
|
|
79
197
|
seed?: any[] | undefined;
|
|
80
198
|
source?: Record<string, unknown> | undefined;
|
|
@@ -43,6 +43,21 @@ const Model = __importStar(require("../model"));
|
|
|
43
43
|
const Branded = __importStar(require("./project-schema.brands"));
|
|
44
44
|
const project_schema_defaults_1 = require("./project-schema.defaults");
|
|
45
45
|
const project_schema_json_decoder_1 = require("./project-schema.json-decoder");
|
|
46
|
+
function extractSchemaNamesAndAuth(schemas) {
|
|
47
|
+
const schemaNames = [];
|
|
48
|
+
const schemaAuth = new Map();
|
|
49
|
+
for (const schema of schemas ?? []) {
|
|
50
|
+
if (typeof schema === 'string') {
|
|
51
|
+
schemaNames.push(schema);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
schemaNames.push(schema.name);
|
|
55
|
+
if (schema.auth) {
|
|
56
|
+
schemaAuth.set(schema.name, schema.auth);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return { schemaNames, schemaAuth };
|
|
60
|
+
}
|
|
46
61
|
function transformProjectSchemaJSON(input, ctx) {
|
|
47
62
|
const result = (0, utils_1.pipeZodTransformers)(input, ctx, [
|
|
48
63
|
convertRecordsToMaps,
|
|
@@ -68,8 +83,9 @@ function convertRecordsToMaps(input) {
|
|
|
68
83
|
};
|
|
69
84
|
}
|
|
70
85
|
function addDefaults(input) {
|
|
71
|
-
const
|
|
72
|
-
const
|
|
86
|
+
const { schemaNames, schemaAuth } = extractSchemaNamesAndAuth(input.schemas);
|
|
87
|
+
const schemas = schemaNames.length > 0 ? schemaNames : [project_schema_defaults_1.databaseSchemaNameData, project_schema_defaults_1.databaseSchemaNameConfig];
|
|
88
|
+
const defaultSchema = getDefaultSchema(schemaNames, input.defaultSchema);
|
|
73
89
|
return {
|
|
74
90
|
name: input.name,
|
|
75
91
|
slug: input.slug,
|
|
@@ -77,7 +93,9 @@ function addDefaults(input) {
|
|
|
77
93
|
projectType: input.projectType ?? 'standalone',
|
|
78
94
|
version: input.version ?? '0.0.1',
|
|
79
95
|
schemas,
|
|
96
|
+
schemaAuth,
|
|
80
97
|
defaultSchema,
|
|
98
|
+
...(input.auth ? { auth: input.auth } : {}),
|
|
81
99
|
systemUser: {
|
|
82
100
|
...project_schema_defaults_1.defaultSystemUser,
|
|
83
101
|
...input.systemUser,
|
|
@@ -101,12 +119,13 @@ function getDefaultSchema(schemas, defaultSchema) {
|
|
|
101
119
|
}
|
|
102
120
|
return schemas[0];
|
|
103
121
|
}
|
|
104
|
-
function brandProjectSchema({ name, slug, schemas, defaultSchema, standardModels, standardEnums, ...input }) {
|
|
122
|
+
function brandProjectSchema({ name, slug, schemas, schemaAuth, defaultSchema, standardModels, standardEnums, ...input }) {
|
|
105
123
|
return {
|
|
106
124
|
...input,
|
|
107
125
|
name: Branded.toProjectSchemaName(name),
|
|
108
126
|
slug: Branded.toProjectSlug(slug),
|
|
109
127
|
databaseSchemas: schemas.map((s) => Branded.toDatabaseSchemaName(s)),
|
|
128
|
+
schemaAuth: new Map([...schemaAuth.entries()].map(([schemaName, auth]) => [Branded.toDatabaseSchemaName(schemaName), auth])),
|
|
110
129
|
defaultDatabaseSchema: Branded.toDatabaseSchemaName(defaultSchema),
|
|
111
130
|
standardModels: standardModels.map((s) => Model.toModelName(s)),
|
|
112
131
|
standardEnums: standardEnums.map((s) => Enum.toEnumName(s)),
|
|
@@ -256,13 +275,30 @@ function decodeFields({ modelsArray, ...projectSchema }, ctx) {
|
|
|
256
275
|
function transformModels(projectSchema, ctx) {
|
|
257
276
|
const models = new Map();
|
|
258
277
|
for (const inputModelName of projectSchema.modelNames) {
|
|
259
|
-
const
|
|
278
|
+
const inputModel = projectSchema.models.get(inputModelName);
|
|
279
|
+
if (!inputModel) {
|
|
280
|
+
ctx.addIssue({
|
|
281
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
282
|
+
message: `Model ${inputModelName} is missing after field decoding`,
|
|
283
|
+
});
|
|
284
|
+
return zod_1.z.NEVER;
|
|
285
|
+
}
|
|
286
|
+
const model = transformModel(inputModel, projectSchema, ctx);
|
|
260
287
|
models.set(model.name, model);
|
|
261
288
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
289
|
+
const { auth, ...remainingProjectSchema } = projectSchema;
|
|
290
|
+
// Keep optional field shape clean: only include `auth` when it is actually set,
|
|
291
|
+
// instead of returning `auth: undefined`.
|
|
292
|
+
return auth
|
|
293
|
+
? {
|
|
294
|
+
...remainingProjectSchema,
|
|
295
|
+
auth,
|
|
296
|
+
models,
|
|
297
|
+
}
|
|
298
|
+
: {
|
|
299
|
+
...remainingProjectSchema,
|
|
300
|
+
models,
|
|
301
|
+
};
|
|
266
302
|
}
|
|
267
303
|
function transformModel(model, projectSchema, ctx) {
|
|
268
304
|
const fields = transformFields(model, projectSchema, ctx);
|
|
@@ -271,14 +307,17 @@ function transformModel(model, projectSchema, ctx) {
|
|
|
271
307
|
const defaultField = extractDefaultField(model, fields, ctx);
|
|
272
308
|
const labelField = extractLabelField(model, fields, ctx);
|
|
273
309
|
const keyField = extractKeyField(model, fields, idField, ctx);
|
|
274
|
-
const
|
|
310
|
+
const defaultSort = extractDefaultSort(model, fields, ctx);
|
|
311
|
+
const { defaultFieldName, labelFieldName, keyFieldName, auth, ...remainingModel } = model;
|
|
275
312
|
return {
|
|
276
313
|
...remainingModel,
|
|
314
|
+
...(auth ? { auth } : {}),
|
|
277
315
|
databaseSchema: model.schema ?? projectSchema.defaultDatabaseSchema,
|
|
278
316
|
fields,
|
|
279
317
|
defaultField,
|
|
280
318
|
labelField,
|
|
281
319
|
keyField,
|
|
320
|
+
defaultSort,
|
|
282
321
|
idField,
|
|
283
322
|
};
|
|
284
323
|
}
|
|
@@ -493,6 +532,49 @@ function extractKeyFieldFromFallbacks(fields, idField) {
|
|
|
493
532
|
// id field is always present and is always a string
|
|
494
533
|
return idField;
|
|
495
534
|
}
|
|
535
|
+
const defaultSortFallbackCandidates = [
|
|
536
|
+
Field.toFieldName('order'),
|
|
537
|
+
Field.toFieldName('sequence'),
|
|
538
|
+
Field.toFieldName('count'),
|
|
539
|
+
Field.toFieldName('name'),
|
|
540
|
+
Field.toFieldName('label'),
|
|
541
|
+
Field.toFieldName('id'),
|
|
542
|
+
];
|
|
543
|
+
function extractDefaultSort(model, fields, ctx) {
|
|
544
|
+
const idFieldName = Field.standardFieldName_id;
|
|
545
|
+
const defaultSort = model.defaultSort;
|
|
546
|
+
if (defaultSort && defaultSort.length > 0) {
|
|
547
|
+
const result = [];
|
|
548
|
+
const seen = new Set();
|
|
549
|
+
for (const fieldName of defaultSort) {
|
|
550
|
+
if (!fields.has(fieldName)) {
|
|
551
|
+
ctx.addIssue({
|
|
552
|
+
code: zod_1.z.ZodIssueCode.custom,
|
|
553
|
+
message: `Default sort field ${fieldName} is not defined in model ${model.name}!`,
|
|
554
|
+
});
|
|
555
|
+
return zod_1.z.NEVER;
|
|
556
|
+
}
|
|
557
|
+
if (!seen.has(fieldName)) {
|
|
558
|
+
seen.add(fieldName);
|
|
559
|
+
result.push(fieldName);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
if (!seen.has(idFieldName) && fields.has(idFieldName)) {
|
|
563
|
+
result.push(idFieldName);
|
|
564
|
+
}
|
|
565
|
+
return result;
|
|
566
|
+
}
|
|
567
|
+
const fallbacks = [];
|
|
568
|
+
for (const candidate of defaultSortFallbackCandidates) {
|
|
569
|
+
if (fields.has(candidate)) {
|
|
570
|
+
fallbacks.push(candidate);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
if (!fallbacks.includes(idFieldName) && fields.has(idFieldName)) {
|
|
574
|
+
fallbacks.push(idFieldName);
|
|
575
|
+
}
|
|
576
|
+
return fallbacks;
|
|
577
|
+
}
|
|
496
578
|
function isStringScalarField(field) {
|
|
497
579
|
return field.kind === 'scalar' && field.type === 'string';
|
|
498
580
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as Enum from '../enum';
|
|
2
2
|
import * as Model from '../model';
|
|
3
|
+
import { AuthRuleSet, ProjectAuth } from './project-schema.auth';
|
|
3
4
|
import * as Branded from './project-schema.brands';
|
|
4
5
|
/**
|
|
5
6
|
* Overall project configuration.
|
|
@@ -39,6 +40,14 @@ export type ProjectSchema = {
|
|
|
39
40
|
* If not provided, the default schema "Data" is used.
|
|
40
41
|
*/
|
|
41
42
|
defaultDatabaseSchema: Branded.DatabaseSchemaName;
|
|
43
|
+
/**
|
|
44
|
+
* Global authorization configuration for this project.
|
|
45
|
+
*/
|
|
46
|
+
auth?: ProjectAuth;
|
|
47
|
+
/**
|
|
48
|
+
* Schema-level authorization defaults by database schema.
|
|
49
|
+
*/
|
|
50
|
+
schemaAuth: Map<Branded.DatabaseSchemaName, AuthRuleSet>;
|
|
42
51
|
/**
|
|
43
52
|
* The system user that is used for root/system tasks, e.g. data seeding.
|
|
44
53
|
*/
|