@digitraffic/common 2023.2.1-1 → 2023.3.10-1
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/aws/infra/api/responses.d.ts +0 -4
- package/dist/aws/infra/api/responses.js +1 -15
- package/dist/aws/infra/api/static-integration.js +11 -1
- package/dist/aws/infra/stacks/db-dns-stack.d.ts +2 -0
- package/dist/aws/infra/stacks/db-dns-stack.js +2 -0
- package/dist/aws/infra/stacks/db-stack.d.ts +11 -6
- package/dist/aws/infra/stacks/db-stack.js +10 -8
- package/dist/types/urn.d.ts +1 -0
- package/dist/types/urn.js +3 -0
- package/package.json +11 -11
- package/src/aws/infra/api/responses.ts +0 -14
- package/src/aws/infra/api/static-integration.ts +13 -1
- package/src/aws/infra/stacks/db-dns-stack.ts +2 -0
- package/src/aws/infra/stacks/db-stack.ts +31 -16
- package/src/types/urn.ts +1 -0
@@ -19,10 +19,6 @@ export declare const RESPONSE_404_NOT_FOUND: {
|
|
19
19
|
* @deprecated Use DigitrafficMethodResponse
|
20
20
|
*/
|
21
21
|
export declare function methodResponse(status: string, contentType: MediaType, model: IModel, parameters?: Record<string, boolean>): MethodResponse;
|
22
|
-
/**
|
23
|
-
* @deprecated Use DigitrafficMethodResponse
|
24
|
-
*/
|
25
|
-
export declare function corsMethod(response: MethodResponse): MethodResponse;
|
26
22
|
interface IntegrationOptions {
|
27
23
|
requestParameters?: {
|
28
24
|
[dest: string]: string;
|
@@ -1,6 +1,6 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.getResponse = exports.defaultIntegration = exports.
|
3
|
+
exports.getResponse = exports.defaultIntegration = exports.methodResponse = exports.RESPONSE_404_NOT_FOUND = exports.RESPONSE_CORS_INTEGRATION = exports.RESPONSE_500_SERVER_ERROR = exports.RESPONSE_400_BAD_REQUEST = exports.RESPONSE_200_OK = void 0;
|
4
4
|
const response_1 = require("./response");
|
5
5
|
const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
|
6
6
|
const errors_1 = require("../../types/errors");
|
@@ -41,20 +41,6 @@ function methodResponse(status, contentType, model, parameters) {
|
|
41
41
|
};
|
42
42
|
}
|
43
43
|
exports.methodResponse = methodResponse;
|
44
|
-
/**
|
45
|
-
* @deprecated Use DigitrafficMethodResponse
|
46
|
-
*/
|
47
|
-
function corsMethod(response) {
|
48
|
-
return {
|
49
|
-
...response,
|
50
|
-
...{
|
51
|
-
responseParameters: {
|
52
|
-
"method.response.header.Access-Control-Allow-Origin": true,
|
53
|
-
},
|
54
|
-
},
|
55
|
-
};
|
56
|
-
}
|
57
|
-
exports.corsMethod = corsMethod;
|
58
44
|
/**
|
59
45
|
* Creates a default Lambda integration for a REST API resource _root_
|
60
46
|
* @param lambdaFunction The Lambda function
|
@@ -52,9 +52,19 @@ class DigitrafficStaticIntegration extends aws_apigateway_1.MockIntegration {
|
|
52
52
|
}
|
53
53
|
static createMethodResponse(enableCors) {
|
54
54
|
return enableCors
|
55
|
-
?
|
55
|
+
? corsMethod(METHOD_RESPONSE_200)
|
56
56
|
: METHOD_RESPONSE_200;
|
57
57
|
}
|
58
58
|
}
|
59
59
|
exports.DigitrafficStaticIntegration = DigitrafficStaticIntegration;
|
60
|
+
function corsMethod(response) {
|
61
|
+
return {
|
62
|
+
...response,
|
63
|
+
...{
|
64
|
+
responseParameters: {
|
65
|
+
"method.response.header.Access-Control-Allow-Origin": true,
|
66
|
+
},
|
67
|
+
},
|
68
|
+
};
|
69
|
+
}
|
60
70
|
//# sourceMappingURL=static-integration.js.map
|
@@ -4,6 +4,8 @@ import { InfraStackConfiguration } from "./intra-stack-configuration";
|
|
4
4
|
/**
|
5
5
|
* Creates a dns local zone and creates records for cluster endpoints and proxy endpoints.
|
6
6
|
*
|
7
|
+
* Please note, that created PrivateHostedZone has RETAIN removalPolicy, so if you want to delete this stack,
|
8
|
+
* you must remove the zone by hand after.
|
7
9
|
*/
|
8
10
|
export declare class DbDnsStack extends Stack {
|
9
11
|
constructor(scope: Construct, id: string, isc: InfraStackConfiguration);
|
@@ -10,6 +10,8 @@ const DEFAULT_RECORD_TTL = aws_cdk_lib_1.Duration.seconds(30);
|
|
10
10
|
/**
|
11
11
|
* Creates a dns local zone and creates records for cluster endpoints and proxy endpoints.
|
12
12
|
*
|
13
|
+
* Please note, that created PrivateHostedZone has RETAIN removalPolicy, so if you want to delete this stack,
|
14
|
+
* you must remove the zone by hand after.
|
13
15
|
*/
|
14
16
|
class DbDnsStack extends aws_cdk_lib_1.Stack {
|
15
17
|
constructor(scope, id, isc) {
|
@@ -1,11 +1,9 @@
|
|
1
1
|
import { Stack } from "aws-cdk-lib";
|
2
|
-
import {
|
3
|
-
import {
|
2
|
+
import { InstanceType, IVpc } from "aws-cdk-lib/aws-ec2";
|
3
|
+
import { ISecurityGroup } from "aws-cdk-lib/aws-ec2/lib/security-group";
|
4
4
|
import { AuroraPostgresEngineVersion, DatabaseCluster, DatabaseClusterProps, IParameterGroup } from "aws-cdk-lib/aws-rds";
|
5
|
-
import {
|
6
|
-
import { InstanceType } from "aws-cdk-lib/aws-ec2";
|
5
|
+
import { Construct } from "constructs";
|
7
6
|
import { InfraStackConfiguration } from "./intra-stack-configuration";
|
8
|
-
import { ISecurityGroup } from "aws-cdk-lib/aws-ec2/lib/security-group";
|
9
7
|
export interface DbConfiguration {
|
10
8
|
readonly secretArn: string;
|
11
9
|
readonly dbVersion: AuroraPostgresEngineVersion;
|
@@ -14,12 +12,19 @@ export interface DbConfiguration {
|
|
14
12
|
readonly instances: number;
|
15
13
|
readonly customParameterGroup: boolean;
|
16
14
|
readonly securityGroupId: string;
|
15
|
+
readonly superuserName: string;
|
16
|
+
readonly superuserPassword: string;
|
17
17
|
readonly proxy: {
|
18
18
|
readonly name?: string;
|
19
19
|
readonly securityGroupId: string;
|
20
20
|
};
|
21
21
|
}
|
22
22
|
/**
|
23
|
+
* Stack that creates DatabaseCluster.
|
24
|
+
*
|
25
|
+
* Please not, that created Cluster has RETAIL removalPolicy, so if you want to delete the stack,
|
26
|
+
* you must first deploy without parameter group, then delete stack and manually delete cluster.
|
27
|
+
*
|
23
28
|
* How to upgrade major version?
|
24
29
|
* 0. Set correct SG for db-stack and db-proxy-stack(this step will be removed in the future)
|
25
30
|
* 1. Update db-stack WITHOUT parameter group
|
@@ -34,6 +39,6 @@ export declare class DbStack extends Stack {
|
|
34
39
|
static CLUSTER_PORT: number;
|
35
40
|
constructor(scope: Construct, id: string, isc: InfraStackConfiguration, configuration: DbConfiguration);
|
36
41
|
createParamaterGroup(configuration: DbConfiguration): IParameterGroup;
|
37
|
-
createClusterParameters(configuration: DbConfiguration, instanceName: string, vpc: IVpc, securityGroup: ISecurityGroup, parameterGroup: IParameterGroup
|
42
|
+
createClusterParameters(configuration: DbConfiguration, instanceName: string, vpc: IVpc, securityGroup: ISecurityGroup, parameterGroup: IParameterGroup): DatabaseClusterProps;
|
38
43
|
createAuroraCluster(isc: InfraStackConfiguration, configuration: DbConfiguration): DatabaseCluster;
|
39
44
|
}
|
@@ -4,9 +4,13 @@ exports.DbStack = void 0;
|
|
4
4
|
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
5
5
|
const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
|
6
6
|
const aws_rds_1 = require("aws-cdk-lib/aws-rds");
|
7
|
-
const aws_secretsmanager_1 = require("aws-cdk-lib/aws-secretsmanager");
|
8
7
|
const import_util_1 = require("../import-util");
|
9
8
|
/**
|
9
|
+
* Stack that creates DatabaseCluster.
|
10
|
+
*
|
11
|
+
* Please not, that created Cluster has RETAIL removalPolicy, so if you want to delete the stack,
|
12
|
+
* you must first deploy without parameter group, then delete stack and manually delete cluster.
|
13
|
+
*
|
10
14
|
* How to upgrade major version?
|
11
15
|
* 0. Set correct SG for db-stack and db-proxy-stack(this step will be removed in the future)
|
12
16
|
* 1. Update db-stack WITHOUT parameter group
|
@@ -38,7 +42,7 @@ class DbStack extends aws_cdk_lib_1.Stack {
|
|
38
42
|
})
|
39
43
|
: aws_rds_1.ParameterGroup.fromParameterGroupName(this, "ParameterGroup", `default.aurora-postgresql${configuration.dbVersion.auroraPostgresMajorVersion}`);
|
40
44
|
}
|
41
|
-
createClusterParameters(configuration, instanceName, vpc, securityGroup, parameterGroup
|
45
|
+
createClusterParameters(configuration, instanceName, vpc, securityGroup, parameterGroup) {
|
42
46
|
return {
|
43
47
|
engine: aws_rds_1.DatabaseClusterEngine.auroraPostgres({
|
44
48
|
version: configuration.dbVersion,
|
@@ -67,19 +71,16 @@ class DbStack extends aws_cdk_lib_1.Stack {
|
|
67
71
|
instanceType: configuration.dbInstanceType,
|
68
72
|
parameterGroup,
|
69
73
|
},
|
70
|
-
credentials: aws_rds_1.Credentials.
|
74
|
+
credentials: aws_rds_1.Credentials.fromPassword(configuration.superuserName, aws_cdk_lib_1.SecretValue.unsafePlainText(configuration.superuserPassword)),
|
71
75
|
parameterGroup,
|
72
76
|
};
|
73
77
|
}
|
74
78
|
createAuroraCluster(isc, configuration) {
|
75
79
|
const instanceName = isc.environmentName + "-db";
|
76
|
-
const secret = aws_secretsmanager_1.Secret.fromSecretAttributes(this, "db-secret", {
|
77
|
-
secretCompleteArn: configuration.secretArn,
|
78
|
-
});
|
79
80
|
const securityGroup = aws_ec2_1.SecurityGroup.fromSecurityGroupId(this, "securitygroup", configuration.securityGroupId);
|
80
|
-
const vpc = (0, import_util_1.importVpc)(this, isc.environmentName);
|
81
81
|
const parameterGroup = this.createParamaterGroup(configuration);
|
82
|
-
const parameters = this.createClusterParameters(configuration, instanceName,
|
82
|
+
const parameters = this.createClusterParameters(configuration, instanceName, (0, import_util_1.importVpc)(this, isc.environmentName), securityGroup, parameterGroup);
|
83
|
+
// create cluster from the snapshot or from the scratch
|
83
84
|
const cluster = configuration.snapshotIdentifier
|
84
85
|
? new aws_rds_1.DatabaseClusterFromSnapshot(this, instanceName, {
|
85
86
|
...parameters,
|
@@ -92,6 +93,7 @@ class DbStack extends aws_cdk_lib_1.Stack {
|
|
92
93
|
throw new Error("Couldn't pull CfnDBInstances from the L1 constructs!");
|
93
94
|
}
|
94
95
|
cfnInstances.forEach((cfnInstance) => delete cfnInstance.engineVersion);
|
96
|
+
cluster.node.addDependency(parameterGroup, "Create ParameterGroup before DatabaseCluster");
|
95
97
|
return cluster;
|
96
98
|
}
|
97
99
|
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export type URN<Namespace extends string, NamespaceSpecificString extends string = ""> = `urn:${Namespace}:${NamespaceSpecificString}`;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@digitraffic/common",
|
3
|
-
"version": "2023.
|
3
|
+
"version": "2023.03.10-1",
|
4
4
|
"description": "",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -19,7 +19,7 @@
|
|
19
19
|
"peerDependencies": {
|
20
20
|
"@aws-cdk/aws-synthetics-alpha": "2.62.2-alpha.0",
|
21
21
|
"@types/geojson": "^7946.0.10",
|
22
|
-
"aws-cdk-lib": "
|
22
|
+
"aws-cdk-lib": "2.62.2",
|
23
23
|
"aws-sdk": "^2.1304.0",
|
24
24
|
"axios": "^1.2.6",
|
25
25
|
"change-case": "^4.1.2",
|
@@ -35,24 +35,24 @@
|
|
35
35
|
"@types/aws-lambda": "^8.10.110",
|
36
36
|
"@types/geojson": "^7946.0.10",
|
37
37
|
"@types/jest": "^29.2.5",
|
38
|
-
"@types/node": "^18.
|
39
|
-
"@types/ramda": "^0.28.
|
38
|
+
"@types/node": "^18.13.0",
|
39
|
+
"@types/ramda": "^0.28.23",
|
40
40
|
"@types/sinon": "^10.0.13",
|
41
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
42
|
-
"@typescript-eslint/parser": "^5.
|
43
|
-
"aws-cdk-lib": "
|
41
|
+
"@typescript-eslint/eslint-plugin": "^5.51.0",
|
42
|
+
"@typescript-eslint/parser": "^5.51.0",
|
43
|
+
"aws-cdk-lib": "2.62.2",
|
44
44
|
"aws-sdk": "^2.1304.0",
|
45
45
|
"axios": "^1.2.6",
|
46
46
|
"change-case": "^4.1.2",
|
47
47
|
"constructs": "^10.1.222",
|
48
|
-
"eslint": "^8.
|
48
|
+
"eslint": "^8.34.0",
|
49
49
|
"eslint-config-prettier": "^8.6.0",
|
50
50
|
"eslint-plugin-deprecation": "1.3.3",
|
51
51
|
"geojson-validation": "^1.0.2",
|
52
52
|
"husky": "^8.0.3",
|
53
|
-
"jest": "^29.
|
53
|
+
"jest": "^29.4.2",
|
54
54
|
"jest-junit": "^15.0.0",
|
55
|
-
"lint-staged": "^13.1.
|
55
|
+
"lint-staged": "^13.1.1",
|
56
56
|
"moment": "^2.29.4",
|
57
57
|
"node-ttl": "^0.2.0",
|
58
58
|
"pg-native": "^3.0.1",
|
@@ -62,7 +62,7 @@
|
|
62
62
|
"rimraf": "^4.1.0",
|
63
63
|
"sinon": "^15.0.1",
|
64
64
|
"ts-jest": "^29.0.5",
|
65
|
-
"typescript": "^4.9.
|
65
|
+
"typescript": "^4.9.5"
|
66
66
|
},
|
67
67
|
"externals": [
|
68
68
|
"aws-sdk",
|
@@ -68,20 +68,6 @@ export function methodResponse(
|
|
68
68
|
};
|
69
69
|
}
|
70
70
|
|
71
|
-
/**
|
72
|
-
* @deprecated Use DigitrafficMethodResponse
|
73
|
-
*/
|
74
|
-
export function corsMethod(response: MethodResponse): MethodResponse {
|
75
|
-
return {
|
76
|
-
...response,
|
77
|
-
...{
|
78
|
-
responseParameters: {
|
79
|
-
"method.response.header.Access-Control-Allow-Origin": true,
|
80
|
-
},
|
81
|
-
},
|
82
|
-
};
|
83
|
-
}
|
84
|
-
|
85
71
|
interface IntegrationOptions {
|
86
72
|
// eslint-disable-next-line @typescript-eslint/consistent-indexed-object-style
|
87
73
|
requestParameters?: { [dest: string]: string };
|
@@ -1,10 +1,11 @@
|
|
1
1
|
import {
|
2
|
+
MethodResponse,
|
2
3
|
MockIntegration,
|
3
4
|
PassthroughBehavior,
|
4
5
|
Resource,
|
5
6
|
} from "aws-cdk-lib/aws-apigateway";
|
6
7
|
import { MediaType } from "../../types/mediatypes";
|
7
|
-
import {
|
8
|
+
import { RESPONSE_CORS_INTEGRATION } from "./responses";
|
8
9
|
|
9
10
|
const INTEGRATION_RESPONSE_200 = `{
|
10
11
|
"statusCode": 200
|
@@ -94,3 +95,14 @@ export class DigitrafficStaticIntegration extends MockIntegration {
|
|
94
95
|
: METHOD_RESPONSE_200;
|
95
96
|
}
|
96
97
|
}
|
98
|
+
|
99
|
+
function corsMethod(response: MethodResponse): MethodResponse {
|
100
|
+
return {
|
101
|
+
...response,
|
102
|
+
...{
|
103
|
+
responseParameters: {
|
104
|
+
"method.response.header.Access-Control-Allow-Origin": true,
|
105
|
+
},
|
106
|
+
},
|
107
|
+
};
|
108
|
+
}
|
@@ -16,6 +16,8 @@ const DEFAULT_RECORD_TTL = Duration.seconds(30);
|
|
16
16
|
/**
|
17
17
|
* Creates a dns local zone and creates records for cluster endpoints and proxy endpoints.
|
18
18
|
*
|
19
|
+
* Please note, that created PrivateHostedZone has RETAIN removalPolicy, so if you want to delete this stack,
|
20
|
+
* you must remove the zone by hand after.
|
19
21
|
*/
|
20
22
|
export class DbDnsStack extends Stack {
|
21
23
|
constructor(scope: Construct, id: string, isc: InfraStackConfiguration) {
|
@@ -1,6 +1,11 @@
|
|
1
|
-
import { Duration, RemovalPolicy, Stack } from "aws-cdk-lib";
|
2
|
-
import {
|
3
|
-
|
1
|
+
import { Duration, RemovalPolicy, SecretValue, Stack } from "aws-cdk-lib";
|
2
|
+
import {
|
3
|
+
InstanceType,
|
4
|
+
IVpc,
|
5
|
+
SecurityGroup,
|
6
|
+
SubnetType,
|
7
|
+
} from "aws-cdk-lib/aws-ec2";
|
8
|
+
import { ISecurityGroup } from "aws-cdk-lib/aws-ec2/lib/security-group";
|
4
9
|
import {
|
5
10
|
AuroraPostgresEngineVersion,
|
6
11
|
CfnDBInstance,
|
@@ -13,11 +18,9 @@ import {
|
|
13
18
|
IParameterGroup,
|
14
19
|
ParameterGroup,
|
15
20
|
} from "aws-cdk-lib/aws-rds";
|
16
|
-
import {
|
21
|
+
import { Construct } from "constructs";
|
17
22
|
import { exportValue, importVpc } from "../import-util";
|
18
|
-
import { InstanceType } from "aws-cdk-lib/aws-ec2";
|
19
23
|
import { InfraStackConfiguration } from "./intra-stack-configuration";
|
20
|
-
import { ISecurityGroup } from "aws-cdk-lib/aws-ec2/lib/security-group";
|
21
24
|
|
22
25
|
export interface DbConfiguration {
|
23
26
|
readonly secretArn: string;
|
@@ -29,6 +32,9 @@ export interface DbConfiguration {
|
|
29
32
|
readonly customParameterGroup: boolean;
|
30
33
|
readonly securityGroupId: string;
|
31
34
|
|
35
|
+
readonly superuserName: string;
|
36
|
+
readonly superuserPassword: string;
|
37
|
+
|
32
38
|
readonly proxy: {
|
33
39
|
readonly name?: string;
|
34
40
|
readonly securityGroupId: string;
|
@@ -36,6 +42,11 @@ export interface DbConfiguration {
|
|
36
42
|
}
|
37
43
|
|
38
44
|
/**
|
45
|
+
* Stack that creates DatabaseCluster.
|
46
|
+
*
|
47
|
+
* Please not, that created Cluster has RETAIL removalPolicy, so if you want to delete the stack,
|
48
|
+
* you must first deploy without parameter group, then delete stack and manually delete cluster.
|
49
|
+
*
|
39
50
|
* How to upgrade major version?
|
40
51
|
* 0. Set correct SG for db-stack and db-proxy-stack(this step will be removed in the future)
|
41
52
|
* 1. Update db-stack WITHOUT parameter group
|
@@ -113,8 +124,7 @@ export class DbStack extends Stack {
|
|
113
124
|
instanceName: string,
|
114
125
|
vpc: IVpc,
|
115
126
|
securityGroup: ISecurityGroup,
|
116
|
-
parameterGroup: IParameterGroup
|
117
|
-
secret: ISecret
|
127
|
+
parameterGroup: IParameterGroup
|
118
128
|
): DatabaseClusterProps {
|
119
129
|
return {
|
120
130
|
engine: DatabaseClusterEngine.auroraPostgres({
|
@@ -144,7 +154,10 @@ export class DbStack extends Stack {
|
|
144
154
|
instanceType: configuration.dbInstanceType,
|
145
155
|
parameterGroup,
|
146
156
|
},
|
147
|
-
credentials: Credentials.
|
157
|
+
credentials: Credentials.fromPassword(
|
158
|
+
configuration.superuserName,
|
159
|
+
SecretValue.unsafePlainText(configuration.superuserPassword)
|
160
|
+
),
|
148
161
|
parameterGroup,
|
149
162
|
};
|
150
163
|
}
|
@@ -154,24 +167,21 @@ export class DbStack extends Stack {
|
|
154
167
|
configuration: DbConfiguration
|
155
168
|
): DatabaseCluster {
|
156
169
|
const instanceName = isc.environmentName + "-db";
|
157
|
-
const secret = Secret.fromSecretAttributes(this, "db-secret", {
|
158
|
-
secretCompleteArn: configuration.secretArn,
|
159
|
-
});
|
160
170
|
const securityGroup = SecurityGroup.fromSecurityGroupId(
|
161
171
|
this,
|
162
172
|
"securitygroup",
|
163
173
|
configuration.securityGroupId
|
164
174
|
);
|
165
|
-
const vpc = importVpc(this, isc.environmentName);
|
166
175
|
const parameterGroup = this.createParamaterGroup(configuration);
|
167
176
|
const parameters = this.createClusterParameters(
|
168
177
|
configuration,
|
169
178
|
instanceName,
|
170
|
-
|
179
|
+
importVpc(this, isc.environmentName),
|
171
180
|
securityGroup,
|
172
|
-
parameterGroup
|
173
|
-
secret
|
181
|
+
parameterGroup
|
174
182
|
);
|
183
|
+
|
184
|
+
// create cluster from the snapshot or from the scratch
|
175
185
|
const cluster = configuration.snapshotIdentifier
|
176
186
|
? new DatabaseClusterFromSnapshot(this, instanceName, {
|
177
187
|
...parameters,
|
@@ -190,6 +200,11 @@ export class DbStack extends Stack {
|
|
190
200
|
}
|
191
201
|
cfnInstances.forEach((cfnInstance) => delete cfnInstance.engineVersion);
|
192
202
|
|
203
|
+
cluster.node.addDependency(
|
204
|
+
parameterGroup,
|
205
|
+
"Create ParameterGroup before DatabaseCluster"
|
206
|
+
);
|
207
|
+
|
193
208
|
return cluster;
|
194
209
|
}
|
195
210
|
}
|
package/src/types/urn.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
export type URN<Namespace extends string, NamespaceSpecificString extends string = ""> = `urn:${Namespace}:${NamespaceSpecificString}`;
|