jopi-toolkit 3.0.5

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 (237) hide show
  1. package/README.md +6 -0
  2. package/dist/jk_app/common.d.ts +40 -0
  3. package/dist/jk_app/common.js +313 -0
  4. package/dist/jk_app/common.js.map +1 -0
  5. package/dist/jk_app/index.d.ts +1 -0
  6. package/dist/jk_app/index.js +4 -0
  7. package/dist/jk_app/index.js.map +1 -0
  8. package/dist/jk_app/jBundler_ifBrowser.d.ts +1 -0
  9. package/dist/jk_app/jBundler_ifBrowser.js +3 -0
  10. package/dist/jk_app/jBundler_ifBrowser.js.map +1 -0
  11. package/dist/jk_app/jBundler_ifServer.d.ts +1 -0
  12. package/dist/jk_app/jBundler_ifServer.js +9 -0
  13. package/dist/jk_app/jBundler_ifServer.js.map +1 -0
  14. package/dist/jk_appResolver/common.d.ts +40 -0
  15. package/dist/jk_appResolver/common.js +306 -0
  16. package/dist/jk_appResolver/common.js.map +1 -0
  17. package/dist/jk_appResolver/index.d.ts +30 -0
  18. package/dist/jk_appResolver/index.js +276 -0
  19. package/dist/jk_appResolver/index.js.map +1 -0
  20. package/dist/jk_appResolver/jBundler_ifBrowser.d.ts +1 -0
  21. package/dist/jk_appResolver/jBundler_ifBrowser.js +3 -0
  22. package/dist/jk_appResolver/jBundler_ifBrowser.js.map +1 -0
  23. package/dist/jk_appResolver/jBundler_ifServer.d.ts +1 -0
  24. package/dist/jk_appResolver/jBundler_ifServer.js +9 -0
  25. package/dist/jk_appResolver/jBundler_ifServer.js.map +1 -0
  26. package/dist/jk_compress/index.d.ts +1 -0
  27. package/dist/jk_compress/index.js +2 -0
  28. package/dist/jk_compress/index.js.map +1 -0
  29. package/dist/jk_compress/jBundler_ifBrowser.d.ts +2 -0
  30. package/dist/jk_compress/jBundler_ifBrowser.js +3 -0
  31. package/dist/jk_compress/jBundler_ifBrowser.js.map +1 -0
  32. package/dist/jk_compress/jBundler_ifServer.d.ts +5 -0
  33. package/dist/jk_compress/jBundler_ifServer.js +11 -0
  34. package/dist/jk_compress/jBundler_ifServer.js.map +1 -0
  35. package/dist/jk_crypto/index.d.ts +1 -0
  36. package/dist/jk_crypto/index.js +2 -0
  37. package/dist/jk_crypto/index.js.map +1 -0
  38. package/dist/jk_crypto/jBundler_ifBrowser.d.ts +2 -0
  39. package/dist/jk_crypto/jBundler_ifBrowser.js +3 -0
  40. package/dist/jk_crypto/jBundler_ifBrowser.js.map +1 -0
  41. package/dist/jk_crypto/jBundler_ifServer.d.ts +5 -0
  42. package/dist/jk_crypto/jBundler_ifServer.js +17 -0
  43. package/dist/jk_crypto/jBundler_ifServer.js.map +1 -0
  44. package/dist/jk_events/index.d.ts +35 -0
  45. package/dist/jk_events/index.js +134 -0
  46. package/dist/jk_events/index.js.map +1 -0
  47. package/dist/jk_fs/common.d.ts +16 -0
  48. package/dist/jk_fs/common.js +2 -0
  49. package/dist/jk_fs/common.js.map +1 -0
  50. package/dist/jk_fs/index.d.ts +2 -0
  51. package/dist/jk_fs/index.js +3 -0
  52. package/dist/jk_fs/index.js.map +1 -0
  53. package/dist/jk_fs/jBundler_ifBrowser.d.ts +41 -0
  54. package/dist/jk_fs/jBundler_ifBrowser.js +88 -0
  55. package/dist/jk_fs/jBundler_ifBrowser.js.map +1 -0
  56. package/dist/jk_fs/jBundler_ifServer.d.ts +48 -0
  57. package/dist/jk_fs/jBundler_ifServer.js +286 -0
  58. package/dist/jk_fs/jBundler_ifServer.js.map +1 -0
  59. package/dist/jk_linker/TypeComposite.d.ts +12 -0
  60. package/dist/jk_linker/TypeComposite.js +112 -0
  61. package/dist/jk_linker/TypeComposite.js.map +1 -0
  62. package/dist/jk_linker/arobaseType_List.d.ts +44 -0
  63. package/dist/jk_linker/arobaseType_List.js +183 -0
  64. package/dist/jk_linker/arobaseType_List.js.map +1 -0
  65. package/dist/jk_linker/arobaseTypes.d.ts +45 -0
  66. package/dist/jk_linker/arobaseTypes.js +181 -0
  67. package/dist/jk_linker/arobaseTypes.js.map +1 -0
  68. package/dist/jk_linker/binding.d.ts +1 -0
  69. package/dist/jk_linker/binding.js +13 -0
  70. package/dist/jk_linker/binding.js.map +1 -0
  71. package/dist/jk_linker/engine.d.ts +119 -0
  72. package/dist/jk_linker/engine.js +553 -0
  73. package/dist/jk_linker/engine.js.map +1 -0
  74. package/dist/jk_linker/index.d.ts +1 -0
  75. package/dist/jk_linker/index.js +2 -0
  76. package/dist/jk_linker/index.js.map +1 -0
  77. package/dist/jk_linker/install.d.ts +4 -0
  78. package/dist/jk_linker/install.js +44 -0
  79. package/dist/jk_linker/install.js.map +1 -0
  80. package/dist/jk_linker/jBundler_ifServer.d.ts +3 -0
  81. package/dist/jk_linker/jBundler_ifServer.js +4 -0
  82. package/dist/jk_linker/jBundler_ifServer.js.map +1 -0
  83. package/dist/jk_linker/modulesInitProcessor.d.ts +7 -0
  84. package/dist/jk_linker/modulesInitProcessor.js +36 -0
  85. package/dist/jk_linker/modulesInitProcessor.js.map +1 -0
  86. package/dist/jk_linker/typeChunks.d.ts +15 -0
  87. package/dist/jk_linker/typeChunks.js +42 -0
  88. package/dist/jk_linker/typeChunks.js.map +1 -0
  89. package/dist/jk_linker/typeComposites.d.ts +13 -0
  90. package/dist/jk_linker/typeComposites.js +121 -0
  91. package/dist/jk_linker/typeComposites.js.map +1 -0
  92. package/dist/jk_linker/typeEvents.d.ts +5 -0
  93. package/dist/jk_linker/typeEvents.js +29 -0
  94. package/dist/jk_linker/typeEvents.js.map +1 -0
  95. package/dist/jk_linker/typeList.d.ts +30 -0
  96. package/dist/jk_linker/typeList.js +144 -0
  97. package/dist/jk_linker/typeList.js.map +1 -0
  98. package/dist/jk_linker/typeListeners.d.ts +21 -0
  99. package/dist/jk_linker/typeListeners.js +188 -0
  100. package/dist/jk_linker/typeListeners.js.map +1 -0
  101. package/dist/jk_linker/typeReplaces.d.ts +8 -0
  102. package/dist/jk_linker/typeReplaces.js +41 -0
  103. package/dist/jk_linker/typeReplaces.js.map +1 -0
  104. package/dist/jk_os/index.d.ts +1 -0
  105. package/dist/jk_os/index.js +2 -0
  106. package/dist/jk_os/index.js.map +1 -0
  107. package/dist/jk_os/jBundler_ifBrowser.d.ts +3 -0
  108. package/dist/jk_os/jBundler_ifBrowser.js +10 -0
  109. package/dist/jk_os/jBundler_ifBrowser.js.map +1 -0
  110. package/dist/jk_os/jBundler_ifServer.d.ts +2 -0
  111. package/dist/jk_os/jBundler_ifServer.js +64 -0
  112. package/dist/jk_os/jBundler_ifServer.js.map +1 -0
  113. package/dist/jk_process/index.d.ts +1 -0
  114. package/dist/jk_process/index.js +2 -0
  115. package/dist/jk_process/index.js.map +1 -0
  116. package/dist/jk_process/jBundler_ifBrowser.d.ts +4 -0
  117. package/dist/jk_process/jBundler_ifBrowser.js +21 -0
  118. package/dist/jk_process/jBundler_ifBrowser.js.map +1 -0
  119. package/dist/jk_process/jBundler_ifServer.d.ts +4 -0
  120. package/dist/jk_process/jBundler_ifServer.js +5 -0
  121. package/dist/jk_process/jBundler_ifServer.js.map +1 -0
  122. package/dist/jk_registry/index.d.ts +11 -0
  123. package/dist/jk_registry/index.js +36 -0
  124. package/dist/jk_registry/index.js.map +1 -0
  125. package/dist/jk_schemas/index.d.ts +118 -0
  126. package/dist/jk_schemas/index.js +220 -0
  127. package/dist/jk_schemas/index.js.map +1 -0
  128. package/dist/jk_streams/index.d.ts +1 -0
  129. package/dist/jk_streams/index.js +6 -0
  130. package/dist/jk_streams/index.js.map +1 -0
  131. package/dist/jk_term/index.d.ts +51 -0
  132. package/dist/jk_term/index.js +102 -0
  133. package/dist/jk_term/index.js.map +1 -0
  134. package/dist/jk_thread/common.d.ts +3 -0
  135. package/dist/jk_thread/common.js +8 -0
  136. package/dist/jk_thread/common.js.map +1 -0
  137. package/dist/jk_thread/index.d.ts +2 -0
  138. package/dist/jk_thread/index.js +3 -0
  139. package/dist/jk_thread/index.js.map +1 -0
  140. package/dist/jk_thread/jBundler_ifBrowser.d.ts +6 -0
  141. package/dist/jk_thread/jBundler_ifBrowser.js +15 -0
  142. package/dist/jk_thread/jBundler_ifBrowser.js.map +1 -0
  143. package/dist/jk_thread/jBundler_ifServer.d.ts +6 -0
  144. package/dist/jk_thread/jBundler_ifServer.js +22 -0
  145. package/dist/jk_thread/jBundler_ifServer.js.map +1 -0
  146. package/dist/jk_timer/index.d.ts +26 -0
  147. package/dist/jk_timer/index.js +100 -0
  148. package/dist/jk_timer/index.js.map +1 -0
  149. package/dist/jk_tools/index.d.ts +20 -0
  150. package/dist/jk_tools/index.js +72 -0
  151. package/dist/jk_tools/index.js.map +1 -0
  152. package/dist/jk_translate/index.d.ts +21 -0
  153. package/dist/jk_translate/index.js +56 -0
  154. package/dist/jk_translate/index.js.map +1 -0
  155. package/dist/jk_webSocket/common.d.ts +2 -0
  156. package/dist/jk_webSocket/common.js +7 -0
  157. package/dist/jk_webSocket/common.js.map +1 -0
  158. package/dist/jk_webSocket/index.d.ts +2 -0
  159. package/dist/jk_webSocket/index.js +3 -0
  160. package/dist/jk_webSocket/index.js.map +1 -0
  161. package/dist/jk_webSocket/jBundler_ifBrowser.ts.d.ts +3 -0
  162. package/dist/jk_webSocket/jBundler_ifBrowser.ts.js +14 -0
  163. package/dist/jk_webSocket/jBundler_ifBrowser.ts.js.map +1 -0
  164. package/dist/jk_webSocket/jBundler_ifServer.d.ts +7 -0
  165. package/dist/jk_webSocket/jBundler_ifServer.js +41 -0
  166. package/dist/jk_webSocket/jBundler_ifServer.js.map +1 -0
  167. package/dist/jk_what/index.d.ts +1 -0
  168. package/dist/jk_what/index.js +2 -0
  169. package/dist/jk_what/index.js.map +1 -0
  170. package/dist/jk_what/jBundler_ifBrowser.d.ts +5 -0
  171. package/dist/jk_what/jBundler_ifBrowser.js +6 -0
  172. package/dist/jk_what/jBundler_ifBrowser.js.map +1 -0
  173. package/dist/jk_what/jBundler_ifServer.d.ts +5 -0
  174. package/dist/jk_what/jBundler_ifServer.js +6 -0
  175. package/dist/jk_what/jBundler_ifServer.js.map +1 -0
  176. package/package.json +100 -0
  177. package/src/jk_app/common.js +442 -0
  178. package/src/jk_app/common.ts +389 -0
  179. package/src/jk_app/index.js +3 -0
  180. package/src/jk_app/index.ts +4 -0
  181. package/src/jk_app/jBundler_ifBrowser.ts +2 -0
  182. package/src/jk_app/jBundler_ifServer.js +8 -0
  183. package/src/jk_app/jBundler_ifServer.ts +11 -0
  184. package/src/jk_compress/index.js +1 -0
  185. package/src/jk_compress/index.ts +1 -0
  186. package/src/jk_compress/jBundler_ifBrowser.ts +2 -0
  187. package/src/jk_compress/jBundler_ifServer.js +10 -0
  188. package/src/jk_compress/jBundler_ifServer.ts +16 -0
  189. package/src/jk_crypto/index.js +1 -0
  190. package/src/jk_crypto/index.ts +1 -0
  191. package/src/jk_crypto/jBundler_ifBrowser.ts +2 -0
  192. package/src/jk_crypto/jBundler_ifServer.ts +21 -0
  193. package/src/jk_events/index.js +203 -0
  194. package/src/jk_events/index.ts +168 -0
  195. package/src/jk_fs/common.js +1 -0
  196. package/src/jk_fs/common.ts +20 -0
  197. package/src/jk_fs/index.js +2 -0
  198. package/src/jk_fs/index.ts +2 -0
  199. package/src/jk_fs/jBundler_ifBrowser.ts +116 -0
  200. package/src/jk_fs/jBundler_ifServer.ts +308 -0
  201. package/src/jk_os/index.js +1 -0
  202. package/src/jk_os/index.ts +1 -0
  203. package/src/jk_os/jBundler_ifBrowser.ts +11 -0
  204. package/src/jk_os/jBundler_ifServer.js +132 -0
  205. package/src/jk_os/jBundler_ifServer.ts +63 -0
  206. package/src/jk_process/index.ts +1 -0
  207. package/src/jk_process/jBundler_ifBrowser.ts +20 -0
  208. package/src/jk_process/jBundler_ifServer.ts +4 -0
  209. package/src/jk_schemas/TODO.txt +7 -0
  210. package/src/jk_schemas/index.js +248 -0
  211. package/src/jk_schemas/index.ts +416 -0
  212. package/src/jk_streams/index.ts +6 -0
  213. package/src/jk_term/index.js +146 -0
  214. package/src/jk_term/index.ts +131 -0
  215. package/src/jk_thread/common.ts +9 -0
  216. package/src/jk_thread/index.js +2 -0
  217. package/src/jk_thread/index.ts +2 -0
  218. package/src/jk_thread/jBundler_ifBrowser.ts +18 -0
  219. package/src/jk_thread/jBundler_ifServer.js +21 -0
  220. package/src/jk_thread/jBundler_ifServer.ts +28 -0
  221. package/src/jk_timer/index.js +155 -0
  222. package/src/jk_timer/index.ts +150 -0
  223. package/src/jk_tools/index.js +82 -0
  224. package/src/jk_tools/index.ts +82 -0
  225. package/src/jk_translate/index.js +56 -0
  226. package/src/jk_translate/index.ts +85 -0
  227. package/src/jk_webSocket/common.js +6 -0
  228. package/src/jk_webSocket/common.ts +7 -0
  229. package/src/jk_webSocket/index.js +2 -0
  230. package/src/jk_webSocket/index.ts +2 -0
  231. package/src/jk_webSocket/jBundler_ifBrowser.ts.ts +16 -0
  232. package/src/jk_webSocket/jBundler_ifServer.js +40 -0
  233. package/src/jk_webSocket/jBundler_ifServer.ts +57 -0
  234. package/src/jk_what/index.js +1 -0
  235. package/src/jk_what/index.ts +1 -0
  236. package/src/jk_what/jBundler_ifBrowser.ts +5 -0
  237. package/src/jk_what/jBundler_ifServer.ts +5 -0
