@openhi/constructs 0.0.0 → 0.0.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/lib/chunk-LZOMFHX3.mjs +38 -0
- package/lib/chunk-LZOMFHX3.mjs.map +1 -0
- package/lib/index.d.mts +664 -0
- package/lib/index.d.ts +745 -3
- package/lib/index.js +1133 -19
- package/lib/index.js.map +1 -0
- package/lib/index.mjs +1120 -0
- package/lib/index.mjs.map +1 -0
- package/lib/rest-api-lambda.handler.d.mts +6 -0
- package/lib/rest-api-lambda.handler.d.ts +6 -0
- package/lib/rest-api-lambda.handler.js +677 -0
- package/lib/rest-api-lambda.handler.js.map +1 -0
- package/lib/rest-api-lambda.handler.mjs +646 -0
- package/lib/rest-api-lambda.handler.mjs.map +1 -0
- package/package.json +37 -28
- package/lib/app/index.d.ts +0 -4
- package/lib/app/index.js +0 -21
- package/lib/app/open-hi-app.d.ts +0 -85
- package/lib/app/open-hi-app.js +0 -127
- package/lib/app/open-hi-environment.d.ts +0 -59
- package/lib/app/open-hi-environment.js +0 -72
- package/lib/app/open-hi-service.d.ts +0 -169
- package/lib/app/open-hi-service.js +0 -195
- package/lib/app/open-hi-stage.d.ts +0 -71
- package/lib/app/open-hi-stage.js +0 -70
- package/lib/components/acm/root-wildcard-certificate.d.ts +0 -15
- package/lib/components/acm/root-wildcard-certificate.js +0 -35
- package/lib/components/api-gateway/core-http-api.d.ts +0 -10
- package/lib/components/api-gateway/core-http-api.js +0 -44
- package/lib/components/api-gateway/http-lambda-integration-no-permissions.d.ts +0 -18
- package/lib/components/api-gateway/http-lambda-integration-no-permissions.js +0 -26
- package/lib/components/app-sync/core-graphql-api.d.ts +0 -12
- package/lib/components/app-sync/core-graphql-api.js +0 -54
- package/lib/components/auth.d.ts +0 -75
- package/lib/components/auth.js +0 -100
- package/lib/components/cognito/core-user-pool-client.d.ts +0 -10
- package/lib/components/cognito/core-user-pool-client.js +0 -47
- package/lib/components/cognito/core-user-pool-domain.d.ts +0 -10
- package/lib/components/cognito/core-user-pool-domain.js +0 -41
- package/lib/components/cognito/core-user-pool-kms-key.d.ts +0 -10
- package/lib/components/cognito/core-user-pool-kms-key.js +0 -37
- package/lib/components/cognito/core-user-pool.d.ts +0 -10
- package/lib/components/cognito/core-user-pool.js +0 -54
- package/lib/components/core.d.ts +0 -102
- package/lib/components/core.js +0 -79
- package/lib/components/dynamodb/dynamo-db-data-store.d.ts +0 -33
- package/lib/components/dynamodb/dynamo-db-data-store.js +0 -107
- package/lib/components/event-bridge/data-event-bus.d.ts +0 -19
- package/lib/components/event-bridge/data-event-bus.js +0 -34
- package/lib/components/event-bridge/ops-event-bus.d.ts +0 -19
- package/lib/components/event-bridge/ops-event-bus.js +0 -34
- package/lib/components/global.d.ts +0 -36
- package/lib/components/global.js +0 -63
- package/lib/components/index.d.ts +0 -1
- package/lib/components/index.js +0 -18
- package/lib/components/route-53/child-hosted-zone.d.ts +0 -20
- package/lib/components/route-53/child-hosted-zone.js +0 -48
- package/lib/components/route-53/root-hosted-zone.d.ts +0 -10
- package/lib/components/route-53/root-hosted-zone.js +0 -20
- package/lib/components/ssm/discoverable-string-parameter.d.ts +0 -59
- package/lib/components/ssm/discoverable-string-parameter.js +0 -50
- package/lib/components/ssm/index.d.ts +0 -1
- package/lib/components/ssm/index.js +0 -18
- package/lib/data/dynamo/ehr/r4/Patient.d.ts +0 -180
- package/lib/data/dynamo/ehr/r4/Patient.js +0 -192
- package/lib/data/dynamo/ehr/r4/ehr-r4-data-service.d.ts +0 -162
- package/lib/data/dynamo/ehr/r4/ehr-r4-data-service.js +0 -37
- package/lib/data/hello-world.d.ts +0 -39
- package/lib/data/hello-world.js +0 -59
- package/lib/data/import-patient-with-dynalite.d.ts +0 -1
- package/lib/data/import-patient-with-dynalite.js +0 -87
- package/lib/data/import-patient.d.ts +0 -47
- package/lib/data/import-patient.js +0 -158
- package/lib/data/lambda/rest-api-lambda.d.ts +0 -13
- package/lib/data/lambda/rest-api-lambda.handler.d.ts +0 -1
- package/lib/data/lambda/rest-api-lambda.handler.js +0 -10
- package/lib/data/lambda/rest-api-lambda.js +0 -22
- package/lib/data/middleware/open-hi-context.d.ts +0 -13
- package/lib/data/middleware/open-hi-context.js +0 -31
- package/lib/data/rest-api/ehr/r4/Patient.d.ts +0 -16
- package/lib/data/rest-api/ehr/r4/Patient.js +0 -234
- package/lib/data/rest-api/rest-api-local.d.ts +0 -1
- package/lib/data/rest-api/rest-api-local.js +0 -8
- package/lib/data/rest-api/rest-api-mockdata.d.ts +0 -7
- package/lib/data/rest-api/rest-api-mockdata.js +0 -585
- package/lib/data/rest-api/rest-api.d.ts +0 -3
- package/lib/data/rest-api/rest-api.js +0 -26
- package/lib/lib/compression.d.ts +0 -27
- package/lib/lib/compression.js +0 -87
- package/lib/services/index.d.ts +0 -5
- package/lib/services/index.js +0 -22
- package/lib/services/open-hi-auth-service.d.ts +0 -31
- package/lib/services/open-hi-auth-service.js +0 -31
- package/lib/services/open-hi-core-service.d.ts +0 -15
- package/lib/services/open-hi-core-service.js +0 -38
- package/lib/services/open-hi-data-service.d.ts +0 -18
- package/lib/services/open-hi-data-service.js +0 -18
- package/lib/services/open-hi-global-service.d.ts +0 -15
- package/lib/services/open-hi-global-service.js +0 -44
- package/lib/services/open-hi-rest-api-service.d.ts +0 -17
- package/lib/services/open-hi-rest-api-service.js +0 -107
package/lib/index.mjs
ADDED
|
@@ -0,0 +1,1120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__commonJS,
|
|
3
|
+
__toESM
|
|
4
|
+
} from "./chunk-LZOMFHX3.mjs";
|
|
5
|
+
|
|
6
|
+
// ../config/lib/open-hi-config.js
|
|
7
|
+
var require_open_hi_config = __commonJS({
|
|
8
|
+
"../config/lib/open-hi-config.js"(exports) {
|
|
9
|
+
"use strict";
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.OPEN_HI_DEPLOYMENT_TARGET_ROLE = exports.OPEN_HI_STAGE = void 0;
|
|
12
|
+
exports.OPEN_HI_STAGE = {
|
|
13
|
+
/**
|
|
14
|
+
* Development environment, typically used for testing and development.
|
|
15
|
+
*/
|
|
16
|
+
DEV: "dev",
|
|
17
|
+
/**
|
|
18
|
+
* Staging environment, used for pre-production testing.
|
|
19
|
+
*/
|
|
20
|
+
STAGE: "stage",
|
|
21
|
+
/**
|
|
22
|
+
* Production environment, used for live deployments.
|
|
23
|
+
*/
|
|
24
|
+
PROD: "prod"
|
|
25
|
+
};
|
|
26
|
+
exports.OPEN_HI_DEPLOYMENT_TARGET_ROLE = {
|
|
27
|
+
/**
|
|
28
|
+
* The primary deployment target for this stage (main account/region).
|
|
29
|
+
* For example, the base DynamoDB region for global tables.
|
|
30
|
+
*/
|
|
31
|
+
PRIMARY: "primary",
|
|
32
|
+
/**
|
|
33
|
+
* A secondary deployment target for this stage (additional account/region).
|
|
34
|
+
* For example, a replica region for a global DynamoDB table, or another cell in the same region.
|
|
35
|
+
*/
|
|
36
|
+
SECONDARY: "secondary"
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// ../config/lib/index.js
|
|
42
|
+
var require_lib = __commonJS({
|
|
43
|
+
"../config/lib/index.js"(exports) {
|
|
44
|
+
"use strict";
|
|
45
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
46
|
+
if (k2 === void 0) k2 = k;
|
|
47
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
48
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
49
|
+
desc = { enumerable: true, get: function() {
|
|
50
|
+
return m[k];
|
|
51
|
+
} };
|
|
52
|
+
}
|
|
53
|
+
Object.defineProperty(o, k2, desc);
|
|
54
|
+
}) : (function(o, m, k, k2) {
|
|
55
|
+
if (k2 === void 0) k2 = k;
|
|
56
|
+
o[k2] = m[k];
|
|
57
|
+
}));
|
|
58
|
+
var __exportStar = exports && exports.__exportStar || function(m, exports2) {
|
|
59
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
|
|
60
|
+
};
|
|
61
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
62
|
+
__exportStar(require_open_hi_config(), exports);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// src/app/open-hi-app.ts
|
|
67
|
+
var import_config2 = __toESM(require_lib());
|
|
68
|
+
import { App } from "aws-cdk-lib";
|
|
69
|
+
|
|
70
|
+
// src/app/open-hi-environment.ts
|
|
71
|
+
var import_config = __toESM(require_lib());
|
|
72
|
+
import { Stage } from "aws-cdk-lib";
|
|
73
|
+
var OPEN_HI_ENVIRONMENT_SYMBOL = /* @__PURE__ */ Symbol.for(
|
|
74
|
+
"@openhi/constructs/core.OpenHiEnvironment"
|
|
75
|
+
);
|
|
76
|
+
var OpenHiEnvironment = class _OpenHiEnvironment extends Stage {
|
|
77
|
+
/**
|
|
78
|
+
* Creates a new OpenHiEnvironment.
|
|
79
|
+
*/
|
|
80
|
+
constructor(ohStage, props) {
|
|
81
|
+
if (props.config.account && props.config.region) {
|
|
82
|
+
props = {
|
|
83
|
+
...props,
|
|
84
|
+
env: {
|
|
85
|
+
account: props.config.account,
|
|
86
|
+
region: props.config.region
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const stageName = props.deploymentTargetRole === import_config.OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY ? props.deploymentTargetRole : [props.deploymentTargetRole, ohStage.environments.length].join("-");
|
|
91
|
+
super(ohStage, stageName, {
|
|
92
|
+
env: props.env ?? ohStage.props.env,
|
|
93
|
+
...props
|
|
94
|
+
});
|
|
95
|
+
this.ohStage = ohStage;
|
|
96
|
+
this.props = props;
|
|
97
|
+
Object.defineProperty(this, OPEN_HI_ENVIRONMENT_SYMBOL, { value: true });
|
|
98
|
+
this.deploymentTargetRole = props.deploymentTargetRole;
|
|
99
|
+
this.config = props.config;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Finds the OpenHiEnvironment that contains the given construct.
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
static of(construct) {
|
|
106
|
+
return construct.node.scopes.reverse().find(_OpenHiEnvironment.isOpenHiEnvironment);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Type guard to check if a value is an OpenHiEnvironment instance.
|
|
110
|
+
*/
|
|
111
|
+
static isOpenHiEnvironment(x) {
|
|
112
|
+
return x !== null && typeof x === "object" && OPEN_HI_ENVIRONMENT_SYMBOL in x;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// src/app/open-hi-stage.ts
|
|
117
|
+
import { Stage as Stage2 } from "aws-cdk-lib";
|
|
118
|
+
var OPEN_HI_STAGE_SYMBOL = /* @__PURE__ */ Symbol.for("@openhi/constructs/core.OpenHiStage");
|
|
119
|
+
var OpenHiStage = class _OpenHiStage extends Stage2 {
|
|
120
|
+
/**
|
|
121
|
+
* Creates a new OpenHiStage instance.
|
|
122
|
+
*/
|
|
123
|
+
constructor(ohApp, props) {
|
|
124
|
+
super(ohApp, props.stageType, props);
|
|
125
|
+
this.ohApp = ohApp;
|
|
126
|
+
this.props = props;
|
|
127
|
+
Object.defineProperty(this, OPEN_HI_STAGE_SYMBOL, { value: true });
|
|
128
|
+
this.stageType = props.stageType;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Finds the OpenHiStage that contains the given construct.
|
|
132
|
+
*/
|
|
133
|
+
static of(construct) {
|
|
134
|
+
return construct.node.scopes.reverse().find(_OpenHiStage.isOpenHiStage);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Type guard to check if a value is an OpenHiStage instance.
|
|
138
|
+
*/
|
|
139
|
+
static isOpenHiStage(x) {
|
|
140
|
+
return x !== null && typeof x === "object" && OPEN_HI_STAGE_SYMBOL in x;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Gets all OpenHiEnvironment instances contained within this stage.
|
|
144
|
+
*/
|
|
145
|
+
get environments() {
|
|
146
|
+
return this.node.children.filter(OpenHiEnvironment.isOpenHiEnvironment);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Gets the primary OpenHiEnvironment for this stage, if one exists.
|
|
150
|
+
*/
|
|
151
|
+
get primaryEnvironment() {
|
|
152
|
+
return this.environments.find(
|
|
153
|
+
(env) => env.deploymentTargetRole === "primary"
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Gets all secondary OpenHiEnvironment instances for this stage.
|
|
158
|
+
*/
|
|
159
|
+
get secondaryEnvironments() {
|
|
160
|
+
return this.environments.filter(
|
|
161
|
+
(env) => env.deploymentTargetRole === "secondary"
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// src/app/open-hi-app.ts
|
|
167
|
+
var OPEN_HI_APP_SYMBOL = /* @__PURE__ */ Symbol.for("@openhi/constructs/core.OpenHiApp");
|
|
168
|
+
var OpenHiApp = class _OpenHiApp extends App {
|
|
169
|
+
/**
|
|
170
|
+
* Finds the OpenHiApp instance that contains the given construct in its
|
|
171
|
+
* construct tree.
|
|
172
|
+
*/
|
|
173
|
+
static of(construct) {
|
|
174
|
+
return construct.node.scopes.reverse().find(_OpenHiApp.isOpenHiApp);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Type guard that checks if a value is an OpenHiApp instance.
|
|
178
|
+
*/
|
|
179
|
+
static isOpenHiApp(x) {
|
|
180
|
+
return x !== null && typeof x === "object" && OPEN_HI_APP_SYMBOL in x;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Creates a new OpenHiApp instance.
|
|
184
|
+
*/
|
|
185
|
+
constructor(props) {
|
|
186
|
+
super(props);
|
|
187
|
+
Object.defineProperty(this, OPEN_HI_APP_SYMBOL, { value: true });
|
|
188
|
+
this.appName = props.appName ?? "openhi";
|
|
189
|
+
this.config = props.config;
|
|
190
|
+
Object.values(import_config2.OPEN_HI_STAGE).forEach((stageType) => {
|
|
191
|
+
if (this.config.deploymentTargets?.[stageType]) {
|
|
192
|
+
const stage = new OpenHiStage(this, { stageType });
|
|
193
|
+
if (this.config.deploymentTargets?.[stageType]?.[import_config2.OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]) {
|
|
194
|
+
const envConfig = this.config.deploymentTargets[stageType][import_config2.OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY];
|
|
195
|
+
new OpenHiEnvironment(stage, {
|
|
196
|
+
deploymentTargetRole: import_config2.OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY,
|
|
197
|
+
config: envConfig,
|
|
198
|
+
env: { account: envConfig.account, region: envConfig.region }
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
if (this.config.deploymentTargets?.[stageType]?.[import_config2.OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]) {
|
|
202
|
+
this.config.deploymentTargets[stageType][import_config2.OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY].forEach((envConfig) => {
|
|
203
|
+
new OpenHiEnvironment(stage, {
|
|
204
|
+
deploymentTargetRole: import_config2.OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY,
|
|
205
|
+
config: envConfig,
|
|
206
|
+
env: { account: envConfig.account, region: envConfig.region }
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/*****************************************************************************
|
|
214
|
+
*
|
|
215
|
+
* Stages
|
|
216
|
+
*
|
|
217
|
+
****************************************************************************/
|
|
218
|
+
/**
|
|
219
|
+
* Gets all OpenHiStage instances that are direct children of this app.
|
|
220
|
+
|
|
221
|
+
*/
|
|
222
|
+
get stages() {
|
|
223
|
+
return this.node.children.filter(OpenHiStage.isOpenHiStage);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Gets the development stage, if it exists.
|
|
227
|
+
*/
|
|
228
|
+
get devStage() {
|
|
229
|
+
return this.stages.find((stage) => stage.stageType === import_config2.OPEN_HI_STAGE.DEV);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Gets the staging stage, if it exists.
|
|
233
|
+
*/
|
|
234
|
+
get stageStage() {
|
|
235
|
+
return this.stages.find((stage) => stage.stageType === import_config2.OPEN_HI_STAGE.STAGE);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Gets the production stage, if it exists.
|
|
239
|
+
*/
|
|
240
|
+
get prodStage() {
|
|
241
|
+
return this.stages.find((stage) => stage.stageType === import_config2.OPEN_HI_STAGE.PROD);
|
|
242
|
+
}
|
|
243
|
+
/*****************************************************************************
|
|
244
|
+
*
|
|
245
|
+
* Environments
|
|
246
|
+
*
|
|
247
|
+
****************************************************************************/
|
|
248
|
+
/**
|
|
249
|
+
* Gets all OpenHiEnvironment instances across all stages in this app.
|
|
250
|
+
*/
|
|
251
|
+
get environments() {
|
|
252
|
+
return this.stages.flatMap((stage) => stage.environments);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Gets all primary environments across all stages in this app.
|
|
256
|
+
*/
|
|
257
|
+
get primaryEnvironments() {
|
|
258
|
+
return this.environments.filter(
|
|
259
|
+
(env) => env.deploymentTargetRole === "primary"
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Gets all secondary environments across all stages in this app.
|
|
264
|
+
*/
|
|
265
|
+
get secondaryEnvironments() {
|
|
266
|
+
return this.environments.filter(
|
|
267
|
+
(env) => env.deploymentTargetRole === "secondary"
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// src/app/open-hi-service.ts
|
|
273
|
+
var import_config3 = __toESM(require_lib());
|
|
274
|
+
import {
|
|
275
|
+
findGitBranch,
|
|
276
|
+
findGitRepoName,
|
|
277
|
+
hashString
|
|
278
|
+
} from "@codedrifters/utils";
|
|
279
|
+
import { RemovalPolicy, Stack, Tags } from "aws-cdk-lib";
|
|
280
|
+
import { paramCase } from "change-case";
|
|
281
|
+
var OPEN_HI_SERVICE_TYPE = {
|
|
282
|
+
/**
|
|
283
|
+
* Authentication service.
|
|
284
|
+
* *
|
|
285
|
+
* Only one instance of the auth service should exist per environment.
|
|
286
|
+
*/
|
|
287
|
+
AUTH: "auth",
|
|
288
|
+
/**
|
|
289
|
+
* Root shared core services.
|
|
290
|
+
*
|
|
291
|
+
* Only one instance of the core service should exist per environment.
|
|
292
|
+
*/
|
|
293
|
+
CORE: "core",
|
|
294
|
+
/**
|
|
295
|
+
* Rest API service.
|
|
296
|
+
*/
|
|
297
|
+
REST_API: "rest-api",
|
|
298
|
+
/**
|
|
299
|
+
* Global Infrastructure stack (Route53, ACM).
|
|
300
|
+
*/
|
|
301
|
+
GLOBAL: "global",
|
|
302
|
+
/**
|
|
303
|
+
* Data service (DynamoDB, S3, persistence).
|
|
304
|
+
*/
|
|
305
|
+
DATA: "data"
|
|
306
|
+
};
|
|
307
|
+
var OpenHiService = class extends Stack {
|
|
308
|
+
/**
|
|
309
|
+
* Core construct containing shared infrastructure.
|
|
310
|
+
*/
|
|
311
|
+
// public core: Core;
|
|
312
|
+
/**
|
|
313
|
+
* Creates a new OpenHI service stack.
|
|
314
|
+
*
|
|
315
|
+
* @param ohEnv - The OpenHI environment (stage) this service belongs to
|
|
316
|
+
* @param id - Unique identifier for this service stack (e.g., "user-service")
|
|
317
|
+
* @param props - Optional properties for configuring the service
|
|
318
|
+
*
|
|
319
|
+
* @throws {Error} If account and region are not defined in props or environment
|
|
320
|
+
*
|
|
321
|
+
*/
|
|
322
|
+
constructor(ohEnv, id, props = {}) {
|
|
323
|
+
const { account, region } = props.env || ohEnv;
|
|
324
|
+
if (!account || !region) {
|
|
325
|
+
throw new Error(
|
|
326
|
+
"Account and region must be defined in OpenHiServiceProps or OpenHiEnvironment"
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
const appName = props.appName ?? ohEnv.ohStage.ohApp.appName ?? "openhi";
|
|
330
|
+
const repoName = props.repoName ?? findGitRepoName();
|
|
331
|
+
const defaultReleaseBranch = props.defaultReleaseBranch ?? "main";
|
|
332
|
+
const branchName = props.branchName ?? (process.env.JEST_WORKER_ID ? "test-branch" : ohEnv.ohStage.stageType === import_config3.OPEN_HI_STAGE.DEV ? findGitBranch() : defaultReleaseBranch);
|
|
333
|
+
const environmentHash = hashString(
|
|
334
|
+
[appName, ohEnv.deploymentTargetRole, account, region].join("-"),
|
|
335
|
+
6
|
|
336
|
+
);
|
|
337
|
+
const branchHash = hashString(
|
|
338
|
+
[appName, ohEnv.deploymentTargetRole, account, region, branchName].join(
|
|
339
|
+
"-"
|
|
340
|
+
),
|
|
341
|
+
6
|
|
342
|
+
);
|
|
343
|
+
const stackHash = hashString(
|
|
344
|
+
[
|
|
345
|
+
appName,
|
|
346
|
+
ohEnv.deploymentTargetRole,
|
|
347
|
+
account,
|
|
348
|
+
region,
|
|
349
|
+
branchName,
|
|
350
|
+
id
|
|
351
|
+
].join("-"),
|
|
352
|
+
6
|
|
353
|
+
);
|
|
354
|
+
const removalPolicy = props.removalPolicy ?? (ohEnv.ohStage.stageType === import_config3.OPEN_HI_STAGE.PROD ? RemovalPolicy.RETAIN : RemovalPolicy.DESTROY);
|
|
355
|
+
Object.assign(props, { removalPolicy });
|
|
356
|
+
const description = `OpenHi Service: ${id} [${branchName}] - ${branchHash}`;
|
|
357
|
+
const hostedZoneId = ohEnv.props.config.hostedZoneId;
|
|
358
|
+
const zoneName = ohEnv.props.config.zoneName;
|
|
359
|
+
if (hostedZoneId && zoneName) {
|
|
360
|
+
props = {
|
|
361
|
+
...props,
|
|
362
|
+
coreProps: {
|
|
363
|
+
...props.coreProps
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
super(ohEnv, [branchHash, id, account, region].join("-"), {
|
|
368
|
+
...props,
|
|
369
|
+
description
|
|
370
|
+
});
|
|
371
|
+
this.ohEnv = ohEnv;
|
|
372
|
+
this.props = props;
|
|
373
|
+
this.serviceId = id;
|
|
374
|
+
this.removalPolicy = removalPolicy;
|
|
375
|
+
this.config = props.config ?? ohEnv.props.config;
|
|
376
|
+
this.serviceType = props.serviceType ?? id;
|
|
377
|
+
this.deploymentTargetRole = ohEnv.deploymentTargetRole;
|
|
378
|
+
this.repoName = repoName;
|
|
379
|
+
this.appName = appName;
|
|
380
|
+
this.defaultReleaseBranch = defaultReleaseBranch;
|
|
381
|
+
this.branchName = branchName;
|
|
382
|
+
this.environmentHash = environmentHash;
|
|
383
|
+
this.branchHash = branchHash;
|
|
384
|
+
this.stackHash = stackHash;
|
|
385
|
+
Tags.of(this).add(`${appName}:repo-name`, repoName.slice(0, 255));
|
|
386
|
+
Tags.of(this).add(`${appName}:branch-name`, branchName.slice(0, 255));
|
|
387
|
+
Tags.of(this).add(
|
|
388
|
+
`${appName}:service-type`,
|
|
389
|
+
this.serviceType.slice(0, 255)
|
|
390
|
+
);
|
|
391
|
+
Tags.of(this).add(
|
|
392
|
+
`${appName}:stage-type`,
|
|
393
|
+
ohEnv.ohStage.stageType.slice(0, 255)
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Creates or returns the core construct for shared infrastructure.
|
|
398
|
+
*/
|
|
399
|
+
/*
|
|
400
|
+
protected createCore(props: OpenHiServiceProps = {}): Core {
|
|
401
|
+
if (!this.core) {
|
|
402
|
+
return new Core(this, props.coreProps);
|
|
403
|
+
}
|
|
404
|
+
return this.core;
|
|
405
|
+
}
|
|
406
|
+
*/
|
|
407
|
+
/**
|
|
408
|
+
* DNS prefix for this branche's child zone.
|
|
409
|
+
*/
|
|
410
|
+
get childZonePrefix() {
|
|
411
|
+
return paramCase(this.branchName).slice(0, 200);
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
// src/components/ssm/discoverable-string-parameter.ts
|
|
416
|
+
import { Tags as Tags2 } from "aws-cdk-lib";
|
|
417
|
+
import {
|
|
418
|
+
StringParameter
|
|
419
|
+
} from "aws-cdk-lib/aws-ssm";
|
|
420
|
+
var DiscoverableStringParameter = class _DiscoverableStringParameter extends StringParameter {
|
|
421
|
+
/**
|
|
422
|
+
* Build a param name based on predictable attributes found in services and
|
|
423
|
+
* constructs. Used for storage and retrieval of SSM values across services.
|
|
424
|
+
*/
|
|
425
|
+
static buildParameterName(scope, props) {
|
|
426
|
+
const stack = OpenHiService.of(scope);
|
|
427
|
+
return "/" + [
|
|
428
|
+
props.branchHash ?? stack.branchHash,
|
|
429
|
+
props.serviceType ?? stack.serviceType,
|
|
430
|
+
props.account ?? stack.account,
|
|
431
|
+
props.region ?? stack.region,
|
|
432
|
+
props.ssmParamName
|
|
433
|
+
].join("/").toUpperCase();
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Read the string value of an SSM parameter created with DiscoverableStringParameter,
|
|
437
|
+
* using props that include ssmParamName and optional overrides (e.g. serviceType).
|
|
438
|
+
*/
|
|
439
|
+
static valueForLookupName(scope, props) {
|
|
440
|
+
const paramName = _DiscoverableStringParameter.buildParameterName(
|
|
441
|
+
scope,
|
|
442
|
+
props
|
|
443
|
+
);
|
|
444
|
+
return StringParameter.valueForStringParameter(scope, paramName);
|
|
445
|
+
}
|
|
446
|
+
constructor(scope, id, props) {
|
|
447
|
+
const { ssmParamName, branchHash, serviceType, account, region, ...rest } = props;
|
|
448
|
+
const parameterName = _DiscoverableStringParameter.buildParameterName(
|
|
449
|
+
scope,
|
|
450
|
+
props
|
|
451
|
+
);
|
|
452
|
+
super(scope, id, {
|
|
453
|
+
...rest,
|
|
454
|
+
parameterName
|
|
455
|
+
});
|
|
456
|
+
const { appName } = OpenHiService.of(scope);
|
|
457
|
+
Tags2.of(this).add(`${appName}:param-name`, ssmParamName);
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
// src/services/open-hi-core-service.ts
|
|
462
|
+
import { Code, Function, Runtime } from "aws-cdk-lib/aws-lambda";
|
|
463
|
+
var OpenHiCoreService = class extends OpenHiService {
|
|
464
|
+
constructor(ohEnv, props = {}) {
|
|
465
|
+
props = {
|
|
466
|
+
...props
|
|
467
|
+
};
|
|
468
|
+
super(ohEnv, OPEN_HI_SERVICE_TYPE.CORE, props);
|
|
469
|
+
this.props = props;
|
|
470
|
+
new Function(this, "test-fn", {
|
|
471
|
+
runtime: Runtime.NODEJS_LATEST,
|
|
472
|
+
handler: "index.handler",
|
|
473
|
+
code: Code.fromInline(
|
|
474
|
+
'exports.handler = async () => { return {statusCode:200, body:"ok"} }'
|
|
475
|
+
)
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
// src/components/auth.ts
|
|
481
|
+
import { Construct } from "constructs";
|
|
482
|
+
|
|
483
|
+
// src/components/cognito/core-user-pool.ts
|
|
484
|
+
import {
|
|
485
|
+
UserPool,
|
|
486
|
+
VerificationEmailStyle
|
|
487
|
+
} from "aws-cdk-lib/aws-cognito";
|
|
488
|
+
var _CoreUserPool = class _CoreUserPool extends UserPool {
|
|
489
|
+
static fromConstruct(scope) {
|
|
490
|
+
const userPoolId = DiscoverableStringParameter.valueForLookupName(scope, {
|
|
491
|
+
ssmParamName: _CoreUserPool.SSM_PARAM_NAME,
|
|
492
|
+
serviceType: OPEN_HI_SERVICE_TYPE.AUTH
|
|
493
|
+
});
|
|
494
|
+
return UserPool.fromUserPoolId(scope, "user-pool", userPoolId);
|
|
495
|
+
}
|
|
496
|
+
constructor(scope, props = {}) {
|
|
497
|
+
const service = OpenHiService.of(scope);
|
|
498
|
+
super(scope, "user-pool", {
|
|
499
|
+
/**
|
|
500
|
+
* Defaults
|
|
501
|
+
*/
|
|
502
|
+
selfSignUpEnabled: true,
|
|
503
|
+
signInAliases: {
|
|
504
|
+
email: true
|
|
505
|
+
},
|
|
506
|
+
userVerification: {
|
|
507
|
+
emailSubject: "Verify your email!",
|
|
508
|
+
emailBody: "Your verification code is {####}.",
|
|
509
|
+
emailStyle: VerificationEmailStyle.CODE
|
|
510
|
+
},
|
|
511
|
+
removalPolicy: props.removalPolicy ?? service.removalPolicy,
|
|
512
|
+
/**
|
|
513
|
+
* Over-rideable props
|
|
514
|
+
*/
|
|
515
|
+
...props,
|
|
516
|
+
/**
|
|
517
|
+
* Required
|
|
518
|
+
*/
|
|
519
|
+
userPoolName: ["core", "user", "pool", service.branchHash].join("-")
|
|
520
|
+
});
|
|
521
|
+
new DiscoverableStringParameter(this, "user-pool-param", {
|
|
522
|
+
ssmParamName: _CoreUserPool.SSM_PARAM_NAME,
|
|
523
|
+
stringValue: this.userPoolId
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
/**
|
|
528
|
+
* Used when storing the User Pool ID in SSM.
|
|
529
|
+
*/
|
|
530
|
+
_CoreUserPool.SSM_PARAM_NAME = "CORE_USER_POOL";
|
|
531
|
+
var CoreUserPool = _CoreUserPool;
|
|
532
|
+
|
|
533
|
+
// src/components/cognito/core-user-pool-client.ts
|
|
534
|
+
import {
|
|
535
|
+
UserPoolClient
|
|
536
|
+
} from "aws-cdk-lib/aws-cognito";
|
|
537
|
+
var _CoreUserPoolClient = class _CoreUserPoolClient extends UserPoolClient {
|
|
538
|
+
static fromConstruct(scope) {
|
|
539
|
+
const userPoolClientId = DiscoverableStringParameter.valueForLookupName(
|
|
540
|
+
scope,
|
|
541
|
+
{
|
|
542
|
+
ssmParamName: _CoreUserPoolClient.SSM_PARAM_NAME,
|
|
543
|
+
serviceType: OPEN_HI_SERVICE_TYPE.AUTH
|
|
544
|
+
}
|
|
545
|
+
);
|
|
546
|
+
return UserPoolClient.fromUserPoolClientId(
|
|
547
|
+
scope,
|
|
548
|
+
"user-pool-client",
|
|
549
|
+
userPoolClientId
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
constructor(scope, props) {
|
|
553
|
+
super(scope, "user-pool-client", {
|
|
554
|
+
/**
|
|
555
|
+
* Defaults
|
|
556
|
+
*/
|
|
557
|
+
generateSecret: false,
|
|
558
|
+
oAuth: {
|
|
559
|
+
flows: {
|
|
560
|
+
authorizationCodeGrant: true,
|
|
561
|
+
implicitCodeGrant: true
|
|
562
|
+
},
|
|
563
|
+
callbackUrls: [`https://localhost:3000/oauth/callback`]
|
|
564
|
+
},
|
|
565
|
+
/**
|
|
566
|
+
* Overrideable props
|
|
567
|
+
*/
|
|
568
|
+
...props
|
|
569
|
+
});
|
|
570
|
+
new DiscoverableStringParameter(this, "user-pool-client-param", {
|
|
571
|
+
ssmParamName: _CoreUserPoolClient.SSM_PARAM_NAME,
|
|
572
|
+
stringValue: this.userPoolClientId
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
/**
|
|
577
|
+
* Used when storing the User Pool Client ID in SSM.
|
|
578
|
+
*/
|
|
579
|
+
_CoreUserPoolClient.SSM_PARAM_NAME = "CORE_USER_POOL_CLIENT";
|
|
580
|
+
var CoreUserPoolClient = _CoreUserPoolClient;
|
|
581
|
+
|
|
582
|
+
// src/components/cognito/core-user-pool-domain.ts
|
|
583
|
+
import {
|
|
584
|
+
UserPoolDomain
|
|
585
|
+
} from "aws-cdk-lib/aws-cognito";
|
|
586
|
+
var _CoreUserPoolDomain = class _CoreUserPoolDomain extends UserPoolDomain {
|
|
587
|
+
static fromConstruct(scope) {
|
|
588
|
+
const userPoolDomain = DiscoverableStringParameter.valueForLookupName(
|
|
589
|
+
scope,
|
|
590
|
+
{
|
|
591
|
+
ssmParamName: _CoreUserPoolDomain.SSM_PARAM_NAME,
|
|
592
|
+
serviceType: OPEN_HI_SERVICE_TYPE.AUTH
|
|
593
|
+
}
|
|
594
|
+
);
|
|
595
|
+
return UserPoolDomain.fromDomainName(
|
|
596
|
+
scope,
|
|
597
|
+
"user-pool-domain",
|
|
598
|
+
userPoolDomain
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
constructor(scope, props) {
|
|
602
|
+
const id = props.cognitoDomain?.domainPrefix ? "cognito-domain" : "custom-domain";
|
|
603
|
+
super(scope, id, {
|
|
604
|
+
...props
|
|
605
|
+
});
|
|
606
|
+
new DiscoverableStringParameter(this, "user-pool-domain-param", {
|
|
607
|
+
ssmParamName: _CoreUserPoolDomain.SSM_PARAM_NAME,
|
|
608
|
+
stringValue: this.domainName
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
/**
|
|
613
|
+
* Used when storing the User Pool Domain in SSM.
|
|
614
|
+
*/
|
|
615
|
+
_CoreUserPoolDomain.SSM_PARAM_NAME = "CORE_USER_POOL_DOMAIN";
|
|
616
|
+
var CoreUserPoolDomain = _CoreUserPoolDomain;
|
|
617
|
+
|
|
618
|
+
// src/components/cognito/core-user-pool-kms-key.ts
|
|
619
|
+
import { Key } from "aws-cdk-lib/aws-kms";
|
|
620
|
+
var _CoreUserPoolKmsKey = class _CoreUserPoolKmsKey extends Key {
|
|
621
|
+
static fromConstruct(scope) {
|
|
622
|
+
const keyArn = DiscoverableStringParameter.valueForLookupName(scope, {
|
|
623
|
+
ssmParamName: _CoreUserPoolKmsKey.SSM_PARAM_NAME,
|
|
624
|
+
serviceType: OPEN_HI_SERVICE_TYPE.AUTH
|
|
625
|
+
});
|
|
626
|
+
return Key.fromKeyArn(scope, "kms-key", keyArn);
|
|
627
|
+
}
|
|
628
|
+
constructor(scope, props = {}) {
|
|
629
|
+
const service = OpenHiService.of(scope);
|
|
630
|
+
super(scope, "kms-key", {
|
|
631
|
+
...props,
|
|
632
|
+
// alias: ["alias", "cognito", service.branchHash].join("/"),
|
|
633
|
+
description: `KMS Key for Cognito User Pool - ${service.branchHash}`,
|
|
634
|
+
removalPolicy: props.removalPolicy ?? service.removalPolicy
|
|
635
|
+
});
|
|
636
|
+
new DiscoverableStringParameter(this, "kms-key-param", {
|
|
637
|
+
ssmParamName: _CoreUserPoolKmsKey.SSM_PARAM_NAME,
|
|
638
|
+
stringValue: this.keyArn
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
/**
|
|
643
|
+
* Used when storing the KMS Key in SSM.
|
|
644
|
+
*/
|
|
645
|
+
_CoreUserPoolKmsKey.SSM_PARAM_NAME = "CORE_USER_POOL_KMS_KEY";
|
|
646
|
+
var CoreUserPoolKmsKey = _CoreUserPoolKmsKey;
|
|
647
|
+
|
|
648
|
+
// src/components/auth.ts
|
|
649
|
+
var Auth = class _Auth extends Construct {
|
|
650
|
+
/**
|
|
651
|
+
* Returns an Auth instance that uses resources imported from AUTH SSM
|
|
652
|
+
* parameters. Use this when creating Core or other stacks that consume
|
|
653
|
+
* auth resources; the Auth stack must be deployed first.
|
|
654
|
+
*
|
|
655
|
+
* @param scope - Construct scope (e.g. Core); must be in a stack that has
|
|
656
|
+
* access to the same account/region as the deployed Auth stack.
|
|
657
|
+
*/
|
|
658
|
+
static fromConstruct(scope) {
|
|
659
|
+
return new _Auth(scope, {});
|
|
660
|
+
}
|
|
661
|
+
constructor(scope, props = {}) {
|
|
662
|
+
super(scope, "auth");
|
|
663
|
+
const service = OpenHiService.of(this);
|
|
664
|
+
this.isAuthService = service.serviceType === OPEN_HI_SERVICE_TYPE.AUTH;
|
|
665
|
+
this.userPoolKmsKey = this.createUserPoolKmsKey();
|
|
666
|
+
this.userPool = this.createUserPool({
|
|
667
|
+
...props.userPoolProps,
|
|
668
|
+
customSenderKmsKey: this.userPoolKmsKey
|
|
669
|
+
});
|
|
670
|
+
this.userPoolClient = this.createUserPoolClient({
|
|
671
|
+
userPool: this.userPool
|
|
672
|
+
});
|
|
673
|
+
this.userPoolDomain = this.createUserPoolDomain({
|
|
674
|
+
userPool: this.userPool
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
/*****************************************************************************
|
|
678
|
+
*
|
|
679
|
+
* Auth Support
|
|
680
|
+
*
|
|
681
|
+
****************************************************************************/
|
|
682
|
+
createUserPoolKmsKey() {
|
|
683
|
+
return this.isAuthService ? new CoreUserPoolKmsKey(this) : CoreUserPoolKmsKey.fromConstruct(this);
|
|
684
|
+
}
|
|
685
|
+
createUserPool(props) {
|
|
686
|
+
return this.isAuthService ? new CoreUserPool(this, props) : CoreUserPool.fromConstruct(this);
|
|
687
|
+
}
|
|
688
|
+
createUserPoolClient(props) {
|
|
689
|
+
return this.isAuthService ? new CoreUserPoolClient(this, { userPool: props.userPool }) : CoreUserPoolClient.fromConstruct(this);
|
|
690
|
+
}
|
|
691
|
+
createUserPoolDomain(props) {
|
|
692
|
+
const service = OpenHiService.of(this);
|
|
693
|
+
return this.isAuthService ? new CoreUserPoolDomain(this, {
|
|
694
|
+
userPool: props.userPool,
|
|
695
|
+
cognitoDomain: {
|
|
696
|
+
domainPrefix: `auth-${service.branchHash}`
|
|
697
|
+
}
|
|
698
|
+
}) : CoreUserPoolDomain.fromConstruct(this);
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// src/services/open-hi-auth-service.ts
|
|
703
|
+
var OpenHiAuthService = class extends OpenHiService {
|
|
704
|
+
constructor(ohEnv, props = {}) {
|
|
705
|
+
super(ohEnv, OPEN_HI_SERVICE_TYPE.AUTH, props);
|
|
706
|
+
this.props = props;
|
|
707
|
+
this.auth = new Auth(this, props.authProps);
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
|
|
711
|
+
// src/components/global.ts
|
|
712
|
+
import {
|
|
713
|
+
CertificateValidation
|
|
714
|
+
} from "aws-cdk-lib/aws-certificatemanager";
|
|
715
|
+
import { Construct as Construct3 } from "constructs";
|
|
716
|
+
|
|
717
|
+
// src/components/acm/root-wildcard-certificate.ts
|
|
718
|
+
import {
|
|
719
|
+
Certificate
|
|
720
|
+
} from "aws-cdk-lib/aws-certificatemanager";
|
|
721
|
+
import { StringParameter as StringParameter2 } from "aws-cdk-lib/aws-ssm";
|
|
722
|
+
var _RootWildcardCertificate = class _RootWildcardCertificate extends Certificate {
|
|
723
|
+
/**
|
|
724
|
+
* Using a special name here since this will be shared and used among many
|
|
725
|
+
* stacks and services.
|
|
726
|
+
*/
|
|
727
|
+
static ssmParameterName() {
|
|
728
|
+
return "/" + ["GLOBAL", _RootWildcardCertificate.SSM_PARAM_NAME].join("/").toUpperCase();
|
|
729
|
+
}
|
|
730
|
+
static fromConstruct(scope) {
|
|
731
|
+
const certificateArn = StringParameter2.valueForStringParameter(
|
|
732
|
+
scope,
|
|
733
|
+
_RootWildcardCertificate.ssmParameterName()
|
|
734
|
+
);
|
|
735
|
+
return Certificate.fromCertificateArn(
|
|
736
|
+
scope,
|
|
737
|
+
"wildcard-certificate",
|
|
738
|
+
certificateArn
|
|
739
|
+
);
|
|
740
|
+
}
|
|
741
|
+
constructor(scope, props) {
|
|
742
|
+
super(scope, "root-wildcard-certificate", { ...props });
|
|
743
|
+
new StringParameter2(this, "wildcard-cert-param", {
|
|
744
|
+
parameterName: _RootWildcardCertificate.ssmParameterName(),
|
|
745
|
+
stringValue: this.certificateArn
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
/**
|
|
750
|
+
* Used when storing the Certificate ARN in SSM.
|
|
751
|
+
*/
|
|
752
|
+
_RootWildcardCertificate.SSM_PARAM_NAME = "ROOT_WILDCARD_CERT_ARN";
|
|
753
|
+
var RootWildcardCertificate = _RootWildcardCertificate;
|
|
754
|
+
|
|
755
|
+
// src/components/route-53/child-hosted-zone.ts
|
|
756
|
+
import { Duration } from "aws-cdk-lib";
|
|
757
|
+
import {
|
|
758
|
+
HostedZone,
|
|
759
|
+
NsRecord
|
|
760
|
+
} from "aws-cdk-lib/aws-route53";
|
|
761
|
+
var _ChildHostedZone = class _ChildHostedZone extends HostedZone {
|
|
762
|
+
static fromConstruct(scope, props) {
|
|
763
|
+
const hostedZoneId = DiscoverableStringParameter.valueForLookupName(scope, {
|
|
764
|
+
ssmParamName: _ChildHostedZone.SSM_PARAM_NAME,
|
|
765
|
+
serviceType: props.serviceType ?? OPEN_HI_SERVICE_TYPE.GLOBAL
|
|
766
|
+
});
|
|
767
|
+
return HostedZone.fromHostedZoneAttributes(scope, "child-zone", {
|
|
768
|
+
hostedZoneId,
|
|
769
|
+
zoneName: props.zoneName
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
constructor(scope, id, props) {
|
|
773
|
+
super(scope, id, { ...props });
|
|
774
|
+
new NsRecord(this, "child-ns-record", {
|
|
775
|
+
zone: props.parentHostedZone,
|
|
776
|
+
recordName: this.zoneName,
|
|
777
|
+
values: this.hostedZoneNameServers || [],
|
|
778
|
+
ttl: Duration.minutes(5)
|
|
779
|
+
});
|
|
780
|
+
new DiscoverableStringParameter(this, "child-zone-param", {
|
|
781
|
+
ssmParamName: _ChildHostedZone.SSM_PARAM_NAME,
|
|
782
|
+
stringValue: this.hostedZoneId,
|
|
783
|
+
description: "Route53 child hosted zone ID."
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
/**
|
|
788
|
+
* Used when storing the API ID in SSM.
|
|
789
|
+
*/
|
|
790
|
+
_ChildHostedZone.SSM_PARAM_NAME = "CHILDHOSTEDZONE";
|
|
791
|
+
var ChildHostedZone = _ChildHostedZone;
|
|
792
|
+
|
|
793
|
+
// src/components/route-53/root-hosted-zone.ts
|
|
794
|
+
import {
|
|
795
|
+
HostedZone as HostedZone2
|
|
796
|
+
} from "aws-cdk-lib/aws-route53";
|
|
797
|
+
import { Construct as Construct2 } from "constructs";
|
|
798
|
+
var RootHostedZone = class extends Construct2 {
|
|
799
|
+
static fromConstruct(scope, props) {
|
|
800
|
+
return HostedZone2.fromHostedZoneAttributes(scope, "root-zone", {
|
|
801
|
+
hostedZoneId: props.hostedZoneId,
|
|
802
|
+
zoneName: props.zoneName
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
// src/components/global.ts
|
|
808
|
+
var Global = class extends Construct3 {
|
|
809
|
+
constructor(scope, id, props) {
|
|
810
|
+
super(scope, id);
|
|
811
|
+
this.props = props;
|
|
812
|
+
const { rootHostedZoneAttributes, childHostedZoneAttributes } = props;
|
|
813
|
+
const service = OpenHiService.of(this);
|
|
814
|
+
this.rootHostedZone = RootHostedZone.fromConstruct(
|
|
815
|
+
this,
|
|
816
|
+
rootHostedZoneAttributes
|
|
817
|
+
);
|
|
818
|
+
if (childHostedZoneAttributes) {
|
|
819
|
+
this.childHostedZone = new ChildHostedZone(this, "child-zone", {
|
|
820
|
+
parentHostedZone: this.rootHostedZone,
|
|
821
|
+
zoneName: childHostedZoneAttributes.zoneName
|
|
822
|
+
});
|
|
823
|
+
}
|
|
824
|
+
if (service.branchName === "main") {
|
|
825
|
+
this.rootWildcardCertificate = new RootWildcardCertificate(this, {
|
|
826
|
+
domainName: `*.${this.rootHostedZone.zoneName}`,
|
|
827
|
+
subjectAlternativeNames: [this.rootHostedZone.zoneName],
|
|
828
|
+
validation: CertificateValidation.fromDns(this.rootHostedZone)
|
|
829
|
+
});
|
|
830
|
+
} else {
|
|
831
|
+
this.rootWildcardCertificate = RootWildcardCertificate.fromConstruct(this);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
|
|
836
|
+
// src/services/open-hi-global-service.ts
|
|
837
|
+
var OpenHiGlobalService = class extends OpenHiService {
|
|
838
|
+
constructor(ohEnv, props = {}) {
|
|
839
|
+
super(ohEnv, OPEN_HI_SERVICE_TYPE.GLOBAL, props);
|
|
840
|
+
const { config } = props;
|
|
841
|
+
if (!config) {
|
|
842
|
+
throw new Error("Config is required");
|
|
843
|
+
}
|
|
844
|
+
if (!config.zoneName) {
|
|
845
|
+
throw new Error("Zone name is required to import the root zone");
|
|
846
|
+
}
|
|
847
|
+
if (!config.hostedZoneId) {
|
|
848
|
+
throw new Error("Hosted zone ID is required to import the root zone");
|
|
849
|
+
}
|
|
850
|
+
this.global = new Global(this, "global", {
|
|
851
|
+
rootHostedZoneAttributes: {
|
|
852
|
+
zoneName: config.zoneName,
|
|
853
|
+
hostedZoneId: config.hostedZoneId
|
|
854
|
+
}
|
|
855
|
+
/*
|
|
856
|
+
childHostedZoneAttributes: {
|
|
857
|
+
zoneName: `${this.childZonePrefix}.${config.zoneName}`,
|
|
858
|
+
hostedZoneId: config.hostedZoneId,
|
|
859
|
+
},
|
|
860
|
+
*/
|
|
861
|
+
});
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
|
|
865
|
+
// src/services/open-hi-rest-api-service.ts
|
|
866
|
+
import {
|
|
867
|
+
DomainName,
|
|
868
|
+
HttpMethod,
|
|
869
|
+
HttpRoute,
|
|
870
|
+
HttpRouteKey
|
|
871
|
+
} from "aws-cdk-lib/aws-apigatewayv2";
|
|
872
|
+
import { HttpLambdaIntegration } from "aws-cdk-lib/aws-apigatewayv2-integrations";
|
|
873
|
+
import { ARecord, HostedZone as HostedZone3, RecordTarget } from "aws-cdk-lib/aws-route53";
|
|
874
|
+
import { ApiGatewayv2DomainProperties } from "aws-cdk-lib/aws-route53-targets";
|
|
875
|
+
|
|
876
|
+
// src/components/api-gateway/core-http-api.ts
|
|
877
|
+
import { HttpApi } from "aws-cdk-lib/aws-apigatewayv2";
|
|
878
|
+
var _CoreHttpApi = class _CoreHttpApi extends HttpApi {
|
|
879
|
+
static fromConstruct(scope) {
|
|
880
|
+
const httpApiId = DiscoverableStringParameter.valueForLookupName(scope, {
|
|
881
|
+
ssmParamName: _CoreHttpApi.SSM_PARAM_NAME,
|
|
882
|
+
serviceType: OPEN_HI_SERVICE_TYPE.REST_API
|
|
883
|
+
});
|
|
884
|
+
return HttpApi.fromHttpApiAttributes(scope, "http-api", {
|
|
885
|
+
httpApiId
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
constructor(scope, props = {}) {
|
|
889
|
+
const stack = OpenHiService.of(scope);
|
|
890
|
+
super(scope, "http-api", {
|
|
891
|
+
/**
|
|
892
|
+
* User provided props
|
|
893
|
+
*/
|
|
894
|
+
...props,
|
|
895
|
+
/**
|
|
896
|
+
* Required
|
|
897
|
+
*/
|
|
898
|
+
apiName: ["core", "http", "api", stack.branchHash].join("-")
|
|
899
|
+
});
|
|
900
|
+
new DiscoverableStringParameter(this, "http-api-url-param", {
|
|
901
|
+
ssmParamName: _CoreHttpApi.SSM_PARAM_NAME,
|
|
902
|
+
serviceType: OPEN_HI_SERVICE_TYPE.REST_API,
|
|
903
|
+
stringValue: this.httpApiId
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
/**
|
|
908
|
+
* Used when storing the API ID in SSM.
|
|
909
|
+
*/
|
|
910
|
+
_CoreHttpApi.SSM_PARAM_NAME = "CORE_HTTP_API";
|
|
911
|
+
var CoreHttpApi = _CoreHttpApi;
|
|
912
|
+
|
|
913
|
+
// src/components/dynamodb/dynamo-db-data-store.ts
|
|
914
|
+
import {
|
|
915
|
+
AttributeType,
|
|
916
|
+
BillingMode,
|
|
917
|
+
ProjectionType,
|
|
918
|
+
Table
|
|
919
|
+
} from "aws-cdk-lib/aws-dynamodb";
|
|
920
|
+
function getDynamoDbDataStoreTableName(scope) {
|
|
921
|
+
const stack = OpenHiService.of(scope);
|
|
922
|
+
return `data-store-${stack.branchHash}`;
|
|
923
|
+
}
|
|
924
|
+
var DynamoDbDataStore = class extends Table {
|
|
925
|
+
/**
|
|
926
|
+
* Import the data store table by name for use in another stack (e.g. data
|
|
927
|
+
* service or Lambda). Uses the same naming as {@link getDynamoDbDataStoreTableName}.
|
|
928
|
+
*/
|
|
929
|
+
static fromConstruct(scope, id = "dynamo-db-data-store") {
|
|
930
|
+
return Table.fromTableName(scope, id, getDynamoDbDataStoreTableName(scope));
|
|
931
|
+
}
|
|
932
|
+
constructor(scope, id, props = {}) {
|
|
933
|
+
const service = OpenHiService.of(scope);
|
|
934
|
+
super(scope, id, {
|
|
935
|
+
...props,
|
|
936
|
+
tableName: getDynamoDbDataStoreTableName(scope),
|
|
937
|
+
partitionKey: {
|
|
938
|
+
name: "PK",
|
|
939
|
+
type: AttributeType.STRING
|
|
940
|
+
},
|
|
941
|
+
sortKey: {
|
|
942
|
+
name: "SK",
|
|
943
|
+
type: AttributeType.STRING
|
|
944
|
+
},
|
|
945
|
+
billingMode: BillingMode.PAY_PER_REQUEST,
|
|
946
|
+
removalPolicy: props.removalPolicy ?? service.removalPolicy
|
|
947
|
+
});
|
|
948
|
+
this.addGlobalSecondaryIndex({
|
|
949
|
+
indexName: "GSI1",
|
|
950
|
+
partitionKey: {
|
|
951
|
+
name: "GSI1PK",
|
|
952
|
+
type: AttributeType.STRING
|
|
953
|
+
},
|
|
954
|
+
sortKey: {
|
|
955
|
+
name: "GSI1SK",
|
|
956
|
+
type: AttributeType.STRING
|
|
957
|
+
},
|
|
958
|
+
projectionType: ProjectionType.INCLUDE,
|
|
959
|
+
nonKeyAttributes: ["srcType", "srcId", "path", "srcPk", "srcSk", "ts"]
|
|
960
|
+
});
|
|
961
|
+
this.addGlobalSecondaryIndex({
|
|
962
|
+
indexName: "GSI2",
|
|
963
|
+
partitionKey: {
|
|
964
|
+
name: "GSI2PK",
|
|
965
|
+
type: AttributeType.STRING
|
|
966
|
+
},
|
|
967
|
+
sortKey: {
|
|
968
|
+
name: "GSI2SK",
|
|
969
|
+
type: AttributeType.STRING
|
|
970
|
+
},
|
|
971
|
+
projectionType: ProjectionType.INCLUDE,
|
|
972
|
+
nonKeyAttributes: ["resourcePk", "resourceSk", "display", "status"]
|
|
973
|
+
});
|
|
974
|
+
this.addGlobalSecondaryIndex({
|
|
975
|
+
indexName: "GSI3",
|
|
976
|
+
partitionKey: {
|
|
977
|
+
name: "GSI3PK",
|
|
978
|
+
type: AttributeType.STRING
|
|
979
|
+
},
|
|
980
|
+
sortKey: {
|
|
981
|
+
name: "GSI3SK",
|
|
982
|
+
type: AttributeType.STRING
|
|
983
|
+
},
|
|
984
|
+
projectionType: ProjectionType.INCLUDE,
|
|
985
|
+
nonKeyAttributes: ["resourcePk", "resourceSk"]
|
|
986
|
+
});
|
|
987
|
+
this.addGlobalSecondaryIndex({
|
|
988
|
+
indexName: "GSI4",
|
|
989
|
+
partitionKey: {
|
|
990
|
+
name: "GSI4PK",
|
|
991
|
+
type: AttributeType.STRING
|
|
992
|
+
},
|
|
993
|
+
sortKey: {
|
|
994
|
+
name: "GSI4SK",
|
|
995
|
+
type: AttributeType.STRING
|
|
996
|
+
},
|
|
997
|
+
projectionType: ProjectionType.ALL
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
|
|
1002
|
+
// src/data/lambda/rest-api-lambda.ts
|
|
1003
|
+
import path from "path";
|
|
1004
|
+
import { Runtime as Runtime2 } from "aws-cdk-lib/aws-lambda";
|
|
1005
|
+
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
|
|
1006
|
+
import { Construct as Construct4 } from "constructs";
|
|
1007
|
+
var RestApiLambda = class extends Construct4 {
|
|
1008
|
+
constructor(scope, props) {
|
|
1009
|
+
super(scope, "rest-api-lambda");
|
|
1010
|
+
this.lambda = new NodejsFunction(this, "handler", {
|
|
1011
|
+
entry: path.join(__dirname, "rest-api-lambda.handler.js"),
|
|
1012
|
+
runtime: Runtime2.NODEJS_LATEST,
|
|
1013
|
+
environment: {
|
|
1014
|
+
DYNAMO_TABLE_NAME: props.dynamoTableName
|
|
1015
|
+
}
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
};
|
|
1019
|
+
|
|
1020
|
+
// src/services/open-hi-rest-api-service.ts
|
|
1021
|
+
var REST_API_BASE_URL_SSM_NAME = "REST_API_BASE_URL";
|
|
1022
|
+
var OpenHiRestApiService = class extends OpenHiService {
|
|
1023
|
+
constructor(ohEnv, props = {}) {
|
|
1024
|
+
super(ohEnv, OPEN_HI_SERVICE_TYPE.REST_API, props);
|
|
1025
|
+
const { config } = props;
|
|
1026
|
+
if (!config) {
|
|
1027
|
+
throw new Error("Config is required");
|
|
1028
|
+
}
|
|
1029
|
+
if (!config.hostedZoneId) {
|
|
1030
|
+
throw new Error("Hosted zone ID is required");
|
|
1031
|
+
}
|
|
1032
|
+
if (!config.zoneName) {
|
|
1033
|
+
throw new Error("Zone name is required");
|
|
1034
|
+
}
|
|
1035
|
+
const hostedZone = HostedZone3.fromHostedZoneAttributes(this, "root-zone", {
|
|
1036
|
+
hostedZoneId: config.hostedZoneId,
|
|
1037
|
+
zoneName: config.zoneName
|
|
1038
|
+
});
|
|
1039
|
+
const certificate = RootWildcardCertificate.fromConstruct(this);
|
|
1040
|
+
const apiPrefix = this.branchName === "main" ? `api` : `api-${this.childZonePrefix}`;
|
|
1041
|
+
const apiDomainName = [apiPrefix, hostedZone.zoneName].join(".");
|
|
1042
|
+
const restApiBaseUrl = `https://${apiDomainName}`;
|
|
1043
|
+
new DiscoverableStringParameter(this, "rest-api-base-url-param", {
|
|
1044
|
+
ssmParamName: REST_API_BASE_URL_SSM_NAME,
|
|
1045
|
+
stringValue: restApiBaseUrl,
|
|
1046
|
+
description: "REST API base URL for this deployment (E2E, scripts)"
|
|
1047
|
+
});
|
|
1048
|
+
const domainName = new DomainName(this, "domain", {
|
|
1049
|
+
domainName: apiDomainName,
|
|
1050
|
+
certificate
|
|
1051
|
+
});
|
|
1052
|
+
this.coreHttpApi = new CoreHttpApi(this, {
|
|
1053
|
+
defaultDomainMapping: {
|
|
1054
|
+
domainName,
|
|
1055
|
+
mappingKey: void 0
|
|
1056
|
+
// serve at root of domain
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
1059
|
+
const dataStoreTable = DynamoDbDataStore.fromConstruct(this);
|
|
1060
|
+
const { lambda } = new RestApiLambda(this, {
|
|
1061
|
+
dynamoTableName: dataStoreTable.tableName
|
|
1062
|
+
});
|
|
1063
|
+
dataStoreTable.grant(
|
|
1064
|
+
lambda,
|
|
1065
|
+
"dynamodb:GetItem",
|
|
1066
|
+
"dynamodb:Query",
|
|
1067
|
+
"dynamodb:BatchGetItem",
|
|
1068
|
+
"dynamodb:ConditionCheckItem",
|
|
1069
|
+
"dynamodb:DescribeTable",
|
|
1070
|
+
"dynamodb:BatchWriteItem",
|
|
1071
|
+
"dynamodb:PutItem",
|
|
1072
|
+
"dynamodb:UpdateItem",
|
|
1073
|
+
"dynamodb:DeleteItem"
|
|
1074
|
+
);
|
|
1075
|
+
const integration = new HttpLambdaIntegration("lambda-integration", lambda);
|
|
1076
|
+
new HttpRoute(this, "proxy-route-root", {
|
|
1077
|
+
httpApi: this.coreHttpApi,
|
|
1078
|
+
routeKey: HttpRouteKey.with("/", HttpMethod.ANY),
|
|
1079
|
+
integration
|
|
1080
|
+
});
|
|
1081
|
+
new HttpRoute(this, "proxy-route", {
|
|
1082
|
+
httpApi: this.coreHttpApi,
|
|
1083
|
+
routeKey: HttpRouteKey.with("/{proxy+}", HttpMethod.ANY),
|
|
1084
|
+
integration
|
|
1085
|
+
});
|
|
1086
|
+
new ARecord(this, "api-a-record", {
|
|
1087
|
+
zone: hostedZone,
|
|
1088
|
+
recordName: apiPrefix,
|
|
1089
|
+
target: RecordTarget.fromAlias(
|
|
1090
|
+
new ApiGatewayv2DomainProperties(
|
|
1091
|
+
domainName.regionalDomainName,
|
|
1092
|
+
domainName.regionalHostedZoneId
|
|
1093
|
+
)
|
|
1094
|
+
)
|
|
1095
|
+
});
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
|
|
1099
|
+
// src/services/open-hi-data-service.ts
|
|
1100
|
+
var OpenHiDataService = class extends OpenHiService {
|
|
1101
|
+
constructor(ohEnv, props = {}) {
|
|
1102
|
+
super(ohEnv, OPEN_HI_SERVICE_TYPE.DATA, props);
|
|
1103
|
+
this.dataStore = new DynamoDbDataStore(this, "dynamo-db-data-store");
|
|
1104
|
+
}
|
|
1105
|
+
};
|
|
1106
|
+
export {
|
|
1107
|
+
DiscoverableStringParameter,
|
|
1108
|
+
OPEN_HI_SERVICE_TYPE,
|
|
1109
|
+
OpenHiApp,
|
|
1110
|
+
OpenHiAuthService,
|
|
1111
|
+
OpenHiCoreService,
|
|
1112
|
+
OpenHiDataService,
|
|
1113
|
+
OpenHiEnvironment,
|
|
1114
|
+
OpenHiGlobalService,
|
|
1115
|
+
OpenHiRestApiService,
|
|
1116
|
+
OpenHiService,
|
|
1117
|
+
OpenHiStage,
|
|
1118
|
+
REST_API_BASE_URL_SSM_NAME
|
|
1119
|
+
};
|
|
1120
|
+
//# sourceMappingURL=index.mjs.map
|