{"id":35832990,"url":"https://github.com/bcgov/reserve-rec-api","last_synced_at":"2026-06-26T00:00:56.769Z","repository":{"id":244132057,"uuid":"813799272","full_name":"bcgov/reserve-rec-api","owner":"bcgov","description":"For the Parks and Recreation Digital Transformation project.","archived":false,"fork":false,"pushed_at":"2026-06-17T21:33:51.000Z","size":5034,"stargazers_count":1,"open_issues_count":27,"forks_count":7,"subscribers_count":3,"default_branch":"main","last_synced_at":"2026-06-17T23:20:25.008Z","etag":null,"topics":["aws","aws-lambda","dds","dyanmodb","env","moe","nodejs","nr","nrm"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bcgov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-06-11T19:06:44.000Z","updated_at":"2026-06-17T21:33:54.000Z","dependencies_parsed_at":"2026-05-15T00:04:05.643Z","dependency_job_id":null,"html_url":"https://github.com/bcgov/reserve-rec-api","commit_stats":null,"previous_names":["bcgov/reserve-rec-api"],"tags_count":123,"template":false,"template_full_name":null,"purl":"pkg:github/bcgov/reserve-rec-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Freserve-rec-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Freserve-rec-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Freserve-rec-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Freserve-rec-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bcgov","download_url":"https://codeload.github.com/bcgov/reserve-rec-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Freserve-rec-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34796761,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-25T02:00:05.521Z","response_time":101,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws","aws-lambda","dds","dyanmodb","env","moe","nodejs","nr","nrm"],"created_at":"2026-01-07T23:19:23.519Z","updated_at":"2026-06-26T00:00:56.236Z","avatar_url":"https://github.com/bcgov.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Reserve Recreation API\n\nA comprehensive AWS CDK-based infrastructure project for managing park and recreation facility reservations. This system provides secure, scalable APIs for both administrative management and public booking functionality.\n\n## Quick Start\n\n\n### Installation \u0026 Setup\n\n1. **Clone and install dependencies**:\n  ```bash\n  git clone \u003crepository-url\u003e\n  cd reserve-rec-api\n  yarn install\n  ```\n\n2. **Configure AWS credentials**:\n  ```bash\n  aws configure\n  # Bootstrap CDK (first time only)\n  cdk bootstrap\n  ```\n\n3. **Deploy to development environment**:\n  ```bash\n  yarn deploy:dev\n  ```\n\n### Local Development\n\nFor local testing and development:\n\n```bash\n# Start local admin API\nyarn run:admin:full\n\n# Start local public API\nyarn run:public:full\n```\n\n### Key Sections\n\n- **[🏗️ Architecture Overview](#️-architecture-overview)** - System design and stack relationships\n- **[📚 Stack Descriptions](#-stack-descriptions)** - Detailed breakdown of each infrastructure component\n- **[🛠️ Development Setup](#️-development-setup)** - Environment configuration and prerequisites\n- **[🚀 Deployment](#-deployment)** - Local and remote deployment instructions\n- **[🔒 Security Considerations](#-security-considerations)** - Authentication, authorization, and data protection\n- **[🐛 Troubleshooting](#-troubleshooting)** - Common issues and debugging tips\n\n\n## 🏗️ Architecture Overview\n\nThis project uses AWS Cloud Development Kit (CDK) to define infrastructure as code, consisting of a number of  interconnected stacks that provide a complete reservation management system:\n\n```\n┌─────────────────┐    ┌───────────────────┐    ┌─────────────────┐\n│   Core Stack    │    │  Identity Stacks  │    │ OpenSearch Stack│\n│                 │    │                   │    │                 │\n│ • KMS Keys      │    │ • Admin Cognito   │    │ • Search Service│\n│ • Lambda Layers │────│ • Public Cognito  │────│ • Fine-grained  │\n│ • IAM Roles     │    │ • User Pools      │    │   Access Control│\n└─────────────────┘    └───────────────────┘    └─────────────────┘\n         │                       │                       │\n         │                       │                       │\n         ▼                       ▼                       ▼\n┌─────────────────┐    ┌───────────────────┐    ┌─────────────────┐\n│  Data Stacks    │    │   API Stacks      │    │  Future Stacks  │\n│                 │    │                   │    │                 │\n│ • Reference     │────│ • Admin API       │────│                 │\n│   Data (DDB)    │    │ • Public API      │    │                 │\n│ • Transactional │    │ • REST Endpoints  │    │                 │\n│   Data (DDB)    │    │ • Lambda Functions│    │                 │\n└─────────────────┘    └───────────────────┘    └─────────────────┘\n```\n\n## 📚 Stack Descriptions\n\n### 🔧 Core Stack (`coreStack`)\n**Foundation services and shared resources**\n- **KMS Keys**: Encryption for data at rest and in transit\n- **Lambda Layers**: Shared code and dependencies (Base Layer, AWS Utils Layer)\n- **API Gateway Logging**: Centralized API request/response logging\n- **IAM Roles**: Cross-stack service permissions\n\n### 🔐 Identity Stacks\n**Authentication and authorization services**\n\n#### Admin Identity Stack (`adminIdentityStack`)\n- **Admin User Pool**: Cognito user pool for administrative users\n- **Admin Identity Pool**: Identity pool for administrative users (Azure Login, BCSC Login)\n- **Admin Groups**: Role-based access control (park managers, system admins)\n\n#### Public Identity Stack (`publicIdentityStack`)\n- **Public User Pool**: Cognito user pool for public users\n- **Self-registration**: Email verification and password policies\n- **Guest Access**: Limited functionality for non-registered users\n\n### 🔍 OpenSearch Stack (`openSearchStack`)\n**Search and analytics engine**\n- **OpenSearch Domain**: Managed search service with fine-grained access control\n- **Security**: IAM and FGAC integration with Cognito identity providers\n- **Initialization Lambda**: Automated domain setup and index templates\n\n### 💾 Data Stacks\n**Persistent data storage and management**\n\n#### Reference Data Stack (`referenceDataStack`)\n- **DynamoDB Tables**: Park information, geozones, facilities, activities, products, policies, and other quasi-static configurations\n- **Reference Data Streaming**: To synchronize OpenSearch `reference-data` indexes.\n- **Audit Table**: For recording changes to static data\n- **PubSub Table**: For webhook subscriptions\n\n#### Transactional Data Stack (`transactionalDataStack`)\n- **DynamoDB Tables**: Reservations, bookings, payments, and user activity\n- **Transactional Data Streaming**: To synchronize OpenSearch `transactional-data` indexes.\n\n### 🚀 API Stacks\n**REST API endpoints and business logic**\n\n#### Admin API Stack (`adminApiStack`)\n- **Nested Stack Architecture**: The stack is decomposed into a hub-and-spoke model. `AdminApiCoreNestedStack` owns the API Gateway and Authorizer; all domain areas (geozones, facilities, activities, products, users, bookings, verify, reports, etc.) are provisioned in their own nested stacks to stay well under CloudFormation's 500-resource-per-stack limit.\n- **Data Management Endpoints**: Park administration, user management, reporting\n- **Lambda Functions**: Business logic for administrative operations\n- **API Gateway**: RESTful endpoints with request validation. The `RestApi` is created with `deploy: false`; the root stack owns the `Deployment` and `Stage` resources and declares explicit dependencies on every domain nested stack to ensure correct redeployment ordering.\n- **Authorization**: Integration with admin Cognito user pool, provided by `AdminApiCoreNestedStack` and shared with domain stacks via authorizer reference.\n- **Feature Flags**: Each domain area can be selectively enabled or disabled at synth time via `ENABLE_*` environment variables (see [Environment Configuration](#environment-configuration)).\n- **Local vs. AWS deployment**: When running locally (`@context=local`), SAM-incompatible nested stacks are replaced with flat constructs for each domain area.\n\n#### Public API Stack (`publicApiStack`)\n- **Booking Endpoints**: Facility search, availability, reservation creation\n- **Lambda Functions**: Public-facing business logic\n- **Search Endpoints**: Public facing search logic\n\n## 🛠️ Development Setup\n\n### Prerequisites\n\n- **Node.js**: Version 20 or higher\n- **AWS CLI**: Version 2.x configured with appropriate credentials\n- **AWS CDK**: Version 2.x\n\n### Environment Configuration\n\nThe project supports multiple deployment environments configured via `cdk.json`:\n\n```json\n{\n  \"context\": {\n    \"dev\": {\n      \"DEPLOYMENT_NAME\": \"dev\",\n      \"AWS_REGION\": \"ca-central-1\",\n      \"IS_OFFLINE\": \"false\",\n      \"FAIL_FAST\": \"false\"\n    },\n    \"test\": {\n      \"DEPLOYMENT_NAME\": \"test\",\n      \"AWS_REGION\": \"ca-central-1\",\n      \"IS_OFFLINE\": \"false\",\n      \"FAIL_FAST\": \"false\"\n    },\n    \"prod\": {\n      \"DEPLOYMENT_NAME\": \"prod\",\n      \"AWS_REGION\": \"ca-central-1\",\n      \"IS_OFFLINE\": \"false\",\n      \"FAIL_FAST\": \"false\"\n    },\n    \"local\": {\n      \"DEPLOYMENT_NAME\": \"local\",\n      \"AWS_REGION\": \"ca-central-1\",\n      \"IS_OFFLINE\": \"true\",\n      \"FAIL_FAST\": \"false\"\n    }\n  }\n}\n```\n\n- **DEPLOYMENT_NAME**: the name of the deployment (often the environment name)\n- **AWS_REGION**: AWS region to deploy the app into (almost always `ca-central-1`)\n- **IS_OFFLINE**: If `\"true\"`, the synthesizing/deployment operations will not attempt to connect to remote AWS servers for context/configuration variables (if synthesizing locally for example).\n- **FAIL_FAST**: Abort synthesis of downstream stacks if an error occurs (useful for prototyping)\n\n#### Admin API Feature Flags\n\nEach domain area of the Admin API stack can be selectively enabled or disabled at synth/deploy time using environment variables. All flags default to `true` (enabled) unless explicitly set to `\"false\"`.\n\n| Environment Variable | Domain Area |\n|---|---|\n| `ENABLE_PING` | Ping / health-check endpoint |\n| `ENABLE_BCSC` | BC Services Card (BCSC) login endpoints |\n| `ENABLE_CONFIG` | Admin config getters |\n| `ENABLE_SEARCH` | OpenSearch-backed admin search |\n| `ENABLE_GEOZONES` | Geozone management |\n| `ENABLE_FACILITIES` | Facility management |\n| `ENABLE_ACTIVITIES` | Activity management |\n| `ENABLE_PRODUCTS` | Product management |\n| `ENABLE_POLICIES` | Policy management |\n| `ENABLE_REPORTS` | Reporting (daily passes, etc.) |\n| `ENABLE_RELATIONSHIPS` | Entity relationship management |\n| `ENABLE_FEATURE_FLAGS` | Feature flag management |\n| `ENABLE_USERS` | User management |\n| `ENABLE_BOOKINGS` | Booking management |\n| `ENABLE_VERIFY` | QR code verification |\n| `ENABLE_PRODUCT_MANAGEMENT` | Product dates and management |\n\nExample — deploy without search or reports:\n```bash\nENABLE_SEARCH=false ENABLE_REPORTS=false yarn deploy:dev\n```\n\n### Resource Naming Convention\n\nThe StackPrimer class enforces a consistent naming convention across all AWS resources to ensure uniqueness, traceability, and proper organization. This convention follows the pattern:\n\n```\n{AppName}-{DeploymentName}-{StackName}-{ResourceName}\n```\n\n#### Naming Components\n\n- **AppName**: The application identifier (e.g., `ReserveRecApi`)\n- **DeploymentName**: The environment or deployment instance (e.g., `Dev`, `Test`, `Prod`)\n- **StackName**: The name of the relevant stack (e.g., `CoreStack`, `AdminApiStack`, `ReferenceDataStack`)\n- **ResourceName**: The specific resource identifier within the stack\n\n#### Examples\n\n```javascript\n// Lambda function in the Admin API stack\nReserveRecApi-Dev-AdminApiStack-UserManagementFunction\n\n// DynamoDB table in the Reference Data stack\nReserveRecApi-Dev-ReferenceDataStack-ReferenceDataTable\n\n// KMS key in the Core stack\nReserveRecApi-Test-CoreStack-DatabaseEncryptionKey\n\n// Cognito User Pool in the Admin Identity stack\nReserveRecApi-Test-AdminIdentityStack-AdminUserPool\n```\n\n### Stack Dependencies\n\nThe system automatically manages stack dependencies. Deployment order is important, as the resources produced in some stacks are consumed by others. The current deployment order is:\n\n1. CoreStack\n2. AdminIndentityStack\n3. PublicIdentityStack\n4. OpenSearchStack\n5. ReferenceDataStack\n6. TransactionalDataStack\n7. AdminApiStack\n8. PublicApiStack\n\n### Installation\n\n1. **Clone the repository**:\n   ```bash\n   git clone \u003crepository-url\u003e\n   cd reserve-rec-api\n   ```\n\n2. **Install dependencies**:\n   ```bash\n   yarn\n   ```\n\n3. **Configure AWS credentials**:\n   ```bash\n   aws configure\n   ```\n\n4. **Bootstrap CDK (first time only)**:\n   ```bash\n    cdk bootstrap\n   ```\n\n## 🚀 Deployment\n\n### Configuration Management\n\n#### Environment-Specific Configuration\n- **Context Resolution**: Environment settings loaded from `cdk.json`\n- **SSM Parameter Store**: Runtime configuration stored in AWS Systems Manager\n- **Secrets Manager**: Sensitive data stored securely in AWS Secrets Manager\n- **Local Development**: Configuration loaded from `/src/scripts/tools/local-testing/sam-config.json` for offline testing\n\n### Local Development\n\nThis application is optimized for deployment of multiple stacks into a remote AWS environment. Local deployment is possible, but not fully supported yet.\n\nLocal deployment uses AWS SAM to generate a local API for testing at `http://localhost:3000`. This necessitates a SAM template with which to generate the API.\n\nCDK synth/deploy operations do not generate a SAM template, so a script has been written to extract the appropriate resources from the generated CDK templates and create a SAM template from them.\n\nIn an effort to reduce the amount of Docker containers used in local development (an issue that tends impedes rapid prototyping by slowing down repeated deployments), the construction of Lambda Layer `dists` that would otherwise occur as part of a local SAM API deployment has been extracted from the process. Lambda Layer construction can now occur separately from local SAM API deployment and only needs to be rerun if the contents of the layers change.\n\nAdditionally, this application now has multiple APIs, so each must be generated and deployed separately from one another. As of now there are two APIs:\n\n* admin\n* public\n\nVariables that can be configured for local enviroment development are stored in `/src/scripts/tooling/local-testing/sam-config.json`.\n\nFor local development and testing:\n\n```bash\n# Synthesize CloudFormation templates locally\nyarn synth:local\n\n# Build Lambda layers for local testing\nyarn build:layers\n\n# Run script to generate SAM template from generated CDK templates\nyarn build:\u003capi\u003e (admin or public)\n\n# Start local API for admin functions\nyarn run:\u003capi\u003e (admin or public)\n\n# Do all the above in one step\nyarn run:\u003capi\u003e:full (admin or public)\n\n```\n\n### Remote Environment Deployments\n\nWhen deploying to a remote environment, it is important to ensure that the configuration variables for each stack are readily available in the remote AWS Parameter Store and Secrets Manager.\n\nAs per the [naming convention](#resource-naming-convention) of resources, each stack should have a `config` variable in Parameter Store that follows the pattern:\n\n```\n/{AppName}/{DeploymentName}/{StackName}/config\n```\nExample of the config parameter for CoreStack in the `dev` environment:\n```\n/reserveRecApi/dev/coreStack/config\n```\n\nRefer to the `defaults` variable in each stack instantiation file for the default structure of the stack's `config` parameter.\n\n\nDeploy to specific environments:\n\n```bash\n# Development environment\nyarn synth:dev (optional)\nyarn deploy:dev\n\n# Test environment\nyarn synth:test (optional)\nyarn deploy:test\n\n# Prior to deployment, the log level can be set to inspect the deployment process\nexport LOG_LEVEL=debug\n```\n\n### 🧪 Sandbox Environments\n\nSandbox environments allow developers to deploy fully isolated personal environments for testing. Each sandbox is completely independent from dev/test/prod and other sandboxes.\n\n#### Prerequisites\n\n- AWS CLI configured with appropriate credentials\n- CDK bootstrapped in target account\n- Access to copy SSM parameters and Secrets Manager secrets\n\n#### Quick Start\n\n```bash\n# 1. Setup - copies config and secrets from dev\n./scripts/sandbox-setup.sh \u003cyour-name\u003e   # e.g., ./scripts/sandbox-setup.sh mark\n\n# 2. Deploy all stacks\nSANDBOX_NAME=\u003cyour-name\u003e yarn sandbox:deploy\n\n# 3. Teardown when done (destroys all resources)\n./scripts/sandbox-teardown.sh \u003cyour-name\u003e\n```\n\n#### Available Scripts\n\n| Script | Description |\n|--------|-------------|\n| `./scripts/sandbox-setup.sh \u003cname\u003e [base-env]` | Copy SSM configs and secrets from base environment (default: dev) |\n| `./scripts/sandbox-teardown.sh \u003cname\u003e` | Destroy CDK stacks, delete SSM params and secrets |\n| `./scripts/sandbox-edit-config.sh \u003cname\u003e \u003cstack\u003e` | Edit a specific stack's config via $EDITOR |\n| `yarn sandbox:synth` | CDK synth with SANDBOX_NAME env var |\n| `yarn sandbox:deploy` | CDK deploy with SANDBOX_NAME env var |\n| `yarn sandbox:destroy` | CDK destroy with SANDBOX_NAME env var |\n\n#### Resource Naming\n\nSandbox resources follow the pattern: `{AppName}-{BaseEnv}-{SandboxName}-{StackName}`\n\nExample with `sandboxName=mark` on `dev`:\n- Stack: `ReserveRecApi-Dev-Mark-CoreStack`\n- DynamoDB: `ReserveRecApi-Dev-Mark-ReferenceDataStack-ReferenceDataTable`\n- SSM Paths: `/reserveRecApi/dev-mark/coreStack/config`\n\n#### Full Stack Deployment\n\nTo deploy a complete sandbox environment across all three repositories:\n\n```bash\n# Setup (run once per sandbox)\ncd reserve-rec-api \u0026\u0026 ./scripts/sandbox-setup.sh \u003cname\u003e\ncd ../reserve-rec-admin \u0026\u0026 ./scripts/sandbox-setup.sh \u003cname\u003e\ncd ../reserve-rec-public \u0026\u0026 ./scripts/sandbox-setup.sh \u003cname\u003e\n\n# Deploy (API must be deployed first)\ncd reserve-rec-api \u0026\u0026 SANDBOX_NAME=\u003cname\u003e yarn sandbox:deploy\ncd ../reserve-rec-admin \u0026\u0026 SANDBOX_NAME=\u003cname\u003e yarn sandbox:deploy\ncd ../reserve-rec-public \u0026\u0026 SANDBOX_NAME=\u003cname\u003e yarn sandbox:deploy\n\n# Teardown\ncd reserve-rec-api \u0026\u0026 ./scripts/sandbox-teardown.sh \u003cname\u003e\ncd ../reserve-rec-admin \u0026\u0026 ./scripts/sandbox-teardown.sh \u003cname\u003e\ncd ../reserve-rec-public \u0026\u0026 ./scripts/sandbox-teardown.sh \u003cname\u003e\n```\n\n#### Cost Considerations\n\nEach sandbox creates dedicated AWS resources including:\n- OpenSearch domain (~$80-100/month idle)\n- DynamoDB tables\n- Lambda functions\n- Cognito user pools\n- CloudFront distributions\n\n**Important:** Always teardown sandboxes when not in use to avoid unnecessary costs.\n\n#### Customizing Configuration\n\nAfter setup, you can customize stack configs before deploying:\n\n```bash\n# Edit a specific stack's config\n./scripts/sandbox-edit-config.sh \u003cname\u003e coreStack\n\n# Or manually edit the SSM parameter\naws ssm get-parameter --name \"/reserveRecApi/dev-\u003cname\u003e/coreStack/config\" --query \"Parameter.Value\" --output text | jq .\n```\n\n\n## 🏗️ CDKProject Architecture\n\n### Core Classes\n\n#### CDKProject Class\nThe main orchestrator that manages the entire deployment lifecycle:\n\n```javascript\nclass CDKProject {\n  // Application configuration\n  getAppName()           // Returns \"ReserveRecApi\"\n  getDeploymentName()    // Returns environment (dev/test/prod)\n  getRegion()           // Returns AWS region\n  isOffline()           // Checks if deploying offline\n}\n```\n\n#### StackPrimer Class\nHandles stack initialization and configuration resolution:\n\n```javascript\nclass StackPrimer {\n  // Stack setup\n  prime()              // Initializes stack configuration\n  nameConstructs()     // Generates CDK construct identifiers\n  getDeploymentConfig() // Loads environment-specific settings\n  getSecrets()         // Resolves AWS Secrets Manager values\n}\n```\n\n#### BaseStack Class\nCommon functionality for all stacks:\n\n```javascript\nclass BaseStack extends Stack {\n  // Resource management\n  createScopedId()     // Generates unique resource identifiers\n  getConstructId()     // Gets the identifier of a construct\n}\n```\n\n### Creating a Stack\n\nEach stack has the the following structure:\n\n* defaults\n* stack definition (extends BaseStack)\n* stack creation function\n\n#### Defaults\n\nEach stack declares default values for any variables or resources that it will create. The `defaults` variable at the head of each stack file has the following structure:\n\n```javascript\nconst defaults = {\n  constructs: {\n    constructName: {\n      name: 'ConstructName'\n    }\n  }\n  config: {\n    configVariable: \"configValue\"\n  }\n  secrets: {\n    secretName: {\n      name: 'SecretName'\n    }\n  }\n}\n```\n* `constructs` contains a list of every construct/resource that the stack declares. To follow the same naming convention across deployments, construct names are standardized. To reference the standardized construct name, use `this.getConstructId('constructName'). For example:\n\n```javascript\nconst defaults = {\n  constructs: {\n    tableName: {\n      name: 'DynamoDBTableName'\n    }\n  }\n}\n\nclass TableStack extends BaseStack {\n  // ...\n\n  const table = new dynamodb.Table(\n    this,\n    this.getConstructId('tableName'),\n    { props }\n  )\n}\n\n// Resulting table construct name:\n// reserveRecApi/env/tableStack/dynamoDBTableName\n```\n\n* `config` contains a copy of the configuration file found in the [SSM config parameter](#remote-environment-deployments) for that stack. Values required by the stack but not provided in SSM will assume the `defaults.config` value via JS object merge. To reference config values in the stack, use `this.getConfigValue('configVariable'). For example:\n\n```javascript\nconst defaults = {\n  config: {\n    defaultTimezone: 'America/Vancouver',\n    overrides: {\n      importedDynamoDBTableName: 'DynamoDBTable'\n    }\n  }\n}\n\nclass TableStack extends BaseStack {\n  // ...\n\n  const tz = this.getConfigValue('defaultTimezome');\n\n  const importedTableName = this.getConfigValue('overrides')?.importedDynamoDBTableName;\n\n  if (importedTableName) {\n    // use imported table reference\n    this.table = dynamodb.Table.fromTableName(this, `${this.getConstructId('tableName')}-Imported`, importedTableName);\n  } else {\n    // initialize new DynamoDBTable\n  }\n\n  // Resulting table construct name:\n  // reserveRecApi/env/tableStack/dynamoDBTableName-Imported\n\n}\n```\n\n* `secrets` contains a list of secret names that the stack will look for in the remote AWS Secrets Manager. Secret names follow the same [naming convention](#naming-components) as components. To reference secret values in a stack, use `this.getSecretValue('secretName')`. For example:\n\n```javascript\nconst defaults: {\n  secrets: {\n    osPassword: {\n      name: 'OpenSearchMasterUserPassword'\n    }\n  }\n}\n\nclass OpenSearchStack extends BaseStack {\n  // ...\n\n  const osMasterUserPW = this.getSecretValue('osPassword');\n\n  // Script will check Secrets Manager for\n  // reserveRecApi/env/openSearchStack/openSearchMasterUserPassword\n}\n```\n\nIn offline mode, the script will not look for secrets.\n\n#### Stack Definition\n\nTo inherit functionality from the `CDKProject` class, all stacks should extend the `BaseStack` class.\n\n```javascript\nclass NewStack extends BaseStack {\n  constructor(scope, primer) {\n    super(scope, primer, defaults);\n  // ...\n  }\n}\n```\n* `scope`: Application scope (`CDKProject.this`)\n* `primer`: Stack primer reference for the stack.\n\n#### Stack Primer\n\nSince JavaScript class constructors are synchronous, the `BaseStack` constructor cannot asynchronously look for remote `config` and `secrets` values prior to creating its constructs. Therefore, prior to instantiating a class, a `StackPrimer` is used for asynchronous configuration.\n\nThe `StackPrimer` class ingests `defaults` and fetches the remote `config` and `secrets` values, and generates the standardized construct names following the [naming convention](#naming-components). Its `prime()` function should be run before instantiating the stack.\n\n```javascript\nconst primer = new StackPrimer(scope, stackKey, defaults);\n// stackKey: any name for the stack, ie 'tableStack'\n```\n\n#### Stack Creation Function\n\nThe stack creation function is an asynchronous function that bundles the stack and the stack primer and returns the newly created stack. It is called by `CDKProject` to initialize the stack.\n\n```javascript\nasync function createTableStack(scope, stackKey) {\n  try {\n    const primer = new StackPrimer(scope, stackKey, defaults);\n    await primer.prime();\n    return new TableStack(scope, primer);\n  } catch (error) {\n    throw new Error(`Error creating TableStack: ${error}`);\n  }\n}\n```\n\n### Cross-Stack Communication\n\nIn a multistack deployment, there are producer stacks and consumer stacks. Producer stacks initialize AWS resources/constructs and export their references to SSM. Consumer stacks import these references at deployment time. As a result, stacks can theoretically be deployed independently from one another, though it is always wise to not specify which stack needs deploying - `cdk deploy` will run through all stacks and determine which stacks need updating, and leave the rest unchanged.\n\n#### Cross-Stack Referencing\n```javascript\n// Exporting from one stack (BaseStack method)\nthis.exportReference(scope, key, value, description);\n\nthis.exportReference(this, 'baseLayer' this.baseLayer, 'Lambda Layer containing basic shared functions');\n\n// Importing in another stack (BaseStack method)\nconst importedReference = this.resolveReference(scope, key);\n\nconst baseLayer = this.resolveReference(this, 'baseLayer');\n```\n\n## 📝 Additional Resources\n\n### AWS Documentation\n- [AWS CDK Developer Guide](https://docs.aws.amazon.com/cdk/latest/guide/)\n- [Amazon DynamoDB Developer Guide](https://docs.aws.amazon.com/dynamodb/)\n- [Amazon OpenSearch Service Developer Guide](https://docs.aws.amazon.com/opensearch-service/)\n- [Amazon Cognito Developer Guide](https://docs.aws.amazon.com/cognito/)\n\n### Project-Specific Documentation\n- `/docs/` - Detailed API documentation\n- `/src/scripts/` - Deployment and utility scripts\n- `/test/` - Test documentation and examples\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbcgov%2Freserve-rec-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbcgov%2Freserve-rec-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbcgov%2Freserve-rec-api/lists"}