@@ -0,0 +1,248 @@
1
+ // noinspection JSUnusedGlobalSymbols
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __assign = (this && this.__assign) || function () {
18
+ __assign = Object.assign || function(t) {
19
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
20
+ s = arguments[i];
21
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
22
+ t[p] = s[p];
23
+ }
24
+ return t;
25
+ };
26
+ return __assign.apply(this, arguments);
27
+ };
28
+ import { generateUUIDv4 } from "jopi-toolkit/jk_tools";
29
+ //region Validation
30
+ /**
31
+ * Throwing this error allows it to be caught
32
+ * when validating an object.
33
+ */
34
+ var SchemaError = /** @class */ (function (_super) {
35
+ __extends(SchemaError, _super);
36
+ function SchemaError(errorMessage, errorCode) {
37
+ var _this = _super.call(this, "") || this;
38
+ _this.errorMessage = errorMessage;
39
+ _this.errorCode = errorCode;
40
+ return _this;
41
+ }
42
+ return SchemaError;
43
+ }(Error));
44
+ /**
45
+ * Declare an error when validating a schema.
46
+ * Must be called when validating or normalizing.
47
+ */
48
+ export function declareError(message, errorCode) {
49
+ throw new SchemaError(message, errorCode);
50
+ }
51
+ var byTypeValidator = {
52
+ "string": function (v, f) {
53
+ if (typeof v !== "string") {
54
+ declareError(f.errorMessage_theValueIsInvalid || "Value must be a string", "INVALID_TYPE");
55
+ return;
56
+ }
57
+ var sf = f;
58
+ if ((sf.minLength !== undefined) && (v.length < sf.minLength)) {
59
+ declareError(sf.errorMessage_minLength || "Value must be at least ".concat(sf.minLength, " characters long"), "INVALID_LENGTH");
60
+ return;
61
+ }
62
+ if ((sf.maxLength !== undefined) && (v.length > sf.maxLength)) {
63
+ declareError(sf.errorMessage_maxLength || "Value must be less than ".concat(sf.maxLength, " characters long"), "INVALID_LENGTH");
64
+ return;
65
+ }
66
+ },
67
+ "number": function (v, f) {
68
+ if (typeof v !== "number") {
69
+ declareError(f.errorMessage_theValueIsInvalid || "Value must be a number", "INVALID_TYPE");
70
+ }
71
+ var sf = f;
72
+ if ((sf.minValue !== undefined) && (v < sf.minValue)) {
73
+ declareError(sf.errorMessage_minValue || "Value must be at least ".concat(sf.minValue), "INVALID_LENGTH");
74
+ return;
75
+ }
76
+ if ((sf.maxValue !== undefined) && (v > sf.maxValue)) {
77
+ declareError(sf.errorMessage_maxValue || "Value must be less than ".concat(sf.maxValue), "INVALID_LENGTH");
78
+ return;
79
+ }
80
+ },
81
+ "boolean": function (v, f) {
82
+ if (typeof v !== "boolean") {
83
+ declareError(f.errorMessage_theValueIsInvalid || "Value must be a boolean", "INVALID_TYPE");
84
+ }
85
+ var sf = f;
86
+ if (sf.requireTrue) {
87
+ if (v !== true) {
88
+ declareError(sf.errorMessage_requireTrue || "Value must be true", "INVALID_VALUE");
89
+ }
90
+ }
91
+ else if (sf.requireFalse) {
92
+ if (v !== false) {
93
+ declareError(sf.errorMessage_requireFalse || "Value must be false", "INVALID_VALUE");
94
+ }
95
+ }
96
+ }
97
+ };
98
+ export function validateSchema(data, schema) {
99
+ if (schema.schemaMeta.normalize) {
100
+ try {
101
+ schema.schemaMeta.normalize(data);
102
+ }
103
+ catch (e) {
104
+ if (e instanceof SchemaError) {
105
+ return {
106
+ globalError: e.errorMessage || "Schema validation failed",
107
+ globalErrorCode: e.errorCode || "SCHEMA_VALIDATION_FAILED"
108
+ };
109
+ }
110
+ else {
111
+ throw e;
112
+ }
113
+ }
114
+ }
115
+ var fieldErrors;
116
+ for (var fieldName in schema.desc) {
117
+ var defaultErrorMessage = void 0;
118
+ try {
119
+ var field = schema.desc[fieldName];
120
+ var value = data[fieldName];
121
+ if (field.normalize) {
122
+ defaultErrorMessage = field.errorMessage_theValueIsInvalid;
123
+ field.normalize(value, data);
124
+ }
125
+ if (!field.optional) {
126
+ if (value === undefined) {
127
+ if (field.errorMessage_isRequired) {
128
+ declareError(field.errorMessage_isRequired, "VALUE_REQUIRED");
129
+ }
130
+ else if (field.errorMessage_theValueIsInvalid) {
131
+ declareError(field.errorMessage_theValueIsInvalid, "VALUE_REQUIRED");
132
+ }
133
+ else {
134
+ declareError("Field ".concat(fieldName, " is required"), "VALUE_REQUIRED");
135
+ }
136
+ }
137
+ }
138
+ var typeValidator = byTypeValidator[field.type];
139
+ if (typeValidator) {
140
+ typeValidator(value, field);
141
+ }
142
+ if (field.validator) {
143
+ defaultErrorMessage = field.errorMessage_theValueIsInvalid;
144
+ field.validator(value, data);
145
+ }
146
+ }
147
+ catch (e) {
148
+ if (e instanceof SchemaError) {
149
+ if (!fieldErrors)
150
+ fieldErrors = {};
151
+ fieldErrors[fieldName] = {
152
+ fieldName: fieldName,
153
+ message: e.errorMessage || defaultErrorMessage || "Field ".concat(fieldName, " is invalid"),
154
+ code: e.errorCode || "FIELD_VALIDATION_FAILED"
155
+ };
156
+ }
157
+ else {
158
+ throw e;
159
+ }
160
+ }
161
+ }
162
+ if (schema.schemaMeta.validate) {
163
+ try {
164
+ schema.schemaMeta.validate(data);
165
+ }
166
+ catch (e) {
167
+ if (e instanceof SchemaError) {
168
+ return {
169
+ globalError: e.errorMessage || "Schema validation failed",
170
+ globalErrorCode: e.errorCode || "SCHEMA_VALIDATION_FAILED",
171
+ fields: fieldErrors
172
+ };
173
+ }
174
+ else {
175
+ throw e;
176
+ }
177
+ }
178
+ }
179
+ if (!fieldErrors)
180
+ return undefined;
181
+ return { fields: fieldErrors };
182
+ }
183
+ export function registerSchema(schemaId, schema, meta) {
184
+ if (!schemaId) {
185
+ throw new Error("jk_schemas - Schema id required. If you need an uid you can use: " + generateUUIDv4());
186
+ }
187
+ gRegistry[schemaId] = { schema: schema, meta: meta };
188
+ }
189
+ export function getSchemaMeta(schemaId) {
190
+ var entry = gRegistry[schemaId];
191
+ if (entry)
192
+ return entry.schema;
193
+ return undefined;
194
+ }
195
+ export function getSchema(schemaId) {
196
+ var entry = gRegistry[schemaId];
197
+ if (entry)
198
+ return entry.schema;
199
+ return undefined;
200
+ }
201
+ export function requireSchema(schemaId) {
202
+ var s = getSchema(schemaId);
203
+ if (!s) {
204
+ throw new Error("jk_schemas - Schema ".concat(schemaId, " not found"));
205
+ }
206
+ return s;
207
+ }
208
+ var gRegistry = {};
209
+ //endregion
210
+ //region Schema
211
+ export function schema(descriptor, meta) {
212
+ return { desc: descriptor, schemaMeta: meta || {} };
213
+ }
214
+ export function toJson(schema) {
215
+ return schema;
216
+ }
217
+ export function string(title, optional, infos) {
218
+ if (!optional) {
219
+ if (!infos)
220
+ infos = {};
221
+ if (infos.minLength === undefined)
222
+ infos.minLength = 1;
223
+ }
224
+ return __assign(__assign({}, infos), { title: title, optional: optional, type: "string" });
225
+ }
226
+ export function boolean(title, optional, infos) {
227
+ return __assign(__assign({}, infos), { title: title, optional: optional, type: "boolean" });
228
+ }
229
+ export function number(title, optional, infos) {
230
+ return __assign(__assign({}, infos), { title: title, optional: optional, type: "number" });
231
+ }
232
+ export function file(title, optional, infos) {
233
+ return __assign(__assign({}, infos), { title: title, optional: optional, type: "file" });
234
+ }
235
+ //endregion
236
+ //endregion
237
+ /*const MAKE_OPTIONAL = true;
238
+ //
239
+ const UserSchema1 = schema({
240
+ testOptional: string("testOptional", true),
241
+ testString: string("testString", MAKE_OPTIONAL),
242
+ testBool: boolean("testBool", MAKE_OPTIONAL),
243
+ testNumber: number("testNumber", MAKE_OPTIONAL),
244
+ testFile: file("testFile", MAKE_OPTIONAL)
245
+ })
246
+
247
+ type UserDataType1 = SchemaToType<typeof UserSchema1>;
248
+ let ud1: UserDataType1 = {};*/
@@ -0,0 +1,416 @@
1
+ // noinspection JSUnusedGlobalSymbols
2
+
3
+ import {generateUUIDv4} from "jopi-toolkit/jk_tools";
4
+
5
+ //region Validation
6
+
7
+ /**
8
+ * Throwing this error allows it to be caught
9
+ * when validating an object.
10
+ */
11
+ class SchemaError extends Error {
12
+ constructor(public readonly errorMessage?: string, public readonly errorCode?: string) {
13
+ super("");
14
+ }
15
+ }
16
+
17
+ /**
18
+ * Declare an error when validating a schema.
19
+ * Must be called when validating or normalizing.
20
+ */
21
+ export function declareError(message?: string, errorCode?: string) {
22
+ throw new SchemaError(message, errorCode);
23
+ }
24
+
25
+ export interface FieldError {
26
+ fieldName: string;
27
+ message: string;
28
+ code?: string;
29
+ }
30
+
31
+ export interface ValidationErrors {
32
+ /**
33
+ * An error about the whole schema.
34
+ */
35
+ globalError?: string;
36
+ globalErrorCode?: string;
37
+
38
+ /**
39
+ * An error per field.
40
+ */
41
+ fields?: Record<string, FieldError>;
42
+ }
43
+
44
+ const byTypeValidator: Record<string, (v: any, fieldInfos: SchemaFieldInfos) => void> = {
45
+ "string": (v, f) => {
46
+ if (typeof v !== "string") {
47
+ declareError(f.errorMessage_theValueIsInvalid || `Value must be a string`, "INVALID_TYPE");
48
+ return;
49
+ }
50
+
51
+ let sf = f as ScString<any>;
52
+
53
+ if ((sf.minLength!==undefined) && (v.length < sf.minLength)) {
54
+ declareError(sf.errorMessage_minLength || `Value must be at least ${sf.minLength} characters long`, "INVALID_LENGTH");
55
+ return;
56
+ }
57
+
58
+ if ((sf.maxLength!==undefined) && (v.length > sf.maxLength)) {
59
+ declareError(sf.errorMessage_maxLength || `Value must be less than ${sf.maxLength} characters long`, "INVALID_LENGTH");
60
+ return;
61
+ }
62
+ },
63
+
64
+ "number": (v, f) => {
65
+ if (typeof v !== "number") {
66
+ declareError(f.errorMessage_theValueIsInvalid || `Value must be a number`, "INVALID_TYPE");
67
+ }
68
+
69
+ let sf = f as ScNumber<any>;
70
+
71
+ if ((sf.minValue!==undefined) && (v < sf.minValue)) {
72
+ declareError(sf.errorMessage_minValue || `Value must be at least ${sf.minValue}`, "INVALID_LENGTH");
73
+ return;
74
+ }
75
+
76
+ if ((sf.maxValue!==undefined) && (v > sf.maxValue)) {
77
+ declareError(sf.errorMessage_maxValue || `Value must be less than ${sf.maxValue}`, "INVALID_LENGTH");
78
+ return;
79
+ }
80
+ },
81
+
82
+ "boolean": (v, f) => {
83
+ if (typeof v !== "boolean") {
84
+ declareError(f.errorMessage_theValueIsInvalid || `Value must be a boolean`, "INVALID_TYPE");
85
+ }
86
+
87
+ let sf = f as ScBoolean<any>;
88
+
89
+ if (sf.requireTrue) {
90
+ if (v!==true) {
91
+ declareError(sf.errorMessage_requireTrue || `Value must be true`, "INVALID_VALUE");
92
+ }
93
+ } else if (sf.requireFalse) {
94
+ if (v!==false) {
95
+ declareError(sf.errorMessage_requireFalse || `Value must be false`, "INVALID_VALUE");
96
+ }
97
+ }
98
+ }
99
+ }
100
+
101
+ export function validateSchema(data: any, schema: Schema): ValidationErrors|undefined {
102
+ if (schema.schemaMeta.normalize) {
103
+ try {
104
+ schema.schemaMeta.normalize(data);
105
+ }
106
+ catch (e: any) {
107
+ if (e instanceof SchemaError) {
108
+ return {
109
+ globalError: e.errorMessage || `Schema validation failed`,
110
+ globalErrorCode: e.errorCode || "SCHEMA_VALIDATION_FAILED"
111
+ };
112
+ }
113
+ else {
114
+ throw e;
115
+ }
116
+ }
117
+ }
118
+
119
+ let fieldErrors: Record<string, FieldError>|undefined;
120
+
121
+ for (let fieldName in schema.desc) {
122
+ let defaultErrorMessage: string|undefined;
123
+
124
+ try {
125
+ const field = schema.desc[fieldName];
126
+ const value = data[fieldName];
127
+
128
+ if (field.normalize) {
129
+ defaultErrorMessage = field.errorMessage_theValueIsInvalid;
130
+ field.normalize(value, data);
131
+ }
132
+
133
+ if (!field.optional) {
134
+ if (value === undefined) {
135
+ if (field.errorMessage_isRequired) {
136
+ declareError(field.errorMessage_isRequired, "VALUE_REQUIRED");
137
+ } else if (field.errorMessage_theValueIsInvalid) {
138
+ declareError(field.errorMessage_theValueIsInvalid, "VALUE_REQUIRED");
139
+ } else {
140
+ declareError(`Field ${fieldName} is required`, "VALUE_REQUIRED");
141
+ }
142
+ }
143
+ }
144
+
145
+ let typeValidator = byTypeValidator[field.type];
146
+
147
+ if (typeValidator) {
148
+ typeValidator(value, field);
149
+ }
150
+
151
+ if (field.validator) {
152
+ defaultErrorMessage = field.errorMessage_theValueIsInvalid;
153
+ field.validator(value, data);
154
+ }
155
+ }
156
+ catch (e: any) {
157
+ if (e instanceof SchemaError) {
158
+ if (!fieldErrors) fieldErrors = {};
159
+
160
+ fieldErrors[fieldName] = {
161
+ fieldName,
162
+ message: e.errorMessage || defaultErrorMessage || `Field ${fieldName} is invalid`,
163
+ code: e.errorCode || "FIELD_VALIDATION_FAILED"
164
+ };
165
+ } else {
166
+ throw e;
167
+ }
168
+ }
169
+ }
170
+
171
+ if (schema.schemaMeta.validate) {
172
+ try {
173
+ schema.schemaMeta.validate(data);
174
+ }
175
+ catch (e: any) {
176
+ if (e instanceof SchemaError) {
177
+ return {
178
+ globalError: e.errorMessage || `Schema validation failed`,
179
+ globalErrorCode: e.errorCode || "SCHEMA_VALIDATION_FAILED",
180
+ fields: fieldErrors
181
+ };
182
+ }
183
+ else {
184
+ throw e;
185
+ }
186
+ }
187
+ }
188
+
189
+ if (!fieldErrors) return undefined;
190
+ return {fields: fieldErrors};
191
+ }
192
+
193
+ //endregion
194
+
195
+ //region Registry
196
+
197
+ interface RegistryEntry {
198
+ schema: Schema;
199
+ meta?: any;
200
+ }
201
+
202
+ export function registerSchema(schemaId: string|undefined, schema: Schema, meta?: any) {
203
+ if (!schemaId) {
204
+ throw new Error("jk_schemas - Schema id required. If you need an uid you can use: " + generateUUIDv4());
205
+ }
206
+
207
+ gRegistry[schemaId!] = {schema, meta};
208
+ }
209
+
210
+ export function getSchemaMeta(schemaId: string): Schema|undefined {
211
+ const entry = gRegistry[schemaId];
212
+ if (entry) return entry.schema;
213
+ return undefined;
214
+ }
215
+
216
+ export function getSchema(schemaId: string): Schema|undefined {
217
+ const entry = gRegistry[schemaId];
218
+ if (entry) return entry.schema;
219
+ return undefined;
220
+ }
221
+
222
+ export function requireSchema(schemaId: string): Schema {
223
+ const s = getSchema(schemaId);
224
+
225
+ if (!s) {
226
+ throw new Error(`jk_schemas - Schema ${schemaId} not found`);
227
+ }
228
+
229
+ return s;
230
+ }
231
+
232
+ const gRegistry: Record<string, RegistryEntry> = {};
233
+
234
+ //endregion
235
+
236
+ //region Schema
237
+
238
+ export function schema<T extends SchemaDescriptor>(descriptor: T, meta?: SchemaMeta): Schema & { desc: T } {
239
+ return { desc: descriptor, schemaMeta: meta || {} };
240
+ }
241
+
242
+ export interface SchemaDescriptor {
243
+ [field: string]: ScField<any, any>;
244
+ }
245
+
246
+ export interface SchemaMeta {
247
+ title?: string;
248
+ description?: string;
249
+ [key: string]: any;
250
+
251
+ normalize?: (allValues: any) => void;
252
+ validate?: (allValues: any) => void;
253
+ }
254
+
255
+ export interface SchemaInfo {
256
+ desc: SchemaDescriptor,
257
+ schemaMeta: SchemaMeta
258
+ }
259
+
260
+ export interface Schema extends SchemaInfo {
261
+ }
262
+
263
+ export function toJson(schema: Schema): SchemaInfo {
264
+ return schema;
265
+ }
266
+
267
+ /**
268
+ * Allow getting a valid TypeScript type for our schema.
269
+ *
270
+ * **Example**
271
+ * ```
272
+ * const UserSchema = { name: string("The name", false), test: string("Test", true) };
273
+ * type UserDataType = SchemaToType<typeof UserSchema>;
274
+ * let ud: UserDataType = {name:"ok", test: "5"};
275
+ * ```
276
+ */
277
+ export type SchemaToType<S extends Schema> =
278
+ // 1. On accède au descripteur de schéma S['desc']
279
+ // 2. On itère sur ses clés K
280
+ // 3. On filtre les champs obligatoires (Opt = false)
281
+ { [K in keyof S['desc'] as S['desc'][K] extends ScField<any, false> ? K : never]:
282
+ // 4. On infère le type T du champ
283
+ S['desc'][K] extends ScField<infer T, any> ? T : never }
284
+
285
+ // 5. On fusionne avec les champs optionnels (Opt = true)
286
+ & { [K in keyof S['desc'] as S['desc'][K] extends ScField<any, true> ? K : never] ?:
287
+ S['desc'][K] extends ScField<infer T, any> ? T : never };
288
+
289
+ export interface ScField<T, Opt extends boolean> {
290
+ title: string;
291
+ type: string;
292
+
293
+ description?: string;
294
+ default?: T;
295
+ optional?: Opt;
296
+
297
+ errorMessage_isRequired?: string;
298
+ errorMessage_theDataTypeIsInvalid?: string;
299
+ errorMessage_theValueIsInvalid?: string;
300
+
301
+ normalize?: (value: T, allValues: any) => void;
302
+ validator?: (value: T, allValues: any) => void;
303
+
304
+ metas?: Record<string, string>;
305
+ }
306
+
307
+ export type SchemaFieldInfos = ScField<any, any>;
308
+
309
+ type OnlyInfos<T> = Omit<Omit<Omit<T, "title">, "optional">, "type">;
310
+
311
+ //endregion
312
+
313
+ //region Common types
314
+
315
+ //region String
316
+
317
+ export interface ScString<Opt extends boolean> extends ScField<string, Opt> {
318
+ minLength?: number;
319
+ errorMessage_minLength?: string;
320
+
321
+ maxLength?: number;
322
+ errorMessage_maxLength?: string;
323
+
324
+ placeholder?: string;
325
+ }
326
+
327
+ export function string<Opt extends boolean>(title: string, optional: Opt, infos?: OnlyInfos<ScString<Opt>>): ScString<Opt> {
328
+ if (!optional) {
329
+ if (!infos) infos = {};
330
+ if (infos.minLength===undefined) infos.minLength = 1;
331
+ }
332
+
333
+ return {...infos, title, optional, type: "string"};
334
+ }
335
+
336
+ //endregion
337
+
338
+ //region Boolean
339
+
340
+ export interface ScBoolean<Opt extends boolean> extends ScField<boolean, Opt> {
341
+ requireTrue?: boolean;
342
+ errorMessage_requireTrue?: string;
343
+
344
+ requireFalse?: boolean;
345
+ errorMessage_requireFalse?: string;
346
+ }
347
+
348
+ export function boolean<Opt extends boolean>(title: string, optional: Opt, infos?: OnlyInfos<ScBoolean<Opt>>): ScBoolean<Opt> {
349
+ return {...infos, title, optional, type: "boolean"};
350
+ }
351
+
352
+ //endregion
353
+
354
+ //region Number
355
+
356
+ export interface ScNumber<Opt extends boolean> extends ScField<number, Opt> {
357
+ minValue?: number;
358
+ errorMessage_minValue?: string;
359
+
360
+ maxValue?: number;
361
+ errorMessage_maxValue?: string;
362
+
363
+ // TODO: allowDecimal
364
+ allowDecimal?: boolean;
365
+ roundMethod?: "round" | "floor" | "ceil";
366
+ errorMessage_dontAllowDecimal?: string;
367
+
368
+ incrStep?: number;
369
+ placeholder?: string;
370
+ }
371
+
372
+ export function number<Opt extends boolean>(title: string, optional: Opt, infos?: OnlyInfos<ScNumber<Opt>>): ScNumber<Opt> {
373
+ return {...infos, title, optional, type: "number"};
374
+ }
375
+
376
+ //endregion
377
+
378
+ //region File
379
+
380
+ export interface File extends Blob {
381
+ readonly lastModified: number;
382
+ readonly name: string;
383
+ readonly webkitRelativePath: string;
384
+ }
385
+
386
+ export interface ScFile<Opt extends boolean> extends ScField<File[], Opt> {
387
+ maxFileCount?: number;
388
+ errorMessage_maxFileCount?: string;
389
+
390
+ acceptFileType?: string;
391
+ errorMessage_invalidFileType?: string;
392
+
393
+ maxFileSize?: number;
394
+ errorMessage_maxFileSize?: string;
395
+ }
396
+
397
+ export function file<Opt extends boolean>(title: string, optional: Opt, infos?: OnlyInfos<ScFile<Opt>>): ScFile<Opt> {
398
+ return {...infos, title, optional, type: "file"};
399
+ }
400
+
401
+ //endregion
402
+
403
+ //endregion
404
+
405
+ /*const MAKE_OPTIONAL = true;
406
+ //
407
+ const UserSchema1 = schema({
408
+ testOptional: string("testOptional", true),
409
+ testString: string("testString", MAKE_OPTIONAL),
410
+ testBool: boolean("testBool", MAKE_OPTIONAL),
411
+ testNumber: number("testNumber", MAKE_OPTIONAL),
412
+ testFile: file("testFile", MAKE_OPTIONAL)
413
+ })
414
+
415
+ type UserDataType1 = SchemaToType<typeof UserSchema1>;
416
+ let ud1: UserDataType1 = {};*/
@@ -0,0 +1,6 @@
1
+ export function teeResponse(r: Response): Promise<[ReadableStream, Response]> {
2
+ const [b1, b2] = r.body!.tee();
3
+
4
+ // The old response body is consumed. So we must rebuild the response.
5
+ return Promise.resolve([b1, new Response(b2, {status: r.status, headers: r.headers})]);
6
+ }