prostgles-server 3.0.86 → 3.0.88
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/.eslintignore +5 -0
- package/.eslintrc.json +30 -0
- package/dist/DBEventsManager.js +1 -1
- package/dist/DBEventsManager.js.map +1 -1
- package/dist/DBSchemaBuilder.d.ts.map +1 -1
- package/dist/DBSchemaBuilder.js +6 -6
- package/dist/DBSchemaBuilder.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/Functions.js +9 -9
- package/dist/DboBuilder/QueryBuilder/Functions.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.js +8 -7
- package/dist/DboBuilder/QueryBuilder/QueryBuilder.js.map +1 -1
- package/dist/DboBuilder/QueryBuilder/makeSelectQuery.d.ts.map +1 -1
- package/dist/DboBuilder/QueryBuilder/makeSelectQuery.js +4 -4
- package/dist/DboBuilder/QueryBuilder/makeSelectQuery.js.map +1 -1
- package/dist/DboBuilder/TableHandler.d.ts.map +1 -1
- package/dist/DboBuilder/TableHandler.js +18 -20
- package/dist/DboBuilder/TableHandler.js.map +1 -1
- package/dist/DboBuilder/ViewHandler.d.ts +0 -10
- package/dist/DboBuilder/ViewHandler.d.ts.map +1 -1
- package/dist/DboBuilder/ViewHandler.js +50 -63
- package/dist/DboBuilder/ViewHandler.js.map +1 -1
- package/dist/DboBuilder/delete.js +0 -1
- package/dist/DboBuilder/delete.js.map +1 -1
- package/dist/DboBuilder/getColumns.js +5 -4
- package/dist/DboBuilder/getColumns.js.map +1 -1
- package/dist/DboBuilder/getCondition.d.ts.map +1 -1
- package/dist/DboBuilder/getCondition.js +6 -6
- package/dist/DboBuilder/getCondition.js.map +1 -1
- package/dist/DboBuilder/insert.js +15 -16
- package/dist/DboBuilder/insert.js.map +1 -1
- package/dist/DboBuilder/insertDataParse.d.ts.map +1 -1
- package/dist/DboBuilder/insertDataParse.js +9 -10
- package/dist/DboBuilder/insertDataParse.js.map +1 -1
- package/dist/DboBuilder/parseUpdateRules.js +2 -2
- package/dist/DboBuilder/parseUpdateRules.js.map +1 -1
- package/dist/DboBuilder/runSQL.d.ts.map +1 -1
- package/dist/DboBuilder/runSQL.js +5 -5
- package/dist/DboBuilder/runSQL.js.map +1 -1
- package/dist/DboBuilder/subscribe.js +3 -3
- package/dist/DboBuilder/subscribe.js.map +1 -1
- package/dist/DboBuilder/update.js +5 -6
- package/dist/DboBuilder/update.js.map +1 -1
- package/dist/DboBuilder/uploadFile.d.ts.map +1 -1
- package/dist/DboBuilder/uploadFile.js +1 -1
- package/dist/DboBuilder/uploadFile.js.map +1 -1
- package/dist/DboBuilder.d.ts.map +1 -1
- package/dist/DboBuilder.js +13 -14
- package/dist/DboBuilder.js.map +1 -1
- package/dist/FileManager.d.ts.map +1 -1
- package/dist/FileManager.js +3 -5
- package/dist/FileManager.js.map +1 -1
- package/dist/Filtering.js +7 -7
- package/dist/Filtering.js.map +1 -1
- package/dist/JSONBValidation/validate_jsonb_schema_sql.d.ts +3 -0
- package/dist/JSONBValidation/validate_jsonb_schema_sql.d.ts.map +1 -0
- package/dist/JSONBValidation/validate_jsonb_schema_sql.js +295 -0
- package/dist/JSONBValidation/validate_jsonb_schema_sql.js.map +1 -0
- package/dist/JSONBValidation/validation.d.ts +108 -0
- package/dist/JSONBValidation/validation.d.ts.map +1 -0
- package/dist/JSONBValidation/validation.js +222 -0
- package/dist/JSONBValidation/validation.js.map +1 -0
- package/dist/PostgresNotifListenManager.js +1 -1
- package/dist/PostgresNotifListenManager.js.map +1 -1
- package/dist/Prostgles.d.ts.map +1 -1
- package/dist/Prostgles.js +20 -20
- package/dist/Prostgles.js.map +1 -1
- package/dist/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/PubSubManager.js +10 -8
- package/dist/PubSubManager/PubSubManager.js.map +1 -1
- package/dist/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/dist/PubSubManager/initPubSubManager.js +10 -7
- package/dist/PubSubManager/initPubSubManager.js.map +1 -1
- package/dist/PublishParser.d.ts.map +1 -1
- package/dist/PublishParser.js +122 -125
- package/dist/PublishParser.js.map +1 -1
- package/dist/SyncReplication.d.ts.map +1 -1
- package/dist/SyncReplication.js +19 -16
- package/dist/SyncReplication.js.map +1 -1
- package/dist/TableConfig.d.ts +9 -5
- package/dist/TableConfig.d.ts.map +1 -1
- package/dist/TableConfig.js +33 -12
- package/dist/TableConfig.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/shortestPath.js +11 -11
- package/dist/shortestPath.js.map +1 -1
- package/dist/validation.d.ts +50 -24
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +177 -53
- package/dist/validation.js.map +1 -1
- package/lib/AuthHandler.d.ts +11 -11
- package/lib/AuthHandler.d.ts.map +1 -1
- package/lib/DBEventsManager.js +1 -1
- package/lib/DBEventsManager.ts +1 -1
- package/lib/DBSchemaBuilder.d.ts +3 -3
- package/lib/DBSchemaBuilder.d.ts.map +1 -1
- package/lib/DBSchemaBuilder.js +6 -6
- package/lib/DBSchemaBuilder.ts +10 -9
- package/lib/DboBuilder/QueryBuilder/Functions.d.ts +3 -3
- package/lib/DboBuilder/QueryBuilder/Functions.d.ts.map +1 -1
- package/lib/DboBuilder/QueryBuilder/Functions.js +9 -9
- package/lib/DboBuilder/QueryBuilder/Functions.ts +13 -13
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.d.ts +3 -3
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.d.ts.map +1 -1
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.js +8 -7
- package/lib/DboBuilder/QueryBuilder/QueryBuilder.ts +12 -12
- package/lib/DboBuilder/QueryBuilder/makeSelectQuery.d.ts.map +1 -1
- package/lib/DboBuilder/QueryBuilder/makeSelectQuery.js +4 -4
- package/lib/DboBuilder/QueryBuilder/makeSelectQuery.ts +5 -5
- package/lib/DboBuilder/TableHandler.d.ts +1 -1
- package/lib/DboBuilder/TableHandler.d.ts.map +1 -1
- package/lib/DboBuilder/TableHandler.js +18 -20
- package/lib/DboBuilder/TableHandler.ts +21 -20
- package/lib/DboBuilder/ViewHandler.d.ts +1 -11
- package/lib/DboBuilder/ViewHandler.d.ts.map +1 -1
- package/lib/DboBuilder/ViewHandler.js +50 -63
- package/lib/DboBuilder/ViewHandler.ts +68 -97
- package/lib/DboBuilder/delete.js +0 -1
- package/lib/DboBuilder/delete.ts +1 -1
- package/lib/DboBuilder/getColumns.js +5 -4
- package/lib/DboBuilder/getColumns.ts +5 -5
- package/lib/DboBuilder/getCondition.d.ts.map +1 -1
- package/lib/DboBuilder/getCondition.js +6 -6
- package/lib/DboBuilder/getCondition.ts +7 -7
- package/lib/DboBuilder/insert.js +15 -16
- package/lib/DboBuilder/insert.ts +18 -18
- package/lib/DboBuilder/insertDataParse.d.ts.map +1 -1
- package/lib/DboBuilder/insertDataParse.js +9 -10
- package/lib/DboBuilder/insertDataParse.ts +42 -43
- package/lib/DboBuilder/parseUpdateRules.js +2 -2
- package/lib/DboBuilder/parseUpdateRules.ts +2 -2
- package/lib/DboBuilder/runSQL.d.ts.map +1 -1
- package/lib/DboBuilder/runSQL.js +5 -5
- package/lib/DboBuilder/runSQL.ts +6 -6
- package/lib/DboBuilder/subscribe.d.ts +1 -1
- package/lib/DboBuilder/subscribe.d.ts.map +1 -1
- package/lib/DboBuilder/subscribe.js +3 -3
- package/lib/DboBuilder/subscribe.ts +3 -3
- package/lib/DboBuilder/update.js +5 -6
- package/lib/DboBuilder/update.ts +6 -6
- package/lib/DboBuilder/uploadFile.d.ts.map +1 -1
- package/lib/DboBuilder/uploadFile.js +1 -1
- package/lib/DboBuilder/uploadFile.ts +2 -2
- package/lib/DboBuilder.d.ts +22 -22
- package/lib/DboBuilder.d.ts.map +1 -1
- package/lib/DboBuilder.js +13 -14
- package/lib/DboBuilder.ts +19 -19
- package/lib/FileManager.d.ts +6 -6
- package/lib/FileManager.d.ts.map +1 -1
- package/lib/FileManager.js +3 -5
- package/lib/FileManager.ts +7 -6
- package/lib/Filtering.d.ts +1 -1
- package/lib/Filtering.d.ts.map +1 -1
- package/lib/Filtering.js +7 -7
- package/lib/Filtering.ts +7 -7
- package/lib/JSONBValidation/validate_jsonb_schema_sql.d.ts +3 -0
- package/lib/JSONBValidation/validate_jsonb_schema_sql.d.ts.map +1 -0
- package/lib/JSONBValidation/validate_jsonb_schema_sql.js +294 -0
- package/lib/JSONBValidation/validate_jsonb_schema_sql.ts +293 -0
- package/lib/JSONBValidation/validation.d.ts +108 -0
- package/lib/JSONBValidation/validation.d.ts.map +1 -0
- package/lib/JSONBValidation/validation.js +221 -0
- package/lib/JSONBValidation/validation.ts +332 -0
- package/lib/PostgresNotifListenManager.d.ts +1 -1
- package/lib/PostgresNotifListenManager.d.ts.map +1 -1
- package/lib/PostgresNotifListenManager.js +1 -1
- package/lib/PostgresNotifListenManager.ts +1 -1
- package/lib/Prostgles.d.ts +14 -14
- package/lib/Prostgles.d.ts.map +1 -1
- package/lib/Prostgles.js +20 -19
- package/lib/Prostgles.ts +22 -21
- package/lib/PubSubManager/PubSubManager.d.ts +7 -7
- package/lib/PubSubManager/PubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager/PubSubManager.js +10 -8
- package/lib/PubSubManager/PubSubManager.ts +13 -8
- package/lib/PubSubManager/initPubSubManager.d.ts.map +1 -1
- package/lib/PubSubManager/initPubSubManager.js +10 -7
- package/lib/PubSubManager/initPubSubManager.ts +12 -7
- package/lib/PublishParser.d.ts +32 -32
- package/lib/PublishParser.d.ts.map +1 -1
- package/lib/PublishParser.js +121 -124
- package/lib/PublishParser.ts +125 -127
- package/lib/SchemaWatch.d.ts +1 -1
- package/lib/SchemaWatch.d.ts.map +1 -1
- package/lib/SyncReplication.d.ts +5 -5
- package/lib/SyncReplication.d.ts.map +1 -1
- package/lib/SyncReplication.js +19 -16
- package/lib/SyncReplication.ts +470 -471
- package/lib/TableConfig.d.ts +28 -24
- package/lib/TableConfig.d.ts.map +1 -1
- package/lib/TableConfig.js +33 -12
- package/lib/TableConfig.ts +55 -21
- package/lib/index.js +1 -1
- package/lib/index.ts +1 -1
- package/lib/shortestPath.d.ts +1 -1
- package/lib/shortestPath.d.ts.map +1 -1
- package/lib/shortestPath.js +11 -11
- package/lib/shortestPath.ts +11 -11
- package/package.json +10 -6
- package/tests/client/PID.txt +1 -1
- package/tests/client/package-lock.json +53 -31
- package/tests/client/package.json +4 -1
- package/tests/isomorphic_queries.d.ts.map +1 -1
- package/tests/isomorphic_queries.js +28 -26
- package/tests/isomorphic_queries.ts +30 -29
- package/tests/server/DBoGenerated.d.ts +1 -1
- package/tests/server/index.js +8 -7
- package/tests/server/index.ts +10 -8
- package/tests/server/package-lock.json +76 -58
- package/tests/server/package.json +2 -2
- package/tests/server/server.ts +2 -3
- package/lib/validation.d.ts +0 -100
- package/lib/validation.d.ts.map +0 -1
- package/lib/validation.js +0 -280
- package/lib/validation.ts +0 -360
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export const VALIDATE_SCHEMA_FUNCNAME = "prostgles.validate_jsonb_schema" as const;
|
|
4
|
+
export const validate_jsonb_schema_sql = `
|
|
5
|
+
DROP FUNCTION IF EXISTS ${VALIDATE_SCHEMA_FUNCNAME}(jsonb_schema text, data jsonb, checked_path text[]);
|
|
6
|
+
|
|
7
|
+
CREATE OR REPLACE FUNCTION ${VALIDATE_SCHEMA_FUNCNAME}(jsonb_schema TEXT, data JSONB, checked_path TEXT[] DEFAULT ARRAY[]::TEXT[]) RETURNS boolean AS
|
|
8
|
+
$f$
|
|
9
|
+
DECLARE
|
|
10
|
+
sub_schema RECORD;
|
|
11
|
+
array_element RECORD;
|
|
12
|
+
schema JSONB;
|
|
13
|
+
path text;
|
|
14
|
+
allowed_types text[] = '{any,boolean,number,integer,string,boolean[],number[],integer[],string[],any[]}';
|
|
15
|
+
typeStr TEXT = NULL;
|
|
16
|
+
optional boolean;
|
|
17
|
+
nullable boolean;
|
|
18
|
+
colname TEXT;
|
|
19
|
+
|
|
20
|
+
extra_keys TEXT[];
|
|
21
|
+
BEGIN
|
|
22
|
+
path = concat_ws(', ',
|
|
23
|
+
'Path: ' || array_to_string(checked_path, '.'),
|
|
24
|
+
'Data: ' || data::TEXT,
|
|
25
|
+
'JSONBSchema: ' || schema::TEXT
|
|
26
|
+
);
|
|
27
|
+
colname = COALESCE(checked_path[1], '');
|
|
28
|
+
|
|
29
|
+
IF length(jsonb_schema) = 0 THEN
|
|
30
|
+
RAISE EXCEPTION 'Empty schema. %', path USING HINT = path, COLUMN = colname;
|
|
31
|
+
END IF;
|
|
32
|
+
|
|
33
|
+
/* 'string' */
|
|
34
|
+
IF ARRAY[jsonb_schema] <@ allowed_types THEN
|
|
35
|
+
schema = jsonb_build_object('type', jsonb_schema);
|
|
36
|
+
/* { "type": ... } */
|
|
37
|
+
ELSIF BTRIM(jsonb_schema) ILIKE '{%' THEN
|
|
38
|
+
schema = jsonb_schema::JSONB;
|
|
39
|
+
ELSE
|
|
40
|
+
RAISE EXCEPTION $$Invalid schema. Expecting 'typename' or { "type": "typename" } but received: %, %$$, jsonb_schema, path USING HINT = path, COLUMN = colname;
|
|
41
|
+
END IF;
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
nullable = COALESCE((schema->'nullable')::BOOLEAN, FALSE);
|
|
45
|
+
IF data IS NULL OR jsonb_typeof(data) = 'null' THEN
|
|
46
|
+
IF NOT nullable THEN
|
|
47
|
+
RAISE EXCEPTION 'Is not nullable. %', path USING HINT = path, COLUMN = colname;
|
|
48
|
+
ELSE
|
|
49
|
+
RETURN true;
|
|
50
|
+
END IF;
|
|
51
|
+
END IF;
|
|
52
|
+
|
|
53
|
+
IF schema ? 'enum' THEN
|
|
54
|
+
IF
|
|
55
|
+
jsonb_typeof(schema->'enum') != 'array' OR
|
|
56
|
+
jsonb_array_length(schema->'enum') < 1
|
|
57
|
+
THEN
|
|
58
|
+
RAISE EXCEPTION 'Invalid schema enum (%) .Must be a non empty array %', schema->'enum', path USING HINT = path, COLUMN = colname;
|
|
59
|
+
END IF;
|
|
60
|
+
|
|
61
|
+
IF NOT jsonb_build_array(data) <@ (schema->'enum') THEN
|
|
62
|
+
RAISE EXCEPTION 'Data not in allowed enum list (%), %', schema->'enum', path USING HINT = path, COLUMN = colname;
|
|
63
|
+
END IF;
|
|
64
|
+
|
|
65
|
+
ELSIF schema ? 'type' THEN
|
|
66
|
+
|
|
67
|
+
IF jsonb_typeof(schema->'type') = 'string' THEN
|
|
68
|
+
typeStr = schema->>'type';
|
|
69
|
+
IF NOT ARRAY[typeStr] <@ allowed_types THEN
|
|
70
|
+
RAISE EXCEPTION 'Bad schema type type %, allowed types: %. %',typeStr, allowed_types, path USING HINT = path, COLUMN = colname;
|
|
71
|
+
END IF;
|
|
72
|
+
|
|
73
|
+
/** Primitive array */
|
|
74
|
+
IF typeStr LIKE '%[]' THEN
|
|
75
|
+
|
|
76
|
+
typeStr = left(typeStr, -2);
|
|
77
|
+
|
|
78
|
+
IF jsonb_typeof(data) != 'array' THEN
|
|
79
|
+
RAISE EXCEPTION 'Types not matching. Expecting an array. %', path USING HINT = path, COLUMN = colname;
|
|
80
|
+
END IF;
|
|
81
|
+
|
|
82
|
+
FOR array_element IN
|
|
83
|
+
SELECT value, row_number() OVER() -1 as idx
|
|
84
|
+
FROM jsonb_array_elements(data)
|
|
85
|
+
LOOP
|
|
86
|
+
IF NOT ${VALIDATE_SCHEMA_FUNCNAME}(
|
|
87
|
+
CASE WHEN schema->'allowedValues' IS NOT NULL THEN
|
|
88
|
+
jsonb_build_object('type', typeStr, 'allowedValues', schema->'allowedValues')::TEXT
|
|
89
|
+
ELSE typeStr END,
|
|
90
|
+
array_element.value,
|
|
91
|
+
checked_path || array_element.idx::TEXT
|
|
92
|
+
) THEN
|
|
93
|
+
|
|
94
|
+
RETURN FALSE;
|
|
95
|
+
END IF;
|
|
96
|
+
END LOOP;
|
|
97
|
+
|
|
98
|
+
RETURN TRUE;
|
|
99
|
+
|
|
100
|
+
/** Primitive */
|
|
101
|
+
ELSE
|
|
102
|
+
|
|
103
|
+
IF (
|
|
104
|
+
typeStr = 'number' AND jsonb_typeof(data) != typeStr OR
|
|
105
|
+
(typeStr = 'integer' AND (jsonb_typeof(data) != 'number' OR ceil(data::NUMERIC) != floor(data::NUMERIC))) OR
|
|
106
|
+
typeStr = 'boolean' AND jsonb_typeof(data) != typeStr OR
|
|
107
|
+
typeStr = 'string' AND jsonb_typeof(data) != typeStr OR
|
|
108
|
+
typeStr = 'any' AND jsonb_typeof(data) = 'null'
|
|
109
|
+
) THEN
|
|
110
|
+
RAISE EXCEPTION 'Data type not matching. Expected: %, Actual: %, %', typeStr, jsonb_typeof(data), path USING HINT = path, COLUMN = colname;
|
|
111
|
+
END IF;
|
|
112
|
+
|
|
113
|
+
IF schema ? 'allowedValues' AND NOT(jsonb_build_array(data) <@ (schema->'allowedValues')) THEN
|
|
114
|
+
IF (
|
|
115
|
+
SELECT COUNT(distinct jsonb_typeof(value))
|
|
116
|
+
FROM jsonb_array_elements(schema->'allowedValues')
|
|
117
|
+
) > 1 THEN
|
|
118
|
+
RAISE EXCEPTION 'Invalid schema. schema.allowedValues (%) contains more than one data type . %', schema->>'allowedValues', path USING HINT = path, COLUMN = colname;
|
|
119
|
+
END IF;
|
|
120
|
+
|
|
121
|
+
IF EXISTS(
|
|
122
|
+
SELECT 1
|
|
123
|
+
FROM jsonb_array_elements(schema->'allowedValues')
|
|
124
|
+
WHERE jsonb_typeof(value) != jsonb_typeof(data)
|
|
125
|
+
) THEN
|
|
126
|
+
RAISE EXCEPTION 'Invalid schema. schema.allowedValues (%) contains contains values not matchine the schema.type %', schema->>'allowedValues', path USING HINT = path, COLUMN = colname;
|
|
127
|
+
END IF;
|
|
128
|
+
|
|
129
|
+
RAISE EXCEPTION 'Data not in allowedValues (%). %', schema->>'allowedValues', path USING HINT = path, COLUMN = colname;
|
|
130
|
+
|
|
131
|
+
END IF;
|
|
132
|
+
|
|
133
|
+
END IF;
|
|
134
|
+
|
|
135
|
+
/* Object */
|
|
136
|
+
ELSIF jsonb_typeof(schema->'type') = 'object' THEN
|
|
137
|
+
|
|
138
|
+
IF jsonb_typeof(data) != 'object' THEN
|
|
139
|
+
RAISE EXCEPTION E'Expecting an object: \n %', path USING HINT = path, COLUMN = colname;
|
|
140
|
+
END IF;
|
|
141
|
+
|
|
142
|
+
extra_keys = ARRAY(SELECT k FROM (
|
|
143
|
+
SELECT jsonb_object_keys(data) as k
|
|
144
|
+
EXCEPT
|
|
145
|
+
SELECT jsonb_object_keys(schema->'type') as k
|
|
146
|
+
) t);
|
|
147
|
+
|
|
148
|
+
IF array_length(extra_keys, 1) > 0 THEN
|
|
149
|
+
RAISE EXCEPTION E'Object contains invalid keys: % \n %',
|
|
150
|
+
array_to_string(extra_keys, ', '), path USING HINT = path, COLUMN = colname;
|
|
151
|
+
END IF;
|
|
152
|
+
|
|
153
|
+
FOR sub_schema IN
|
|
154
|
+
SELECT key, value
|
|
155
|
+
FROM jsonb_each(schema->'type')
|
|
156
|
+
LOOP
|
|
157
|
+
optional = COALESCE((sub_schema.value->'optional')::BOOLEAN, FALSE);
|
|
158
|
+
IF NOT (data ? sub_schema.key) THEN
|
|
159
|
+
|
|
160
|
+
IF NOT optional THEN
|
|
161
|
+
RAISE EXCEPTION 'Types not matching. Required property (%) is missing. %',sub_schema.key , path USING HINT = path, COLUMN = colname;
|
|
162
|
+
ELSE
|
|
163
|
+
RETURN true;
|
|
164
|
+
END IF;
|
|
165
|
+
END IF;
|
|
166
|
+
|
|
167
|
+
IF NOT ${VALIDATE_SCHEMA_FUNCNAME}(
|
|
168
|
+
-- sub_schema.value::TEXT,
|
|
169
|
+
CASE WHEN jsonb_typeof(sub_schema.value) = 'string' THEN TRIM(both '"' from sub_schema.value::TEXT) ELSE sub_schema.value::TEXT END,
|
|
170
|
+
data->sub_schema.key,
|
|
171
|
+
checked_path || sub_schema.key
|
|
172
|
+
) THEN
|
|
173
|
+
RETURN false;
|
|
174
|
+
END IF;
|
|
175
|
+
|
|
176
|
+
END LOOP;
|
|
177
|
+
ELSE
|
|
178
|
+
RAISE EXCEPTION 'Unexpected schema.type ( % ), %',jsonb_typeof(schema->'type'), path USING HINT = path, COLUMN = colname;
|
|
179
|
+
END IF;
|
|
180
|
+
|
|
181
|
+
/* oneOf: [{ key_name: { type: "string" } }] */
|
|
182
|
+
ELSIF schema ? 'oneOf' THEN
|
|
183
|
+
IF jsonb_typeof(schema->'oneOf') != 'array' THEN
|
|
184
|
+
RAISE EXCEPTION 'Unexpected oneOf schema. Expecting an array of objects but received: % , %',schema->>'oneOf', path USING HINT = path, COLUMN = colname;
|
|
185
|
+
END IF;
|
|
186
|
+
|
|
187
|
+
FOR sub_schema IN
|
|
188
|
+
SELECT jsonb_build_object('type', value) as value
|
|
189
|
+
FROM jsonb_array_elements(schema->'oneOf')
|
|
190
|
+
LOOP
|
|
191
|
+
|
|
192
|
+
BEGIN
|
|
193
|
+
|
|
194
|
+
IF ${VALIDATE_SCHEMA_FUNCNAME}(
|
|
195
|
+
sub_schema.value::TEXT,
|
|
196
|
+
data,
|
|
197
|
+
checked_path
|
|
198
|
+
) THEN
|
|
199
|
+
RETURN true;
|
|
200
|
+
END IF;
|
|
201
|
+
|
|
202
|
+
/* Ignore exceptions in case the last schema will match */
|
|
203
|
+
EXCEPTION WHEN others THEN
|
|
204
|
+
END;
|
|
205
|
+
END LOOP;
|
|
206
|
+
|
|
207
|
+
RAISE EXCEPTION 'Could not validate against any oneOf schemas ( % ), %', schema->>'oneOf', path USING HINT = path, COLUMN = colname;
|
|
208
|
+
|
|
209
|
+
/* arrayOf: { key_name: { type: "string" } } */
|
|
210
|
+
ELSIF jsonb_typeof(schema->'arrayOf') = 'object' THEN
|
|
211
|
+
IF jsonb_typeof(data) != 'array' THEN
|
|
212
|
+
RAISE EXCEPTION 'Is not an array. %', path USING HINT = path, COLUMN = colname;
|
|
213
|
+
END IF;
|
|
214
|
+
|
|
215
|
+
FOR array_element IN
|
|
216
|
+
SELECT value, row_number() OVER() -1 as idx
|
|
217
|
+
FROM jsonb_array_elements(data)
|
|
218
|
+
LOOP
|
|
219
|
+
IF NOT ${VALIDATE_SCHEMA_FUNCNAME}(
|
|
220
|
+
(schema - 'arrayOf' || jsonb_build_object('type', schema->'arrayOf'))::TEXT, -- RENAME
|
|
221
|
+
array_element.value, checked_path || array_element.idx::TEXT
|
|
222
|
+
) THEN
|
|
223
|
+
RETURN false;
|
|
224
|
+
END IF;
|
|
225
|
+
END LOOP;
|
|
226
|
+
|
|
227
|
+
ELSE
|
|
228
|
+
RAISE EXCEPTION 'Unexpected schema: %, %', schema, path USING HINT = path, COLUMN = colname;
|
|
229
|
+
END IF;
|
|
230
|
+
|
|
231
|
+
RETURN true;
|
|
232
|
+
END;
|
|
233
|
+
$f$ LANGUAGE 'plpgsql' IMMUTABLE;
|
|
234
|
+
|
|
235
|
+
COMMENT ON FUNCTION ${VALIDATE_SCHEMA_FUNCNAME}
|
|
236
|
+
IS $$Used to validate jsonb data against a schema:
|
|
237
|
+
validate_jsonb_schema(
|
|
238
|
+
'{ "type": { "a": "number[]" } }',
|
|
239
|
+
'{ "a": [2] }'
|
|
240
|
+
)
|
|
241
|
+
$$;
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
/* TESTS */
|
|
245
|
+
|
|
246
|
+
SELECT ${VALIDATE_SCHEMA_FUNCNAME}(
|
|
247
|
+
'{ "enum": ["a", "b", 2] }',
|
|
248
|
+
'"a"'::JSONB
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
SELECT ${VALIDATE_SCHEMA_FUNCNAME}(
|
|
252
|
+
'{ "enum": ["a", "b", 2] }',
|
|
253
|
+
'2'::JSONB
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
SELECT ${VALIDATE_SCHEMA_FUNCNAME}(
|
|
257
|
+
'{
|
|
258
|
+
"oneOf": [
|
|
259
|
+
{ "a": "string" } ,
|
|
260
|
+
{
|
|
261
|
+
"a": {
|
|
262
|
+
"type": "boolean",
|
|
263
|
+
"allowedValues": [false],
|
|
264
|
+
"optional": true
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
]
|
|
268
|
+
}',
|
|
269
|
+
'{ "a": false }'
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
SELECT ${VALIDATE_SCHEMA_FUNCNAME}(
|
|
273
|
+
'{ "arrayOf": { "a": "string", "narr": { "arrayOf": { "a": { "type": "string", "optional": false, "nullable": true } } } } }',
|
|
274
|
+
'[{ "a": "ddd", "narr": [{ "a": null }] }]'::JSONB
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
SELECT ${VALIDATE_SCHEMA_FUNCNAME}(
|
|
278
|
+
'{ "type": { "a": { "type": "integer[]", "allowedValues": [2] } } }'::TEXT,
|
|
279
|
+
'{ "a": [2, 2] }'
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
SELECT ${VALIDATE_SCHEMA_FUNCNAME}(
|
|
283
|
+
'{ "type": { "a": { "type": "string[]", "allowedValues": ["2"] } } }'::TEXT,
|
|
284
|
+
'{ "a": ["2"] }'
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
SELECT ${VALIDATE_SCHEMA_FUNCNAME}('{ "type": "any"}', '{}');
|
|
288
|
+
|
|
289
|
+
SELECT ${VALIDATE_SCHEMA_FUNCNAME}('{ "type": { "a": { "enum": ["a"] } } }', '{ "a": "a"}');
|
|
290
|
+
|
|
291
|
+
SELECT ${VALIDATE_SCHEMA_FUNCNAME}('{ "arrayOf": { "a": { "enum": ["a"] } } }', '[{ "a": "a"}]');
|
|
292
|
+
|
|
293
|
+
`;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { JSONSchema7 } from "json-schema";
|
|
2
|
+
import { BaseColumn, JSONBColumnDef, StrictUnion } from "../TableConfig";
|
|
3
|
+
declare const DATA_TYPES: readonly ["boolean", "number", "integer", "string", "any", ...("string[]" | "number[]" | "boolean[]" | "integer[]" | "any[]")[]];
|
|
4
|
+
type DataType = typeof DATA_TYPES[number];
|
|
5
|
+
export declare namespace JSONB {
|
|
6
|
+
export type BaseOptions = {
|
|
7
|
+
/**
|
|
8
|
+
* False by default
|
|
9
|
+
*/
|
|
10
|
+
optional?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* False by default
|
|
13
|
+
*/
|
|
14
|
+
nullable?: boolean;
|
|
15
|
+
description?: string;
|
|
16
|
+
title?: string;
|
|
17
|
+
};
|
|
18
|
+
export type BasicType = BaseOptions & {
|
|
19
|
+
type: DataType;
|
|
20
|
+
allowedValues?: any[];
|
|
21
|
+
oneOf?: undefined;
|
|
22
|
+
arrayOf?: undefined;
|
|
23
|
+
enum?: undefined;
|
|
24
|
+
};
|
|
25
|
+
export type ObjectType = BaseOptions & {
|
|
26
|
+
type: ObjectSchema;
|
|
27
|
+
allowedValues?: undefined;
|
|
28
|
+
oneOf?: undefined;
|
|
29
|
+
arrayOf?: undefined;
|
|
30
|
+
enum?: undefined;
|
|
31
|
+
};
|
|
32
|
+
export type EnumType = BaseOptions & {
|
|
33
|
+
type?: undefined;
|
|
34
|
+
enum: readonly any[];
|
|
35
|
+
oneOf?: undefined;
|
|
36
|
+
arrayOf?: undefined;
|
|
37
|
+
allowedValues?: undefined;
|
|
38
|
+
};
|
|
39
|
+
export type OneOf = BaseOptions & {
|
|
40
|
+
type?: undefined;
|
|
41
|
+
oneOf: readonly ObjectSchema[];
|
|
42
|
+
arrayOf?: undefined;
|
|
43
|
+
allowedValues?: undefined;
|
|
44
|
+
enum?: undefined;
|
|
45
|
+
};
|
|
46
|
+
export type ArrayOf = BaseOptions & {
|
|
47
|
+
type?: undefined;
|
|
48
|
+
arrayOf: ObjectSchema;
|
|
49
|
+
allowedValues?: undefined;
|
|
50
|
+
oneOf?: undefined;
|
|
51
|
+
enum?: undefined;
|
|
52
|
+
};
|
|
53
|
+
export type FieldTypeObj = BasicType | ObjectType | EnumType | OneOf | ArrayOf;
|
|
54
|
+
export type FieldType = DataType | FieldTypeObj;
|
|
55
|
+
export type GetType<T extends FieldType | Omit<FieldTypeObj, "optional">> = T extends {
|
|
56
|
+
type: ObjectSchema;
|
|
57
|
+
} ? NestedSchemaObject<T["type"]> : T extends "number" | {
|
|
58
|
+
type: "number";
|
|
59
|
+
} ? number : T extends "boolean" | {
|
|
60
|
+
type: "boolean";
|
|
61
|
+
} ? boolean : T extends "integer" | {
|
|
62
|
+
type: "integer";
|
|
63
|
+
} ? number : T extends "string" | {
|
|
64
|
+
type: "string";
|
|
65
|
+
} ? string : T extends "any" | {
|
|
66
|
+
type: "any";
|
|
67
|
+
} ? any : T extends "number[]" | {
|
|
68
|
+
type: "number[]";
|
|
69
|
+
} ? number[] : T extends "boolean[]" | {
|
|
70
|
+
type: "boolean[]";
|
|
71
|
+
} ? boolean[] : T extends "integer[]" | {
|
|
72
|
+
type: "integer[]";
|
|
73
|
+
} ? number[] : T extends "string[]" | {
|
|
74
|
+
type: "string[]";
|
|
75
|
+
} ? string[] : T extends "any[]" | {
|
|
76
|
+
type: "any[]";
|
|
77
|
+
} ? any[] : T extends {
|
|
78
|
+
enum: readonly any[];
|
|
79
|
+
} ? T["enum"][number] : T extends {
|
|
80
|
+
oneOf: readonly ObjectSchema[];
|
|
81
|
+
} ? StrictUnion<NestedSchemaObject<T["oneOf"][number]>> : T extends {
|
|
82
|
+
arrayOf: ObjectSchema;
|
|
83
|
+
} ? NestedSchemaObject<T["arrayOf"]>[] : any;
|
|
84
|
+
type IsOptional<F extends FieldType> = F extends DataType ? false : F extends {
|
|
85
|
+
optional: true;
|
|
86
|
+
} ? true : false;
|
|
87
|
+
export type ObjectSchema = Record<string, FieldType>;
|
|
88
|
+
export type JSONBSchema = Omit<FieldTypeObj, "optional">;
|
|
89
|
+
export type NestedSchemaObject<S extends ObjectSchema> = ({
|
|
90
|
+
[K in keyof S as IsOptional<S[K]> extends true ? K : never]?: GetType<S[K]>;
|
|
91
|
+
} & {
|
|
92
|
+
[K in keyof S as IsOptional<S[K]> extends true ? never : K]: GetType<S[K]>;
|
|
93
|
+
});
|
|
94
|
+
export type SchemaObject<S extends JSONBSchema> = S["nullable"] extends true ? (null | GetType<S>) : GetType<S>;
|
|
95
|
+
export {};
|
|
96
|
+
}
|
|
97
|
+
export declare function validate<T>(obj: T, key: keyof T, rawFieldType: JSONB.FieldType): boolean;
|
|
98
|
+
export declare function validateSchema<S extends JSONB.ObjectSchema>(schema: S, obj: JSONB.NestedSchemaObject<S>, objName?: string, optional?: boolean): void;
|
|
99
|
+
type ColOpts = {
|
|
100
|
+
nullable?: boolean;
|
|
101
|
+
};
|
|
102
|
+
export declare function getSchemaTSTypes(schema: JSONB.ObjectSchema, leading?: string, isOneOf?: boolean): string;
|
|
103
|
+
export declare function getJSONBSchemaTSTypes(schema: JSONB.JSONBSchema, colOpts: ColOpts, leading?: string, isOneOf?: boolean): string;
|
|
104
|
+
export declare function getJSONBSchemaAsJSONSchema(tableName: string, colName: string, columnConfig: BaseColumn<{
|
|
105
|
+
en: 1;
|
|
106
|
+
}> & JSONBColumnDef): JSONSchema7;
|
|
107
|
+
export {};
|
|
108
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getJSONBSchemaAsJSONSchema = exports.getJSONBSchemaTSTypes = exports.getSchemaTSTypes = exports.validateSchema = exports.validate = void 0;
|
|
4
|
+
const prostgles_types_1 = require("prostgles-types");
|
|
5
|
+
const PubSubManager_1 = require("../PubSubManager/PubSubManager");
|
|
6
|
+
const PrimitiveTypes = ["boolean", "number", "integer", "string", "any"];
|
|
7
|
+
const DATA_TYPES = [
|
|
8
|
+
...PrimitiveTypes,
|
|
9
|
+
...PrimitiveTypes.map(v => `${v}[]`)
|
|
10
|
+
];
|
|
11
|
+
/** tests */
|
|
12
|
+
const s = {
|
|
13
|
+
type: {
|
|
14
|
+
a: { type: "boolean" },
|
|
15
|
+
c: { type: { c1: { type: "string" } } },
|
|
16
|
+
arr: { arrayOf: { d: "string" } },
|
|
17
|
+
o: {
|
|
18
|
+
oneOf: [
|
|
19
|
+
{ z: { type: "integer" } },
|
|
20
|
+
{ z1: { type: "integer" } }
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const ss = {
|
|
26
|
+
a: true,
|
|
27
|
+
arr: [{ d: "" }],
|
|
28
|
+
c: {
|
|
29
|
+
c1: ""
|
|
30
|
+
},
|
|
31
|
+
o: { z1: 23 }
|
|
32
|
+
};
|
|
33
|
+
const getFieldTypeObj = (rawFieldType) => {
|
|
34
|
+
if (typeof rawFieldType === "string")
|
|
35
|
+
return { type: rawFieldType };
|
|
36
|
+
return rawFieldType;
|
|
37
|
+
};
|
|
38
|
+
function validate(obj, key, rawFieldType) {
|
|
39
|
+
let err = `The provided value for ${JSON.stringify(key)} is of invalid type. Expecting `;
|
|
40
|
+
const val = obj[key];
|
|
41
|
+
const fieldType = getFieldTypeObj(rawFieldType);
|
|
42
|
+
if ("type" in fieldType && fieldType.type) {
|
|
43
|
+
if (typeof fieldType.type !== "string") {
|
|
44
|
+
(0, prostgles_types_1.getKeys)(fieldType.type).forEach(subKey => {
|
|
45
|
+
validate(val, subKey, fieldType.type[subKey]);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
err += fieldType.type;
|
|
49
|
+
if (fieldType.type === "boolean" && typeof val !== fieldType.type)
|
|
50
|
+
throw new Error(err);
|
|
51
|
+
if (fieldType.type === "string" && typeof val !== fieldType.type)
|
|
52
|
+
throw new Error(err);
|
|
53
|
+
if (fieldType.type === "number" && !Number.isFinite(val))
|
|
54
|
+
throw new Error(err);
|
|
55
|
+
if (fieldType.type === "integer" && !Number.isInteger(val))
|
|
56
|
+
throw new Error(err);
|
|
57
|
+
}
|
|
58
|
+
else if (fieldType.enum) {
|
|
59
|
+
err += `on of: ${fieldType.enum}`;
|
|
60
|
+
if (!fieldType.enum.includes(val))
|
|
61
|
+
throw new Error(err);
|
|
62
|
+
}
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
exports.validate = validate;
|
|
66
|
+
function validateSchema(schema, obj, objName, optional = false) {
|
|
67
|
+
if ((!schema || (0, prostgles_types_1.isEmpty)(schema)) && !optional)
|
|
68
|
+
throw new Error(`Expecting ${objName} to be defined`);
|
|
69
|
+
(0, prostgles_types_1.getKeys)(schema).forEach(k => validate(obj, k, schema[k]));
|
|
70
|
+
}
|
|
71
|
+
exports.validateSchema = validateSchema;
|
|
72
|
+
function getSchemaTSTypes(schema, leading = "", isOneOf = false) {
|
|
73
|
+
const getFieldType = (rawFieldType) => {
|
|
74
|
+
const fieldType = getFieldTypeObj(rawFieldType);
|
|
75
|
+
const nullType = (fieldType.nullable ? `null | ` : "");
|
|
76
|
+
if (fieldType?.type) {
|
|
77
|
+
if (typeof fieldType.type === "string") {
|
|
78
|
+
const correctType = fieldType.type.replace("integer", "number");
|
|
79
|
+
if (fieldType.allowedValues && fieldType.type.endsWith("[]")) {
|
|
80
|
+
return nullType + ` (${fieldType.allowedValues.map(v => JSON.stringify(v)).join(" | ")})[]`;
|
|
81
|
+
}
|
|
82
|
+
return nullType + correctType;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
return nullType + getSchemaTSTypes(fieldType.type, "", true);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else if (fieldType?.enum) {
|
|
89
|
+
return nullType + fieldType.enum.map(v => (0, PubSubManager_1.asValue)(v)).join(" | ");
|
|
90
|
+
}
|
|
91
|
+
else if (fieldType?.oneOf) {
|
|
92
|
+
return (fieldType.nullable ? `\n${leading} | null` : "") + fieldType.oneOf.map(v => `\n${leading} | ` + getSchemaTSTypes(v, "", true)).join("");
|
|
93
|
+
}
|
|
94
|
+
else if (fieldType?.arrayOf) {
|
|
95
|
+
return (fieldType.nullable ? `\n${leading} | null` : "") + getSchemaTSTypes(fieldType.arrayOf, "", true) + "[]";
|
|
96
|
+
}
|
|
97
|
+
else
|
|
98
|
+
throw "Unexpected getSchemaTSTypes: " + JSON.stringify({ fieldType, schema }, null, 2);
|
|
99
|
+
};
|
|
100
|
+
const spacing = isOneOf ? " " : " ";
|
|
101
|
+
const res = `${leading}{ \n` + (0, prostgles_types_1.getKeys)(schema).map(k => {
|
|
102
|
+
const fieldType = getFieldTypeObj(schema[k]);
|
|
103
|
+
return `${leading}${spacing}${k}${fieldType.optional ? "?" : ""}: ` + getFieldType(fieldType) + ";";
|
|
104
|
+
}).join("\n") + ` \n${leading}}${isOneOf ? "" : ";"}`;
|
|
105
|
+
/** Keep single line */
|
|
106
|
+
if (isOneOf)
|
|
107
|
+
return res.split("\n").join("");
|
|
108
|
+
return res;
|
|
109
|
+
}
|
|
110
|
+
exports.getSchemaTSTypes = getSchemaTSTypes;
|
|
111
|
+
function getJSONBSchemaTSTypes(schema, colOpts, leading = "", isOneOf = false) {
|
|
112
|
+
if (schema.arrayOf) {
|
|
113
|
+
return (colOpts.nullable ? `\n${leading} | null` : "") + getSchemaTSTypes(schema.arrayOf, leading, isOneOf) + "[]";
|
|
114
|
+
}
|
|
115
|
+
else if (schema.enum) {
|
|
116
|
+
return (colOpts.nullable ? `\n${leading} | null` : "") + schema.enum.map(v => (0, PubSubManager_1.asValue)(v)).join(" | ");
|
|
117
|
+
}
|
|
118
|
+
else if (schema.oneOf) {
|
|
119
|
+
return (colOpts.nullable ? `\n${leading} | null` : "") + schema.oneOf.map(s => `\n${leading} | ` + getSchemaTSTypes(s, "", true)).join("");
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
if (typeof schema.type === "string") {
|
|
123
|
+
return (colOpts.nullable ? `null | ` : "") + schema.type;
|
|
124
|
+
}
|
|
125
|
+
else if (schema.type) {
|
|
126
|
+
return (colOpts.nullable ? `null | ` : "") + getSchemaTSTypes(schema.type, leading, isOneOf);
|
|
127
|
+
}
|
|
128
|
+
return "";
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
exports.getJSONBSchemaTSTypes = getJSONBSchemaTSTypes;
|
|
132
|
+
const getJSONSchemaObject = (rawType, rootInfo) => {
|
|
133
|
+
const { type, arrayOf, description, nullable, oneOf, title, ...t } = typeof rawType === "string" ? ({ type: rawType }) :
|
|
134
|
+
rawType;
|
|
135
|
+
let result = {};
|
|
136
|
+
const partialProps = {
|
|
137
|
+
...((t.enum || t.allowedValues?.length) && { enum: t.allowedValues ?? t.enum.slice(0) }),
|
|
138
|
+
...(!!description && { description }),
|
|
139
|
+
...(!!title && { title }),
|
|
140
|
+
};
|
|
141
|
+
if (t.enum?.length) {
|
|
142
|
+
partialProps.type = typeof t.enum[0];
|
|
143
|
+
}
|
|
144
|
+
if (typeof type === "string" || arrayOf) {
|
|
145
|
+
/** ARRAY */
|
|
146
|
+
if (type && typeof type !== "string") {
|
|
147
|
+
throw "Not expected";
|
|
148
|
+
}
|
|
149
|
+
if (arrayOf || type?.endsWith("[]")) {
|
|
150
|
+
const arrayItems = arrayOf ? getJSONSchemaObject({ type: arrayOf }) :
|
|
151
|
+
type?.startsWith("any") ? { type: undefined } :
|
|
152
|
+
{
|
|
153
|
+
type: type?.slice(0, -2),
|
|
154
|
+
...(t.allowedValues && { enum: t.allowedValues }),
|
|
155
|
+
};
|
|
156
|
+
result = {
|
|
157
|
+
type: "array",
|
|
158
|
+
items: arrayItems,
|
|
159
|
+
};
|
|
160
|
+
/** PRIMITIVES */
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
result = {
|
|
164
|
+
type: type,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/** OBJECT */
|
|
168
|
+
}
|
|
169
|
+
else if ((0, prostgles_types_1.isObject)(type)) {
|
|
170
|
+
result = {
|
|
171
|
+
type: "object",
|
|
172
|
+
required: (0, prostgles_types_1.getKeys)(type).filter(k => {
|
|
173
|
+
const t = type[k];
|
|
174
|
+
return typeof t === "string" || !t.optional;
|
|
175
|
+
}),
|
|
176
|
+
properties: (0, prostgles_types_1.getKeys)(type).reduce((a, k) => {
|
|
177
|
+
return {
|
|
178
|
+
...a,
|
|
179
|
+
[k]: getJSONSchemaObject(type[k])
|
|
180
|
+
};
|
|
181
|
+
}, {}),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
else if (oneOf) {
|
|
185
|
+
result = {
|
|
186
|
+
type: "object",
|
|
187
|
+
oneOf: oneOf.map(s => getJSONSchemaObject({ type: s }))
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
if (nullable) {
|
|
191
|
+
const nullDef = { type: "null" };
|
|
192
|
+
if (result.oneOf) {
|
|
193
|
+
result.oneOf.push(nullDef);
|
|
194
|
+
}
|
|
195
|
+
else if (result.enum && !result.enum.includes(null)) {
|
|
196
|
+
result.enum.push(null);
|
|
197
|
+
}
|
|
198
|
+
else
|
|
199
|
+
result = {
|
|
200
|
+
type: 'object',
|
|
201
|
+
oneOf: [result, nullDef]
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
const rootSchema = !rootInfo ? undefined : {
|
|
205
|
+
"$id": rootInfo?.id,
|
|
206
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
207
|
+
};
|
|
208
|
+
return {
|
|
209
|
+
...rootSchema,
|
|
210
|
+
...partialProps,
|
|
211
|
+
...result,
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
function getJSONBSchemaAsJSONSchema(tableName, colName, columnConfig) {
|
|
215
|
+
const schema = {
|
|
216
|
+
...columnConfig,
|
|
217
|
+
...(columnConfig.jsonbSchema ?? { type: columnConfig.jsonbSchemaType })
|
|
218
|
+
};
|
|
219
|
+
return getJSONSchemaObject(schema, { id: `${tableName}.${colName}` });
|
|
220
|
+
}
|
|
221
|
+
exports.getJSONBSchemaAsJSONSchema = getJSONBSchemaAsJSONSchema;
|