@twin.org/core 0.9.1-next.3 → 0.9.1-next.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  import { GuardError } from "../errors/guardError.js";
2
+ import { ArrayHelper } from "../helpers/arrayHelper.js";
2
3
  import { RandomHelper } from "../helpers/randomHelper.js";
3
4
  import { Guards } from "../utils/guards.js";
4
5
  import { Is } from "../utils/is.js";
@@ -115,14 +116,29 @@ export class Urn {
115
116
  * @param source The source of the error.
116
117
  * @param property The name of the property.
117
118
  * @param value The urn to parse.
119
+ * @param options Optional constraints to validate the urn namespace identifier and specific parts.
120
+ * @param options.namespaceIdentifier The namespace identifier the urn must match.
121
+ * @param options.namespaceSpecific The namespace specific part(s) the urn must match.
118
122
  * @throws GuardError If the value does not match the assertion.
119
123
  */
120
- static guard(source, property, value) {
124
+ static guard(source, property, value, options) {
121
125
  Guards.stringValue(source, property, value);
122
126
  const result = Urn.tryParseExact(value);
123
127
  if (!result) {
124
128
  throw new GuardError(source, "guard.urn", property, value);
125
129
  }
130
+ if (!Is.empty(options)) {
131
+ if (Is.stringValue(options.namespaceIdentifier) &&
132
+ result.namespaceIdentifier() !== options.namespaceIdentifier) {
133
+ throw new GuardError(source, "guard.urnNamespaceIdentifier", property, value, options.namespaceIdentifier);
134
+ }
135
+ if (!Is.empty(options.namespaceSpecific)) {
136
+ const expected = ArrayHelper.fromObjectOrArray(options.namespaceSpecific);
137
+ if (!ArrayHelper.matches(result.namespaceSpecificParts(), expected)) {
138
+ throw new GuardError(source, "guard.urnNamespaceSpecific", property, value, expected?.join(":"));
139
+ }
140
+ }
141
+ }
126
142
  }
127
143
  /**
128
144
  * Validate a string as a Urn.
@@ -177,10 +193,17 @@ export class Urn {
177
193
  /**
178
194
  * Get the namespace specific parts.
179
195
  * @param startIndex The index to start from, defaults to 0.
196
+ * @param count The number of parts to return, defaults to all remaining parts.
180
197
  * @returns The namespace specific parts.
181
198
  */
182
- namespaceSpecificParts(startIndex = 0) {
183
- return this._urnParts.length > 1 ? this._urnParts.slice(startIndex + 1) : [];
199
+ namespaceSpecificParts(startIndex = 0, count) {
200
+ if (this._urnParts.length <= 1) {
201
+ return [];
202
+ }
203
+ const start = startIndex + 1;
204
+ return Is.undefined(count)
205
+ ? this._urnParts.slice(start)
206
+ : this._urnParts.slice(start, start + count);
184
207
  }
185
208
  /**
186
209
  * Get the namespace specific.
@@ -1 +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 { 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, RandomHelper.generateUuidV7(\"compact\"));\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"]}
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 { ArrayHelper } from \"../helpers/arrayHelper.js\";\nimport { RandomHelper } from \"../helpers/randomHelper.js\";\nimport type { IValidationFailure } from \"../models/IValidationFailure.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, RandomHelper.generateUuidV7(\"compact\"));\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 * @param options Optional constraints to validate the urn namespace identifier and specific parts.\n\t * @param options.namespaceIdentifier The namespace identifier the urn must match.\n\t * @param options.namespaceSpecific The namespace specific part(s) the urn must match.\n\t * @throws GuardError If the value does not match the assertion.\n\t */\n\tpublic static guard(\n\t\tsource: string,\n\t\tproperty: string,\n\t\tvalue: unknown,\n\t\toptions?: { namespaceIdentifier?: string; namespaceSpecific?: string | string[] }\n\t): 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\n\t\tif (!Is.empty(options)) {\n\t\t\tif (\n\t\t\t\tIs.stringValue(options.namespaceIdentifier) &&\n\t\t\t\tresult.namespaceIdentifier() !== options.namespaceIdentifier\n\t\t\t) {\n\t\t\t\tthrow new GuardError(\n\t\t\t\t\tsource,\n\t\t\t\t\t\"guard.urnNamespaceIdentifier\",\n\t\t\t\t\tproperty,\n\t\t\t\t\tvalue,\n\t\t\t\t\toptions.namespaceIdentifier\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!Is.empty(options.namespaceSpecific)) {\n\t\t\t\tconst expected = ArrayHelper.fromObjectOrArray(options.namespaceSpecific);\n\t\t\t\tif (!ArrayHelper.matches(result.namespaceSpecificParts(), expected)) {\n\t\t\t\t\tthrow new GuardError(\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\"guard.urnNamespaceSpecific\",\n\t\t\t\t\t\tproperty,\n\t\t\t\t\t\tvalue,\n\t\t\t\t\t\texpected?.join(\":\")\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\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 * @param count The number of parts to return, defaults to all remaining parts.\n\t * @returns The namespace specific parts.\n\t */\n\tpublic namespaceSpecificParts(startIndex: number = 0, count?: number): string[] {\n\t\tif (this._urnParts.length <= 1) {\n\t\t\treturn [];\n\t\t}\n\t\tconst start = startIndex + 1;\n\t\treturn Is.undefined(count)\n\t\t\t? this._urnParts.slice(start)\n\t\t\t: this._urnParts.slice(start, start + count);\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"]}
@@ -49,9 +49,15 @@ export declare class Urn {
49
49
  * @param source The source of the error.
50
50
  * @param property The name of the property.
51
51
  * @param value The urn to parse.
52
+ * @param options Optional constraints to validate the urn namespace identifier and specific parts.
53
+ * @param options.namespaceIdentifier The namespace identifier the urn must match.
54
+ * @param options.namespaceSpecific The namespace specific part(s) the urn must match.
52
55
  * @throws GuardError If the value does not match the assertion.
53
56
  */
54
- static guard(source: string, property: string, value: unknown): asserts value is string;
57
+ static guard(source: string, property: string, value: unknown, options?: {
58
+ namespaceIdentifier?: string;
59
+ namespaceSpecific?: string | string[];
60
+ }): asserts value is string;
55
61
  /**
56
62
  * Validate a string as a Urn.
57
63
  * @param property Throw an exception if the urn property is invalid.
@@ -80,9 +86,10 @@ export declare class Urn {
80
86
  /**
81
87
  * Get the namespace specific parts.
82
88
  * @param startIndex The index to start from, defaults to 0.
89
+ * @param count The number of parts to return, defaults to all remaining parts.
83
90
  * @returns The namespace specific parts.
84
91
  */
85
- namespaceSpecificParts(startIndex?: number): string[];
92
+ namespaceSpecificParts(startIndex?: number, count?: number): string[];
86
93
  /**
87
94
  * Get the namespace specific.
88
95
  * @param startIndex The index to start from, defaults to 0.
package/docs/changelog.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.1-next.5](https://github.com/iotaledger/twin-framework/compare/core-v0.9.1-next.4...core-v0.9.1-next.5) (2026-06-29)
4
+
5
+
6
+ ### Features
7
+
8
+ * urn and header helper extensions ([#395](https://github.com/iotaledger/twin-framework/issues/395)) ([5976756](https://github.com/iotaledger/twin-framework/commit/5976756886d22e5063671052abc4dfa04ce23a53))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/nameof bumped from 0.9.1-next.4 to 0.9.1-next.5
16
+ * devDependencies
17
+ * @twin.org/nameof-transformer bumped from 0.9.1-next.4 to 0.9.1-next.5
18
+ * @twin.org/nameof-vitest-plugin bumped from 0.9.1-next.4 to 0.9.1-next.5
19
+
20
+ ## [0.9.1-next.4](https://github.com/iotaledger/twin-framework/compare/core-v0.9.1-next.3...core-v0.9.1-next.4) (2026-06-26)
21
+
22
+
23
+ ### Miscellaneous Chores
24
+
25
+ * **core:** Synchronize repo versions
26
+
27
+
28
+ ### Dependencies
29
+
30
+ * The following workspace dependencies were updated
31
+ * dependencies
32
+ * @twin.org/nameof bumped from 0.9.1-next.3 to 0.9.1-next.4
33
+ * devDependencies
34
+ * @twin.org/nameof-transformer bumped from 0.9.1-next.3 to 0.9.1-next.4
35
+ * @twin.org/nameof-vitest-plugin bumped from 0.9.1-next.3 to 0.9.1-next.4
36
+
3
37
  ## [0.9.1-next.3](https://github.com/iotaledger/twin-framework/compare/core-v0.9.1-next.2...core-v0.9.1-next.3) (2026-06-26)
4
38
 
5
39
 
@@ -156,7 +156,7 @@ The urn with a prefix.
156
156
 
157
157
  ### guard() {#guard}
158
158
 
159
- > `static` **guard**(`source`, `property`, `value`): `asserts value is string`
159
+ > `static` **guard**(`source`, `property`, `value`, `options?`): `asserts value is string`
160
160
 
161
161
  Parse a string into the urn parts.
162
162
 
@@ -180,6 +180,22 @@ The name of the property.
180
180
 
181
181
  The urn to parse.
182
182
 
183
+ ##### options?
184
+
185
+ Optional constraints to validate the urn namespace identifier and specific parts.
186
+
187
+ ###### namespaceIdentifier?
188
+
189
+ `string`
190
+
191
+ The namespace identifier the urn must match.
192
+
193
+ ###### namespaceSpecific?
194
+
195
+ `string` \| `string`[]
196
+
197
+ The namespace specific part(s) the urn must match.
198
+
183
199
  #### Returns
184
200
 
185
201
  `asserts value is string`
@@ -282,7 +298,7 @@ The namespace method.
282
298
 
283
299
  ### namespaceSpecificParts() {#namespacespecificparts}
284
300
 
285
- > **namespaceSpecificParts**(`startIndex?`): `string`[]
301
+ > **namespaceSpecificParts**(`startIndex?`, `count?`): `string`[]
286
302
 
287
303
  Get the namespace specific parts.
288
304
 
@@ -294,6 +310,12 @@ Get the namespace specific parts.
294
310
 
295
311
  The index to start from, defaults to 0.
296
312
 
313
+ ##### count?
314
+
315
+ `number`
316
+
317
+ The number of parts to return, defaults to all remaining parts.
318
+
297
319
  #### Returns
298
320
 
299
321
  `string`[]
package/locales/en.json CHANGED
@@ -71,6 +71,8 @@
71
71
  "uint8Array": "Property \"{property}\" must be a Uint8Array, it is \"{value}\"",
72
72
  "function": "Property \"{property}\" must be a function, it is \"{value}\"",
73
73
  "urn": "Property \"{property}\" must be a URN formatted string, it is \"{value}\"",
74
+ "urnNamespaceIdentifier": "Property \"{property}\" must be a URN with namespace identifier \"{options}\", it is \"{value}\"",
75
+ "urnNamespaceSpecific": "Property \"{property}\" must be a URN with namespace specific \"{options}\", it is \"{value}\"",
74
76
  "url": "Property \"{property}\" must be a URL formatted string, it is \"{value}\"",
75
77
  "email": "Property \"{property}\" must be string in e-mail format, it is \"{value}\"",
76
78
  "uuidV7": "Property \"{property}\" must be a UUIDv7 formatted string, it is \"{value}\"",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/core",
3
- "version": "0.9.1-next.3",
3
+ "version": "0.9.1-next.5",
4
4
  "description": "Helper methods/classes for data type checking/validation/guarding/error handling",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,7 +14,7 @@
14
14
  "node": ">=20.0.0"
15
15
  },
16
16
  "dependencies": {
17
- "@twin.org/nameof": "0.9.1-next.3",
17
+ "@twin.org/nameof": "0.9.1-next.5",
18
18
  "intl-messageformat": "11.2.8",
19
19
  "rfc6902": "5.2.0"
20
20
  },