From 6c54026649d71831ed2f2a3b1d6cc0161955c6ee Mon Sep 17 00:00:00 2001 From: Dercraker Date: Fri, 3 Oct 2025 22:37:55 +0200 Subject: [PATCH 01/12] (Docs): Base doc --- Documentation/Guidelines/Architecture.md | 182 ++++++++++++++++++ .../Guidelines/Code-Review-Process.md | 3 + .../Guidelines/Development-Process.md | 63 ++++++ Documentation/Guidelines/Onboarding.md | 56 ++++++ .../Guidelines/Release-And-Deployment.md | 12 ++ .../Guidelines/pictures/git-flow-model.png | Bin 0 -> 124925 bytes README.md | 37 +--- 7 files changed, 326 insertions(+), 27 deletions(-) create mode 100644 Documentation/Guidelines/Architecture.md create mode 100644 Documentation/Guidelines/Code-Review-Process.md create mode 100644 Documentation/Guidelines/Development-Process.md create mode 100644 Documentation/Guidelines/Onboarding.md create mode 100644 Documentation/Guidelines/Release-And-Deployment.md create mode 100644 Documentation/Guidelines/pictures/git-flow-model.png diff --git a/Documentation/Guidelines/Architecture.md b/Documentation/Guidelines/Architecture.md new file mode 100644 index 0000000..b3506cd --- /dev/null +++ b/Documentation/Guidelines/Architecture.md @@ -0,0 +1,182 @@ +########### TODO ########### + +# [DyingStar - Webapp] Software Architecture + +We plan to build the application using [Architecture] style. + +## Architecture Diagram + +![](architecture.png) + +> We recommend building architecture using [Draw.io](https://app.diagrams.net/). Draw.io also has a desktop application. + +You can also document your architecture using [C4Model](https://c4model.com/). We recommend C1(System Context) and C2(Container) diagrams. + +> C4 model is a lean graphical notation technique for modelling the architecture of software systems. It is based on a structural decomposition of a system into containers and components and relies on existing modelling techniques such as the Unified Modelling Language (UML) or Entity Relation Diagrams (ERD) for the more detailed decomposition of the architectural building blocks. + +## Technologies + +The list of technologies we will use to build the application are as follows: + +| Technology | Purpose | Version | +| ------------------- | ---------------------- | -------- | +| [Java] | [Programming Language] | [11.0.9] | +| [Postgres] | [Database] | [13.1] | +| [Backend Framework] | [Spring Boot] | [2.4.1] | +| [Frontend] | [React] | [17.0.1] | + +## Non-functional Requirements + +Non-functional requirement for the project are: + +| Quality Attribute | Description | Target | +| --- | --- | --- | +| [Performance] | [Transaction Response Time] | [2 seconds] | +| [Availability] | [System Uptime] | [99.9] | +| [Throughput] | [Number of requests/transactions per second at peak time] | [1000 RPS] | +| [Auditability] | [Ability of the application to show what has happened to it, who did it and when] | [A log file that captures the event with the timestamp] | +| [Reliability] | [Mean time to recovery] | [System should be able to recover from failure under 5 mins] | +| [Usability] | [Usability can be described as the capacity of a system to provide a condition for its users to perform the tasks safely, effectively, and efficiently while enjoying the experience] | [Browsers: Chrome, IE, Firefox]
[Screen Size] | + +# Architecture Decision Records + +## ADR-0001 - Microservices in a monorepo + +- Status: +- Deciders: [names] +- Date: + +### Context and Problem Statement + +There will be two teams working on one FE, one GraphQL API and multiple BE microservices. We are about to take the learnings from the PoA into a the MVP product, by starting one monorepo or multiple repos per service. + +### Considered Options + +1. One repository containing one service per root directory +2. A repository per service + +### Decision Outcome + +A monorepo has been chosen, because all code is moving quickly in the beginning of the project and we don't want blocking dependencies or an inefficient development workflow. Since we will implement User Stories end to end, a single developer usually has to work in multiple services simultaneously, which is easier in a monorepo. + +We will evaluate the decision after two Sprints. + +#### Positive Consequences + +- A monorepo will speed up development. +- Package dependencies can be managed using tools like Lerna or NX. +- We think it is easier to move from monorepo into multiple repos than to merge multiple repos into a monorepo. + +#### Negative Consequences + +- There is a risk of coupling we don't want with microservices. +- The unfiltered git history is mixed for the different services. +- Every developer gets access to all code, even when they are assigned to work on one service. + +## ADR-0002 - GraphQL + +## ADR-0003 - DevOps + +## ADR-0004 - Styling solution + +## ADR-0005 - CSS-in-JS solution + +## ADR-0006 - Component library + +## ADR-0007 - Component library setup + +## ADR-0008 - Testing strategy + +## ADR-0009 - Coding Style + +## ADR-0010 - Performance testing + +## ADR-0011 - Testing practices + +## ADR-0012 - Frontend schema validation library + +## ADR-0013 - Monorepo tooling + +## ADR-0014 - Frontend folder naming + +- Status: +- Deciders: [names] +- Date: + +### Context and Problem Statement + +As the project organically grew, adhoc decision were made around the naming of the folders, eventually leading to small inconsistencies between the domains. + +At the time of writing the structure is as follows: + +- `app/customer/customer-edit-page/CustomerEditPage.tsx` +- `app/product/product-search-page/ProductSearchPage.tsx` + +We want an improved and agreed upon way of naming our directories moving forward. + +### Suggested Solution + +The suggestion was made to make the folder naming more concise; removing the domain prefix and the page suffix in the folder naming, while keeping the file names and exports as is to preserve searchability. + +The following change was suggested: + +- `app/customer/customer-edit-page/CustomerEditPage.tsx` -> `app/customer/edit/CustomerEditPage.tsx` +- `app/product/product-search-page/ProductSearchPage.tsx` -> `app/product/search/ProductSearchPage.tsx` + +To be added domains e.g. Order could be implemented using to the following naming convention: + +``` +product/ + ├── ... +customer/ + ├── ... +order/ + ├── view/ + │ ├── details/ + │ │ └── OrderDetails.tsx // only used by OrderViewPage + │ └── OrderViewPage.tsx + ├── create/ + │ └── OrderCreatePage.tsx + ├── edit/ + │ └── OrderEditPage.tsx + └── search/ + └── OrderSearchPage.tsx +``` + +### Decision Outcome + +We've agreed on the suggested change of more concise naming for folders; by removing the domain and page prefix in the directories. + +## ADR-0015 - Frontend shared components + +- Status: +- Deciders: [names] +- Date: + +### Context and Problem Statement + +Where to store components that are shared between domains e.g. product, customer, etc + +### Suggested Solution + +Store components shared between domains under `/components/shared` directory. + +### Decision Outcome + +Agreed on suggested solution. + +## ADR-0016 - Frontend component file order + +## ADR-0017 - Organise styling code + +## ADR-0018 - Cypress test selectors + +## ADR-0019 - NodeJS / NPM version management + +## ADR-0020 - PR Merge strategy + +## ADR-0021 - Timestamps & timezones + +## ADR-0022 - Code sharing style + +## ADR-0023 - Testing GraphQL API diff --git a/Documentation/Guidelines/Code-Review-Process.md b/Documentation/Guidelines/Code-Review-Process.md new file mode 100644 index 0000000..947a1d8 --- /dev/null +++ b/Documentation/Guidelines/Code-Review-Process.md @@ -0,0 +1,3 @@ +########### TODO ########### + +# Code Review Process diff --git a/Documentation/Guidelines/Development-Process.md b/Documentation/Guidelines/Development-Process.md new file mode 100644 index 0000000..85a9fc1 --- /dev/null +++ b/Documentation/Guidelines/Development-Process.md @@ -0,0 +1,63 @@ +# Development Process + +The application is developed using the git-flow model. Developers cannot commit to **master** and **develop** branches. All features are developed in feature branches. A feature can then be merged into develop using Pull/merge request. + +You can find more information about the git-flow model [here](https://nvie.com/posts/a-successful-git-branching-model/). + +Here is a screenshot of the git-flow model : ![Git-flow Model](./pictures/git-flow-model.png) + +All branches must be named using the following conventions : + +- `feat/{issue-number}-{ShortIssueName}` : use for application new features +- `fix/{issue-number}-{ShortIssueName}` : use for fixing application bugs / issues +- `release/release-{semantic-version-number}` : use for release tasks + +examples : + +- feat/15469-AddNewFeature +- fix/15469-FixBug +- release/release-1.2.3 + +## Merging process + +### Merging process for `feat` or `fix` branch into `develop` branch + +_Only the Website Lead can merge the `feat` or `fix` branch into the `develop` branch_ + +- Get all details from the issue on github projects +- Ask the Website Lead for any questions about the issue on discord post related to the issue +- Ask the Website Lead to be assigned to the issue +- Updated the `develop` : `git pull origin develop` +- Create feature branch : `git checkout -b feat/15469-AddNewFeature` +- Develop the specified requirements +- Run the formater, linter, tests, build and make sure they are passing +- Commit and Push the code +- Create a Pull request to merge the feature branch into the `develop` branch +- Indicate on discord post that the PR is ready for review +- Address the required review comments (if any) +- Approve the PR when the code is ready to be merged by the Website Lead +- Website Lead merge the PR into the `develop` branch + +### Creating hotfix process : + +TODO + +### Creating release process : + +_Only the Website Lead can create a release_ + +- Updated the `develop` : `git pull origin develop` +- Create release branch : `git checkout -b release/release-1.2.3` +- Update the version number in the `package.json` file +- _On this branch: small fixes and preparation of metadata (changelog, dates, etc.). No big features_ +- Update changelog, version notes, build numbers... +- Commit and Push the code +- Create a Pull request to merge the release branch into the `master` branch +- Indicate on discord post that the PR is ready for review +- Address the required review comments (if any) +- Approve the PR when the code is ready to be merged by the Website Lead +- Merge the PR into the `master` branch +- Create tag with the new version number : `git tag -a v1.2.3 -m "Release 1.2.3"` +- Push the tag : `git push origin v1.2.3` +- Merge the `master` branch into the `develop` branch +- Create a new release on github with the new version number diff --git a/Documentation/Guidelines/Onboarding.md b/Documentation/Guidelines/Onboarding.md new file mode 100644 index 0000000..fa20233 --- /dev/null +++ b/Documentation/Guidelines/Onboarding.md @@ -0,0 +1,56 @@ +# [DyingStar - Webapp] Tools + +Please install following tools + +| Tool | Version | Required | +| --------------------------------- | ----------------- | -------- | +| [Node.js](https://nodejs.org/en) | 22.14.0 or higher | Yes | +| [Docker](https://www.docker.com/) | 28.4.0 or higher | Yes | +| [Docker](https://www.docker.com/) | 28.4.0 or higher | Yes | +| [Git](https://git-scm.com/) | 2.50.0 or higher | Yes | +| [pnpm](https://pnpm.io/) | 10.0.0 or higher | Yes | + +# Git command-line configuration + +Make sure you have configured your user with Git. This information will be used by Git. + +``` +git config --global user.name "Your Fullname" +git config --global user.email "Your Email" +``` + +Windows users should use Git bash for better command-line experience. If you are not well-versed with Git then you can read the [tutorial](https://github.com/shekhargulati/git-the-missing-tutorial). + +# Connecting to Github using SSH + +Refer to this [link](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/connecting-to-github-with-ssh) to setup SSH for your Github account. + +# Get your access to the repository + +Ask to the Website Lead on this [discord channel](https://discord.com/channels/1399325839665004554/1417133740810833940) to get push permissions to the repository. + +# Clone the application + +Clone the application using the following command. + +``` +git clone git@github.com:DyingStar-game/website.git +``` + +# Local Development + +## Setup + +1. Copy `.env.example` to `.env.local` and fill in the required environment variables +2. Run `make dev` to start the development server. This will install dependencies and start the server. +3. Open your browser and navigate to `http://localhost:3000` to see the website. +4. To stop the development server, stop the Docker container with `Ctrl+C` in the terminal where `make dev` was run. + +## Notes + +- The development server supports hot-reloading, so any changes you make to the code will automatically be reflected in the browser. +- If you need to install new dependencies, you can do so by running `make add-dependency ` or `make add-dev-dependency ` for dev dependencies. + +## Environment Variables + +- The workflow expects a secret named `WEBSITE_ENV_PRODUCTION_FILE` containing the contents of the `.env.production` file. This file is created during the CI process to ensure that sensitive information is not hardcoded in the repository diff --git a/Documentation/Guidelines/Release-And-Deployment.md b/Documentation/Guidelines/Release-And-Deployment.md new file mode 100644 index 0000000..e8a8f7a --- /dev/null +++ b/Documentation/Guidelines/Release-And-Deployment.md @@ -0,0 +1,12 @@ +########### TODO ########### + +# Release and Deployment Process + +## CI/CD Pipeline + +The project uses GitHub Actions for continuous integration and deployment. The workflow is defined in `.github/workflows/build.yml`. + +### Stages + +1. **Next.js Build**: This stage installs dependencies, lints the code, and builds the Next.js application. +2. **Docker Build and Push**: This stage builds a Docker image of the application and pushes it to the registry. The push is triggered only on the `main` branch with a tag starting with `v`. diff --git a/Documentation/Guidelines/pictures/git-flow-model.png b/Documentation/Guidelines/pictures/git-flow-model.png new file mode 100644 index 0000000000000000000000000000000000000000..5b96426c76e9b59f162331cf2c8eb5bd1446b8f6 GIT binary patch literal 124925 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�QQpl!FqPohLNfFE1 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

