@twin.org/core 0.0.2-next.9 → 0.0.2

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 (225) hide show
  1. package/README.md +1 -9
  2. package/dist/es/encoding/base32.js +75 -0
  3. package/dist/es/encoding/base32.js.map +1 -0
  4. package/dist/es/encoding/base58.js +124 -0
  5. package/dist/es/encoding/base58.js.map +1 -0
  6. package/dist/es/encoding/base64.js +231 -0
  7. package/dist/es/encoding/base64.js.map +1 -0
  8. package/dist/es/encoding/base64Url.js +42 -0
  9. package/dist/es/encoding/base64Url.js.map +1 -0
  10. package/dist/es/errors/alreadyExistsError.js +22 -0
  11. package/dist/es/errors/alreadyExistsError.js.map +1 -0
  12. package/dist/es/errors/baseError.js +257 -0
  13. package/dist/es/errors/baseError.js.map +1 -0
  14. package/dist/es/errors/conflictError.js +23 -0
  15. package/dist/es/errors/conflictError.js.map +1 -0
  16. package/dist/es/errors/generalError.js +21 -0
  17. package/dist/es/errors/generalError.js.map +1 -0
  18. package/dist/es/errors/guardError.js +27 -0
  19. package/dist/es/errors/guardError.js.map +1 -0
  20. package/dist/es/errors/notFoundError.js +22 -0
  21. package/dist/es/errors/notFoundError.js.map +1 -0
  22. package/dist/es/errors/notImplementedError.js +24 -0
  23. package/dist/es/errors/notImplementedError.js.map +1 -0
  24. package/dist/es/errors/notSupportedError.js +21 -0
  25. package/dist/es/errors/notSupportedError.js.map +1 -0
  26. package/dist/es/errors/unauthorizedError.js +21 -0
  27. package/dist/es/errors/unauthorizedError.js.map +1 -0
  28. package/dist/es/errors/unprocessableError.js +21 -0
  29. package/dist/es/errors/unprocessableError.js.map +1 -0
  30. package/dist/es/errors/validationError.js +23 -0
  31. package/dist/es/errors/validationError.js.map +1 -0
  32. package/dist/es/factories/componentFactory.js +9 -0
  33. package/dist/es/factories/componentFactory.js.map +1 -0
  34. package/dist/es/factories/factory.js +297 -0
  35. package/dist/es/factories/factory.js.map +1 -0
  36. package/dist/es/helpers/arrayHelper.js +46 -0
  37. package/dist/es/helpers/arrayHelper.js.map +1 -0
  38. package/dist/es/helpers/envHelper.js +39 -0
  39. package/dist/es/helpers/envHelper.js.map +1 -0
  40. package/dist/es/helpers/errorHelper.js +100 -0
  41. package/dist/es/helpers/errorHelper.js.map +1 -0
  42. package/dist/es/helpers/filenameHelper.js +32 -0
  43. package/dist/es/helpers/filenameHelper.js.map +1 -0
  44. package/dist/es/helpers/hexHelper.js +45 -0
  45. package/dist/es/helpers/hexHelper.js.map +1 -0
  46. package/dist/es/helpers/jsonHelper.js +163 -0
  47. package/dist/es/helpers/jsonHelper.js.map +1 -0
  48. package/dist/es/helpers/numberHelper.js +30 -0
  49. package/dist/es/helpers/numberHelper.js.map +1 -0
  50. package/dist/es/helpers/objectHelper.js +309 -0
  51. package/dist/es/helpers/objectHelper.js.map +1 -0
  52. package/dist/es/helpers/randomHelper.js +66 -0
  53. package/dist/es/helpers/randomHelper.js.map +1 -0
  54. package/dist/es/helpers/stringHelper.js +252 -0
  55. package/dist/es/helpers/stringHelper.js.map +1 -0
  56. package/dist/es/helpers/uint8ArrayHelper.js +26 -0
  57. package/dist/es/helpers/uint8ArrayHelper.js.map +1 -0
  58. package/dist/es/index.js +60 -0
  59. package/dist/es/index.js.map +1 -0
  60. package/dist/es/models/IComponent.js +2 -0
  61. package/dist/es/models/IComponent.js.map +1 -0
  62. package/dist/es/models/IError.js +4 -0
  63. package/dist/es/models/IError.js.map +1 -0
  64. package/dist/es/models/IHealth.js +2 -0
  65. package/dist/es/models/IHealth.js.map +1 -0
  66. package/dist/es/models/II18nShared.js +2 -0
  67. package/dist/es/models/II18nShared.js.map +1 -0
  68. package/dist/es/models/IKeyValue.js +2 -0
  69. package/dist/es/models/IKeyValue.js.map +1 -0
  70. package/dist/es/models/ILabelledValue.js +2 -0
  71. package/dist/es/models/ILabelledValue.js.map +1 -0
  72. package/dist/es/models/ILocale.js +2 -0
  73. package/dist/es/models/ILocale.js.map +1 -0
  74. package/dist/es/models/ILocaleDictionary.js +4 -0
  75. package/dist/es/models/ILocaleDictionary.js.map +1 -0
  76. package/dist/es/models/ILocalesIndex.js +2 -0
  77. package/dist/es/models/ILocalesIndex.js.map +1 -0
  78. package/dist/es/models/IPatchOperation.js +4 -0
  79. package/dist/es/models/IPatchOperation.js.map +1 -0
  80. package/dist/es/models/IUrlParts.js +4 -0
  81. package/dist/es/models/IUrlParts.js.map +1 -0
  82. package/dist/es/models/IValidationFailure.js +2 -0
  83. package/dist/es/models/IValidationFailure.js.map +1 -0
  84. package/dist/es/models/coerceType.js +49 -0
  85. package/dist/es/models/coerceType.js.map +1 -0
  86. package/dist/es/models/compressionType.js +17 -0
  87. package/dist/es/models/compressionType.js.map +1 -0
  88. package/dist/es/models/healthStatus.js +21 -0
  89. package/dist/es/models/healthStatus.js.map +1 -0
  90. package/dist/es/types/bitString.js +98 -0
  91. package/dist/es/types/bitString.js.map +1 -0
  92. package/dist/es/types/objectOrArray.js +2 -0
  93. package/dist/es/types/objectOrArray.js.map +1 -0
  94. package/dist/es/types/singleOccurrenceArray.js +2 -0
  95. package/dist/es/types/singleOccurrenceArray.js.map +1 -0
  96. package/dist/es/types/url.js +144 -0
  97. package/dist/es/types/url.js.map +1 -0
  98. package/dist/es/types/urn.js +211 -0
  99. package/dist/es/types/urn.js.map +1 -0
  100. package/dist/es/utils/asyncCache.js +206 -0
  101. package/dist/es/utils/asyncCache.js.map +1 -0
  102. package/dist/es/utils/coerce.js +269 -0
  103. package/dist/es/utils/coerce.js.map +1 -0
  104. package/dist/es/utils/compression.js +49 -0
  105. package/dist/es/utils/compression.js.map +1 -0
  106. package/dist/es/utils/converter.js +256 -0
  107. package/dist/es/utils/converter.js.map +1 -0
  108. package/dist/es/utils/guards.js +385 -0
  109. package/dist/es/utils/guards.js.map +1 -0
  110. package/dist/es/utils/i18n.js +243 -0
  111. package/dist/es/utils/i18n.js.map +1 -0
  112. package/dist/es/utils/is.js +367 -0
  113. package/dist/es/utils/is.js.map +1 -0
  114. package/dist/es/utils/sharedStore.js +48 -0
  115. package/dist/es/utils/sharedStore.js.map +1 -0
  116. package/dist/es/utils/validation.js +774 -0
  117. package/dist/es/utils/validation.js.map +1 -0
  118. package/dist/types/encoding/base32.d.ts +5 -1
  119. package/dist/types/encoding/base58.d.ts +4 -0
  120. package/dist/types/encoding/base64.d.ts +4 -0
  121. package/dist/types/encoding/base64Url.d.ts +4 -0
  122. package/dist/types/errors/alreadyExistsError.d.ts +6 -3
  123. package/dist/types/errors/baseError.d.ts +2 -2
  124. package/dist/types/errors/conflictError.d.ts +6 -3
  125. package/dist/types/errors/generalError.d.ts +2 -2
  126. package/dist/types/errors/guardError.d.ts +2 -2
  127. package/dist/types/errors/notFoundError.d.ts +6 -3
  128. package/dist/types/errors/notImplementedError.d.ts +6 -2
  129. package/dist/types/errors/notSupportedError.d.ts +6 -3
  130. package/dist/types/errors/unauthorizedError.d.ts +7 -4
  131. package/dist/types/errors/unprocessableError.d.ts +2 -2
  132. package/dist/types/errors/validationError.d.ts +2 -2
  133. package/dist/types/factories/componentFactory.d.ts +2 -2
  134. package/dist/types/factories/factory.d.ts +27 -1
  135. package/dist/types/helpers/arrayHelper.d.ts +1 -8
  136. package/dist/types/helpers/errorHelper.d.ts +1 -1
  137. package/dist/types/helpers/jsonHelper.d.ts +5 -1
  138. package/dist/types/helpers/numberHelper.d.ts +17 -0
  139. package/dist/types/helpers/objectHelper.d.ts +24 -6
  140. package/dist/types/helpers/randomHelper.d.ts +16 -0
  141. package/dist/types/helpers/stringHelper.d.ts +12 -6
  142. package/dist/types/index.d.ts +57 -53
  143. package/dist/types/models/IComponent.d.ts +18 -7
  144. package/dist/types/models/IError.d.ts +1 -1
  145. package/dist/types/models/IHealth.d.ts +32 -0
  146. package/dist/types/models/ILocalesIndex.d.ts +1 -1
  147. package/dist/types/models/IValidationFailure.d.ts +0 -4
  148. package/dist/types/models/healthStatus.d.ts +21 -0
  149. package/dist/types/types/bitString.d.ts +4 -0
  150. package/dist/types/types/singleOccurrenceArray.d.ts +9 -0
  151. package/dist/types/types/url.d.ts +8 -3
  152. package/dist/types/types/urn.d.ts +7 -2
  153. package/dist/types/utils/asyncCache.d.ts +7 -0
  154. package/dist/types/utils/coerce.d.ts +1 -1
  155. package/dist/types/utils/compression.d.ts +5 -1
  156. package/dist/types/utils/guards.d.ts +11 -3
  157. package/dist/types/utils/i18n.d.ts +16 -1
  158. package/dist/types/utils/is.d.ts +8 -1
  159. package/dist/types/utils/validation.d.ts +1 -1
  160. package/docs/changelog.md +1224 -131
  161. package/docs/examples.md +308 -1
  162. package/docs/reference/classes/AlreadyExistsError.md +43 -39
  163. package/docs/reference/classes/ArrayHelper.md +10 -44
  164. package/docs/reference/classes/AsyncCache.md +12 -12
  165. package/docs/reference/classes/Base32.md +11 -3
  166. package/docs/reference/classes/Base58.md +10 -2
  167. package/docs/reference/classes/Base64.md +11 -3
  168. package/docs/reference/classes/Base64Url.md +10 -2
  169. package/docs/reference/classes/BaseError.md +37 -37
  170. package/docs/reference/classes/BitString.md +13 -5
  171. package/docs/reference/classes/Coerce.md +31 -31
  172. package/docs/reference/classes/Compression.md +10 -2
  173. package/docs/reference/classes/ConflictError.md +43 -39
  174. package/docs/reference/classes/Converter.md +18 -18
  175. package/docs/reference/classes/EnvHelper.md +1 -1
  176. package/docs/reference/classes/ErrorHelper.md +5 -5
  177. package/docs/reference/classes/Factory.md +122 -20
  178. package/docs/reference/classes/FilenameHelper.md +1 -1
  179. package/docs/reference/classes/GeneralError.md +38 -38
  180. package/docs/reference/classes/GuardError.md +38 -38
  181. package/docs/reference/classes/Guards.md +80 -34
  182. package/docs/reference/classes/HexHelper.md +6 -6
  183. package/docs/reference/classes/I18n.md +66 -14
  184. package/docs/reference/classes/Is.md +77 -43
  185. package/docs/reference/classes/JsonHelper.md +17 -9
  186. package/docs/reference/classes/NotFoundError.md +43 -39
  187. package/docs/reference/classes/NotImplementedError.md +48 -38
  188. package/docs/reference/classes/NotSupportedError.md +43 -39
  189. package/docs/reference/classes/NumberHelper.md +55 -0
  190. package/docs/reference/classes/ObjectHelper.md +163 -51
  191. package/docs/reference/classes/RandomHelper.md +53 -1
  192. package/docs/reference/classes/SharedStore.md +5 -5
  193. package/docs/reference/classes/StringHelper.md +52 -30
  194. package/docs/reference/classes/Uint8ArrayHelper.md +1 -1
  195. package/docs/reference/classes/UnauthorizedError.md +44 -40
  196. package/docs/reference/classes/UnprocessableError.md +38 -38
  197. package/docs/reference/classes/Url.md +24 -10
  198. package/docs/reference/classes/Urn.md +42 -28
  199. package/docs/reference/classes/Validation.md +27 -27
  200. package/docs/reference/classes/ValidationError.md +37 -37
  201. package/docs/reference/index.md +6 -0
  202. package/docs/reference/interfaces/IComponent.md +57 -27
  203. package/docs/reference/interfaces/IError.md +11 -11
  204. package/docs/reference/interfaces/IHealth.md +55 -0
  205. package/docs/reference/interfaces/II18nShared.md +4 -4
  206. package/docs/reference/interfaces/IKeyValue.md +2 -2
  207. package/docs/reference/interfaces/ILabelledValue.md +2 -2
  208. package/docs/reference/interfaces/ILocale.md +2 -2
  209. package/docs/reference/interfaces/ILocaleDictionary.md +1 -1
  210. package/docs/reference/interfaces/ILocalesIndex.md +1 -1
  211. package/docs/reference/interfaces/IPatchOperation.md +6 -6
  212. package/docs/reference/interfaces/IUrlParts.md +9 -9
  213. package/docs/reference/interfaces/IValidationFailure.md +4 -12
  214. package/docs/reference/type-aliases/HealthStatus.md +5 -0
  215. package/docs/reference/type-aliases/SingleOccurrenceArray.md +15 -0
  216. package/docs/reference/type-aliases/SingleOccurrenceArrayDepthHelper.md +19 -0
  217. package/docs/reference/variables/CoerceType.md +10 -10
  218. package/docs/reference/variables/CompressionType.md +2 -2
  219. package/docs/reference/variables/HealthStatus.md +25 -0
  220. package/locales/.validate-ignore +1 -0
  221. package/locales/en.json +9 -7
  222. package/package.json +24 -12
  223. package/dist/cjs/index.cjs +0 -5175
  224. package/dist/esm/index.mjs +0 -5133
  225. /package/dist/types/{models → types}/objectOrArray.d.ts +0 -0
