bootpress 4.1.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,22 +2,37 @@ import { HttpError } from "..";
2
2
 
3
3
  type TypeMap = {
4
4
  "string": string,
5
- "string?": string | null,
5
+ "string[]": string[],
6
6
  "boolean": boolean,
7
- "boolean?": boolean | null,
7
+ "boolean[]": boolean[],
8
8
  "number": number,
9
- "number?": number | null,
9
+ "number[]": number[],
10
10
  }
11
11
 
12
+ type ValidTypeKeys = keyof TypeMap;
13
+ type ValOf<T extends keyof TypeMap> = TypeMap[T]
14
+
15
+ type StringEndsWithQm = `${string}?`;
16
+
12
17
  type JsSchema = {
13
- [key: string]: keyof TypeMap | JsSchema
18
+ [key: PropertyKey]: ValidTypeKeys | JsSchema | ArraySchema
14
19
  }
15
20
 
16
- type SchemadRecord<T> = { [E in keyof T]: T[E] extends string ? TypeMap[T[E]] : SchemadRecord<T[E]> };
21
+ type ArraySchema = [JsSchema]
22
+
23
+ type RemoveQuestionMark<T extends string> = T extends `${infer Prefix}?` ? Prefix : T;
24
+
25
+ type TypedSchema<T> = {
26
+ [key in keyof T as `${RemoveQuestionMark<string & key>}`]:
27
+ key extends StringEndsWithQm ? T[key] extends ValidTypeKeys ? ValOf<T[key]> | null : T[key] extends ArraySchema ? TypedSchema<T[key][0]>[] | null : TypedSchema<T[key]> | null
28
+ : (T[key] extends ValidTypeKeys ? ValOf<T[key]> : T[key] extends ArraySchema ? TypedSchema<T[key][0]>[] : TypedSchema<T[key]>)
29
+ }
17
30
 
18
31
  export function getOrThrow<T, E extends HttpError>(data: T, error: E): T;
19
32
  export function getOrElse<T, E>(data: T, defaultValue: E): T | E;
20
33
  export function asBoolean(o: any): boolean;
21
34
  export function asNumber(o: any): number;
22
35
  export function asInteger(o: any): number;
23
- export function asSchema<T extends JsSchema>(o: any, jsSchema: T): SchemadRecord<T>
36
+ export function asString(o: any): string;
37
+ export function asSchema<T extends JsSchema>(o: any, jsSchema: T): TypedSchema<T>;
38
+ export function schema<T extends JsSchema>(schema: T): T;
package/helpers/index.js CHANGED
@@ -17,7 +17,7 @@ function getOrElse(data, defaultValue) {
17
17
  }
18
18
 