Kh5V?q&1SWLKGwoIdmjHtQyKHxgywu0?&pf* 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

|W@eX7X<*f|U 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 E57MRp_5c6? literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 98b92b4..4835932 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,13 @@ -# DyingStar Website +# [DyingStar - Webapp] Collaboration Guideline's wiki -## Local Development +Here you'll find all the documents you need to collaborate on the project. -### Requirements -- [Docker](https://www.docker.com/get-started) -- [Docker Compose](https://docs.docker.com/compose/install/) -- [Make](https://www.gnu.org/software/make/) to use the provided Makefile (optional but recommended) +| Topic | Description | +| ---------------------------------------------------------------------------- | ------------------------------------------------------------------ | +| [Onboarding](Documentation\Guidelines\Onboarding.md) | Documents related to new developer onboarding | +| [Development Process](Documentation\Guidelines\Development-Process.md) | Documents related to development process | +| [Architecture](Documentation\Guidelines\Architecture.md) | Documents related to architecture | +| [Code Review Process](Documentation\Guidelines\Code-Review-Process.md) | Documents related to code review process, definition of ready/done | +| [Release and Deployment](Documentation\Guidelines\Release-And-Deployment.md) | Documents related to release and deployment | -### Setup -1. Copy `.env.example` to `.env.local` and fill in the required environment variables -2. Run `make dev` to start the development server. This will install dependencies and start the server. -3. Open your browser and navigate to `http://localhost:3000` to see the website. -4. To stop the development server, stop the Docker container with `Ctrl+C` in the terminal where `make dev` was run. - -### Notes -- The development server supports hot-reloading, so any changes you make to the code will automatically be reflected in the browser. -- If you need to install new dependencies, you can do so by running `make add-dependency ` or `make add-dev-dependency ` for dev dependencies. - -## CI/CD Pipeline - -The project uses GitHub Actions for continuous integration and deployment. The workflow is defined in `.github/workflows/build.yml`. - -### Stages - -1. **Next.js Build**: This stage installs dependencies, lints the code, and builds the Next.js application. -2. **Docker Build and Push**: This stage builds a Docker image of the application and pushes it to the registry. The push is triggered only on the `main` branch with a tag starting with `v`. - -### Environment Variables -- The workflow expects a secret named `WEBSITE_ENV_PRODUCTION_FILE` containing the contents of the `.env.production` file. This file is created during the CI process to ensure that sensitive information is not hardcoded in the repository +**NB** : Got an idea ? Or a suggestion ? Feel free to open an issue or contact one of our developers. From 4af218a96dccf363cadd2315b98582aedadc25be Mon Sep 17 00:00:00 2001 From: Dercraker Date: Sat, 4 Oct 2025 00:06:10 +0200 Subject: [PATCH 02/12] WIP ADRs --- Documentation/Guidelines/Architecture.md | 182 --------- .../architecture/ADR/000-Template.md | 72 ++++ Documentation/Guidelines/architecture/ADRs.md | 9 + .../Guidelines/architecture/Architecture.md | 30 ++ README.md | 2 +- package.json | 4 +- pnpm-lock.yaml | 385 ++++++++++++++++++ 7 files changed, 500 insertions(+), 184 deletions(-) delete mode 100644 Documentation/Guidelines/Architecture.md create mode 100644 Documentation/Guidelines/architecture/ADR/000-Template.md create mode 100644 Documentation/Guidelines/architecture/ADRs.md create mode 100644 Documentation/Guidelines/architecture/Architecture.md diff --git a/Documentation/Guidelines/Architecture.md b/Documentation/Guidelines/Architecture.md deleted file mode 100644 index b3506cd..0000000 --- a/Documentation/Guidelines/Architecture.md +++ /dev/null @@ -1,182 +0,0 @@ -########### TODO ########### - -# [DyingStar - Webapp] Software Architecture - -We plan to build the application using [Architecture] style. - -## Architecture Diagram - -![](architecture.png) - -> We recommend building architecture using [Draw.io](https://app.diagrams.net/). Draw.io also has a desktop application. - -You can also document your architecture using [C4Model](https://c4model.com/). We recommend C1(System Context) and C2(Container) diagrams. - -> C4 model is a lean graphical notation technique for modelling the architecture of software systems. It is based on a structural decomposition of a system into containers and components and relies on existing modelling techniques such as the Unified Modelling Language (UML) or Entity Relation Diagrams (ERD) for the more detailed decomposition of the architectural building blocks. - -## Technologies - -The list of technologies we will use to build the application are as follows: - -| Technology | Purpose | Version | -| ------------------- | ---------------------- | -------- | -| [Java] | [Programming Language] | [11.0.9] | -| [Postgres] | [Database] | [13.1] | -| [Backend Framework] | [Spring Boot] | [2.4.1] | -| [Frontend] | [React] | [17.0.1] | - -## Non-functional Requirements - -Non-functional requirement for the project are: - -| Quality Attribute | Description | Target | -| --- | --- | --- | -| [Performance] | [Transaction Response Time] | [2 seconds] | -| [Availability] | [System Uptime] | [99.9] | -| [Throughput] | [Number of requests/transactions per second at peak time] | [1000 RPS] | -| [Auditability] | [Ability of the application to show what has happened to it, who did it and when] | [A log file that captures the event with the timestamp] | -| [Reliability] | [Mean time to recovery] | [System should be able to recover from failure under 5 mins] | -| [Usability] | [Usability can be described as the capacity of a system to provide a condition for its users to perform the tasks safely, effectively, and efficiently while enjoying the experience] | [Browsers: Chrome, IE, Firefox]
[Screen Size] | - -# Architecture Decision Records - -## ADR-0001 - Microservices in a monorepo - -- Status: -- Deciders: [names] -- Date: - -### Context and Problem Statement - -There will be two teams working on one FE, one GraphQL API and multiple BE microservices. We are about to take the learnings from the PoA into a the MVP product, by starting one monorepo or multiple repos per service. - -### Considered Options - -1. One repository containing one service per root directory -2. A repository per service - -### Decision Outcome - -A monorepo has been chosen, because all code is moving quickly in the beginning of the project and we don't want blocking dependencies or an inefficient development workflow. Since we will implement User Stories end to end, a single developer usually has to work in multiple services simultaneously, which is easier in a monorepo. - -We will evaluate the decision after two Sprints. - -#### Positive Consequences - -- A monorepo will speed up development. -- Package dependencies can be managed using tools like Lerna or NX. -- We think it is easier to move from monorepo into multiple repos than to merge multiple repos into a monorepo. - -#### Negative Consequences - -- There is a risk of coupling we don't want with microservices. -- The unfiltered git history is mixed for the different services. -- Every developer gets access to all code, even when they are assigned to work on one service. - -## ADR-0002 - GraphQL - -## ADR-0003 - DevOps - -## ADR-0004 - Styling solution - -## ADR-0005 - CSS-in-JS solution - -## ADR-0006 - Component library - -## ADR-0007 - Component library setup - -## ADR-0008 - Testing strategy - -## ADR-0009 - Coding Style - -## ADR-0010 - Performance testing - -## ADR-0011 - Testing practices - -## ADR-0012 - Frontend schema validation library - -## ADR-0013 - Monorepo tooling - -## ADR-0014 - Frontend folder naming - -- Status: -- Deciders: [names] -- Date: - -### Context and Problem Statement - -As the project organically grew, adhoc decision were made around the naming of the folders, eventually leading to small inconsistencies between the domains. - -At the time of writing the structure is as follows: - -- `app/customer/customer-edit-page/CustomerEditPage.tsx` -- `app/product/product-search-page/ProductSearchPage.tsx` - -We want an improved and agreed upon way of naming our directories moving forward. - -### Suggested Solution - -The suggestion was made to make the folder naming more concise; removing the domain prefix and the page suffix in the folder naming, while keeping the file names and exports as is to preserve searchability. - -The following change was suggested: - -- `app/customer/customer-edit-page/CustomerEditPage.tsx` -> `app/customer/edit/CustomerEditPage.tsx` -- `app/product/product-search-page/ProductSearchPage.tsx` -> `app/product/search/ProductSearchPage.tsx` - -To be added domains e.g. Order could be implemented using to the following naming convention: - -``` -product/ - ├── ... -customer/ - ├── ... -order/ - ├── view/ - │ ├── details/ - │ │ └── OrderDetails.tsx // only used by OrderViewPage - │ └── OrderViewPage.tsx - ├── create/ - │ └── OrderCreatePage.tsx - ├── edit/ - │ └── OrderEditPage.tsx - └── search/ - └── OrderSearchPage.tsx -``` - -### Decision Outcome - -We've agreed on the suggested change of more concise naming for folders; by removing the domain and page prefix in the directories. - -## ADR-0015 - Frontend shared components - -- Status: -- Deciders: [names] -- Date: - -### Context and Problem Statement - -Where to store components that are shared between domains e.g. product, customer, etc - -### Suggested Solution - -Store components shared between domains under `/components/shared` directory. - -### Decision Outcome - -Agreed on suggested solution. - -## ADR-0016 - Frontend component file order - -## ADR-0017 - Organise styling code - -## ADR-0018 - Cypress test selectors - -## ADR-0019 - NodeJS / NPM version management - -## ADR-0020 - PR Merge strategy - -## ADR-0021 - Timestamps & timezones - -## ADR-0022 - Code sharing style - -## ADR-0023 - Testing GraphQL API diff --git a/Documentation/Guidelines/architecture/ADR/000-Template.md b/Documentation/Guidelines/architecture/ADR/000-Template.md new file mode 100644 index 0000000..ae8f69d --- /dev/null +++ b/Documentation/Guidelines/architecture/ADR/000-Template.md @@ -0,0 +1,72 @@ +# [short title of solved problem and solution] + +- Status: [proposed | rejected | accepted | deprecated | … | superseded by [ADR-0005](0005-example.md)] +- Deciders: [list everyone involved in the decision] +- Date: [YYYY-MM-DD when the decision was last updated] + +Technical Story: [description | ticket/issue URL] + +## Context and Problem Statement + +[Describe the context and problem statement, e.g., in free form using two to three sentences. You may want to articulate the problem in form of a question.] + +## Decision Drivers + +- [driver 1, e.g., a force, facing concern, …] +- [driver 2, e.g., a force, facing concern, …] +- … + +## Considered Options + +- [option 1] +- [option 2] +- [option 3] +- … + +## Decision Outcome + +Chosen option: "[option 1]", because [justification. e.g., only option, which meets k.o. criterion decision driver | which resolves force force | … | comes out best (see below)]. + +### Positive Consequences + +- [e.g., improvement of quality attribute satisfaction, follow-up decisions required, …] +- … + +### Negative Consequences + +- [e.g., compromising quality attribute, follow-up decisions required, …] +- … + +## Pros and Cons of the Options + +### [option 1] + +[example | description | pointer to more information | …] + +- Good, because [argument a] +- Good, because [argument b] +- Bad, because [argument c] +- … + +### [option 2] + +[example | description | pointer to more information | …] + +- Good, because [argument a] +- Good, because [argument b] +- Bad, because [argument c] +- … + +### [option 3] + +[example | description | pointer to more information | …] + +- Good, because [argument a] +- Good, because [argument b] +- Bad, because [argument c] +- … + +## Links + +- [Link type] [Link to ADR] +- … diff --git a/Documentation/Guidelines/architecture/ADRs.md b/Documentation/Guidelines/architecture/ADRs.md new file mode 100644 index 0000000..b4e0541 --- /dev/null +++ b/Documentation/Guidelines/architecture/ADRs.md @@ -0,0 +1,9 @@ + + + + +* [ADR-000](ADR/000-Template.md) - [short title of solved problem and solution] + + + + diff --git a/Documentation/Guidelines/architecture/Architecture.md b/Documentation/Guidelines/architecture/Architecture.md new file mode 100644 index 0000000..6c396a0 --- /dev/null +++ b/Documentation/Guidelines/architecture/Architecture.md @@ -0,0 +1,30 @@ +# [DyingStar - Webapp] Webapp Architecture + +## Technologies + +The list of technologies we will use to build the application are as follows: + +| Technology | Description | Version | ADR if available | +| -------------------------- | --------------------- | -------- | ---------------- | +| [Next.Js] | Base framework | [11.0.9] | | +| [t3-oss] | Environment variables | [13.1] | | +| [TailwindCss] | Styling | [2.4.1] | | +| [class-variance-authority] | | [17.0.1] | | +| [clsx] | | [17.0.1] | | + +## Non-functional Requirements + +Non-functional requirement for the project are: + +| Quality Attribute | Description | Target | +| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | +| Performance | Transaction Response Time | 2 seconds | +| Availability | System Uptime | 99.9 | +| Throughput | Number of requests/transactions per second at peak time | 1000 RPS | +| Auditability | Ability of the application to show what has happened to it, who did it and when | A log file that captures the event with the timestamp | +| Reliability | Mean time to recovery | System should be able to recover from failure under 5 mins | +| Usability | Usability can be described as the capacity of a system to provide a condition for its users to perform the tasks safely, effectively, and efficiently while enjoying the experience | Browsers: Chrome, IE, Firefox | + +# Architecture Decision Records + +All ADRs are stored in the [ADR](./ADR) folder and referenced in the [ADRs.md](./ADRs.md) file. diff --git a/README.md b/README.md index 4835932..66133db 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Here you'll find all the documents you need to collaborate on the project. | ---------------------------------------------------------------------------- | ------------------------------------------------------------------ | | [Onboarding](Documentation\Guidelines\Onboarding.md) | Documents related to new developer onboarding | | [Development Process](Documentation\Guidelines\Development-Process.md) | Documents related to development process | -| [Architecture](Documentation\Guidelines\Architecture.md) | Documents related to architecture | +| [Architecture](Documentation\Guidelines\architecture\Architecture.md) | Documents related to architecture | | [Code Review Process](Documentation\Guidelines\Code-Review-Process.md) | Documents related to code review process, definition of ready/done | | [Release and Deployment](Documentation\Guidelines\Release-And-Deployment.md) | Documents related to release and deployment | diff --git a/package.json b/package.json index cbc0192..3e6cd24 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "format": "prettier --write .", "lint": "eslint . --fix", "start": "next start", - "ts": "tsc --noEmit" + "ts": "tsc --noEmit", + "adr:generate": "adr-log -d ./Documentation/Guidelines/architecture/ADR -i ./Documentation/Guidelines/architecture/ADRs.md" }, "dependencies": { "@hookform/resolvers": "^5.2.1", @@ -98,6 +99,7 @@ "@typescript-eslint/eslint-plugin": "^8.42.0", "@typescript-eslint/parser": "^8.42.0", "@vitejs/plugin-react": "^5.0.2", + "adr-log": "^2.2.0", "cross-fetch": "^4.1.0", "dotenv": "^17.2.2", "eslint": "^9.35.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0e00cac..432a7fc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -258,6 +258,9 @@ importers: '@vitejs/plugin-react': specifier: ^5.0.2 version: 5.0.2(vite@7.0.5(@types/node@24.3.1)(jiti@2.5.1)(lightningcss@1.30.1)(sass@1.92.1)(tsx@4.20.5)(yaml@2.8.1)) + adr-log: + specifier: ^2.2.0 + version: 2.2.0 cross-fetch: specifier: ^4.1.0 version: 4.1.0 @@ -2178,6 +2181,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + adr-log@2.2.0: + resolution: {integrity: sha512-+J6SUdITpd+N4tvptSPu672zckVITj9ux7xClpfVoB1W148X4KGCOIj82ONIzK2acUMNN4OUYvIG1hLZ+fGy5g==} + hasBin: true + agent-base@7.1.3: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} @@ -2185,10 +2192,22 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ansi-red@0.1.1: + resolution: {integrity: sha512-ewaIr5y+9CUTGFwZfpECUbFlGcC0GCw1oqR9RI6h1gQCd9Aj2GxSckCnPsVJnmfMZbwFYE+leZGASgkWl06Jow==} + engines: {node: '>=0.10.0'} + + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -2197,6 +2216,10 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} + ansi-wrap@0.1.0: + resolution: {integrity: sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==} + engines: {node: '>=0.10.0'} + arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -2257,6 +2280,9 @@ packages: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} + autolinker@0.28.1: + resolution: {integrity: sha512-zQAFO1Dlsn69eXaO6+7YZc+v84aquQKbwpzCE3L0stj56ERn9hutFxPopViLjo9G+rWwjozRhgS5KJ25Xy19cQ==} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -2318,6 +2344,10 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -2358,6 +2388,12 @@ packages: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc + coffee-script@1.12.7: + resolution: {integrity: sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==} + engines: {node: '>=0.8.0'} + deprecated: CoffeeScript on NPM has moved to "coffeescript" (no hyphen) + hasBin: true + collapse-white-space@2.1.0: resolution: {integrity: sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==} @@ -2381,12 +2417,21 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + concat-with-sourcemaps@1.1.0: + resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} + + console-stamp@0.2.10: + resolution: {integrity: sha512-HjPHHsUGj5xcwkcwolgBg9SxhVqLzktH16GmvGsdZJ+FJPNq+xr+wSdYh8744JEAbCkJ0pNJuDN+34Bx14vERg==} + convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} copy-to-clipboard@3.3.3: resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} @@ -2482,6 +2527,10 @@ packages: date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + dateformat@1.0.11: + resolution: {integrity: sha512-5zcI+Qoul0QgiCcjzsobs9G1c+vHCNaYB2NGa57ZbVnP7bZeKJJgoM/K+I/obaHAmyEL0J8hJafbQ+HFSZnzZA==} + hasBin: true + debug@4.4.0: resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} @@ -2628,6 +2677,10 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -2727,6 +2780,10 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} @@ -2804,6 +2861,9 @@ packages: front-matter@4.0.2: resolution: {integrity: sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==} + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -2840,6 +2900,10 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} + get-stdin@9.0.0: + resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} + engines: {node: '>=12'} + get-symbol-description@1.1.0: resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} engines: {node: '>= 0.4'} @@ -2858,6 +2922,10 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -2880,6 +2948,18 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + gray-matter@2.1.1: + resolution: {integrity: sha512-vbmvP1Fe/fxuT2QuLVcqb2BfK7upGhhbLIt9/owWEvPYrZZEkelLcq2HqzxosV+PQ67dUFLaAeNpH7C4hhICAA==} + engines: {node: '>=0.10.0'} + + gulp-header@1.8.12: + resolution: {integrity: sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ==} + deprecated: Removed event-stream from gulp-header + + has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + has-bigints@1.1.0: resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} engines: {node: '>= 0.4'} @@ -2976,6 +3056,16 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inline-style-parser@0.2.4: resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} @@ -3024,6 +3114,9 @@ packages: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} + is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} @@ -3043,6 +3136,10 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -3117,6 +3214,9 @@ packages: resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} engines: {node: '>= 0.4'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -3186,10 +3286,18 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + kysely@0.28.5: resolution: {integrity: sha512-rlB0I/c6FBDWPcQoDtkxi9zIvpmnV5xoIalfCMSMCa7nuA6VGA3F54TW9mEgX4DVf10sXAWCF5fDbamI/5ZpKA==} engines: {node: '>=20.0.0'} + lazy-cache@2.0.2: + resolution: {integrity: sha512-7vp2Acd2+Kz4XkzxGxaB1FWOi8KjWIWsgdfD5MCb86DWvlLqhRPM+d6Pro3iNEL5VT9mstz5hKAlcd+QR6H3aA==} + engines: {node: '>=0.10.0'} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -3262,9 +3370,19 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash._reinterpolate@3.0.0: + resolution: {integrity: sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.template@4.5.0: + resolution: {integrity: sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==} + deprecated: This package is deprecated. Use https://socket.dev/npm/package/eta instead. + + lodash.templatesettings@4.2.0: + resolution: {integrity: sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==} + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -3364,6 +3482,10 @@ packages: mdn-data@2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + meow@14.0.0: + resolution: {integrity: sha512-JhC3R1f6dbspVtmF3vKjAWz1EVIvwFrGGPLSdU6rK79xBwHWTuHoLnRX/t1/zHS1Ch1Y2UtIrih7DAHuH9JFJA==} + engines: {node: '>=20'} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -3488,6 +3610,9 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -3677,6 +3802,9 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + oniguruma-parser@0.12.1: resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==} @@ -3713,6 +3841,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -3720,6 +3852,9 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path@0.12.7: + resolution: {integrity: sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -3837,6 +3972,13 @@ packages: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -3948,6 +4090,9 @@ packages: resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} engines: {node: '>=0.10.0'} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readdirp@4.1.2: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} @@ -4035,6 +4180,11 @@ packages: remark-stringify@11.0.0: resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + remarkable@1.7.4: + resolution: {integrity: sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg==} + engines: {node: '>= 0.10.0'} + hasBin: true + reselect@5.1.1: resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} @@ -4077,6 +4227,9 @@ packages: resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-push-apply@1.0.0: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} @@ -4128,6 +4281,10 @@ packages: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} + set-getter@0.1.1: + resolution: {integrity: sha512-9sVWOy+gthr+0G9DzqqLaYNA7+5OKkSmcqjL9cBpDEaZrr3ShQlyX2cZ/O/ozE41oxn/Tt0LGEM/w4Rub3A3gw==} + engines: {node: '>=0.10.0'} + set-harmonic-interval@1.0.1: resolution: {integrity: sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==} engines: {node: '>=6.9'} @@ -4170,6 +4327,10 @@ packages: simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + sonner@2.0.7: resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} peerDependencies: @@ -4229,9 +4390,16 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -4281,6 +4449,10 @@ packages: stylis@4.3.6: resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -4315,6 +4487,9 @@ packages: resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} engines: {node: '>=10'} + through2@2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -4329,6 +4504,10 @@ packages: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true + to-object-path@0.3.0: + resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==} + engines: {node: '>=0.10.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4336,6 +4515,9 @@ packages: toggle-selection@1.0.6: resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + toml@2.3.6: + resolution: {integrity: sha512-gVweAectJU3ebq//Ferr2JUY4WKSDe5N+z0FvjDncLGyHmIDoxgY/2Ie4qfEIDm4IS7OA6Rmdm7pdEEdMcV/xQ==} + tough-cookie@5.1.2: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} @@ -4510,6 +4692,9 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + util@0.10.4: + resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -4627,6 +4812,9 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.18.2: resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==} engines: {node: '>=10.0.0'} @@ -4646,6 +4834,10 @@ packages: xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -6447,6 +6639,17 @@ snapshots: acorn@8.15.0: {} + adr-log@2.2.0: + dependencies: + console-stamp: 0.2.10 + glob: 7.2.3 + gray-matter: 2.1.1 + lazy-cache: 2.0.2 + minimist: 1.2.8 + path: 0.12.7 + remarkable: 1.7.4 + slash: 3.0.0 + agent-base@7.1.3: {} ajv@6.12.6: @@ -6456,14 +6659,24 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ansi-red@0.1.1: + dependencies: + ansi-wrap: 0.1.0 + + ansi-regex@2.1.1: {} + ansi-regex@5.0.1: {} + ansi-styles@2.2.1: {} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 ansi-styles@5.2.0: {} + ansi-wrap@0.1.0: {} + arg@4.1.3: {} argparse@1.0.10: @@ -6547,6 +6760,10 @@ snapshots: async-function@1.0.0: {} + autolinker@0.28.1: + dependencies: + gulp-header: 1.8.12 + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -6623,6 +6840,14 @@ snapshots: ccount@2.0.1: {} + chalk@1.1.3: + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -6662,6 +6887,8 @@ snapshots: - '@types/react' - '@types/react-dom' + coffee-script@1.12.7: {} + collapse-white-space@2.1.0: {} color-convert@2.0.1: @@ -6686,12 +6913,23 @@ snapshots: concat-map@0.0.1: {} + concat-with-sourcemaps@1.1.0: + dependencies: + source-map: 0.6.1 + + console-stamp@0.2.10: + dependencies: + chalk: 1.1.3 + dateformat: 1.0.11 + convert-source-map@2.0.0: {} copy-to-clipboard@3.3.3: dependencies: toggle-selection: 1.0.6 + core-util-is@1.0.3: {} + create-require@1.1.1: {} cross-fetch@4.1.0: @@ -6789,6 +7027,11 @@ snapshots: date-fns@4.1.0: {} + dateformat@1.0.11: + dependencies: + get-stdin: 9.0.0 + meow: 14.0.0 + debug@4.4.0: dependencies: ms: 2.1.3 @@ -7010,6 +7253,8 @@ snapshots: escalade@3.2.0: {} + escape-string-regexp@1.0.5: {} + escape-string-regexp@4.0.0: {} escape-string-regexp@5.0.0: {} @@ -7154,6 +7399,10 @@ snapshots: eventemitter3@5.0.1: {} + extend-shallow@2.0.1: + dependencies: + is-extendable: 0.1.1 + extend@3.0.2: {} fast-deep-equal@3.1.3: {} @@ -7227,6 +7476,8 @@ snapshots: dependencies: js-yaml: 3.14.1 + fs.realpath@1.0.0: {} + fsevents@2.3.2: optional: true @@ -7268,6 +7519,8 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-stdin@9.0.0: {} + get-symbol-description@1.1.0: dependencies: call-bound: 1.0.4 @@ -7288,6 +7541,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + globals@14.0.0: {} globals@16.3.0: {} @@ -7303,6 +7565,24 @@ snapshots: graphemer@1.4.0: {} + gray-matter@2.1.1: + dependencies: + ansi-red: 0.1.1 + coffee-script: 1.12.7 + extend-shallow: 2.0.1 + js-yaml: 3.14.1 + toml: 2.3.6 + + gulp-header@1.8.12: + dependencies: + concat-with-sourcemaps: 1.1.0 + lodash.template: 4.5.0 + through2: 2.0.5 + + has-ansi@2.0.0: + dependencies: + ansi-regex: 2.1.1 + has-bigints@1.1.0: {} has-flag@4.0.0: {} @@ -7439,6 +7719,15 @@ snapshots: indent-string@4.0.0: {} + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.3: {} + + inherits@2.0.4: {} + inline-style-parser@0.2.4: {} inline-style-prefixer@7.0.1: @@ -7498,6 +7787,8 @@ snapshots: call-bound: 1.0.4 has-tostringtag: 1.0.2 + is-buffer@1.1.6: {} + is-callable@1.2.7: {} is-core-module@2.16.1: @@ -7517,6 +7808,8 @@ snapshots: is-decimal@2.0.1: {} + is-extendable@0.1.1: {} + is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -7588,6 +7881,8 @@ snapshots: call-bound: 1.0.4 get-intrinsic: 1.3.0 + isarray@1.0.0: {} + isarray@2.0.5: {} isexe@2.0.0: {} @@ -7668,8 +7963,16 @@ snapshots: dependencies: json-buffer: 3.0.1 + kind-of@3.2.2: + dependencies: + is-buffer: 1.1.6 + kysely@0.28.5: {} + lazy-cache@2.0.2: + dependencies: + set-getter: 0.1.1 + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -7724,8 +8027,19 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash._reinterpolate@3.0.0: {} + lodash.merge@4.6.2: {} + lodash.template@4.5.0: + dependencies: + lodash._reinterpolate: 3.0.0 + lodash.templatesettings: 4.2.0 + + lodash.templatesettings@4.2.0: + dependencies: + lodash._reinterpolate: 3.0.0 + lodash@4.17.21: {} longest-streak@3.1.0: {} @@ -7927,6 +8241,8 @@ snapshots: mdn-data@2.0.14: {} + meow@14.0.0: {} + merge2@1.4.1: {} micromark-core-commonmark@2.0.3: @@ -8208,6 +8524,8 @@ snapshots: dependencies: brace-expansion: 2.0.2 + minimist@1.2.8: {} + minipass@7.1.2: {} minizlib@3.0.2: @@ -8379,6 +8697,10 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + once@1.4.0: + dependencies: + wrappy: 1.0.2 + oniguruma-parser@0.12.1: {} oniguruma-to-es@4.3.3: @@ -8430,10 +8752,17 @@ snapshots: path-exists@4.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-parse@1.0.7: {} + path@0.12.7: + dependencies: + process: 0.11.10 + util: 0.10.4 + picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -8489,6 +8818,10 @@ snapshots: ansi-styles: 5.2.0 react-is: 17.0.2 + process-nextick-args@2.0.1: {} + + process@0.11.10: {} + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -8593,6 +8926,16 @@ snapshots: react@19.1.1: {} + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readdirp@4.1.2: {} recharts@3.1.2(react-dom@19.1.1(react@19.1.1))(react-is@18.3.1)(react@19.1.1)(redux@5.0.1)(types-react@19.0.0-rc.1): @@ -8762,6 +9105,11 @@ snapshots: mdast-util-to-markdown: 2.1.2 unified: 11.0.5 + remarkable@1.7.4: + dependencies: + argparse: 1.0.10 + autolinker: 0.28.1 + reselect@5.1.1: {} resize-observer-polyfill@1.5.1: {} @@ -8824,6 +9172,8 @@ snapshots: has-symbols: 1.1.0 isarray: 2.0.5 + safe-buffer@5.1.2: {} + safe-push-apply@1.0.0: dependencies: es-errors: 1.3.0 @@ -8879,6 +9229,10 @@ snapshots: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 + set-getter@0.1.1: + dependencies: + to-object-path: 0.3.0 + set-harmonic-interval@1.0.1: {} set-proto@1.0.0: @@ -8967,6 +9321,8 @@ snapshots: is-arrayish: 0.3.2 optional: true + slash@3.0.0: {} + sonner@2.0.7(react-dom@19.1.1(react@19.1.1))(react@19.1.1): dependencies: react: 19.1.1 @@ -9045,11 +9401,19 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 character-entities-legacy: 3.0.0 + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -9088,6 +9452,8 @@ snapshots: stylis@4.3.6: {} + supports-color@2.0.0: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 @@ -9117,6 +9483,11 @@ snapshots: throttle-debounce@3.0.1: {} + through2@2.0.5: + dependencies: + readable-stream: 2.3.8 + xtend: 4.0.2 + tiny-invariant@1.3.3: {} tinyglobby@0.2.14: @@ -9130,12 +9501,18 @@ snapshots: dependencies: tldts-core: 6.1.86 + to-object-path@0.3.0: + dependencies: + kind-of: 3.2.2 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 toggle-selection@1.0.6: {} + toml@2.3.6: {} + tough-cookie@5.1.2: dependencies: tldts: 6.1.86 @@ -9339,6 +9716,10 @@ snapshots: util-deprecate@1.0.2: {} + util@0.10.4: + dependencies: + inherits: 2.0.3 + v8-compile-cache-lib@3.0.1: {} valibot@1.0.0-beta.15(typescript@5.9.2): @@ -9471,12 +9852,16 @@ snapshots: word-wrap@1.2.5: {} + wrappy@1.0.2: {} + ws@8.18.2: {} xml-name-validator@5.0.0: {} xmlchars@2.2.0: {} + xtend@4.0.2: {} + yallist@3.1.1: {} yallist@5.0.0: {} From 92724730d835ac58149cefca087fcb64af426558 Mon Sep 17 00:00:00 2001 From: Dercraker Date: Sun, 5 Oct 2025 21:32:07 +0200 Subject: [PATCH 03/12] WIP Architecture --- .vscode/keybindings.nowts.json | 25 --- .../Guidelines/architecture/Architecture.md | 17 +- .../architecture/projectTreeFolder.md | 186 ++++++++++++++++++ README.md | 2 +- 4 files changed, 203 insertions(+), 27 deletions(-) delete mode 100644 .vscode/keybindings.nowts.json create mode 100644 Documentation/Guidelines/architecture/projectTreeFolder.md diff --git a/.vscode/keybindings.nowts.json b/.vscode/keybindings.nowts.json deleted file mode 100644 index 691d28c..0000000 --- a/.vscode/keybindings.nowts.json +++ /dev/null @@ -1,25 +0,0 @@ -[ - { - "INFO": "Here is the keybidding I use for VSCode. You can copy/past them in your key binding file.", - "TUTO1": "Use CMD + SHIFT + P to open the command palette and search for 'keybinding' to open the keybinding file.", - "TUTO2": "Choose 'Open Keyboard Shortcuts (JSON)' settings." - }, - { - "key": "shift+cmd+r", - "command": "editor.action.rename", - "when": "editorHasRenameProvider && editorTextFocus && !editorReadonly" - }, - { - "key": "shift+cmd+o", - "command": "editor.action.organizeImports", - "when": "editorTextFocus && !editorReadonly && supportedCodeAction =~ /(\\s|^)source\\.organizeImports\\b/" - }, - { - "key": "shift+cmd+i", - "command": "editor.action.sourceAction", - "args": { - "kind": "source.addMissingImports", - "apply": "first" - } - } -] diff --git a/Documentation/Guidelines/architecture/Architecture.md b/Documentation/Guidelines/architecture/Architecture.md index 6c396a0..df2de34 100644 --- a/Documentation/Guidelines/architecture/Architecture.md +++ b/Documentation/Guidelines/architecture/Architecture.md @@ -25,6 +25,21 @@ Non-functional requirement for the project are: | Reliability | Mean time to recovery | System should be able to recover from failure under 5 mins | | Usability | Usability can be described as the capacity of a system to provide a condition for its users to perform the tasks safely, effectively, and efficiently while enjoying the experience | Browsers: Chrome, IE, Firefox | -# Architecture Decision Records +## Folder Structure + +The folder structure of repository is as follows: [tree](./projectTreeFolder.md) + +### Logic structure of folders + +- **App/** : The main folder for routing and page rendering. + - **Top level folders** : Top-level files are used to configure your application, manage dependencies, run middleware, integrate monitoring tools, and define environment variables. [NextJs documentation](https://nextjs.org/docs/app/getting-started/project-structure#folder-and-file-conventions) + - **[locale]/** : The folder for the locale pages. + - **(name)/** : Groupe of pages related to the same theme. + - **page, layout, loading, error, not-found** : The main page component. + - **pathName/** : Folder to add new path url for the page. + - **page, layout, loading, error, not-found** : The page component. + - **\_components** : The components folder for page only. + +## Architecture Decision Records All ADRs are stored in the [ADR](./ADR) folder and referenced in the [ADRs.md](./ADRs.md) file. diff --git a/Documentation/Guidelines/architecture/projectTreeFolder.md b/Documentation/Guidelines/architecture/projectTreeFolder.md new file mode 100644 index 0000000..76ac568 --- /dev/null +++ b/Documentation/Guidelines/architecture/projectTreeFolder.md @@ -0,0 +1,186 @@ +# Project Folder Structure + +Here is the folder structure of the repository. +You can find all informations for each folder + +--- + +# Root + +- **.env.sample** — Template for environment variables. + → Keep it updated, never include real secrets. + +- **.github/workflows/** — GitHub Actions CI/CD Pipeline + - **build.yml** — Deploy pipeline (build/test/deploy). + +- **.nvmrc** — Node.js version to use. + +- **.prettierrc** — Code formatting rules. + → Works alongside ESLint. + +- **.vscode/** — Shared editor config (snippets, settings, extensions). + +- **Documentation/Guidelines/** — Internal documentation (conventions, processes, ADRs, etc.). + → Store common "how-to" workflows (release, i18n, contribution). + +- **LICENSE** — Project license. + +- **Makefile** — Development shortcuts (e.g., `make dev`, `make build`). + +- **README.md** — Project overview, quickstart, useful links. + +- **components.json** — Config for shadcn/ui component generator. + +- **eslint.config.mjs** — ESLint rules (TS/React/Next). + +- **middleware.ts (root)** — Global Next.js middleware (e.g., i18n, redirects). + → Runs before `app/`. + +- **next.config.ts / next-env.d.ts** — Next.js & TypeScript configs. + +- **package.json / pnpm-lock.yaml** — Dependencies & scripts. + → Project is PNPM-first. + +- **postcss.config.mjs** — Tailwind/PostCSS pipeline config. + +- **tsconfig.json** — TypeScript config, path aliases, strict mode. + +--- + +# app/ (Next.js App Router) + +**Purpose**: Handles routing, layouts, error boundaries, and providers. + +- **app/layout.tsx** — Root layout (html, body, theme, fonts). +- **app/error.tsx / global-error.tsx** — Error boundaries. +- **app/unauthorized.tsx** — Generic 401 page. +- **app/favicon.ico / icon.png / apple-icon.png** — PWA icons. +- **app/sitemap.tsx / manifest.ts** — SEO + PWA manifest. + +## Internationalization & segments + +- **app/[locale]/** — Locale-based segment (`en`, `fr`, …). + - **(landing)/page.tsx** — Landing page per locale. + - **(layout)/…** — Shared static pages: + - **about/page.tsx** — About page + - **legal/privacy/page.tsx** — Privacy policy + - **legal/terms/page.tsx** — Terms & conditions + - **news/** — News listing and detail: + - **page.tsx** — Listing + - **[slug]/page.tsx** — Single article + - **loading.tsx / error.tsx / not-found.tsx** — States + - **newsSlugMetadataImage.tsx** — Dynamic OG image + + - **not-found/page.tsx** — Segment-specific 404 + + - **(logged-in)/** — Protected pages after auth: + **error.tsx / not-found.tsx / unauthorized.tsx** — States + - **@modal/** — Parallel route slot for modals: + **[...catchAll]/page.tsx** + **default.tsx** — “Intercepted routes” pattern + - **docs/** — Documentation UI: + - **layout.tsx / page.tsx** — Docs shell + - **[slug]/page.tsx** — Dynamic doc pages + - **\_components/doc-sidebar.tsx** — Docs sidebar + - **doc-manager.ts** — Loader/parsing logic + + - **globals.css** — Global styles (reset, design tokens) + - **layout.tsx / providers.tsx / not-found.tsx** — Locale-level layout & context + +--- + +# content/ (Editorial content) + +- **content/news/en|fr/\*.mdx** — News articles (per language). + → Parsed and displayed via `features/news`. + +--- + +# public/ (Static assets) + +- **public/images/** — Static images (logos, backgrounds, illustrations). +- **public/\*.svg** — Icons/illustrations (e.g., news categories). + → Served directly (`/images/...`). + +--- + +# messages/ (i18n dictionaries) + +- **en.json / fr.json** — Translation keys. + → Consumed by `src/i18n` + UI components (`LocaleSwitcher`). + +--- + +# docker/ + +- **Dockerfile.dev / Dockerfile.prod** — Dev vs production Next.js images. +- **docker-compose.yml** — Local/preview orchestration. + +--- + +# src/ (Application code) + +## src/components/ (Reusable UI) + +- **DS/** — DyingStar Design System (custom components): + - **layout/** — Layouts (header, footer, base) + - **CTA/** — Call-to-action blocks + - **legal/** — Floating legal footer + - Utilities: **divider.tsx, grid-background.tsx, loader.tsx, logo.tsx, typography.tsx** + +- **ui/** — shadcn/ui components (buttons, inputs, modals, tables, tabs, etc.). +- **svg/** — React components for SVGs. +- **utils/** — Visual helpers (`tailwind-indicator`, `intercept-dialog`). + +## src/features/ (Vertical features) + +- **dialog-manager/** — Global dialog system (store, factory, renderer, types). +- **form/** — Form UX (auto-save, submit button). +- **global-dialog/** — Global dialogs + store (e.g., org plan modal). +- **i18n/** — Language switcher UI. +- **landing/** — Landing page sections (CTA, layout). +- **markdown/** — Markdown/MDX rendering (client/server, config). +- **navigation/** — Navigation model & rendering (links, wrapper, types). +- **news/** — News feature (items, reading time, manager). +- **page/** — Error/state pages + top loader. +- **server-sonner/** — Server-to-client toasts. + +## src/hooks/ + +Cross-cutting React hooks: + +- **useDebounceFn**, **useIsClient**, **useMobile**, **useWarnIfUnsavedChanges**, **useCurrentPath**. + +## src/i18n/ + +- **config.ts / routing.ts / navigation.ts / request.ts** — Core i18n utilities (locale detection, localized routes, helpers). + +## src/lib/ + +- **actions/** — Safe server actions (`safe-actions.ts`, utils). +- **env/** — Zod validation for environment variables (client & server). +- **errors/** — App error types (ActionError, ApplicationError, ZodRouteError). +- **format/** — Helpers (date, display-name, id). +- **logger.ts** — Logging utility. +- **metadata.ts** — Page metadata generator (SEO/OG). +- **server-toast.tsx** — Bridge server → client toasts. +- **server-url.ts** — Server-side base URL. +- **utils.ts** — General utilities. +- **zod-route.ts** — Route schema/validation. + +## src/middleware.ts + +Additional middleware specific to `src` (if not root). + +## src/site-config.ts + +Central site configuration (name, links, social, feature flags). + +## src/types/ + +- **next.ts** — Next.js custom/extended types. + +--- + +# Docs pipeline (summary) + +- **content/news/** (MDX) → **features/markdown** (parsing) → **features/news/news-manager.ts** (loading, mapping, reading time) → **app/[locale]/(layout)/news/** (UI pages). diff --git a/README.md b/README.md index 66133db..b21962f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Here you'll find all the documents you need to collaborate on the project. | ---------------------------------------------------------------------------- | ------------------------------------------------------------------ | | [Onboarding](Documentation\Guidelines\Onboarding.md) | Documents related to new developer onboarding | | [Development Process](Documentation\Guidelines\Development-Process.md) | Documents related to development process | -| [Architecture](Documentation\Guidelines\architecture\Architecture.md) | Documents related to architecture | +| [Architecture](Documentation\Guidelines\architecture\Architecture.md) | Documents related to architecture and Technical choices | | [Code Review Process](Documentation\Guidelines\Code-Review-Process.md) | Documents related to code review process, definition of ready/done | | [Release and Deployment](Documentation\Guidelines\Release-And-Deployment.md) | Documents related to release and deployment | From 373e43683e12b9dcdc37a7cff925fe3c31b2b600 Mon Sep 17 00:00:00 2001 From: Dercraker Date: Mon, 6 Oct 2025 21:24:05 +0200 Subject: [PATCH 04/12] Archi --- .../Guidelines/architecture/Architecture.md | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/Documentation/Guidelines/architecture/Architecture.md b/Documentation/Guidelines/architecture/Architecture.md index df2de34..644b9f5 100644 --- a/Documentation/Guidelines/architecture/Architecture.md +++ b/Documentation/Guidelines/architecture/Architecture.md @@ -25,20 +25,30 @@ Non-functional requirement for the project are: | Reliability | Mean time to recovery | System should be able to recover from failure under 5 mins | | Usability | Usability can be described as the capacity of a system to provide a condition for its users to perform the tasks safely, effectively, and efficiently while enjoying the experience | Browsers: Chrome, IE, Firefox | -## Folder Structure +## Folder and File structure The folder structure of repository is as follows: [tree](./projectTreeFolder.md) ### Logic structure of folders -- **App/** : The main folder for routing and page rendering. - - **Top level folders** : Top-level files are used to configure your application, manage dependencies, run middleware, integrate monitoring tools, and define environment variables. [NextJs documentation](https://nextjs.org/docs/app/getting-started/project-structure#folder-and-file-conventions) - - **[locale]/** : The folder for the locale pages. - - **(name)/** : Groupe of pages related to the same theme. - - **page, layout, loading, error, not-found** : The main page component. - - **pathName/** : Folder to add new path url for the page. - - **page, layout, loading, error, not-found** : The page component. - - **\_components** : The components folder for page only. +############# +TODO : +Il faudrait reprendre la doc de nextjs pour la structure des folders +Ajouter des liens pour chaques folders +############# + +### Files Types and conventions + +- **\*.mdx** - utiliser pour les pages ayant du rendu markdown exemple : news + links +- **\*.ts** - Fichier de logique pure +- **\*.type.ts** - Permet de définir des types et schema avec zod +- **\*.hook.ts** - Permet de définir des hooks react qui ne sont pas implicitement dans le dossier hooks +- **\*.link.ts** - Logique localisée des liens de navigation +- **\*.query.ts** - query prisma +- **\*query.hook.ts** - query tanstack +- **\*mutation.hook.ts** - mutation tanstack +- **\*.tsx** - Fichier contenant les composants react + .... ## Architecture Decision Records From 1059eff4ca5e5c6919dafba8e21e714b7348a448 Mon Sep 17 00:00:00 2001 From: Dercraker Date: Wed, 8 Oct 2025 22:51:50 +0200 Subject: [PATCH 05/12] update --- ...Code-Review-Process.md => CodeReviewProcess.md} | 0 ...evelopment-Process.md => DevelopmentProcess.md} | 0 ...e-And-Deployment.md => ReleaseAndDeployment.md} | 0 README.md | 14 +++++++------- 4 files changed, 7 insertions(+), 7 deletions(-) rename Documentation/Guidelines/{Code-Review-Process.md => CodeReviewProcess.md} (100%) rename Documentation/Guidelines/{Development-Process.md => DevelopmentProcess.md} (100%) rename Documentation/Guidelines/{Release-And-Deployment.md => ReleaseAndDeployment.md} (100%) diff --git a/Documentation/Guidelines/Code-Review-Process.md b/Documentation/Guidelines/CodeReviewProcess.md similarity index 100% rename from Documentation/Guidelines/Code-Review-Process.md rename to Documentation/Guidelines/CodeReviewProcess.md diff --git a/Documentation/Guidelines/Development-Process.md b/Documentation/Guidelines/DevelopmentProcess.md similarity index 100% rename from Documentation/Guidelines/Development-Process.md rename to Documentation/Guidelines/DevelopmentProcess.md diff --git a/Documentation/Guidelines/Release-And-Deployment.md b/Documentation/Guidelines/ReleaseAndDeployment.md similarity index 100% rename from Documentation/Guidelines/Release-And-Deployment.md rename to Documentation/Guidelines/ReleaseAndDeployment.md diff --git a/README.md b/README.md index b21962f..4c844a7 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ Here you'll find all the documents you need to collaborate on the project. -| Topic | Description | -| ---------------------------------------------------------------------------- | ------------------------------------------------------------------ | -| [Onboarding](Documentation\Guidelines\Onboarding.md) | Documents related to new developer onboarding | -| [Development Process](Documentation\Guidelines\Development-Process.md) | Documents related to development process | -| [Architecture](Documentation\Guidelines\architecture\Architecture.md) | Documents related to architecture and Technical choices | -| [Code Review Process](Documentation\Guidelines\Code-Review-Process.md) | Documents related to code review process, definition of ready/done | -| [Release and Deployment](Documentation\Guidelines\Release-And-Deployment.md) | Documents related to release and deployment | +| Topic | Description | +| -------------------------------------------------------------------------- | ------------------------------------------------------------------ | +| [Onboarding](Documentation/Guidelines/Onboarding.md) | Documents related to new developer onboarding | +| [Development Process](Documentation/Guidelines/DevelopmentProcess.md) | Documents related to development process | +| [Architecture](Documentation/Guidelines/architecture/Architecture.md) | Documents related to architecture and Technical choices | +| [Code Review Process](Documentation/Guidelines/CodeReviewProcess.md) | Documents related to code review process, definition of ready/done | +| [Release and Deployment](Documentation/Guidelines/ReleaseAndDeployment.md) | Documents related to release and deployment | **NB** : Got an idea ? Or a suggestion ? Feel free to open an issue or contact one of our developers. From b57e07527a87e6071c1b15cbc186136cd641957a Mon Sep 17 00:00:00 2001 From: Dercraker Date: Fri, 10 Oct 2025 00:54:50 +0200 Subject: [PATCH 06/12] Add files and folder --- .../Guidelines/architecture/Architecture.md | 26 +- .../Guidelines/architecture/FileTypes.md | 984 ++++++++++++++++++ 2 files changed, 1000 insertions(+), 10 deletions(-) create mode 100644 Documentation/Guidelines/architecture/FileTypes.md diff --git a/Documentation/Guidelines/architecture/Architecture.md b/Documentation/Guidelines/architecture/Architecture.md index 644b9f5..0936351 100644 --- a/Documentation/Guidelines/architecture/Architecture.md +++ b/Documentation/Guidelines/architecture/Architecture.md @@ -39,16 +39,22 @@ Ajouter des liens pour chaques folders ### Files Types and conventions -- **\*.mdx** - utiliser pour les pages ayant du rendu markdown exemple : news + links -- **\*.ts** - Fichier de logique pure -- **\*.type.ts** - Permet de définir des types et schema avec zod -- **\*.hook.ts** - Permet de définir des hooks react qui ne sont pas implicitement dans le dossier hooks -- **\*.link.ts** - Logique localisée des liens de navigation -- **\*.query.ts** - query prisma -- **\*query.hook.ts** - query tanstack -- **\*mutation.hook.ts** - mutation tanstack -- **\*.tsx** - Fichier contenant les composants react - .... +For a comprehensive guide to file types and naming conventions, see [FileTypes](./FileTypes.md). + +Quick reference: + +- **\*.mdx** - Markdown with JSX for content-driven pages (news) +- **\*.ts** - Pure TypeScript logic (utilities, configs, helpers) +- **\*.type.ts** - Type definitions and Zod validation schemas +- **\*.hook.ts** - Feature-specific React hooks (co-located with features) +- **\*.link.ts** - Navigation link definitions and logic +- **\*.query.ts** - Prisma database queries +- **\*.query.hook.ts** - TanStack Query hooks for data fetching +- **\*.mutation.hook.ts** - TanStack Query hooks for mutations +- **\*.action.ts** - Next.js Server Actions +- **\*.tsx** - React components with JSX + +See the [detailed documentation](./FileTypes.md) for examples, usage patterns, and best practices. ## Architecture Decision Records diff --git a/Documentation/Guidelines/architecture/FileTypes.md b/Documentation/Guidelines/architecture/FileTypes.md new file mode 100644 index 0000000..ba0cc67 --- /dev/null +++ b/Documentation/Guidelines/architecture/FileTypes.md @@ -0,0 +1,984 @@ +# File Types and Naming Conventions + +## Overview + +This document provides a comprehensive guide to the file naming conventions and architectural patterns used throughout the DyingStar codebase. Each file type serves a specific purpose and follows strict conventions to maintain code organization, readability, and maintainability. + +--- + +## Table of Contents + +1. [File Type Reference](#file-type-reference) +2. [Detailed Explanations](#detailed-explanations) +3. [Directory Structure Patterns](#directory-structure-patterns) +4. [Path Aliases](#path-aliases) +5. [Best Practices](#best-practices) + +--- + +## File Type Reference + +Quick reference table for all file types: + +| Extension/Pattern | Purpose | Location | Example | +| -------------------- | --------------------------------------------------- | ------------------------------------------ | ---------------------------------- | +| `*.tsx` | React components with JSX | `src/components/`, `src/features/`, `app/` | `button.tsx`, `header.tsx` | +| `*.ts` | Pure TypeScript logic (utilities, configs, helpers) | `src/lib/`, `src/hooks/`, `src/i18n/` | `utils.ts`, `logger.ts` | +| `*.type.ts` | Type definitions and Zod schemas | Any `src/` subdirectory | `navigation.type.ts` | +| `*.hook.ts` | Custom React hooks (outside `src/hooks/`) | `src/features/*/` | `use-news-filter.hook.ts` | +| `*.link.ts` | Navigation link logic and definitions | `src/features/navigation/` | `footer.link.tsx`, `Links.ts` | +| `*.query.ts` | Prisma database queries | `src/lib/queries/` | `user.query.ts` | +| `*.query.hook.ts` | TanStack Query (React Query) queries | `src/features/*/` | `news.query.hook.ts` | +| `*.mutation.hook.ts` | TanStack Query mutations | `src/features/*/` | `create-user.mutation.hook.ts` | +| `*.action.ts` | Server actions (Next.js Server Actions) | `src/lib/actions/` | `newsletter.action.ts` | +| `*.mdx` | Markdown with JSX for content-driven pages | `content/news/`, `app/` | `demo.mdx` | +| `*.config.ts` | Configuration files | Root, `src/i18n/` | `next.config.ts`, `site-config.ts` | +| `middleware.ts` | Next.js middleware (routing, i18n, auth) | Root, `src/` | `middleware.ts` | +| `layout.tsx` | Next.js layouts | `app/` segments | `layout.tsx` | +| `page.tsx` | Next.js pages/routes | `app/` segments | `page.tsx` | +| `loading.tsx` | Next.js loading UI | `app/` segments | `loading.tsx` | +| `error.tsx` | Next.js error boundaries | `app/` segments | `error.tsx`, `global-error.tsx` | +| `not-found.tsx` | Next.js 404 pages | `app/` segments | `not-found.tsx` | +| `route.ts` | Next.js API routes | `app/api/` | `route.ts` | + +--- + +## Detailed Explanations + +### 1. `*.tsx` - React Components + +**Purpose**: Files containing React components that use JSX syntax. + +**Location**: + +- `src/components/` - Reusable UI components +- `src/features/` - Feature-specific components +- `app/` - Next.js App Router pages and layouts + +**Conventions**: + +- Use PascalCase for component names +- Use camelCase for file names +- One primary component per file +- Export component and related types + +**Example**: + +```tsx +// src/components/ui/button.tsx +import * as React from "react"; + +import { cn } from "@lib/utils"; +import { Slot } from "@radix-ui/react-slot"; +import { type VariantProps, cva } from "class-variance-authority"; + +const buttonVariants = cva("justify-center... inline-flex items-center", { + variants: { + variant: { + default: "bg-primary text-primary-foreground...", + destructive: "bg-destructive text-white...", + }, + size: { + default: "px-6 py-2", + sm: "px-5 py-2", + }, + }, +}); + +export type ButtonProps = React.ComponentProps<"button"> & + VariantProps & { + asChild?: boolean; + }; + +function Button({ + className, + variant, + size, + asChild = false, + ...props +}: ButtonProps) { + const Comp = asChild ? Slot : "button"; + return ( + + ); +} + +export { Button, buttonVariants }; +``` + +**Usage Scenarios**: + +- UI components (buttons, inputs, cards) +- Layout components (headers, footers, sidebars) +- Feature components (news items, forms, dialogs) +- Page components in the App Router + +--- + +### 2. `*.ts` - Pure TypeScript Logic + +**Purpose**: Pure TypeScript files without JSX, containing business logic, utilities, configurations, or helper functions. + +**Location**: + +- `src/lib/` - Core utilities and libraries +- `src/hooks/` - React hooks +- `src/i18n/` - Internationalization logic +- Root directory - Configuration files + +**Conventions**: + +- Use camelCase for file names (except configs) +- Pure functions without side effects (when possible) +- No React or JSX imports +- Thoroughly documented with JSDoc + +**Example**: + +```ts +// src/lib/utils.ts +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +/** + * Combines class names using clsx and merges Tailwind classes + */ +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} +``` + +**Usage Scenarios**: + +- Utility functions (`utils.ts`, `format.ts`) +- Configuration (`site-config.ts`, `routing.ts`) +- Non-React helpers (`logger.ts`, `server-url.ts`) + +--- + +### 3. `*.type.ts` - Type Definitions and Schemas + +**Purpose**: Dedicated files for TypeScript type definitions and Zod validation schemas. This pattern centralizes type safety and runtime validation. + +**Location**: Any `src/` subdirectory, typically alongside related logic + +**Conventions**: + +- Define both Zod schemas and TypeScript types +- Export schemas and infer types from them +- Group related types logically +- Use clear, descriptive region comments + +**Example**: + +```ts +// src/features/navigation/navigation.type.ts + +TODO ADD FILE EXAMPLE + +``` + +**Why This Pattern**: + +- **Type Safety**: Compile-time type checking via TypeScript +- **Runtime Validation**: Zod schemas validate data at runtime +- **Single Source of Truth**: Types are inferred from schemas +- **Documentation**: Schemas serve as self-documenting contracts + +**Usage Scenarios**: + +- API response/request types +- Component prop types +- Database model types +- Form validation schemas + +--- + +### 4. `*.hook.ts` - Custom React Hooks (Feature-Specific) + +**Purpose**: Custom React hooks that are specific to a feature and not general enough to belong in `src/hooks/`. + +**Location**: Within feature directories (`src/features/*/`) + +**Conventions**: + +- File name should match hook name +- Use `use` prefix for hook functions +- Export one primary hook per file +- Include TypeScript types for parameters and return values + +**Example**: + +```ts +// src/features/news/use-news-filter.hook.ts +import { useMemo, useState } from "react"; + +import type { NewsItem } from "./news.type"; + +export function useNewsFilter(items: NewsItem[]) { + const [searchTerm, setSearchTerm] = useState(""); + const [category, setCategory] = useState(null); + + const filteredItems = useMemo(() => { + return items.filter((item) => { + const matchesSearch = item.title + .toLowerCase() + .includes(searchTerm.toLowerCase()); + const matchesCategory = !category || item.category === category; + return matchesSearch && matchesCategory; + }); + }, [items, searchTerm, category]); + + return { + filteredItems, + searchTerm, + setSearchTerm, + category, + setCategory, + }; +} +``` + +**Difference from `src/hooks/`**: + +- `src/hooks/*.ts` - General-purpose, reusable across features +- `*.hook.ts` - Feature-specific, co-located with feature code + +**Usage Scenarios**: + +- Feature-specific state management +- Complex component logic extraction +- Business logic hooks tied to a feature + +--- + +### 5. `*.link.ts` / `*.link.tsx` - Navigation Link Definitions + +**Purpose**: Centralized navigation link definitions and logic, providing type-safe routing throughout the application. + +**Location**: `src/features/navigation/` + +**Conventions**: + +- Define link structure with params +- Use link generator functions for dynamic routes +- Export typed link objects +- Support both static and parameterized links + +**Example**: + +```ts +// src/features/navigation/Links.ts +import { z } from "zod"; + +import type { NavigationLink } from "./navigation.type"; + +const PATHS = { + NEWS: `/news/:newsSlug`, +}; + +export const EmptyLinkParamsSchema = z.object({}).strict(); + +export const NewsLinkParamsSchema = EmptyLinkParamsSchema.extend({ + newsSlug: z.string(), +}).strict(); + +// Utility to create link generators +const createLinkGenerator = (path: string, needsParams = false) => { + if (!needsParams) { + return () => path; + } + + return (params: Record = {}) => { + let result = path; + Object.entries(params).forEach(([key, value]) => { + result = result.replace(`:${key}`, value); + }); + return result; + }; +}; + +const createLink = ( + href: string, + label: string, + options: Partial> = {}, + needsParams = false, +): NavigationLink => ({ + href: createLinkGenerator(href, needsParams), + label, + ...options, +}); + +export const LINKS = { + Landing: { + Landing: createLink("/", "Project", undefined, false), + }, + News: { + All: createLink("/news", "All News", undefined, false), + News: createLink(`${PATHS.NEWS}`, "News", { Icon: Info }, true), + }, +}; +``` + +**Benefits**: + +- Type-safe navigation +- Centralized route definitions +- Easy refactoring (change route in one place) +- Auto-complete for links throughout the app + +**Usage Scenarios**: + +- Navigation menus +- Footer links +- Programmatic navigation +- Link generation with parameters + +--- + +### 6. `*.query.ts` - Prisma Database Queries + +**Purpose**: Encapsulates Prisma database queries in reusable, testable functions. + +**Location**: `src/lib/queries/` or within feature directories + +**Conventions**: + +- One query function per operation +- Use descriptive function names +- Include error handling +- Return typed results + +**Example**: + +```ts +// src/lib/queries/user.query.ts +import { prisma } from "@lib/prisma"; +import type { User } from "@prisma/client"; + +export async function getUserById(userId: string): Promise { + return prisma.user.findUnique({ + where: { id: userId }, + include: { + profile: true, + }, + }); +} + +export async function getUsersByRole(role: string): Promise { + return prisma.user.findMany({ + where: { role }, + orderBy: { createdAt: "desc" }, + }); +} +``` + +**Why Separate Query Files**: + +- **Testability**: Easy to mock in tests +- **Reusability**: Share queries across features +- **Maintainability**: Database logic in one place +- **Performance**: Optimize queries independently + +--- + +### 7. `*.query.hook.ts` - TanStack Query (React Query) + +**Purpose**: React hooks that use TanStack Query for server state management, caching, and synchronization. + +**Location**: Within feature directories + +**Conventions**: + +- Use `useQuery` from TanStack Query +- Define query keys at the top +- Include proper TypeScript types +- Handle loading and error states + +**Example**: + +```ts +// src/features/news/news.query.hook.ts +import { useQuery } from "@tanstack/react-query"; + +import type { NewsItem } from "./news.type"; + +// Query keys +export const newsKeys = { + all: ["news"] as const, + lists: () => [...newsKeys.all, "list"] as const, + list: (filters: string) => [...newsKeys.lists(), { filters }] as const, + details: () => [...newsKeys.all, "detail"] as const, + detail: (slug: string) => [...newsKeys.details(), slug] as const, +}; + +// Fetch function +async function fetchNewsItem(slug: string): Promise { + const res = await fetch(`/api/news/${slug}`); + if (!res.ok) throw new Error("Failed to fetch news"); + return res.json(); +} + +// React Query hook +export function useNewsItem(slug: string) { + return useQuery({ + queryKey: newsKeys.detail(slug), + queryFn: () => fetchNewsItem(slug), + staleTime: 5 * 60 * 1000, // 5 minutes + }); +} +``` + +**Benefits**: + +- Automatic caching +- Background refetching +- Optimistic updates +- Request deduplication + +--- + +### 8. `*.mutation.hook.ts` - TanStack Query Mutations + +**Purpose**: React hooks for data mutations (create, update, delete) using TanStack Query. + +**Location**: Within feature directories + +**Conventions**: + +- Use `useMutation` from TanStack Query +- Include optimistic updates +- Invalidate relevant queries +- Handle success/error callbacks + +**Example**: + +```ts +// src/features/news/create-news.mutation.hook.ts +import { useMutation, useQueryClient } from "@tanstack/react-query"; + +import { newsKeys } from "./news.query.hook"; +import type { CreateNewsInput, NewsItem } from "./news.type"; + +async function createNews(data: CreateNewsInput): Promise { + const res = await fetch("/api/news", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(data), + }); + if (!res.ok) throw new Error("Failed to create news"); + return res.json(); +} + +export function useCreateNews() { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: createNews, + onSuccess: () => { + // Invalidate and refetch news list + queryClient.invalidateQueries({ queryKey: newsKeys.lists() }); + }, + }); +} +``` + +**Usage**: + +```tsx +function CreateNewsForm() { + const createNews = useCreateNews(); + + const handleSubmit = (data: CreateNewsInput) => { + createNews.mutate(data, { + onSuccess: () => { + toast.success("News created!"); + }, + }); + }; + + return

