diff --git a/.clinerules/memory-bank.md b/.clinerules/memory-bank.md
new file mode 100644
index 0000000..e6be63d
--- /dev/null
+++ b/.clinerules/memory-bank.md
@@ -0,0 +1,115 @@
+# Cline's Memory Bank
+
+I am Cline, an expert software engineer with a unique characteristic: my memory resets completely between sessions. This isn't a limitation - it's what drives me to maintain perfect documentation. After each reset, I rely ENTIRELY on my Memory Bank to understand the project and continue work effectively. I MUST read ALL memory bank files at the start of EVERY task - this is not optional.
+
+## Memory Bank Structure
+
+The Memory Bank consists of core files and optional context files, all in Markdown format. Files build upon each other in a clear hierarchy:
+
+flowchart TD
+ PB[projectbrief.md] --> PC[productContext.md]
+ PB --> SP[systemPatterns.md]
+ PB --> TC[techContext.md]
+
+ PC --> AC[activeContext.md]
+ SP --> AC
+ TC --> AC
+
+ AC --> P[progress.md]
+
+### Core Files (Required)
+1. `projectbrief.md`
+ - Foundation document that shapes all other files
+ - Created at project start if it doesn't exist
+ - Defines core requirements and goals
+ - Source of truth for project scope
+
+2. `productContext.md`
+ - Why this project exists
+ - Problems it solves
+ - How it should work
+ - User experience goals
+
+3. `activeContext.md`
+ - Current work focus
+ - Recent changes
+ - Next steps
+ - Active decisions and considerations
+ - Important patterns and preferences
+ - Learnings and project insights
+
+4. `systemPatterns.md`
+ - System architecture
+ - Key technical decisions
+ - Design patterns in use
+ - Component relationships
+ - Critical implementation paths
+
+5. `techContext.md`
+ - Technologies used
+ - Development setup
+ - Technical constraints
+ - Dependencies
+ - Tool usage patterns
+
+6. `progress.md`
+ - What works
+ - What's left to build
+ - Current status
+ - Known issues
+ - Evolution of project decisions
+
+### Additional Context
+Create additional files/folders within memory-bank/ when they help organize:
+- Complex feature documentation
+- Integration specifications
+- API documentation
+- Testing strategies
+- Deployment procedures
+
+## Core Workflows
+
+### Plan Mode
+flowchart TD
+ Start[Start] --> ReadFiles[Read Memory Bank]
+ ReadFiles --> CheckFiles{Files Complete?}
+
+ CheckFiles -->|No| Plan[Create Plan]
+ Plan --> Document[Document in Chat]
+
+ CheckFiles -->|Yes| Verify[Verify Context]
+ Verify --> Strategy[Develop Strategy]
+ Strategy --> Present[Present Approach]
+
+### Act Mode
+flowchart TD
+ Start[Start] --> Context[Check Memory Bank]
+ Context --> Update[Update Documentation]
+ Update --> Execute[Execute Task]
+ Execute --> Document[Document Changes]
+
+## Documentation Updates
+
+Memory Bank updates occur when:
+1. Discovering new project patterns
+2. After implementing significant changes
+3. When user requests with **update memory bank** (MUST review ALL files)
+4. When context needs clarification
+
+flowchart TD
+ Start[Update Process]
+
+ subgraph Process
+ P1[Review ALL Files]
+ P2[Document Current State]
+ P3[Clarify Next Steps]
+ P4[Document Insights & Patterns]
+
+ P1 --> P2 --> P3 --> P4
+ end
+
+ Start --> Process
+
+Note: When triggered by **update memory bank**, I MUST review every memory bank file, even if some don't require updates. Focus particularly on activeContext.md and progress.md as they track current state.
+
+REMEMBER: After every memory reset, I begin completely fresh. The Memory Bank is my only link to previous work. It must be maintained with precision and clarity, as my effectiveness depends entirely on its accuracy.
\ No newline at end of file
diff --git a/adventure-rental-app/package-lock.json b/adventure-rental-app/package-lock.json
index 41ecf52..a639fbe 100644
--- a/adventure-rental-app/package-lock.json
+++ b/adventure-rental-app/package-lock.json
@@ -10,7 +10,8 @@
"dependencies": {
"axios": "^1.11.0",
"react": "^19.1.0",
- "react-dom": "^19.1.0"
+ "react-dom": "^19.1.0",
+ "react-router-dom": "^7.7.1"
},
"devDependencies": {
"@eslint/js": "^9.30.1",
@@ -1905,6 +1906,15 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/cookie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -3580,6 +3590,44 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.7.1.tgz",
+ "integrity": "sha512-jVKHXoWRIsD/qS6lvGveckwb862EekvapdHJN/cGmzw40KnJH5gg53ujOJ4qX6EKIK9LSBfFed/xiQ5yeXNrUA==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.7.1.tgz",
+ "integrity": "sha512-bavdk2BA5r3MYalGKZ01u8PGuDBloQmzpBZVhDLrOOv1N943Wq6dcM9GhB3x8b7AbqPMEezauv4PeGkAJfy7FQ==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.7.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -3738,6 +3786,12 @@
"semver": "bin/semver.js"
}
},
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
+ "license": "MIT"
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
diff --git a/adventure-rental-app/package.json b/adventure-rental-app/package.json
index dfac63e..fd7a4d8 100644
--- a/adventure-rental-app/package.json
+++ b/adventure-rental-app/package.json
@@ -12,7 +12,8 @@
"dependencies": {
"axios": "^1.11.0",
"react": "^19.1.0",
- "react-dom": "^19.1.0"
+ "react-dom": "^19.1.0",
+ "react-router-dom": "^7.7.1"
},
"devDependencies": {
"@eslint/js": "^9.30.1",
diff --git a/adventure-rental-app/src/ForgotPasswordForm.jsx b/adventure-rental-app/src/ForgotPasswordForm.jsx
index c9b2a24..496e068 100644
--- a/adventure-rental-app/src/ForgotPasswordForm.jsx
+++ b/adventure-rental-app/src/ForgotPasswordForm.jsx
@@ -101,7 +101,7 @@ const ForgotPasswordForm = ({ showLogin, showReset }) => {
{success &&
{success}
}
diff --git a/adventure-rental-app/src/ResetPasswordForm.jsx b/adventure-rental-app/src/ResetPasswordForm.jsx
index 13c557d..e3efeb7 100644
--- a/adventure-rental-app/src/ResetPasswordForm.jsx
+++ b/adventure-rental-app/src/ResetPasswordForm.jsx
@@ -22,7 +22,7 @@ const ResetPasswordForm = ({ showLogin }) => {
try {
// Assuming you have a webhook for resetting the password
await axios.post('https://api.karyamanswasta.my.id/webhook/forgot-password/adventure', { token, newPassword });
- setSuccess('Password has been sent successfully!');
+ setSuccess('Password has been reset successfully!');
setTimeout(() => {
showLogin();
}, 2000);
diff --git a/memory-bank/activeContext.md b/memory-bank/activeContext.md
new file mode 100644
index 0000000..2cf0d6b
--- /dev/null
+++ b/memory-bank/activeContext.md
@@ -0,0 +1,33 @@
+# Active Context
+
+This document describes the current work focus, recent changes, next steps, active decisions and considerations, important patterns and preferences, learnings and project insights.
+
+## Current Work Focus
+
+- Building the chatbot page and its components.
+
+## Recent Changes
+
+- Initialized the memory bank with project details.
+
+## Next Steps
+
+- Install `react-router-dom` for routing.
+- Create the `Chatbot.jsx` component.
+- Create the `ChatbotPage.jsx` component.
+- Update `App.jsx` to include routing.
+- Add a link to the chatbot page.
+
+## Active Decisions and Considerations
+
+- Deciding on the structure and styling of the chatbot interface.
+
+## Important Patterns and Preferences
+
+- Continue using functional components with React Hooks.
+- Adhere to the existing Tailwind CSS configuration for styling.
+
+## Learnings and Project Insights
+
+- The project has a solid foundation with the authentication system in place.
+- The memory bank is now up-to-date, providing a clear context for future development.
diff --git a/memory-bank/productContext.md b/memory-bank/productContext.md
new file mode 100644
index 0000000..706076b
--- /dev/null
+++ b/memory-bank/productContext.md
@@ -0,0 +1,23 @@
+# Product Context
+
+This document explains why this project exists, the problems it solves, how it should work, and the user experience goals.
+
+## Why This Project Exists
+
+To provide a platform for users to easily rent adventure gear.
+
+## Problems It Solves
+
+- Users need a centralized place to find and rent adventure equipment.
+- Users often have questions about the gear, rental process, or policies and need quick answers.
+
+## How It Should Work
+
+- Users can create an account and log in.
+- Users can browse available gear.
+- Users can interact with a chatbot to get information and support.
+
+## User Experience Goals
+
+- A simple and intuitive interface for browsing and renting gear.
+- A helpful and responsive chatbot that can answer user queries effectively.
diff --git a/memory-bank/progress.md b/memory-bank/progress.md
new file mode 100644
index 0000000..16efd9d
--- /dev/null
+++ b/memory-bank/progress.md
@@ -0,0 +1,27 @@
+# Progress
+
+This document describes what works, what's left to build, the current status, known issues, and the evolution of project decisions.
+
+## What Works
+
+- User authentication system (Login, Signup, OTP, Forgot Password, Reset Password).
+
+## What's Left to Build
+
+- Chatbot page and functionality.
+- Routing to navigate between the authentication page and the chatbot page.
+- The main application features beyond authentication and chatbot.
+
+## Current Status
+
+- The authentication flow is implemented.
+- The project is ready for the development of the chatbot feature.
+
+## Known Issues
+
+- None at the moment.
+
+## Evolution of Project Decisions
+
+- The project initially focused only on authentication.
+- The scope has been expanded to include a chatbot feature.
diff --git a/memory-bank/projectbrief.md b/memory-bank/projectbrief.md
new file mode 100644
index 0000000..bf12c47
--- /dev/null
+++ b/memory-bank/projectbrief.md
@@ -0,0 +1,13 @@
+# Project Brief
+
+This document defines the core requirements and goals of the current project. It serves as the source of truth for the project scope.
+
+## Core Requirements
+
+- User authentication (Login, Signup, OTP, Forgot Password, Reset Password).
+- A chatbot page for users to ask questions.
+
+## Goals
+
+- To build a functional rental application for adventure gear.
+- To provide a chatbot for instant user support.
diff --git a/memory-bank/systemPatterns.md b/memory-bank/systemPatterns.md
new file mode 100644
index 0000000..a8615da
--- /dev/null
+++ b/memory-bank/systemPatterns.md
@@ -0,0 +1,31 @@
+# System Patterns
+
+This document describes the system architecture, key technical decisions, design patterns in use, component relationships, and critical implementation paths.
+
+## System Architecture
+
+The application is a Single Page Application (SPA) built with React and Vite. It uses a component-based architecture.
+
+## Key Technical Decisions
+
+- Using Vite for a fast development experience.
+- Using Tailwind CSS for utility-first styling.
+- State management is handled within individual components using React Hooks.
+
+## Design Patterns In Use
+
+- **Component-Based Architecture:** The UI is broken down into reusable components.
+- **Stateful and Stateless Components:** Using React functional components with and without state.
+
+## Component Relationships
+
+- `main.jsx`: The application entry point, renders the `App` component.
+- `App.jsx`: The root component, currently renders the `AuthPage`. It will be updated to handle routing.
+- `AuthPage.jsx`: Manages the display of different authentication forms (`LoginForm`, `SignupForm`, etc.).
+- `ChatbotPage.jsx`: A new page that will contain the `Chatbot` component.
+- `Chatbot.jsx`: A new component for the chat interface.
+
+## Critical Implementation Paths
+
+- User authentication flow.
+- Chatbot interaction and response handling.
diff --git a/memory-bank/techContext.md b/memory-bank/techContext.md
new file mode 100644
index 0000000..54bdf34
--- /dev/null
+++ b/memory-bank/techContext.md
@@ -0,0 +1,40 @@
+# Tech Context
+
+This document describes the technologies used, development setup, technical constraints, dependencies, and tool usage patterns.
+
+## Technologies Used
+
+- **Frontend:** React 19, Vite
+- **Styling:** Tailwind CSS, PostCSS
+- **Linting:** ESLint
+- **HTTP Client:** Axios
+
+## Development Setup
+
+- Run `npm install` to install dependencies.
+- Run `npm run dev` to start the development server.
+
+## Technical Constraints
+
+- Single Page Application (SPA) architecture.
+
+## Dependencies
+
+### Production
+- `axios`: For making HTTP requests.
+- `react`: For building the user interface.
+- `react-dom`: For rendering React components in the DOM.
+- `react-router-dom`: For routing.
+
+### Development
+- `@vitejs/plugin-react`: Vite plugin for React.
+- `autoprefixer`: PostCSS plugin to parse CSS and add vendor prefixes.
+- `eslint`: For linting JavaScript code.
+- `tailwindcss`: A utility-first CSS framework.
+- `vite`: A build tool that aims to provide a faster and leaner development experience for modern web projects.
+
+## Tool Usage Patterns
+
+- Vite is used for the development server and build process.
+- ESLint is used for code quality and consistency.
+- Tailwind CSS is used for styling.
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
new file mode 100644
index 0000000..7fb8160
--- /dev/null
+++ b/node_modules/.package-lock.json
@@ -0,0 +1,90 @@
+{
+ "name": "karyaman-project",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "node_modules/cookie": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/react": {
+ "version": "19.1.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
+ "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==",
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "19.1.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz",
+ "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "scheduler": "^0.26.0"
+ },
+ "peerDependencies": {
+ "react": "^19.1.1"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.7.1.tgz",
+ "integrity": "sha512-jVKHXoWRIsD/qS6lvGveckwb862EekvapdHJN/cGmzw40KnJH5gg53ujOJ4qX6EKIK9LSBfFed/xiQ5yeXNrUA==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "^1.0.1",
+ "set-cookie-parser": "^2.6.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.7.1.tgz",
+ "integrity": "sha512-bavdk2BA5r3MYalGKZ01u8PGuDBloQmzpBZVhDLrOOv1N943Wq6dcM9GhB3x8b7AbqPMEezauv4PeGkAJfy7FQ==",
+ "license": "MIT",
+ "dependencies": {
+ "react-router": "7.7.1"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.26.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
+ "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/set-cookie-parser": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
+ "license": "MIT"
+ }
+ }
+}
diff --git a/node_modules/cookie/LICENSE b/node_modules/cookie/LICENSE
new file mode 100644
index 0000000..058b6b4
--- /dev/null
+++ b/node_modules/cookie/LICENSE
@@ -0,0 +1,24 @@
+(The MIT License)
+
+Copyright (c) 2012-2014 Roman Shtylman
+Copyright (c) 2015 Douglas Christopher Wilson
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/node_modules/cookie/README.md b/node_modules/cookie/README.md
new file mode 100644
index 0000000..54e1cda
--- /dev/null
+++ b/node_modules/cookie/README.md
@@ -0,0 +1,248 @@
+# cookie
+
+[![NPM Version][npm-version-image]][npm-url]
+[![NPM Downloads][npm-downloads-image]][npm-url]
+[![Build Status][ci-image]][ci-url]
+[![Coverage Status][coverage-image]][coverage-url]
+
+Basic HTTP cookie parser and serializer for HTTP servers.
+
+## Installation
+
+```sh
+$ npm install cookie
+```
+
+## API
+
+```js
+const cookie = require("cookie");
+// import * as cookie from 'cookie';
+```
+
+### cookie.parse(str, options)
+
+Parse a HTTP `Cookie` header string and returning an object of all cookie name-value pairs.
+The `str` argument is the string representing a `Cookie` header value and `options` is an
+optional object containing additional parsing options.
+
+```js
+const cookies = cookie.parse("foo=bar; equation=E%3Dmc%5E2");
+// { foo: 'bar', equation: 'E=mc^2' }
+```
+
+#### Options
+
+`cookie.parse` accepts these properties in the options object.
+
+##### decode
+
+Specifies a function that will be used to decode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1).
+Since the value of a cookie has a limited character set (and must be a simple string), this function can be used to decode
+a previously-encoded cookie value into a JavaScript string.
+
+The default function is the global `decodeURIComponent`, wrapped in a `try..catch`. If an error
+is thrown it will return the cookie's original value. If you provide your own encode/decode
+scheme you must ensure errors are appropriately handled.
+
+### cookie.serialize(name, value, options)
+
+Serialize a cookie name-value pair into a `Set-Cookie` header string. The `name` argument is the
+name for the cookie, the `value` argument is the value to set the cookie to, and the `options`
+argument is an optional object containing additional serialization options.
+
+```js
+const setCookie = cookie.serialize("foo", "bar");
+// foo=bar
+```
+
+#### Options
+
+`cookie.serialize` accepts these properties in the options object.
+
+##### encode
+
+Specifies a function that will be used to encode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1).
+Since value of a cookie has a limited character set (and must be a simple string), this function can be used to encode
+a value into a string suited for a cookie's value, and should mirror `decode` when parsing.
+
+The default function is the global `encodeURIComponent`.
+
+##### maxAge
+
+Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.2).
+
+The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
+`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
+so if both are set, they should point to the same date and time.
+
+##### expires
+
+Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.1).
+When no expiration is set clients consider this a "non-persistent cookie" and delete it the current session is over.
+
+The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
+`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
+so if both are set, they should point to the same date and time.
+
+##### domain
+
+Specifies the value for the [`Domain` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.3).
+When no domain is set clients consider the cookie to apply to the current domain only.
+
+##### path
+
+Specifies the value for the [`Path` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.4).
+When no path is set, the path is considered the ["default path"](https://tools.ietf.org/html/rfc6265#section-5.1.4).
+
+##### httpOnly
+
+Enables the [`HttpOnly` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.6).
+When enabled, clients will not allow client-side JavaScript to see the cookie in `document.cookie`.
+
+##### secure
+
+Enables the [`Secure` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.5).
+When enabled, clients will only send the cookie back if the browser has a HTTPS connection.
+
+##### partitioned
+
+Enables the [`Partitioned` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/).
+When enabled, clients will only send the cookie back when the current domain _and_ top-level domain matches.
+
+This is an attribute that has not yet been fully standardized, and may change in the future.
+This also means clients may ignore this attribute until they understand it. More information
+about can be found in [the proposal](https://github.com/privacycg/CHIPS).
+
+##### priority
+
+Specifies the value for the [`Priority` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).
+
+- `'low'` will set the `Priority` attribute to `Low`.
+- `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
+- `'high'` will set the `Priority` attribute to `High`.
+
+More information about priority levels can be found in [the specification](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).
+
+##### sameSite
+
+Specifies the value for the [`SameSite` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).
+
+- `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+- `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
+- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
+- `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+
+More information about enforcement levels can be found in [the specification](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).
+
+## Example
+
+The following example uses this module in conjunction with the Node.js core HTTP server
+to prompt a user for their name and display it back on future visits.
+
+```js
+var cookie = require("cookie");
+var escapeHtml = require("escape-html");
+var http = require("http");
+var url = require("url");
+
+function onRequest(req, res) {
+ // Parse the query string
+ var query = url.parse(req.url, true, true).query;
+
+ if (query && query.name) {
+ // Set a new cookie with the name
+ res.setHeader(
+ "Set-Cookie",
+ cookie.serialize("name", String(query.name), {
+ httpOnly: true,
+ maxAge: 60 * 60 * 24 * 7, // 1 week
+ }),
+ );
+
+ // Redirect back after setting cookie
+ res.statusCode = 302;
+ res.setHeader("Location", req.headers.referer || "/");
+ res.end();
+ return;
+ }
+
+ // Parse the cookies on the request
+ var cookies = cookie.parse(req.headers.cookie || "");
+
+ // Get the visitor name set in the cookie
+ var name = cookies.name;
+
+ res.setHeader("Content-Type", "text/html; charset=UTF-8");
+
+ if (name) {
+ res.write("
Welcome back, " + escapeHtml(name) + "!
");
+ } else {
+ res.write("
Hello, new visitor!
");
+ }
+
+ res.write('");
+}
+
+http.createServer(onRequest).listen(3000);
+```
+
+## Testing
+
+```sh
+npm test
+```
+
+## Benchmark
+
+```sh
+npm run bench
+```
+
+```
+ name hz min max mean p75 p99 p995 p999 rme samples
+ · simple 8,566,313.09 0.0000 0.3694 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.64% 4283157 fastest
+ · decode 3,834,348.85 0.0001 0.2465 0.0003 0.0003 0.0003 0.0004 0.0006 ±0.38% 1917175
+ · unquote 8,315,355.96 0.0000 0.3824 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.72% 4157880
+ · duplicates 1,944,765.97 0.0004 0.2959 0.0005 0.0005 0.0006 0.0006 0.0008 ±0.24% 972384
+ · 10 cookies 675,345.67 0.0012 0.4328 0.0015 0.0015 0.0019 0.0020 0.0058 ±0.75% 337673
+ · 100 cookies 61,040.71 0.0152 0.4092 0.0164 0.0160 0.0196 0.0228 0.2260 ±0.71% 30521 slowest
+ ✓ parse top-sites (15) 22945ms
+ name hz min max mean p75 p99 p995 p999 rme samples
+ · parse accounts.google.com 7,164,349.17 0.0000 0.0929 0.0001 0.0002 0.0002 0.0002 0.0003 ±0.09% 3582184
+ · parse apple.com 7,817,686.84 0.0000 0.6048 0.0001 0.0001 0.0002 0.0002 0.0003 ±1.05% 3908844
+ · parse cloudflare.com 7,189,841.70 0.0000 0.0390 0.0001 0.0002 0.0002 0.0002 0.0003 ±0.06% 3594921
+ · parse docs.google.com 7,051,765.61 0.0000 0.0296 0.0001 0.0002 0.0002 0.0002 0.0003 ±0.06% 3525883
+ · parse drive.google.com 7,349,104.77 0.0000 0.0368 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.05% 3674553
+ · parse en.wikipedia.org 1,929,909.49 0.0004 0.3598 0.0005 0.0005 0.0007 0.0007 0.0012 ±0.16% 964955
+ · parse linkedin.com 2,225,658.01 0.0003 0.0595 0.0004 0.0005 0.0005 0.0005 0.0006 ±0.06% 1112830
+ · parse maps.google.com 4,423,511.68 0.0001 0.0942 0.0002 0.0003 0.0003 0.0003 0.0005 ±0.08% 2211756
+ · parse microsoft.com 3,387,601.88 0.0002 0.0725 0.0003 0.0003 0.0004 0.0004 0.0005 ±0.09% 1693801
+ · parse play.google.com 7,375,980.86 0.0000 0.1994 0.0001 0.0001 0.0002 0.0002 0.0003 ±0.12% 3687991
+ · parse support.google.com 4,912,267.94 0.0001 2.8958 0.0002 0.0002 0.0003 0.0003 0.0005 ±1.28% 2456134
+ · parse www.google.com 3,443,035.87 0.0002 0.2783 0.0003 0.0003 0.0004 0.0004 0.0007 ±0.51% 1721518
+ · parse youtu.be 1,910,492.87 0.0004 0.3490 0.0005 0.0005 0.0007 0.0007 0.0011 ±0.46% 955247
+ · parse youtube.com 1,895,082.62 0.0004 0.7454 0.0005 0.0005 0.0006 0.0007 0.0013 ±0.64% 947542 slowest
+ · parse example.com 21,582,835.27 0.0000 0.1095 0.0000 0.0000 0.0001 0.0001 0.0001 ±0.13% 10791418
+```
+
+## References
+
+- [RFC 6265: HTTP State Management Mechanism](https://tools.ietf.org/html/rfc6265)
+- [Same-site Cookies](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7)
+
+## License
+
+[MIT](LICENSE)
+
+[ci-image]: https://img.shields.io/github/actions/workflow/status/jshttp/cookie/ci.yml
+[ci-url]: https://github.com/jshttp/cookie/actions/workflows/ci.yml?query=branch%3Amaster
+[coverage-image]: https://img.shields.io/codecov/c/github/jshttp/cookie/master
+[coverage-url]: https://app.codecov.io/gh/jshttp/cookie
+[npm-downloads-image]: https://img.shields.io/npm/dm/cookie
+[npm-url]: https://npmjs.org/package/cookie
+[npm-version-image]: https://img.shields.io/npm/v/cookie
diff --git a/node_modules/cookie/dist/index.d.ts b/node_modules/cookie/dist/index.d.ts
new file mode 100644
index 0000000..784b0db
--- /dev/null
+++ b/node_modules/cookie/dist/index.d.ts
@@ -0,0 +1,114 @@
+/**
+ * Parse options.
+ */
+export interface ParseOptions {
+ /**
+ * Specifies a function that will be used to decode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1).
+ * Since the value of a cookie has a limited character set (and must be a simple string), this function can be used to decode
+ * a previously-encoded cookie value into a JavaScript string.
+ *
+ * The default function is the global `decodeURIComponent`, wrapped in a `try..catch`. If an error
+ * is thrown it will return the cookie's original value. If you provide your own encode/decode
+ * scheme you must ensure errors are appropriately handled.
+ *
+ * @default decode
+ */
+ decode?: (str: string) => string | undefined;
+}
+/**
+ * Parse a cookie header.
+ *
+ * Parse the given cookie header string into an object
+ * The object has the various cookies as keys(names) => values
+ */
+export declare function parse(str: string, options?: ParseOptions): Record;
+/**
+ * Serialize options.
+ */
+export interface SerializeOptions {
+ /**
+ * Specifies a function that will be used to encode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1).
+ * Since value of a cookie has a limited character set (and must be a simple string), this function can be used to encode
+ * a value into a string suited for a cookie's value, and should mirror `decode` when parsing.
+ *
+ * @default encodeURIComponent
+ */
+ encode?: (str: string) => string;
+ /**
+ * Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.2).
+ *
+ * The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
+ * `maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
+ * so if both are set, they should point to the same date and time.
+ */
+ maxAge?: number;
+ /**
+ * Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.1).
+ * When no expiration is set clients consider this a "non-persistent cookie" and delete it the current session is over.
+ *
+ * The [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and
+ * `maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this,
+ * so if both are set, they should point to the same date and time.
+ */
+ expires?: Date;
+ /**
+ * Specifies the value for the [`Domain` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.3).
+ * When no domain is set clients consider the cookie to apply to the current domain only.
+ */
+ domain?: string;
+ /**
+ * Specifies the value for the [`Path` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.4).
+ * When no path is set, the path is considered the ["default path"](https://tools.ietf.org/html/rfc6265#section-5.1.4).
+ */
+ path?: string;
+ /**
+ * Enables the [`HttpOnly` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.6).
+ * When enabled, clients will not allow client-side JavaScript to see the cookie in `document.cookie`.
+ */
+ httpOnly?: boolean;
+ /**
+ * Enables the [`Secure` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.5).
+ * When enabled, clients will only send the cookie back if the browser has a HTTPS connection.
+ */
+ secure?: boolean;
+ /**
+ * Enables the [`Partitioned` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/).
+ * When enabled, clients will only send the cookie back when the current domain _and_ top-level domain matches.
+ *
+ * This is an attribute that has not yet been fully standardized, and may change in the future.
+ * This also means clients may ignore this attribute until they understand it. More information
+ * about can be found in [the proposal](https://github.com/privacycg/CHIPS).
+ */
+ partitioned?: boolean;
+ /**
+ * Specifies the value for the [`Priority` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).
+ *
+ * - `'low'` will set the `Priority` attribute to `Low`.
+ * - `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.
+ * - `'high'` will set the `Priority` attribute to `High`.
+ *
+ * More information about priority levels can be found in [the specification](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).
+ */
+ priority?: "low" | "medium" | "high";
+ /**
+ * Specifies the value for the [`SameSite` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).
+ *
+ * - `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+ * - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.
+ * - `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.
+ * - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.
+ *
+ * More information about enforcement levels can be found in [the specification](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).
+ */
+ sameSite?: boolean | "lax" | "strict" | "none";
+}
+/**
+ * Serialize data into a cookie header.
+ *
+ * Serialize a name value pair into a cookie string suitable for
+ * http headers. An optional options object specifies cookie parameters.
+ *
+ * serialize('foo', 'bar', { httpOnly: true })
+ * => "foo=bar; httpOnly"
+ */
+export declare function serialize(name: string, val: string, options?: SerializeOptions): string;
diff --git a/node_modules/cookie/dist/index.js b/node_modules/cookie/dist/index.js
new file mode 100644
index 0000000..423acb4
--- /dev/null
+++ b/node_modules/cookie/dist/index.js
@@ -0,0 +1,239 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.parse = parse;
+exports.serialize = serialize;
+/**
+ * RegExp to match cookie-name in RFC 6265 sec 4.1.1
+ * This refers out to the obsoleted definition of token in RFC 2616 sec 2.2
+ * which has been replaced by the token definition in RFC 7230 appendix B.
+ *
+ * cookie-name = token
+ * token = 1*tchar
+ * tchar = "!" / "#" / "$" / "%" / "&" / "'" /
+ * "*" / "+" / "-" / "." / "^" / "_" /
+ * "`" / "|" / "~" / DIGIT / ALPHA
+ *
+ * Note: Allowing more characters - https://github.com/jshttp/cookie/issues/191
+ * Allow same range as cookie value, except `=`, which delimits end of name.
+ */
+const cookieNameRegExp = /^[\u0021-\u003A\u003C\u003E-\u007E]+$/;
+/**
+ * RegExp to match cookie-value in RFC 6265 sec 4.1.1
+ *
+ * cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
+ * cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
+ * ; US-ASCII characters excluding CTLs,
+ * ; whitespace DQUOTE, comma, semicolon,
+ * ; and backslash
+ *
+ * Allowing more characters: https://github.com/jshttp/cookie/issues/191
+ * Comma, backslash, and DQUOTE are not part of the parsing algorithm.
+ */
+const cookieValueRegExp = /^[\u0021-\u003A\u003C-\u007E]*$/;
+/**
+ * RegExp to match domain-value in RFC 6265 sec 4.1.1
+ *
+ * domain-value =
+ * ; defined in [RFC1034], Section 3.5, as
+ * ; enhanced by [RFC1123], Section 2.1
+ * =