{"id":23363857,"url":"https://github.com/bcgov/nr-rec-resources","last_synced_at":"2025-10-29T01:31:15.143Z","repository":{"id":257885197,"uuid":"863693902","full_name":"bcgov/nr-rec-resources","owner":"bcgov","description":"Product to support managing recreation resources across the province, within the Parks \u0026 Recreation division. Focused on Rec Sites and Trails BC.","archived":false,"fork":false,"pushed_at":"2025-02-13T18:48:40.000Z","size":6745,"stargazers_count":3,"open_issues_count":130,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-13T19:38:10.078Z","etag":null,"topics":["alb","apigateway","aurora","aws","cloudfront","ecs","gha","nest","node","react","sea"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bcgov.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-26T18:35:00.000Z","updated_at":"2025-02-12T21:55:37.000Z","dependencies_parsed_at":"2024-10-16T22:11:19.784Z","dependency_job_id":"15f0103d-08c7-467f-b6ea-5ebb9a0622c1","html_url":"https://github.com/bcgov/nr-rec-resources","commit_stats":null,"previous_names":["bcgov/rec-resources","bcgov/nr-rec-resources"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Fnr-rec-resources","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Fnr-rec-resources/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Fnr-rec-resources/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bcgov%2Fnr-rec-resources/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bcgov","download_url":"https://codeload.github.com/bcgov/nr-rec-resources/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238754217,"owners_count":19524904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["alb","apigateway","aurora","aws","cloudfront","ecs","gha","nest","node","react","sea"],"created_at":"2024-12-21T13:12:14.285Z","updated_at":"2025-10-29T01:31:15.137Z","avatar_url":"https://github.com/bcgov.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![MIT License](https://img.shields.io/github/license/bcgov/quickstart-openshift.svg)](/LICENSE)\n[![Lifecycle](https://img.shields.io/badge/Lifecycle-Experimental-339999)](https://github.com/bcgov/repomountie/blob/master/doc/lifecycle-badges.md)\n\n[![Merge](https://github.com/bcgov/quickstart-openshift/actions/workflows/merge.yml/badge.svg)](https://github.com/bcgov/nr-rec-resources/actions/workflows/main.yml)\n[![Analysis](https://github.com/bcgov/quickstart-openshift/actions/workflows/analysis.yml/badge.svg)](https://github.com/bcgov/nr-rec-resources/actions/workflows/analysis.yml)\n[![Scheduled](https://github.com/bcgov/quickstart-openshift/actions/workflows/scheduled.yml/badge.svg)](https://github.com/bcgov/nr-rec-resources/actions/workflows/scheduled.yml)\n\n# Recreation Resource Services - RSTBC\n\n- [Contributing](CONTRIBUTING.md)\n- [Code of Conduct](CODE_OF_CONDUCT.md)\n- [License](LICENSE)\n- [Security](SECURITY.md)\n\n## Table of Contents\n\n### Project Setup\n\n- [Local Development](#local-development)\n  - [Prerequisites](#prerequisites)\n  - [Docker Compose](#docker-compose)\n  - [Installing and running the application locally](#installing-and-running-the-application-locally)\n  - [Database](#database)\n    - [Flyway](#flyway)\n    - [Running migrations](#running-migrations)\n    - [Migrating RDS Postgres database between AWS environments](docs/database_migration.md#migrating-rds-postgres-database-between-aws-environments)\n  - [Backend](#backend)\n  - [Frontend](#frontend)\n  - [Generate API Client Library](#generate-api-client-library)\n    - [Prerequisites](#client-library-prerequisites)\n    - [Generate TypeScript Axios Client](#generate-typescript-axios-client)\n  - [Generating Prisma Schema and Client](#generating-prisma-schema-and-client)\n  - [Shared Library](shared/README.md)\n- [Pre-commit hooks](#pre-commit-hooks)\n  - [Skipping pre-commit hooks](#skipping-pre-commit-hooks)\n  - [Running pre-commit on all files](#running-pre-commit-on-all-files)\n- [Style Guide](#style-guide)\n- [Schemaspy Database Schema Documentation](#schemaspy-database-schema-documentation)\n- [Storybook Integration](#storybook-integration)\n- [API Metrics](#api-metrics)\n\n### API\n\n- [OpenAPI/Swagger Documentation](docs/open-api-swagger.md)\n  - [Swagger Decorators](docs/open-api-swagger.md#swagger-decorators)\n  - [Accessing Generated Documentation](docs/open-api-swagger.md#accessing-generated-documentation)\n\n### CI/CD\n\n- [CI/CD pipeline with GitHub Actions](docs/ci.md#ci-cd-pipeline-with-github-actions)\n- [Matomo Analytics Deployment](#matomo-analytics-deployment)\n\n### Matomo Analytics Deployment\n\nThe project uses Matomo for web analytics, which is deployed using AWS CDK. The\ndeployment is managed through GitHub Actions.\n\n#### Deployment Workflow\n\n\u003e Currently matomo is only deployed in prod and is being used by all three\n\u003e environments for public and admin apps.\n\nThe deployment workflow is triggered manually and supports three environments:\n`dev`, `test`, and `prod`. The workflow performs the following steps:\n\n1. Checks out the Matomo CDK repository\n2. Sets up Node.js environment\n3. Installs AWS CDK CLI\n4. Installs project dependencies\n5. Configures AWS credentials using OIDC\n6. Bootstraps the CDK environment (if not already done)\n7. Deploys all CDK stacks\n\n#### Prerequisites\n\nBefore deploying, ensure the following secrets are configured in the repository:\n\n- `MATOMO_ENV_ID`: Environment-specific Matomo ID\n- `MATOMO_AWS_ACCOUNT`: AWS account ID for Matomo\n- `MATOMO_NOTIFICATION_EMAILS`: Comma-separated list of emails for notifications\n- `MATOMO_ALLOWED_ORIGINS`: Allowed origins for Matomo tracking\n- `AWS_LZA_DEPLOY_ROLE_ARN`: ARN of the IAM role for deployment\n\n#### Manual Deployment\n\nTo deploy Matomo to an environment:\n\n1. Go to the **Actions** tab in GitHub\n2. Select the **Matomo deployment** workflow\n3. Click **Run workflow**\n4. Select the target environment (`dev`, `test`, or `prod`)\n5. Click **Run workflow**\n\nThe deployment will start and you can monitor its progress in the Actions tab.\n\n#### Environment Configuration\n\nEach environment has its own configuration with appropriate resource sizing and\nscaling. The deployment uses AWS services in the `ca-central-1` region.\n\n- [Docker image build and push](docs/ci.md#docker-image-build-and-push)\n- [Visual Regression Testing with Happo](docs/ci.md#visual-regression-testing)\n\n### Deployment\n\n- [Deploying to AWS](docs/deployment.md#deploying-to-aws)\n  - [Manually deploying pull request to AWS](docs/deployment.md#manually-deploying-pull-request-to-aws)\n  - [Clearing Terraform state lock](docs/deployment.md#clearing-terraform-state-lock)\n  - [AWS Logging](docs/deployment.md#aws-logging)\n    - [Cloudwatch](docs/deployment.md#cloudwatch)\n    - [API logs](docs/deployment.md#api-logs)\n    - [Aurora RDS PostgreSQL logs](docs/deployment.md#aurora-rds-postgresql-logs)\n  - [Aurora RDS PostgreSQL Query Editor](docs/deployment.md#aurora-rds-postgresql-query-editor)\n\n### Database\n\n- [Postgresql](docs/postgresql.md)\n  - [Metadata columns](docs/postgresql.md#metadata-columns)\n  - [History tracking with temporal tables](docs/postgresql.md#history-tracking-with-temporal-tables)\n\n### Testing\n\n- [Playwright](docs/playwright.md)\n  - [Running e2e tests](docs/playwright.md#running-e2e-tests)\n  - [Writing tests](docs/playwright.md#writing-tests)\n    - [POM (Page Object Model)](docs/playwright.md#pom-page-object-model)\n\n## Local Development\n\n### Prerequisites\n\n- Node.js\n- npm\n- Docker OR PostgreSQL 16\n- Flyway\n\n### Docker Compose\n\nTo run the entire application using Docker Compose, run the following commands:\n\n```bash\ngit clone git@github.com:bcgov/nr-rec-resources.git\ncd nr-rec-resources\ndocker-compose up\n```\n\nNavigate to `http://localhost:3000` in your web browser to view the application.\n\n### Installing and running the application locally\n\nBefore starting development on this project, run `npm install` in the base\ndirectory to install eslint and plugins to ensure linting is working correctly.\n\n### Database\n\nTo run this on your local machine, you will need a working installation of\nPostgreSQL 16 and Flyway.\n\n#### Flyway\n\nFlyway is a database migration tool that is used to manage the database schema.\n\nTo install flyway locally on macOS or Linux, if you have Homebrew installed, you\ncan run:\n\n```bash\nbrew install flyway\n```\n\nAlternatively you can manually download the latest version of Flyway from the\n[Flyway website](https://flywaydb.org/download/).\n\n#### Running migrations\n\nCreate an `.env` file in the `backend` directory using the example in\n`backend/.env.example` as a template.\n\n```bash\ncd nr-rec-resources\nmake create_db\nmake migrate\nmake load_fixtures\n```\n\nor to drop, recreate, run migrations and reseed the database, ensure no\nconnections are open to the database then run:\n\n```bash\nmake reset_db\n```\n\n### Backend\n\nEnsure you have the `.env` file in the `backend` directory from the previous\nstep.\n\n```bash\ncd backend\nnpm install\nnpx prisma generate\nnpm run dev\n```\n\n### Frontend\n\nCreate an `.env` file in the `frontend` directory using the example in\n`frontend/.env.example` as a template.\n\n```bash\ncd frontend\nnpm install\nnpm run dev\n```\n\nNavigate to `http://localhost:3000` in your web browser to view the application.\n\n### Generate API Client Library\n\n#### Client Library Prerequisites\n\nInstall Java Development Kit (JDK) 17:\n\n```bash\nbrew install openjdk@17\n```\n\n#### Generate TypeScript Axios Client\n\nRun the following command from the project root folder to generate the\nTypeScript client library from your OpenAPI specification and run `prettier-fix`\nto format the files:\n\n```bash\nnpm run install-client-sdk\n```\n\nThis command will:\n\n- Generate TypeScript client code using Axios\n- Use the OpenAPI spec from your local NestJS server which should be running on\n  port **8000**\n- Output the generated code to `src/service/recreation-resource` directory\n\n### Generating Prisma Schema and Client\n\nWhen you make changes to the database schema, you will need to regenerate the\nPrisma schema and client. Ensure your database is running and run the following\ncommands:\n\n```bash\ncd backend\nnpx prisma db pull # Pull the latest schema from the database\nnpx prisma generate # Generate the Prisma client\n```\n\nThe updated Prisma schema can be viewed in `backend/prisma/schema.prisma`\n\n## Pre-commit hooks\n\nPre-commit is set up to run checks for linting, formatting, and secrets.\n\n- Install [pre-commit](https://pre-commit.com/)\n- With pre-commit installed run `pre-commit install` in the root directory of\n  the project\n- Pre-commit should now run on your staged files every time you make a commit\n\n### Skipping pre-commit hooks\n\nIf you need to skip the pre-commit hooks for a specific commit, you can use the\n`--no-verify` flag. Some developers may use this when they are making a commit\nthat they know will fail the pre-commit checks, but they still want to commit\nthe changes. This is a perfectly acceptable workflow, though there is a\npre-commit check in CI so it may be necessary to run pre-commit on all files\nbefore putting a PR up for review if this is skipped.\n\n```bash\ngit commit -m \"Your commit message\" --no-verify\n```\n\n### Running pre-commit on all files\n\nSometimes it may be necessary to run `pre-commit` on the entire project due to a\nmistake or a configuration change.\n\n```bash\npre-commit run --all-files\n```\n\n## Style Guide\n\nCommits follow the conventions defined in the\n[Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/)\nspecification.\n\n## Schemaspy Database Schema Documentation\n\nSchedule job runs every saturday and keep schema documentation upto date in\n[github pages](https://bcgov.github.io/nr-rec-resources/).\n\n## Architecture\n\n#### Public App\n\n![RST Public App Architecture](docs/rst-arch.drawio.svg)\n\n#### Admin App\n\n![RST Admin App Architecture](docs/admin-architecture/rst-admin-arch.mermaid.svg)\n\n## Storybook Integration\n\nThis project integrates Storybook for component development and includes MSW\n(Mock Service Worker) for API mocking.\n\n### Running Storybook\n\n```bash\nnpm run storybook\n```\n\n### Directory Structure\n\n```\nfrontend/.storybook/        # Storybook configuration\n\nfrontend/stories/          # Component stories - Folder structure mirrors src\n├── components\n│   └── rec-resource\n│       ├── AdditionalFees.stories.ts\n│       ├── Camping.stories.ts\n│       ├── RecResourcePage.stories.tsx\n│       ├── mockData.ts\n│       └── mockHandlers.ts\n└── mock\n    └── mockServiceWorker.js\n\n```\n\n---\n\n## API Metrics\n\nThis application uses AWS CloudWatch SDK to automatically capture and report key\nperformance and usage metrics for API endpoints. This is primarily handled by\nthe `ApiMetricsInterceptor` located in\n`/backend/src/api-metrics/api-metrics.interceptor.ts`.\n\n\u003e ❗❗❗ When running locally make sure to include the environment variable\n\u003e `APP_ENV=Local`. This disables the metric emission.\n\n## How it Works\n\n- **Interceptor:** The `ApiMetricsInterceptor` intercepts incoming HTTP requests\n  and outgoing responses.\n- **Timing:** It measures the latency (duration) of each request.\n- **Operation Identification:** `OperationNameUtil` determines the operation\n  name, preferring the operationId from `@ApiOperation` if available.\n- **Metric Construction:** `ApiMetricsService` constructs metric data points,\n  including latency, request count, and error count when applicable.\n- **Publishing:** If metrics are enabled (i.e., not running locally),\n  MetricsService publishes the metrics to AWS CloudWatch under the namespace\n  `RecreationSitesAndTrailsBCAPI`.\n\n### Metrics Captured\n\nFor each request, the following metrics are potentially logged:\n\n- **RequestLatency**: The time taken to process the request (Unit:\n  Milliseconds).\n- **RequestCount**: A count of requests received (Unit: Count).\n- **ErrorCount**: A count of requests resulting in a 4xx or 5xx status code\n  (Unit: Count).\n\n### Dimensions\n\nMetrics are published with the following dimensions for filtering and\naggregation in CloudWatch:\n\n- **Operation:** Identifies the specific API operation/endpoint being called.\n- **Method:** The HTTP request method (e.g., `GET`, `POST`).\n- **StatusCode:** The HTTP status code of the response (as a string).\n\n### Setting Up Metrics for a New Operation/Endpoint\n\nThe `ApiMetricsInterceptor` needs an `Operation` name to associate the metrics\nwith a specific endpoint.\n\n1. **[Recommended] Custom Operation Name:** For better clarity or to decouple\n   the metric name from potential code refactoring (like renaming a class or\n   method), you can set an operation name using Swagger's `@ApiOperation`\n   decorator with an `operationId` property on your controller method.\n2. **Default Behavior:** If you do _not_ specify an operation name, the\n   interceptor will automatically generate one using the format:\n   `\u003cControllerClassName\u003e.\u003chandlerMethodName\u003e`. For example, if you have a\n   `getRecreationSiteById` method in a `RecreationResourceController`, the\n   default operation name will be\n   `RecreationResourceController.getRecreationSiteById`.\n\n### Viewing Metrics\n\nMetrics can be viewed in:\n\n- AWS CloudWatch under the namespace `RecreationSitesAndTrailsBCAPI`\n- Filter metrics by dimensions:\n  - Operation\n  - Method\n  - StatusCode\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbcgov%2Fnr-rec-resources","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbcgov%2Fnr-rec-resources","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbcgov%2Fnr-rec-resources/lists"}