...
; +} +``` + +--- + +### 9. `*.action.ts` - Next.js Server Actions + +**Purpose**: Server-side functions that can be called from client components, providing type-safe RPC-style endpoints. + +**Location**: `src/lib/actions/` or within feature directories + +**Conventions**: + +- Use `"use server"` directive +- Use `next-safe-action` for validation +- Define input schemas with Zod +- Handle errors gracefully + +**Example**: + +```ts +// src/lib/actions/newsletter.action.ts +"use server"; + +import { action } from "@lib/actions/safe-actions"; +import { z } from "zod"; + +// src/lib/actions/newsletter.action.ts + +// src/lib/actions/newsletter.action.ts + +// src/lib/actions/newsletter.action.ts + +// src/lib/actions/newsletter.action.ts + +// src/lib/actions/newsletter.action.ts + +// src/lib/actions/newsletter.action.ts + +// src/lib/actions/newsletter.action.ts + +// src/lib/actions/newsletter.action.ts + +const subscribeNewsletterSchema = z.object({ + email: z.string().email(), + name: z.string().optional(), +}); + +export const subscribeNewsletter = action + .inputSchema(subscribeNewsletterSchema) + .action(async ({ parsedInput: { email, name } }) => { + // Add to newsletter service + await addToMailingList(email, name); + + return { success: true, message: "Successfully subscribed!" }; + }); +``` + +**Usage in Client Component**: + +```tsx +"use client"; + +import { subscribeNewsletter } from "@lib/actions/newsletter.action"; + +export function NewsletterForm() { + const [, execute, isPending] = useAction(subscribeNewsletter); + + const handleSubmit = async (formData: FormData) => { + const result = await execute({ + email: formData.get("email") as string, + }); + + if (result.data?.success) { + toast.success(result.data.message); + } + }; + + return
...
; +} +``` + +**Benefits**: + +- Type-safe client-server communication +- Automatic validation +- No need for API routes for simple operations +- Direct database access from actions + +--- + +### 10. `*.mdx` - Markdown with JSX + +**Purpose**: Content-driven pages that combine Markdown for text content with React components for interactive elements. + +**Location**: + +- `content/news/` - Editorial content (articles, blog posts) +- `app/` - Static/semi-static pages + +**Conventions**: + +- Frontmatter for metadata +- Localized content (separate files per language) +- Use JSX components when needed + +**Example**: + +````mdx +--- +title: Introducing Our New Feature +titleIcon: 🎉 +category: announcement +description: We're excited to announce a new feature that will change how you work +keywords: + - feature + - announcement + - update +tags: + - product + - release +coverUrl: https://example.com/cover.jpg +date: 2025-01-15T10:00:00 +author: Team DyingStar +authorRoles: + - Product Manager +--- + +# Introducing Our New Feature + +We're thrilled to announce our latest feature! + +## What's New + +Here's what you can expect: + +- **Feature 1**: Description +- **Feature 2**: Description + +```ts +// Code example +const example = "You can include code blocks"; +``` +```` + + + +## Get Started + +Try it out today! + +```` + +**Processing Pipeline**: +1. MDX file stored in `content/` +2. Parsed by `features/markdown/` +3. Managed by feature-specific manager (e.g., `news-manager.ts`) +4. Rendered in App Router pages +5. Metadata extracted for SEO + +**Benefits**: +- Easy content authoring +- Mix static content with dynamic components +- Type-safe component usage +- Great for non-technical content editors + +--- + +### 11. Configuration Files + +#### `site-config.ts` + +**Purpose**: Central configuration for site-wide settings. + +**Example**: + +```ts +// src/site-config.ts +export const SiteConfig = { + title: "Dying Star", + description: "Collect and showcase powerful video and text testimonials", + prodUrl: "https://demo.dyingstar.app", + appId: "dyingstar", + domain: "demo.dyingstar.app", + appIcon: "/images/icon.png", +}; +```` + +#### `middleware.ts` + +**Purpose**: Next.js middleware for request interception and modification. + +**Example**: + +```ts +// middleware.ts +import { routing } from "i18n/routing"; +import createMiddleware from "next-intl/middleware"; + +export default createMiddleware(routing); + +export const config = { + matcher: [ + "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)", + ], + runtime: "nodejs", +}; +``` + +--- + +### 12. Next.js App Router Special Files + +#### `layout.tsx` + +**Purpose**: Shared UI that wraps pages within a route segment. + +**Key Features**: + +- Persists across navigation +- Can fetch data +- Can be nested + +**Example**: + +```tsx +// app/[locale]/layout.tsx +export default function LocaleLayout({ + children, + params: { locale }, +}: { + children: React.ReactNode; + params: { locale: string }; +}) { + return ( + + +
+ {children} +