prostgles-server 2.0.234 → 2.0.237

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 (43) hide show
  1. package/dist/DBSchemaBuilder.d.ts +4 -2
  2. package/dist/DBSchemaBuilder.d.ts.map +1 -1
  3. package/dist/DBSchemaBuilder.js +54 -47
  4. package/dist/DBSchemaBuilder.js.map +1 -1
  5. package/dist/DboBuilder.d.ts +6 -6
  6. package/dist/DboBuilder.d.ts.map +1 -1
  7. package/dist/Prostgles.d.ts +1 -1
  8. package/dist/Prostgles.d.ts.map +1 -1
  9. package/dist/TableConfig.d.ts +2 -2
  10. package/dist/TableConfig.d.ts.map +1 -1
  11. package/dist/TableConfig.js +1 -1
  12. package/dist/TableConfig.js.map +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/validation.d.ts +15 -6
  15. package/dist/validation.d.ts.map +1 -1
  16. package/dist/validation.js +38 -11
  17. package/dist/validation.js.map +1 -1
  18. package/lib/DBSchemaBuilder.d.ts +4 -2
  19. package/lib/DBSchemaBuilder.d.ts.map +1 -1
  20. package/lib/DBSchemaBuilder.js +54 -47
  21. package/lib/DBSchemaBuilder.ts +95 -83
  22. package/lib/DboBuilder.d.ts +6 -6
  23. package/lib/DboBuilder.d.ts.map +1 -1
  24. package/lib/DboBuilder.ts +7 -7
  25. package/lib/Prostgles.d.ts +1 -1
  26. package/lib/Prostgles.d.ts.map +1 -1
  27. package/lib/TableConfig.d.ts +2 -2
  28. package/lib/TableConfig.d.ts.map +1 -1
  29. package/lib/TableConfig.js +1 -1
  30. package/lib/TableConfig.ts +3 -3
  31. package/lib/index.d.ts +1 -1
  32. package/lib/validation.d.ts +15 -6
  33. package/lib/validation.d.ts.map +1 -1
  34. package/lib/validation.js +38 -11
  35. package/lib/validation.ts +50 -17
  36. package/package.json +2 -2
  37. package/tests/client/PID.txt +1 -1
  38. package/tests/isomorphic_queries.js +1 -1
  39. package/tests/isomorphic_queries.ts +1 -1
  40. package/tests/server/DBoGenerated.d.ts +13 -7
  41. package/tests/server/index.js +18 -1
  42. package/tests/server/index.ts +19 -2
  43. package/tests/server/package-lock.json +3 -3