19
19
  function asBoolean(o, errorMessage = undefined, errorStatus = 400) {
20
- errorMessage = errorMessage ?? `Value ${o} should have been a boolean but it's not`;
20
+ errorMessage = errorMessage ?? `Value ${o} should have been a boolean but it's ${typeof o}`;
21
21
  if (typeof o === "string") {
22
22
  const lowercased = o.toLowerCase();
23
23
  const validBooleanStrings = new Map(Object.entries({
@@ -39,7 +39,7 @@ function asBoolean(o, errorMessage = undefined, errorStatus = 400) {
39
39
  }
40
40
 
41
41
  function asNumber(o, errorMessage = undefined, errorStatus = 400) {
42
- errorMessage = errorMessage ?? `Value ${o} should have been a number but it's not`
42
+ errorMessage = errorMessage ?? `Value ${o} should have been a number but it's ${typeof o}`
43
43
  if (typeof o === "number") {
44
44
  return o;
45
45
  }
@@ -53,7 +53,7 @@ function asNumber(o, errorMessage = undefined, errorStatus = 400) {
53
53
  }
54
54
 
55
55
  function asInteger(o, errorMessage = undefined, errorStatus = 400) {
56
- errorMessage = errorMessage ?? `Value ${o} should have been a integer but it's not`;
56
+ errorMessage = errorMessage ?? `Value ${o} should have been a integer but it's ${typeof o}`;
57
57
  let value = o;
58
58
  if (typeof o === "string") {
59
59
  value = Number(o);
@@ -64,22 +64,54 @@ function asInteger(o, errorMessage = undefined, errorStatus = 400) {
64
64
  return value;
65
65
  }
66
66
 
67
- function asSchema(o, schema){
67
+ function asString(o, errorMessage = undefined, errorStatus = 400) {
68
+ errorMessage = errorMessage ?? `Value ${o} should have been a string but it's not`;
69
+ const validTypes = ["string", "number"];
70
+ if (validTypes.includes(typeof o)) {
71
+ return '' + o;
72
+ } else {
73
+ throw new HttpError(errorStatus, errorMessage);
74
+ }
75
+ }
76
+
77
+ function asSchema(o, schema) {
68
78
  const schemaKeyValues = Object.entries(schema);
69
- for(let i = 0; i < schemaKeyValues.length; i ++){
70
- const key = schemaKeyValues[i][0];
79
+ let result = {};
80
+ for (let i = 0; i < schemaKeyValues.length; i++) {
81
+ let key = schemaKeyValues[i][0];
82
+ if (key.endsWith("?")) {
83
+ key = key.substring(0, key.length - 1);
84
+ if (o[key] == null) {
85
+ result[key] = null;
86
+ continue;
87
+ }
88
+ }
71
89
  const expectedType = schemaKeyValues[i][1];
72
- const errorMessage = `Value of ${key} should have been a ${expectedType} but it's a ${typeof o[key]}`;
90
+ const errorMessage = o[key] == null ? `Value of ${key} should have been a ${expectedType} but it's null` : `Value of ${key} should have been a ${expectedType} but it's a ${typeof o[key]}`;
73
91
 
74
- if(typeof expectedType === "object"){
75
- asSchema(o[key], expectedType);
92
+ if (typeof expectedType === "object") {
93
+ if (Array.isArray(expectedType)) {
94
+ result[key] = [];
95
+ for (let j = 0; j < o[key].length; j++) {
96
+ result[key][j] = asSchema(o[key][j], expectedType[0])
97
+ }
98
+ } else {
99
+ result[key] = asSchema(o[key], expectedType);
100
+ }
76
101
  }
77
- else if(typeof expectedType === "string"){
78
- if(expectedType.endsWith("?") && o[key] == null){
79
- continue;
102
+ else if (typeof expectedType === "string") {
103
+ if (expectedType.endsWith("[]")) {
104
+ const elementType = expectedType.replace("[]", "");
105
+ for (let j = 0; j < o[key].length; j++){
106
+ if(typeof o[key][j] !== elementType){
107
+ throw new HttpError(400, `Each element of ${key} should have been a ${elementType} but a ${typeof o[key][j]} is present (${o[key][j]})`);
108
+ }
109
+ }
110
+ result[key] = o[key];
80
111
  }
81
- expectedType.replace("?", "");
82
- if(typeof o[key] !== expectedType){
112
+ else if (typeof o[key] === expectedType) {
113
+ result[key] = o[key];
114
+ } else {
83
115
  throw new HttpError(400, errorMessage);
84
116
  }
85
117
  }
@@ -87,7 +119,12 @@ function asSchema(o, schema){
87
119
  throw new HttpError(500, `Type of a schema key should be a primitive type or another schema`);
88
120
  }
89
121
  }
90
- return o;
122
+ return result;
123
+ }
124
+
125
+
126
+ function schema(schema) {
127
+ return schema;
91
128
  }
92
129
 
93
130
  module.exports = {
@@ -96,5 +133,7 @@ module.exports = {
96
133
  asBoolean,
97
134
  asNumber,
98
135
  asInteger,
99
- asSchema
136
+ asString,
137
+ asSchema,
138
+ schema
100
139
  }
@@ -0,0 +1,12 @@
1
+ import { asSchema, schema } from ".";
2
+
3
+ const mysch = schema({
4
+ "name": "string",
5
+ "parents": [{
6
+ "name": "string",
7
+ "relation": "string",
8
+ "age?": "number"
9
+ }]
10
+ });
11
+
12
+ asSchema({}, mysch).parents[0].age
package/package.json CHANGED
@@ -1,33 +1,33 @@
1
- {
2
- "name": "bootpress",
3
- "version": "4.1.1",
4
- "description": "REST service methods for express",
5
- "main": "index.js",
6
- "scripts": {},
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/ufukbakan/bootpress.git"
10
- },
11
- "keywords": [
12
- "bootpress",
13
- "express",
14
- "rest",
15
- "service",
16
- "methods",
17
- "spring",
18
- "boot",
19
- "like"
20
- ],
21
- "author": "Ufuk Bakan",
22
- "license": "MIT",
23
- "bugs": {
24
- "url": "https://github.com/ufukbakan/bootpress/issues"
25
- },
26
- "homepage": "https://github.com/ufukbakan/bootpress#readme",
27
- "dependencies": {
28
- "@types/body-parser": "^1.19.2",
29
- "@types/express": "^4.17.17",
30
- "body-parser": "^1.20.2",
31
- "express": "^4.18.2"
32
- }
33
- }
1
+ {
2
+ "name": "bootpress",
3
+ "version": "5.0.0",
4
+ "description": "REST service methods for express",
5
+ "main": "index.js",
6
+ "scripts": {},
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/ufukbakan/bootpress.git"
10
+ },
11
+ "keywords": [
12
+ "bootpress",
13
+ "express",
14
+ "rest",
15
+ "service",
16
+ "methods",
17
+ "spring",
18
+ "boot",
19
+ "like"
20
+ ],
21
+ "author": "Ufuk Bakan",
22
+ "license": "MIT",
23
+ "bugs": {
24
+ "url": "https://github.com/ufukbakan/bootpress/issues"
25
+ },
26
+ "homepage": "https://github.com/ufukbakan/bootpress#readme",
27
+ "dependencies": {
28
+ "@types/body-parser": "^1.19.2",
29
+ "@types/express": "^4.17.17",
30
+ "body-parser": "^1.20.2",
31
+ "express": "^4.18.2"
32
+ }
33
+ }