@@ -0,0 +1,206 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { Is } from "./is.js";
4
+ import { SharedStore } from "./sharedStore.js";
5
+ /**
6
+ * Cache the results from asynchronous requests.
7
+ */
8
+ export class AsyncCache {
9
+ /**
10
+ * Execute an async request and cache the result.
11
+ * @param key The key for the entry in the cache.
12
+ * @param ttlMs The TTL of the entry in the cache.
13
+ * @param requestMethod The method to call if not cached.
14
+ * @param cacheFailures Cache failure results, defaults to false.
15
+ * @returns The response.
16
+ */
17
+ static exec(key, ttlMs, requestMethod, cacheFailures) {
18
+ const cacheEnabled = Is.integer(ttlMs) && ttlMs > 0;
19
+ if (!cacheEnabled) {
20
+ // No caching, just execute the request method
21
+ return requestMethod();
22
+ }
23
+ AsyncCache.cleanupExpired();
24
+ const cache = AsyncCache.getSharedCache();
25
+ const cachedEntry = cache[key];
26
+ // Do we have a cache entry for the key
27
+ if (cachedEntry) {
28
+ if (!Is.empty(cachedEntry.result)) {
29
+ // If the cache has already resulted in a value, resolve it
30
+ return Promise.resolve(cachedEntry.result);
31
+ }
32
+ else if (!Is.empty(cachedEntry.error)) {
33
+ // If the cache has already resulted in an error, reject it
34
+ return Promise.reject(cachedEntry.error);
35
+ }
36
+ // Otherwise create a promise to return and store the resolver
37
+ // and rejector in the cache entry, so that we can call then
38
+ // when the request is done
39
+ let storedResolve;
40
+ let storedReject;
41
+ const wait = new Promise((resolve, reject) => {
42
+ storedResolve = resolve;
43
+ storedReject = reject;
44
+ });
45
+ if (!Is.empty(storedResolve) && !Is.empty(storedReject)) {
46
+ cachedEntry.promiseQueue.push({
47
+ requestMethod,
48
+ resolve: storedResolve,
49
+ reject: storedReject
50
+ });
51
+ }
52
+ return wait;
53
+ }
54
+ // If we don't have a cache entry, create a new one
55
+ const cacheEntry = {
56
+ inProgress: true,
57
+ promiseQueue: [],
58
+ expires: Date.now() + ttlMs
59
+ };
60
+ cache[key] = cacheEntry;
61
+ // Return a promise that wraps the original request method
62
+ // so that we can store any results or errors in the cache
63
+ return new Promise((resolve, reject) => {
64
+ // Call the request method and store the result
65
+ requestMethod()
66
+ // eslint-disable-next-line promise/prefer-await-to-then
67
+ .then(res => {
68
+ // If the request was successful, store the result
69
+ cacheEntry.inProgress = false;
70
+ cacheEntry.result = res;
71
+ // and resolve both this promise and all the waiters
72
+ resolve(res);
73
+ for (const wait of cacheEntry.promiseQueue) {
74
+ wait.resolve(res);
75
+ }
76
+ cacheEntry.promiseQueue = [];
77
+ return res;
78
+ })
79
+ // eslint-disable-next-line promise/prefer-await-to-then
80
+ .catch((err) => {
81
+ // Reject the promise
82
+ reject(err);
83
+ cacheEntry.inProgress = false;
84
+ // Handle the waiters based on the cacheFailures flag
85
+ if (cacheFailures ?? false) {
86
+ // If we are caching failures, store the error and reject the waiters
87
+ cacheEntry.error = err;
88
+ for (const wait of cacheEntry.promiseQueue) {
89
+ wait.reject(err);
90
+ }
91
+ // Clear the waiters so we don't call them again
92
+ cacheEntry.promiseQueue = [];
93
+ }
94
+ else {
95
+ // If not caching failures for any queued requests we
96
+ // have no value to either resolve or reject, so we
97
+ // just resolve with the original request method
98
+ for (const wait of cacheEntry.promiseQueue) {
99
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
100
+ AsyncCache.resolveWaiter(wait.requestMethod, wait.resolve, wait.reject);
101
+ }
102
+ if (cache[key] === cacheEntry) {
103
+ delete cache[key];
104
+ }
105
+ }
106
+ });
107
+ });
108
+ }
109
+ /**
110
+ * Get an entry from the cache.
111
+ * @param key The key to get from the cache.
112
+ * @returns The item from the cache if it exists.
113
+ */
114
+ static async get(key) {
115
+ const cache = AsyncCache.getSharedCache();
116
+ if (!Is.empty(cache[key]?.result)) {
117
+ // If the cache has already resulted in a value, resolve it
118
+ return cache[key].result;
119
+ }
120
+ if (!Is.empty(cache[key]?.error)) {
121
+ // If the cache has already resulted in an error, reject it
122
+ throw cache[key].error;
123
+ }
124
+ }
125
+ /**
126
+ * Set an entry into the cache.
127
+ * @param key The key to set in the cache.
128
+ * @param value The value to set in the cache.
129
+ * @param ttlMs The TTL of the entry in the cache in ms, defaults to 1s.
130
+ * @returns Nothing.
131
+ */
132
+ static async set(key, value, ttlMs) {
133
+ const cache = AsyncCache.getSharedCache();
134
+ cache[key] = {
135
+ result: value,
136
+ promiseQueue: [],
137
+ expires: Date.now() + (ttlMs ?? 1000)
138
+ };
139
+ }
140
+ /**
141
+ * Remove an entry from the cache.
142
+ * @param key The key to remove from the cache.
143
+ */
144
+ static remove(key) {
145
+ const cache = AsyncCache.getSharedCache();
146
+ delete cache[key];
147
+ }
148
+ /**
149
+ * Clear the cache.
150
+ * @param prefix Optional prefix to clear only entries with that prefix.
151
+ */
152
+ static clearCache(prefix) {
153
+ const cache = AsyncCache.getSharedCache();
154
+ if (Is.stringValue(prefix)) {
155
+ for (const entry in cache) {
156
+ if (entry.startsWith(prefix)) {
157
+ delete cache[entry];
158
+ }
159
+ }
160
+ }
161
+ else {
162
+ SharedStore.set("asyncCache", {});
163
+ }
164
+ }
165
+ /**
166
+ * Perform a cleanup of the expired entries in the cache.
167
+ */
168
+ static cleanupExpired() {
169
+ const cache = AsyncCache.getSharedCache();
170
+ for (const entry in cache) {
171
+ if (cache[entry].expires > 0 &&
172
+ cache[entry].expires < Date.now() &&
173
+ cache[entry].inProgress !== true) {
174
+ delete cache[entry];
175
+ }
176
+ }
177
+ }
178
+ /**
179
+ * Get the shared cache.
180
+ * @returns The shared cache.
181
+ * @internal
182
+ */
183
+ static getSharedCache() {
184
+ let sharedCache = SharedStore.get("asyncCache");
185
+ if (Is.undefined(sharedCache)) {
186
+ sharedCache = {};
187
+ SharedStore.set("asyncCache", sharedCache);
188
+ }
189
+ return sharedCache;
190
+ }
191
+ /**
192
+ * Resolve a waiter by re-running its request method safely.
193
+ * @param requestMethod The method to execute.
194
+ * @param resolve The resolver for the waiter.
195
+ * @param reject The rejector for the waiter.
196
+ */
197
+ static async resolveWaiter(requestMethod, resolve, reject) {
198
+ try {
199
+ resolve(await requestMethod());
200
+ }
201
+ catch (waitErr) {
202
+ reject(waitErr);
203
+ }
204
+ }
205
+ }
206
+ //# sourceMappingURL=asyncCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asyncCache.js","sourceRoot":"","sources":["../../../src/utils/asyncCache.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Is } from \"./is.js\";\nimport { SharedStore } from \"./sharedStore.js\";\n\n/**\n * Cache the results from asynchronous requests.\n */\nexport class AsyncCache {\n\t/**\n\t * Execute an async request and cache the result.\n\t * @param key The key for the entry in the cache.\n\t * @param ttlMs The TTL of the entry in the cache.\n\t * @param requestMethod The method to call if not cached.\n\t * @param cacheFailures Cache failure results, defaults to false.\n\t * @returns The response.\n\t */\n\tpublic static exec<T = unknown>(\n\t\tkey: string,\n\t\tttlMs: number | undefined,\n\t\trequestMethod: () => Promise<T>,\n\t\tcacheFailures?: boolean\n\t): Promise<T> | undefined {\n\t\tconst cacheEnabled = Is.integer(ttlMs) && ttlMs > 0;\n\t\tif (!cacheEnabled) {\n\t\t\t// No caching, just execute the request method\n\t\t\treturn requestMethod();\n\t\t}\n\n\t\tAsyncCache.cleanupExpired();\n\n\t\tconst cache = AsyncCache.getSharedCache<T>();\n\t\tconst cachedEntry = cache[key];\n\n\t\t// Do we have a cache entry for the key\n\t\tif (cachedEntry) {\n\t\t\tif (!Is.empty(cachedEntry.result)) {\n\t\t\t\t// If the cache has already resulted in a value, resolve it\n\t\t\t\treturn Promise.resolve(cachedEntry.result);\n\t\t\t} else if (!Is.empty(cachedEntry.error)) {\n\t\t\t\t// If the cache has already resulted in an error, reject it\n\t\t\t\treturn Promise.reject(cachedEntry.error);\n\t\t\t}\n\n\t\t\t// Otherwise create a promise to return and store the resolver\n\t\t\t// and rejector in the cache entry, so that we can call then\n\t\t\t// when the request is done\n\n\t\t\tlet storedResolve: ((value: T | PromiseLike<T>) => void) | undefined;\n\t\t\tlet storedReject: ((reason?: unknown) => void) | undefined;\n\t\t\tconst wait = new Promise<T>((resolve, reject) => {\n\t\t\t\tstoredResolve = resolve;\n\t\t\t\tstoredReject = reject;\n\t\t\t});\n\t\t\tif (!Is.empty(storedResolve) && !Is.empty(storedReject)) {\n\t\t\t\tcachedEntry.promiseQueue.push({\n\t\t\t\t\trequestMethod,\n\t\t\t\t\tresolve: storedResolve,\n\t\t\t\t\treject: storedReject\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn wait;\n\t\t}\n\n\t\t// If we don't have a cache entry, create a new one\n\t\tconst cacheEntry: {\n\t\t\tresult?: T;\n\t\t\terror?: unknown;\n\t\t\tinProgress?: boolean;\n\t\t\tpromiseQueue: {\n\t\t\t\trequestMethod: () => Promise<T>;\n\t\t\t\tresolve: (value: T | PromiseLike<T>) => void;\n\t\t\t\treject: (reason?: unknown) => void;\n\t\t\t}[];\n\t\t\texpires: number;\n\t\t} = {\n\t\t\tinProgress: true,\n\t\t\tpromiseQueue: [],\n\t\t\texpires: Date.now() + ttlMs\n\t\t};\n\t\tcache[key] = cacheEntry;\n\n\t\t// Return a promise that wraps the original request method\n\t\t// so that we can store any results or errors in the cache\n\t\treturn new Promise((resolve, reject) => {\n\t\t\t// Call the request method and store the result\n\t\t\trequestMethod()\n\t\t\t\t// eslint-disable-next-line promise/prefer-await-to-then\n\t\t\t\t.then(res => {\n\t\t\t\t\t// If the request was successful, store the result\n\t\t\t\t\tcacheEntry.inProgress = false;\n\t\t\t\t\tcacheEntry.result = res;\n\n\t\t\t\t\t// and resolve both this promise and all the waiters\n\t\t\t\t\tresolve(res);\n\t\t\t\t\tfor (const wait of cacheEntry.promiseQueue) {\n\t\t\t\t\t\twait.resolve(res);\n\t\t\t\t\t}\n\t\t\t\t\tcacheEntry.promiseQueue = [];\n\t\t\t\t\treturn res;\n\t\t\t\t})\n\t\t\t\t// eslint-disable-next-line promise/prefer-await-to-then\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\t// Reject the promise\n\t\t\t\t\treject(err);\n\t\t\t\t\tcacheEntry.inProgress = false;\n\n\t\t\t\t\t// Handle the waiters based on the cacheFailures flag\n\t\t\t\t\tif (cacheFailures ?? false) {\n\t\t\t\t\t\t// If we are caching failures, store the error and reject the waiters\n\t\t\t\t\t\tcacheEntry.error = err;\n\t\t\t\t\t\tfor (const wait of cacheEntry.promiseQueue) {\n\t\t\t\t\t\t\twait.reject(err);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Clear the waiters so we don't call them again\n\t\t\t\t\t\tcacheEntry.promiseQueue = [];\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If not caching failures for any queued requests we\n\t\t\t\t\t\t// have no value to either resolve or reject, so we\n\t\t\t\t\t\t// just resolve with the original request method\n\t\t\t\t\t\tfor (const wait of cacheEntry.promiseQueue) {\n\t\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-floating-promises\n\t\t\t\t\t\t\tAsyncCache.resolveWaiter(wait.requestMethod, wait.resolve, wait.reject);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (cache[key] === cacheEntry) {\n\t\t\t\t\t\t\tdelete cache[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Get an entry from the cache.\n\t * @param key The key to get from the cache.\n\t * @returns The item from the cache if it exists.\n\t */\n\tpublic static async get<T = unknown>(key: string): Promise<T | undefined> {\n\t\tconst cache = AsyncCache.getSharedCache<T>();\n\t\tif (!Is.empty(cache[key]?.result)) {\n\t\t\t// If the cache has already resulted in a value, resolve it\n\t\t\treturn cache[key].result;\n\t\t}\n\n\t\tif (!Is.empty(cache[key]?.error)) {\n\t\t\t// If the cache has already resulted in an error, reject it\n\t\t\tthrow cache[key].error as Error;\n\t\t}\n\t}\n\n\t/**\n\t * Set an entry into the cache.\n\t * @param key The key to set in the cache.\n\t * @param value The value to set in the cache.\n\t * @param ttlMs The TTL of the entry in the cache in ms, defaults to 1s.\n\t * @returns Nothing.\n\t */\n\tpublic static async set<T = unknown>(key: string, value: T, ttlMs?: number): Promise<void> {\n\t\tconst cache = AsyncCache.getSharedCache();\n\t\tcache[key] = {\n\t\t\tresult: value,\n\t\t\tpromiseQueue: [],\n\t\t\texpires: Date.now() + (ttlMs ?? 1000)\n\t\t};\n\t}\n\n\t/**\n\t * Remove an entry from the cache.\n\t * @param key The key to remove from the cache.\n\t */\n\tpublic static remove(key: string): void {\n\t\tconst cache = AsyncCache.getSharedCache();\n\t\tdelete cache[key];\n\t}\n\n\t/**\n\t * Clear the cache.\n\t * @param prefix Optional prefix to clear only entries with that prefix.\n\t */\n\tpublic static clearCache(prefix?: string): void {\n\t\tconst cache = AsyncCache.getSharedCache();\n\t\tif (Is.stringValue(prefix)) {\n\t\t\tfor (const entry in cache) {\n\t\t\t\tif (entry.startsWith(prefix)) {\n\t\t\t\t\tdelete cache[entry];\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tSharedStore.set(\"asyncCache\", {});\n\t\t}\n\t}\n\n\t/**\n\t * Perform a cleanup of the expired entries in the cache.\n\t */\n\tpublic static cleanupExpired(): void {\n\t\tconst cache = AsyncCache.getSharedCache();\n\t\tfor (const entry in cache) {\n\t\t\tif (\n\t\t\t\tcache[entry].expires > 0 &&\n\t\t\t\tcache[entry].expires < Date.now() &&\n\t\t\t\tcache[entry].inProgress !== true\n\t\t\t) {\n\t\t\t\tdelete cache[entry];\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Get the shared cache.\n\t * @returns The shared cache.\n\t * @internal\n\t */\n\tprivate static getSharedCache<T = unknown>(): {\n\t\t[url: string]: {\n\t\t\tresult?: T;\n\t\t\terror?: unknown;\n\t\t\tinProgress?: boolean;\n\t\t\tpromiseQueue: {\n\t\t\t\trequestMethod: () => Promise<T>;\n\t\t\t\tresolve: (value: T | PromiseLike<T>) => void;\n\t\t\t\treject: (reason?: unknown) => void;\n\t\t\t}[];\n\t\t\texpires: number;\n\t\t};\n\t} {\n\t\tlet sharedCache = SharedStore.get<{\n\t\t\t[url: string]: {\n\t\t\t\tresult?: T;\n\t\t\t\terror?: unknown;\n\t\t\t\tinProgress?: boolean;\n\t\t\t\tpromiseQueue: {\n\t\t\t\t\trequestMethod: () => Promise<T>;\n\t\t\t\t\tresolve: (value: T | PromiseLike<T>) => void;\n\t\t\t\t\treject: (reason?: unknown) => void;\n\t\t\t\t}[];\n\t\t\t\texpires: number;\n\t\t\t};\n\t\t}>(\"asyncCache\");\n\n\t\tif (Is.undefined(sharedCache)) {\n\t\t\tsharedCache = {};\n\t\t\tSharedStore.set(\"asyncCache\", sharedCache);\n\t\t}\n\n\t\treturn sharedCache;\n\t}\n\n\t/**\n\t * Resolve a waiter by re-running its request method safely.\n\t * @param requestMethod The method to execute.\n\t * @param resolve The resolver for the waiter.\n\t * @param reject The rejector for the waiter.\n\t */\n\tprivate static async resolveWaiter<T>(\n\t\trequestMethod: () => Promise<T>,\n\t\tresolve: (value: T | PromiseLike<T>) => void,\n\t\treject: (reason?: unknown) => void\n\t): Promise<void> {\n\t\ttry {\n\t\t\tresolve(await requestMethod());\n\t\t} catch (waitErr) {\n\t\t\treject(waitErr);\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,269 @@
1
+ // Copyright 2024 IOTA Stiftung.
2
+ // SPDX-License-Identifier: Apache-2.0.
3
+ import { Converter } from "./converter.js";
4
+ import { Is } from "./is.js";
5
+ import { CoerceType } from "../models/coerceType.js";
6
+ /**
7
+ * Coerce an object from one type to another.
8
+ */
9
+ export class Coerce {
10
+ /**
11
+ * Coerce the value to a string.
12
+ * @param value The value to coerce.
13
+ * @throws TypeError If the value can not be coerced.
14
+ * @returns The value if it can be coerced.
15
+ */
16
+ static string(value) {
17
+ if (Is.undefined(value)) {
18
+ return value;
19
+ }
20
+ if (Is.string(value)) {
21
+ return value;
22
+ }
23
+ if (Is.number(value)) {
24
+ return value.toString();
25
+ }
26
+ if (Is.boolean(value)) {
27
+ return value ? "true" : "false";
28
+ }
29
+ if (Is.date(value)) {
30
+ return value.toISOString();
31
+ }
32
+ }
33
+ /**
34
+ * Coerce the value to a number.
35
+ * @param value The value to coerce.
36
+ * @throws TypeError If the value can not be coerced.
37
+ * @returns The value if it can be coerced.
38
+ */
39
+ static number(value) {
40
+ if (Is.undefined(value)) {
41
+ return value;
42
+ }
43
+ if (Is.number(value)) {
44
+ return value;
45
+ }
46
+ if (Is.string(value)) {
47
+ const parsed = Number.parseFloat(value);
48
+ if (Is.number(parsed)) {
49
+ return parsed;
50
+ }
51
+ }
52
+ if (Is.boolean(value)) {
53
+ return value ? 1 : 0;
54
+ }
55
+ if (Is.date(value)) {
56
+ return value.getTime();
57
+ }
58
+ }
59
+ /**
60
+ * Coerce the value to an integer.
61
+ * @param value The value to coerce.
62
+ * @throws TypeError If the value can not be coerced.
63
+ * @returns The value if it can be coerced.
64
+ */
65
+ static integer(value) {
66
+ const num = Coerce.number(value);
67
+ if (!Is.undefined(num)) {
68
+ return Math.trunc(num);
69
+ }
70
+ }
71
+ /**
72
+ * Coerce the value to a bigint.
73
+ * @param value The value to coerce.
74
+ * @throws TypeError If the value can not be coerced.
75
+ * @returns The value if it can be coerced.
76
+ */
77
+ static bigint(value) {
78
+ if (Is.undefined(value)) {
79
+ return value;
80
+ }
81
+ if (Is.bigint(value)) {
82
+ return value;
83
+ }
84
+ if (Is.number(value)) {
85
+ return BigInt(value);
86
+ }
87
+ if (Is.string(value)) {
88
+ const parsed = Number.parseFloat(value);
89
+ if (Is.integer(parsed)) {
90
+ return BigInt(parsed);
91
+ }
92
+ }
93
+ if (Is.boolean(value)) {
94
+ return value ? 1n : 0n;
95
+ }
96
+ }
97
+ /**
98
+ * Coerce the value to a boolean.
99
+ * @param value The value to coerce.
100
+ * @throws TypeError If the value can not be coerced.
101
+ * @returns The value if it can be coerced.
102
+ */
103
+ static boolean(value) {
104
+ if (Is.undefined(value)) {
105
+ return value;
106
+ }
107
+ if (Is.boolean(value)) {
108
+ return value;
109
+ }
110
+ if (Is.number(value)) {
111
+ // eslint-disable-next-line no-unneeded-ternary
112
+ return value ? true : false;
113
+ }
114
+ if (Is.string(value)) {
115
+ if (/true/i.test(value)) {
116
+ return true;
117
+ }
118
+ if (/false/i.test(value)) {
119
+ return false;
120
+ }
121
+ }
122
+ }
123
+ /**
124
+ * Coerce the value to a date.
125
+ * @param value The value to coerce.
126
+ * @throws TypeError If the value can not be coerced.
127
+ * @returns The value if it can be coerced.
128
+ */
129
+ static date(value) {
130
+ if (Is.undefined(value)) {
131
+ return value;
132
+ }
133
+ if (Is.date(value)) {
134
+ return value;
135
+ }
136
+ if (Is.number(value)) {
137
+ return new Date(value);
138
+ }
139
+ if (Is.string(value)) {
140
+ const dt = new Date(value);
141
+ if (!Number.isNaN(dt.getTime())) {
142
+ const utc = Date.UTC(dt.getUTCFullYear(), dt.getUTCMonth(), dt.getUTCDate());
143
+ return new Date(utc);
144
+ }
145
+ }
146
+ }
147
+ /**
148
+ * Coerce the value to a date/time.
149
+ * @param value The value to coerce.
150
+ * @throws TypeError If the value can not be coerced.
151
+ * @returns The value if it can be coerced.
152
+ */
153
+ static dateTime(value) {
154
+ if (Is.undefined(value)) {
155
+ return value;
156
+ }
157
+ if (Is.date(value)) {
158
+ return value;
159
+ }
160
+ if (Is.number(value)) {
161
+ return new Date(value);
162
+ }
163
+ if (Is.string(value)) {
164
+ const dt = new Date(value);
165
+ if (!Number.isNaN(dt.getTime())) {
166
+ const utc = Date.UTC(dt.getUTCFullYear(), dt.getUTCMonth(), dt.getUTCDate(), dt.getUTCHours(), dt.getUTCMinutes(), dt.getUTCSeconds(), dt.getUTCMilliseconds());
167
+ return new Date(utc);
168
+ }
169
+ }
170
+ }
171
+ /**
172
+ * Coerce the value to a time.
173
+ * @param value The value to coerce.
174
+ * @throws TypeError If the value can not be coerced.
175
+ * @returns The value if it can be coerced.
176
+ */
177
+ static time(value) {
178
+ if (Is.undefined(value)) {
179
+ return value;
180
+ }
181
+ if (Is.date(value)) {
182
+ return value;
183
+ }
184
+ if (Is.number(value)) {
185
+ const dt = new Date(value);
186
+ dt.setFullYear(1970, 0, 1);
187
+ return dt;
188
+ }
189
+ if (Is.string(value)) {
190
+ const dt = new Date(value);
191
+ if (!Number.isNaN(dt.getTime())) {
192
+ const utc = Date.UTC(1970, 0, 1, dt.getUTCHours(), dt.getUTCMinutes(), dt.getUTCSeconds(), dt.getUTCMilliseconds());
193
+ return new Date(utc);
194
+ }
195
+ }
196
+ }
197
+ /**
198
+ * Coerce the value to an object.
199
+ * @param value The value to coerce.
200
+ * @throws TypeError If the value can not be coerced.
201
+ * @returns The value if it can be coerced.
202
+ */
203
+ static object(value) {
204
+ if (Is.undefined(value)) {
205
+ return value;
206
+ }
207
+ if (Is.object(value)) {
208
+ return value;
209
+ }
210
+ if (Is.stringValue(value)) {
211
+ try {
212
+ return JSON.parse(value);
213
+ }
214
+ catch { }
215
+ }
216
+ }
217
+ /**
218
+ * Coerce the value to a Uint8Array.
219
+ * @param value The value to coerce.
220
+ * @throws TypeError If the value can not be coerced.
221
+ * @returns The value if it can be coerced.
222
+ */
223
+ static uint8Array(value) {
224
+ if (Is.undefined(value)) {
225
+ return value;
226
+ }
227
+ if (Is.string(value)) {
228
+ if (Is.stringHex(value.toLowerCase(), true)) {
229
+ return Converter.hexToBytes(value.toLowerCase());
230
+ }
231
+ if (Is.stringBase64(value)) {
232
+ return Converter.base64ToBytes(value);
233
+ }
234
+ }
235
+ }
236
+ /**
237
+ * Coerces a value based on the coercion type.
238
+ * @param value The value to coerce.
239
+ * @param type The coercion type to perform.
240
+ * @returns The coerced value.
241
+ */
242
+ static byType(value, type) {
243
+ switch (type) {
244
+ case CoerceType.String:
245
+ return Coerce.string(value);
246
+ case CoerceType.Number:
247
+ return Coerce.number(value);
248
+ case CoerceType.Integer:
249
+ return Coerce.integer(value);
250
+ case CoerceType.BigInt:
251
+ return Coerce.bigint(value);
252
+ case CoerceType.Boolean:
253
+ return Coerce.boolean(value);
254
+ case CoerceType.Date:
255
+ return Coerce.date(value);
256
+ case CoerceType.DateTime:
257
+ return Coerce.dateTime(value);
258
+ case CoerceType.Time:
259
+ return Coerce.time(value);
260
+ case CoerceType.Object:
261
+ return Coerce.object(value);
262
+ case CoerceType.Uint8Array:
263
+ return Coerce.uint8Array(value);
264
+ default:
265
+ return value;
266
+ }
267
+ }
268
+ }
269
+ //# sourceMappingURL=coerce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coerce.js","sourceRoot":"","sources":["../../../src/utils/coerce.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Converter } from \"./converter.js\";\nimport { Is } from \"./is.js\";\nimport { CoerceType } from \"../models/coerceType.js\";\n\n/**\n * Coerce an object from one type to another.\n */\nexport class Coerce {\n\t/**\n\t * Coerce the value to a string.\n\t * @param value The value to coerce.\n\t * @throws TypeError If the value can not be coerced.\n\t * @returns The value if it can be coerced.\n\t */\n\tpublic static string(value: unknown): string | undefined {\n\t\tif (Is.undefined(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.string(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.number(value)) {\n\t\t\treturn value.toString();\n\t\t}\n\t\tif (Is.boolean(value)) {\n\t\t\treturn value ? \"true\" : \"false\";\n\t\t}\n\t\tif (Is.date(value)) {\n\t\t\treturn value.toISOString();\n\t\t}\n\t}\n\n\t/**\n\t * Coerce the value to a number.\n\t * @param value The value to coerce.\n\t * @throws TypeError If the value can not be coerced.\n\t * @returns The value if it can be coerced.\n\t */\n\tpublic static number(value: unknown): number | undefined {\n\t\tif (Is.undefined(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.number(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.string(value)) {\n\t\t\tconst parsed = Number.parseFloat(value);\n\t\t\tif (Is.number(parsed)) {\n\t\t\t\treturn parsed;\n\t\t\t}\n\t\t}\n\t\tif (Is.boolean(value)) {\n\t\t\treturn value ? 1 : 0;\n\t\t}\n\t\tif (Is.date(value)) {\n\t\t\treturn value.getTime();\n\t\t}\n\t}\n\n\t/**\n\t * Coerce the value to an integer.\n\t * @param value The value to coerce.\n\t * @throws TypeError If the value can not be coerced.\n\t * @returns The value if it can be coerced.\n\t */\n\tpublic static integer(value: unknown): number | undefined {\n\t\tconst num = Coerce.number(value);\n\t\tif (!Is.undefined(num)) {\n\t\t\treturn Math.trunc(num);\n\t\t}\n\t}\n\n\t/**\n\t * Coerce the value to a bigint.\n\t * @param value The value to coerce.\n\t * @throws TypeError If the value can not be coerced.\n\t * @returns The value if it can be coerced.\n\t */\n\tpublic static bigint(value: unknown): bigint | undefined {\n\t\tif (Is.undefined(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.bigint(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.number(value)) {\n\t\t\treturn BigInt(value);\n\t\t}\n\t\tif (Is.string(value)) {\n\t\t\tconst parsed = Number.parseFloat(value);\n\t\t\tif (Is.integer(parsed)) {\n\t\t\t\treturn BigInt(parsed);\n\t\t\t}\n\t\t}\n\t\tif (Is.boolean(value)) {\n\t\t\treturn value ? 1n : 0n;\n\t\t}\n\t}\n\n\t/**\n\t * Coerce the value to a boolean.\n\t * @param value The value to coerce.\n\t * @throws TypeError If the value can not be coerced.\n\t * @returns The value if it can be coerced.\n\t */\n\tpublic static boolean(value: unknown): boolean | undefined {\n\t\tif (Is.undefined(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.boolean(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.number(value)) {\n\t\t\t// eslint-disable-next-line no-unneeded-ternary\n\t\t\treturn value ? true : false;\n\t\t}\n\t\tif (Is.string(value)) {\n\t\t\tif (/true/i.test(value)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (/false/i.test(value)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Coerce the value to a date.\n\t * @param value The value to coerce.\n\t * @throws TypeError If the value can not be coerced.\n\t * @returns The value if it can be coerced.\n\t */\n\tpublic static date(value: unknown): Date | undefined {\n\t\tif (Is.undefined(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.date(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.number(value)) {\n\t\t\treturn new Date(value);\n\t\t}\n\t\tif (Is.string(value)) {\n\t\t\tconst dt = new Date(value);\n\t\t\tif (!Number.isNaN(dt.getTime())) {\n\t\t\t\tconst utc = Date.UTC(dt.getUTCFullYear(), dt.getUTCMonth(), dt.getUTCDate());\n\t\t\t\treturn new Date(utc);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Coerce the value to a date/time.\n\t * @param value The value to coerce.\n\t * @throws TypeError If the value can not be coerced.\n\t * @returns The value if it can be coerced.\n\t */\n\tpublic static dateTime(value: unknown): Date | undefined {\n\t\tif (Is.undefined(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.date(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.number(value)) {\n\t\t\treturn new Date(value);\n\t\t}\n\t\tif (Is.string(value)) {\n\t\t\tconst dt = new Date(value);\n\t\t\tif (!Number.isNaN(dt.getTime())) {\n\t\t\t\tconst utc = Date.UTC(\n\t\t\t\t\tdt.getUTCFullYear(),\n\t\t\t\t\tdt.getUTCMonth(),\n\t\t\t\t\tdt.getUTCDate(),\n\t\t\t\t\tdt.getUTCHours(),\n\t\t\t\t\tdt.getUTCMinutes(),\n\t\t\t\t\tdt.getUTCSeconds(),\n\t\t\t\t\tdt.getUTCMilliseconds()\n\t\t\t\t);\n\t\t\t\treturn new Date(utc);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Coerce the value to a time.\n\t * @param value The value to coerce.\n\t * @throws TypeError If the value can not be coerced.\n\t * @returns The value if it can be coerced.\n\t */\n\tpublic static time(value: unknown): Date | undefined {\n\t\tif (Is.undefined(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.date(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.number(value)) {\n\t\t\tconst dt = new Date(value);\n\t\t\tdt.setFullYear(1970, 0, 1);\n\t\t\treturn dt;\n\t\t}\n\t\tif (Is.string(value)) {\n\t\t\tconst dt = new Date(value);\n\t\t\tif (!Number.isNaN(dt.getTime())) {\n\t\t\t\tconst utc = Date.UTC(\n\t\t\t\t\t1970,\n\t\t\t\t\t0,\n\t\t\t\t\t1,\n\t\t\t\t\tdt.getUTCHours(),\n\t\t\t\t\tdt.getUTCMinutes(),\n\t\t\t\t\tdt.getUTCSeconds(),\n\t\t\t\t\tdt.getUTCMilliseconds()\n\t\t\t\t);\n\t\t\t\treturn new Date(utc);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Coerce the value to an object.\n\t * @param value The value to coerce.\n\t * @throws TypeError If the value can not be coerced.\n\t * @returns The value if it can be coerced.\n\t */\n\tpublic static object<T = unknown>(value: unknown): T | undefined {\n\t\tif (Is.undefined(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.object<T>(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.stringValue(value)) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(value) as T;\n\t\t\t} catch {}\n\t\t}\n\t}\n\n\t/**\n\t * Coerce the value to a Uint8Array.\n\t * @param value The value to coerce.\n\t * @throws TypeError If the value can not be coerced.\n\t * @returns The value if it can be coerced.\n\t */\n\tpublic static uint8Array(value: unknown): Uint8Array | undefined {\n\t\tif (Is.undefined(value)) {\n\t\t\treturn value;\n\t\t}\n\t\tif (Is.string(value)) {\n\t\t\tif (Is.stringHex(value.toLowerCase(), true)) {\n\t\t\t\treturn Converter.hexToBytes(value.toLowerCase());\n\t\t\t}\n\t\t\tif (Is.stringBase64(value)) {\n\t\t\t\treturn Converter.base64ToBytes(value);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Coerces a value based on the coercion type.\n\t * @param value The value to coerce.\n\t * @param type The coercion type to perform.\n\t * @returns The coerced value.\n\t */\n\tpublic static byType(value: unknown, type?: CoerceType): unknown {\n\t\tswitch (type) {\n\t\t\tcase CoerceType.String:\n\t\t\t\treturn Coerce.string(value);\n\t\t\tcase CoerceType.Number:\n\t\t\t\treturn Coerce.number(value);\n\t\t\tcase CoerceType.Integer:\n\t\t\t\treturn Coerce.integer(value);\n\t\t\tcase CoerceType.BigInt:\n\t\t\t\treturn Coerce.bigint(value);\n\t\t\tcase CoerceType.Boolean:\n\t\t\t\treturn Coerce.boolean(value);\n\t\t\tcase CoerceType.Date:\n\t\t\t\treturn Coerce.date(value);\n\t\t\tcase CoerceType.DateTime:\n\t\t\t\treturn Coerce.dateTime(value);\n\t\t\tcase CoerceType.Time:\n\t\t\t\treturn Coerce.time(value);\n\t\t\tcase CoerceType.Object:\n\t\t\t\treturn Coerce.object(value);\n\t\t\tcase CoerceType.Uint8Array:\n\t\t\t\treturn Coerce.uint8Array(value);\n\t\t\tdefault:\n\t\t\t\treturn value;\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,49 @@
1
+ import { Guards } from "./guards.js";
2
+ import { CompressionType } from "../models/compressionType.js";
3
+ /**
4
+ * A class to handle compression.
5
+ */
6
+ export class Compression {
7
+ /**
8
+ * Runtime name for the class.
9
+ */
10
+ static CLASS_NAME = "Compression";
11
+ /**
12
+ * Compress bytes using GZIP.
13
+ * @param bytes The bytes to compress.
14
+ * @param type The type of compression to use.
15
+ * @returns The compressed bytes.
16
+ */
17
+ static async compress(bytes, type) {
18
+ Guards.uint8Array(Compression.CLASS_NAME, "bytes", bytes);
19
+ Guards.arrayOneOf(Compression.CLASS_NAME, "type", type, Object.values(CompressionType));
20
+ const blob = new Blob([new Uint8Array(bytes)]);
21
+ const compressionStream = new CompressionStream(type);
22
+ const compressionPipe = blob.stream().pipeThrough(compressionStream);
23
+ const compressedBlob = await new Response(compressionPipe).blob();
24
+ const compressedBytes = new Uint8Array(await compressedBlob.arrayBuffer());
25
+ // GZIP header contains a byte which specifies the OS the
26
+ // compression was performed on. We set this to 3 (Unix) to ensure
27
+ // that we produce consistent results.
28
+ if (type === CompressionType.Gzip && compressedBytes.length >= 10) {
29
+ compressedBytes[9] = 3;
30
+ }
31
+ return compressedBytes;
32
+ }
33
+ /**
34
+ * Decompress a gzipped compressed byte array.
35
+ * @param compressedBytes The compressed bytes.
36
+ * @param type The type of compression to use.
37
+ * @returns The decompressed bytes.
38
+ */
39
+ static async decompress(compressedBytes, type) {
40
+ Guards.uint8Array(Compression.CLASS_NAME, "compressedBytes", compressedBytes);
41
+ Guards.arrayOneOf(Compression.CLASS_NAME, "type", type, Object.values(CompressionType));
42
+ const blob = new Blob([new Uint8Array(compressedBytes)]);
43
+ const decompressionStream = new DecompressionStream(type);
44
+ const decompressionPipe = blob.stream().pipeThrough(decompressionStream);
45
+ const decompressedBlob = await new Response(decompressionPipe).blob();
46
+ return new Uint8Array(await decompressedBlob.bytes());
47
+ }
48
+ }
49
+ //# sourceMappingURL=compression.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compression.js","sourceRoot":"","sources":["../../../src/utils/compression.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D;;GAEG;AACH,MAAM,OAAO,WAAW;IACvB;;OAEG;IACI,MAAM,CAAU,UAAU,iBAAiC;IAElE;;;;;OAKG;IACI,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAiB,EAAE,IAAqB;QACpE,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,WAAiB,KAAK,CAAC,CAAC;QAChE,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,UAAgB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QAE9F,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/C,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACtD,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QACrE,MAAM,cAAc,GAAG,MAAM,IAAI,QAAQ,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC;QAElE,MAAM,eAAe,GAAG,IAAI,UAAU,CAAC,MAAM,cAAc,CAAC,WAAW,EAAE,CAAC,CAAC;QAE3E,yDAAyD;QACzD,kEAAkE;QAClE,sCAAsC;QACtC,IAAI,IAAI,KAAK,eAAe,CAAC,IAAI,IAAI,eAAe,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;YACnE,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;QAED,OAAO,eAAe,CAAC;IACxB,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,KAAK,CAAC,UAAU,CAC7B,eAA2B,EAC3B,IAAqB;QAErB,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,qBAA2B,eAAe,CAAC,CAAC;QACpF,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC,UAAU,UAAgB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;QAE9F,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACzD,MAAM,mBAAmB,GAAG,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1D,MAAM,iBAAiB,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;QACzE,MAAM,gBAAgB,GAAG,MAAM,IAAI,QAAQ,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAC;QAEtE,OAAO,IAAI,UAAU,CAAC,MAAM,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC;IACvD,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { nameof } from \"@twin.org/nameof\";\nimport { Guards } from \"./guards.js\";\nimport { CompressionType } from \"../models/compressionType.js\";\n\n/**\n * A class to handle compression.\n */\nexport class Compression {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Compression>();\n\n\t/**\n\t * Compress bytes using GZIP.\n\t * @param bytes The bytes to compress.\n\t * @param type The type of compression to use.\n\t * @returns The compressed bytes.\n\t */\n\tpublic static async compress(bytes: Uint8Array, type: CompressionType): Promise<Uint8Array> {\n\t\tGuards.uint8Array(Compression.CLASS_NAME, nameof(bytes), bytes);\n\t\tGuards.arrayOneOf(Compression.CLASS_NAME, nameof(type), type, Object.values(CompressionType));\n\n\t\tconst blob = new Blob([new Uint8Array(bytes)]);\n\t\tconst compressionStream = new CompressionStream(type);\n\t\tconst compressionPipe = blob.stream().pipeThrough(compressionStream);\n\t\tconst compressedBlob = await new Response(compressionPipe).blob();\n\n\t\tconst compressedBytes = new Uint8Array(await compressedBlob.arrayBuffer());\n\n\t\t// GZIP header contains a byte which specifies the OS the\n\t\t// compression was performed on. We set this to 3 (Unix) to ensure\n\t\t// that we produce consistent results.\n\t\tif (type === CompressionType.Gzip && compressedBytes.length >= 10) {\n\t\t\tcompressedBytes[9] = 3;\n\t\t}\n\n\t\treturn compressedBytes;\n\t}\n\n\t/**\n\t * Decompress a gzipped compressed byte array.\n\t * @param compressedBytes The compressed bytes.\n\t * @param type The type of compression to use.\n\t * @returns The decompressed bytes.\n\t */\n\tpublic static async decompress(\n\t\tcompressedBytes: Uint8Array,\n\t\ttype: CompressionType\n\t): Promise<Uint8Array> {\n\t\tGuards.uint8Array(Compression.CLASS_NAME, nameof(compressedBytes), compressedBytes);\n\t\tGuards.arrayOneOf(Compression.CLASS_NAME, nameof(type), type, Object.values(CompressionType));\n\n\t\tconst blob = new Blob([new Uint8Array(compressedBytes)]);\n\t\tconst decompressionStream = new DecompressionStream(type);\n\t\tconst decompressionPipe = blob.stream().pipeThrough(decompressionStream);\n\t\tconst decompressedBlob = await new Response(decompressionPipe).blob();\n\n\t\treturn new Uint8Array(await decompressedBlob.bytes());\n\t}\n}\n"]}