@@ -2,7 +2,7 @@ import { getKeys, asName, AnyObject, TableInfo, ALLOWED_EXTENSION, ALLOWED_CONT
2
2
  import { isPlainObject, JoinInfo } from "./DboBuilder";
3
3
  import { DB, DBHandlerServer, Joins, Prostgles } from "./Prostgles";
4
4
  import { asValue } from "./PubSubManager";
5
- import { getPGCheckConstraint, ValidationSchema } from "./validation";
5
+ import { getPGCheckConstraint, OneOfTypes, ValidationSchema } from "./validation";
6
6
 
7
7
  type ColExtraInfo = {
8
8
  min?: string | number;
@@ -87,7 +87,7 @@ type TextColumn = TextColDef & {
87
87
  }
88
88
 
89
89
  type JSONBColumnDef = TextColDef & {
90
- jsonbSchema: ValidationSchema;
90
+ jsonbSchema: ValidationSchema | Pick<OneOfTypes, "oneOfTypes">;
91
91
 
92
92
  /**
93
93
  * If the new schema CHECK fails old rows the update old rows using this function
@@ -394,7 +394,7 @@ export default class TableConfigurator<LANG_IDS = { en: 1 }> {
394
394
 
395
395
  } else if ("jsonbSchema" in colConf && colConf.jsonbSchema) {
396
396
 
397
- return ` ${colNameEsc} ${getColDef(colConf, "JSONB")} CHECK(${getPGCheckConstraint({ schema: colConf.jsonbSchema, escapedFieldName: colNameEsc }, 0)})`;
397
+ return ` ${colNameEsc} ${getColDef(colConf, "JSONB")} CHECK(${getPGCheckConstraint({ schema: colConf.jsonbSchema, escapedFieldName: colNameEsc, nullable: !!colConf.nullable }, 0)})`;
398
398
 
399
399
  } else {
400
400
  throw "Unknown column config: " + JSON.stringify(colConf);
package/lib/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ProstglesInitOptions } from "./Prostgles";
2
2
  declare function prostgles<S = void>(params: ProstglesInitOptions<S>): Promise<{
3
- db: import("./DboBuilder").DBHandlerServer;
3
+ db: import("./DboBuilder").DBHandlerServer<import("./DboBuilder").TableHandlers>;
4
4
  _db: import("./Prostgles").DB;
5
5
  pgp: import("./Prostgles").PGP;
6
6
  io?: any;
@@ -1,13 +1,16 @@
1
- declare type FieldType = ({
1
+ declare type BaseOptions = {
2
+ optional?: boolean;
3
+ nullable?: boolean;
4
+ };
5
+ declare type SimpleType = BaseOptions & ({
2
6
  type: "number" | "boolean" | "integer" | "string" | "number[]" | "boolean[]" | "integer[]" | "string[]" | ValidationSchema;
3
7
  } | {
4
8
  oneOf: readonly any[];
5
- } | {
9
+ });
10
+ export declare type OneOfTypes = BaseOptions & {
6
11
  oneOfTypes: readonly ValidationSchema[];
7
- }) & {
8
- optional?: boolean;
9
- nullable?: boolean;
10
12
  };
13
+ declare type FieldType = SimpleType | OneOfTypes;
11
14
  declare type GetType<T extends FieldType> = T extends {
12
15
  type: ValidationSchema;
13
16
  } ? SchemaObject<T["type"]> : T extends {
@@ -43,8 +46,14 @@ export declare function validate<T>(obj: T, key: keyof T, validation: FieldType)
43
46
  export declare function validateSchema<S extends ValidationSchema>(schema: S, obj: SchemaObject<S>, objName?: string, optional?: boolean): void;
44
47
  export declare function getPGCheckConstraint(args: {
45
48
  escapedFieldName: string;
46
- schema: ValidationSchema;
49
+ schema: ValidationSchema | OneOfTypes;
50
+ nullable: boolean;
51
+ isRootQuery?: boolean;
47
52
  }, depth: number): string;
53
+ declare type ColOpts = {
54
+ nullable?: boolean;
55
+ };
48
56
  export declare function getSchemaTSTypes(schema: ValidationSchema, leading?: string, isOneOf?: boolean): string;
57
+ export declare function getJSONBSchemaTSTypes(schema: ValidationSchema | OneOfTypes, colOpts: ColOpts, leading?: string, isOneOf?: boolean): string;
49
58
  export {};
50
59
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["validation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["validation.ts"],"names":[],"mappings":"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"}
package/lib/validation.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSchemaTSTypes = exports.getPGCheckConstraint = exports.validateSchema = exports.validate = void 0;
3
+ exports.getJSONBSchemaTSTypes = exports.getSchemaTSTypes = exports.getPGCheckConstraint = exports.validateSchema = exports.validate = void 0;
4
4
  const prostgles_types_1 = require("prostgles-types");
5
5
  const PubSubManager_1 = require("./PubSubManager");
6
6
  /** tests */
@@ -53,14 +53,14 @@ function validateSchema(schema, obj, objName, optional = false) {
53
53
  }
54
54
  exports.validateSchema = validateSchema;
55
55
  function getPGCheckConstraint(args, depth) {
56
- const { schema: s, escapedFieldName } = args;
56
+ const { schema: s, escapedFieldName, nullable } = args;
57
57
  const jsToPGtypes = {
58
58
  "integer": "::INTEGER",
59
59
  "number": "::NUMERIC",
60
60
  "boolean": "::BOOLEAN",
61
61
  "string": "::TEXT"
62
62
  };
63
- const kChecks = (k) => {
63
+ const kChecks = (k, s) => {
64
64
  const t = s[k];
65
65
  const checks = [];
66
66
  const valAsJson = `${escapedFieldName}->${(0, PubSubManager_1.asValue)(k)}`;
@@ -70,7 +70,7 @@ function getPGCheckConstraint(args, depth) {
70
70
  if (t.optional)
71
71
  checks.push(`${escapedFieldName} ? ${(0, PubSubManager_1.asValue)(k)} = FALSE`);
72
72
  if ("oneOfTypes" in t) {
73
- checks.push(`(${t.oneOfTypes.map(subType => getPGCheckConstraint({ escapedFieldName: valAsJson, schema: subType }, depth + 1)).join(" OR ")})`);
73
+ checks.push(`(${t.oneOfTypes.map(subType => getPGCheckConstraint({ escapedFieldName: valAsJson, schema: subType, nullable }, depth + 1)).join(" OR ")})`);
74
74
  }
75
75
  else if ("oneOf" in t) {
76
76
  if (!t.oneOf.length || t.oneOf.some(v => v === undefined || !["number", "boolean", "string", null].includes(typeof v))) {
@@ -96,7 +96,7 @@ function getPGCheckConstraint(args, depth) {
96
96
  }
97
97
  }
98
98
  else {
99
- checks.push("( " + getPGCheckConstraint({ escapedFieldName: valAsJson, schema: t.type }, depth + 1) + " )");
99
+ checks.push("( " + getPGCheckConstraint({ escapedFieldName: valAsJson, schema: t.type, nullable: !!t.nullable }, depth + 1) + " )");
100
100
  }
101
101
  }
102
102
  const result = checks.join(" OR ");
@@ -104,25 +104,43 @@ function getPGCheckConstraint(args, depth) {
104
104
  return `COALESCE(${result}, false)`;
105
105
  return result;
106
106
  };
107
- return (0, prostgles_types_1.getKeys)(s).map(k => "(" + kChecks(k) + ")").join(" AND ");
107
+ const getSchemaChecks = (s) => (0, prostgles_types_1.getKeys)(s).map(k => "(" + kChecks(k, s) + ")").join(" AND ");
108
+ let q = "";
109
+ if (isOneOfTypes(s)) {
110
+ q = s.oneOfTypes.map(t => `(${getSchemaChecks(t)})`).join(" OR ");
111
+ }
112
+ else {
113
+ q = getSchemaChecks(s);
114
+ }
115
+ return nullable ? ` ${escapedFieldName} IS NULL OR (${q})` : q;
108
116
  }
109
117
  exports.getPGCheckConstraint = getPGCheckConstraint;
118
+ const isOneOfTypes = (s) => {
119
+ if ("oneOfTypes" in s) {
120
+ if (!Array.isArray(s.oneOfTypes)) {
121
+ throw "Expecting oneOfTypes to be an array of types";
122
+ }
123
+ return true;
124
+ }
125
+ return false;
126
+ };
110
127
  function getSchemaTSTypes(schema, leading = "", isOneOf = false) {
111
128
  const getFieldType = (def) => {
129
+ const nullType = (def.nullable ? `null | ` : "");
112
130
  if ("type" in def) {
113
131
  if (typeof def.type === "string") {
114
132
  const correctType = def.type.replace("integer", "number");
115
- return correctType;
133
+ return nullType + correctType;
116
134
  }
117
135
  else {
118
- return getSchemaTSTypes(def.type);
136
+ return nullType + getSchemaTSTypes(def.type);
119
137
  }
120
138
  }
121
139
  else if ("oneOf" in def) {
122
- return def.oneOf.map(v => (0, PubSubManager_1.asValue)(v)).join(" | ");
140
+ return nullType + def.oneOf.map(v => (0, PubSubManager_1.asValue)(v)).join(" | ");
123
141
  }
124
142
  else if ("oneOfTypes" in def) {
125
- return def.oneOfTypes.map(v => `\n${leading} | ` + getSchemaTSTypes(v, "", true)).join("");
143
+ return (def.nullable ? `\n${leading} | null` : "") + def.oneOfTypes.map(v => `\n${leading} | ` + getSchemaTSTypes(v, "", true)).join("");
126
144
  }
127
145
  else
128
146
  throw "Unexpected getSchemaTSTypes";
@@ -130,7 +148,7 @@ function getSchemaTSTypes(schema, leading = "", isOneOf = false) {
130
148
  let spacing = isOneOf ? " " : " ";
131
149
  let res = `${leading}{ \n` + (0, prostgles_types_1.getKeys)(schema).map(k => {
132
150
  const def = schema[k];
133
- return `${leading}${spacing}${k}${def.optional ? "?" : ""}: ${def.nullable ? " null | " : ""} ` + getFieldType(def) + ";";
151
+ return `${leading}${spacing}${k}${def.optional ? "?" : ""}: ` + getFieldType(def) + ";";
134
152
  }).join("\n") + ` \n${leading}}${isOneOf ? "" : ";"}`;
135
153
  /** Keep single line */
136
154
  if (isOneOf)
@@ -138,3 +156,12 @@ function getSchemaTSTypes(schema, leading = "", isOneOf = false) {
138
156
  return res;
139
157
  }
140
158
  exports.getSchemaTSTypes = getSchemaTSTypes;
159
+ function getJSONBSchemaTSTypes(schema, colOpts, leading = "", isOneOf = false) {
160
+ if (isOneOfTypes(schema)) {
161
+ return (colOpts.nullable ? `\n${leading} | null` : "") + schema.oneOfTypes.map(s => `\n${leading} | ` + getSchemaTSTypes(s, "", true)).join("");
162
+ }
163
+ else {
164
+ return (colOpts.nullable ? `null | ` : "") + getSchemaTSTypes(schema, leading, isOneOf);
165
+ }
166
+ }
167
+ exports.getJSONBSchemaTSTypes = getJSONBSchemaTSTypes;
package/lib/validation.ts CHANGED
@@ -1,7 +1,12 @@
1
1
  import { asName, getKeys, isEmpty, isObject } from "prostgles-types";
2
2
  import { asValue } from "./PubSubManager";
3
3
 
4
- type FieldType = ({
4
+ type BaseOptions = {
5
+ optional?: boolean;
6
+ nullable?: boolean;
7
+ };
8
+
9
+ type SimpleType = BaseOptions & ({
5
10
  type:
6
11
  | "number" | "boolean" | "integer" | "string"
7
12
  | "number[]" | "boolean[]" | "integer[]" | "string[]"
@@ -9,12 +14,12 @@ type FieldType = ({
9
14
 
10
15
  } | {
11
16
  oneOf: readonly any[];
12
- } | {
17
+ })
18
+
19
+ export type OneOfTypes = BaseOptions & {
13
20
  oneOfTypes: readonly ValidationSchema[];
14
- }) & {
15
- optional?: boolean;
16
- nullable?: boolean;
17
- };
21
+ }
22
+ type FieldType = SimpleType | OneOfTypes;
18
23
 
19
24
  type GetType<T extends FieldType> =
20
25
  | T extends { type: ValidationSchema }? SchemaObject<T["type"]> :
@@ -82,8 +87,8 @@ export function validateSchema<S extends ValidationSchema>(schema: S, obj: Schem
82
87
  getKeys(schema).forEach(k => validate(obj as any, k, schema[k]));
83
88
  }
84
89
 
85
- export function getPGCheckConstraint(args: { escapedFieldName: string; schema: ValidationSchema }, depth: number): string {
86
- const { schema: s, escapedFieldName } = args;
90
+ export function getPGCheckConstraint(args: { escapedFieldName: string; schema: ValidationSchema | OneOfTypes, nullable: boolean; isRootQuery?: boolean; }, depth: number): string {
91
+ const { schema: s, escapedFieldName, nullable } = args;
87
92
 
88
93
  const jsToPGtypes = {
89
94
  "integer": "::INTEGER",
@@ -92,7 +97,7 @@ export function getPGCheckConstraint(args: { escapedFieldName: string; schema: V
92
97
  "string": "::TEXT"
93
98
  }
94
99
 
95
- const kChecks = (k: string) => {
100
+ const kChecks = (k: string, s: ValidationSchema) => {
96
101
  const t = s[k];
97
102
  const checks: string[] = [];
98
103
  const valAsJson = `${escapedFieldName}->${asValue(k)}`;
@@ -101,7 +106,7 @@ export function getPGCheckConstraint(args: { escapedFieldName: string; schema: V
101
106
  if(t.optional) checks.push(`${escapedFieldName} ? ${asValue(k)} = FALSE`);
102
107
 
103
108
  if("oneOfTypes" in t){
104
- checks.push(`(${t.oneOfTypes.map(subType => getPGCheckConstraint({ escapedFieldName: valAsJson, schema: subType }, depth + 1)).join(" OR ")})`)
109
+ checks.push(`(${t.oneOfTypes.map(subType => getPGCheckConstraint({ escapedFieldName: valAsJson, schema: subType, nullable }, depth + 1)).join(" OR ")})`)
105
110
  } else if("oneOf" in t){
106
111
  if(!t.oneOf.length || t.oneOf.some(v => v === undefined || !["number", "boolean", "string", null].includes(typeof v))) {
107
112
  throw new Error(`Invalid ValidationSchema for property: ${k} of field ${escapedFieldName}: oneOf cannot be empty AND can only contain: numbers, text, boolean, null`);
@@ -122,7 +127,7 @@ export function getPGCheckConstraint(args: { escapedFieldName: string; schema: V
122
127
  checks.push(`jsonb_typeof(${valAsJson}) = ${asValue(correctType)} `)
123
128
  }
124
129
  } else {
125
- checks.push("( " + getPGCheckConstraint({ escapedFieldName: valAsJson, schema: t.type }, depth + 1) + " )")
130
+ checks.push("( " + getPGCheckConstraint({ escapedFieldName: valAsJson, schema: t.type, nullable: !!t.nullable }, depth + 1) + " )")
126
131
  }
127
132
  }
128
133
  const result = checks.join(" OR ")
@@ -130,22 +135,42 @@ export function getPGCheckConstraint(args: { escapedFieldName: string; schema: V
130
135
  return result
131
136
  }
132
137
 
133
- return getKeys(s).map(k => "(" + kChecks(k) + ")").join(" AND ");
138
+ const getSchemaChecks = (s: ValidationSchema) => getKeys(s).map(k => "(" + kChecks(k, s) + ")").join(" AND ")
139
+
140
+ let q = "";
141
+ if(isOneOfTypes(s)){
142
+ q = s.oneOfTypes.map(t => `(${getSchemaChecks(t)})` ).join(" OR ");
143
+ } else {
144
+ q = getSchemaChecks(s);
145
+ }
146
+ return nullable? ` ${escapedFieldName} IS NULL OR (${q})` : q
147
+ }
148
+ type ColOpts = { nullable?: boolean };
149
+ const isOneOfTypes = (s: ValidationSchema | OneOfTypes): s is OneOfTypes => {
150
+
151
+ if("oneOfTypes" in s){
152
+ if(!Array.isArray(s.oneOfTypes)){
153
+ throw "Expecting oneOfTypes to be an array of types";
154
+ }
155
+ return true;
156
+ }
157
+ return false;
134
158
  }
135
159
 
136
160
  export function getSchemaTSTypes(schema: ValidationSchema, leading = "", isOneOf = false): string {
137
161
  const getFieldType = (def: FieldType) => {
162
+ const nullType = (def.nullable? `null | ` : "");
138
163
  if("type" in def){
139
164
  if(typeof def.type === "string"){
140
165
  const correctType = def.type.replace("integer", "number")
141
- return correctType
166
+ return nullType + correctType
142
167
  } else {
143
- return getSchemaTSTypes(def.type)
168
+ return nullType + getSchemaTSTypes(def.type)
144
169
  }
145
170
  } else if("oneOf" in def){
146
- return def.oneOf.map(v => asValue(v)).join(" | ")
171
+ return nullType + def.oneOf.map(v => asValue(v)).join(" | ")
147
172
  } else if("oneOfTypes" in def){
148
- return def.oneOfTypes.map(v => `\n${leading} | ` + getSchemaTSTypes(v, "", true)).join("")
173
+ return (def.nullable? `\n${leading} | null` : "") + def.oneOfTypes.map(v => `\n${leading} | ` + getSchemaTSTypes(v, "", true)).join("")
149
174
  } else throw "Unexpected getSchemaTSTypes"
150
175
  }
151
176
 
@@ -153,10 +178,18 @@ export function getSchemaTSTypes(schema: ValidationSchema, leading = "", isOneOf
153
178
 
154
179
  let res = `${leading}{ \n` + getKeys(schema).map(k => {
155
180
  const def = schema[k];
156
- return `${leading}${spacing}${k}${def.optional? "?" : ""}: ${def.nullable? " null | " : ""} ` + getFieldType(def) + ";";
181
+ return `${leading}${spacing}${k}${def.optional? "?" : ""}: ` + getFieldType(def) + ";";
157
182
  }).join("\n") + ` \n${leading}}${isOneOf? "" : ";"}`;
158
183
 
159
184
  /** Keep single line */
160
185
  if(isOneOf) res = res.split("\n").join("")
161
186
  return res;
162
187
  }
188
+
189
+ export function getJSONBSchemaTSTypes(schema: ValidationSchema | OneOfTypes, colOpts: ColOpts, leading = "", isOneOf = false): string {
190
+ if(isOneOfTypes(schema)){
191
+ return (colOpts.nullable? `\n${leading} | null` : "") + schema.oneOfTypes.map(s => `\n${leading} | ` + getSchemaTSTypes(s, "", true)).join("")
192
+ } else {
193
+ return (colOpts.nullable? `null | ` : "") + getSchemaTSTypes(schema, leading, isOneOf);
194
+ }
195
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prostgles-server",
3
- "version": "2.0.234",
3
+ "version": "2.0.237",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -29,7 +29,7 @@
29
29
  "aws-sdk": "^2.1168.0",
30
30
  "bluebird": "^3.7.2",
31
31
  "check-disk-space": "^3.3.1",
32
- "file-type": "^17.1.3",
32
+ "file-type": "^17.1.4",
33
33
  "pg-promise": "^10.11.1",
34
34
  "prostgles-types": "^1.5.169",
35
35
  "sharp": "^0.30.7"
@@ -1 +1 @@
1
- 3720
1
+ 77079
@@ -558,7 +558,7 @@ async function isomorphic(db) {
558
558
  }
559
559
  },
560
560
  */
561
- const json = { a: true, arr: "2", arr1: 3, arr2: [1] };
561
+ const json = { a: true, arr: "2", arr1: 3, arr2: [1], arrStr: ["1123.string"] };
562
562
  const fo = await db.tjson.insert({ json }, { returning: "*" });
563
563
  // assert.deepStrictEqual(fo.json, json);
564
564
  await db.tjson.insert({ json: { ...json, o: { o1: 2, o2: true } } });
@@ -641,7 +641,7 @@ export default async function isomorphic(db: Partial<DBHandlerServer> | Partial<
641
641
  },
642
642
  */
643
643
 
644
- const json = {a: true, arr: "2", arr1: 3, arr2: [1] }
644
+ const json = {a: true, arr: "2", arr1: 3, arr2: [1], arrStr: ["1123.string"] }
645
645
  const fo = await db.tjson.insert({ json }, { returning: "*"});
646
646
  // assert.deepStrictEqual(fo.json, json);
647
647
  await db.tjson.insert({ json: {...json, o: { o1: 2, o2: true } } })
@@ -336,14 +336,20 @@ export type DBSchemaGenerated = {
336
336
  delete: true;
337
337
  columns: {
338
338
  json: {
339
- a: boolean;
340
- arr: '1' | '2' | '3';
341
- arr1: 1 | 2 | 3;
342
- arr2: number[];
343
- o?:
344
- | { o1: number; }
345
- | { o2: boolean; };
339
+ a: boolean;
340
+ arr: '1' | '2' | '3';
341
+ arr1: 1 | 2 | 3;
342
+ arr2: number[];
343
+ arrStr?: null | string[];
344
+ o?:
345
+ | null
346
+ | { o1: number; }
347
+ | { o2: boolean; };
346
348
  };
349
+ jsonOneOf?:
350
+ | null
351
+ | { command: 'a'; }
352
+ | { command: 'b'; option: number[]; }
347
353
  };
348
354
  };
349
355
  tr1: {
@@ -72,7 +72,24 @@ function dd() {
72
72
  arr: { oneOf: ["1", "2", "3"] },
73
73
  arr1: { oneOf: [1, 2, 3] },
74
74
  arr2: { type: "integer[]" },
75
- o: { oneOfTypes: [{ o1: { type: "integer" } }, { o2: { type: "boolean" } }], optional: true },
75
+ arrStr: { type: "string[]", optional: true, nullable: true },
76
+ o: { oneOfTypes: [{ o1: { type: "integer" } }, { o2: { type: "boolean" } }], optional: true, nullable: true },
77
+ }
78
+ },
79
+ jsonOneOf: { nullable: true, jsonbSchema: {
80
+ oneOfTypes: [
81
+ { command: { oneOf: ["a"] } },
82
+ {
83
+ command: { oneOf: ["b"] },
84
+ option: { type: "integer[]" }
85
+ }
86
+ ]
87
+ // a: { type: "boolean" },
88
+ // arr: { oneOf: ["1", "2", "3"] },
89
+ // arr1: { oneOf: [1, 2, 3] },
90
+ // arr2: { type: "integer[]" },
91
+ // arrStr: { type: "string[]", optional: true },
92
+ // o: { oneOfTypes: [{ o1: { type: "integer" } }, { o2: { type: "boolean" } }], optional: true },
76
93
  }
77
94
  }
78
95
  }
@@ -93,9 +93,26 @@ function dd(){
93
93
  arr: { oneOf: ["1", "2", "3"] },
94
94
  arr1: { oneOf: [1, 2, 3] },
95
95
  arr2: { type: "integer[]" },
96
- o: { oneOfTypes: [{ o1: { type: "integer" } }, { o2: { type: "boolean" } }], optional: true },
96
+ arrStr: { type: "string[]", optional: true, nullable: true },
97
+ o: { oneOfTypes: [{ o1: { type: "integer" } }, { o2: { type: "boolean" } }], optional: true, nullable: true },
97
98
  }
98
- }
99
+ },
100
+ jsonOneOf: { nullable: true, jsonbSchema: {
101
+ oneOfTypes: [
102
+ { command: { oneOf: ["a"] } },
103
+ {
104
+ command: { oneOf: ["b"] },
105
+ option: { type: "integer[]" }
106
+ }
107
+ ]
108
+ // a: { type: "boolean" },
109
+ // arr: { oneOf: ["1", "2", "3"] },
110
+ // arr1: { oneOf: [1, 2, 3] },
111
+ // arr2: { type: "integer[]" },
112
+ // arrStr: { type: "string[]", optional: true },
113
+ // o: { oneOfTypes: [{ o1: { type: "integer" } }, { o2: { type: "boolean" } }], optional: true },
114
+ }
115
+ }
99
116
  }
100
117
  },
101
118
  lookup_col1: {
@@ -21,7 +21,7 @@
21
21
  },
22
22
  "../..": {
23
23
  "name": "prostgles-server",
24
- "version": "2.0.233",
24
+ "version": "2.0.236",
25
25
  "license": "MIT",
26
26
  "dependencies": {
27
27
  "@aws-sdk/client-s3": "^3.121.0",
@@ -29,7 +29,7 @@
29
29
  "aws-sdk": "^2.1168.0",
30
30
  "bluebird": "^3.7.2",
31
31
  "check-disk-space": "^3.3.1",
32
- "file-type": "^17.1.3",
32
+ "file-type": "^17.1.4",
33
33
  "pg-promise": "^10.11.1",
34
34
  "prostgles-types": "^1.5.169",
35
35
  "sharp": "^0.30.7"
@@ -1373,7 +1373,7 @@
1373
1373
  "aws-sdk": "^2.1168.0",
1374
1374
  "bluebird": "^3.7.2",
1375
1375
  "check-disk-space": "^3.3.1",
1376
- "file-type": "^17.1.3",
1376
+ "file-type": "^17.1.4",
1377
1377
  "pg-promise": "^10.11.1",
1378
1378
  "prostgles-types": "^1.5.169",
1379
1379
  "sharp": "^0.30.7",