prostgles-server 3.0.87 → 3.0.89

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.
Files changed (212) hide show
  1. package/.eslintignore +5 -0
  2. package/.eslintrc.json +30 -0
  3. package/dist/DBEventsManager.js +1 -1
  4. package/dist/DBEventsManager.js.map +1 -1
  5. package/dist/DBSchemaBuilder.d.ts.map +1 -1
  6. package/dist/DBSchemaBuilder.js +6 -6
  7. package/dist/DBSchemaBuilder.js.map +1 -1
  8. package/dist/DboBuilder/QueryBuilder/Functions.js +9 -9
  9. package/dist/DboBuilder/QueryBuilder/Functions.js.map +1 -1
  10. package/dist/DboBuilder/QueryBuilder/QueryBuilder.d.ts.map +1 -1
  11. package/dist/DboBuilder/QueryBuilder/QueryBuilder.js +8 -7
  12. package/dist/DboBuilder/QueryBuilder/QueryBuilder.js.map +1 -1
  13. package/dist/DboBuilder/QueryBuilder/makeSelectQuery.d.ts.map +1 -1
  14. package/dist/DboBuilder/QueryBuilder/makeSelectQuery.js +4 -4
  15. package/dist/DboBuilder/QueryBuilder/makeSelectQuery.js.map +1 -1
  16. package/dist/DboBuilder/TableHandler.d.ts.map +1 -1
  17. package/dist/DboBuilder/TableHandler.js +18 -20
  18. package/dist/DboBuilder/TableHandler.js.map +1 -1
  19. package/dist/DboBuilder/ViewHandler.d.ts +0 -10
  20. package/dist/DboBuilder/ViewHandler.d.ts.map +1 -1
  21. package/dist/DboBuilder/ViewHandler.js +50 -63
  22. package/dist/DboBuilder/ViewHandler.js.map +1 -1
  23. package/dist/DboBuilder/delete.js +0 -1
  24. package/dist/DboBuilder/delete.js.map +1 -1
  25. package/dist/DboBuilder/getColumns.js +5 -4
  26. package/dist/DboBuilder/getColumns.js.map +1 -1
  27. package/dist/DboBuilder/getCondition.d.ts.map +1 -1
  28. package/dist/DboBuilder/getCondition.js +6 -6
  29. package/dist/DboBuilder/getCondition.js.map +1 -1
  30. package/dist/DboBuilder/insert.js +15 -16
  31. package/dist/DboBuilder/insert.js.map +1 -1
  32. package/dist/DboBuilder/insertDataParse.d.ts.map +1 -1
  33. package/dist/DboBuilder/insertDataParse.js +9 -10
  34. package/dist/DboBuilder/insertDataParse.js.map +1 -1
  35. package/dist/DboBuilder/parseUpdateRules.js +2 -2
  36. package/dist/DboBuilder/parseUpdateRules.js.map +1 -1
  37. package/dist/DboBuilder/runSQL.d.ts.map +1 -1
  38. package/dist/DboBuilder/runSQL.js +5 -5
  39. package/dist/DboBuilder/runSQL.js.map +1 -1
  40. package/dist/DboBuilder/subscribe.js +3 -3
  41. package/dist/DboBuilder/subscribe.js.map +1 -1
  42. package/dist/DboBuilder/update.js +5 -6
  43. package/dist/DboBuilder/update.js.map +1 -1
  44. package/dist/DboBuilder/uploadFile.d.ts.map +1 -1
  45. package/dist/DboBuilder/uploadFile.js +1 -1
  46. package/dist/DboBuilder/uploadFile.js.map +1 -1
  47. package/dist/DboBuilder.d.ts.map +1 -1
  48. package/dist/DboBuilder.js +13 -14
  49. package/dist/DboBuilder.js.map +1 -1
  50. package/dist/FileManager.d.ts.map +1 -1
  51. package/dist/FileManager.js +3 -5
  52. package/dist/FileManager.js.map +1 -1
  53. package/dist/Filtering.js +7 -7
  54. package/dist/Filtering.js.map +1 -1
  55. package/dist/JSONBValidation/validate_jsonb_schema_sql.d.ts +3 -0
  56. package/dist/JSONBValidation/validate_jsonb_schema_sql.d.ts.map +1 -0
  57. package/dist/JSONBValidation/validate_jsonb_schema_sql.js +295 -0
  58. package/dist/JSONBValidation/validate_jsonb_schema_sql.js.map +1 -0
  59. package/dist/JSONBValidation/validation.d.ts +108 -0
  60. package/dist/JSONBValidation/validation.d.ts.map +1 -0
  61. package/dist/JSONBValidation/validation.js +222 -0
  62. package/dist/JSONBValidation/validation.js.map +1 -0
  63. package/dist/PostgresNotifListenManager.js +1 -1
  64. package/dist/PostgresNotifListenManager.js.map +1 -1
  65. package/dist/Prostgles.d.ts.map +1 -1
  66. package/dist/Prostgles.js +20 -20
  67. package/dist/Prostgles.js.map +1 -1
  68. package/dist/PubSubManager/initPubSubManager.d.ts.map +1 -1
  69. package/dist/PubSubManager/initPubSubManager.js +10 -7
  70. package/dist/PubSubManager/initPubSubManager.js.map +1 -1
  71. package/dist/PublishParser.d.ts.map +1 -1
  72. package/dist/PublishParser.js +122 -125
  73. package/dist/PublishParser.js.map +1 -1
  74. package/dist/SyncReplication.d.ts.map +1 -1
  75. package/dist/SyncReplication.js +19 -16
  76. package/dist/SyncReplication.js.map +1 -1
  77. package/dist/TableConfig.d.ts +9 -5
  78. package/dist/TableConfig.d.ts.map +1 -1
  79. package/dist/TableConfig.js +33 -12
  80. package/dist/TableConfig.js.map +1 -1
  81. package/dist/index.js +1 -1
  82. package/dist/index.js.map +1 -1
  83. package/dist/shortestPath.js +11 -11
  84. package/dist/shortestPath.js.map +1 -1
  85. package/dist/validation.d.ts +50 -24
  86. package/dist/validation.d.ts.map +1 -1
  87. package/dist/validation.js +177 -53
  88. package/dist/validation.js.map +1 -1
  89. package/lib/AuthHandler.d.ts +11 -11
  90. package/lib/AuthHandler.d.ts.map +1 -1
  91. package/lib/DBEventsManager.js +1 -1
  92. package/lib/DBEventsManager.ts +1 -1
  93. package/lib/DBSchemaBuilder.d.ts +3 -3
  94. package/lib/DBSchemaBuilder.d.ts.map +1 -1
  95. package/lib/DBSchemaBuilder.js +6 -6
  96. package/lib/DBSchemaBuilder.ts +10 -12
  97. package/lib/DboBuilder/QueryBuilder/Functions.d.ts +3 -3
  98. package/lib/DboBuilder/QueryBuilder/Functions.d.ts.map +1 -1
  99. package/lib/DboBuilder/QueryBuilder/Functions.js +9 -9
  100. package/lib/DboBuilder/QueryBuilder/Functions.ts +13 -13
  101. package/lib/DboBuilder/QueryBuilder/QueryBuilder.d.ts +3 -3
  102. package/lib/DboBuilder/QueryBuilder/QueryBuilder.d.ts.map +1 -1
  103. package/lib/DboBuilder/QueryBuilder/QueryBuilder.js +8 -7
  104. package/lib/DboBuilder/QueryBuilder/QueryBuilder.ts +12 -12
  105. package/lib/DboBuilder/QueryBuilder/makeSelectQuery.d.ts.map +1 -1
  106. package/lib/DboBuilder/QueryBuilder/makeSelectQuery.js +4 -4
  107. package/lib/DboBuilder/QueryBuilder/makeSelectQuery.ts +5 -5
  108. package/lib/DboBuilder/TableHandler.d.ts +1 -1
  109. package/lib/DboBuilder/TableHandler.d.ts.map +1 -1
  110. package/lib/DboBuilder/TableHandler.js +18 -20
  111. package/lib/DboBuilder/TableHandler.ts +21 -20
  112. package/lib/DboBuilder/ViewHandler.d.ts +1 -11
  113. package/lib/DboBuilder/ViewHandler.d.ts.map +1 -1
  114. package/lib/DboBuilder/ViewHandler.js +50 -63
  115. package/lib/DboBuilder/ViewHandler.ts +68 -97
  116. package/lib/DboBuilder/delete.js +0 -1
  117. package/lib/DboBuilder/delete.ts +1 -1
  118. package/lib/DboBuilder/getColumns.js +5 -4
  119. package/lib/DboBuilder/getColumns.ts +5 -5
  120. package/lib/DboBuilder/getCondition.d.ts.map +1 -1
  121. package/lib/DboBuilder/getCondition.js +6 -6
  122. package/lib/DboBuilder/getCondition.ts +7 -7
  123. package/lib/DboBuilder/insert.js +15 -16
  124. package/lib/DboBuilder/insert.ts +18 -18
  125. package/lib/DboBuilder/insertDataParse.d.ts.map +1 -1
  126. package/lib/DboBuilder/insertDataParse.js +9 -10
  127. package/lib/DboBuilder/insertDataParse.ts +42 -43
  128. package/lib/DboBuilder/parseUpdateRules.js +2 -2
  129. package/lib/DboBuilder/parseUpdateRules.ts +2 -2
  130. package/lib/DboBuilder/runSQL.d.ts.map +1 -1
  131. package/lib/DboBuilder/runSQL.js +5 -5
  132. package/lib/DboBuilder/runSQL.ts +6 -6
  133. package/lib/DboBuilder/subscribe.d.ts +1 -1
  134. package/lib/DboBuilder/subscribe.d.ts.map +1 -1
  135. package/lib/DboBuilder/subscribe.js +3 -3
  136. package/lib/DboBuilder/subscribe.ts +3 -3
  137. package/lib/DboBuilder/update.js +5 -6
  138. package/lib/DboBuilder/update.ts +6 -6
  139. package/lib/DboBuilder/uploadFile.d.ts.map +1 -1
  140. package/lib/DboBuilder/uploadFile.js +1 -1
  141. package/lib/DboBuilder/uploadFile.ts +2 -2
  142. package/lib/DboBuilder.d.ts +22 -22
  143. package/lib/DboBuilder.d.ts.map +1 -1
  144. package/lib/DboBuilder.js +13 -14
  145. package/lib/DboBuilder.ts +19 -19
  146. package/lib/FileManager.d.ts +6 -6
  147. package/lib/FileManager.d.ts.map +1 -1
  148. package/lib/FileManager.js +3 -5
  149. package/lib/FileManager.ts +7 -6
  150. package/lib/Filtering.d.ts +1 -1
  151. package/lib/Filtering.d.ts.map +1 -1
  152. package/lib/Filtering.js +7 -7
  153. package/lib/Filtering.ts +7 -7
  154. package/lib/JSONBValidation/validate_jsonb_schema_sql.d.ts +3 -0
  155. package/lib/JSONBValidation/validate_jsonb_schema_sql.d.ts.map +1 -0
  156. package/lib/JSONBValidation/validate_jsonb_schema_sql.js +294 -0
  157. package/lib/JSONBValidation/validate_jsonb_schema_sql.ts +293 -0
  158. package/lib/JSONBValidation/validation.d.ts +108 -0
  159. package/lib/JSONBValidation/validation.d.ts.map +1 -0
  160. package/lib/JSONBValidation/validation.js +221 -0
  161. package/lib/JSONBValidation/validation.ts +332 -0
  162. package/lib/PostgresNotifListenManager.d.ts +1 -1
  163. package/lib/PostgresNotifListenManager.d.ts.map +1 -1
  164. package/lib/PostgresNotifListenManager.js +1 -1
  165. package/lib/PostgresNotifListenManager.ts +1 -1
  166. package/lib/Prostgles.d.ts +14 -14
  167. package/lib/Prostgles.d.ts.map +1 -1
  168. package/lib/Prostgles.js +20 -20
  169. package/lib/Prostgles.ts +22 -21
  170. package/lib/PubSubManager/PubSubManager.d.ts +7 -7
  171. package/lib/PubSubManager/PubSubManager.d.ts.map +1 -1
  172. package/lib/PubSubManager/initPubSubManager.d.ts.map +1 -1
  173. package/lib/PubSubManager/initPubSubManager.js +10 -7
  174. package/lib/PubSubManager/initPubSubManager.ts +12 -7
  175. package/lib/PublishParser.d.ts +32 -32
  176. package/lib/PublishParser.d.ts.map +1 -1
  177. package/lib/PublishParser.js +121 -124
  178. package/lib/PublishParser.ts +125 -127
  179. package/lib/SchemaWatch.d.ts +1 -1
  180. package/lib/SchemaWatch.d.ts.map +1 -1
  181. package/lib/SyncReplication.d.ts +5 -5
  182. package/lib/SyncReplication.d.ts.map +1 -1
  183. package/lib/SyncReplication.js +19 -16
  184. package/lib/SyncReplication.ts +470 -471
  185. package/lib/TableConfig.d.ts +28 -24
  186. package/lib/TableConfig.d.ts.map +1 -1
  187. package/lib/TableConfig.js +33 -12
  188. package/lib/TableConfig.ts +55 -21
  189. package/lib/index.js +1 -1
  190. package/lib/index.ts +1 -1
  191. package/lib/shortestPath.d.ts +1 -1
  192. package/lib/shortestPath.d.ts.map +1 -1
  193. package/lib/shortestPath.js +11 -11
  194. package/lib/shortestPath.ts +11 -11
  195. package/package.json +10 -6
  196. package/tests/client/PID.txt +1 -1
  197. package/tests/client/package-lock.json +53 -31
  198. package/tests/client/package.json +4 -1
  199. package/tests/isomorphic_queries.d.ts +4 -1
  200. package/tests/isomorphic_queries.d.ts.map +1 -1
  201. package/tests/isomorphic_queries.js +38 -30
  202. package/tests/isomorphic_queries.ts +40 -33
  203. package/tests/server/DBoGenerated.d.ts +1 -1
  204. package/tests/server/index.js +8 -7
  205. package/tests/server/index.ts +10 -8
  206. package/tests/server/package-lock.json +76 -58
  207. package/tests/server/package.json +2 -2
  208. package/tests/server/server.ts +2 -3
  209. package/lib/validation.d.ts +0 -100
  210. package/lib/validation.d.ts.map +0 -1
  211. package/lib/validation.js +0 -280
  212. package/lib/validation.ts +0 -360
