@twin.org/core 0.0.2-next.9 → 0.0.3-next.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.
- package/dist/es/encoding/base32.js +75 -0
- package/dist/es/encoding/base32.js.map +1 -0
- package/dist/es/encoding/base58.js +124 -0
- package/dist/es/encoding/base58.js.map +1 -0
- package/dist/es/encoding/base64.js +231 -0
- package/dist/es/encoding/base64.js.map +1 -0
- package/dist/es/encoding/base64Url.js +42 -0
- package/dist/es/encoding/base64Url.js.map +1 -0
- package/dist/es/errors/alreadyExistsError.js +22 -0
- package/dist/es/errors/alreadyExistsError.js.map +1 -0
- package/dist/es/errors/baseError.js +257 -0
- package/dist/es/errors/baseError.js.map +1 -0
- package/dist/es/errors/conflictError.js +23 -0
- package/dist/es/errors/conflictError.js.map +1 -0
- package/dist/es/errors/generalError.js +21 -0
- package/dist/es/errors/generalError.js.map +1 -0
- package/dist/es/errors/guardError.js +27 -0
- package/dist/es/errors/guardError.js.map +1 -0
- package/dist/es/errors/notFoundError.js +22 -0
- package/dist/es/errors/notFoundError.js.map +1 -0
- package/dist/es/errors/notImplementedError.js +24 -0
- package/dist/es/errors/notImplementedError.js.map +1 -0
- package/dist/es/errors/notSupportedError.js +21 -0
- package/dist/es/errors/notSupportedError.js.map +1 -0
- package/dist/es/errors/unauthorizedError.js +21 -0
- package/dist/es/errors/unauthorizedError.js.map +1 -0
- package/dist/es/errors/unprocessableError.js +21 -0
- package/dist/es/errors/unprocessableError.js.map +1 -0
- package/dist/es/errors/validationError.js +23 -0
- package/dist/es/errors/validationError.js.map +1 -0
- package/dist/es/factories/componentFactory.js +9 -0
- package/dist/es/factories/componentFactory.js.map +1 -0
- package/dist/es/factories/factory.js +256 -0
- package/dist/es/factories/factory.js.map +1 -0
- package/dist/es/helpers/arrayHelper.js +44 -0
- package/dist/es/helpers/arrayHelper.js.map +1 -0
- package/dist/es/helpers/envHelper.js +39 -0
- package/dist/es/helpers/envHelper.js.map +1 -0
- package/dist/es/helpers/errorHelper.js +100 -0
- package/dist/es/helpers/errorHelper.js.map +1 -0
- package/dist/es/helpers/filenameHelper.js +32 -0
- package/dist/es/helpers/filenameHelper.js.map +1 -0
- package/dist/es/helpers/hexHelper.js +45 -0
- package/dist/es/helpers/hexHelper.js.map +1 -0
- package/dist/es/helpers/jsonHelper.js +163 -0
- package/dist/es/helpers/jsonHelper.js.map +1 -0
- package/dist/es/helpers/numberHelper.js +30 -0
- package/dist/es/helpers/numberHelper.js.map +1 -0
- package/dist/es/helpers/objectHelper.js +333 -0
- package/dist/es/helpers/objectHelper.js.map +1 -0
- package/dist/es/helpers/randomHelper.js +18 -0
- package/dist/es/helpers/randomHelper.js.map +1 -0
- package/dist/es/helpers/stringHelper.js +241 -0
- package/dist/es/helpers/stringHelper.js.map +1 -0
- package/dist/es/helpers/uint8ArrayHelper.js +26 -0
- package/dist/es/helpers/uint8ArrayHelper.js.map +1 -0
- package/dist/es/index.js +57 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/models/IComponent.js +4 -0
- package/dist/es/models/IComponent.js.map +1 -0
- package/dist/es/models/IError.js +4 -0
- package/dist/es/models/IError.js.map +1 -0
- package/dist/es/models/II18nShared.js +2 -0
- package/dist/es/models/II18nShared.js.map +1 -0
- package/dist/es/models/IKeyValue.js +2 -0
- package/dist/es/models/IKeyValue.js.map +1 -0
- package/dist/es/models/ILabelledValue.js +2 -0
- package/dist/es/models/ILabelledValue.js.map +1 -0
- package/dist/es/models/ILocale.js +2 -0
- package/dist/es/models/ILocale.js.map +1 -0
- package/dist/es/models/ILocaleDictionary.js +4 -0
- package/dist/es/models/ILocaleDictionary.js.map +1 -0
- package/dist/es/models/ILocalesIndex.js +2 -0
- package/dist/es/models/ILocalesIndex.js.map +1 -0
- package/dist/es/models/IPatchOperation.js +4 -0
- package/dist/es/models/IPatchOperation.js.map +1 -0
- package/dist/es/models/IUrlParts.js +4 -0
- package/dist/es/models/IUrlParts.js.map +1 -0
- package/dist/es/models/IValidationFailure.js +2 -0
- package/dist/es/models/IValidationFailure.js.map +1 -0
- package/dist/es/models/coerceType.js +49 -0
- package/dist/es/models/coerceType.js.map +1 -0
- package/dist/es/models/compressionType.js +17 -0
- package/dist/es/models/compressionType.js.map +1 -0
- package/dist/es/models/objectOrArray.js +2 -0
- package/dist/es/models/objectOrArray.js.map +1 -0
- package/dist/es/types/bitString.js +98 -0
- package/dist/es/types/bitString.js.map +1 -0
- package/dist/es/types/url.js +144 -0
- package/dist/es/types/url.js.map +1 -0
- package/dist/es/types/urn.js +212 -0
- package/dist/es/types/urn.js.map +1 -0
- package/dist/es/utils/asyncCache.js +179 -0
- package/dist/es/utils/asyncCache.js.map +1 -0
- package/dist/es/utils/coerce.js +269 -0
- package/dist/es/utils/coerce.js.map +1 -0
- package/dist/es/utils/compression.js +49 -0
- package/dist/es/utils/compression.js.map +1 -0
- package/dist/es/utils/converter.js +256 -0
- package/dist/es/utils/converter.js.map +1 -0
- package/dist/es/utils/guards.js +369 -0
- package/dist/es/utils/guards.js.map +1 -0
- package/dist/es/utils/i18n.js +243 -0
- package/dist/es/utils/i18n.js.map +1 -0
- package/dist/es/utils/is.js +351 -0
- package/dist/es/utils/is.js.map +1 -0
- package/dist/es/utils/sharedStore.js +48 -0
- package/dist/es/utils/sharedStore.js.map +1 -0
- package/dist/es/utils/validation.js +774 -0
- package/dist/es/utils/validation.js.map +1 -0
- package/dist/types/encoding/base32.d.ts +4 -0
- package/dist/types/encoding/base58.d.ts +4 -0
- package/dist/types/encoding/base64.d.ts +4 -0
- package/dist/types/encoding/base64Url.d.ts +4 -0
- package/dist/types/errors/alreadyExistsError.d.ts +5 -2
- package/dist/types/errors/baseError.d.ts +1 -1
- package/dist/types/errors/conflictError.d.ts +5 -2
- package/dist/types/errors/generalError.d.ts +1 -1
- package/dist/types/errors/guardError.d.ts +1 -1
- package/dist/types/errors/notFoundError.d.ts +5 -2
- package/dist/types/errors/notImplementedError.d.ts +6 -2
- package/dist/types/errors/notSupportedError.d.ts +5 -2
- package/dist/types/errors/unauthorizedError.d.ts +5 -2
- package/dist/types/errors/unprocessableError.d.ts +1 -1
- package/dist/types/errors/validationError.d.ts +2 -2
- package/dist/types/factories/componentFactory.d.ts +2 -2
- package/dist/types/factories/factory.d.ts +4 -0
- package/dist/types/helpers/arrayHelper.d.ts +1 -1
- package/dist/types/helpers/errorHelper.d.ts +1 -1
- package/dist/types/helpers/jsonHelper.d.ts +5 -1
- package/dist/types/helpers/numberHelper.d.ts +17 -0
- package/dist/types/helpers/objectHelper.d.ts +14 -0
- package/dist/types/helpers/stringHelper.d.ts +6 -6
- package/dist/types/index.d.ts +54 -53
- package/dist/types/models/IComponent.d.ts +6 -7
- package/dist/types/models/ILocalesIndex.d.ts +1 -1
- package/dist/types/models/IValidationFailure.d.ts +0 -4
- package/dist/types/types/bitString.d.ts +4 -0
- package/dist/types/types/url.d.ts +8 -3
- package/dist/types/types/urn.d.ts +7 -2
- package/dist/types/utils/coerce.d.ts +1 -1
- package/dist/types/utils/compression.d.ts +5 -1
- package/dist/types/utils/guards.d.ts +2 -3
- package/dist/types/utils/i18n.d.ts +16 -1
- package/dist/types/utils/is.d.ts +1 -1
- package/dist/types/utils/validation.d.ts +1 -1
- package/docs/changelog.md +283 -0
- package/docs/reference/classes/AlreadyExistsError.md +8 -4
- package/docs/reference/classes/AsyncCache.md +5 -5
- package/docs/reference/classes/Base32.md +8 -0
- package/docs/reference/classes/Base58.md +8 -0
- package/docs/reference/classes/Base64.md +8 -0
- package/docs/reference/classes/Base64Url.md +8 -0
- package/docs/reference/classes/BaseError.md +3 -3
- package/docs/reference/classes/BitString.md +8 -0
- package/docs/reference/classes/Coerce.md +20 -20
- package/docs/reference/classes/Compression.md +8 -0
- package/docs/reference/classes/ConflictError.md +8 -4
- package/docs/reference/classes/ErrorHelper.md +2 -2
- package/docs/reference/classes/Factory.md +11 -3
- package/docs/reference/classes/GeneralError.md +3 -3
- package/docs/reference/classes/GuardError.md +3 -3
- package/docs/reference/classes/Guards.md +8 -4
- package/docs/reference/classes/I18n.md +54 -2
- package/docs/reference/classes/Is.md +10 -4
- package/docs/reference/classes/JsonHelper.md +8 -0
- package/docs/reference/classes/NotFoundError.md +8 -4
- package/docs/reference/classes/NotImplementedError.md +14 -4
- package/docs/reference/classes/NotSupportedError.md +8 -4
- package/docs/reference/classes/NumberHelper.md +55 -0
- package/docs/reference/classes/ObjectHelper.md +58 -8
- package/docs/reference/classes/SharedStore.md +2 -2
- package/docs/reference/classes/StringHelper.md +8 -8
- package/docs/reference/classes/UnauthorizedError.md +8 -4
- package/docs/reference/classes/UnprocessableError.md +3 -3
- package/docs/reference/classes/Url.md +17 -3
- package/docs/reference/classes/Urn.md +19 -5
- package/docs/reference/classes/Validation.md +2 -2
- package/docs/reference/classes/ValidationError.md +3 -3
- package/docs/reference/index.md +1 -0
- package/docs/reference/interfaces/IComponent.md +19 -25
- package/docs/reference/interfaces/IValidationFailure.md +0 -8
- package/locales/.validate-ignore +1 -0
- package/locales/en.json +4 -5
- package/package.json +22 -10
- package/dist/cjs/index.cjs +0 -5175
- package/dist/esm/index.mjs +0 -5133
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { GeneralError } from "../errors/generalError.js";
|
|
2
|
+
import { Guards } from "../utils/guards.js";
|
|
3
|
+
/**
|
|
4
|
+
* A class to represent a bit string.
|
|
5
|
+
*/
|
|
6
|
+
export class BitString {
|
|
7
|
+
/**
|
|
8
|
+
* Runtime name for the class.
|
|
9
|
+
*/
|
|
10
|
+
static CLASS_NAME = "BitString";
|
|
11
|
+
/**
|
|
12
|
+
* The storage for the bits.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
_bits;
|
|
16
|
+
/**
|
|
17
|
+
* The number of bits stored in the buffer.
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
20
|
+
_numberBits;
|
|
21
|
+
/**
|
|
22
|
+
* Create a new instance of BitString.
|
|
23
|
+
* @param numberBits The length of the bit string.
|
|
24
|
+
*/
|
|
25
|
+
constructor(numberBits) {
|
|
26
|
+
Guards.integer(BitString.CLASS_NAME, "numberBits", numberBits);
|
|
27
|
+
this._numberBits = numberBits;
|
|
28
|
+
this._bits = new Uint8Array(Math.ceil(numberBits / 8));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Create a new instance of BitString from a bit array.
|
|
32
|
+
* @param bits The bits to create the bit string from.
|
|
33
|
+
* @param numberBits The number of bits in the bit string.
|
|
34
|
+
* @returns The new instance of BitString.
|
|
35
|
+
*/
|
|
36
|
+
static fromBits(bits, numberBits) {
|
|
37
|
+
Guards.uint8Array(BitString.CLASS_NAME, "bits", bits);
|
|
38
|
+
Guards.integer(BitString.CLASS_NAME, "numberBits", numberBits);
|
|
39
|
+
const bs = new BitString(numberBits);
|
|
40
|
+
bs._bits.set(bits);
|
|
41
|
+
return bs;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Get the bit at the given index.
|
|
45
|
+
* @param index The index to get the bit for.
|
|
46
|
+
* @returns True if the bit at the index is set.
|
|
47
|
+
* @throws GeneralError if the index is out of range.
|
|
48
|
+
*/
|
|
49
|
+
getBit(index) {
|
|
50
|
+
Guards.integer(BitString.CLASS_NAME, "index", index);
|
|
51
|
+
if (index < 0 || index >= this._numberBits) {
|
|
52
|
+
throw new GeneralError(BitString.CLASS_NAME, "outOfRange", {
|
|
53
|
+
index,
|
|
54
|
+
numberBits: this._numberBits
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const byteIndex = Math.floor(index / 8);
|
|
58
|
+
const bitIndex = index % 8;
|
|
59
|
+
return (this._bits[byteIndex] & (1 << bitIndex)) !== 0;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Set the bit at the given index.
|
|
63
|
+
* @param index The index to set the bit for.
|
|
64
|
+
* @param value The value to set the bit to.
|
|
65
|
+
* @throws GeneralError if the index is out of range.
|
|
66
|
+
*/
|
|
67
|
+
setBit(index, value) {
|
|
68
|
+
if (index < 0 || index >= this._numberBits) {
|
|
69
|
+
throw new GeneralError(BitString.CLASS_NAME, "outOfRange", {
|
|
70
|
+
index,
|
|
71
|
+
numberBits: this._numberBits
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
const byteIndex = Math.floor(index / 8);
|
|
75
|
+
const bitIndex = index % 8;
|
|
76
|
+
if (value) {
|
|
77
|
+
this._bits[byteIndex] |= 1 << bitIndex;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
this._bits[byteIndex] &= ~(1 << bitIndex);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get the bits of the bit string.
|
|
85
|
+
* @returns The bits stored in a Uint8Array.
|
|
86
|
+
*/
|
|
87
|
+
getBits() {
|
|
88
|
+
return this._bits;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get the length of the bit string.
|
|
92
|
+
* @returns The length of the bit string.
|
|
93
|
+
*/
|
|
94
|
+
getLength() {
|
|
95
|
+
return this._numberBits;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=bitString.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bitString.js","sourceRoot":"","sources":["../../../src/types/bitString.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;GAEG;AACH,MAAM,OAAO,SAAS;IACrB;;OAEG;IACI,MAAM,CAAU,UAAU,eAA+B;IAEhE;;;OAGG;IACc,KAAK,CAAa;IAEnC;;;OAGG;IACc,WAAW,CAAS;IAErC;;;OAGG;IACH,YAAY,UAAkB;QAC7B,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,gBAAsB,UAAU,CAAC,CAAC;QACrE,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;QAC9B,IAAI,CAAC,KAAK,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,QAAQ,CAAC,IAAgB,EAAE,UAAkB;QAC1D,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,UAAgB,IAAI,CAAC,CAAC;QAC5D,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,gBAAsB,UAAU,CAAC,CAAC;QACrE,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,UAAU,CAAC,CAAC;QACrC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO,EAAE,CAAC;IACX,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,KAAa;QAC1B,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,WAAiB,KAAK,CAAC,CAAC;QAC3D,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC5C,MAAM,IAAI,YAAY,CAAC,SAAS,CAAC,UAAU,EAAE,YAAY,EAAE;gBAC1D,KAAK;gBACL,UAAU,EAAE,IAAI,CAAC,WAAW;aAC5B,CAAC,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,KAAa,EAAE,KAAc;QAC1C,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC5C,MAAM,IAAI,YAAY,CAAC,SAAS,CAAC,UAAU,EAAE,YAAY,EAAE;gBAC1D,KAAK;gBACL,UAAU,EAAE,IAAI,CAAC,WAAW;aAC5B,CAAC,CAAC;QACJ,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC;QAC3B,IAAI,KAAK,EAAE,CAAC;YACX,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC;QACxC,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC;QAC3C,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,OAAO;QACb,OAAO,IAAI,CAAC,KAAK,CAAC;IACnB,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,IAAI,CAAC,WAAW,CAAC;IACzB,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\n/* eslint-disable no-bitwise */\nimport { nameof } from \"@twin.org/nameof\";\nimport { GeneralError } from \"../errors/generalError.js\";\nimport { Guards } from \"../utils/guards.js\";\n\n/**\n * A class to represent a bit string.\n */\nexport class BitString {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<BitString>();\n\n\t/**\n\t * The storage for the bits.\n\t * @internal\n\t */\n\tprivate readonly _bits: Uint8Array;\n\n\t/**\n\t * The number of bits stored in the buffer.\n\t * @internal\n\t */\n\tprivate readonly _numberBits: number;\n\n\t/**\n\t * Create a new instance of BitString.\n\t * @param numberBits The length of the bit string.\n\t */\n\tconstructor(numberBits: number) {\n\t\tGuards.integer(BitString.CLASS_NAME, nameof(numberBits), numberBits);\n\t\tthis._numberBits = numberBits;\n\t\tthis._bits = new Uint8Array(Math.ceil(numberBits / 8));\n\t}\n\n\t/**\n\t * Create a new instance of BitString from a bit array.\n\t * @param bits The bits to create the bit string from.\n\t * @param numberBits The number of bits in the bit string.\n\t * @returns The new instance of BitString.\n\t */\n\tpublic static fromBits(bits: Uint8Array, numberBits: number): BitString {\n\t\tGuards.uint8Array(BitString.CLASS_NAME, nameof(bits), bits);\n\t\tGuards.integer(BitString.CLASS_NAME, nameof(numberBits), numberBits);\n\t\tconst bs = new BitString(numberBits);\n\t\tbs._bits.set(bits);\n\t\treturn bs;\n\t}\n\n\t/**\n\t * Get the bit at the given index.\n\t * @param index The index to get the bit for.\n\t * @returns True if the bit at the index is set.\n\t * @throws GeneralError if the index is out of range.\n\t */\n\tpublic getBit(index: number): boolean {\n\t\tGuards.integer(BitString.CLASS_NAME, nameof(index), index);\n\t\tif (index < 0 || index >= this._numberBits) {\n\t\t\tthrow new GeneralError(BitString.CLASS_NAME, \"outOfRange\", {\n\t\t\t\tindex,\n\t\t\t\tnumberBits: this._numberBits\n\t\t\t});\n\t\t}\n\n\t\tconst byteIndex = Math.floor(index / 8);\n\t\tconst bitIndex = index % 8;\n\t\treturn (this._bits[byteIndex] & (1 << bitIndex)) !== 0;\n\t}\n\n\t/**\n\t * Set the bit at the given index.\n\t * @param index The index to set the bit for.\n\t * @param value The value to set the bit to.\n\t * @throws GeneralError if the index is out of range.\n\t */\n\tpublic setBit(index: number, value: boolean): void {\n\t\tif (index < 0 || index >= this._numberBits) {\n\t\t\tthrow new GeneralError(BitString.CLASS_NAME, \"outOfRange\", {\n\t\t\t\tindex,\n\t\t\t\tnumberBits: this._numberBits\n\t\t\t});\n\t\t}\n\t\tconst byteIndex = Math.floor(index / 8);\n\t\tconst bitIndex = index % 8;\n\t\tif (value) {\n\t\t\tthis._bits[byteIndex] |= 1 << bitIndex;\n\t\t} else {\n\t\t\tthis._bits[byteIndex] &= ~(1 << bitIndex);\n\t\t}\n\t}\n\n\t/**\n\t * Get the bits of the bit string.\n\t * @returns The bits stored in a Uint8Array.\n\t */\n\tpublic getBits(): Uint8Array {\n\t\treturn this._bits;\n\t}\n\n\t/**\n\t * Get the length of the bit string.\n\t * @returns The length of the bit string.\n\t */\n\tpublic getLength(): number {\n\t\treturn this._numberBits;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { GuardError } from "../errors/guardError.js";
|
|
2
|
+
import { Coerce } from "../utils/coerce.js";
|
|
3
|
+
import { Guards } from "../utils/guards.js";
|
|
4
|
+
import { Is } from "../utils/is.js";
|
|
5
|
+
/**
|
|
6
|
+
* Class to help with urls.
|
|
7
|
+
*/
|
|
8
|
+
export class Url {
|
|
9
|
+
/**
|
|
10
|
+
* Runtime name for the class.
|
|
11
|
+
*/
|
|
12
|
+
static CLASS_NAME = "Url";
|
|
13
|
+
/**
|
|
14
|
+
* The internal representation of the url.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
_urlParts;
|
|
18
|
+
/**
|
|
19
|
+
* Create a new instance of Url.
|
|
20
|
+
* @param url The url string.
|
|
21
|
+
*/
|
|
22
|
+
constructor(url) {
|
|
23
|
+
Guards.stringValue(Url.CLASS_NAME, "url", url);
|
|
24
|
+
try {
|
|
25
|
+
const u = new URL(url);
|
|
26
|
+
this._urlParts = Url.fromURLToParts(u);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
throw new GuardError(Url.CLASS_NAME, "guard.url", "url", url);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Try and parse a string into the url parts.
|
|
34
|
+
* @param url The url to parse.
|
|
35
|
+
* @returns The formatted url or undefined if the value is not a url.
|
|
36
|
+
*/
|
|
37
|
+
static tryParseExact(url) {
|
|
38
|
+
if (!Is.stringValue(url)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
// By constructing a new standard URL class this will
|
|
43
|
+
// validate the format
|
|
44
|
+
const u = new URL(url);
|
|
45
|
+
return Url.fromParts(Url.fromURLToParts(u));
|
|
46
|
+
}
|
|
47
|
+
catch { }
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Parse a string into the url parts.
|
|
51
|
+
* @param source The source of the error.
|
|
52
|
+
* @param property The name of the property.
|
|
53
|
+
* @param value The url to parse.
|
|
54
|
+
* @throws GuardError If the value does not match the assertion.
|
|
55
|
+
*/
|
|
56
|
+
static guard(source, property, value) {
|
|
57
|
+
Guards.stringValue(source, property, value);
|
|
58
|
+
const result = Url.tryParseExact(value);
|
|
59
|
+
if (!result) {
|
|
60
|
+
throw new GuardError(source, "guard.url", property, value);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Validate a string as a Url.
|
|
65
|
+
* @param property Throw an exception if the url property is invalid.
|
|
66
|
+
* @param value The url to parse.
|
|
67
|
+
* @param failures The list of failures to add to.
|
|
68
|
+
* @param fieldNameResource The optional human readable name for the field as an i18 resource.
|
|
69
|
+
* @returns The formatted url.
|
|
70
|
+
*/
|
|
71
|
+
static validate(property, value, failures, fieldNameResource) {
|
|
72
|
+
if (!Is.stringValue(value)) {
|
|
73
|
+
failures.push({
|
|
74
|
+
property,
|
|
75
|
+
reason: "validation.beNotEmpty",
|
|
76
|
+
properties: { fieldName: fieldNameResource ?? "validation.defaultFieldName", value }
|
|
77
|
+
});
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
const result = Url.tryParseExact(value);
|
|
81
|
+
if (Is.undefined(result)) {
|
|
82
|
+
failures.push({
|
|
83
|
+
property,
|
|
84
|
+
reason: "validation.beUrl",
|
|
85
|
+
properties: { fieldName: fieldNameResource ?? "validation.defaultFieldName", value }
|
|
86
|
+
});
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Construct a url from a URL.
|
|
93
|
+
* @param url The url to construct from.
|
|
94
|
+
* @returns The formatted url.
|
|
95
|
+
*/
|
|
96
|
+
static fromURLToParts(url) {
|
|
97
|
+
return {
|
|
98
|
+
schema: url.protocol.replace(/:$/, ""),
|
|
99
|
+
host: url.hostname,
|
|
100
|
+
port: Coerce.number(url.port),
|
|
101
|
+
path: url.pathname,
|
|
102
|
+
params: Is.stringValue(url.search) ? url.search.replace(/^\?/, "") : undefined,
|
|
103
|
+
hash: Is.stringValue(url.hash) ? url.hash.replace(/^#/, "") : undefined
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Construct a url from valid parts.
|
|
108
|
+
* @param urlParts The url to create the parts from.
|
|
109
|
+
* @returns The formatted url.
|
|
110
|
+
*/
|
|
111
|
+
static fromParts(urlParts) {
|
|
112
|
+
const u = new Url("http://dummy");
|
|
113
|
+
u._urlParts = urlParts;
|
|
114
|
+
return u;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get the parts of the url.
|
|
118
|
+
* @returns The parts of the url.
|
|
119
|
+
*/
|
|
120
|
+
parts() {
|
|
121
|
+
return this._urlParts;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Convert the parts in to a full string.
|
|
125
|
+
* @returns The formatted url.
|
|
126
|
+
*/
|
|
127
|
+
toString() {
|
|
128
|
+
const parts = [this._urlParts.schema, "://", this._urlParts.host];
|
|
129
|
+
if (Is.number(this._urlParts.port)) {
|
|
130
|
+
parts.push(`:${this._urlParts.port}`);
|
|
131
|
+
}
|
|
132
|
+
if (Is.stringValue(this._urlParts.path)) {
|
|
133
|
+
parts.push(this._urlParts.path);
|
|
134
|
+
}
|
|
135
|
+
if (Is.stringValue(this._urlParts.params)) {
|
|
136
|
+
parts.push(`?${this._urlParts.params}`);
|
|
137
|
+
}
|
|
138
|
+
if (Is.stringValue(this._urlParts.hash)) {
|
|
139
|
+
parts.push(`#${this._urlParts.hash}`);
|
|
140
|
+
}
|
|
141
|
+
return parts.join("");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=url.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.js","sourceRoot":"","sources":["../../../src/types/url.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { nameof } from \"@twin.org/nameof\";\nimport { GuardError } from \"../errors/guardError.js\";\nimport type { IUrlParts } from \"../models/IUrlParts.js\";\nimport type { IValidationFailure } from \"../models/IValidationFailure.js\";\nimport { Coerce } from \"../utils/coerce.js\";\nimport { Guards } from \"../utils/guards.js\";\nimport { Is } from \"../utils/is.js\";\n\n/**\n * Class to help with urls.\n */\nexport class Url {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Url>();\n\n\t/**\n\t * The internal representation of the url.\n\t * @internal\n\t */\n\tprivate _urlParts: IUrlParts;\n\n\t/**\n\t * Create a new instance of Url.\n\t * @param url The url string.\n\t */\n\tconstructor(url: string) {\n\t\tGuards.stringValue(Url.CLASS_NAME, nameof(url), url);\n\n\t\ttry {\n\t\t\tconst u = new URL(url);\n\t\t\tthis._urlParts = Url.fromURLToParts(u);\n\t\t} catch {\n\t\t\tthrow new GuardError(Url.CLASS_NAME, \"guard.url\", \"url\", url);\n\t\t}\n\t}\n\n\t/**\n\t * Try and parse a string into the url parts.\n\t * @param url The url to parse.\n\t * @returns The formatted url or undefined if the value is not a url.\n\t */\n\tpublic static tryParseExact(url: unknown): Url | undefined {\n\t\tif (!Is.stringValue(url)) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\t// By constructing a new standard URL class this will\n\t\t\t// validate the format\n\t\t\tconst u = new URL(url);\n\t\t\treturn Url.fromParts(Url.fromURLToParts(u));\n\t\t} catch {}\n\t}\n\n\t/**\n\t * Parse a string into the url parts.\n\t * @param source The source of the error.\n\t * @param property The name of the property.\n\t * @param value The url to parse.\n\t * @throws GuardError If the value does not match the assertion.\n\t */\n\tpublic static guard(source: string, property: string, value: unknown): asserts value is string {\n\t\tGuards.stringValue(source, property, value);\n\n\t\tconst result = Url.tryParseExact(value);\n\n\t\tif (!result) {\n\t\t\tthrow new GuardError(source, \"guard.url\", property, value);\n\t\t}\n\t}\n\n\t/**\n\t * Validate a string as a Url.\n\t * @param property Throw an exception if the url property is invalid.\n\t * @param value The url to parse.\n\t * @param failures The list of failures to add to.\n\t * @param fieldNameResource The optional human readable name for the field as an i18 resource.\n\t * @returns The formatted url.\n\t */\n\tpublic static validate(\n\t\tproperty: string,\n\t\tvalue: unknown,\n\t\tfailures: IValidationFailure[],\n\t\tfieldNameResource?: string\n\t): value is Url {\n\t\tif (!Is.stringValue(value)) {\n\t\t\tfailures.push({\n\t\t\t\tproperty,\n\t\t\t\treason: \"validation.beNotEmpty\",\n\t\t\t\tproperties: { fieldName: fieldNameResource ?? \"validation.defaultFieldName\", value }\n\t\t\t});\n\n\t\t\treturn false;\n\t\t}\n\n\t\tconst result = Url.tryParseExact(value);\n\n\t\tif (Is.undefined(result)) {\n\t\t\tfailures.push({\n\t\t\t\tproperty,\n\t\t\t\treason: \"validation.beUrl\",\n\t\t\t\tproperties: { fieldName: fieldNameResource ?? \"validation.defaultFieldName\", value }\n\t\t\t});\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Construct a url from a URL.\n\t * @param url The url to construct from.\n\t * @returns The formatted url.\n\t */\n\tpublic static fromURLToParts(url: URL): IUrlParts {\n\t\treturn {\n\t\t\tschema: url.protocol.replace(/:$/, \"\"),\n\t\t\thost: url.hostname,\n\t\t\tport: Coerce.number(url.port),\n\t\t\tpath: url.pathname,\n\t\t\tparams: Is.stringValue(url.search) ? url.search.replace(/^\\?/, \"\") : undefined,\n\t\t\thash: Is.stringValue(url.hash) ? url.hash.replace(/^#/, \"\") : undefined\n\t\t};\n\t}\n\n\t/**\n\t * Construct a url from valid parts.\n\t * @param urlParts The url to create the parts from.\n\t * @returns The formatted url.\n\t */\n\tpublic static fromParts(urlParts: IUrlParts): Url {\n\t\tconst u = new Url(\"http://dummy\");\n\t\tu._urlParts = urlParts;\n\t\treturn u;\n\t}\n\n\t/**\n\t * Get the parts of the url.\n\t * @returns The parts of the url.\n\t */\n\tpublic parts(): IUrlParts {\n\t\treturn this._urlParts;\n\t}\n\n\t/**\n\t * Convert the parts in to a full string.\n\t * @returns The formatted url.\n\t */\n\tpublic toString(): string {\n\t\tconst parts: string[] = [this._urlParts.schema, \"://\", this._urlParts.host];\n\t\tif (Is.number(this._urlParts.port)) {\n\t\t\tparts.push(`:${this._urlParts.port}`);\n\t\t}\n\t\tif (Is.stringValue(this._urlParts.path)) {\n\t\t\tparts.push(this._urlParts.path);\n\t\t}\n\t\tif (Is.stringValue(this._urlParts.params)) {\n\t\t\tparts.push(`?${this._urlParts.params}`);\n\t\t}\n\t\tif (Is.stringValue(this._urlParts.hash)) {\n\t\t\tparts.push(`#${this._urlParts.hash}`);\n\t\t}\n\t\treturn parts.join(\"\");\n\t}\n}\n"]}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { GuardError } from "../errors/guardError.js";
|
|
2
|
+
import { RandomHelper } from "../helpers/randomHelper.js";
|
|
3
|
+
import { Converter } from "../utils/converter.js";
|
|
4
|
+
import { Guards } from "../utils/guards.js";
|
|
5
|
+
import { Is } from "../utils/is.js";
|
|
6
|
+
/**
|
|
7
|
+
* Class to help with urns.
|
|
8
|
+
*/
|
|
9
|
+
export class Urn {
|
|
10
|
+
/**
|
|
11
|
+
* Runtime name for the class.
|
|
12
|
+
*/
|
|
13
|
+
static CLASS_NAME = "Urn";
|
|
14
|
+
/**
|
|
15
|
+
* The specific part of the namespace.
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
_urnParts;
|
|
19
|
+
/**
|
|
20
|
+
* Create a new instance of Urn.
|
|
21
|
+
* @param namespaceIdentifier The identifier for the namespace.
|
|
22
|
+
* @param namespaceSpecific The specific part of the namespace.
|
|
23
|
+
*/
|
|
24
|
+
constructor(namespaceIdentifier, namespaceSpecific) {
|
|
25
|
+
Guards.stringValue(Urn.CLASS_NAME, "namespaceIdentifier", namespaceIdentifier);
|
|
26
|
+
// Strip leading and trailing colons
|
|
27
|
+
this._urnParts = [this.stripColons(namespaceIdentifier)];
|
|
28
|
+
if (Is.array(namespaceSpecific)) {
|
|
29
|
+
Guards.arrayValue(Urn.CLASS_NAME, "namespaceSpecific", namespaceSpecific);
|
|
30
|
+
this._urnParts.push(...namespaceSpecific);
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
Guards.stringValue(Urn.CLASS_NAME, "namespaceSpecific", namespaceSpecific);
|
|
34
|
+
this._urnParts.push(...this.stripColons(namespaceSpecific).split(":"));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Generate a random identifier with 32 byte id.
|
|
39
|
+
* @param namespace The prefix for the urn.
|
|
40
|
+
* @returns A new Id in URN format.
|
|
41
|
+
*/
|
|
42
|
+
static generateRandom(namespace) {
|
|
43
|
+
return new Urn(namespace, Converter.bytesToHex(RandomHelper.generate(32)));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Does the provided urn match the namespace.
|
|
47
|
+
* @param urn The urn to check.
|
|
48
|
+
* @param namespace The namespace to match.
|
|
49
|
+
* @returns True if the namespace matches.
|
|
50
|
+
*/
|
|
51
|
+
static hasNamespace(urn, namespace) {
|
|
52
|
+
if (!Is.stringValue(urn)) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
if (urn.startsWith("urn:")) {
|
|
56
|
+
urn = urn.slice(4);
|
|
57
|
+
}
|
|
58
|
+
if (urn.length === namespace.length) {
|
|
59
|
+
return urn === namespace;
|
|
60
|
+
}
|
|
61
|
+
return urn.startsWith(`${namespace}:`);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Try and parse a string into the urn parts.
|
|
65
|
+
* @param urn The urn to parse.
|
|
66
|
+
* @returns The formatted urn or undefined if the value is not a urn.
|
|
67
|
+
*/
|
|
68
|
+
static tryParseExact(urn) {
|
|
69
|
+
if (!Is.stringValue(urn)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const parts = urn.split(":");
|
|
73
|
+
if (parts[0] === "urn") {
|
|
74
|
+
parts.shift();
|
|
75
|
+
}
|
|
76
|
+
if (parts.length < 2) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (!/[\da-z][\da-z-]{0,31}/.test(parts[0])) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
for (let i = 1; i < parts.length; i++) {
|
|
83
|
+
if (!/[\d!#$%'()*+,./:;=?@_a-z-]+/.test(parts[i])) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return new Urn(parts[0], parts.slice(1));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Construct a urn from a string that has already been validated.
|
|
91
|
+
* @param urn The urn to parse.
|
|
92
|
+
* @returns The formatted urn.
|
|
93
|
+
*/
|
|
94
|
+
static fromValidString(urn) {
|
|
95
|
+
const parts = urn.split(":");
|
|
96
|
+
if (parts[0] === "urn") {
|
|
97
|
+
parts.shift();
|
|
98
|
+
}
|
|
99
|
+
return new Urn(parts[0], parts.slice(1));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Add a urn: prefix if there isn't one already.
|
|
103
|
+
* @param urn The urn string to add a prefix to.
|
|
104
|
+
* @returns The urn with a prefix.
|
|
105
|
+
*/
|
|
106
|
+
static addPrefix(urn) {
|
|
107
|
+
if (Is.stringValue(urn)) {
|
|
108
|
+
if (urn.startsWith("urn:")) {
|
|
109
|
+
return urn;
|
|
110
|
+
}
|
|
111
|
+
return `urn:${urn}`;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse a string into the urn parts.
|
|
116
|
+
* @param source The source of the error.
|
|
117
|
+
* @param property The name of the property.
|
|
118
|
+
* @param value The urn to parse.
|
|
119
|
+
* @throws GuardError If the value does not match the assertion.
|
|
120
|
+
*/
|
|
121
|
+
static guard(source, property, value) {
|
|
122
|
+
Guards.stringValue(source, property, value);
|
|
123
|
+
const result = Urn.tryParseExact(value);
|
|
124
|
+
if (!result) {
|
|
125
|
+
throw new GuardError(source, "guard.urn", property, value);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Validate a string as a Urn.
|
|
130
|
+
* @param property Throw an exception if the urn property is invalid.
|
|
131
|
+
* @param value The urn to parse.
|
|
132
|
+
* @param failures The list of failures to add to.
|
|
133
|
+
* @param fieldNameResource The optional human readable name for the field as an i18 resource.
|
|
134
|
+
* @returns The formatted urn.
|
|
135
|
+
*/
|
|
136
|
+
static validate(property, value, failures, fieldNameResource) {
|
|
137
|
+
if (!Is.stringValue(value)) {
|
|
138
|
+
failures.push({
|
|
139
|
+
property,
|
|
140
|
+
reason: "validation.beNotEmpty",
|
|
141
|
+
properties: { fieldName: fieldNameResource ?? "validation.defaultFieldName", value }
|
|
142
|
+
});
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
const result = Urn.tryParseExact(value);
|
|
146
|
+
if (Is.undefined(result)) {
|
|
147
|
+
failures.push({
|
|
148
|
+
property,
|
|
149
|
+
reason: "validation.beUrn",
|
|
150
|
+
properties: { fieldName: fieldNameResource ?? "validation.defaultFieldName", value }
|
|
151
|
+
});
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get the parts.
|
|
158
|
+
* @param startIndex The index to start from, defaults to 0.
|
|
159
|
+
* @returns The parts.
|
|
160
|
+
*/
|
|
161
|
+
parts(startIndex = 0) {
|
|
162
|
+
return this._urnParts.slice(startIndex);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get the namespace identifier.
|
|
166
|
+
* @returns The namespace identifier.
|
|
167
|
+
*/
|
|
168
|
+
namespaceIdentifier() {
|
|
169
|
+
return this._urnParts[0];
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get the namespace method, the first component after the identifier.
|
|
173
|
+
* @returns The namespace method.
|
|
174
|
+
*/
|
|
175
|
+
namespaceMethod() {
|
|
176
|
+
return this._urnParts.length > 1 ? this._urnParts[1] : "";
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get the namespace specific parts.
|
|
180
|
+
* @param startIndex The index to start from, defaults to 0.
|
|
181
|
+
* @returns The namespace specific parts.
|
|
182
|
+
*/
|
|
183
|
+
namespaceSpecificParts(startIndex = 0) {
|
|
184
|
+
return this._urnParts.length > 1 ? this._urnParts.slice(startIndex + 1) : [];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Get the namespace specific.
|
|
188
|
+
* @param startIndex The index to start from, defaults to 0.
|
|
189
|
+
* @returns The namespace specific.
|
|
190
|
+
*/
|
|
191
|
+
namespaceSpecific(startIndex = 0) {
|
|
192
|
+
return this._urnParts.length > 1 ? this._urnParts.slice(startIndex + 1).join(":") : "";
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Convert the parts in to a full string.
|
|
196
|
+
* @param omitPrefix Omit the urn: prefix from the string.
|
|
197
|
+
* @returns The formatted urn.
|
|
198
|
+
*/
|
|
199
|
+
toString(omitPrefix = true) {
|
|
200
|
+
return omitPrefix ? this._urnParts.join(":") : `urn:${this._urnParts.join(":")}`;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Strip the leading and trailing colons from a string.
|
|
204
|
+
* @param val The value to strip.
|
|
205
|
+
* @returns The stripped string.
|
|
206
|
+
* @internal
|
|
207
|
+
*/
|
|
208
|
+
stripColons(val) {
|
|
209
|
+
return val.replace(/^:?(.*?):?$/, "$1");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=urn.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"urn.js","sourceRoot":"","sources":["../../../src/types/urn.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { nameof } from \"@twin.org/nameof\";\nimport { GuardError } from \"../errors/guardError.js\";\nimport { RandomHelper } from \"../helpers/randomHelper.js\";\nimport type { IValidationFailure } from \"../models/IValidationFailure.js\";\nimport { Converter } from \"../utils/converter.js\";\nimport { Guards } from \"../utils/guards.js\";\nimport { Is } from \"../utils/is.js\";\n\n/**\n * Class to help with urns.\n */\nexport class Urn {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<Urn>();\n\n\t/**\n\t * The specific part of the namespace.\n\t * @internal\n\t */\n\tprivate readonly _urnParts: string[];\n\n\t/**\n\t * Create a new instance of Urn.\n\t * @param namespaceIdentifier The identifier for the namespace.\n\t * @param namespaceSpecific The specific part of the namespace.\n\t */\n\tconstructor(namespaceIdentifier: string, namespaceSpecific: string | string[]) {\n\t\tGuards.stringValue(Urn.CLASS_NAME, nameof(namespaceIdentifier), namespaceIdentifier);\n\n\t\t// Strip leading and trailing colons\n\t\tthis._urnParts = [this.stripColons(namespaceIdentifier)];\n\n\t\tif (Is.array(namespaceSpecific)) {\n\t\t\tGuards.arrayValue(Urn.CLASS_NAME, nameof(namespaceSpecific), namespaceSpecific);\n\t\t\tthis._urnParts.push(...namespaceSpecific);\n\t\t} else {\n\t\t\tGuards.stringValue(Urn.CLASS_NAME, nameof(namespaceSpecific), namespaceSpecific);\n\t\t\tthis._urnParts.push(...this.stripColons(namespaceSpecific).split(\":\"));\n\t\t}\n\t}\n\n\t/**\n\t * Generate a random identifier with 32 byte id.\n\t * @param namespace The prefix for the urn.\n\t * @returns A new Id in URN format.\n\t */\n\tpublic static generateRandom(namespace: string): Urn {\n\t\treturn new Urn(namespace, Converter.bytesToHex(RandomHelper.generate(32)));\n\t}\n\n\t/**\n\t * Does the provided urn match the namespace.\n\t * @param urn The urn to check.\n\t * @param namespace The namespace to match.\n\t * @returns True if the namespace matches.\n\t */\n\tpublic static hasNamespace(urn: string, namespace: string): boolean {\n\t\tif (!Is.stringValue(urn)) {\n\t\t\treturn false;\n\t\t}\n\t\tif (urn.startsWith(\"urn:\")) {\n\t\t\turn = urn.slice(4);\n\t\t}\n\n\t\tif (urn.length === namespace.length) {\n\t\t\treturn urn === namespace;\n\t\t}\n\n\t\treturn urn.startsWith(`${namespace}:`);\n\t}\n\n\t/**\n\t * Try and parse a string into the urn parts.\n\t * @param urn The urn to parse.\n\t * @returns The formatted urn or undefined if the value is not a urn.\n\t */\n\tpublic static tryParseExact(urn: unknown): Urn | undefined {\n\t\tif (!Is.stringValue(urn)) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst parts = urn.split(\":\");\n\n\t\tif (parts[0] === \"urn\") {\n\t\t\tparts.shift();\n\t\t}\n\n\t\tif (parts.length < 2) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (!/[\\da-z][\\da-z-]{0,31}/.test(parts[0])) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (let i = 1; i < parts.length; i++) {\n\t\t\tif (!/[\\d!#$%'()*+,./:;=?@_a-z-]+/.test(parts[i])) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\treturn new Urn(parts[0], parts.slice(1));\n\t}\n\n\t/**\n\t * Construct a urn from a string that has already been validated.\n\t * @param urn The urn to parse.\n\t * @returns The formatted urn.\n\t */\n\tpublic static fromValidString(urn: string): Urn {\n\t\tconst parts = urn.split(\":\");\n\n\t\tif (parts[0] === \"urn\") {\n\t\t\tparts.shift();\n\t\t}\n\n\t\treturn new Urn(parts[0], parts.slice(1));\n\t}\n\n\t/**\n\t * Add a urn: prefix if there isn't one already.\n\t * @param urn The urn string to add a prefix to.\n\t * @returns The urn with a prefix.\n\t */\n\tpublic static addPrefix(urn: unknown): string | undefined {\n\t\tif (Is.stringValue(urn)) {\n\t\t\tif (urn.startsWith(\"urn:\")) {\n\t\t\t\treturn urn;\n\t\t\t}\n\t\t\treturn `urn:${urn}`;\n\t\t}\n\t}\n\n\t/**\n\t * Parse a string into the urn parts.\n\t * @param source The source of the error.\n\t * @param property The name of the property.\n\t * @param value The urn to parse.\n\t * @throws GuardError If the value does not match the assertion.\n\t */\n\tpublic static guard(source: string, property: string, value: unknown): asserts value is string {\n\t\tGuards.stringValue(source, property, value);\n\n\t\tconst result = Urn.tryParseExact(value);\n\n\t\tif (!result) {\n\t\t\tthrow new GuardError(source, \"guard.urn\", property, value);\n\t\t}\n\t}\n\n\t/**\n\t * Validate a string as a Urn.\n\t * @param property Throw an exception if the urn property is invalid.\n\t * @param value The urn to parse.\n\t * @param failures The list of failures to add to.\n\t * @param fieldNameResource The optional human readable name for the field as an i18 resource.\n\t * @returns The formatted urn.\n\t */\n\tpublic static validate(\n\t\tproperty: string,\n\t\tvalue: unknown,\n\t\tfailures: IValidationFailure[],\n\t\tfieldNameResource?: string\n\t): value is string {\n\t\tif (!Is.stringValue(value)) {\n\t\t\tfailures.push({\n\t\t\t\tproperty,\n\t\t\t\treason: \"validation.beNotEmpty\",\n\t\t\t\tproperties: { fieldName: fieldNameResource ?? \"validation.defaultFieldName\", value }\n\t\t\t});\n\n\t\t\treturn false;\n\t\t}\n\n\t\tconst result = Urn.tryParseExact(value);\n\n\t\tif (Is.undefined(result)) {\n\t\t\tfailures.push({\n\t\t\t\tproperty,\n\t\t\t\treason: \"validation.beUrn\",\n\t\t\t\tproperties: { fieldName: fieldNameResource ?? \"validation.defaultFieldName\", value }\n\t\t\t});\n\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get the parts.\n\t * @param startIndex The index to start from, defaults to 0.\n\t * @returns The parts.\n\t */\n\tpublic parts(startIndex: number = 0): string[] {\n\t\treturn this._urnParts.slice(startIndex);\n\t}\n\n\t/**\n\t * Get the namespace identifier.\n\t * @returns The namespace identifier.\n\t */\n\tpublic namespaceIdentifier(): string {\n\t\treturn this._urnParts[0];\n\t}\n\n\t/**\n\t * Get the namespace method, the first component after the identifier.\n\t * @returns The namespace method.\n\t */\n\tpublic namespaceMethod(): string {\n\t\treturn this._urnParts.length > 1 ? this._urnParts[1] : \"\";\n\t}\n\n\t/**\n\t * Get the namespace specific parts.\n\t * @param startIndex The index to start from, defaults to 0.\n\t * @returns The namespace specific parts.\n\t */\n\tpublic namespaceSpecificParts(startIndex: number = 0): string[] {\n\t\treturn this._urnParts.length > 1 ? this._urnParts.slice(startIndex + 1) : [];\n\t}\n\n\t/**\n\t * Get the namespace specific.\n\t * @param startIndex The index to start from, defaults to 0.\n\t * @returns The namespace specific.\n\t */\n\tpublic namespaceSpecific(startIndex: number = 0): string {\n\t\treturn this._urnParts.length > 1 ? this._urnParts.slice(startIndex + 1).join(\":\") : \"\";\n\t}\n\n\t/**\n\t * Convert the parts in to a full string.\n\t * @param omitPrefix Omit the urn: prefix from the string.\n\t * @returns The formatted urn.\n\t */\n\tpublic toString(omitPrefix: boolean = true): string {\n\t\treturn omitPrefix ? this._urnParts.join(\":\") : `urn:${this._urnParts.join(\":\")}`;\n\t}\n\n\t/**\n\t * Strip the leading and trailing colons from a string.\n\t * @param val The value to strip.\n\t * @returns The stripped string.\n\t * @internal\n\t */\n\tprivate stripColons(val: string): string {\n\t\treturn val.replace(/^:?(.*?):?$/, \"$1\");\n\t}\n}\n"]}
|