@openhi/platform 0.0.40 → 0.0.42
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/index.js +45 -1
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +45 -1
- package/lib/index.mjs.map +1 -1
- package/package.json +5 -5
package/lib/index.js
CHANGED
|
@@ -473,6 +473,16 @@ var OpenHiService = class {
|
|
|
473
473
|
"@openhi/constructs@workspace:*"
|
|
474
474
|
);
|
|
475
475
|
new import_configulator.TurboRepo(this.project);
|
|
476
|
+
import_configulator.TurboRepo.of(this.project)?.activateBranchNameEnvVar({
|
|
477
|
+
tasks: ["post-compile"]
|
|
478
|
+
});
|
|
479
|
+
if (this.options.type === OPEN_HI_SERVICE_TYPE.WEBSITE) {
|
|
480
|
+
const turbo = import_configulator.TurboRepo.of(this.project);
|
|
481
|
+
const postCompileEnv = turbo?.postCompileTask?.env;
|
|
482
|
+
if (postCompileEnv && !postCompileEnv.includes("OPENHI_PR_NUMBER")) {
|
|
483
|
+
postCompileEnv.push("OPENHI_PR_NUMBER");
|
|
484
|
+
}
|
|
485
|
+
}
|
|
476
486
|
new GenerateTemplates(this);
|
|
477
487
|
[import_config2.OPEN_HI_STAGE.DEV, import_config2.OPEN_HI_STAGE.STAGE, import_config2.OPEN_HI_STAGE.PROD].forEach(
|
|
478
488
|
(stage) => {
|
|
@@ -700,6 +710,7 @@ var AwsTeardownWorkflow = class extends import_projen4.Component {
|
|
|
700
710
|
// src/workflows/build-dev-workflow.ts
|
|
701
711
|
var import_configulator3 = require("@codedrifters/configulator");
|
|
702
712
|
var import_projen5 = require("projen");
|
|
713
|
+
var PR_GATED_WEBSITE_JOB_IF = "${{ !needs.build.outputs.self_mutation_happened && (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch') }}";
|
|
703
714
|
var BuildDevelopmentWorkflow = class extends import_projen5.Component {
|
|
704
715
|
constructor(parent, options) {
|
|
705
716
|
super(parent, "dev-workflow");
|
|
@@ -735,10 +746,39 @@ var BuildDevelopmentWorkflow = class extends import_projen5.Component {
|
|
|
735
746
|
buildWorkflow: parent.buildWorkflow,
|
|
736
747
|
deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets]
|
|
737
748
|
});
|
|
738
|
-
new import_configulator3.AwsDeployWorkflow(openhi.website.project, {
|
|
749
|
+
const websiteDeploy = new import_configulator3.AwsDeployWorkflow(openhi.website.project, {
|
|
739
750
|
buildWorkflow: parent.buildWorkflow,
|
|
740
751
|
deployAfterTargets: [...globalTargets, ...restApiTargets]
|
|
741
752
|
});
|
|
753
|
+
const buildWorkflow = parent.buildWorkflow;
|
|
754
|
+
if (!buildWorkflow) {
|
|
755
|
+
throw new Error("BuildDevelopmentWorkflow requires a buildWorkflow");
|
|
756
|
+
}
|
|
757
|
+
const ghWorkflow = buildWorkflow.workflow;
|
|
758
|
+
ghWorkflow.on({
|
|
759
|
+
pullRequest: {
|
|
760
|
+
types: ["opened", "synchronize", "reopened"]
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
ghWorkflow.file?.addOverride(
|
|
764
|
+
"env.OPENHI_PR_NUMBER",
|
|
765
|
+
"${{ github.event.pull_request.number || '' }}"
|
|
766
|
+
);
|
|
767
|
+
websiteDeploy.awsDeploymentTargets.forEach((target) => {
|
|
768
|
+
const jobId = [
|
|
769
|
+
target.awsStageType,
|
|
770
|
+
target.deploymentTargetRole,
|
|
771
|
+
"deploy",
|
|
772
|
+
target.project.name,
|
|
773
|
+
target.account,
|
|
774
|
+
target.region
|
|
775
|
+
].join("-");
|
|
776
|
+
const job = ghWorkflow.getJob(jobId);
|
|
777
|
+
ghWorkflow.updateJob(jobId, {
|
|
778
|
+
...job,
|
|
779
|
+
if: PR_GATED_WEBSITE_JOB_IF
|
|
780
|
+
});
|
|
781
|
+
});
|
|
742
782
|
}
|
|
743
783
|
};
|
|
744
784
|
|
|
@@ -762,6 +802,10 @@ var BuildStageWorkflow = class extends import_projen6.Component {
|
|
|
762
802
|
}
|
|
763
803
|
}
|
|
764
804
|
});
|
|
805
|
+
buildWorkflow.workflow.file?.addOverride(
|
|
806
|
+
"env.OPENHI_PR_NUMBER",
|
|
807
|
+
"${{ github.event.pull_request.number || '' }}"
|
|
808
|
+
);
|
|
765
809
|
const { awsDeploymentTargets: authTargets } = new import_configulator4.AwsDeployWorkflow(
|
|
766
810
|
openhi.auth.project,
|
|
767
811
|
{
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../config/src/open-hi-config.ts","../../config/src/index.ts","../src/index.ts","../src/openhi.ts","../src/service.ts","../src/templates/service-template.ts","../src/templates/src/app.ts","../src/templates/src/app-test.ts","../src/templates/src/config.ts","../src/templates/src/data/models/README.md.ts","../src/templates/src/data/README.md.ts","../src/templates/src/infrastructure/README.md.ts","../src/templates/src/integrations/README.md.ts","../src/templates/src/main.ts","../src/templates/src/README.md.ts","../src/templates/src/workflows/README.md.ts","../src/templates/generate-templates.ts","../src/workflows/aws-teardown-workflow.ts","../src/workflows/build-dev-workflow.ts","../src/workflows/build-stage-workflow.ts"],"sourcesContent":["/*******************************************************************************\n *\n * OpenHi Config\n *\n * These types are kept in their own package to prevent dependency conflicts and\n * conditions between @openhi/constructs and @openhi/platform..\n *\n ******************************************************************************/\n\n/**\n * Stage Types\n *\n * What stage of deployment is this? Dev, staging, or prod?\n */\nexport const OPEN_HI_STAGE = {\n /**\n * Development environment, typically used for testing and development.\n */\n DEV: \"dev\",\n /**\n * Staging environment, used for pre-production testing.\n */\n STAGE: \"stage\",\n /**\n * Production environment, used for live deployments.\n */\n PROD: \"prod\",\n} as const;\n\n/**\n * Above const as a type.\n */\nexport type OpenHiStageType =\n (typeof OPEN_HI_STAGE)[keyof typeof OPEN_HI_STAGE];\n\n/**\n * Deployment Target Role\n *\n * Is this (account, region) the primary or a secondary deployment target for the stage?\n * Works for both multi-region (different regions) and cellular (same region, different accounts).\n */\nexport const OPEN_HI_DEPLOYMENT_TARGET_ROLE = {\n /**\n * The primary deployment target for this stage (main account/region).\n * For example, the base DynamoDB region for global tables.\n */\n PRIMARY: \"primary\",\n\n /**\n * A secondary deployment target for this stage (additional account/region).\n * For example, a replica region for a global DynamoDB table, or another cell in the same region.\n */\n SECONDARY: \"secondary\",\n} as const;\n\n/**\n * Above const as a type.\n */\nexport type OpenHiDeploymentTargetRoleType =\n (typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE)[keyof typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE];\n\nexport interface OpenHiEnvironmentConfig {\n account: string;\n region: string;\n /**\n * Route53 zone containing DNS for this service.\n */\n hostedZoneId?: string;\n zoneName?: string;\n}\n\n/**\n * Represents the configuration for OpenHi services across different stages and\n * deployment targets.\n */\nexport interface OpenHiConfig {\n versions?: {\n cdk?: {\n cdkLibVersion?: string;\n cdkCliVersion?: string;\n };\n };\n deploymentTargets?: {\n [OPEN_HI_STAGE.DEV]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n [OPEN_HI_STAGE.STAGE]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n [OPEN_HI_STAGE.PROD]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n };\n}\n","export * from \"./open-hi-config\";\n","/**\n * @see sites/www-docs/content/packages/@openhi/platform/index.md\n */\n/** @openhi/platform — root barrel exports. */\nexport * from \"./openhi\";\nexport * from \"./service\";\n","import {\n MonorepoProject,\n MonorepoProjectOptions,\n} from \"@codedrifters/configulator\";\nimport { OpenHiConfig } from \"@openhi/config\";\nimport { merge } from \"ts-deepmerge\";\nimport { SetOptional } from \"type-fest\";\nimport { OPEN_HI_SERVICE_TYPE, OpenHiService } from \"./service\";\nimport { AwsTeardownWorkflow } from \"./workflows/aws-teardown-workflow\";\nimport { BuildDevelopmentWorkflow } from \"./workflows/build-dev-workflow\";\nimport { BuildStageWorkflow } from \"./workflows/build-stage-workflow\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/openhi.md\n */\n\nexport interface OpenHiOptions {\n /*****************************************************************************\n *\n * Root Project Configuration Options\n *\n * Configuration options for the root monorepo project that contains all\n * OpenHi services and coordinate releases and builds.\n *\n ****************************************************************************/\n\n readonly rootProjectOptions?: SetOptional<MonorepoProjectOptions, \"name\">;\n\n /**\n * Monorepo root project, if using an existing project.\n */\n readonly rootProject?: MonorepoProject;\n\n /*****************************************************************************\n *\n * Service Configuration Options\n *\n * These options are used to configure the various services within the OpenHi\n * framework. Each service can have its own configuration settings, which will\n * be merged with the default configuration.\n *\n ****************************************************************************/\n\n /**\n * Default configuration used in all services with undefined configs.\n */\n readonly defaultConfig?: OpenHiConfig;\n\n /**\n * Global Service Config\n */\n readonly globalServiceConfig?: OpenHiConfig;\n\n /**\n * Auth Service Config\n */\n readonly authServiceConfig?: OpenHiConfig;\n\n /**\n * Rest API Service Config\n */\n readonly restApiServiceConfig?: OpenHiConfig;\n\n /**\n * Data Service Config (DynamoDB FHIR store, S3, etc.)\n */\n readonly dataServiceConfig?: OpenHiConfig;\n\n /**\n * GraphQL API Service Config\n */\n readonly graphApiServiceConfig?: OpenHiConfig;\n\n /**\n * Website Service Config (static hosting + content uploader).\n */\n readonly websiteServiceConfig?: OpenHiConfig;\n}\n\nexport class OpenHi {\n /**\n * Final options used to build this instance.\n */\n public options: OpenHiOptions;\n\n /**\n * Monorepo root project, either passed in as an argument or generated in\n * this component\n */\n public readonly rootProject?: MonorepoProject;\n\n /**\n * Test identifier for this instance.\n */\n public readonly id: string;\n\n /**\n * Global service (deployed first; Auth, data service, and other stacks depend on it).\n */\n public readonly global: OpenHiService;\n\n /**\n * Auth service (deployed first; data service, REST API, and data services depend on it).\n */\n public readonly auth: OpenHiService;\n\n /**\n * Rest API service\n */\n public readonly restApi: OpenHiService;\n\n /**\n * Data service (DynamoDB FHIR store, S3, and other persistence).\n */\n public readonly data: OpenHiService;\n\n /**\n * GraphQL API service (AppSync); deploys as sibling to REST API after Data.\n */\n public readonly graphApi: OpenHiService;\n\n /**\n * Website service (static hosting + content uploader); deploys as sibling\n * to the other services after Global.\n */\n public readonly website: OpenHiService;\n\n constructor(options: OpenHiOptions = {}) {\n /***************************************************************************\n *\n * Options\n *\n * Combine input options with defaults.\n *\n **************************************************************************/\n\n this.options = merge({ name: \"openhi\" }, options);\n this.rootProject = this.options.rootProject;\n this.id = this.options.rootProject?.name ?? \"openhi\";\n\n /**\n * In future we would create root project here. For now, require it to be\n * passed in.\n */\n if (!this.rootProject) {\n throw new Error(\n \"OpenHi requires a MonorepoProject to be passed in via the rootProject option\",\n );\n }\n\n const rootProject = this.rootProject;\n\n /***************************************************************************\n *\n * Global Service\n *\n * Global infrastructure (Route53, ACM). Deployed first in primary;\n * Auth, data service, and other stacks depend on it.\n *\n **************************************************************************/\n\n this.global = new OpenHiService(this, \"global\", {\n type: OPEN_HI_SERVICE_TYPE.GLOBAL,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.globalServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Auth Service\n *\n * Authentication (Cognito user pool, client, domain, KMS). Deployed first;\n * data service, REST API, and data services consume auth via SSM.\n *\n **************************************************************************/\n\n this.auth = new OpenHiService(this, \"auth\", {\n type: OPEN_HI_SERVICE_TYPE.AUTH,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.authServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Rest API service\n *\n * This contains the REST API for the OpenHi platform.\n *\n **************************************************************************/\n\n this.restApi = new OpenHiService(this, \"rest-api\", {\n type: OPEN_HI_SERVICE_TYPE.REST_API,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.restApiServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Data Service\n *\n * Data storage stack (DynamoDB FHIR store, S3, etc.). Deployed so that\n * REST API and other services can reference the table via cross-stack.\n *\n **************************************************************************/\n\n this.data = new OpenHiService(this, \"data\", {\n type: OPEN_HI_SERVICE_TYPE.DATA_SERVICE,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.dataServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * GraphQL API service\n *\n * AppSync API; deploys as sibling to REST API after Data.\n *\n **************************************************************************/\n\n this.graphApi = new OpenHiService(this, \"graphql\", {\n type: OPEN_HI_SERVICE_TYPE.GRAPHQL,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.graphApiServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Website service\n *\n * Static hosting (CloudFront + S3 + Lambda@Edge) and content uploader;\n * deploys as a sibling to the other services after Global.\n *\n **************************************************************************/\n\n this.website = new OpenHiService(this, \"website\", {\n type: OPEN_HI_SERVICE_TYPE.WEBSITE,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.websiteServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Integrations\n *\n * Various purpose specific integrations.\n *\n **************************************************************************/\n\n /***************************************************************************\n *\n * Workflows\n *\n * Workflows for each environment.\n *\n **************************************************************************/\n\n new BuildDevelopmentWorkflow(rootProject, { openhi: this });\n new BuildStageWorkflow(rootProject, { openhi: this });\n\n new AwsTeardownWorkflow(rootProject, { openhi: this });\n }\n}\n","import { sep } from \"path\";\nimport {\n AwsDeploymentTarget,\n TurboRepo,\n VERSION,\n} from \"@codedrifters/configulator\";\nimport {\n OPEN_HI_DEPLOYMENT_TARGET_ROLE,\n OPEN_HI_STAGE,\n OpenHiConfig,\n OpenHiEnvironmentConfig,\n} from \"@openhi/config\";\nimport { paramCase, pascalCase } from \"change-case\";\nimport { awscdk } from \"projen\";\nimport { NodePackageManager, Transform } from \"projen/lib/javascript\";\nimport { ValueOf } from \"type-fest\";\nimport { OpenHi } from \"./openhi\";\nimport { GenerateTemplates } from \"./templates/generate-templates\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/service.md\n */\n\nexport const OPEN_HI_SERVICE_TYPE = {\n AUTH: \"auth\",\n DATA_SERVICE: \"data\",\n GLOBAL: \"global\",\n GRAPHQL: \"graphql\",\n INTEGRATION: \"integration\",\n REST_API: \"rest-api\",\n WEBSITE: \"website\",\n} as const;\n\nexport interface OpenHiServiceOptions {\n /**\n * Configuration for this service.\n *\n * @default uses the global default config.\n */\n readonly config: OpenHiConfig;\n\n /**\n * What type of service is this?\n */\n readonly type: ValueOf<typeof OPEN_HI_SERVICE_TYPE>;\n}\n\nexport class OpenHiService {\n public readonly project: awscdk.AwsCdkTypeScriptApp;\n\n constructor(\n public openHi: OpenHi,\n public id: string,\n public options: OpenHiServiceOptions,\n ) {\n /**\n * Build the construct name we expect to use in this service.\n */\n\n /***************************************************************************\n *\n * Projen based CDK build\n *\n **************************************************************************/\n\n this.project = new awscdk.AwsCdkTypeScriptApp({\n /**\n * Top level project config options\n */\n defaultReleaseBranch: \"main\",\n name: this.serviceName,\n outdir: this.outDir,\n parent: this.openHi.rootProject,\n cdkVersion:\n this.options?.config?.versions?.cdk?.cdkLibVersion ??\n VERSION.AWS_CDK_LIB_VERSION,\n cdkCliVersion:\n this.options?.config?.versions?.cdk?.cdkCliVersion ??\n VERSION.AWS_CDK_CLI_VERSION,\n\n /**\n * Packaging options\n *\n * TODO: Figure out license for monorepo vs per package?\n */\n licensed: false,\n\n /**\n * Node configs\n */\n packageManager: NodePackageManager.PNPM,\n\n /**\n * Turn on prettier formatting\n */\n prettier: true,\n\n /**\n * Don't generate sample code.\n */\n sampleCode: false,\n\n /**\n * Make sure jest config is stored outside of package.json and use SWC\n * for faster tests.\n */\n jestOptions: {\n configFilePath: \"jest.config.json\",\n jestConfig: {\n transform: {\n [\"^.+\\\\.[t]sx?$\"]: new Transform(\"@swc/jest\"),\n },\n },\n },\n\n /**\n * SWC for faster testing\n */\n devDeps: [\"@swc/jest\", \"@swc/core\"],\n\n /**\n * Don't package test files.\n */\n npmIgnoreOptions: {\n ignorePatterns: [\"*.spec.*\", \"*.test.*\"],\n },\n });\n\n /**\n * We're using SWC now, remove ts-jest which is included by default.\n */\n this.project.deps.removeDependency(\"ts-jest\");\n\n /***************************************************************************\n *\n * Workspace Dependencies\n *\n * - Constructs are used to build out the AWS CDK environments.\n *\n **************************************************************************/\n\n this.project.addDeps(\n \"@openhi/config@workspace:*\",\n \"@openhi/constructs@workspace:*\",\n );\n\n /***************************************************************************\n *\n * Turbo Configuration\n *\n * - Activate turborepo for the project.\n *\n **************************************************************************/\n\n new TurboRepo(this.project);\n\n /***************************************************************************\n *\n * Define some basic Service Structure\n *\n **************************************************************************/\n\n new GenerateTemplates(this);\n\n /***************************************************************************\n *\n * Deployment Targets\n *\n **************************************************************************/\n\n [OPEN_HI_STAGE.DEV, OPEN_HI_STAGE.STAGE, OPEN_HI_STAGE.PROD].forEach(\n (stage) => {\n const targets = this.options?.config?.deploymentTargets?.[stage];\n if (targets?.primary) {\n this.addDeploymentTarget(\n stage,\n OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY,\n targets.primary,\n );\n }\n targets?.secondary?.forEach((env) => {\n this.addDeploymentTarget(\n stage,\n OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY,\n env,\n );\n });\n },\n );\n }\n\n private addDeploymentTarget = (\n awsStageType: ValueOf<typeof OPEN_HI_STAGE>,\n awsEnvironmentType: ValueOf<typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE>,\n envConfig: OpenHiEnvironmentConfig,\n ) => {\n new AwsDeploymentTarget(this.project, {\n account: envConfig.account,\n region: envConfig.region,\n awsStageType,\n awsEnvironmentType,\n localDeployment: true,\n localDeploymentConfig: {\n stackPattern: `${awsStageType}/${awsEnvironmentType}/*-${envConfig.account}-${envConfig.region}`,\n roleName: \"poweruseraccess\",\n },\n ciDeployment: true,\n ciDeploymentConfig: {\n roleArn: `arn:aws:iam::${envConfig.account}:role/GitHubOpenHiDeployer`,\n stackPattern: `${awsStageType}/${awsEnvironmentType}/*-${envConfig.account}-${envConfig.region}`,\n },\n\n branches:\n awsStageType === OPEN_HI_STAGE.DEV\n ? [\n {\n branch: \"feat/*\",\n description: [\n \"Feature branches for OpenHI (short form).\",\n \"These branches are used for developing new features.\",\n ],\n },\n {\n branch: \"feature/*\",\n description: [\n \"Feature branches for OpenHI.\",\n \"These branches are used for developing new features.\",\n ],\n },\n {\n branch: \"fix/*\",\n description: [\n \"Fix branches for OpenHI.\",\n \"This branch pattern is used when a developer is working on a fix on the project.\",\n ],\n },\n ]\n : [\n {\n branch: \"main\",\n description: [\n \"Main branch for OpenHI.\",\n \"This branch is used for the main branch.\",\n ],\n },\n ],\n });\n };\n\n get constructName(): string {\n return pascalCase([\"open\", \"hi\", this.id, \"service\"].join(\"-\"));\n }\n\n get outDir() {\n return [paramCase(this.openHi.id), paramCase(this.id)].join(sep);\n }\n\n get serviceName() {\n return [paramCase(this.openHi.id), paramCase(this.id)].join(\"-\");\n }\n}\n","import { existsSync, unlinkSync } from \"node:fs\";\nimport { sep } from \"node:path\";\nimport { SampleFile } from \"projen\";\nimport { OpenHiService } from \"../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/service-template.md\n */\n\nexport interface ServiceTemplateOptions {\n /**\n * The content of the sample file, as an array.\n */\n readonly contents: Array<string>;\n\n /**\n * The relative file path from the project root.\n */\n readonly filePath: string;\n\n /**\n * Overwrite this template file to it's original state?\n *\n * @default false\n */\n readonly overwrite?: boolean;\n}\n\nexport class ServiceTemplate {\n /**\n * The file being generated.\n */\n public file?: SampleFile;\n\n /**\n * Absolute Filepath, including the project path.\n */\n public fullFilePath: string;\n\n constructor(\n public service: OpenHiService,\n public options: ServiceTemplateOptions,\n ) {\n /**\n * Determine the full file path for this file.\n */\n this.fullFilePath = [\n this.service.project.outdir,\n this.options.filePath,\n ].join(sep);\n\n /**\n * Build the template file.\n */\n this.createTemplate();\n }\n\n protected createTemplate() {\n if (this.options.overwrite) {\n this.overwriteTemplate();\n }\n\n this.file = new SampleFile(this.service.project, this.options.filePath, {\n contents: this.options.contents.join(\"\\n\"),\n });\n }\n\n public overwriteTemplate() {\n /**\n * Delete file, if it exists.\n */\n if (existsSync(this.fullFilePath)) {\n unlinkSync(this.fullFilePath);\n }\n this.file = undefined;\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/app.md\n */\n\nexport class SrcApp extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/app.ts\",\n contents: [\n `import { OpenHiApp, ${service.constructName} } from \"@openhi/constructs\";`,\n `import { CONFIG } from \"./config\";`,\n ``,\n `const app = new OpenHiApp({ config: CONFIG });`,\n ``,\n `const stacks = app.environments.map((e) => {`,\n ` return new ${service.constructName}(e, { config: e.config });`,\n `});`,\n ``,\n `export { app, stacks };`,\n ``,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/app-test.md\n */\n\nexport class SrcAppTest extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/app.test.ts\",\n contents: [\n `import { Template } from \"aws-cdk-lib/assertions\";`,\n `import { Code, type CodeConfig } from \"aws-cdk-lib/aws-lambda\";`,\n `import { stacks } from \"./app\"`,\n ``,\n `/** Replace volatile CDK asset S3 keys/buckets with static values for snapshot stability. */`,\n `function normalizeTemplateForSnapshot(template: Record<string, unknown>): Record<string, unknown> {`,\n ` const staticBucket = \"mock-assets-bucket\";`,\n ` const staticKey = \"mock-asset-key.zip\";`,\n ` const json = JSON.stringify(template);`,\n ` const normalized = json`,\n ` .replace(/\"S3Key\":\\\\s*\"[^\"]+\\\\.zip\"/g, \\`\"S3Key\": \"\\${staticKey}\"\\`)`,\n ` .replace(/\"S3Bucket\":\\\\s*\"[^\"]+\"/g, \\`\"S3Bucket\": \"\\${staticBucket}\"\\`);`,\n ` return JSON.parse(normalized) as Record<string, unknown>;`,\n `}`,\n ``,\n `let fromAssetMock: jest.SpyInstance;`,\n ``,\n `beforeAll(() => {`,\n ` fromAssetMock = jest.spyOn(Code, \"fromAsset\").mockReturnValue({`,\n ` isInline: false,`,\n ` bind: (): CodeConfig => ({`,\n ` s3Location: {`,\n ` bucketName: \"mock-assets-bucket\",`,\n ` objectKey: \"mock-asset-key.zip\",`,\n ` },`,\n ` }),`,\n ` bindToResource: () => {`,\n ` return;`,\n ` },`,\n ` } as any);`,\n `});`,\n ``,\n `afterAll(() => {`,\n ` fromAssetMock?.mockRestore();`,\n `});`,\n ``,\n `describe(\"Smoke Test\", () => {`,\n ` it(\"should match previous snapshots\", () => {`,\n ` stacks.forEach((s) => {`,\n ` const template = Template.fromStack(s).toJSON();`,\n ` expect(normalizeTemplateForSnapshot(template)).toMatchSnapshot();`,\n ` });`,\n ` });`,\n `});`,\n ``,\n ],\n });\n }\n}\n","import { SourceCode } from \"projen\";\nimport { OpenHiService } from \"../../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/config.md\n */\n\nexport class SrcConfig extends SourceCode {\n constructor(service: OpenHiService) {\n super(service.project, \"src/config.ts\");\n\n /**\n * Imports\n */\n this.line(`import { OpenHiConfig } from \"@openhi/config\";`);\n this.line(\"\");\n\n /**\n * Write the config content\n */\n const start = \"export const CONFIG: OpenHiConfig = \";\n const mid = JSON.stringify(service.options?.config, null, 2);\n const end = \" as const;\";\n this.line(`${start}${mid}${end}`);\n }\n}\n","import { OpenHiService } from \"../../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/data/models/readme.md\n */\n\nexport class DataModelsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/data/models/README.md\",\n contents: [\n `# ${service.serviceName}: Data Models`,\n ``,\n `This directory contains data model definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/data/readme.md\n */\n\nexport class DataReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/data/README.md\",\n contents: [\n `# ${service.serviceName}: Data`,\n ``,\n `This directory contains data models and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/infrastructure/readme.md\n */\n\nexport class InfrastructureReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/infrastructure/README.md\",\n contents: [\n `# ${service.serviceName}: Infrastructure`,\n ``,\n `This directory contains infrastructure definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/integrations/readme.md\n */\n\nexport class IntegrationsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/integrations/README.md\",\n contents: [\n `# ${service.serviceName}: Integrations`,\n ``,\n `This directory contains integration definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/main.md\n */\n\nexport class SrcMain extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/main.ts\",\n contents: [`import { app } from \"./app\";`, ``, `app.synth();`, ``],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/readme.md\n */\n\nexport class SrcReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/README.md\",\n contents: [\n `# ${service.serviceName}: Service Overview`,\n ``,\n `This directory contains the main entry point for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/workflows/readme.md\n */\n\nexport class WorkflowsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/workflows/README.md\",\n contents: [\n `# ${service.serviceName}: Workflows`,\n ``,\n `This directory contains workflow definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../service\";\nimport { SrcApp } from \"./src/app\";\nimport { SrcAppTest } from \"./src/app-test\";\nimport { SrcConfig } from \"./src/config\";\nimport { DataModelsReadMe } from \"./src/data/models/README.md\";\nimport { DataReadMe } from \"./src/data/README.md\";\nimport { InfrastructureReadMe } from \"./src/infrastructure/README.md\";\nimport { IntegrationsReadMe } from \"./src/integrations/README.md\";\nimport { SrcMain } from \"./src/main\";\nimport { SrcReadMe } from \"./src/README.md\";\nimport { WorkflowsReadMe } from \"./src/workflows/README.md\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/generate-templates.md\n */\n\nexport class GenerateTemplates {\n constructor(private service: OpenHiService) {\n /**\n * Root src templates\n */\n new SrcApp(this.service);\n new SrcAppTest(this.service);\n new SrcConfig(this.service);\n new SrcMain(this.service);\n new SrcReadMe(this.service);\n\n /**\n * Data\n */\n new DataReadMe(this.service);\n new DataModelsReadMe(this.service);\n\n /**\n * Infrastructure\n */\n new InfrastructureReadMe(this.service);\n\n /**\n * Integrations\n */\n new IntegrationsReadMe(this.service);\n\n /**\n * Workflows\n */\n new WorkflowsReadMe(this.service);\n }\n}\n","import {\n AwsDeploymentConfig,\n MonorepoProject,\n} from \"@codedrifters/configulator\";\nimport { OPEN_HI_STAGE } from \"@openhi/config\";\nimport { Component } from \"projen\";\nimport { GitHub, GithubWorkflow } from \"projen/lib/github\";\nimport { JobPermission } from \"projen/lib/github/workflows-model\";\nimport { OpenHi } from \"../openhi\";\nimport type { OpenHiService } from \"../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/aws-teardown-workflow.md\n */\n\nexport interface AwsTeardownWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class AwsTeardownWorkflow extends Component {\n constructor(\n public rootProject: MonorepoProject,\n options: AwsTeardownWorkflowOptions,\n ) {\n super(rootProject);\n\n const { openhi } = options;\n\n /***************************************************************************\n *\n * Root project check\n *\n * Detect the root project and ensure it's of type MonorepoProject.\n *\n **************************************************************************/\n\n if (!(rootProject instanceof MonorepoProject)) {\n throw new Error(\n \"AwsTeardownWorkflow requires the root project to be a MonorepoProject\",\n );\n }\n\n //this.rootProject = project.root;\n\n /***************************************************************************\n *\n * GitHub Check\n *\n * Make sure github config is active in the project. This is to ensure all\n * workflows will be output properly during synth.\n *\n **************************************************************************/\n\n const github = GitHub.of(this.rootProject);\n\n if (!github) {\n throw new Error(\n \"AwsTeardownWorkflow requires a GitHub component in the root project\",\n );\n }\n\n /***************************************************************************\n *\n * Workflow Destroy Targets\n *\n * Find all the CI targets for the Global project in the DEV stage\n * only. One job per (account, region) teardowns all orphan stacks (Auth,\n * Core, data) in that account/region.\n *\n **************************************************************************/\n\n const devTargetsFor = (service: OpenHiService) =>\n AwsDeploymentConfig.of(service.project)?.awsDeploymentTargets.filter(\n (target) =>\n target.awsStageType === OPEN_HI_STAGE.DEV && target.ciDeployment,\n ) ?? [];\n const awsDestructionTargets = devTargetsFor(openhi.global);\n\n /***************************************************************************\n *\n * Create Workflow\n *\n * Make a new workflow for AWS stack teardown. This runs each night and is\n * also triggered each time a branch is deleted.\n *\n **************************************************************************/\n\n const workflow = new GithubWorkflow(github, \"teardown-dev\");\n workflow.on({\n workflowDispatch: {},\n schedule: [\n {\n cron: \"32 6 * * *\", // Every Sunday at 6:32 AM UTC\n },\n ],\n delete: {\n branches: [\"feature/*\", \"feat/*\", \"fix/*\"],\n },\n /* for debugging \n push: {\n branches: [\"feature/*\"],\n },\n */\n });\n\n awsDestructionTargets.forEach((target) => {\n const {\n awsStageType,\n awsEnvironmentType,\n account,\n region,\n ciDeploymentConfig,\n } = target;\n const { roleArn } = ciDeploymentConfig ?? {};\n\n workflow.addJob(`teardown-${account}-${region}`.toLowerCase(), {\n name: `Teardown Stacks in ${target.account}/${target.region}`,\n //if: \"github.event.ref_type == 'branch'\",\n runsOn: [\"ubuntu-latest\"],\n permissions: {\n contents: JobPermission.READ,\n idToken: JobPermission.WRITE,\n },\n env: {\n REPO: \"${{ github.repository }}\",\n REGIONS: [region].join(\" \"),\n },\n steps: [\n /**\n * Configure AWS creds.\n */\n {\n name: `AWS Creds ${awsStageType}/${awsEnvironmentType}/${account}/${region}`,\n uses: \"aws-actions/configure-aws-credentials@v4\",\n with: {\n \"role-to-assume\": roleArn,\n \"aws-region\": region,\n \"role-duration-seconds\": 900, // 15 minutes\n },\n },\n\n /**\n * Fetch all branch names in the repo\n */\n {\n name: \"Fetch All Branches\",\n id: \"fetch_branches\",\n uses: \"actions/github-script@v7\",\n with: {\n script: [\n \"const all = await github.paginate(github.rest.repos.listBranches, {\",\n \" owner: context.repo.owner,\",\n \" repo: context.repo.repo,\",\n \" per_page: 100\",\n \"});\",\n \"const names = all.map(b => b.name);\",\n \"console.log(`Found branches: ${names}`);\",\n 'core.setOutput(\"json\", JSON.stringify(names));',\n ].join(\"\\n\"),\n },\n },\n\n /**\n * Save branches to a file\n */\n {\n name: \"Save Branches to File\",\n run: [\n 'echo \"Saving branches to file\"',\n \"echo '${{ steps.fetch_branches.outputs.json }}' | jq -r '.[]' | sort -u > branches.txt\",\n 'echo \"Branches:\"',\n \"cat branches.txt\",\n ].join(\"\\n\"),\n },\n\n /**\n * Find all stacks tagged with a stage of dev. for this repo. return\n * tag and resource arn.\n */\n {\n name: \"Find Stacks by Tag\",\n id: \"find_stacks\",\n run: [\n \"set -euo pipefail\",\n \": > candidates.txt # columns: arn region branchTag\",\n\n \"# Build tag filters\",\n 'TAG_FILTERS=( \"Key=openhi:repo-name,Values=$REPO\" )',\n `TAG_FILTERS+=( \"Key=openhi:stage-type,Values=${OPEN_HI_STAGE.DEV}\" )`,\n\n \"for r in $REGIONS; do\",\n ` echo \"Scanning region: $r\"`,\n \" aws resourcegroupstaggingapi get-resources \\\\\",\n ' --region \"$r\" \\\\',\n ' --resource-type-filters \"cloudformation:stack\" \\\\',\n ' --tag-filters \"${TAG_FILTERS[@]}\" \\\\',\n ` | jq -r --arg r \"$r\" '`,\n \" .ResourceTagMappingList[]\",\n \" | . as $res\",\n ' | ($res.Tags[] | select(.Key==\"openhi:branch-name\") | .Value) as $branch',\n ' | [$res.ResourceARN, $r, ($branch // \"\")]',\n \" | @tsv\",\n \" ' >> candidates.txt\",\n \"done\",\n\n \"echo 'Tagged stacks:'\",\n `(echo -e \"ARN\\\\tREGION\\\\tBRANCH\"; cat candidates.txt) | column -t -s $'\\\\t'`,\n ].join(\"\\n\"),\n },\n\n /**\n * Determine which stacks are orphans that no longer have a matching branch.\n * Save those to a file for the next step.\n */\n {\n name: \"Determine Orphan Stacks (No Matching Branch)\",\n run: [\n \"set -euo pipefail\",\n \": > orphans.txt # arn region branch\",\n \"while IFS=$'\\\\t' read -r arn region branch; do\",\n ' [ -z \"$arn\" ] && continue',\n ' if [ -z \"$branch\" ]; then',\n \" # If no Branch tag, treat as not-a-preview; skip (or flip to delete if you want)\",\n \" continue\",\n \" fi\",\n ' if ! grep -Fxq \"$branch\" branches.txt; then',\n ' echo -e \"$arn\\\\t$region\\\\t$branch\" >> orphans.txt',\n \" fi\",\n \"done < candidates.txt\",\n \"\",\n \"if [ -s orphans.txt ]; then\",\n ' echo \"Orphan stacks (no matching branch):\"',\n \" (echo -e \\\"ARN\\\\tREGION\\\\tBRANCH\\\"; cat orphans.txt) | column -t -s $'\\\\t'\",\n \"else\",\n ' echo \"No orphan stacks found.\"',\n \"fi\",\n ].join(\"\\n\"),\n },\n\n /**\n * Delete orphan stacks.\n */\n {\n name: \"Delete Orphan Stacks\",\n if: \"hashFiles('orphans.txt') != ''\",\n run: [\n \"set -euo pipefail\",\n \"while IFS=$'\\\\t' read -r arn region branch; do\",\n ' [ -z \"$arn\" ] && continue',\n \" stack_name=$(cut -d'/' -f2 <<<\\\"$arn\\\")\",\n ' echo \"Deleting $stack_name (branch=$branch) in $region\"',\n ' aws cloudformation delete-stack --region \"$region\" --stack-name \"$stack_name\" || true',\n \"done < orphans.txt\",\n ].join(\"\\n\"),\n },\n ],\n });\n });\n }\n}\n","import { AwsDeployWorkflow, MonorepoProject } from \"@codedrifters/configulator\";\nimport { Component } from \"projen\";\nimport { OpenHi } from \"../openhi\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/build-dev-workflow.md\n */\n\nexport interface BuildDevelopmentWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class BuildDevelopmentWorkflow extends Component {\n constructor(\n parent: MonorepoProject,\n options: BuildDevelopmentWorkflowOptions,\n ) {\n super(parent, \"dev-workflow\");\n\n const { openhi } = options;\n\n /**\n * Global Service Deploy\n *\n * Deploy the Global service first to configure DNS\n */\n const { awsDeploymentTargets: globalTargets } = new AwsDeployWorkflow(\n openhi.global.project,\n {\n buildWorkflow: parent.buildWorkflow,\n },\n );\n\n /**\n * Auth Service Deploy\n *\n * Deploy the Auth service first (Cognito); data service and other stacks consume auth via SSM.\n */\n const { awsDeploymentTargets: authTargets } = new AwsDeployWorkflow(\n openhi.auth.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets],\n },\n );\n\n /**\n * Data Service Deploy\n *\n * Deploy the Data service (DynamoDB FHIR store, S3) after Global.\n */\n const { awsDeploymentTargets: dataTargets } = new AwsDeployWorkflow(\n openhi.data.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets],\n },\n );\n\n /**\n * Rest API Service Deploy\n *\n * Deploy the Rest API service after Data (and Global).\n */\n const { awsDeploymentTargets: restApiTargets } = new AwsDeployWorkflow(\n openhi.restApi.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n },\n );\n\n /**\n * GraphQL API Service Deploy\n *\n * Deploy the GraphQL API service after Data (sibling to REST API).\n */\n new AwsDeployWorkflow(openhi.graphApi.project, {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n });\n\n /**\n * Website Service Deploy\n *\n * Deploy the Website service after Global and REST API. The website\n * stack's CloudFront distribution fronts the REST API via an\n * `/api/*` behavior whose origin host is resolved at CFN update time\n * from the `REST_API_DOMAIN_NAME` SSM parameter — that parameter is\n * written by the matching branch's rest-api stack, so rest-api must\n * deploy first. The Global dependency holds for the child hosted zone\n * and wildcard certificate. Auth no longer needs to be upstream — the\n * Cognito IDs are exposed via the REST API's runtime-config endpoint\n * at request time, not via CFN dynamic references at update time.\n */\n new AwsDeployWorkflow(openhi.website.project, {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...restApiTargets],\n });\n }\n}\n","import { AwsDeployWorkflow, MonorepoProject } from \"@codedrifters/configulator\";\nimport { OPEN_HI_STAGE } from \"@openhi/config\";\nimport { Component } from \"projen\";\nimport { OpenHi } from \"../openhi\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/build-stage-workflow.md\n */\n\nexport interface BuildStageWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class BuildStageWorkflow extends Component {\n constructor(parent: MonorepoProject, options: BuildStageWorkflowOptions) {\n super(parent, \"stage-workflow\");\n\n const { openhi } = options;\n\n /**\n * Global Service Deploy\n *\n * Deploy the Global service first to configure DNS\n */\n const { awsDeploymentTargets: globalTargets, buildWorkflow } =\n new AwsDeployWorkflow(openhi.global.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflowOptions: {\n name: \"deploy-stage\",\n workflowTriggers: {\n push: {\n branches: [\"main\"],\n },\n workflowDispatch: {},\n },\n },\n });\n\n /**\n * Auth Service Deploy\n *\n * Deploy the Auth service first (Cognito); data service and other stacks consume auth via SSM.\n * Auth creates the stage build workflow; data service and REST API services add to it.\n */\n const { awsDeploymentTargets: authTargets } = new AwsDeployWorkflow(\n openhi.auth.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets],\n },\n );\n\n /**\n * Data Service Deploy\n *\n * Deploy the Data service (DynamoDB FHIR store, S3) after Global.\n */\n const { awsDeploymentTargets: dataTargets } = new AwsDeployWorkflow(\n openhi.data.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets],\n },\n );\n\n /**\n * Rest API Service Deploy\n */\n const { awsDeploymentTargets: restApiTargets } = new AwsDeployWorkflow(\n openhi.restApi.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n },\n );\n\n /**\n * GraphQL API Service Deploy\n */\n new AwsDeployWorkflow(openhi.graphApi.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n });\n\n /**\n * Website Service Deploy\n *\n * Deploy the Website service after Global and REST API. The website\n * stack's CloudFront distribution fronts the REST API via an\n * `/api/*` behavior whose origin host is resolved at CFN update time\n * from the `REST_API_DOMAIN_NAME` SSM parameter — that parameter is\n * written by the matching branch's rest-api stack, so rest-api must\n * deploy first. The Global dependency holds for the child hosted zone\n * and wildcard certificate. Auth no longer needs to be upstream — the\n * Cognito IDs are exposed via the REST API's runtime-config endpoint\n * at request time, not via CFN dynamic references at update time.\n */\n new AwsDeployWorkflow(openhi.website.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...restApiTargets],\n });\n }\n}\n"],"mappings":"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","names":["exports","exports","import_config","import_projen","import_projen","import_configulator","import_config","import_projen","import_configulator","import_projen","import_configulator","import_config","import_projen"]}
|
|
1
|
+
{"version":3,"sources":["../../config/src/open-hi-config.ts","../../config/src/index.ts","../src/index.ts","../src/openhi.ts","../src/service.ts","../src/templates/service-template.ts","../src/templates/src/app.ts","../src/templates/src/app-test.ts","../src/templates/src/config.ts","../src/templates/src/data/models/README.md.ts","../src/templates/src/data/README.md.ts","../src/templates/src/infrastructure/README.md.ts","../src/templates/src/integrations/README.md.ts","../src/templates/src/main.ts","../src/templates/src/README.md.ts","../src/templates/src/workflows/README.md.ts","../src/templates/generate-templates.ts","../src/workflows/aws-teardown-workflow.ts","../src/workflows/build-dev-workflow.ts","../src/workflows/build-stage-workflow.ts"],"sourcesContent":["/*******************************************************************************\n *\n * OpenHi Config\n *\n * These types are kept in their own package to prevent dependency conflicts and\n * conditions between @openhi/constructs and @openhi/platform..\n *\n ******************************************************************************/\n\n/**\n * Stage Types\n *\n * What stage of deployment is this? Dev, staging, or prod?\n */\nexport const OPEN_HI_STAGE = {\n /**\n * Development environment, typically used for testing and development.\n */\n DEV: \"dev\",\n /**\n * Staging environment, used for pre-production testing.\n */\n STAGE: \"stage\",\n /**\n * Production environment, used for live deployments.\n */\n PROD: \"prod\",\n} as const;\n\n/**\n * Above const as a type.\n */\nexport type OpenHiStageType =\n (typeof OPEN_HI_STAGE)[keyof typeof OPEN_HI_STAGE];\n\n/**\n * Deployment Target Role\n *\n * Is this (account, region) the primary or a secondary deployment target for the stage?\n * Works for both multi-region (different regions) and cellular (same region, different accounts).\n */\nexport const OPEN_HI_DEPLOYMENT_TARGET_ROLE = {\n /**\n * The primary deployment target for this stage (main account/region).\n * For example, the base DynamoDB region for global tables.\n */\n PRIMARY: \"primary\",\n\n /**\n * A secondary deployment target for this stage (additional account/region).\n * For example, a replica region for a global DynamoDB table, or another cell in the same region.\n */\n SECONDARY: \"secondary\",\n} as const;\n\n/**\n * Above const as a type.\n */\nexport type OpenHiDeploymentTargetRoleType =\n (typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE)[keyof typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE];\n\nexport interface OpenHiEnvironmentConfig {\n account: string;\n region: string;\n /**\n * Route53 zone containing DNS for this service.\n */\n hostedZoneId?: string;\n zoneName?: string;\n}\n\n/**\n * Represents the configuration for OpenHi services across different stages and\n * deployment targets.\n */\nexport interface OpenHiConfig {\n versions?: {\n cdk?: {\n cdkLibVersion?: string;\n cdkCliVersion?: string;\n };\n };\n deploymentTargets?: {\n [OPEN_HI_STAGE.DEV]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n [OPEN_HI_STAGE.STAGE]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n [OPEN_HI_STAGE.PROD]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n };\n}\n","export * from \"./open-hi-config\";\n","/**\n * @see sites/www-docs/content/packages/@openhi/platform/index.md\n */\n/** @openhi/platform — root barrel exports. */\nexport * from \"./openhi\";\nexport * from \"./service\";\n","import {\n MonorepoProject,\n MonorepoProjectOptions,\n} from \"@codedrifters/configulator\";\nimport { OpenHiConfig } from \"@openhi/config\";\nimport { merge } from \"ts-deepmerge\";\nimport { SetOptional } from \"type-fest\";\nimport { OPEN_HI_SERVICE_TYPE, OpenHiService } from \"./service\";\nimport { AwsTeardownWorkflow } from \"./workflows/aws-teardown-workflow\";\nimport { BuildDevelopmentWorkflow } from \"./workflows/build-dev-workflow\";\nimport { BuildStageWorkflow } from \"./workflows/build-stage-workflow\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/openhi.md\n */\n\nexport interface OpenHiOptions {\n /*****************************************************************************\n *\n * Root Project Configuration Options\n *\n * Configuration options for the root monorepo project that contains all\n * OpenHi services and coordinate releases and builds.\n *\n ****************************************************************************/\n\n readonly rootProjectOptions?: SetOptional<MonorepoProjectOptions, \"name\">;\n\n /**\n * Monorepo root project, if using an existing project.\n */\n readonly rootProject?: MonorepoProject;\n\n /*****************************************************************************\n *\n * Service Configuration Options\n *\n * These options are used to configure the various services within the OpenHi\n * framework. Each service can have its own configuration settings, which will\n * be merged with the default configuration.\n *\n ****************************************************************************/\n\n /**\n * Default configuration used in all services with undefined configs.\n */\n readonly defaultConfig?: OpenHiConfig;\n\n /**\n * Global Service Config\n */\n readonly globalServiceConfig?: OpenHiConfig;\n\n /**\n * Auth Service Config\n */\n readonly authServiceConfig?: OpenHiConfig;\n\n /**\n * Rest API Service Config\n */\n readonly restApiServiceConfig?: OpenHiConfig;\n\n /**\n * Data Service Config (DynamoDB FHIR store, S3, etc.)\n */\n readonly dataServiceConfig?: OpenHiConfig;\n\n /**\n * GraphQL API Service Config\n */\n readonly graphApiServiceConfig?: OpenHiConfig;\n\n /**\n * Website Service Config (static hosting + content uploader).\n */\n readonly websiteServiceConfig?: OpenHiConfig;\n}\n\nexport class OpenHi {\n /**\n * Final options used to build this instance.\n */\n public options: OpenHiOptions;\n\n /**\n * Monorepo root project, either passed in as an argument or generated in\n * this component\n */\n public readonly rootProject?: MonorepoProject;\n\n /**\n * Test identifier for this instance.\n */\n public readonly id: string;\n\n /**\n * Global service (deployed first; Auth, data service, and other stacks depend on it).\n */\n public readonly global: OpenHiService;\n\n /**\n * Auth service (deployed first; data service, REST API, and data services depend on it).\n */\n public readonly auth: OpenHiService;\n\n /**\n * Rest API service\n */\n public readonly restApi: OpenHiService;\n\n /**\n * Data service (DynamoDB FHIR store, S3, and other persistence).\n */\n public readonly data: OpenHiService;\n\n /**\n * GraphQL API service (AppSync); deploys as sibling to REST API after Data.\n */\n public readonly graphApi: OpenHiService;\n\n /**\n * Website service (static hosting + content uploader); deploys as sibling\n * to the other services after Global.\n */\n public readonly website: OpenHiService;\n\n constructor(options: OpenHiOptions = {}) {\n /***************************************************************************\n *\n * Options\n *\n * Combine input options with defaults.\n *\n **************************************************************************/\n\n this.options = merge({ name: \"openhi\" }, options);\n this.rootProject = this.options.rootProject;\n this.id = this.options.rootProject?.name ?? \"openhi\";\n\n /**\n * In future we would create root project here. For now, require it to be\n * passed in.\n */\n if (!this.rootProject) {\n throw new Error(\n \"OpenHi requires a MonorepoProject to be passed in via the rootProject option\",\n );\n }\n\n const rootProject = this.rootProject;\n\n /***************************************************************************\n *\n * Global Service\n *\n * Global infrastructure (Route53, ACM). Deployed first in primary;\n * Auth, data service, and other stacks depend on it.\n *\n **************************************************************************/\n\n this.global = new OpenHiService(this, \"global\", {\n type: OPEN_HI_SERVICE_TYPE.GLOBAL,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.globalServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Auth Service\n *\n * Authentication (Cognito user pool, client, domain, KMS). Deployed first;\n * data service, REST API, and data services consume auth via SSM.\n *\n **************************************************************************/\n\n this.auth = new OpenHiService(this, \"auth\", {\n type: OPEN_HI_SERVICE_TYPE.AUTH,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.authServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Rest API service\n *\n * This contains the REST API for the OpenHi platform.\n *\n **************************************************************************/\n\n this.restApi = new OpenHiService(this, \"rest-api\", {\n type: OPEN_HI_SERVICE_TYPE.REST_API,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.restApiServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Data Service\n *\n * Data storage stack (DynamoDB FHIR store, S3, etc.). Deployed so that\n * REST API and other services can reference the table via cross-stack.\n *\n **************************************************************************/\n\n this.data = new OpenHiService(this, \"data\", {\n type: OPEN_HI_SERVICE_TYPE.DATA_SERVICE,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.dataServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * GraphQL API service\n *\n * AppSync API; deploys as sibling to REST API after Data.\n *\n **************************************************************************/\n\n this.graphApi = new OpenHiService(this, \"graphql\", {\n type: OPEN_HI_SERVICE_TYPE.GRAPHQL,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.graphApiServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Website service\n *\n * Static hosting (CloudFront + S3 + Lambda@Edge) and content uploader;\n * deploys as a sibling to the other services after Global.\n *\n **************************************************************************/\n\n this.website = new OpenHiService(this, \"website\", {\n type: OPEN_HI_SERVICE_TYPE.WEBSITE,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.websiteServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Integrations\n *\n * Various purpose specific integrations.\n *\n **************************************************************************/\n\n /***************************************************************************\n *\n * Workflows\n *\n * Workflows for each environment.\n *\n **************************************************************************/\n\n new BuildDevelopmentWorkflow(rootProject, { openhi: this });\n new BuildStageWorkflow(rootProject, { openhi: this });\n\n new AwsTeardownWorkflow(rootProject, { openhi: this });\n }\n}\n","import { sep } from \"path\";\nimport {\n AwsDeploymentTarget,\n TurboRepo,\n VERSION,\n} from \"@codedrifters/configulator\";\nimport {\n OPEN_HI_DEPLOYMENT_TARGET_ROLE,\n OPEN_HI_STAGE,\n OpenHiConfig,\n OpenHiEnvironmentConfig,\n} from \"@openhi/config\";\nimport { paramCase, pascalCase } from \"change-case\";\nimport { awscdk } from \"projen\";\nimport { NodePackageManager, Transform } from \"projen/lib/javascript\";\nimport { ValueOf } from \"type-fest\";\nimport { OpenHi } from \"./openhi\";\nimport { GenerateTemplates } from \"./templates/generate-templates\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/service.md\n */\n\nexport const OPEN_HI_SERVICE_TYPE = {\n AUTH: \"auth\",\n DATA_SERVICE: \"data\",\n GLOBAL: \"global\",\n GRAPHQL: \"graphql\",\n INTEGRATION: \"integration\",\n REST_API: \"rest-api\",\n WEBSITE: \"website\",\n} as const;\n\nexport interface OpenHiServiceOptions {\n /**\n * Configuration for this service.\n *\n * @default uses the global default config.\n */\n readonly config: OpenHiConfig;\n\n /**\n * What type of service is this?\n */\n readonly type: ValueOf<typeof OPEN_HI_SERVICE_TYPE>;\n}\n\nexport class OpenHiService {\n public readonly project: awscdk.AwsCdkTypeScriptApp;\n\n constructor(\n public openHi: OpenHi,\n public id: string,\n public options: OpenHiServiceOptions,\n ) {\n /**\n * Build the construct name we expect to use in this service.\n */\n\n /***************************************************************************\n *\n * Projen based CDK build\n *\n **************************************************************************/\n\n this.project = new awscdk.AwsCdkTypeScriptApp({\n /**\n * Top level project config options\n */\n defaultReleaseBranch: \"main\",\n name: this.serviceName,\n outdir: this.outDir,\n parent: this.openHi.rootProject,\n cdkVersion:\n this.options?.config?.versions?.cdk?.cdkLibVersion ??\n VERSION.AWS_CDK_LIB_VERSION,\n cdkCliVersion:\n this.options?.config?.versions?.cdk?.cdkCliVersion ??\n VERSION.AWS_CDK_CLI_VERSION,\n\n /**\n * Packaging options\n *\n * TODO: Figure out license for monorepo vs per package?\n */\n licensed: false,\n\n /**\n * Node configs\n */\n packageManager: NodePackageManager.PNPM,\n\n /**\n * Turn on prettier formatting\n */\n prettier: true,\n\n /**\n * Don't generate sample code.\n */\n sampleCode: false,\n\n /**\n * Make sure jest config is stored outside of package.json and use SWC\n * for faster tests.\n */\n jestOptions: {\n configFilePath: \"jest.config.json\",\n jestConfig: {\n transform: {\n [\"^.+\\\\.[t]sx?$\"]: new Transform(\"@swc/jest\"),\n },\n },\n },\n\n /**\n * SWC for faster testing\n */\n devDeps: [\"@swc/jest\", \"@swc/core\"],\n\n /**\n * Don't package test files.\n */\n npmIgnoreOptions: {\n ignorePatterns: [\"*.spec.*\", \"*.test.*\"],\n },\n });\n\n /**\n * We're using SWC now, remove ts-jest which is included by default.\n */\n this.project.deps.removeDependency(\"ts-jest\");\n\n /***************************************************************************\n *\n * Workspace Dependencies\n *\n * - Constructs are used to build out the AWS CDK environments.\n *\n **************************************************************************/\n\n this.project.addDeps(\n \"@openhi/config@workspace:*\",\n \"@openhi/constructs@workspace:*\",\n );\n\n /***************************************************************************\n *\n * Turbo Configuration\n *\n * - Activate turborepo for the project.\n *\n **************************************************************************/\n\n new TurboRepo(this.project);\n\n TurboRepo.of(this.project)?.activateBranchNameEnvVar({\n tasks: [\"post-compile\"],\n });\n\n /**\n * The website service composes its hostname (and the S3 key prefix\n * the lifecycle rule expires) from the OPENHI_PR_NUMBER env var on\n * non-release-branch synths. Turborepo strips env vars that are\n * not declared on the task, so the value reaches the workflow's\n * `env:` block but never reaches the `cdk synth` subprocess that\n * the post-compile task runs. Add OPENHI_PR_NUMBER to the\n * post-compile task env so Turborepo passes it through.\n *\n * Scoped to the website project — no other service reads\n * OPENHI_PR_NUMBER, so adding it elsewhere would only cause\n * spurious per-PR cache misses on cdk synth.\n */\n if (this.options.type === OPEN_HI_SERVICE_TYPE.WEBSITE) {\n const turbo = TurboRepo.of(this.project);\n const postCompileEnv = turbo?.postCompileTask?.env;\n if (postCompileEnv && !postCompileEnv.includes(\"OPENHI_PR_NUMBER\")) {\n postCompileEnv.push(\"OPENHI_PR_NUMBER\");\n }\n }\n\n /***************************************************************************\n *\n * Define some basic Service Structure\n *\n **************************************************************************/\n\n new GenerateTemplates(this);\n\n /***************************************************************************\n *\n * Deployment Targets\n *\n **************************************************************************/\n\n [OPEN_HI_STAGE.DEV, OPEN_HI_STAGE.STAGE, OPEN_HI_STAGE.PROD].forEach(\n (stage) => {\n const targets = this.options?.config?.deploymentTargets?.[stage];\n if (targets?.primary) {\n this.addDeploymentTarget(\n stage,\n OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY,\n targets.primary,\n );\n }\n targets?.secondary?.forEach((env) => {\n this.addDeploymentTarget(\n stage,\n OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY,\n env,\n );\n });\n },\n );\n }\n\n private addDeploymentTarget = (\n awsStageType: ValueOf<typeof OPEN_HI_STAGE>,\n awsEnvironmentType: ValueOf<typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE>,\n envConfig: OpenHiEnvironmentConfig,\n ) => {\n new AwsDeploymentTarget(this.project, {\n account: envConfig.account,\n region: envConfig.region,\n awsStageType,\n awsEnvironmentType,\n localDeployment: true,\n localDeploymentConfig: {\n stackPattern: `${awsStageType}/${awsEnvironmentType}/*-${envConfig.account}-${envConfig.region}`,\n roleName: \"poweruseraccess\",\n },\n ciDeployment: true,\n ciDeploymentConfig: {\n roleArn: `arn:aws:iam::${envConfig.account}:role/GitHubOpenHiDeployer`,\n stackPattern: `${awsStageType}/${awsEnvironmentType}/*-${envConfig.account}-${envConfig.region}`,\n },\n\n branches:\n awsStageType === OPEN_HI_STAGE.DEV\n ? [\n {\n branch: \"feat/*\",\n description: [\n \"Feature branches for OpenHI (short form).\",\n \"These branches are used for developing new features.\",\n ],\n },\n {\n branch: \"feature/*\",\n description: [\n \"Feature branches for OpenHI.\",\n \"These branches are used for developing new features.\",\n ],\n },\n {\n branch: \"fix/*\",\n description: [\n \"Fix branches for OpenHI.\",\n \"This branch pattern is used when a developer is working on a fix on the project.\",\n ],\n },\n ]\n : [\n {\n branch: \"main\",\n description: [\n \"Main branch for OpenHI.\",\n \"This branch is used for the main branch.\",\n ],\n },\n ],\n });\n };\n\n get constructName(): string {\n return pascalCase([\"open\", \"hi\", this.id, \"service\"].join(\"-\"));\n }\n\n get outDir() {\n return [paramCase(this.openHi.id), paramCase(this.id)].join(sep);\n }\n\n get serviceName() {\n return [paramCase(this.openHi.id), paramCase(this.id)].join(\"-\");\n }\n}\n","import { existsSync, unlinkSync } from \"node:fs\";\nimport { sep } from \"node:path\";\nimport { SampleFile } from \"projen\";\nimport { OpenHiService } from \"../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/service-template.md\n */\n\nexport interface ServiceTemplateOptions {\n /**\n * The content of the sample file, as an array.\n */\n readonly contents: Array<string>;\n\n /**\n * The relative file path from the project root.\n */\n readonly filePath: string;\n\n /**\n * Overwrite this template file to it's original state?\n *\n * @default false\n */\n readonly overwrite?: boolean;\n}\n\nexport class ServiceTemplate {\n /**\n * The file being generated.\n */\n public file?: SampleFile;\n\n /**\n * Absolute Filepath, including the project path.\n */\n public fullFilePath: string;\n\n constructor(\n public service: OpenHiService,\n public options: ServiceTemplateOptions,\n ) {\n /**\n * Determine the full file path for this file.\n */\n this.fullFilePath = [\n this.service.project.outdir,\n this.options.filePath,\n ].join(sep);\n\n /**\n * Build the template file.\n */\n this.createTemplate();\n }\n\n protected createTemplate() {\n if (this.options.overwrite) {\n this.overwriteTemplate();\n }\n\n this.file = new SampleFile(this.service.project, this.options.filePath, {\n contents: this.options.contents.join(\"\\n\"),\n });\n }\n\n public overwriteTemplate() {\n /**\n * Delete file, if it exists.\n */\n if (existsSync(this.fullFilePath)) {\n unlinkSync(this.fullFilePath);\n }\n this.file = undefined;\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/app.md\n */\n\nexport class SrcApp extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/app.ts\",\n contents: [\n `import { OpenHiApp, ${service.constructName} } from \"@openhi/constructs\";`,\n `import { CONFIG } from \"./config\";`,\n ``,\n `const app = new OpenHiApp({ config: CONFIG });`,\n ``,\n `const stacks = app.environments.map((e) => {`,\n ` return new ${service.constructName}(e, { config: e.config });`,\n `});`,\n ``,\n `export { app, stacks };`,\n ``,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/app-test.md\n */\n\nexport class SrcAppTest extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/app.test.ts\",\n contents: [\n `import { Template } from \"aws-cdk-lib/assertions\";`,\n `import { Code, type CodeConfig } from \"aws-cdk-lib/aws-lambda\";`,\n `import { stacks } from \"./app\"`,\n ``,\n `/** Replace volatile CDK asset S3 keys/buckets with static values for snapshot stability. */`,\n `function normalizeTemplateForSnapshot(template: Record<string, unknown>): Record<string, unknown> {`,\n ` const staticBucket = \"mock-assets-bucket\";`,\n ` const staticKey = \"mock-asset-key.zip\";`,\n ` const json = JSON.stringify(template);`,\n ` const normalized = json`,\n ` .replace(/\"S3Key\":\\\\s*\"[^\"]+\\\\.zip\"/g, \\`\"S3Key\": \"\\${staticKey}\"\\`)`,\n ` .replace(/\"S3Bucket\":\\\\s*\"[^\"]+\"/g, \\`\"S3Bucket\": \"\\${staticBucket}\"\\`);`,\n ` return JSON.parse(normalized) as Record<string, unknown>;`,\n `}`,\n ``,\n `let fromAssetMock: jest.SpyInstance;`,\n ``,\n `beforeAll(() => {`,\n ` fromAssetMock = jest.spyOn(Code, \"fromAsset\").mockReturnValue({`,\n ` isInline: false,`,\n ` bind: (): CodeConfig => ({`,\n ` s3Location: {`,\n ` bucketName: \"mock-assets-bucket\",`,\n ` objectKey: \"mock-asset-key.zip\",`,\n ` },`,\n ` }),`,\n ` bindToResource: () => {`,\n ` return;`,\n ` },`,\n ` } as any);`,\n `});`,\n ``,\n `afterAll(() => {`,\n ` fromAssetMock?.mockRestore();`,\n `});`,\n ``,\n `describe(\"Smoke Test\", () => {`,\n ` it(\"should match previous snapshots\", () => {`,\n ` stacks.forEach((s) => {`,\n ` const template = Template.fromStack(s).toJSON();`,\n ` expect(normalizeTemplateForSnapshot(template)).toMatchSnapshot();`,\n ` });`,\n ` });`,\n `});`,\n ``,\n ],\n });\n }\n}\n","import { SourceCode } from \"projen\";\nimport { OpenHiService } from \"../../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/config.md\n */\n\nexport class SrcConfig extends SourceCode {\n constructor(service: OpenHiService) {\n super(service.project, \"src/config.ts\");\n\n /**\n * Imports\n */\n this.line(`import { OpenHiConfig } from \"@openhi/config\";`);\n this.line(\"\");\n\n /**\n * Write the config content\n */\n const start = \"export const CONFIG: OpenHiConfig = \";\n const mid = JSON.stringify(service.options?.config, null, 2);\n const end = \" as const;\";\n this.line(`${start}${mid}${end}`);\n }\n}\n","import { OpenHiService } from \"../../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/data/models/readme.md\n */\n\nexport class DataModelsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/data/models/README.md\",\n contents: [\n `# ${service.serviceName}: Data Models`,\n ``,\n `This directory contains data model definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/data/readme.md\n */\n\nexport class DataReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/data/README.md\",\n contents: [\n `# ${service.serviceName}: Data`,\n ``,\n `This directory contains data models and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/infrastructure/readme.md\n */\n\nexport class InfrastructureReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/infrastructure/README.md\",\n contents: [\n `# ${service.serviceName}: Infrastructure`,\n ``,\n `This directory contains infrastructure definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/integrations/readme.md\n */\n\nexport class IntegrationsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/integrations/README.md\",\n contents: [\n `# ${service.serviceName}: Integrations`,\n ``,\n `This directory contains integration definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/main.md\n */\n\nexport class SrcMain extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/main.ts\",\n contents: [`import { app } from \"./app\";`, ``, `app.synth();`, ``],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/readme.md\n */\n\nexport class SrcReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/README.md\",\n contents: [\n `# ${service.serviceName}: Service Overview`,\n ``,\n `This directory contains the main entry point for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/workflows/readme.md\n */\n\nexport class WorkflowsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/workflows/README.md\",\n contents: [\n `# ${service.serviceName}: Workflows`,\n ``,\n `This directory contains workflow definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../service\";\nimport { SrcApp } from \"./src/app\";\nimport { SrcAppTest } from \"./src/app-test\";\nimport { SrcConfig } from \"./src/config\";\nimport { DataModelsReadMe } from \"./src/data/models/README.md\";\nimport { DataReadMe } from \"./src/data/README.md\";\nimport { InfrastructureReadMe } from \"./src/infrastructure/README.md\";\nimport { IntegrationsReadMe } from \"./src/integrations/README.md\";\nimport { SrcMain } from \"./src/main\";\nimport { SrcReadMe } from \"./src/README.md\";\nimport { WorkflowsReadMe } from \"./src/workflows/README.md\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/generate-templates.md\n */\n\nexport class GenerateTemplates {\n constructor(private service: OpenHiService) {\n /**\n * Root src templates\n */\n new SrcApp(this.service);\n new SrcAppTest(this.service);\n new SrcConfig(this.service);\n new SrcMain(this.service);\n new SrcReadMe(this.service);\n\n /**\n * Data\n */\n new DataReadMe(this.service);\n new DataModelsReadMe(this.service);\n\n /**\n * Infrastructure\n */\n new InfrastructureReadMe(this.service);\n\n /**\n * Integrations\n */\n new IntegrationsReadMe(this.service);\n\n /**\n * Workflows\n */\n new WorkflowsReadMe(this.service);\n }\n}\n","import {\n AwsDeploymentConfig,\n MonorepoProject,\n} from \"@codedrifters/configulator\";\nimport { OPEN_HI_STAGE } from \"@openhi/config\";\nimport { Component } from \"projen\";\nimport { GitHub, GithubWorkflow } from \"projen/lib/github\";\nimport { JobPermission } from \"projen/lib/github/workflows-model\";\nimport { OpenHi } from \"../openhi\";\nimport type { OpenHiService } from \"../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/aws-teardown-workflow.md\n */\n\nexport interface AwsTeardownWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class AwsTeardownWorkflow extends Component {\n constructor(\n public rootProject: MonorepoProject,\n options: AwsTeardownWorkflowOptions,\n ) {\n super(rootProject);\n\n const { openhi } = options;\n\n /***************************************************************************\n *\n * Root project check\n *\n * Detect the root project and ensure it's of type MonorepoProject.\n *\n **************************************************************************/\n\n if (!(rootProject instanceof MonorepoProject)) {\n throw new Error(\n \"AwsTeardownWorkflow requires the root project to be a MonorepoProject\",\n );\n }\n\n //this.rootProject = project.root;\n\n /***************************************************************************\n *\n * GitHub Check\n *\n * Make sure github config is active in the project. This is to ensure all\n * workflows will be output properly during synth.\n *\n **************************************************************************/\n\n const github = GitHub.of(this.rootProject);\n\n if (!github) {\n throw new Error(\n \"AwsTeardownWorkflow requires a GitHub component in the root project\",\n );\n }\n\n /***************************************************************************\n *\n * Workflow Destroy Targets\n *\n * Find all the CI targets for the Global project in the DEV stage\n * only. One job per (account, region) teardowns all orphan stacks (Auth,\n * Core, data) in that account/region.\n *\n **************************************************************************/\n\n const devTargetsFor = (service: OpenHiService) =>\n AwsDeploymentConfig.of(service.project)?.awsDeploymentTargets.filter(\n (target) =>\n target.awsStageType === OPEN_HI_STAGE.DEV && target.ciDeployment,\n ) ?? [];\n const awsDestructionTargets = devTargetsFor(openhi.global);\n\n /***************************************************************************\n *\n * Create Workflow\n *\n * Make a new workflow for AWS stack teardown. This runs each night and is\n * also triggered each time a branch is deleted.\n *\n **************************************************************************/\n\n const workflow = new GithubWorkflow(github, \"teardown-dev\");\n workflow.on({\n workflowDispatch: {},\n schedule: [\n {\n cron: \"32 6 * * *\", // Every Sunday at 6:32 AM UTC\n },\n ],\n delete: {\n branches: [\"feature/*\", \"feat/*\", \"fix/*\"],\n },\n /* for debugging \n push: {\n branches: [\"feature/*\"],\n },\n */\n });\n\n awsDestructionTargets.forEach((target) => {\n const {\n awsStageType,\n awsEnvironmentType,\n account,\n region,\n ciDeploymentConfig,\n } = target;\n const { roleArn } = ciDeploymentConfig ?? {};\n\n workflow.addJob(`teardown-${account}-${region}`.toLowerCase(), {\n name: `Teardown Stacks in ${target.account}/${target.region}`,\n //if: \"github.event.ref_type == 'branch'\",\n runsOn: [\"ubuntu-latest\"],\n permissions: {\n contents: JobPermission.READ,\n idToken: JobPermission.WRITE,\n },\n env: {\n REPO: \"${{ github.repository }}\",\n REGIONS: [region].join(\" \"),\n },\n steps: [\n /**\n * Configure AWS creds.\n */\n {\n name: `AWS Creds ${awsStageType}/${awsEnvironmentType}/${account}/${region}`,\n uses: \"aws-actions/configure-aws-credentials@v4\",\n with: {\n \"role-to-assume\": roleArn,\n \"aws-region\": region,\n \"role-duration-seconds\": 900, // 15 minutes\n },\n },\n\n /**\n * Fetch all branch names in the repo\n */\n {\n name: \"Fetch All Branches\",\n id: \"fetch_branches\",\n uses: \"actions/github-script@v7\",\n with: {\n script: [\n \"const all = await github.paginate(github.rest.repos.listBranches, {\",\n \" owner: context.repo.owner,\",\n \" repo: context.repo.repo,\",\n \" per_page: 100\",\n \"});\",\n \"const names = all.map(b => b.name);\",\n \"console.log(`Found branches: ${names}`);\",\n 'core.setOutput(\"json\", JSON.stringify(names));',\n ].join(\"\\n\"),\n },\n },\n\n /**\n * Save branches to a file\n */\n {\n name: \"Save Branches to File\",\n run: [\n 'echo \"Saving branches to file\"',\n \"echo '${{ steps.fetch_branches.outputs.json }}' | jq -r '.[]' | sort -u > branches.txt\",\n 'echo \"Branches:\"',\n \"cat branches.txt\",\n ].join(\"\\n\"),\n },\n\n /**\n * Find all stacks tagged with a stage of dev. for this repo. return\n * tag and resource arn.\n */\n {\n name: \"Find Stacks by Tag\",\n id: \"find_stacks\",\n run: [\n \"set -euo pipefail\",\n \": > candidates.txt # columns: arn region branchTag\",\n\n \"# Build tag filters\",\n 'TAG_FILTERS=( \"Key=openhi:repo-name,Values=$REPO\" )',\n `TAG_FILTERS+=( \"Key=openhi:stage-type,Values=${OPEN_HI_STAGE.DEV}\" )`,\n\n \"for r in $REGIONS; do\",\n ` echo \"Scanning region: $r\"`,\n \" aws resourcegroupstaggingapi get-resources \\\\\",\n ' --region \"$r\" \\\\',\n ' --resource-type-filters \"cloudformation:stack\" \\\\',\n ' --tag-filters \"${TAG_FILTERS[@]}\" \\\\',\n ` | jq -r --arg r \"$r\" '`,\n \" .ResourceTagMappingList[]\",\n \" | . as $res\",\n ' | ($res.Tags[] | select(.Key==\"openhi:branch-name\") | .Value) as $branch',\n ' | [$res.ResourceARN, $r, ($branch // \"\")]',\n \" | @tsv\",\n \" ' >> candidates.txt\",\n \"done\",\n\n \"echo 'Tagged stacks:'\",\n `(echo -e \"ARN\\\\tREGION\\\\tBRANCH\"; cat candidates.txt) | column -t -s $'\\\\t'`,\n ].join(\"\\n\"),\n },\n\n /**\n * Determine which stacks are orphans that no longer have a matching branch.\n * Save those to a file for the next step.\n */\n {\n name: \"Determine Orphan Stacks (No Matching Branch)\",\n run: [\n \"set -euo pipefail\",\n \": > orphans.txt # arn region branch\",\n \"while IFS=$'\\\\t' read -r arn region branch; do\",\n ' [ -z \"$arn\" ] && continue',\n ' if [ -z \"$branch\" ]; then',\n \" # If no Branch tag, treat as not-a-preview; skip (or flip to delete if you want)\",\n \" continue\",\n \" fi\",\n ' if ! grep -Fxq \"$branch\" branches.txt; then',\n ' echo -e \"$arn\\\\t$region\\\\t$branch\" >> orphans.txt',\n \" fi\",\n \"done < candidates.txt\",\n \"\",\n \"if [ -s orphans.txt ]; then\",\n ' echo \"Orphan stacks (no matching branch):\"',\n \" (echo -e \\\"ARN\\\\tREGION\\\\tBRANCH\\\"; cat orphans.txt) | column -t -s $'\\\\t'\",\n \"else\",\n ' echo \"No orphan stacks found.\"',\n \"fi\",\n ].join(\"\\n\"),\n },\n\n /**\n * Delete orphan stacks.\n */\n {\n name: \"Delete Orphan Stacks\",\n if: \"hashFiles('orphans.txt') != ''\",\n run: [\n \"set -euo pipefail\",\n \"while IFS=$'\\\\t' read -r arn region branch; do\",\n ' [ -z \"$arn\" ] && continue',\n \" stack_name=$(cut -d'/' -f2 <<<\\\"$arn\\\")\",\n ' echo \"Deleting $stack_name (branch=$branch) in $region\"',\n ' aws cloudformation delete-stack --region \"$region\" --stack-name \"$stack_name\" || true',\n \"done < orphans.txt\",\n ].join(\"\\n\"),\n },\n ],\n });\n });\n }\n}\n","import { AwsDeployWorkflow, MonorepoProject } from \"@codedrifters/configulator\";\nimport { Component } from \"projen\";\nimport { OpenHi } from \"../openhi\";\n\n/**\n * Job-level `if:` condition that restricts the per-PR website deploy to\n * pull-request events plus manual dispatch. Push events to feat/fix/feature\n * branches no longer trigger a website deploy because the OPENHI_PR_NUMBER\n * env var is only resolvable when a PR exists.\n */\nconst PR_GATED_WEBSITE_JOB_IF =\n \"${{ !needs.build.outputs.self_mutation_happened && \" +\n \"(github.event_name == 'pull_request' || \" +\n \"github.event_name == 'workflow_dispatch') }}\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/build-dev-workflow.md\n */\n\nexport interface BuildDevelopmentWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class BuildDevelopmentWorkflow extends Component {\n constructor(\n parent: MonorepoProject,\n options: BuildDevelopmentWorkflowOptions,\n ) {\n super(parent, \"dev-workflow\");\n\n const { openhi } = options;\n\n /**\n * Global Service Deploy\n *\n * Deploy the Global service first to configure DNS\n */\n const { awsDeploymentTargets: globalTargets } = new AwsDeployWorkflow(\n openhi.global.project,\n {\n buildWorkflow: parent.buildWorkflow,\n },\n );\n\n /**\n * Auth Service Deploy\n *\n * Deploy the Auth service first (Cognito); data service and other stacks consume auth via SSM.\n */\n const { awsDeploymentTargets: authTargets } = new AwsDeployWorkflow(\n openhi.auth.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets],\n },\n );\n\n /**\n * Data Service Deploy\n *\n * Deploy the Data service (DynamoDB FHIR store, S3) after Global.\n */\n const { awsDeploymentTargets: dataTargets } = new AwsDeployWorkflow(\n openhi.data.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets],\n },\n );\n\n /**\n * Rest API Service Deploy\n *\n * Deploy the Rest API service after Data (and Global).\n */\n const { awsDeploymentTargets: restApiTargets } = new AwsDeployWorkflow(\n openhi.restApi.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n },\n );\n\n /**\n * GraphQL API Service Deploy\n *\n * Deploy the GraphQL API service after Data (sibling to REST API).\n */\n new AwsDeployWorkflow(openhi.graphApi.project, {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n });\n\n /**\n * Website Service Deploy\n *\n * Deploy the Website service after Global and REST API. The website\n * stack's CloudFront distribution fronts the REST API via an\n * `/api/*` behavior whose origin host is resolved at CFN update time\n * from the `REST_API_DOMAIN_NAME` SSM parameter — that parameter is\n * written by the matching branch's rest-api stack, so rest-api must\n * deploy first. The Global dependency holds for the child hosted zone\n * and wildcard certificate. Auth no longer needs to be upstream — the\n * Cognito IDs are exposed via the REST API's runtime-config endpoint\n * at request time, not via CFN dynamic references at update time.\n */\n const websiteDeploy = new AwsDeployWorkflow(openhi.website.project, {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...restApiTargets],\n });\n\n /**\n * Per-PR preview wiring for the website deploy:\n *\n * 1. Trigger the build workflow on PR events so feature-branch deploys\n * have a PR number to address themselves with\n * (`admin-pr-<N>.<zone>`).\n * 2. Inject `OPENHI_PR_NUMBER` at the workflow env level so\n * `OpenHiWebsiteService` resolves it via the same fallback path it\n * uses for the `prNumber` prop.\n * 3. Gate every `*-deploy-openhi-website-*` job to `pull_request` +\n * `workflow_dispatch` only — push-to-branch no longer triggers a\n * website deploy (a website deploy requires a PR for its hostname).\n * Other services' deploy jobs are unchanged.\n */\n const buildWorkflow = parent.buildWorkflow;\n if (!buildWorkflow) {\n throw new Error(\"BuildDevelopmentWorkflow requires a buildWorkflow\");\n }\n const ghWorkflow = buildWorkflow.workflow;\n ghWorkflow.on({\n pullRequest: {\n types: [\"opened\", \"synchronize\", \"reopened\"],\n },\n });\n ghWorkflow.file?.addOverride(\n \"env.OPENHI_PR_NUMBER\",\n \"${{ github.event.pull_request.number || '' }}\",\n );\n websiteDeploy.awsDeploymentTargets.forEach((target) => {\n const jobId = [\n target.awsStageType,\n target.deploymentTargetRole,\n \"deploy\",\n target.project.name,\n target.account,\n target.region,\n ].join(\"-\");\n const job = ghWorkflow.getJob(jobId);\n ghWorkflow.updateJob(jobId, {\n ...job,\n if: PR_GATED_WEBSITE_JOB_IF,\n });\n });\n }\n}\n","import { AwsDeployWorkflow, MonorepoProject } from \"@codedrifters/configulator\";\nimport { OPEN_HI_STAGE } from \"@openhi/config\";\nimport { Component } from \"projen\";\nimport { OpenHi } from \"../openhi\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/build-stage-workflow.md\n */\n\nexport interface BuildStageWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class BuildStageWorkflow extends Component {\n constructor(parent: MonorepoProject, options: BuildStageWorkflowOptions) {\n super(parent, \"stage-workflow\");\n\n const { openhi } = options;\n\n /**\n * Global Service Deploy\n *\n * Deploy the Global service first to configure DNS\n */\n const { awsDeploymentTargets: globalTargets, buildWorkflow } =\n new AwsDeployWorkflow(openhi.global.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflowOptions: {\n name: \"deploy-stage\",\n workflowTriggers: {\n push: {\n branches: [\"main\"],\n },\n workflowDispatch: {},\n },\n },\n });\n\n // Inject OPENHI_PR_NUMBER at the workflow env level so it propagates\n // to every job (including the website deploy job). Release-branch\n // deploys ignore this value (no PR exists on a main push); the env is\n // included so OpenHiWebsiteService resolves consistently across\n // workflows. See BuildDevelopmentWorkflow for the PR-event wiring on\n // the dev side.\n buildWorkflow.workflow.file?.addOverride(\n \"env.OPENHI_PR_NUMBER\",\n \"${{ github.event.pull_request.number || '' }}\",\n );\n\n /**\n * Auth Service Deploy\n *\n * Deploy the Auth service first (Cognito); data service and other stacks consume auth via SSM.\n * Auth creates the stage build workflow; data service and REST API services add to it.\n */\n const { awsDeploymentTargets: authTargets } = new AwsDeployWorkflow(\n openhi.auth.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets],\n },\n );\n\n /**\n * Data Service Deploy\n *\n * Deploy the Data service (DynamoDB FHIR store, S3) after Global.\n */\n const { awsDeploymentTargets: dataTargets } = new AwsDeployWorkflow(\n openhi.data.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets],\n },\n );\n\n /**\n * Rest API Service Deploy\n */\n const { awsDeploymentTargets: restApiTargets } = new AwsDeployWorkflow(\n openhi.restApi.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n },\n );\n\n /**\n * GraphQL API Service Deploy\n */\n new AwsDeployWorkflow(openhi.graphApi.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n });\n\n /**\n * Website Service Deploy\n *\n * Deploy the Website service after Global and REST API. The website\n * stack's CloudFront distribution fronts the REST API via an\n * `/api/*` behavior whose origin host is resolved at CFN update time\n * from the `REST_API_DOMAIN_NAME` SSM parameter — that parameter is\n * written by the matching branch's rest-api stack, so rest-api must\n * deploy first. The Global dependency holds for the child hosted zone\n * and wildcard certificate. Auth no longer needs to be upstream — the\n * Cognito IDs are exposed via the REST API's runtime-config endpoint\n * at request time, not via CFN dynamic references at update time.\n */\n new AwsDeployWorkflow(openhi.website.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...restApiTargets],\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAca,IAAAA,SAAA,gBAAgB;;;;MAI3B,KAAK;;;;MAIL,OAAO;;;;MAIP,MAAM;;AAeK,IAAAA,SAAA,iCAAiC;;;;;MAK5C,SAAS;;;;;MAMT,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;ACpDb,iBAAA,0BAAAC,QAAA;;;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKA,0BAAsB;;;ACLtB,kBAAoB;AACpB,0BAIO;AACP,IAAAC,iBAKO;AACP,yBAAsC;AACtC,IAAAC,iBAAuB;AACvB,wBAA8C;;;ACd9C,qBAAuC;AACvC,uBAAoB;AACpB,oBAA2B;AA0BpB,IAAM,kBAAN,MAAsB;AAAA,EAW3B,YACS,SACA,SACP;AAFO;AACA;AAKP,SAAK,eAAe;AAAA,MAClB,KAAK,QAAQ,QAAQ;AAAA,MACrB,KAAK,QAAQ;AAAA,IACf,EAAE,KAAK,oBAAG;AAKV,SAAK,eAAe;AAAA,EACtB;AAAA,EAEU,iBAAiB;AACzB,QAAI,KAAK,QAAQ,WAAW;AAC1B,WAAK,kBAAkB;AAAA,IACzB;AAEA,SAAK,OAAO,IAAI,yBAAW,KAAK,QAAQ,SAAS,KAAK,QAAQ,UAAU;AAAA,MACtE,UAAU,KAAK,QAAQ,SAAS,KAAK,IAAI;AAAA,IAC3C,CAAC;AAAA,EACH;AAAA,EAEO,oBAAoB;AAIzB,YAAI,2BAAW,KAAK,YAAY,GAAG;AACjC,qCAAW,KAAK,YAAY;AAAA,IAC9B;AACA,SAAK,OAAO;AAAA,EACd;AACF;;;ACrEO,IAAM,SAAN,cAAqB,gBAAgB;AAAA,EAC1C,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,uBAAuB,QAAQ,aAAa;AAAA,QAC5C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB,QAAQ,aAAa;AAAA,QACrC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACvBO,IAAM,aAAN,cAAyB,gBAAgB;AAAA,EAC9C,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AChEA,IAAAC,iBAA2B;AAOpB,IAAM,YAAN,cAAwB,0BAAW;AAAA,EACxC,YAAY,SAAwB;AAClC,UAAM,QAAQ,SAAS,eAAe;AAKtC,SAAK,KAAK,gDAAgD;AAC1D,SAAK,KAAK,EAAE;AAKZ,UAAM,QAAQ;AACd,UAAM,MAAM,KAAK,UAAU,QAAQ,SAAS,QAAQ,MAAM,CAAC;AAC3D,UAAM,MAAM;AACZ,SAAK,KAAK,GAAG,KAAK,GAAG,GAAG,GAAG,GAAG,EAAE;AAAA,EAClC;AACF;;;ACfO,IAAM,mBAAN,cAA+B,gBAAgB;AAAA,EACpD,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,kFAAkF,QAAQ,WAAW;AAAA,MACvG;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACfO,IAAM,aAAN,cAAyB,gBAAgB;AAAA,EAC9C,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,uEAAuE,QAAQ,WAAW;AAAA,MAC5F;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACfO,IAAM,uBAAN,cAAmC,gBAAgB;AAAA,EACxD,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,sFAAsF,QAAQ,WAAW;AAAA,MAC3G;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACfO,IAAM,qBAAN,cAAiC,gBAAgB;AAAA,EACtD,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,mFAAmF,QAAQ,WAAW;AAAA,MACxG;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AClBO,IAAM,UAAN,cAAsB,gBAAgB;AAAA,EAC3C,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU,CAAC,gCAAgC,IAAI,gBAAgB,EAAE;AAAA,IACnE,CAAC;AAAA,EACH;AACF;;;ACXO,IAAM,YAAN,cAAwB,gBAAgB;AAAA,EAC7C,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,wDAAwD,QAAQ,WAAW;AAAA,MAC7E;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACZO,IAAM,kBAAN,cAA8B,gBAAgB;AAAA,EACnD,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,gFAAgF,QAAQ,WAAW;AAAA,MACrG;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACTO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,SAAwB;AAAxB;AAIlB,QAAI,OAAO,KAAK,OAAO;AACvB,QAAI,WAAW,KAAK,OAAO;AAC3B,QAAI,UAAU,KAAK,OAAO;AAC1B,QAAI,QAAQ,KAAK,OAAO;AACxB,QAAI,UAAU,KAAK,OAAO;AAK1B,QAAI,WAAW,KAAK,OAAO;AAC3B,QAAI,iBAAiB,KAAK,OAAO;AAKjC,QAAI,qBAAqB,KAAK,OAAO;AAKrC,QAAI,mBAAmB,KAAK,OAAO;AAKnC,QAAI,gBAAgB,KAAK,OAAO;AAAA,EAClC;AACF;;;AZzBO,IAAM,uBAAuB;AAAA,EAClC,MAAM;AAAA,EACN,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU;AAAA,EACV,SAAS;AACX;AAgBO,IAAM,gBAAN,MAAoB;AAAA,EAGzB,YACS,QACA,IACA,SACP;AAHO;AACA;AACA;AAmKT,SAAQ,sBAAsB,CAC5B,cACA,oBACA,cACG;AACH,UAAI,wCAAoB,KAAK,SAAS;AAAA,QACpC,SAAS,UAAU;AAAA,QACnB,QAAQ,UAAU;AAAA,QAClB;AAAA,QACA;AAAA,QACA,iBAAiB;AAAA,QACjB,uBAAuB;AAAA,UACrB,cAAc,GAAG,YAAY,IAAI,kBAAkB,MAAM,UAAU,OAAO,IAAI,UAAU,MAAM;AAAA,UAC9F,UAAU;AAAA,QACZ;AAAA,QACA,cAAc;AAAA,QACd,oBAAoB;AAAA,UAClB,SAAS,gBAAgB,UAAU,OAAO;AAAA,UAC1C,cAAc,GAAG,YAAY,IAAI,kBAAkB,MAAM,UAAU,OAAO,IAAI,UAAU,MAAM;AAAA,QAChG;AAAA,QAEA,UACE,iBAAiB,6BAAc,MAC3B;AAAA,UACE;AAAA,YACE,QAAQ;AAAA,YACR,aAAa;AAAA,cACX;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,aAAa;AAAA,cACX;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,aAAa;AAAA,cACX;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF,IACA;AAAA,UACE;AAAA,YACE,QAAQ;AAAA,YACR,aAAa;AAAA,cACX;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACR,CAAC;AAAA,IACH;AA/ME,SAAK,UAAU,IAAI,sBAAO,oBAAoB;AAAA;AAAA;AAAA;AAAA,MAI5C,sBAAsB;AAAA,MACtB,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK,OAAO;AAAA,MACpB,YACE,KAAK,SAAS,QAAQ,UAAU,KAAK,iBACrC,4BAAQ;AAAA,MACV,eACE,KAAK,SAAS,QAAQ,UAAU,KAAK,iBACrC,4BAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOV,UAAU;AAAA;AAAA;AAAA;AAAA,MAKV,gBAAgB,qCAAmB;AAAA;AAAA;AAAA;AAAA,MAKnC,UAAU;AAAA;AAAA;AAAA;AAAA,MAKV,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,MAMZ,aAAa;AAAA,QACX,gBAAgB;AAAA,QAChB,YAAY;AAAA,UACV,WAAW;AAAA,YACT,CAAC,eAAe,GAAG,IAAI,4BAAU,WAAW;AAAA,UAC9C;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,SAAS,CAAC,aAAa,WAAW;AAAA;AAAA;AAAA;AAAA,MAKlC,kBAAkB;AAAA,QAChB,gBAAgB,CAAC,YAAY,UAAU;AAAA,MACzC;AAAA,IACF,CAAC;AAKD,SAAK,QAAQ,KAAK,iBAAiB,SAAS;AAU5C,SAAK,QAAQ;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAUA,QAAI,8BAAU,KAAK,OAAO;AAE1B,kCAAU,GAAG,KAAK,OAAO,GAAG,yBAAyB;AAAA,MACnD,OAAO,CAAC,cAAc;AAAA,IACxB,CAAC;AAeD,QAAI,KAAK,QAAQ,SAAS,qBAAqB,SAAS;AACtD,YAAM,QAAQ,8BAAU,GAAG,KAAK,OAAO;AACvC,YAAM,iBAAiB,OAAO,iBAAiB;AAC/C,UAAI,kBAAkB,CAAC,eAAe,SAAS,kBAAkB,GAAG;AAClE,uBAAe,KAAK,kBAAkB;AAAA,MACxC;AAAA,IACF;AAQA,QAAI,kBAAkB,IAAI;AAQ1B,KAAC,6BAAc,KAAK,6BAAc,OAAO,6BAAc,IAAI,EAAE;AAAA,MAC3D,CAAC,UAAU;AACT,cAAM,UAAU,KAAK,SAAS,QAAQ,oBAAoB,KAAK;AAC/D,YAAI,SAAS,SAAS;AACpB,eAAK;AAAA,YACH;AAAA,YACA,8CAA+B;AAAA,YAC/B,QAAQ;AAAA,UACV;AAAA,QACF;AACA,iBAAS,WAAW,QAAQ,CAAC,QAAQ;AACnC,eAAK;AAAA,YACH;AAAA,YACA,8CAA+B;AAAA,YAC/B;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EA4DA,IAAI,gBAAwB;AAC1B,eAAO,+BAAW,CAAC,QAAQ,MAAM,KAAK,IAAI,SAAS,EAAE,KAAK,GAAG,CAAC;AAAA,EAChE;AAAA,EAEA,IAAI,SAAS;AACX,WAAO,KAAC,8BAAU,KAAK,OAAO,EAAE,OAAG,8BAAU,KAAK,EAAE,CAAC,EAAE,KAAK,eAAG;AAAA,EACjE;AAAA,EAEA,IAAI,cAAc;AAChB,WAAO,KAAC,8BAAU,KAAK,OAAO,EAAE,OAAG,8BAAU,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG;AAAA,EACjE;AACF;;;Aa7RA,IAAAC,uBAGO;AACP,IAAAC,iBAA8B;AAC9B,IAAAC,iBAA0B;AAC1B,oBAAuC;AACvC,6BAA8B;AAevB,IAAM,sBAAN,cAAkC,yBAAU;AAAA,EACjD,YACS,aACP,SACA;AACA,UAAM,WAAW;AAHV;AAKP,UAAM,EAAE,OAAO,IAAI;AAUnB,QAAI,EAAE,uBAAuB,uCAAkB;AAC7C,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAaA,UAAM,SAAS,qBAAO,GAAG,KAAK,WAAW;AAEzC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAYA,UAAM,gBAAgB,CAAC,YACrB,yCAAoB,GAAG,QAAQ,OAAO,GAAG,qBAAqB;AAAA,MAC5D,CAAC,WACC,OAAO,iBAAiB,6BAAc,OAAO,OAAO;AAAA,IACxD,KAAK,CAAC;AACR,UAAM,wBAAwB,cAAc,OAAO,MAAM;AAWzD,UAAM,WAAW,IAAI,6BAAe,QAAQ,cAAc;AAC1D,aAAS,GAAG;AAAA,MACV,kBAAkB,CAAC;AAAA,MACnB,UAAU;AAAA,QACR;AAAA,UACE,MAAM;AAAA;AAAA,QACR;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,UAAU,CAAC,aAAa,UAAU,OAAO;AAAA,MAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMF,CAAC;AAED,0BAAsB,QAAQ,CAAC,WAAW;AACxC,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,IAAI;AACJ,YAAM,EAAE,QAAQ,IAAI,sBAAsB,CAAC;AAE3C,eAAS,OAAO,YAAY,OAAO,IAAI,MAAM,GAAG,YAAY,GAAG;AAAA,QAC7D,MAAM,sBAAsB,OAAO,OAAO,IAAI,OAAO,MAAM;AAAA;AAAA,QAE3D,QAAQ,CAAC,eAAe;AAAA,QACxB,aAAa;AAAA,UACX,UAAU,qCAAc;AAAA,UACxB,SAAS,qCAAc;AAAA,QACzB;AAAA,QACA,KAAK;AAAA,UACH,MAAM;AAAA,UACN,SAAS,CAAC,MAAM,EAAE,KAAK,GAAG;AAAA,QAC5B;AAAA,QACA,OAAO;AAAA;AAAA;AAAA;AAAA,UAIL;AAAA,YACE,MAAM,aAAa,YAAY,IAAI,kBAAkB,IAAI,OAAO,IAAI,MAAM;AAAA,YAC1E,MAAM;AAAA,YACN,MAAM;AAAA,cACJ,kBAAkB;AAAA,cAClB,cAAc;AAAA,cACd,yBAAyB;AAAA;AAAA,YAC3B;AAAA,UACF;AAAA;AAAA;AAAA;AAAA,UAKA;AAAA,YACE,MAAM;AAAA,YACN,IAAI;AAAA,YACJ,MAAM;AAAA,YACN,MAAM;AAAA,cACJ,QAAQ;AAAA,gBACN;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cACF,EAAE,KAAK,IAAI;AAAA,YACb;AAAA,UACF;AAAA;AAAA;AAAA;AAAA,UAKA;AAAA,YACE,MAAM;AAAA,YACN,KAAK;AAAA,cACH;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF,EAAE,KAAK,IAAI;AAAA,UACb;AAAA;AAAA;AAAA;AAAA;AAAA,UAMA;AAAA,YACE,MAAM;AAAA,YACN,IAAI;AAAA,YACJ,KAAK;AAAA,cACH;AAAA,cACA;AAAA,cAEA;AAAA,cACA;AAAA,cACA,gDAAgD,6BAAc,GAAG;AAAA,cAEjE;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cAEA;AAAA,cACA;AAAA,YACF,EAAE,KAAK,IAAI;AAAA,UACb;AAAA;AAAA;AAAA;AAAA;AAAA,UAMA;AAAA,YACE,MAAM;AAAA,YACN,KAAK;AAAA,cACH;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF,EAAE,KAAK,IAAI;AAAA,UACb;AAAA;AAAA;AAAA;AAAA,UAKA;AAAA,YACE,MAAM;AAAA,YACN,IAAI;AAAA,YACJ,KAAK;AAAA,cACH;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF,EAAE,KAAK,IAAI;AAAA,UACb;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;;;ACtQA,IAAAC,uBAAmD;AACnD,IAAAC,iBAA0B;AAS1B,IAAM,0BACJ;AAeK,IAAM,2BAAN,cAAuC,yBAAU;AAAA,EACtD,YACE,QACA,SACA;AACA,UAAM,QAAQ,cAAc;AAE5B,UAAM,EAAE,OAAO,IAAI;AAOnB,UAAM,EAAE,sBAAsB,cAAc,IAAI,IAAI;AAAA,MAClD,OAAO,OAAO;AAAA,MACd;AAAA,QACE,eAAe,OAAO;AAAA,MACxB;AAAA,IACF;AAOA,UAAM,EAAE,sBAAsB,YAAY,IAAI,IAAI;AAAA,MAChD,OAAO,KAAK;AAAA,MACZ;AAAA,QACE,eAAe,OAAO;AAAA,QACtB,oBAAoB,CAAC,GAAG,aAAa;AAAA,MACvC;AAAA,IACF;AAOA,UAAM,EAAE,sBAAsB,YAAY,IAAI,IAAI;AAAA,MAChD,OAAO,KAAK;AAAA,MACZ;AAAA,QACE,eAAe,OAAO;AAAA,QACtB,oBAAoB,CAAC,GAAG,eAAe,GAAG,WAAW;AAAA,MACvD;AAAA,IACF;AAOA,UAAM,EAAE,sBAAsB,eAAe,IAAI,IAAI;AAAA,MACnD,OAAO,QAAQ;AAAA,MACf;AAAA,QACE,eAAe,OAAO;AAAA,QACtB,oBAAoB,CAAC,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW;AAAA,MACvE;AAAA,IACF;AAOA,QAAI,uCAAkB,OAAO,SAAS,SAAS;AAAA,MAC7C,eAAe,OAAO;AAAA,MACtB,oBAAoB,CAAC,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW;AAAA,IACvE,CAAC;AAeD,UAAM,gBAAgB,IAAI,uCAAkB,OAAO,QAAQ,SAAS;AAAA,MAClE,eAAe,OAAO;AAAA,MACtB,oBAAoB,CAAC,GAAG,eAAe,GAAG,cAAc;AAAA,IAC1D,CAAC;AAgBD,UAAM,gBAAgB,OAAO;AAC7B,QAAI,CAAC,eAAe;AAClB,YAAM,IAAI,MAAM,mDAAmD;AAAA,IACrE;AACA,UAAM,aAAa,cAAc;AACjC,eAAW,GAAG;AAAA,MACZ,aAAa;AAAA,QACX,OAAO,CAAC,UAAU,eAAe,UAAU;AAAA,MAC7C;AAAA,IACF,CAAC;AACD,eAAW,MAAM;AAAA,MACf;AAAA,MACA;AAAA,IACF;AACA,kBAAc,qBAAqB,QAAQ,CAAC,WAAW;AACrD,YAAM,QAAQ;AAAA,QACZ,OAAO;AAAA,QACP,OAAO;AAAA,QACP;AAAA,QACA,OAAO,QAAQ;AAAA,QACf,OAAO;AAAA,QACP,OAAO;AAAA,MACT,EAAE,KAAK,GAAG;AACV,YAAM,MAAM,WAAW,OAAO,KAAK;AACnC,iBAAW,UAAU,OAAO;AAAA,QAC1B,GAAG;AAAA,QACH,IAAI;AAAA,MACN,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;;;AC9JA,IAAAC,uBAAmD;AACnD,IAAAC,iBAA8B;AAC9B,IAAAC,iBAA0B;AAcnB,IAAM,qBAAN,cAAiC,yBAAU;AAAA,EAChD,YAAY,QAAyB,SAAoC;AACvE,UAAM,QAAQ,gBAAgB;AAE9B,UAAM,EAAE,OAAO,IAAI;AAOnB,UAAM,EAAE,sBAAsB,eAAe,cAAc,IACzD,IAAI,uCAAkB,OAAO,OAAO,SAAS;AAAA,MAC3C,cAAc,6BAAc;AAAA,MAC5B,sBAAsB;AAAA,QACpB,MAAM;AAAA,QACN,kBAAkB;AAAA,UAChB,MAAM;AAAA,YACJ,UAAU,CAAC,MAAM;AAAA,UACnB;AAAA,UACA,kBAAkB,CAAC;AAAA,QACrB;AAAA,MACF;AAAA,IACF,CAAC;AAQH,kBAAc,SAAS,MAAM;AAAA,MAC3B;AAAA,MACA;AAAA,IACF;AAQA,UAAM,EAAE,sBAAsB,YAAY,IAAI,IAAI;AAAA,MAChD,OAAO,KAAK;AAAA,MACZ;AAAA,QACE,cAAc,6BAAc;AAAA,QAC5B;AAAA,QACA,oBAAoB,CAAC,GAAG,aAAa;AAAA,MACvC;AAAA,IACF;AAOA,UAAM,EAAE,sBAAsB,YAAY,IAAI,IAAI;AAAA,MAChD,OAAO,KAAK;AAAA,MACZ;AAAA,QACE,cAAc,6BAAc;AAAA,QAC5B;AAAA,QACA,oBAAoB,CAAC,GAAG,eAAe,GAAG,WAAW;AAAA,MACvD;AAAA,IACF;AAKA,UAAM,EAAE,sBAAsB,eAAe,IAAI,IAAI;AAAA,MACnD,OAAO,QAAQ;AAAA,MACf;AAAA,QACE,cAAc,6BAAc;AAAA,QAC5B;AAAA,QACA,oBAAoB,CAAC,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW;AAAA,MACvE;AAAA,IACF;AAKA,QAAI,uCAAkB,OAAO,SAAS,SAAS;AAAA,MAC7C,cAAc,6BAAc;AAAA,MAC5B;AAAA,MACA,oBAAoB,CAAC,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW;AAAA,IACvE,CAAC;AAeD,QAAI,uCAAkB,OAAO,QAAQ,SAAS;AAAA,MAC5C,cAAc,6BAAc;AAAA,MAC5B;AAAA,MACA,oBAAoB,CAAC,GAAG,eAAe,GAAG,cAAc;AAAA,IAC1D,CAAC;AAAA,EACH;AACF;;;AhB1CO,IAAM,SAAN,MAAa;AAAA,EAgDlB,YAAY,UAAyB,CAAC,GAAG;AASvC,SAAK,cAAU,2BAAM,EAAE,MAAM,SAAS,GAAG,OAAO;AAChD,SAAK,cAAc,KAAK,QAAQ;AAChC,SAAK,KAAK,KAAK,QAAQ,aAAa,QAAQ;AAM5C,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cAAc,KAAK;AAWzB,SAAK,SAAS,IAAI,cAAc,MAAM,UAAU;AAAA,MAC9C,MAAM,qBAAqB;AAAA,MAC3B,YAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,uBAAuB,CAAC;AAAA,MACxC;AAAA,IACF,CAAC;AAWD,SAAK,OAAO,IAAI,cAAc,MAAM,QAAQ;AAAA,MAC1C,MAAM,qBAAqB;AAAA,MAC3B,YAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,qBAAqB,CAAC;AAAA,MACtC;AAAA,IACF,CAAC;AAUD,SAAK,UAAU,IAAI,cAAc,MAAM,YAAY;AAAA,MACjD,MAAM,qBAAqB;AAAA,MAC3B,YAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,wBAAwB,CAAC;AAAA,MACzC;AAAA,IACF,CAAC;AAWD,SAAK,OAAO,IAAI,cAAc,MAAM,QAAQ;AAAA,MAC1C,MAAM,qBAAqB;AAAA,MAC3B,YAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,qBAAqB,CAAC;AAAA,MACtC;AAAA,IACF,CAAC;AAUD,SAAK,WAAW,IAAI,cAAc,MAAM,WAAW;AAAA,MACjD,MAAM,qBAAqB;AAAA,MAC3B,YAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,yBAAyB,CAAC;AAAA,MAC1C;AAAA,IACF,CAAC;AAWD,SAAK,UAAU,IAAI,cAAc,MAAM,WAAW;AAAA,MAChD,MAAM,qBAAqB;AAAA,MAC3B,YAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,wBAAwB,CAAC;AAAA,MACzC;AAAA,IACF,CAAC;AAkBD,QAAI,yBAAyB,aAAa,EAAE,QAAQ,KAAK,CAAC;AAC1D,QAAI,mBAAmB,aAAa,EAAE,QAAQ,KAAK,CAAC;AAEpD,QAAI,oBAAoB,aAAa,EAAE,QAAQ,KAAK,CAAC;AAAA,EACvD;AACF;","names":["exports","exports","import_config","import_projen","import_projen","import_configulator","import_config","import_projen","import_configulator","import_projen","import_configulator","import_config","import_projen"]}
|
package/lib/index.mjs
CHANGED
|
@@ -462,6 +462,16 @@ var OpenHiService = class {
|
|
|
462
462
|
"@openhi/constructs@workspace:*"
|
|
463
463
|
);
|
|
464
464
|
new TurboRepo(this.project);
|
|
465
|
+
TurboRepo.of(this.project)?.activateBranchNameEnvVar({
|
|
466
|
+
tasks: ["post-compile"]
|
|
467
|
+
});
|
|
468
|
+
if (this.options.type === OPEN_HI_SERVICE_TYPE.WEBSITE) {
|
|
469
|
+
const turbo = TurboRepo.of(this.project);
|
|
470
|
+
const postCompileEnv = turbo?.postCompileTask?.env;
|
|
471
|
+
if (postCompileEnv && !postCompileEnv.includes("OPENHI_PR_NUMBER")) {
|
|
472
|
+
postCompileEnv.push("OPENHI_PR_NUMBER");
|
|
473
|
+
}
|
|
474
|
+
}
|
|
465
475
|
new GenerateTemplates(this);
|
|
466
476
|
[import_config2.OPEN_HI_STAGE.DEV, import_config2.OPEN_HI_STAGE.STAGE, import_config2.OPEN_HI_STAGE.PROD].forEach(
|
|
467
477
|
(stage) => {
|
|
@@ -692,6 +702,7 @@ var AwsTeardownWorkflow = class extends Component {
|
|
|
692
702
|
// src/workflows/build-dev-workflow.ts
|
|
693
703
|
import { AwsDeployWorkflow } from "@codedrifters/configulator";
|
|
694
704
|
import { Component as Component2 } from "projen";
|
|
705
|
+
var PR_GATED_WEBSITE_JOB_IF = "${{ !needs.build.outputs.self_mutation_happened && (github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch') }}";
|
|
695
706
|
var BuildDevelopmentWorkflow = class extends Component2 {
|
|
696
707
|
constructor(parent, options) {
|
|
697
708
|
super(parent, "dev-workflow");
|
|
@@ -727,10 +738,39 @@ var BuildDevelopmentWorkflow = class extends Component2 {
|
|
|
727
738
|
buildWorkflow: parent.buildWorkflow,
|
|
728
739
|
deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets]
|
|
729
740
|
});
|
|
730
|
-
new AwsDeployWorkflow(openhi.website.project, {
|
|
741
|
+
const websiteDeploy = new AwsDeployWorkflow(openhi.website.project, {
|
|
731
742
|
buildWorkflow: parent.buildWorkflow,
|
|
732
743
|
deployAfterTargets: [...globalTargets, ...restApiTargets]
|
|
733
744
|
});
|
|
745
|
+
const buildWorkflow = parent.buildWorkflow;
|
|
746
|
+
if (!buildWorkflow) {
|
|
747
|
+
throw new Error("BuildDevelopmentWorkflow requires a buildWorkflow");
|
|
748
|
+
}
|
|
749
|
+
const ghWorkflow = buildWorkflow.workflow;
|
|
750
|
+
ghWorkflow.on({
|
|
751
|
+
pullRequest: {
|
|
752
|
+
types: ["opened", "synchronize", "reopened"]
|
|
753
|
+
}
|
|
754
|
+
});
|
|
755
|
+
ghWorkflow.file?.addOverride(
|
|
756
|
+
"env.OPENHI_PR_NUMBER",
|
|
757
|
+
"${{ github.event.pull_request.number || '' }}"
|
|
758
|
+
);
|
|
759
|
+
websiteDeploy.awsDeploymentTargets.forEach((target) => {
|
|
760
|
+
const jobId = [
|
|
761
|
+
target.awsStageType,
|
|
762
|
+
target.deploymentTargetRole,
|
|
763
|
+
"deploy",
|
|
764
|
+
target.project.name,
|
|
765
|
+
target.account,
|
|
766
|
+
target.region
|
|
767
|
+
].join("-");
|
|
768
|
+
const job = ghWorkflow.getJob(jobId);
|
|
769
|
+
ghWorkflow.updateJob(jobId, {
|
|
770
|
+
...job,
|
|
771
|
+
if: PR_GATED_WEBSITE_JOB_IF
|
|
772
|
+
});
|
|
773
|
+
});
|
|
734
774
|
}
|
|
735
775
|
};
|
|
736
776
|
|
|
@@ -754,6 +794,10 @@ var BuildStageWorkflow = class extends Component3 {
|
|
|
754
794
|
}
|
|
755
795
|
}
|
|
756
796
|
});
|
|
797
|
+
buildWorkflow.workflow.file?.addOverride(
|
|
798
|
+
"env.OPENHI_PR_NUMBER",
|
|
799
|
+
"${{ github.event.pull_request.number || '' }}"
|
|
800
|
+
);
|
|
757
801
|
const { awsDeploymentTargets: authTargets } = new AwsDeployWorkflow2(
|
|
758
802
|
openhi.auth.project,
|
|
759
803
|
{
|
package/lib/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../config/src/open-hi-config.ts","../../config/src/index.ts","../src/openhi.ts","../src/service.ts","../src/templates/service-template.ts","../src/templates/src/app.ts","../src/templates/src/app-test.ts","../src/templates/src/config.ts","../src/templates/src/data/models/README.md.ts","../src/templates/src/data/README.md.ts","../src/templates/src/infrastructure/README.md.ts","../src/templates/src/integrations/README.md.ts","../src/templates/src/main.ts","../src/templates/src/README.md.ts","../src/templates/src/workflows/README.md.ts","../src/templates/generate-templates.ts","../src/workflows/aws-teardown-workflow.ts","../src/workflows/build-dev-workflow.ts","../src/workflows/build-stage-workflow.ts"],"sourcesContent":["/*******************************************************************************\n *\n * OpenHi Config\n *\n * These types are kept in their own package to prevent dependency conflicts and\n * conditions between @openhi/constructs and @openhi/platform..\n *\n ******************************************************************************/\n\n/**\n * Stage Types\n *\n * What stage of deployment is this? Dev, staging, or prod?\n */\nexport const OPEN_HI_STAGE = {\n /**\n * Development environment, typically used for testing and development.\n */\n DEV: \"dev\",\n /**\n * Staging environment, used for pre-production testing.\n */\n STAGE: \"stage\",\n /**\n * Production environment, used for live deployments.\n */\n PROD: \"prod\",\n} as const;\n\n/**\n * Above const as a type.\n */\nexport type OpenHiStageType =\n (typeof OPEN_HI_STAGE)[keyof typeof OPEN_HI_STAGE];\n\n/**\n * Deployment Target Role\n *\n * Is this (account, region) the primary or a secondary deployment target for the stage?\n * Works for both multi-region (different regions) and cellular (same region, different accounts).\n */\nexport const OPEN_HI_DEPLOYMENT_TARGET_ROLE = {\n /**\n * The primary deployment target for this stage (main account/region).\n * For example, the base DynamoDB region for global tables.\n */\n PRIMARY: \"primary\",\n\n /**\n * A secondary deployment target for this stage (additional account/region).\n * For example, a replica region for a global DynamoDB table, or another cell in the same region.\n */\n SECONDARY: \"secondary\",\n} as const;\n\n/**\n * Above const as a type.\n */\nexport type OpenHiDeploymentTargetRoleType =\n (typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE)[keyof typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE];\n\nexport interface OpenHiEnvironmentConfig {\n account: string;\n region: string;\n /**\n * Route53 zone containing DNS for this service.\n */\n hostedZoneId?: string;\n zoneName?: string;\n}\n\n/**\n * Represents the configuration for OpenHi services across different stages and\n * deployment targets.\n */\nexport interface OpenHiConfig {\n versions?: {\n cdk?: {\n cdkLibVersion?: string;\n cdkCliVersion?: string;\n };\n };\n deploymentTargets?: {\n [OPEN_HI_STAGE.DEV]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n [OPEN_HI_STAGE.STAGE]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n [OPEN_HI_STAGE.PROD]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n };\n}\n","export * from \"./open-hi-config\";\n","import {\n MonorepoProject,\n MonorepoProjectOptions,\n} from \"@codedrifters/configulator\";\nimport { OpenHiConfig } from \"@openhi/config\";\nimport { merge } from \"ts-deepmerge\";\nimport { SetOptional } from \"type-fest\";\nimport { OPEN_HI_SERVICE_TYPE, OpenHiService } from \"./service\";\nimport { AwsTeardownWorkflow } from \"./workflows/aws-teardown-workflow\";\nimport { BuildDevelopmentWorkflow } from \"./workflows/build-dev-workflow\";\nimport { BuildStageWorkflow } from \"./workflows/build-stage-workflow\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/openhi.md\n */\n\nexport interface OpenHiOptions {\n /*****************************************************************************\n *\n * Root Project Configuration Options\n *\n * Configuration options for the root monorepo project that contains all\n * OpenHi services and coordinate releases and builds.\n *\n ****************************************************************************/\n\n readonly rootProjectOptions?: SetOptional<MonorepoProjectOptions, \"name\">;\n\n /**\n * Monorepo root project, if using an existing project.\n */\n readonly rootProject?: MonorepoProject;\n\n /*****************************************************************************\n *\n * Service Configuration Options\n *\n * These options are used to configure the various services within the OpenHi\n * framework. Each service can have its own configuration settings, which will\n * be merged with the default configuration.\n *\n ****************************************************************************/\n\n /**\n * Default configuration used in all services with undefined configs.\n */\n readonly defaultConfig?: OpenHiConfig;\n\n /**\n * Global Service Config\n */\n readonly globalServiceConfig?: OpenHiConfig;\n\n /**\n * Auth Service Config\n */\n readonly authServiceConfig?: OpenHiConfig;\n\n /**\n * Rest API Service Config\n */\n readonly restApiServiceConfig?: OpenHiConfig;\n\n /**\n * Data Service Config (DynamoDB FHIR store, S3, etc.)\n */\n readonly dataServiceConfig?: OpenHiConfig;\n\n /**\n * GraphQL API Service Config\n */\n readonly graphApiServiceConfig?: OpenHiConfig;\n\n /**\n * Website Service Config (static hosting + content uploader).\n */\n readonly websiteServiceConfig?: OpenHiConfig;\n}\n\nexport class OpenHi {\n /**\n * Final options used to build this instance.\n */\n public options: OpenHiOptions;\n\n /**\n * Monorepo root project, either passed in as an argument or generated in\n * this component\n */\n public readonly rootProject?: MonorepoProject;\n\n /**\n * Test identifier for this instance.\n */\n public readonly id: string;\n\n /**\n * Global service (deployed first; Auth, data service, and other stacks depend on it).\n */\n public readonly global: OpenHiService;\n\n /**\n * Auth service (deployed first; data service, REST API, and data services depend on it).\n */\n public readonly auth: OpenHiService;\n\n /**\n * Rest API service\n */\n public readonly restApi: OpenHiService;\n\n /**\n * Data service (DynamoDB FHIR store, S3, and other persistence).\n */\n public readonly data: OpenHiService;\n\n /**\n * GraphQL API service (AppSync); deploys as sibling to REST API after Data.\n */\n public readonly graphApi: OpenHiService;\n\n /**\n * Website service (static hosting + content uploader); deploys as sibling\n * to the other services after Global.\n */\n public readonly website: OpenHiService;\n\n constructor(options: OpenHiOptions = {}) {\n /***************************************************************************\n *\n * Options\n *\n * Combine input options with defaults.\n *\n **************************************************************************/\n\n this.options = merge({ name: \"openhi\" }, options);\n this.rootProject = this.options.rootProject;\n this.id = this.options.rootProject?.name ?? \"openhi\";\n\n /**\n * In future we would create root project here. For now, require it to be\n * passed in.\n */\n if (!this.rootProject) {\n throw new Error(\n \"OpenHi requires a MonorepoProject to be passed in via the rootProject option\",\n );\n }\n\n const rootProject = this.rootProject;\n\n /***************************************************************************\n *\n * Global Service\n *\n * Global infrastructure (Route53, ACM). Deployed first in primary;\n * Auth, data service, and other stacks depend on it.\n *\n **************************************************************************/\n\n this.global = new OpenHiService(this, \"global\", {\n type: OPEN_HI_SERVICE_TYPE.GLOBAL,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.globalServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Auth Service\n *\n * Authentication (Cognito user pool, client, domain, KMS). Deployed first;\n * data service, REST API, and data services consume auth via SSM.\n *\n **************************************************************************/\n\n this.auth = new OpenHiService(this, \"auth\", {\n type: OPEN_HI_SERVICE_TYPE.AUTH,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.authServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Rest API service\n *\n * This contains the REST API for the OpenHi platform.\n *\n **************************************************************************/\n\n this.restApi = new OpenHiService(this, \"rest-api\", {\n type: OPEN_HI_SERVICE_TYPE.REST_API,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.restApiServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Data Service\n *\n * Data storage stack (DynamoDB FHIR store, S3, etc.). Deployed so that\n * REST API and other services can reference the table via cross-stack.\n *\n **************************************************************************/\n\n this.data = new OpenHiService(this, \"data\", {\n type: OPEN_HI_SERVICE_TYPE.DATA_SERVICE,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.dataServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * GraphQL API service\n *\n * AppSync API; deploys as sibling to REST API after Data.\n *\n **************************************************************************/\n\n this.graphApi = new OpenHiService(this, \"graphql\", {\n type: OPEN_HI_SERVICE_TYPE.GRAPHQL,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.graphApiServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Website service\n *\n * Static hosting (CloudFront + S3 + Lambda@Edge) and content uploader;\n * deploys as a sibling to the other services after Global.\n *\n **************************************************************************/\n\n this.website = new OpenHiService(this, \"website\", {\n type: OPEN_HI_SERVICE_TYPE.WEBSITE,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.websiteServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Integrations\n *\n * Various purpose specific integrations.\n *\n **************************************************************************/\n\n /***************************************************************************\n *\n * Workflows\n *\n * Workflows for each environment.\n *\n **************************************************************************/\n\n new BuildDevelopmentWorkflow(rootProject, { openhi: this });\n new BuildStageWorkflow(rootProject, { openhi: this });\n\n new AwsTeardownWorkflow(rootProject, { openhi: this });\n }\n}\n","import { sep } from \"path\";\nimport {\n AwsDeploymentTarget,\n TurboRepo,\n VERSION,\n} from \"@codedrifters/configulator\";\nimport {\n OPEN_HI_DEPLOYMENT_TARGET_ROLE,\n OPEN_HI_STAGE,\n OpenHiConfig,\n OpenHiEnvironmentConfig,\n} from \"@openhi/config\";\nimport { paramCase, pascalCase } from \"change-case\";\nimport { awscdk } from \"projen\";\nimport { NodePackageManager, Transform } from \"projen/lib/javascript\";\nimport { ValueOf } from \"type-fest\";\nimport { OpenHi } from \"./openhi\";\nimport { GenerateTemplates } from \"./templates/generate-templates\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/service.md\n */\n\nexport const OPEN_HI_SERVICE_TYPE = {\n AUTH: \"auth\",\n DATA_SERVICE: \"data\",\n GLOBAL: \"global\",\n GRAPHQL: \"graphql\",\n INTEGRATION: \"integration\",\n REST_API: \"rest-api\",\n WEBSITE: \"website\",\n} as const;\n\nexport interface OpenHiServiceOptions {\n /**\n * Configuration for this service.\n *\n * @default uses the global default config.\n */\n readonly config: OpenHiConfig;\n\n /**\n * What type of service is this?\n */\n readonly type: ValueOf<typeof OPEN_HI_SERVICE_TYPE>;\n}\n\nexport class OpenHiService {\n public readonly project: awscdk.AwsCdkTypeScriptApp;\n\n constructor(\n public openHi: OpenHi,\n public id: string,\n public options: OpenHiServiceOptions,\n ) {\n /**\n * Build the construct name we expect to use in this service.\n */\n\n /***************************************************************************\n *\n * Projen based CDK build\n *\n **************************************************************************/\n\n this.project = new awscdk.AwsCdkTypeScriptApp({\n /**\n * Top level project config options\n */\n defaultReleaseBranch: \"main\",\n name: this.serviceName,\n outdir: this.outDir,\n parent: this.openHi.rootProject,\n cdkVersion:\n this.options?.config?.versions?.cdk?.cdkLibVersion ??\n VERSION.AWS_CDK_LIB_VERSION,\n cdkCliVersion:\n this.options?.config?.versions?.cdk?.cdkCliVersion ??\n VERSION.AWS_CDK_CLI_VERSION,\n\n /**\n * Packaging options\n *\n * TODO: Figure out license for monorepo vs per package?\n */\n licensed: false,\n\n /**\n * Node configs\n */\n packageManager: NodePackageManager.PNPM,\n\n /**\n * Turn on prettier formatting\n */\n prettier: true,\n\n /**\n * Don't generate sample code.\n */\n sampleCode: false,\n\n /**\n * Make sure jest config is stored outside of package.json and use SWC\n * for faster tests.\n */\n jestOptions: {\n configFilePath: \"jest.config.json\",\n jestConfig: {\n transform: {\n [\"^.+\\\\.[t]sx?$\"]: new Transform(\"@swc/jest\"),\n },\n },\n },\n\n /**\n * SWC for faster testing\n */\n devDeps: [\"@swc/jest\", \"@swc/core\"],\n\n /**\n * Don't package test files.\n */\n npmIgnoreOptions: {\n ignorePatterns: [\"*.spec.*\", \"*.test.*\"],\n },\n });\n\n /**\n * We're using SWC now, remove ts-jest which is included by default.\n */\n this.project.deps.removeDependency(\"ts-jest\");\n\n /***************************************************************************\n *\n * Workspace Dependencies\n *\n * - Constructs are used to build out the AWS CDK environments.\n *\n **************************************************************************/\n\n this.project.addDeps(\n \"@openhi/config@workspace:*\",\n \"@openhi/constructs@workspace:*\",\n );\n\n /***************************************************************************\n *\n * Turbo Configuration\n *\n * - Activate turborepo for the project.\n *\n **************************************************************************/\n\n new TurboRepo(this.project);\n\n /***************************************************************************\n *\n * Define some basic Service Structure\n *\n **************************************************************************/\n\n new GenerateTemplates(this);\n\n /***************************************************************************\n *\n * Deployment Targets\n *\n **************************************************************************/\n\n [OPEN_HI_STAGE.DEV, OPEN_HI_STAGE.STAGE, OPEN_HI_STAGE.PROD].forEach(\n (stage) => {\n const targets = this.options?.config?.deploymentTargets?.[stage];\n if (targets?.primary) {\n this.addDeploymentTarget(\n stage,\n OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY,\n targets.primary,\n );\n }\n targets?.secondary?.forEach((env) => {\n this.addDeploymentTarget(\n stage,\n OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY,\n env,\n );\n });\n },\n );\n }\n\n private addDeploymentTarget = (\n awsStageType: ValueOf<typeof OPEN_HI_STAGE>,\n awsEnvironmentType: ValueOf<typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE>,\n envConfig: OpenHiEnvironmentConfig,\n ) => {\n new AwsDeploymentTarget(this.project, {\n account: envConfig.account,\n region: envConfig.region,\n awsStageType,\n awsEnvironmentType,\n localDeployment: true,\n localDeploymentConfig: {\n stackPattern: `${awsStageType}/${awsEnvironmentType}/*-${envConfig.account}-${envConfig.region}`,\n roleName: \"poweruseraccess\",\n },\n ciDeployment: true,\n ciDeploymentConfig: {\n roleArn: `arn:aws:iam::${envConfig.account}:role/GitHubOpenHiDeployer`,\n stackPattern: `${awsStageType}/${awsEnvironmentType}/*-${envConfig.account}-${envConfig.region}`,\n },\n\n branches:\n awsStageType === OPEN_HI_STAGE.DEV\n ? [\n {\n branch: \"feat/*\",\n description: [\n \"Feature branches for OpenHI (short form).\",\n \"These branches are used for developing new features.\",\n ],\n },\n {\n branch: \"feature/*\",\n description: [\n \"Feature branches for OpenHI.\",\n \"These branches are used for developing new features.\",\n ],\n },\n {\n branch: \"fix/*\",\n description: [\n \"Fix branches for OpenHI.\",\n \"This branch pattern is used when a developer is working on a fix on the project.\",\n ],\n },\n ]\n : [\n {\n branch: \"main\",\n description: [\n \"Main branch for OpenHI.\",\n \"This branch is used for the main branch.\",\n ],\n },\n ],\n });\n };\n\n get constructName(): string {\n return pascalCase([\"open\", \"hi\", this.id, \"service\"].join(\"-\"));\n }\n\n get outDir() {\n return [paramCase(this.openHi.id), paramCase(this.id)].join(sep);\n }\n\n get serviceName() {\n return [paramCase(this.openHi.id), paramCase(this.id)].join(\"-\");\n }\n}\n","import { existsSync, unlinkSync } from \"node:fs\";\nimport { sep } from \"node:path\";\nimport { SampleFile } from \"projen\";\nimport { OpenHiService } from \"../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/service-template.md\n */\n\nexport interface ServiceTemplateOptions {\n /**\n * The content of the sample file, as an array.\n */\n readonly contents: Array<string>;\n\n /**\n * The relative file path from the project root.\n */\n readonly filePath: string;\n\n /**\n * Overwrite this template file to it's original state?\n *\n * @default false\n */\n readonly overwrite?: boolean;\n}\n\nexport class ServiceTemplate {\n /**\n * The file being generated.\n */\n public file?: SampleFile;\n\n /**\n * Absolute Filepath, including the project path.\n */\n public fullFilePath: string;\n\n constructor(\n public service: OpenHiService,\n public options: ServiceTemplateOptions,\n ) {\n /**\n * Determine the full file path for this file.\n */\n this.fullFilePath = [\n this.service.project.outdir,\n this.options.filePath,\n ].join(sep);\n\n /**\n * Build the template file.\n */\n this.createTemplate();\n }\n\n protected createTemplate() {\n if (this.options.overwrite) {\n this.overwriteTemplate();\n }\n\n this.file = new SampleFile(this.service.project, this.options.filePath, {\n contents: this.options.contents.join(\"\\n\"),\n });\n }\n\n public overwriteTemplate() {\n /**\n * Delete file, if it exists.\n */\n if (existsSync(this.fullFilePath)) {\n unlinkSync(this.fullFilePath);\n }\n this.file = undefined;\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/app.md\n */\n\nexport class SrcApp extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/app.ts\",\n contents: [\n `import { OpenHiApp, ${service.constructName} } from \"@openhi/constructs\";`,\n `import { CONFIG } from \"./config\";`,\n ``,\n `const app = new OpenHiApp({ config: CONFIG });`,\n ``,\n `const stacks = app.environments.map((e) => {`,\n ` return new ${service.constructName}(e, { config: e.config });`,\n `});`,\n ``,\n `export { app, stacks };`,\n ``,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/app-test.md\n */\n\nexport class SrcAppTest extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/app.test.ts\",\n contents: [\n `import { Template } from \"aws-cdk-lib/assertions\";`,\n `import { Code, type CodeConfig } from \"aws-cdk-lib/aws-lambda\";`,\n `import { stacks } from \"./app\"`,\n ``,\n `/** Replace volatile CDK asset S3 keys/buckets with static values for snapshot stability. */`,\n `function normalizeTemplateForSnapshot(template: Record<string, unknown>): Record<string, unknown> {`,\n ` const staticBucket = \"mock-assets-bucket\";`,\n ` const staticKey = \"mock-asset-key.zip\";`,\n ` const json = JSON.stringify(template);`,\n ` const normalized = json`,\n ` .replace(/\"S3Key\":\\\\s*\"[^\"]+\\\\.zip\"/g, \\`\"S3Key\": \"\\${staticKey}\"\\`)`,\n ` .replace(/\"S3Bucket\":\\\\s*\"[^\"]+\"/g, \\`\"S3Bucket\": \"\\${staticBucket}\"\\`);`,\n ` return JSON.parse(normalized) as Record<string, unknown>;`,\n `}`,\n ``,\n `let fromAssetMock: jest.SpyInstance;`,\n ``,\n `beforeAll(() => {`,\n ` fromAssetMock = jest.spyOn(Code, \"fromAsset\").mockReturnValue({`,\n ` isInline: false,`,\n ` bind: (): CodeConfig => ({`,\n ` s3Location: {`,\n ` bucketName: \"mock-assets-bucket\",`,\n ` objectKey: \"mock-asset-key.zip\",`,\n ` },`,\n ` }),`,\n ` bindToResource: () => {`,\n ` return;`,\n ` },`,\n ` } as any);`,\n `});`,\n ``,\n `afterAll(() => {`,\n ` fromAssetMock?.mockRestore();`,\n `});`,\n ``,\n `describe(\"Smoke Test\", () => {`,\n ` it(\"should match previous snapshots\", () => {`,\n ` stacks.forEach((s) => {`,\n ` const template = Template.fromStack(s).toJSON();`,\n ` expect(normalizeTemplateForSnapshot(template)).toMatchSnapshot();`,\n ` });`,\n ` });`,\n `});`,\n ``,\n ],\n });\n }\n}\n","import { SourceCode } from \"projen\";\nimport { OpenHiService } from \"../../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/config.md\n */\n\nexport class SrcConfig extends SourceCode {\n constructor(service: OpenHiService) {\n super(service.project, \"src/config.ts\");\n\n /**\n * Imports\n */\n this.line(`import { OpenHiConfig } from \"@openhi/config\";`);\n this.line(\"\");\n\n /**\n * Write the config content\n */\n const start = \"export const CONFIG: OpenHiConfig = \";\n const mid = JSON.stringify(service.options?.config, null, 2);\n const end = \" as const;\";\n this.line(`${start}${mid}${end}`);\n }\n}\n","import { OpenHiService } from \"../../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/data/models/readme.md\n */\n\nexport class DataModelsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/data/models/README.md\",\n contents: [\n `# ${service.serviceName}: Data Models`,\n ``,\n `This directory contains data model definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/data/readme.md\n */\n\nexport class DataReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/data/README.md\",\n contents: [\n `# ${service.serviceName}: Data`,\n ``,\n `This directory contains data models and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/infrastructure/readme.md\n */\n\nexport class InfrastructureReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/infrastructure/README.md\",\n contents: [\n `# ${service.serviceName}: Infrastructure`,\n ``,\n `This directory contains infrastructure definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/integrations/readme.md\n */\n\nexport class IntegrationsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/integrations/README.md\",\n contents: [\n `# ${service.serviceName}: Integrations`,\n ``,\n `This directory contains integration definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/main.md\n */\n\nexport class SrcMain extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/main.ts\",\n contents: [`import { app } from \"./app\";`, ``, `app.synth();`, ``],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/readme.md\n */\n\nexport class SrcReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/README.md\",\n contents: [\n `# ${service.serviceName}: Service Overview`,\n ``,\n `This directory contains the main entry point for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/workflows/readme.md\n */\n\nexport class WorkflowsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/workflows/README.md\",\n contents: [\n `# ${service.serviceName}: Workflows`,\n ``,\n `This directory contains workflow definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../service\";\nimport { SrcApp } from \"./src/app\";\nimport { SrcAppTest } from \"./src/app-test\";\nimport { SrcConfig } from \"./src/config\";\nimport { DataModelsReadMe } from \"./src/data/models/README.md\";\nimport { DataReadMe } from \"./src/data/README.md\";\nimport { InfrastructureReadMe } from \"./src/infrastructure/README.md\";\nimport { IntegrationsReadMe } from \"./src/integrations/README.md\";\nimport { SrcMain } from \"./src/main\";\nimport { SrcReadMe } from \"./src/README.md\";\nimport { WorkflowsReadMe } from \"./src/workflows/README.md\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/generate-templates.md\n */\n\nexport class GenerateTemplates {\n constructor(private service: OpenHiService) {\n /**\n * Root src templates\n */\n new SrcApp(this.service);\n new SrcAppTest(this.service);\n new SrcConfig(this.service);\n new SrcMain(this.service);\n new SrcReadMe(this.service);\n\n /**\n * Data\n */\n new DataReadMe(this.service);\n new DataModelsReadMe(this.service);\n\n /**\n * Infrastructure\n */\n new InfrastructureReadMe(this.service);\n\n /**\n * Integrations\n */\n new IntegrationsReadMe(this.service);\n\n /**\n * Workflows\n */\n new WorkflowsReadMe(this.service);\n }\n}\n","import {\n AwsDeploymentConfig,\n MonorepoProject,\n} from \"@codedrifters/configulator\";\nimport { OPEN_HI_STAGE } from \"@openhi/config\";\nimport { Component } from \"projen\";\nimport { GitHub, GithubWorkflow } from \"projen/lib/github\";\nimport { JobPermission } from \"projen/lib/github/workflows-model\";\nimport { OpenHi } from \"../openhi\";\nimport type { OpenHiService } from \"../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/aws-teardown-workflow.md\n */\n\nexport interface AwsTeardownWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class AwsTeardownWorkflow extends Component {\n constructor(\n public rootProject: MonorepoProject,\n options: AwsTeardownWorkflowOptions,\n ) {\n super(rootProject);\n\n const { openhi } = options;\n\n /***************************************************************************\n *\n * Root project check\n *\n * Detect the root project and ensure it's of type MonorepoProject.\n *\n **************************************************************************/\n\n if (!(rootProject instanceof MonorepoProject)) {\n throw new Error(\n \"AwsTeardownWorkflow requires the root project to be a MonorepoProject\",\n );\n }\n\n //this.rootProject = project.root;\n\n /***************************************************************************\n *\n * GitHub Check\n *\n * Make sure github config is active in the project. This is to ensure all\n * workflows will be output properly during synth.\n *\n **************************************************************************/\n\n const github = GitHub.of(this.rootProject);\n\n if (!github) {\n throw new Error(\n \"AwsTeardownWorkflow requires a GitHub component in the root project\",\n );\n }\n\n /***************************************************************************\n *\n * Workflow Destroy Targets\n *\n * Find all the CI targets for the Global project in the DEV stage\n * only. One job per (account, region) teardowns all orphan stacks (Auth,\n * Core, data) in that account/region.\n *\n **************************************************************************/\n\n const devTargetsFor = (service: OpenHiService) =>\n AwsDeploymentConfig.of(service.project)?.awsDeploymentTargets.filter(\n (target) =>\n target.awsStageType === OPEN_HI_STAGE.DEV && target.ciDeployment,\n ) ?? [];\n const awsDestructionTargets = devTargetsFor(openhi.global);\n\n /***************************************************************************\n *\n * Create Workflow\n *\n * Make a new workflow for AWS stack teardown. This runs each night and is\n * also triggered each time a branch is deleted.\n *\n **************************************************************************/\n\n const workflow = new GithubWorkflow(github, \"teardown-dev\");\n workflow.on({\n workflowDispatch: {},\n schedule: [\n {\n cron: \"32 6 * * *\", // Every Sunday at 6:32 AM UTC\n },\n ],\n delete: {\n branches: [\"feature/*\", \"feat/*\", \"fix/*\"],\n },\n /* for debugging \n push: {\n branches: [\"feature/*\"],\n },\n */\n });\n\n awsDestructionTargets.forEach((target) => {\n const {\n awsStageType,\n awsEnvironmentType,\n account,\n region,\n ciDeploymentConfig,\n } = target;\n const { roleArn } = ciDeploymentConfig ?? {};\n\n workflow.addJob(`teardown-${account}-${region}`.toLowerCase(), {\n name: `Teardown Stacks in ${target.account}/${target.region}`,\n //if: \"github.event.ref_type == 'branch'\",\n runsOn: [\"ubuntu-latest\"],\n permissions: {\n contents: JobPermission.READ,\n idToken: JobPermission.WRITE,\n },\n env: {\n REPO: \"${{ github.repository }}\",\n REGIONS: [region].join(\" \"),\n },\n steps: [\n /**\n * Configure AWS creds.\n */\n {\n name: `AWS Creds ${awsStageType}/${awsEnvironmentType}/${account}/${region}`,\n uses: \"aws-actions/configure-aws-credentials@v4\",\n with: {\n \"role-to-assume\": roleArn,\n \"aws-region\": region,\n \"role-duration-seconds\": 900, // 15 minutes\n },\n },\n\n /**\n * Fetch all branch names in the repo\n */\n {\n name: \"Fetch All Branches\",\n id: \"fetch_branches\",\n uses: \"actions/github-script@v7\",\n with: {\n script: [\n \"const all = await github.paginate(github.rest.repos.listBranches, {\",\n \" owner: context.repo.owner,\",\n \" repo: context.repo.repo,\",\n \" per_page: 100\",\n \"});\",\n \"const names = all.map(b => b.name);\",\n \"console.log(`Found branches: ${names}`);\",\n 'core.setOutput(\"json\", JSON.stringify(names));',\n ].join(\"\\n\"),\n },\n },\n\n /**\n * Save branches to a file\n */\n {\n name: \"Save Branches to File\",\n run: [\n 'echo \"Saving branches to file\"',\n \"echo '${{ steps.fetch_branches.outputs.json }}' | jq -r '.[]' | sort -u > branches.txt\",\n 'echo \"Branches:\"',\n \"cat branches.txt\",\n ].join(\"\\n\"),\n },\n\n /**\n * Find all stacks tagged with a stage of dev. for this repo. return\n * tag and resource arn.\n */\n {\n name: \"Find Stacks by Tag\",\n id: \"find_stacks\",\n run: [\n \"set -euo pipefail\",\n \": > candidates.txt # columns: arn region branchTag\",\n\n \"# Build tag filters\",\n 'TAG_FILTERS=( \"Key=openhi:repo-name,Values=$REPO\" )',\n `TAG_FILTERS+=( \"Key=openhi:stage-type,Values=${OPEN_HI_STAGE.DEV}\" )`,\n\n \"for r in $REGIONS; do\",\n ` echo \"Scanning region: $r\"`,\n \" aws resourcegroupstaggingapi get-resources \\\\\",\n ' --region \"$r\" \\\\',\n ' --resource-type-filters \"cloudformation:stack\" \\\\',\n ' --tag-filters \"${TAG_FILTERS[@]}\" \\\\',\n ` | jq -r --arg r \"$r\" '`,\n \" .ResourceTagMappingList[]\",\n \" | . as $res\",\n ' | ($res.Tags[] | select(.Key==\"openhi:branch-name\") | .Value) as $branch',\n ' | [$res.ResourceARN, $r, ($branch // \"\")]',\n \" | @tsv\",\n \" ' >> candidates.txt\",\n \"done\",\n\n \"echo 'Tagged stacks:'\",\n `(echo -e \"ARN\\\\tREGION\\\\tBRANCH\"; cat candidates.txt) | column -t -s $'\\\\t'`,\n ].join(\"\\n\"),\n },\n\n /**\n * Determine which stacks are orphans that no longer have a matching branch.\n * Save those to a file for the next step.\n */\n {\n name: \"Determine Orphan Stacks (No Matching Branch)\",\n run: [\n \"set -euo pipefail\",\n \": > orphans.txt # arn region branch\",\n \"while IFS=$'\\\\t' read -r arn region branch; do\",\n ' [ -z \"$arn\" ] && continue',\n ' if [ -z \"$branch\" ]; then',\n \" # If no Branch tag, treat as not-a-preview; skip (or flip to delete if you want)\",\n \" continue\",\n \" fi\",\n ' if ! grep -Fxq \"$branch\" branches.txt; then',\n ' echo -e \"$arn\\\\t$region\\\\t$branch\" >> orphans.txt',\n \" fi\",\n \"done < candidates.txt\",\n \"\",\n \"if [ -s orphans.txt ]; then\",\n ' echo \"Orphan stacks (no matching branch):\"',\n \" (echo -e \\\"ARN\\\\tREGION\\\\tBRANCH\\\"; cat orphans.txt) | column -t -s $'\\\\t'\",\n \"else\",\n ' echo \"No orphan stacks found.\"',\n \"fi\",\n ].join(\"\\n\"),\n },\n\n /**\n * Delete orphan stacks.\n */\n {\n name: \"Delete Orphan Stacks\",\n if: \"hashFiles('orphans.txt') != ''\",\n run: [\n \"set -euo pipefail\",\n \"while IFS=$'\\\\t' read -r arn region branch; do\",\n ' [ -z \"$arn\" ] && continue',\n \" stack_name=$(cut -d'/' -f2 <<<\\\"$arn\\\")\",\n ' echo \"Deleting $stack_name (branch=$branch) in $region\"',\n ' aws cloudformation delete-stack --region \"$region\" --stack-name \"$stack_name\" || true',\n \"done < orphans.txt\",\n ].join(\"\\n\"),\n },\n ],\n });\n });\n }\n}\n","import { AwsDeployWorkflow, MonorepoProject } from \"@codedrifters/configulator\";\nimport { Component } from \"projen\";\nimport { OpenHi } from \"../openhi\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/build-dev-workflow.md\n */\n\nexport interface BuildDevelopmentWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class BuildDevelopmentWorkflow extends Component {\n constructor(\n parent: MonorepoProject,\n options: BuildDevelopmentWorkflowOptions,\n ) {\n super(parent, \"dev-workflow\");\n\n const { openhi } = options;\n\n /**\n * Global Service Deploy\n *\n * Deploy the Global service first to configure DNS\n */\n const { awsDeploymentTargets: globalTargets } = new AwsDeployWorkflow(\n openhi.global.project,\n {\n buildWorkflow: parent.buildWorkflow,\n },\n );\n\n /**\n * Auth Service Deploy\n *\n * Deploy the Auth service first (Cognito); data service and other stacks consume auth via SSM.\n */\n const { awsDeploymentTargets: authTargets } = new AwsDeployWorkflow(\n openhi.auth.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets],\n },\n );\n\n /**\n * Data Service Deploy\n *\n * Deploy the Data service (DynamoDB FHIR store, S3) after Global.\n */\n const { awsDeploymentTargets: dataTargets } = new AwsDeployWorkflow(\n openhi.data.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets],\n },\n );\n\n /**\n * Rest API Service Deploy\n *\n * Deploy the Rest API service after Data (and Global).\n */\n const { awsDeploymentTargets: restApiTargets } = new AwsDeployWorkflow(\n openhi.restApi.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n },\n );\n\n /**\n * GraphQL API Service Deploy\n *\n * Deploy the GraphQL API service after Data (sibling to REST API).\n */\n new AwsDeployWorkflow(openhi.graphApi.project, {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n });\n\n /**\n * Website Service Deploy\n *\n * Deploy the Website service after Global and REST API. The website\n * stack's CloudFront distribution fronts the REST API via an\n * `/api/*` behavior whose origin host is resolved at CFN update time\n * from the `REST_API_DOMAIN_NAME` SSM parameter — that parameter is\n * written by the matching branch's rest-api stack, so rest-api must\n * deploy first. The Global dependency holds for the child hosted zone\n * and wildcard certificate. Auth no longer needs to be upstream — the\n * Cognito IDs are exposed via the REST API's runtime-config endpoint\n * at request time, not via CFN dynamic references at update time.\n */\n new AwsDeployWorkflow(openhi.website.project, {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...restApiTargets],\n });\n }\n}\n","import { AwsDeployWorkflow, MonorepoProject } from \"@codedrifters/configulator\";\nimport { OPEN_HI_STAGE } from \"@openhi/config\";\nimport { Component } from \"projen\";\nimport { OpenHi } from \"../openhi\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/build-stage-workflow.md\n */\n\nexport interface BuildStageWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class BuildStageWorkflow extends Component {\n constructor(parent: MonorepoProject, options: BuildStageWorkflowOptions) {\n super(parent, \"stage-workflow\");\n\n const { openhi } = options;\n\n /**\n * Global Service Deploy\n *\n * Deploy the Global service first to configure DNS\n */\n const { awsDeploymentTargets: globalTargets, buildWorkflow } =\n new AwsDeployWorkflow(openhi.global.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflowOptions: {\n name: \"deploy-stage\",\n workflowTriggers: {\n push: {\n branches: [\"main\"],\n },\n workflowDispatch: {},\n },\n },\n });\n\n /**\n * Auth Service Deploy\n *\n * Deploy the Auth service first (Cognito); data service and other stacks consume auth via SSM.\n * Auth creates the stage build workflow; data service and REST API services add to it.\n */\n const { awsDeploymentTargets: authTargets } = new AwsDeployWorkflow(\n openhi.auth.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets],\n },\n );\n\n /**\n * Data Service Deploy\n *\n * Deploy the Data service (DynamoDB FHIR store, S3) after Global.\n */\n const { awsDeploymentTargets: dataTargets } = new AwsDeployWorkflow(\n openhi.data.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets],\n },\n );\n\n /**\n * Rest API Service Deploy\n */\n const { awsDeploymentTargets: restApiTargets } = new AwsDeployWorkflow(\n openhi.restApi.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n },\n );\n\n /**\n * GraphQL API Service Deploy\n */\n new AwsDeployWorkflow(openhi.graphApi.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n });\n\n /**\n * Website Service Deploy\n *\n * Deploy the Website service after Global and REST API. The website\n * stack's CloudFront distribution fronts the REST API via an\n * `/api/*` behavior whose origin host is resolved at CFN update time\n * from the `REST_API_DOMAIN_NAME` SSM parameter — that parameter is\n * written by the matching branch's rest-api stack, so rest-api must\n * deploy first. The Global dependency holds for the child hosted zone\n * and wildcard certificate. Auth no longer needs to be upstream — the\n * Cognito IDs are exposed via the REST API's runtime-config endpoint\n * at request time, not via CFN dynamic references at update time.\n */\n new AwsDeployWorkflow(openhi.website.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...restApiTargets],\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAca,YAAA,gBAAgB;;;;MAI3B,KAAK;;;;MAIL,OAAO;;;;MAIP,MAAM;;AAeK,YAAA,iCAAiC;;;;;MAK5C,SAAS;;;;;MAMT,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;ACpDb,iBAAA,0BAAA,OAAA;;;;;ACKA,SAAS,aAAa;;;ACCtB,IAAAA,iBAKO;AAXP,SAAS,OAAAC,YAAW;AACpB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAOP,SAAS,WAAW,kBAAkB;AACtC,SAAS,cAAc;AACvB,SAAS,oBAAoB,iBAAiB;;;ACd9C,SAAS,YAAY,kBAAkB;AACvC,SAAS,WAAW;AACpB,SAAS,kBAAkB;AA0BpB,IAAM,kBAAN,MAAsB;AAAA,EAW3B,YACS,SACA,SACP;AAFO;AACA;AAKP,SAAK,eAAe;AAAA,MAClB,KAAK,QAAQ,QAAQ;AAAA,MACrB,KAAK,QAAQ;AAAA,IACf,EAAE,KAAK,GAAG;AAKV,SAAK,eAAe;AAAA,EACtB;AAAA,EAEU,iBAAiB;AACzB,QAAI,KAAK,QAAQ,WAAW;AAC1B,WAAK,kBAAkB;AAAA,IACzB;AAEA,SAAK,OAAO,IAAI,WAAW,KAAK,QAAQ,SAAS,KAAK,QAAQ,UAAU;AAAA,MACtE,UAAU,KAAK,QAAQ,SAAS,KAAK,IAAI;AAAA,IAC3C,CAAC;AAAA,EACH;AAAA,EAEO,oBAAoB;AAIzB,QAAI,WAAW,KAAK,YAAY,GAAG;AACjC,iBAAW,KAAK,YAAY;AAAA,IAC9B;AACA,SAAK,OAAO;AAAA,EACd;AACF;;;ACrEO,IAAM,SAAN,cAAqB,gBAAgB;AAAA,EAC1C,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,uBAAuB,QAAQ,aAAa;AAAA,QAC5C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,gBAAgB,QAAQ,aAAa;AAAA,QACrC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACvBO,IAAM,aAAN,cAAyB,gBAAgB;AAAA,EAC9C,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AChEA,SAAS,kBAAkB;AAOpB,IAAM,YAAN,cAAwB,WAAW;AAAA,EACxC,YAAY,SAAwB;AAClC,UAAM,QAAQ,SAAS,eAAe;AAKtC,SAAK,KAAK,gDAAgD;AAC1D,SAAK,KAAK,EAAE;AAKZ,UAAM,QAAQ;AACd,UAAM,MAAM,KAAK,UAAU,QAAQ,SAAS,QAAQ,MAAM,CAAC;AAC3D,UAAM,MAAM;AACZ,SAAK,KAAK,GAAG,KAAK,GAAG,GAAG,GAAG,GAAG,EAAE;AAAA,EAClC;AACF;;;ACfO,IAAM,mBAAN,cAA+B,gBAAgB;AAAA,EACpD,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,kFAAkF,QAAQ,WAAW;AAAA,MACvG;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACfO,IAAM,aAAN,cAAyB,gBAAgB;AAAA,EAC9C,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,uEAAuE,QAAQ,WAAW;AAAA,MAC5F;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACfO,IAAM,uBAAN,cAAmC,gBAAgB;AAAA,EACxD,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,sFAAsF,QAAQ,WAAW;AAAA,MAC3G;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACfO,IAAM,qBAAN,cAAiC,gBAAgB;AAAA,EACtD,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,mFAAmF,QAAQ,WAAW;AAAA,MACxG;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AClBO,IAAM,UAAN,cAAsB,gBAAgB;AAAA,EAC3C,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU,CAAC,gCAAgC,IAAI,gBAAgB,EAAE;AAAA,IACnE,CAAC;AAAA,EACH;AACF;;;ACXO,IAAM,YAAN,cAAwB,gBAAgB;AAAA,EAC7C,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,wDAAwD,QAAQ,WAAW;AAAA,MAC7E;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACZO,IAAM,kBAAN,cAA8B,gBAAgB;AAAA,EACnD,YACE,SACA,SACA;AACA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU;AAAA,MACV,UAAU;AAAA,QACR,KAAK,QAAQ,WAAW;AAAA,QACxB;AAAA,QACA,gFAAgF,QAAQ,WAAW;AAAA,MACrG;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACTO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,SAAwB;AAAxB;AAIlB,QAAI,OAAO,KAAK,OAAO;AACvB,QAAI,WAAW,KAAK,OAAO;AAC3B,QAAI,UAAU,KAAK,OAAO;AAC1B,QAAI,QAAQ,KAAK,OAAO;AACxB,QAAI,UAAU,KAAK,OAAO;AAK1B,QAAI,WAAW,KAAK,OAAO;AAC3B,QAAI,iBAAiB,KAAK,OAAO;AAKjC,QAAI,qBAAqB,KAAK,OAAO;AAKrC,QAAI,mBAAmB,KAAK,OAAO;AAKnC,QAAI,gBAAgB,KAAK,OAAO;AAAA,EAClC;AACF;;;AZzBO,IAAM,uBAAuB;AAAA,EAClC,MAAM;AAAA,EACN,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,aAAa;AAAA,EACb,UAAU;AAAA,EACV,SAAS;AACX;AAgBO,IAAM,gBAAN,MAAoB;AAAA,EAGzB,YACS,QACA,IACA,SACP;AAHO;AACA;AACA;AA0IT,SAAQ,sBAAsB,CAC5B,cACA,oBACA,cACG;AACH,UAAI,oBAAoB,KAAK,SAAS;AAAA,QACpC,SAAS,UAAU;AAAA,QACnB,QAAQ,UAAU;AAAA,QAClB;AAAA,QACA;AAAA,QACA,iBAAiB;AAAA,QACjB,uBAAuB;AAAA,UACrB,cAAc,GAAG,YAAY,IAAI,kBAAkB,MAAM,UAAU,OAAO,IAAI,UAAU,MAAM;AAAA,UAC9F,UAAU;AAAA,QACZ;AAAA,QACA,cAAc;AAAA,QACd,oBAAoB;AAAA,UAClB,SAAS,gBAAgB,UAAU,OAAO;AAAA,UAC1C,cAAc,GAAG,YAAY,IAAI,kBAAkB,MAAM,UAAU,OAAO,IAAI,UAAU,MAAM;AAAA,QAChG;AAAA,QAEA,UACE,iBAAiB,6BAAc,MAC3B;AAAA,UACE;AAAA,YACE,QAAQ;AAAA,YACR,aAAa;AAAA,cACX;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,aAAa;AAAA,cACX;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,aAAa;AAAA,cACX;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF,IACA;AAAA,UACE;AAAA,YACE,QAAQ;AAAA,YACR,aAAa;AAAA,cACX;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACR,CAAC;AAAA,IACH;AAtLE,SAAK,UAAU,IAAI,OAAO,oBAAoB;AAAA;AAAA;AAAA;AAAA,MAI5C,sBAAsB;AAAA,MACtB,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,QAAQ,KAAK,OAAO;AAAA,MACpB,YACE,KAAK,SAAS,QAAQ,UAAU,KAAK,iBACrC,QAAQ;AAAA,MACV,eACE,KAAK,SAAS,QAAQ,UAAU,KAAK,iBACrC,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOV,UAAU;AAAA;AAAA;AAAA;AAAA,MAKV,gBAAgB,mBAAmB;AAAA;AAAA;AAAA;AAAA,MAKnC,UAAU;AAAA;AAAA;AAAA;AAAA,MAKV,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,MAMZ,aAAa;AAAA,QACX,gBAAgB;AAAA,QAChB,YAAY;AAAA,UACV,WAAW;AAAA,YACT,CAAC,eAAe,GAAG,IAAI,UAAU,WAAW;AAAA,UAC9C;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,SAAS,CAAC,aAAa,WAAW;AAAA;AAAA;AAAA;AAAA,MAKlC,kBAAkB;AAAA,QAChB,gBAAgB,CAAC,YAAY,UAAU;AAAA,MACzC;AAAA,IACF,CAAC;AAKD,SAAK,QAAQ,KAAK,iBAAiB,SAAS;AAU5C,SAAK,QAAQ;AAAA,MACX;AAAA,MACA;AAAA,IACF;AAUA,QAAI,UAAU,KAAK,OAAO;AAQ1B,QAAI,kBAAkB,IAAI;AAQ1B,KAAC,6BAAc,KAAK,6BAAc,OAAO,6BAAc,IAAI,EAAE;AAAA,MAC3D,CAAC,UAAU;AACT,cAAM,UAAU,KAAK,SAAS,QAAQ,oBAAoB,KAAK;AAC/D,YAAI,SAAS,SAAS;AACpB,eAAK;AAAA,YACH;AAAA,YACA,8CAA+B;AAAA,YAC/B,QAAQ;AAAA,UACV;AAAA,QACF;AACA,iBAAS,WAAW,QAAQ,CAAC,QAAQ;AACnC,eAAK;AAAA,YACH;AAAA,YACA,8CAA+B;AAAA,YAC/B;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EA4DA,IAAI,gBAAwB;AAC1B,WAAO,WAAW,CAAC,QAAQ,MAAM,KAAK,IAAI,SAAS,EAAE,KAAK,GAAG,CAAC;AAAA,EAChE;AAAA,EAEA,IAAI,SAAS;AACX,WAAO,CAAC,UAAU,KAAK,OAAO,EAAE,GAAG,UAAU,KAAK,EAAE,CAAC,EAAE,KAAKC,IAAG;AAAA,EACjE;AAAA,EAEA,IAAI,cAAc;AAChB,WAAO,CAAC,UAAU,KAAK,OAAO,EAAE,GAAG,UAAU,KAAK,EAAE,CAAC,EAAE,KAAK,GAAG;AAAA,EACjE;AACF;;;AahQA,IAAAC,iBAA8B;AAJ9B;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,SAAS,iBAAiB;AAC1B,SAAS,QAAQ,sBAAsB;AACvC,SAAS,qBAAqB;AAevB,IAAM,sBAAN,cAAkC,UAAU;AAAA,EACjD,YACS,aACP,SACA;AACA,UAAM,WAAW;AAHV;AAKP,UAAM,EAAE,OAAO,IAAI;AAUnB,QAAI,EAAE,uBAAuB,kBAAkB;AAC7C,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAaA,UAAM,SAAS,OAAO,GAAG,KAAK,WAAW;AAEzC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAYA,UAAM,gBAAgB,CAAC,YACrB,oBAAoB,GAAG,QAAQ,OAAO,GAAG,qBAAqB;AAAA,MAC5D,CAAC,WACC,OAAO,iBAAiB,6BAAc,OAAO,OAAO;AAAA,IACxD,KAAK,CAAC;AACR,UAAM,wBAAwB,cAAc,OAAO,MAAM;AAWzD,UAAM,WAAW,IAAI,eAAe,QAAQ,cAAc;AAC1D,aAAS,GAAG;AAAA,MACV,kBAAkB,CAAC;AAAA,MACnB,UAAU;AAAA,QACR;AAAA,UACE,MAAM;AAAA;AAAA,QACR;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,UAAU,CAAC,aAAa,UAAU,OAAO;AAAA,MAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMF,CAAC;AAED,0BAAsB,QAAQ,CAAC,WAAW;AACxC,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,IAAI;AACJ,YAAM,EAAE,QAAQ,IAAI,sBAAsB,CAAC;AAE3C,eAAS,OAAO,YAAY,OAAO,IAAI,MAAM,GAAG,YAAY,GAAG;AAAA,QAC7D,MAAM,sBAAsB,OAAO,OAAO,IAAI,OAAO,MAAM;AAAA;AAAA,QAE3D,QAAQ,CAAC,eAAe;AAAA,QACxB,aAAa;AAAA,UACX,UAAU,cAAc;AAAA,UACxB,SAAS,cAAc;AAAA,QACzB;AAAA,QACA,KAAK;AAAA,UACH,MAAM;AAAA,UACN,SAAS,CAAC,MAAM,EAAE,KAAK,GAAG;AAAA,QAC5B;AAAA,QACA,OAAO;AAAA;AAAA;AAAA;AAAA,UAIL;AAAA,YACE,MAAM,aAAa,YAAY,IAAI,kBAAkB,IAAI,OAAO,IAAI,MAAM;AAAA,YAC1E,MAAM;AAAA,YACN,MAAM;AAAA,cACJ,kBAAkB;AAAA,cAClB,cAAc;AAAA,cACd,yBAAyB;AAAA;AAAA,YAC3B;AAAA,UACF;AAAA;AAAA;AAAA;AAAA,UAKA;AAAA,YACE,MAAM;AAAA,YACN,IAAI;AAAA,YACJ,MAAM;AAAA,YACN,MAAM;AAAA,cACJ,QAAQ;AAAA,gBACN;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cACF,EAAE,KAAK,IAAI;AAAA,YACb;AAAA,UACF;AAAA;AAAA;AAAA;AAAA,UAKA;AAAA,YACE,MAAM;AAAA,YACN,KAAK;AAAA,cACH;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF,EAAE,KAAK,IAAI;AAAA,UACb;AAAA;AAAA;AAAA;AAAA;AAAA,UAMA;AAAA,YACE,MAAM;AAAA,YACN,IAAI;AAAA,YACJ,KAAK;AAAA,cACH;AAAA,cACA;AAAA,cAEA;AAAA,cACA;AAAA,cACA,gDAAgD,6BAAc,GAAG;AAAA,cAEjE;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cAEA;AAAA,cACA;AAAA,YACF,EAAE,KAAK,IAAI;AAAA,UACb;AAAA;AAAA;AAAA;AAAA;AAAA,UAMA;AAAA,YACE,MAAM;AAAA,YACN,KAAK;AAAA,cACH;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF,EAAE,KAAK,IAAI;AAAA,UACb;AAAA;AAAA;AAAA;AAAA,UAKA;AAAA,YACE,MAAM;AAAA,YACN,IAAI;AAAA,YACJ,KAAK;AAAA,cACH;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF,EAAE,KAAK,IAAI;AAAA,UACb;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;;;ACtQA,SAAS,yBAA0C;AACnD,SAAS,aAAAC,kBAAiB;AAcnB,IAAM,2BAAN,cAAuCA,WAAU;AAAA,EACtD,YACE,QACA,SACA;AACA,UAAM,QAAQ,cAAc;AAE5B,UAAM,EAAE,OAAO,IAAI;AAOnB,UAAM,EAAE,sBAAsB,cAAc,IAAI,IAAI;AAAA,MAClD,OAAO,OAAO;AAAA,MACd;AAAA,QACE,eAAe,OAAO;AAAA,MACxB;AAAA,IACF;AAOA,UAAM,EAAE,sBAAsB,YAAY,IAAI,IAAI;AAAA,MAChD,OAAO,KAAK;AAAA,MACZ;AAAA,QACE,eAAe,OAAO;AAAA,QACtB,oBAAoB,CAAC,GAAG,aAAa;AAAA,MACvC;AAAA,IACF;AAOA,UAAM,EAAE,sBAAsB,YAAY,IAAI,IAAI;AAAA,MAChD,OAAO,KAAK;AAAA,MACZ;AAAA,QACE,eAAe,OAAO;AAAA,QACtB,oBAAoB,CAAC,GAAG,eAAe,GAAG,WAAW;AAAA,MACvD;AAAA,IACF;AAOA,UAAM,EAAE,sBAAsB,eAAe,IAAI,IAAI;AAAA,MACnD,OAAO,QAAQ;AAAA,MACf;AAAA,QACE,eAAe,OAAO;AAAA,QACtB,oBAAoB,CAAC,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW;AAAA,MACvE;AAAA,IACF;AAOA,QAAI,kBAAkB,OAAO,SAAS,SAAS;AAAA,MAC7C,eAAe,OAAO;AAAA,MACtB,oBAAoB,CAAC,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW;AAAA,IACvE,CAAC;AAeD,QAAI,kBAAkB,OAAO,QAAQ,SAAS;AAAA,MAC5C,eAAe,OAAO;AAAA,MACtB,oBAAoB,CAAC,GAAG,eAAe,GAAG,cAAc;AAAA,IAC1D,CAAC;AAAA,EACH;AACF;;;ACtGA,IAAAC,iBAA8B;AAD9B,SAAS,qBAAAC,0BAA0C;AAEnD,SAAS,aAAAC,kBAAiB;AAcnB,IAAM,qBAAN,cAAiCA,WAAU;AAAA,EAChD,YAAY,QAAyB,SAAoC;AACvE,UAAM,QAAQ,gBAAgB;AAE9B,UAAM,EAAE,OAAO,IAAI;AAOnB,UAAM,EAAE,sBAAsB,eAAe,cAAc,IACzD,IAAID,mBAAkB,OAAO,OAAO,SAAS;AAAA,MAC3C,cAAc,6BAAc;AAAA,MAC5B,sBAAsB;AAAA,QACpB,MAAM;AAAA,QACN,kBAAkB;AAAA,UAChB,MAAM;AAAA,YACJ,UAAU,CAAC,MAAM;AAAA,UACnB;AAAA,UACA,kBAAkB,CAAC;AAAA,QACrB;AAAA,MACF;AAAA,IACF,CAAC;AAQH,UAAM,EAAE,sBAAsB,YAAY,IAAI,IAAIA;AAAA,MAChD,OAAO,KAAK;AAAA,MACZ;AAAA,QACE,cAAc,6BAAc;AAAA,QAC5B;AAAA,QACA,oBAAoB,CAAC,GAAG,aAAa;AAAA,MACvC;AAAA,IACF;AAOA,UAAM,EAAE,sBAAsB,YAAY,IAAI,IAAIA;AAAA,MAChD,OAAO,KAAK;AAAA,MACZ;AAAA,QACE,cAAc,6BAAc;AAAA,QAC5B;AAAA,QACA,oBAAoB,CAAC,GAAG,eAAe,GAAG,WAAW;AAAA,MACvD;AAAA,IACF;AAKA,UAAM,EAAE,sBAAsB,eAAe,IAAI,IAAIA;AAAA,MACnD,OAAO,QAAQ;AAAA,MACf;AAAA,QACE,cAAc,6BAAc;AAAA,QAC5B;AAAA,QACA,oBAAoB,CAAC,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW;AAAA,MACvE;AAAA,IACF;AAKA,QAAIA,mBAAkB,OAAO,SAAS,SAAS;AAAA,MAC7C,cAAc,6BAAc;AAAA,MAC5B;AAAA,MACA,oBAAoB,CAAC,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW;AAAA,IACvE,CAAC;AAeD,QAAIA,mBAAkB,OAAO,QAAQ,SAAS;AAAA,MAC5C,cAAc,6BAAc;AAAA,MAC5B;AAAA,MACA,oBAAoB,CAAC,GAAG,eAAe,GAAG,cAAc;AAAA,IAC1D,CAAC;AAAA,EACH;AACF;;;AhB/BO,IAAM,SAAN,MAAa;AAAA,EAgDlB,YAAY,UAAyB,CAAC,GAAG;AASvC,SAAK,UAAU,MAAM,EAAE,MAAM,SAAS,GAAG,OAAO;AAChD,SAAK,cAAc,KAAK,QAAQ;AAChC,SAAK,KAAK,KAAK,QAAQ,aAAa,QAAQ;AAM5C,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cAAc,KAAK;AAWzB,SAAK,SAAS,IAAI,cAAc,MAAM,UAAU;AAAA,MAC9C,MAAM,qBAAqB;AAAA,MAC3B,QAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,uBAAuB,CAAC;AAAA,MACxC;AAAA,IACF,CAAC;AAWD,SAAK,OAAO,IAAI,cAAc,MAAM,QAAQ;AAAA,MAC1C,MAAM,qBAAqB;AAAA,MAC3B,QAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,qBAAqB,CAAC;AAAA,MACtC;AAAA,IACF,CAAC;AAUD,SAAK,UAAU,IAAI,cAAc,MAAM,YAAY;AAAA,MACjD,MAAM,qBAAqB;AAAA,MAC3B,QAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,wBAAwB,CAAC;AAAA,MACzC;AAAA,IACF,CAAC;AAWD,SAAK,OAAO,IAAI,cAAc,MAAM,QAAQ;AAAA,MAC1C,MAAM,qBAAqB;AAAA,MAC3B,QAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,qBAAqB,CAAC;AAAA,MACtC;AAAA,IACF,CAAC;AAUD,SAAK,WAAW,IAAI,cAAc,MAAM,WAAW;AAAA,MACjD,MAAM,qBAAqB;AAAA,MAC3B,QAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,yBAAyB,CAAC;AAAA,MAC1C;AAAA,IACF,CAAC;AAWD,SAAK,UAAU,IAAI,cAAc,MAAM,WAAW;AAAA,MAChD,MAAM,qBAAqB;AAAA,MAC3B,QAAQ;AAAA,QACN,KAAK,SAAS,iBAAiB,CAAC;AAAA,QAChC,KAAK,SAAS,wBAAwB,CAAC;AAAA,MACzC;AAAA,IACF,CAAC;AAkBD,QAAI,yBAAyB,aAAa,EAAE,QAAQ,KAAK,CAAC;AAC1D,QAAI,mBAAmB,aAAa,EAAE,QAAQ,KAAK,CAAC;AAEpD,QAAI,oBAAoB,aAAa,EAAE,QAAQ,KAAK,CAAC;AAAA,EACvD;AACF;","names":["import_config","sep","sep","import_config","Component","import_config","AwsDeployWorkflow","Component"]}
|
|
1
|
+
{"version":3,"sources":["../../config/src/open-hi-config.ts","../../config/src/index.ts","../src/openhi.ts","../src/service.ts","../src/templates/service-template.ts","../src/templates/src/app.ts","../src/templates/src/app-test.ts","../src/templates/src/config.ts","../src/templates/src/data/models/README.md.ts","../src/templates/src/data/README.md.ts","../src/templates/src/infrastructure/README.md.ts","../src/templates/src/integrations/README.md.ts","../src/templates/src/main.ts","../src/templates/src/README.md.ts","../src/templates/src/workflows/README.md.ts","../src/templates/generate-templates.ts","../src/workflows/aws-teardown-workflow.ts","../src/workflows/build-dev-workflow.ts","../src/workflows/build-stage-workflow.ts"],"sourcesContent":["/*******************************************************************************\n *\n * OpenHi Config\n *\n * These types are kept in their own package to prevent dependency conflicts and\n * conditions between @openhi/constructs and @openhi/platform..\n *\n ******************************************************************************/\n\n/**\n * Stage Types\n *\n * What stage of deployment is this? Dev, staging, or prod?\n */\nexport const OPEN_HI_STAGE = {\n /**\n * Development environment, typically used for testing and development.\n */\n DEV: \"dev\",\n /**\n * Staging environment, used for pre-production testing.\n */\n STAGE: \"stage\",\n /**\n * Production environment, used for live deployments.\n */\n PROD: \"prod\",\n} as const;\n\n/**\n * Above const as a type.\n */\nexport type OpenHiStageType =\n (typeof OPEN_HI_STAGE)[keyof typeof OPEN_HI_STAGE];\n\n/**\n * Deployment Target Role\n *\n * Is this (account, region) the primary or a secondary deployment target for the stage?\n * Works for both multi-region (different regions) and cellular (same region, different accounts).\n */\nexport const OPEN_HI_DEPLOYMENT_TARGET_ROLE = {\n /**\n * The primary deployment target for this stage (main account/region).\n * For example, the base DynamoDB region for global tables.\n */\n PRIMARY: \"primary\",\n\n /**\n * A secondary deployment target for this stage (additional account/region).\n * For example, a replica region for a global DynamoDB table, or another cell in the same region.\n */\n SECONDARY: \"secondary\",\n} as const;\n\n/**\n * Above const as a type.\n */\nexport type OpenHiDeploymentTargetRoleType =\n (typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE)[keyof typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE];\n\nexport interface OpenHiEnvironmentConfig {\n account: string;\n region: string;\n /**\n * Route53 zone containing DNS for this service.\n */\n hostedZoneId?: string;\n zoneName?: string;\n}\n\n/**\n * Represents the configuration for OpenHi services across different stages and\n * deployment targets.\n */\nexport interface OpenHiConfig {\n versions?: {\n cdk?: {\n cdkLibVersion?: string;\n cdkCliVersion?: string;\n };\n };\n deploymentTargets?: {\n [OPEN_HI_STAGE.DEV]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n [OPEN_HI_STAGE.STAGE]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n [OPEN_HI_STAGE.PROD]?: {\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY]?: OpenHiEnvironmentConfig;\n [OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY]?: Array<OpenHiEnvironmentConfig>;\n };\n };\n}\n","export * from \"./open-hi-config\";\n","import {\n MonorepoProject,\n MonorepoProjectOptions,\n} from \"@codedrifters/configulator\";\nimport { OpenHiConfig } from \"@openhi/config\";\nimport { merge } from \"ts-deepmerge\";\nimport { SetOptional } from \"type-fest\";\nimport { OPEN_HI_SERVICE_TYPE, OpenHiService } from \"./service\";\nimport { AwsTeardownWorkflow } from \"./workflows/aws-teardown-workflow\";\nimport { BuildDevelopmentWorkflow } from \"./workflows/build-dev-workflow\";\nimport { BuildStageWorkflow } from \"./workflows/build-stage-workflow\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/openhi.md\n */\n\nexport interface OpenHiOptions {\n /*****************************************************************************\n *\n * Root Project Configuration Options\n *\n * Configuration options for the root monorepo project that contains all\n * OpenHi services and coordinate releases and builds.\n *\n ****************************************************************************/\n\n readonly rootProjectOptions?: SetOptional<MonorepoProjectOptions, \"name\">;\n\n /**\n * Monorepo root project, if using an existing project.\n */\n readonly rootProject?: MonorepoProject;\n\n /*****************************************************************************\n *\n * Service Configuration Options\n *\n * These options are used to configure the various services within the OpenHi\n * framework. Each service can have its own configuration settings, which will\n * be merged with the default configuration.\n *\n ****************************************************************************/\n\n /**\n * Default configuration used in all services with undefined configs.\n */\n readonly defaultConfig?: OpenHiConfig;\n\n /**\n * Global Service Config\n */\n readonly globalServiceConfig?: OpenHiConfig;\n\n /**\n * Auth Service Config\n */\n readonly authServiceConfig?: OpenHiConfig;\n\n /**\n * Rest API Service Config\n */\n readonly restApiServiceConfig?: OpenHiConfig;\n\n /**\n * Data Service Config (DynamoDB FHIR store, S3, etc.)\n */\n readonly dataServiceConfig?: OpenHiConfig;\n\n /**\n * GraphQL API Service Config\n */\n readonly graphApiServiceConfig?: OpenHiConfig;\n\n /**\n * Website Service Config (static hosting + content uploader).\n */\n readonly websiteServiceConfig?: OpenHiConfig;\n}\n\nexport class OpenHi {\n /**\n * Final options used to build this instance.\n */\n public options: OpenHiOptions;\n\n /**\n * Monorepo root project, either passed in as an argument or generated in\n * this component\n */\n public readonly rootProject?: MonorepoProject;\n\n /**\n * Test identifier for this instance.\n */\n public readonly id: string;\n\n /**\n * Global service (deployed first; Auth, data service, and other stacks depend on it).\n */\n public readonly global: OpenHiService;\n\n /**\n * Auth service (deployed first; data service, REST API, and data services depend on it).\n */\n public readonly auth: OpenHiService;\n\n /**\n * Rest API service\n */\n public readonly restApi: OpenHiService;\n\n /**\n * Data service (DynamoDB FHIR store, S3, and other persistence).\n */\n public readonly data: OpenHiService;\n\n /**\n * GraphQL API service (AppSync); deploys as sibling to REST API after Data.\n */\n public readonly graphApi: OpenHiService;\n\n /**\n * Website service (static hosting + content uploader); deploys as sibling\n * to the other services after Global.\n */\n public readonly website: OpenHiService;\n\n constructor(options: OpenHiOptions = {}) {\n /***************************************************************************\n *\n * Options\n *\n * Combine input options with defaults.\n *\n **************************************************************************/\n\n this.options = merge({ name: \"openhi\" }, options);\n this.rootProject = this.options.rootProject;\n this.id = this.options.rootProject?.name ?? \"openhi\";\n\n /**\n * In future we would create root project here. For now, require it to be\n * passed in.\n */\n if (!this.rootProject) {\n throw new Error(\n \"OpenHi requires a MonorepoProject to be passed in via the rootProject option\",\n );\n }\n\n const rootProject = this.rootProject;\n\n /***************************************************************************\n *\n * Global Service\n *\n * Global infrastructure (Route53, ACM). Deployed first in primary;\n * Auth, data service, and other stacks depend on it.\n *\n **************************************************************************/\n\n this.global = new OpenHiService(this, \"global\", {\n type: OPEN_HI_SERVICE_TYPE.GLOBAL,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.globalServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Auth Service\n *\n * Authentication (Cognito user pool, client, domain, KMS). Deployed first;\n * data service, REST API, and data services consume auth via SSM.\n *\n **************************************************************************/\n\n this.auth = new OpenHiService(this, \"auth\", {\n type: OPEN_HI_SERVICE_TYPE.AUTH,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.authServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Rest API service\n *\n * This contains the REST API for the OpenHi platform.\n *\n **************************************************************************/\n\n this.restApi = new OpenHiService(this, \"rest-api\", {\n type: OPEN_HI_SERVICE_TYPE.REST_API,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.restApiServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Data Service\n *\n * Data storage stack (DynamoDB FHIR store, S3, etc.). Deployed so that\n * REST API and other services can reference the table via cross-stack.\n *\n **************************************************************************/\n\n this.data = new OpenHiService(this, \"data\", {\n type: OPEN_HI_SERVICE_TYPE.DATA_SERVICE,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.dataServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * GraphQL API service\n *\n * AppSync API; deploys as sibling to REST API after Data.\n *\n **************************************************************************/\n\n this.graphApi = new OpenHiService(this, \"graphql\", {\n type: OPEN_HI_SERVICE_TYPE.GRAPHQL,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.graphApiServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Website service\n *\n * Static hosting (CloudFront + S3 + Lambda@Edge) and content uploader;\n * deploys as a sibling to the other services after Global.\n *\n **************************************************************************/\n\n this.website = new OpenHiService(this, \"website\", {\n type: OPEN_HI_SERVICE_TYPE.WEBSITE,\n config: merge(\n this.options?.defaultConfig ?? {},\n this.options?.websiteServiceConfig ?? {},\n ),\n });\n\n /***************************************************************************\n *\n * Integrations\n *\n * Various purpose specific integrations.\n *\n **************************************************************************/\n\n /***************************************************************************\n *\n * Workflows\n *\n * Workflows for each environment.\n *\n **************************************************************************/\n\n new BuildDevelopmentWorkflow(rootProject, { openhi: this });\n new BuildStageWorkflow(rootProject, { openhi: this });\n\n new AwsTeardownWorkflow(rootProject, { openhi: this });\n }\n}\n","import { sep } from \"path\";\nimport {\n AwsDeploymentTarget,\n TurboRepo,\n VERSION,\n} from \"@codedrifters/configulator\";\nimport {\n OPEN_HI_DEPLOYMENT_TARGET_ROLE,\n OPEN_HI_STAGE,\n OpenHiConfig,\n OpenHiEnvironmentConfig,\n} from \"@openhi/config\";\nimport { paramCase, pascalCase } from \"change-case\";\nimport { awscdk } from \"projen\";\nimport { NodePackageManager, Transform } from \"projen/lib/javascript\";\nimport { ValueOf } from \"type-fest\";\nimport { OpenHi } from \"./openhi\";\nimport { GenerateTemplates } from \"./templates/generate-templates\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/service.md\n */\n\nexport const OPEN_HI_SERVICE_TYPE = {\n AUTH: \"auth\",\n DATA_SERVICE: \"data\",\n GLOBAL: \"global\",\n GRAPHQL: \"graphql\",\n INTEGRATION: \"integration\",\n REST_API: \"rest-api\",\n WEBSITE: \"website\",\n} as const;\n\nexport interface OpenHiServiceOptions {\n /**\n * Configuration for this service.\n *\n * @default uses the global default config.\n */\n readonly config: OpenHiConfig;\n\n /**\n * What type of service is this?\n */\n readonly type: ValueOf<typeof OPEN_HI_SERVICE_TYPE>;\n}\n\nexport class OpenHiService {\n public readonly project: awscdk.AwsCdkTypeScriptApp;\n\n constructor(\n public openHi: OpenHi,\n public id: string,\n public options: OpenHiServiceOptions,\n ) {\n /**\n * Build the construct name we expect to use in this service.\n */\n\n /***************************************************************************\n *\n * Projen based CDK build\n *\n **************************************************************************/\n\n this.project = new awscdk.AwsCdkTypeScriptApp({\n /**\n * Top level project config options\n */\n defaultReleaseBranch: \"main\",\n name: this.serviceName,\n outdir: this.outDir,\n parent: this.openHi.rootProject,\n cdkVersion:\n this.options?.config?.versions?.cdk?.cdkLibVersion ??\n VERSION.AWS_CDK_LIB_VERSION,\n cdkCliVersion:\n this.options?.config?.versions?.cdk?.cdkCliVersion ??\n VERSION.AWS_CDK_CLI_VERSION,\n\n /**\n * Packaging options\n *\n * TODO: Figure out license for monorepo vs per package?\n */\n licensed: false,\n\n /**\n * Node configs\n */\n packageManager: NodePackageManager.PNPM,\n\n /**\n * Turn on prettier formatting\n */\n prettier: true,\n\n /**\n * Don't generate sample code.\n */\n sampleCode: false,\n\n /**\n * Make sure jest config is stored outside of package.json and use SWC\n * for faster tests.\n */\n jestOptions: {\n configFilePath: \"jest.config.json\",\n jestConfig: {\n transform: {\n [\"^.+\\\\.[t]sx?$\"]: new Transform(\"@swc/jest\"),\n },\n },\n },\n\n /**\n * SWC for faster testing\n */\n devDeps: [\"@swc/jest\", \"@swc/core\"],\n\n /**\n * Don't package test files.\n */\n npmIgnoreOptions: {\n ignorePatterns: [\"*.spec.*\", \"*.test.*\"],\n },\n });\n\n /**\n * We're using SWC now, remove ts-jest which is included by default.\n */\n this.project.deps.removeDependency(\"ts-jest\");\n\n /***************************************************************************\n *\n * Workspace Dependencies\n *\n * - Constructs are used to build out the AWS CDK environments.\n *\n **************************************************************************/\n\n this.project.addDeps(\n \"@openhi/config@workspace:*\",\n \"@openhi/constructs@workspace:*\",\n );\n\n /***************************************************************************\n *\n * Turbo Configuration\n *\n * - Activate turborepo for the project.\n *\n **************************************************************************/\n\n new TurboRepo(this.project);\n\n TurboRepo.of(this.project)?.activateBranchNameEnvVar({\n tasks: [\"post-compile\"],\n });\n\n /**\n * The website service composes its hostname (and the S3 key prefix\n * the lifecycle rule expires) from the OPENHI_PR_NUMBER env var on\n * non-release-branch synths. Turborepo strips env vars that are\n * not declared on the task, so the value reaches the workflow's\n * `env:` block but never reaches the `cdk synth` subprocess that\n * the post-compile task runs. Add OPENHI_PR_NUMBER to the\n * post-compile task env so Turborepo passes it through.\n *\n * Scoped to the website project — no other service reads\n * OPENHI_PR_NUMBER, so adding it elsewhere would only cause\n * spurious per-PR cache misses on cdk synth.\n */\n if (this.options.type === OPEN_HI_SERVICE_TYPE.WEBSITE) {\n const turbo = TurboRepo.of(this.project);\n const postCompileEnv = turbo?.postCompileTask?.env;\n if (postCompileEnv && !postCompileEnv.includes(\"OPENHI_PR_NUMBER\")) {\n postCompileEnv.push(\"OPENHI_PR_NUMBER\");\n }\n }\n\n /***************************************************************************\n *\n * Define some basic Service Structure\n *\n **************************************************************************/\n\n new GenerateTemplates(this);\n\n /***************************************************************************\n *\n * Deployment Targets\n *\n **************************************************************************/\n\n [OPEN_HI_STAGE.DEV, OPEN_HI_STAGE.STAGE, OPEN_HI_STAGE.PROD].forEach(\n (stage) => {\n const targets = this.options?.config?.deploymentTargets?.[stage];\n if (targets?.primary) {\n this.addDeploymentTarget(\n stage,\n OPEN_HI_DEPLOYMENT_TARGET_ROLE.PRIMARY,\n targets.primary,\n );\n }\n targets?.secondary?.forEach((env) => {\n this.addDeploymentTarget(\n stage,\n OPEN_HI_DEPLOYMENT_TARGET_ROLE.SECONDARY,\n env,\n );\n });\n },\n );\n }\n\n private addDeploymentTarget = (\n awsStageType: ValueOf<typeof OPEN_HI_STAGE>,\n awsEnvironmentType: ValueOf<typeof OPEN_HI_DEPLOYMENT_TARGET_ROLE>,\n envConfig: OpenHiEnvironmentConfig,\n ) => {\n new AwsDeploymentTarget(this.project, {\n account: envConfig.account,\n region: envConfig.region,\n awsStageType,\n awsEnvironmentType,\n localDeployment: true,\n localDeploymentConfig: {\n stackPattern: `${awsStageType}/${awsEnvironmentType}/*-${envConfig.account}-${envConfig.region}`,\n roleName: \"poweruseraccess\",\n },\n ciDeployment: true,\n ciDeploymentConfig: {\n roleArn: `arn:aws:iam::${envConfig.account}:role/GitHubOpenHiDeployer`,\n stackPattern: `${awsStageType}/${awsEnvironmentType}/*-${envConfig.account}-${envConfig.region}`,\n },\n\n branches:\n awsStageType === OPEN_HI_STAGE.DEV\n ? [\n {\n branch: \"feat/*\",\n description: [\n \"Feature branches for OpenHI (short form).\",\n \"These branches are used for developing new features.\",\n ],\n },\n {\n branch: \"feature/*\",\n description: [\n \"Feature branches for OpenHI.\",\n \"These branches are used for developing new features.\",\n ],\n },\n {\n branch: \"fix/*\",\n description: [\n \"Fix branches for OpenHI.\",\n \"This branch pattern is used when a developer is working on a fix on the project.\",\n ],\n },\n ]\n : [\n {\n branch: \"main\",\n description: [\n \"Main branch for OpenHI.\",\n \"This branch is used for the main branch.\",\n ],\n },\n ],\n });\n };\n\n get constructName(): string {\n return pascalCase([\"open\", \"hi\", this.id, \"service\"].join(\"-\"));\n }\n\n get outDir() {\n return [paramCase(this.openHi.id), paramCase(this.id)].join(sep);\n }\n\n get serviceName() {\n return [paramCase(this.openHi.id), paramCase(this.id)].join(\"-\");\n }\n}\n","import { existsSync, unlinkSync } from \"node:fs\";\nimport { sep } from \"node:path\";\nimport { SampleFile } from \"projen\";\nimport { OpenHiService } from \"../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/service-template.md\n */\n\nexport interface ServiceTemplateOptions {\n /**\n * The content of the sample file, as an array.\n */\n readonly contents: Array<string>;\n\n /**\n * The relative file path from the project root.\n */\n readonly filePath: string;\n\n /**\n * Overwrite this template file to it's original state?\n *\n * @default false\n */\n readonly overwrite?: boolean;\n}\n\nexport class ServiceTemplate {\n /**\n * The file being generated.\n */\n public file?: SampleFile;\n\n /**\n * Absolute Filepath, including the project path.\n */\n public fullFilePath: string;\n\n constructor(\n public service: OpenHiService,\n public options: ServiceTemplateOptions,\n ) {\n /**\n * Determine the full file path for this file.\n */\n this.fullFilePath = [\n this.service.project.outdir,\n this.options.filePath,\n ].join(sep);\n\n /**\n * Build the template file.\n */\n this.createTemplate();\n }\n\n protected createTemplate() {\n if (this.options.overwrite) {\n this.overwriteTemplate();\n }\n\n this.file = new SampleFile(this.service.project, this.options.filePath, {\n contents: this.options.contents.join(\"\\n\"),\n });\n }\n\n public overwriteTemplate() {\n /**\n * Delete file, if it exists.\n */\n if (existsSync(this.fullFilePath)) {\n unlinkSync(this.fullFilePath);\n }\n this.file = undefined;\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/app.md\n */\n\nexport class SrcApp extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/app.ts\",\n contents: [\n `import { OpenHiApp, ${service.constructName} } from \"@openhi/constructs\";`,\n `import { CONFIG } from \"./config\";`,\n ``,\n `const app = new OpenHiApp({ config: CONFIG });`,\n ``,\n `const stacks = app.environments.map((e) => {`,\n ` return new ${service.constructName}(e, { config: e.config });`,\n `});`,\n ``,\n `export { app, stacks };`,\n ``,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/app-test.md\n */\n\nexport class SrcAppTest extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/app.test.ts\",\n contents: [\n `import { Template } from \"aws-cdk-lib/assertions\";`,\n `import { Code, type CodeConfig } from \"aws-cdk-lib/aws-lambda\";`,\n `import { stacks } from \"./app\"`,\n ``,\n `/** Replace volatile CDK asset S3 keys/buckets with static values for snapshot stability. */`,\n `function normalizeTemplateForSnapshot(template: Record<string, unknown>): Record<string, unknown> {`,\n ` const staticBucket = \"mock-assets-bucket\";`,\n ` const staticKey = \"mock-asset-key.zip\";`,\n ` const json = JSON.stringify(template);`,\n ` const normalized = json`,\n ` .replace(/\"S3Key\":\\\\s*\"[^\"]+\\\\.zip\"/g, \\`\"S3Key\": \"\\${staticKey}\"\\`)`,\n ` .replace(/\"S3Bucket\":\\\\s*\"[^\"]+\"/g, \\`\"S3Bucket\": \"\\${staticBucket}\"\\`);`,\n ` return JSON.parse(normalized) as Record<string, unknown>;`,\n `}`,\n ``,\n `let fromAssetMock: jest.SpyInstance;`,\n ``,\n `beforeAll(() => {`,\n ` fromAssetMock = jest.spyOn(Code, \"fromAsset\").mockReturnValue({`,\n ` isInline: false,`,\n ` bind: (): CodeConfig => ({`,\n ` s3Location: {`,\n ` bucketName: \"mock-assets-bucket\",`,\n ` objectKey: \"mock-asset-key.zip\",`,\n ` },`,\n ` }),`,\n ` bindToResource: () => {`,\n ` return;`,\n ` },`,\n ` } as any);`,\n `});`,\n ``,\n `afterAll(() => {`,\n ` fromAssetMock?.mockRestore();`,\n `});`,\n ``,\n `describe(\"Smoke Test\", () => {`,\n ` it(\"should match previous snapshots\", () => {`,\n ` stacks.forEach((s) => {`,\n ` const template = Template.fromStack(s).toJSON();`,\n ` expect(normalizeTemplateForSnapshot(template)).toMatchSnapshot();`,\n ` });`,\n ` });`,\n `});`,\n ``,\n ],\n });\n }\n}\n","import { SourceCode } from \"projen\";\nimport { OpenHiService } from \"../../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/config.md\n */\n\nexport class SrcConfig extends SourceCode {\n constructor(service: OpenHiService) {\n super(service.project, \"src/config.ts\");\n\n /**\n * Imports\n */\n this.line(`import { OpenHiConfig } from \"@openhi/config\";`);\n this.line(\"\");\n\n /**\n * Write the config content\n */\n const start = \"export const CONFIG: OpenHiConfig = \";\n const mid = JSON.stringify(service.options?.config, null, 2);\n const end = \" as const;\";\n this.line(`${start}${mid}${end}`);\n }\n}\n","import { OpenHiService } from \"../../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/data/models/readme.md\n */\n\nexport class DataModelsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/data/models/README.md\",\n contents: [\n `# ${service.serviceName}: Data Models`,\n ``,\n `This directory contains data model definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/data/readme.md\n */\n\nexport class DataReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/data/README.md\",\n contents: [\n `# ${service.serviceName}: Data`,\n ``,\n `This directory contains data models and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/infrastructure/readme.md\n */\n\nexport class InfrastructureReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/infrastructure/README.md\",\n contents: [\n `# ${service.serviceName}: Infrastructure`,\n ``,\n `This directory contains infrastructure definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/integrations/readme.md\n */\n\nexport class IntegrationsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/integrations/README.md\",\n contents: [\n `# ${service.serviceName}: Integrations`,\n ``,\n `This directory contains integration definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/main.md\n */\n\nexport class SrcMain extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/main.ts\",\n contents: [`import { app } from \"./app\";`, ``, `app.synth();`, ``],\n });\n }\n}\n","import { OpenHiService } from \"../../service\";\nimport { ServiceTemplate, ServiceTemplateOptions } from \"../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/readme.md\n */\n\nexport class SrcReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/README.md\",\n contents: [\n `# ${service.serviceName}: Service Overview`,\n ``,\n `This directory contains the main entry point for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../../../service\";\nimport {\n ServiceTemplate,\n ServiceTemplateOptions,\n} from \"../../service-template\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/src/workflows/readme.md\n */\n\nexport class WorkflowsReadMe extends ServiceTemplate {\n constructor(\n service: OpenHiService,\n options?: Partial<ServiceTemplateOptions>,\n ) {\n super(service, {\n ...options,\n filePath: \"src/workflows/README.md\",\n contents: [\n `# ${service.serviceName}: Workflows`,\n ``,\n `This directory contains workflow definitions and other related files for the ${service.serviceName} service.`,\n ],\n });\n }\n}\n","import { OpenHiService } from \"../service\";\nimport { SrcApp } from \"./src/app\";\nimport { SrcAppTest } from \"./src/app-test\";\nimport { SrcConfig } from \"./src/config\";\nimport { DataModelsReadMe } from \"./src/data/models/README.md\";\nimport { DataReadMe } from \"./src/data/README.md\";\nimport { InfrastructureReadMe } from \"./src/infrastructure/README.md\";\nimport { IntegrationsReadMe } from \"./src/integrations/README.md\";\nimport { SrcMain } from \"./src/main\";\nimport { SrcReadMe } from \"./src/README.md\";\nimport { WorkflowsReadMe } from \"./src/workflows/README.md\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/templates/generate-templates.md\n */\n\nexport class GenerateTemplates {\n constructor(private service: OpenHiService) {\n /**\n * Root src templates\n */\n new SrcApp(this.service);\n new SrcAppTest(this.service);\n new SrcConfig(this.service);\n new SrcMain(this.service);\n new SrcReadMe(this.service);\n\n /**\n * Data\n */\n new DataReadMe(this.service);\n new DataModelsReadMe(this.service);\n\n /**\n * Infrastructure\n */\n new InfrastructureReadMe(this.service);\n\n /**\n * Integrations\n */\n new IntegrationsReadMe(this.service);\n\n /**\n * Workflows\n */\n new WorkflowsReadMe(this.service);\n }\n}\n","import {\n AwsDeploymentConfig,\n MonorepoProject,\n} from \"@codedrifters/configulator\";\nimport { OPEN_HI_STAGE } from \"@openhi/config\";\nimport { Component } from \"projen\";\nimport { GitHub, GithubWorkflow } from \"projen/lib/github\";\nimport { JobPermission } from \"projen/lib/github/workflows-model\";\nimport { OpenHi } from \"../openhi\";\nimport type { OpenHiService } from \"../service\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/aws-teardown-workflow.md\n */\n\nexport interface AwsTeardownWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class AwsTeardownWorkflow extends Component {\n constructor(\n public rootProject: MonorepoProject,\n options: AwsTeardownWorkflowOptions,\n ) {\n super(rootProject);\n\n const { openhi } = options;\n\n /***************************************************************************\n *\n * Root project check\n *\n * Detect the root project and ensure it's of type MonorepoProject.\n *\n **************************************************************************/\n\n if (!(rootProject instanceof MonorepoProject)) {\n throw new Error(\n \"AwsTeardownWorkflow requires the root project to be a MonorepoProject\",\n );\n }\n\n //this.rootProject = project.root;\n\n /***************************************************************************\n *\n * GitHub Check\n *\n * Make sure github config is active in the project. This is to ensure all\n * workflows will be output properly during synth.\n *\n **************************************************************************/\n\n const github = GitHub.of(this.rootProject);\n\n if (!github) {\n throw new Error(\n \"AwsTeardownWorkflow requires a GitHub component in the root project\",\n );\n }\n\n /***************************************************************************\n *\n * Workflow Destroy Targets\n *\n * Find all the CI targets for the Global project in the DEV stage\n * only. One job per (account, region) teardowns all orphan stacks (Auth,\n * Core, data) in that account/region.\n *\n **************************************************************************/\n\n const devTargetsFor = (service: OpenHiService) =>\n AwsDeploymentConfig.of(service.project)?.awsDeploymentTargets.filter(\n (target) =>\n target.awsStageType === OPEN_HI_STAGE.DEV && target.ciDeployment,\n ) ?? [];\n const awsDestructionTargets = devTargetsFor(openhi.global);\n\n /***************************************************************************\n *\n * Create Workflow\n *\n * Make a new workflow for AWS stack teardown. This runs each night and is\n * also triggered each time a branch is deleted.\n *\n **************************************************************************/\n\n const workflow = new GithubWorkflow(github, \"teardown-dev\");\n workflow.on({\n workflowDispatch: {},\n schedule: [\n {\n cron: \"32 6 * * *\", // Every Sunday at 6:32 AM UTC\n },\n ],\n delete: {\n branches: [\"feature/*\", \"feat/*\", \"fix/*\"],\n },\n /* for debugging \n push: {\n branches: [\"feature/*\"],\n },\n */\n });\n\n awsDestructionTargets.forEach((target) => {\n const {\n awsStageType,\n awsEnvironmentType,\n account,\n region,\n ciDeploymentConfig,\n } = target;\n const { roleArn } = ciDeploymentConfig ?? {};\n\n workflow.addJob(`teardown-${account}-${region}`.toLowerCase(), {\n name: `Teardown Stacks in ${target.account}/${target.region}`,\n //if: \"github.event.ref_type == 'branch'\",\n runsOn: [\"ubuntu-latest\"],\n permissions: {\n contents: JobPermission.READ,\n idToken: JobPermission.WRITE,\n },\n env: {\n REPO: \"${{ github.repository }}\",\n REGIONS: [region].join(\" \"),\n },\n steps: [\n /**\n * Configure AWS creds.\n */\n {\n name: `AWS Creds ${awsStageType}/${awsEnvironmentType}/${account}/${region}`,\n uses: \"aws-actions/configure-aws-credentials@v4\",\n with: {\n \"role-to-assume\": roleArn,\n \"aws-region\": region,\n \"role-duration-seconds\": 900, // 15 minutes\n },\n },\n\n /**\n * Fetch all branch names in the repo\n */\n {\n name: \"Fetch All Branches\",\n id: \"fetch_branches\",\n uses: \"actions/github-script@v7\",\n with: {\n script: [\n \"const all = await github.paginate(github.rest.repos.listBranches, {\",\n \" owner: context.repo.owner,\",\n \" repo: context.repo.repo,\",\n \" per_page: 100\",\n \"});\",\n \"const names = all.map(b => b.name);\",\n \"console.log(`Found branches: ${names}`);\",\n 'core.setOutput(\"json\", JSON.stringify(names));',\n ].join(\"\\n\"),\n },\n },\n\n /**\n * Save branches to a file\n */\n {\n name: \"Save Branches to File\",\n run: [\n 'echo \"Saving branches to file\"',\n \"echo '${{ steps.fetch_branches.outputs.json }}' | jq -r '.[]' | sort -u > branches.txt\",\n 'echo \"Branches:\"',\n \"cat branches.txt\",\n ].join(\"\\n\"),\n },\n\n /**\n * Find all stacks tagged with a stage of dev. for this repo. return\n * tag and resource arn.\n */\n {\n name: \"Find Stacks by Tag\",\n id: \"find_stacks\",\n run: [\n \"set -euo pipefail\",\n \": > candidates.txt # columns: arn region branchTag\",\n\n \"# Build tag filters\",\n 'TAG_FILTERS=( \"Key=openhi:repo-name,Values=$REPO\" )',\n `TAG_FILTERS+=( \"Key=openhi:stage-type,Values=${OPEN_HI_STAGE.DEV}\" )`,\n\n \"for r in $REGIONS; do\",\n ` echo \"Scanning region: $r\"`,\n \" aws resourcegroupstaggingapi get-resources \\\\\",\n ' --region \"$r\" \\\\',\n ' --resource-type-filters \"cloudformation:stack\" \\\\',\n ' --tag-filters \"${TAG_FILTERS[@]}\" \\\\',\n ` | jq -r --arg r \"$r\" '`,\n \" .ResourceTagMappingList[]\",\n \" | . as $res\",\n ' | ($res.Tags[] | select(.Key==\"openhi:branch-name\") | .Value) as $branch',\n ' | [$res.ResourceARN, $r, ($branch // \"\")]',\n \" | @tsv\",\n \" ' >> candidates.txt\",\n \"done\",\n\n \"echo 'Tagged stacks:'\",\n `(echo -e \"ARN\\\\tREGION\\\\tBRANCH\"; cat candidates.txt) | column -t -s $'\\\\t'`,\n ].join(\"\\n\"),\n },\n\n /**\n * Determine which stacks are orphans that no longer have a matching branch.\n * Save those to a file for the next step.\n */\n {\n name: \"Determine Orphan Stacks (No Matching Branch)\",\n run: [\n \"set -euo pipefail\",\n \": > orphans.txt # arn region branch\",\n \"while IFS=$'\\\\t' read -r arn region branch; do\",\n ' [ -z \"$arn\" ] && continue',\n ' if [ -z \"$branch\" ]; then',\n \" # If no Branch tag, treat as not-a-preview; skip (or flip to delete if you want)\",\n \" continue\",\n \" fi\",\n ' if ! grep -Fxq \"$branch\" branches.txt; then',\n ' echo -e \"$arn\\\\t$region\\\\t$branch\" >> orphans.txt',\n \" fi\",\n \"done < candidates.txt\",\n \"\",\n \"if [ -s orphans.txt ]; then\",\n ' echo \"Orphan stacks (no matching branch):\"',\n \" (echo -e \\\"ARN\\\\tREGION\\\\tBRANCH\\\"; cat orphans.txt) | column -t -s $'\\\\t'\",\n \"else\",\n ' echo \"No orphan stacks found.\"',\n \"fi\",\n ].join(\"\\n\"),\n },\n\n /**\n * Delete orphan stacks.\n */\n {\n name: \"Delete Orphan Stacks\",\n if: \"hashFiles('orphans.txt') != ''\",\n run: [\n \"set -euo pipefail\",\n \"while IFS=$'\\\\t' read -r arn region branch; do\",\n ' [ -z \"$arn\" ] && continue',\n \" stack_name=$(cut -d'/' -f2 <<<\\\"$arn\\\")\",\n ' echo \"Deleting $stack_name (branch=$branch) in $region\"',\n ' aws cloudformation delete-stack --region \"$region\" --stack-name \"$stack_name\" || true',\n \"done < orphans.txt\",\n ].join(\"\\n\"),\n },\n ],\n });\n });\n }\n}\n","import { AwsDeployWorkflow, MonorepoProject } from \"@codedrifters/configulator\";\nimport { Component } from \"projen\";\nimport { OpenHi } from \"../openhi\";\n\n/**\n * Job-level `if:` condition that restricts the per-PR website deploy to\n * pull-request events plus manual dispatch. Push events to feat/fix/feature\n * branches no longer trigger a website deploy because the OPENHI_PR_NUMBER\n * env var is only resolvable when a PR exists.\n */\nconst PR_GATED_WEBSITE_JOB_IF =\n \"${{ !needs.build.outputs.self_mutation_happened && \" +\n \"(github.event_name == 'pull_request' || \" +\n \"github.event_name == 'workflow_dispatch') }}\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/build-dev-workflow.md\n */\n\nexport interface BuildDevelopmentWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class BuildDevelopmentWorkflow extends Component {\n constructor(\n parent: MonorepoProject,\n options: BuildDevelopmentWorkflowOptions,\n ) {\n super(parent, \"dev-workflow\");\n\n const { openhi } = options;\n\n /**\n * Global Service Deploy\n *\n * Deploy the Global service first to configure DNS\n */\n const { awsDeploymentTargets: globalTargets } = new AwsDeployWorkflow(\n openhi.global.project,\n {\n buildWorkflow: parent.buildWorkflow,\n },\n );\n\n /**\n * Auth Service Deploy\n *\n * Deploy the Auth service first (Cognito); data service and other stacks consume auth via SSM.\n */\n const { awsDeploymentTargets: authTargets } = new AwsDeployWorkflow(\n openhi.auth.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets],\n },\n );\n\n /**\n * Data Service Deploy\n *\n * Deploy the Data service (DynamoDB FHIR store, S3) after Global.\n */\n const { awsDeploymentTargets: dataTargets } = new AwsDeployWorkflow(\n openhi.data.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets],\n },\n );\n\n /**\n * Rest API Service Deploy\n *\n * Deploy the Rest API service after Data (and Global).\n */\n const { awsDeploymentTargets: restApiTargets } = new AwsDeployWorkflow(\n openhi.restApi.project,\n {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n },\n );\n\n /**\n * GraphQL API Service Deploy\n *\n * Deploy the GraphQL API service after Data (sibling to REST API).\n */\n new AwsDeployWorkflow(openhi.graphApi.project, {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n });\n\n /**\n * Website Service Deploy\n *\n * Deploy the Website service after Global and REST API. The website\n * stack's CloudFront distribution fronts the REST API via an\n * `/api/*` behavior whose origin host is resolved at CFN update time\n * from the `REST_API_DOMAIN_NAME` SSM parameter — that parameter is\n * written by the matching branch's rest-api stack, so rest-api must\n * deploy first. The Global dependency holds for the child hosted zone\n * and wildcard certificate. Auth no longer needs to be upstream — the\n * Cognito IDs are exposed via the REST API's runtime-config endpoint\n * at request time, not via CFN dynamic references at update time.\n */\n const websiteDeploy = new AwsDeployWorkflow(openhi.website.project, {\n buildWorkflow: parent.buildWorkflow,\n deployAfterTargets: [...globalTargets, ...restApiTargets],\n });\n\n /**\n * Per-PR preview wiring for the website deploy:\n *\n * 1. Trigger the build workflow on PR events so feature-branch deploys\n * have a PR number to address themselves with\n * (`admin-pr-<N>.<zone>`).\n * 2. Inject `OPENHI_PR_NUMBER` at the workflow env level so\n * `OpenHiWebsiteService` resolves it via the same fallback path it\n * uses for the `prNumber` prop.\n * 3. Gate every `*-deploy-openhi-website-*` job to `pull_request` +\n * `workflow_dispatch` only — push-to-branch no longer triggers a\n * website deploy (a website deploy requires a PR for its hostname).\n * Other services' deploy jobs are unchanged.\n */\n const buildWorkflow = parent.buildWorkflow;\n if (!buildWorkflow) {\n throw new Error(\"BuildDevelopmentWorkflow requires a buildWorkflow\");\n }\n const ghWorkflow = buildWorkflow.workflow;\n ghWorkflow.on({\n pullRequest: {\n types: [\"opened\", \"synchronize\", \"reopened\"],\n },\n });\n ghWorkflow.file?.addOverride(\n \"env.OPENHI_PR_NUMBER\",\n \"${{ github.event.pull_request.number || '' }}\",\n );\n websiteDeploy.awsDeploymentTargets.forEach((target) => {\n const jobId = [\n target.awsStageType,\n target.deploymentTargetRole,\n \"deploy\",\n target.project.name,\n target.account,\n target.region,\n ].join(\"-\");\n const job = ghWorkflow.getJob(jobId);\n ghWorkflow.updateJob(jobId, {\n ...job,\n if: PR_GATED_WEBSITE_JOB_IF,\n });\n });\n }\n}\n","import { AwsDeployWorkflow, MonorepoProject } from \"@codedrifters/configulator\";\nimport { OPEN_HI_STAGE } from \"@openhi/config\";\nimport { Component } from \"projen\";\nimport { OpenHi } from \"../openhi\";\n\n/**\n * @see sites/www-docs/content/packages/@openhi/platform/workflows/build-stage-workflow.md\n */\n\nexport interface BuildStageWorkflowOptions {\n /**\n * openhi project\n */\n readonly openhi: OpenHi;\n}\n\nexport class BuildStageWorkflow extends Component {\n constructor(parent: MonorepoProject, options: BuildStageWorkflowOptions) {\n super(parent, \"stage-workflow\");\n\n const { openhi } = options;\n\n /**\n * Global Service Deploy\n *\n * Deploy the Global service first to configure DNS\n */\n const { awsDeploymentTargets: globalTargets, buildWorkflow } =\n new AwsDeployWorkflow(openhi.global.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflowOptions: {\n name: \"deploy-stage\",\n workflowTriggers: {\n push: {\n branches: [\"main\"],\n },\n workflowDispatch: {},\n },\n },\n });\n\n // Inject OPENHI_PR_NUMBER at the workflow env level so it propagates\n // to every job (including the website deploy job). Release-branch\n // deploys ignore this value (no PR exists on a main push); the env is\n // included so OpenHiWebsiteService resolves consistently across\n // workflows. See BuildDevelopmentWorkflow for the PR-event wiring on\n // the dev side.\n buildWorkflow.workflow.file?.addOverride(\n \"env.OPENHI_PR_NUMBER\",\n \"${{ github.event.pull_request.number || '' }}\",\n );\n\n /**\n * Auth Service Deploy\n *\n * Deploy the Auth service first (Cognito); data service and other stacks consume auth via SSM.\n * Auth creates the stage build workflow; data service and REST API services add to it.\n */\n const { awsDeploymentTargets: authTargets } = new AwsDeployWorkflow(\n openhi.auth.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets],\n },\n );\n\n /**\n * Data Service Deploy\n *\n * Deploy the Data service (DynamoDB FHIR store, S3) after Global.\n */\n const { awsDeploymentTargets: dataTargets } = new AwsDeployWorkflow(\n openhi.data.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets],\n },\n );\n\n /**\n * Rest API Service Deploy\n */\n const { awsDeploymentTargets: restApiTargets } = new AwsDeployWorkflow(\n openhi.restApi.project,\n {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n },\n );\n\n /**\n * GraphQL API Service Deploy\n */\n new AwsDeployWorkflow(openhi.graphApi.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...authTargets, ...dataTargets],\n });\n\n /**\n * Website Service Deploy\n *\n * Deploy the Website service after Global and REST API. The website\n * stack's CloudFront distribution fronts the REST API via an\n * `/api/*` behavior whose origin host is resolved at CFN update time\n * from the `REST_API_DOMAIN_NAME` SSM parameter — that parameter is\n * written by the matching branch's rest-api stack, so rest-api must\n * deploy first. The Global dependency holds for the child hosted zone\n * and wildcard certificate. Auth no longer needs to be upstream — the\n * Cognito IDs are exposed via the REST API's runtime-config endpoint\n * at request time, not via CFN dynamic references at update time.\n */\n new AwsDeployWorkflow(openhi.website.project, {\n awsStageType: OPEN_HI_STAGE.STAGE,\n buildWorkflow,\n deployAfterTargets: [...globalTargets, ...restApiTargets],\n });\n }\n}\n"],"mappings":"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","names":["import_config","sep","sep","import_config","Component","import_config","AwsDeployWorkflow","Component"]}
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"@swc/core": "^1.15.33",
|
|
6
6
|
"@swc/jest": "^0.2.39",
|
|
7
7
|
"@types/jest": "^30.0.0",
|
|
8
|
-
"@types/node": "25.
|
|
8
|
+
"@types/node": "25.8.0",
|
|
9
9
|
"@typescript-eslint/eslint-plugin": "^8",
|
|
10
10
|
"@typescript-eslint/parser": "^8",
|
|
11
11
|
"commit-and-tag-version": "^12",
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
"typescript": "^5.9.3"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@codedrifters/configulator": "0.0.
|
|
28
|
+
"@codedrifters/configulator": "0.0.317",
|
|
29
29
|
"change-case": "^4",
|
|
30
30
|
"constructs": "10.6.0",
|
|
31
|
-
"projen": "0.99.
|
|
31
|
+
"projen": "0.99.61",
|
|
32
32
|
"ts-deepmerge": "7.0.3",
|
|
33
33
|
"type-fest": "^4",
|
|
34
34
|
"@openhi/config": "0.0.0"
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"devEngines": {
|
|
37
37
|
"packageManager": {
|
|
38
38
|
"name": "pnpm",
|
|
39
|
-
"version": "11.1.
|
|
39
|
+
"version": "11.1.2",
|
|
40
40
|
"onFail": "ignore"
|
|
41
41
|
}
|
|
42
42
|
},
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
|
-
"version": "0.0.
|
|
48
|
+
"version": "0.0.42",
|
|
49
49
|
"types": "lib/index.d.ts",
|
|
50
50
|
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"pnpm exec projen\".",
|
|
51
51
|
"scripts": {
|