package/lib/validation.js DELETED
@@ -1,280 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getJSONBSchemaAsJSONSchema = exports.getJSONBSchemaTSTypes = exports.getSchemaTSTypes = exports.getPGCheckConstraint = exports.validateSchema = exports.validate = void 0;
4
- const prostgles_types_1 = require("prostgles-types");
5
- const PubSubManager_1 = require("./PubSubManager/PubSubManager");
6
- /** tests */
7
- const s = {
8
- a: { type: "boolean" },
9
- c: { type: { c1: { type: "string" } } },
10
- o: {
11
- oneOf: [
12
- { z: { type: "integer" } },
13
- { z1: { type: "integer" } }
14
- ]
15
- }
16
- };
17
- const ss = {
18
- a: true,
19
- c: {
20
- c1: ""
21
- },
22
- o: { z: 1, z1: 23 }
23
- };
24
- function validate(obj, key, validation) {
25
- let err = `The provided value for ${JSON.stringify(key)} is of invalid type. Expecting `;
26
- const val = obj[key];
27
- if ("type" in validation && validation.type) {
28
- if (typeof validation.type !== "string") {
29
- (0, prostgles_types_1.getKeys)(validation.type).forEach(subKey => {
30
- validate(val, subKey, validation.type[subKey]);
31
- });
32
- }
33
- err += validation.type;
34
- if (validation.type === "boolean" && typeof val !== validation.type)
35
- throw new Error(err);
36
- if (validation.type === "string" && typeof val !== validation.type)
37
- throw new Error(err);
38
- if (validation.type === "number" && !Number.isFinite(val))
39
- throw new Error(err);
40
- if (validation.type === "integer" && !Number.isInteger(val))
41
- throw new Error(err);
42
- }
43
- else if ("enum" in validation && validation.enum) {
44
- err += `on of: ${validation.enum}`;
45
- if (!validation.enum.includes(val))
46
- throw new Error(err);
47
- }
48
- return true;
49
- }
50
- exports.validate = validate;
51
- function validateSchema(schema, obj, objName, optional = false) {
52
- if ((!schema || (0, prostgles_types_1.isEmpty)(schema)) && !optional)
53
- throw new Error(`Expecting ${objName} to be defined`);
54
- (0, prostgles_types_1.getKeys)(schema).forEach(k => validate(obj, k, schema[k]));
55
- }
56
- exports.validateSchema = validateSchema;
57
- function getPGCheckConstraint(args, depth) {
58
- const { schema: s, escapedFieldName, nullable, optional, isRootQuery } = args;
59
- const jsToPGtypes = {
60
- "integer": "::INTEGER",
61
- "number": "::NUMERIC",
62
- "boolean": "::BOOLEAN",
63
- "string": "::TEXT",
64
- "any": "::JSONB"
65
- };
66
- const kChecks = (k, s) => {
67
- const t = s[k];
68
- const checks = [];
69
- const valAsJson = `${escapedFieldName}->${(0, PubSubManager_1.asValue)(k)}`;
70
- const valAsText = `${escapedFieldName}->>${(0, PubSubManager_1.asValue)(k)}`;
71
- if (t.nullable)
72
- checks.push(`${valAsJson} IS NULL`);
73
- if (t.optional)
74
- checks.push(`${escapedFieldName} ? ${(0, PubSubManager_1.asValue)(k)} = FALSE`);
75
- if ("oneOf" in t) {
76
- checks.push(`(${t.oneOf.map(subType => getPGCheckConstraint({ escapedFieldName: valAsJson, schema: subType, nullable, optional: t.optional }, depth + 1)).join(" OR ")})`);
77
- }
78
- else if ("enum" in t) {
79
- if (!t.enum.length || t.enum.some(v => v === undefined || !["number", "boolean", "string", null].includes(typeof v))) {
80
- throw new Error(`Invalid ValidationSchema for property: ${k} of field ${escapedFieldName}: enum cannot be empty AND can only contain: numbers, text, boolean, null`);
81
- }
82
- checks.push(`array_position(${(0, PubSubManager_1.asValue)(t.enum)}::text[], ${valAsText}::text) IS NOT NULL`);
83
- }
84
- else if ("type" in t) {
85
- if (typeof t.type === "string") {
86
- if (t.type.endsWith("[]")) {
87
- const correctType = t.type.slice(0, -2);
88
- let elemCheck = correctType === "any" ? "" : `AND ('{' || right(left(${valAsText},-1),-1) || '}')${jsToPGtypes[correctType]}[] IS NOT NULL`;
89
- checks.push(`jsonb_typeof(${valAsJson}) = 'array' ${elemCheck}`);
90
- if (t.allowedValues) {
91
- const types = Array.from(new Set(t.allowedValues.map(v => typeof v)));
92
- const allowedTypes = ["boolean", "number", "string"];
93
- if (types.length !== 1 || !allowedTypes.includes(types[0])) {
94
- throw new Error(`Invalid allowedValues (${t.allowedValues}). Must be a non empty array with elements of same type. Allowed types: ${allowedTypes}`);
95
- }
96
- const type = types[0];
97
- checks.push(`(${valAsText})${jsToPGtypes[type]}[] <@ ${(0, PubSubManager_1.asValue)(t.allowedValues)}`);
98
- }
99
- }
100
- else {
101
- const correctType = t.type.replace("integer", "number");
102
- if (correctType !== "any") {
103
- checks.push(`jsonb_typeof(${valAsJson}) = ${(0, PubSubManager_1.asValue)(correctType)} `);
104
- }
105
- }
106
- }
107
- else {
108
- const check = getPGCheckConstraint({ escapedFieldName: valAsJson, schema: t.type, nullable: !!t.nullable, optional: !!t.optional }, depth + 1).trim();
109
- if (check)
110
- checks.push(`(${check})`);
111
- }
112
- }
113
- const result = checks.join(" OR ");
114
- if (!depth)
115
- return `COALESCE(${result}, false)`;
116
- return result;
117
- };
118
- const getSchemaChecks = (s) => (0, prostgles_types_1.getKeys)(s).map(k => "(" + kChecks(k, s) + ")").join(" AND ");
119
- const checks = [];
120
- let typeChecks = "";
121
- if (isOneOfTypes(s)) {
122
- typeChecks = s.oneOf.map(t => `(${getSchemaChecks(t)})`).join(" OR ");
123
- }
124
- else {
125
- typeChecks = getSchemaChecks(s);
126
- }
127
- if (nullable)
128
- checks.push(` ${escapedFieldName} IS NULL `);
129
- checks.push(`jsonb_typeof(${escapedFieldName}) = 'object' ${typeChecks ? ` AND (${typeChecks})` : ""}`);
130
- return checks.join(" OR ");
131
- }
132
- exports.getPGCheckConstraint = getPGCheckConstraint;
133
- const isOneOfTypes = (s) => {
134
- if ("oneOf" in s) {
135
- if (!Array.isArray(s.oneOf)) {
136
- throw "Expecting oneOf to be an array of types";
137
- }
138
- return true;
139
- }
140
- return false;
141
- };
142
- function getSchemaTSTypes(schema, leading = "", isOneOf = false) {
143
- const getFieldType = (def) => {
144
- const nullType = (def.nullable ? `null | ` : "");
145
- if ("type" in def) {
146
- if (typeof def.type === "string") {
147
- const correctType = def.type.replace("integer", "number");
148
- if (def.allowedValues && def.type.endsWith("[]")) {
149
- return nullType + ` (${def.allowedValues.map(v => JSON.stringify(v)).join(" | ")})[]`;
150
- }
151
- return nullType + correctType;
152
- }
153
- else {
154
- return nullType + getSchemaTSTypes(def.type, "", true);
155
- }
156
- }
157
- else if ("enum" in def) {
158
- return nullType + def.enum.map(v => (0, PubSubManager_1.asValue)(v)).join(" | ");
159
- }
160
- else if ("oneOf" in def) {
161
- return (def.nullable ? `\n${leading} | null` : "") + def.oneOf.map(v => `\n${leading} | ` + getSchemaTSTypes(v, "", true)).join("");
162
- }
163
- else
164
- throw "Unexpected getSchemaTSTypes";
165
- };
166
- let spacing = isOneOf ? " " : " ";
167
- let res = `${leading}{ \n` + (0, prostgles_types_1.getKeys)(schema).map(k => {
168
- const def = schema[k];
169
- return `${leading}${spacing}${k}${def.optional ? "?" : ""}: ` + getFieldType(def) + ";";
170
- }).join("\n") + ` \n${leading}}${isOneOf ? "" : ";"}`;
171
- /** Keep single line */
172
- if (isOneOf)
173
- res = res.split("\n").join("");
174
- return res;
175
- }
176
- exports.getSchemaTSTypes = getSchemaTSTypes;
177
- function getJSONBSchemaTSTypes(schema, colOpts, leading = "", isOneOf = false) {
178
- if (isOneOfTypes(schema)) {
179
- return (colOpts.nullable ? `\n${leading} | null` : "") + schema.oneOf.map(s => `\n${leading} | ` + getSchemaTSTypes(s, "", true)).join("");
180
- }
181
- else {
182
- return (colOpts.nullable ? `null | ` : "") + getSchemaTSTypes(schema, leading, isOneOf);
183
- }
184
- }
185
- exports.getJSONBSchemaTSTypes = getJSONBSchemaTSTypes;
186
- const getJSONSchemaObject = (objDef) => {
187
- const resultType = {
188
- type: "object",
189
- properties: (0, prostgles_types_1.getKeys)(objDef).reduce((a, k) => {
190
- const itemSchema = objDef[k];
191
- const { nullable, optional, description, title } = itemSchema;
192
- let item = {};
193
- if ("type" in itemSchema) {
194
- const { type } = itemSchema;
195
- /**
196
- * Is primitive or any
197
- */
198
- if (typeof type === "string") {
199
- const arrayType = type.endsWith("[]") ? type.slice(0, -2) : undefined;
200
- if (arrayType) {
201
- item = {
202
- type: "array",
203
- items: itemSchema.allowedValues ? {
204
- enum: itemSchema.allowedValues
205
- } : {
206
- type: arrayType === "any" ? {} : arrayType
207
- }
208
- };
209
- }
210
- else {
211
- item = {
212
- type: type === "any" ? {} : type
213
- };
214
- }
215
- /**
216
- * Is object
217
- */
218
- }
219
- else {
220
- item = getJSONSchemaObject(type);
221
- }
222
- }
223
- else if ("enum" in itemSchema) {
224
- item = {
225
- type: typeof itemSchema.enum[0],
226
- "enum": itemSchema.enum //.concat(nullable? [null] : [])
227
- };
228
- }
229
- else if ("oneOf" in itemSchema) {
230
- item = {
231
- type: "object",
232
- oneOf: itemSchema.oneOf.map(t => getJSONSchemaObject(t))
233
- };
234
- }
235
- else {
236
- throw new Error("Unexpected jsonbSchema itemSchema" + JSON.stringify({ itemSchema, objDef }, null, 2));
237
- }
238
- if (nullable) {
239
- const nullDef = { type: "null" };
240
- if (item.oneOf) {
241
- item.oneOf.push(nullDef);
242
- }
243
- else if (item.enum) {
244
- item.enum.push(null);
245
- }
246
- else
247
- item = {
248
- type: 'object',
249
- oneOf: [item, nullDef]
250
- };
251
- }
252
- return {
253
- ...a,
254
- [k]: {
255
- ...item,
256
- required: !optional,
257
- ...(!!description && { description }),
258
- ...(!!title && { title }),
259
- }
260
- };
261
- }, {})
262
- };
263
- return resultType;
264
- };
265
- function getJSONBSchemaAsJSONSchema(tableName, colName, columnConfig) {
266
- const schema = columnConfig.jsonbSchema;
267
- let jSchema = getJSONSchemaObject({
268
- field1: isOneOfTypes(schema) ? schema :
269
- { type: schema }
270
- }).properties.field1;
271
- return {
272
- "$id": `${tableName}.${colName}`,
273
- "$schema": "https://json-schema.org/draft/2020-12/schema",
274
- ...jSchema,
275
- "title": columnConfig.label ?? colName,
276
- ...(!!columnConfig.info?.hint && { description: columnConfig.info?.hint }),
277
- required: !columnConfig.nullable
278
- };
279
- }
280
- exports.getJSONBSchemaAsJSONSchema = getJSONBSchemaAsJSONSchema;
package/lib/validation.ts DELETED
@@ -1,360 +0,0 @@
1
- import { AnyObject, asName, getKeys, isEmpty, isObject } from "prostgles-types";
2
- import { asValue } from "./PubSubManager/PubSubManager";
3
- import { BaseColumn, ColumnConfig, JSONBColumnDef } from "./TableConfig";
4
-
5
- type BaseOptions = {
6
- optional?: boolean;
7
- nullable?: boolean;
8
- description?: string;
9
- allowedValues?: any[];
10
- title?: string;
11
- };
12
-
13
-
14
- type SimpleType = BaseOptions & ({
15
- type:
16
- | "number" | "boolean" | "integer" | "string"
17
- | "number[]" | "boolean[]" | "integer[]" | "string[]"
18
- | "any[]"
19
- | "any"
20
- | ValidationSchema;
21
- } | {
22
- enum: readonly any[];
23
- })
24
-
25
- export type OneOf = BaseOptions & {
26
- oneOf: readonly ValidationSchema[];
27
- }
28
- type FieldType = SimpleType | OneOf;
29
-
30
- type GetType<T extends FieldType> =
31
- | T extends { type: ValidationSchema } ? SchemaObject<T["type"]> :
32
- | T extends { type: "number" } ? number :
33
- | T extends { type: "boolean" } ? boolean :
34
- | T extends { type: "integer" } ? number :
35
- | T extends { type: "string" } ? string :
36
- | T extends { type: "any" } ? any :
37
- | T extends { type: "number[]" } ? number[] :
38
- | T extends { type: "boolean[]" } ? boolean[] :
39
- | T extends { type: "integer[]" } ? number[] :
40
- | T extends { type: "string[]" } ? string[] :
41
- | T extends { type: "any[]" } ? any[] :
42
- | T extends { enum: readonly any[] } ? T["enum"][number] :
43
-
44
- /** This needs fixing */
45
- | T extends { oneOf: readonly ValidationSchema[] } ? SchemaObject<T["oneOf"][number]> :
46
- any;
47
-
48
- export type ValidationSchema = Record<string, FieldType>;
49
- export type SchemaObject<S extends ValidationSchema> = ({
50
- [K in keyof S as S[K]["optional"] extends true ? K : never]?: GetType<S[K]>
51
- } & {
52
- [K in keyof S as S[K]["optional"] extends true ? never : K]: GetType<S[K]>
53
- });
54
-
55
- /** tests */
56
- const s = {
57
- a: { type: "boolean" },
58
- c: { type: { c1: { type: "string" } } },
59
- o: {
60
- oneOf: [
61
- { z: { type: "integer" } },
62
- { z1: { type: "integer" } }
63
- ]
64
- }
65
- } as const;
66
- const ss: SchemaObject<typeof s> = {
67
- a: true,
68
- c: {
69
- c1: ""
70
- },
71
- o: { z: 1, z1: 23 }
72
- }
73
-
74
- export function validate<T>(obj: T, key: keyof T, validation: FieldType): boolean {
75
- let err = `The provided value for ${JSON.stringify(key)} is of invalid type. Expecting `;
76
- const val = obj[key];
77
- if ("type" in validation && validation.type) {
78
- if (typeof validation.type !== "string") {
79
- getKeys(validation.type).forEach(subKey => {
80
- validate(val, subKey as any, (validation.type as ValidationSchema)[subKey])
81
- });
82
- }
83
- err += validation.type;
84
- if (validation.type === "boolean" && typeof val !== validation.type) throw new Error(err)
85
- if (validation.type === "string" && typeof val !== validation.type) throw new Error(err)
86
- if (validation.type === "number" && !Number.isFinite(val)) throw new Error(err)
87
- if (validation.type === "integer" && !Number.isInteger(val)) throw new Error(err)
88
- } else if ("enum" in validation && validation.enum) {
89
- err += `on of: ${validation.enum}`;
90
- if (!validation.enum.includes(val)) throw new Error(err)
91
- }
92
- return true
93
- }
94
-
95
- export function validateSchema<S extends ValidationSchema>(schema: S, obj: SchemaObject<S>, objName?: string, optional = false) {
96
- if ((!schema || isEmpty(schema)) && !optional) throw new Error(`Expecting ${objName} to be defined`);
97
- getKeys(schema).forEach(k => validate(obj as any, k, schema[k]));
98
- }
99
-
100
- export function getPGCheckConstraint(args: { escapedFieldName: string; schema: ValidationSchema | OneOf, nullable: boolean; isRootQuery?: boolean; optional?: boolean; }, depth: number): string {
101
- const { schema: s, escapedFieldName, nullable, optional, isRootQuery } = args;
102
-
103
- const jsToPGtypes = {
104
- "integer": "::INTEGER",
105
- "number": "::NUMERIC",
106
- "boolean": "::BOOLEAN",
107
- "string": "::TEXT",
108
- "any": "::JSONB"
109
- }
110
-
111
- const kChecks = (k: string, s: ValidationSchema) => {
112
- const t = s[k];
113
- const checks: string[] = [];
114
- const valAsJson = `${escapedFieldName}->${asValue(k)}`;
115
- const valAsText = `${escapedFieldName}->>${asValue(k)}`;
116
- if (t.nullable) checks.push(`${valAsJson} IS NULL`);
117
- if (t.optional) checks.push(`${escapedFieldName} ? ${asValue(k)} = FALSE`);
118
-
119
- if ("oneOf" in t) {
120
- checks.push(`(${t.oneOf.map(subType => getPGCheckConstraint({ escapedFieldName: valAsJson, schema: subType, nullable, optional: t.optional }, depth + 1)).join(" OR ")})`)
121
- } else if ("enum" in t) {
122
- if (!t.enum.length || t.enum.some(v => v === undefined || !["number", "boolean", "string", null].includes(typeof v))) {
123
- throw new Error(`Invalid ValidationSchema for property: ${k} of field ${escapedFieldName}: enum cannot be empty AND can only contain: numbers, text, boolean, null`);
124
- }
125
-
126
- checks.push(`array_position(${asValue(t.enum)}::text[], ${valAsText}::text) IS NOT NULL`)
127
- } else if ("type" in t) {
128
- if (typeof t.type === "string") {
129
- if (t.type.endsWith("[]")) {
130
- const correctType = t.type.slice(0, -2);
131
- let elemCheck = correctType === "any" ? "" : `AND ('{' || right(left(${valAsText},-1),-1) || '}')${jsToPGtypes[correctType as keyof typeof jsToPGtypes]}[] IS NOT NULL`
132
- checks.push(`jsonb_typeof(${valAsJson}) = 'array' ${elemCheck}`);
133
- if(t.allowedValues){
134
- const types = Array.from(new Set(t.allowedValues.map(v => typeof v)));
135
- const allowedTypes = ["boolean", "number", "string"] as const;
136
- if(types.length !== 1 || !allowedTypes.includes(types[0] as any)){
137
- throw new Error(`Invalid allowedValues (${t.allowedValues}). Must be a non empty array with elements of same type. Allowed types: ${allowedTypes}`)
138
- }
139
- const type = types[0] as typeof allowedTypes[number];
140
- checks.push(`(${valAsText})${jsToPGtypes[type]}[] <@ ${asValue(t.allowedValues)}`)
141
- }
142
- } else {
143
- const correctType = t.type.replace("integer", "number");
144
- if (correctType !== "any") {
145
- checks.push(`jsonb_typeof(${valAsJson}) = ${asValue(correctType)} `)
146
- }
147
- }
148
- } else {
149
- const check = getPGCheckConstraint({ escapedFieldName: valAsJson, schema: t.type, nullable: !!t.nullable, optional: !!t.optional }, depth + 1).trim();
150
- if (check) checks.push(`(${check})`)
151
- }
152
- }
153
- const result = checks.join(" OR ")
154
- if (!depth) return `COALESCE(${result}, false)`
155
- return result
156
- }
157
-
158
- const getSchemaChecks = (s: ValidationSchema) => getKeys(s).map(k => "(" + kChecks(k, s) + ")").join(" AND ")
159
-
160
- const checks: string[] = [];
161
- let typeChecks = "";
162
- if (isOneOfTypes(s)) {
163
- typeChecks = s.oneOf.map(t => `(${getSchemaChecks(t)})`).join(" OR ");
164
- } else {
165
- typeChecks = getSchemaChecks(s);
166
- }
167
- if (nullable) checks.push(` ${escapedFieldName} IS NULL `);
168
- checks.push(`jsonb_typeof(${escapedFieldName}) = 'object' ${typeChecks ? ` AND (${typeChecks})` : ""}`);
169
- return checks.join(" OR ");
170
- }
171
- type ColOpts = { nullable?: boolean };
172
- const isOneOfTypes = (s: ValidationSchema | OneOf): s is OneOf => {
173
-
174
- if ("oneOf" in s) {
175
- if (!Array.isArray(s.oneOf)) {
176
- throw "Expecting oneOf to be an array of types";
177
- }
178
- return true;
179
- }
180
- return false;
181
- }
182
-
183
- export function getSchemaTSTypes(schema: ValidationSchema, leading = "", isOneOf = false): string {
184
- const getFieldType = (def: FieldType) => {
185
- const nullType = (def.nullable ? `null | ` : "");
186
- if ("type" in def) {
187
- if (typeof def.type === "string") {
188
- const correctType = def.type.replace("integer", "number");
189
- if(def.allowedValues && def.type.endsWith("[]")){
190
- return nullType + ` (${def.allowedValues.map(v => JSON.stringify(v)).join(" | ")})[]`
191
- }
192
- return nullType + correctType
193
- } else {
194
- return nullType + getSchemaTSTypes(def.type, "", true)
195
- }
196
- } else if ("enum" in def) {
197
- return nullType + def.enum.map(v => asValue(v)).join(" | ")
198
- } else if ("oneOf" in def) {
199
- return (def.nullable ? `\n${leading} | null` : "") + def.oneOf.map(v => `\n${leading} | ` + getSchemaTSTypes(v, "", true)).join("")
200
- } else throw "Unexpected getSchemaTSTypes"
201
- }
202
-
203
- let spacing = isOneOf ? " " : " ";
204
-
205
- let res = `${leading}{ \n` + getKeys(schema).map(k => {
206
- const def = schema[k];
207
- return `${leading}${spacing}${k}${def.optional ? "?" : ""}: ` + getFieldType(def) + ";";
208
- }).join("\n") + ` \n${leading}}${isOneOf ? "" : ";"}`;
209
-
210
- /** Keep single line */
211
- if (isOneOf) res = res.split("\n").join("")
212
- return res;
213
- }
214
-
215
- export function getJSONBSchemaTSTypes(schema: ValidationSchema | OneOf, colOpts: ColOpts, leading = "", isOneOf = false): string {
216
- if (isOneOfTypes(schema)) {
217
- return (colOpts.nullable ? `\n${leading} | null` : "") + schema.oneOf.map(s => `\n${leading} | ` + getSchemaTSTypes(s, "", true)).join("")
218
- } else {
219
- return (colOpts.nullable ? `null | ` : "") + getSchemaTSTypes(schema, leading, isOneOf);
220
- }
221
- }
222
-
223
- namespace JSTypes {
224
- type Base = {
225
- $id?: string;
226
- $schema?: string;
227
- title?: string;
228
- description?: string;
229
- required?: boolean;
230
- // nullable?: boolean;
231
- // optional?: boolean;
232
- }
233
- export type Any = {};
234
-
235
- export type Object<T extends AnyObject = AnyObject> = Base & {
236
- type: "object";
237
- properties: Record<keyof T, Schema>;
238
- }
239
- export type Enum = Base & {
240
- type: "string" | "number";
241
- enum: (string | number)[]
242
- }
243
- export type Array = Base & {
244
- type: "array";
245
- items: (string | number)[]
246
- }
247
- export type OneOf = {
248
- oneOf: (Any | Object | Enum | Array)[]
249
- }
250
- export type Schema =
251
- | Any
252
- | Object
253
- | Enum
254
- | Array
255
- | OneOf;
256
- }
257
-
258
- type JSONSchema = JSTypes.Schema
259
-
260
- const getJSONSchemaObject = <T extends ValidationSchema>(objDef: T): JSTypes.Object<T> => {
261
- const resultType: JSONSchema = {
262
- type: "object",
263
- properties: getKeys(objDef).reduce((a, k) => {
264
- const itemSchema: FieldType = objDef[k];
265
- const { nullable, optional, description, title } = itemSchema;
266
- let item = {} as any;
267
-
268
- if ("type" in itemSchema) {
269
- const { type } = itemSchema;
270
- /**
271
- * Is primitive or any
272
- */
273
- if (typeof type === "string") {
274
- const arrayType = type.endsWith("[]") ? type.slice(0, -2) : undefined;
275
- if (arrayType) {
276
- item = {
277
- type: "array",
278
- items: itemSchema.allowedValues? {
279
- enum: itemSchema.allowedValues
280
- } : {
281
- type: arrayType === "any" ? {} : arrayType
282
- }
283
- }
284
-
285
- } else {
286
- item = {
287
- type: type === "any" ? {} : type
288
- }
289
- }
290
-
291
- /**
292
- * Is object
293
- */
294
- } else {
295
- item = getJSONSchemaObject(type)
296
-
297
- }
298
-
299
- } else if ("enum" in itemSchema) {
300
- item = {
301
- type: typeof itemSchema.enum[0]!,
302
- "enum": itemSchema.enum //.concat(nullable? [null] : [])
303
- }
304
- } else if ("oneOf" in itemSchema) {
305
- item = {
306
- type: "object",
307
- oneOf: itemSchema.oneOf.map(t => getJSONSchemaObject(t))
308
- }
309
- } else {
310
- throw new Error("Unexpected jsonbSchema itemSchema" + JSON.stringify({ itemSchema, objDef }, null, 2))
311
- }
312
-
313
- if (nullable) {
314
- const nullDef = { type: "null" }
315
- if (item.oneOf){
316
- item.oneOf.push(nullDef)
317
- } else if(item.enum){
318
- item.enum.push(null)
319
-
320
- } else item = {
321
- type: 'object',
322
- oneOf: [item, nullDef]
323
- }
324
- }
325
-
326
- return {
327
- ...a,
328
- [k]: {
329
- ...item,
330
- required: !optional,
331
- ...(!!description && {description}),
332
- ...(!!title && {title}),
333
- }
334
- }
335
- }, {} as Record<string, JSTypes.Schema>)
336
- }
337
-
338
- return resultType as any;
339
- }
340
-
341
- export function getJSONBSchemaAsJSONSchema(tableName: string, colName: string, columnConfig: BaseColumn<{ en: 1 }> & JSONBColumnDef): JSONSchema {
342
-
343
- const schema = columnConfig.jsonbSchema;
344
-
345
- let jSchema: JSONSchema = getJSONSchemaObject({
346
- field1:
347
- isOneOfTypes(schema) ? schema :
348
- { type: schema as ValidationSchema }
349
- }).properties.field1;
350
-
351
- return {
352
- "$id": `${tableName}.${colName}`,
353
- "$schema": "https://json-schema.org/draft/2020-12/schema",
354
- ...jSchema,
355
- "title": columnConfig.label ?? colName,
356
- ...(!!columnConfig.info?.hint && { description: columnConfig.info?.hint }),
357
- required: !columnConfig.nullable
358
- }
359
-
360
- }