Compare commits
50 Commits
23-trades-
...
31-testing
Author | SHA1 | Date | |
---|---|---|---|
00b7f3b0b6 | |||
c21b6ff634 | |||
c96db51219
|
|||
90e0768054
|
|||
9aaa9b003f | |||
f7eb23c52d
|
|||
32c15b2032
|
|||
5f4e9a57d7
|
|||
29cdd467a1
|
|||
e5b1212af4
|
|||
7bb7986bf6
|
|||
dd691132b2 | |||
a2a8cea193 | |||
5bc1576133 | |||
49227e397e | |||
d1b538e39b | |||
9df557d972 | |||
6e7f968b06 | |||
f9166de925 | |||
5bd98c32d3 | |||
10baa478c2 | |||
e6289ffc12
|
|||
fd1aea0af5 | |||
eec61fe330 | |||
dba27461b6 | |||
485c900160 | |||
b29879c11f | |||
d9ae49c53f | |||
0234846521 | |||
fdd0a294ff
|
|||
0dbb9bdc47 | |||
e6bea411e0 | |||
ccd6dbdd81
|
|||
2fd018911e
|
|||
4a66aa87f3
|
|||
48e3832624
|
|||
39a28844dd
|
|||
338694767a
|
|||
3fa5579a4b | |||
f4b6fdef2c | |||
eff4af24da | |||
f56ce1c7d8 | |||
730b9939dd | |||
acaf711e10 | |||
722343e754
|
|||
8c2870e5b0
|
|||
360cd91f2b
|
|||
db5219207a | |||
09df7432a3 | |||
e3421ad462 |
7
.dockerignore
Normal file
7
.dockerignore
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Dockerfile
|
||||||
|
.dockerignore
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
README.md
|
||||||
|
.next
|
||||||
|
.git
|
@ -57,7 +57,7 @@ const config = {
|
|||||||
"func-style": [ "error", "expression" ],
|
"func-style": [ "error", "expression" ],
|
||||||
"grouped-accessor-pairs": [ "error", "getBeforeSet" ],
|
"grouped-accessor-pairs": [ "error", "getBeforeSet" ],
|
||||||
"no-caller": "error",
|
"no-caller": "error",
|
||||||
"no-console": "error",
|
"no-console": "warn",
|
||||||
"no-eq-null": "error",
|
"no-eq-null": "error",
|
||||||
"no-eval": "error",
|
"no-eval": "error",
|
||||||
"no-extend-native": "error",
|
"no-extend-native": "error",
|
||||||
@ -73,7 +73,7 @@ const config = {
|
|||||||
"no-lone-blocks": "error",
|
"no-lone-blocks": "error",
|
||||||
"no-lonely-if": "error",
|
"no-lonely-if": "error",
|
||||||
"no-loop-func": "error",
|
"no-loop-func": "error",
|
||||||
"no-magic-numbers": "error",
|
"no-magic-numbers": [ "error", { "ignore": [-1, 0] } ],
|
||||||
"no-mixed-operators": "error",
|
"no-mixed-operators": "error",
|
||||||
"no-multi-assign": "error",
|
"no-multi-assign": "error",
|
||||||
"no-multi-str": "error",
|
"no-multi-str": "error",
|
||||||
|
@ -1,10 +1,32 @@
|
|||||||
stages:
|
stages:
|
||||||
- lint
|
- build
|
||||||
|
|
||||||
# Lint the project
|
# Lint the project
|
||||||
lint:
|
lint:
|
||||||
stage: lint
|
stage: build
|
||||||
image: node:18
|
image: node:18
|
||||||
script:
|
script:
|
||||||
- npm ci
|
- npm ci
|
||||||
- npm run lint
|
- npm run lint
|
||||||
|
|
||||||
|
# Do a test build of the project
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
image: node:18
|
||||||
|
variables:
|
||||||
|
SKIP_ENV_VALIDATION: 1
|
||||||
|
script:
|
||||||
|
- npm ci
|
||||||
|
- npm run build
|
||||||
|
|
||||||
|
# Build the docker image and push it to the registry
|
||||||
|
docker-build:
|
||||||
|
stage: build
|
||||||
|
image: docker:latest
|
||||||
|
script:
|
||||||
|
- /usr/local/bin/dockerd-entrypoint.sh &
|
||||||
|
- while ! docker info; do echo "Waiting for Docker to become available..."; sleep 1; done
|
||||||
|
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD registry.mregirouard.com
|
||||||
|
- docker build -t registry.mregirouard.com/finvis/finvis:$CI_COMMIT_SHORT_SHA
|
||||||
|
-t registry.mregirouard.com/finvis/finvis:$CI_COMMIT_BRANCH .
|
||||||
|
- docker push registry.mregirouard.com/finvis/finvis --all-tags
|
||||||
|
1
.npmrc
Normal file
1
.npmrc
Normal file
@ -0,0 +1 @@
|
|||||||
|
@finvis:registry=https://gitlab.mregirouard.com/api/v4/packages/npm/
|
40
Dockerfile
Normal file
40
Dockerfile
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
FROM node:18-alpine AS base
|
||||||
|
|
||||||
|
LABEL maintainer="FinVis Rensselear Center for Open Source Project Team"
|
||||||
|
LABEL license="GNU GPLv3"
|
||||||
|
LABEL description="Docker image for FinVis T3 app."
|
||||||
|
|
||||||
|
ENV SKIP_ENV_VALIDATION 1
|
||||||
|
ENV PORT 80
|
||||||
|
ENV HOSTNAME "0.0.0.0"
|
||||||
|
|
||||||
|
FROM base AS deps
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json ./
|
||||||
|
COPY package-lock.json ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
FROM base as build
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM base AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN addgroup --system --gid 1005 nodejs
|
||||||
|
RUN adduser --system --uid 1005 nextjs
|
||||||
|
COPY --from=build /app/public ./public
|
||||||
|
|
||||||
|
RUN mkdir .next
|
||||||
|
RUN chown nextjs:nodejs .next
|
||||||
|
|
||||||
|
COPY --from=build --chown=nextjs:nodejs /app/.next/standalone ./
|
||||||
|
COPY --from=build --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
|
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
|
CMD ["node", "server.js"]
|
42
README.md
42
README.md
@ -1,28 +1,34 @@
|
|||||||
# Create T3 App
|

|
||||||
|
|
||||||
This is a [T3 Stack](https://create.t3.gg/) project bootstrapped with `create-t3-app`.
|
# FinVis
|
||||||
|
|
||||||
## What's next? How do I make an app with this?
|
A financial tracking web app that allows users to track their investments across multiple exchanges.
|
||||||
|
|
||||||
We try to keep this project as simple as possible, so you can start with just the scaffolding we set up for you, and add additional things later when they become necessary.
|
## Purpose
|
||||||
|
To organize, display, and analyze stock trades on different exchanges in one place.
|
||||||
|
|
||||||
If you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help.
|
## Try It
|
||||||
|
You can run FinVis by checking out this repository, and running:
|
||||||
|
`npm run start`
|
||||||
|
|
||||||
- [Next.js](https://nextjs.org)
|
Or view the [production site](https://fin-vis.com).
|
||||||
- [NextAuth.js](https://next-auth.js.org)
|
|
||||||
- [Prisma](https://prisma.io)
|
|
||||||
- [Tailwind CSS](https://tailwindcss.com)
|
|
||||||
- [tRPC](https://trpc.io)
|
|
||||||
|
|
||||||
## Learn More
|
## The Team
|
||||||
|
|
||||||
To learn more about the [T3 Stack](https://create.t3.gg/), take a look at the following resources:
|
This project is being developed for [Rensselaer Center for Open Source (RCOS)](https://new.rcos.io) by:
|
||||||
|
|
||||||
- [Documentation](https://create.t3.gg/)
|
- [Ethan Girouard](https://gitlab.mregirouard.com/MRegirouard)
|
||||||
- [Learn the T3 Stack](https://create.t3.gg/en/faq#what-learning-resources-are-currently-available) — Check out these awesome tutorials
|
- [Carter Bertolini](https://gitlab.mregirouard.com/clbertolini)
|
||||||
|
- [Aaron Verkleeren](https://gitlab.mregirouard.com/averkleeren)
|
||||||
|
- [Derrick Lin](https://gitlab.mregirouard.com/derricklin)
|
||||||
|
- [Connor Wittman](https://gitlab.mregirouard.com/ecco257)
|
||||||
|
- [Danny Zou](https://gitlab.mregirouard.com/dannyzou18)
|
||||||
|
- [Aidan Westphal](https://gitlab.mregirouard.com/hifwiend)
|
||||||
|
|
||||||
You can check out the [create-t3-app GitHub repository](https://github.com/t3-oss/create-t3-app) — your feedback and contributions are welcome!
|
## Stack
|
||||||
|
|
||||||
## How do I deploy this?
|
- We created this project using [create t3 app](https://create.t3.gg)
|
||||||
|
- We are making the frontend with [React](https://reactjs.org) and styling is done with [Tailwind CSS](https://tailwindcss.com)
|
||||||
Follow our deployment guides for [Vercel](https://create.t3.gg/en/deployment/vercel), [Netlify](https://create.t3.gg/en/deployment/netlify) and [Docker](https://create.t3.gg/en/deployment/docker) for more information.
|
- For server-side rendering, we are using [Next.js](https://nextjs.org)
|
||||||
|
- [tRPC](https://trpc.io) is used to handle API calls
|
||||||
|
- [MongoDB](https://www.mongodb.com) provides the database
|
||||||
|
@ -17,6 +17,10 @@ const config = {
|
|||||||
locales: ["en"],
|
locales: ["en"],
|
||||||
defaultLocale: "en",
|
defaultLocale: "en",
|
||||||
},
|
},
|
||||||
|
output: "standalone",
|
||||||
|
eslint: {
|
||||||
|
ignoreDuringBuilds: true,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
561
package-lock.json
generated
561
package-lock.json
generated
@ -8,6 +8,7 @@
|
|||||||
"name": "finvis",
|
"name": "finvis",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@finvis/usxi": "^1.7.0",
|
||||||
"@t3-oss/env-nextjs": "^0.6.0",
|
"@t3-oss/env-nextjs": "^0.6.0",
|
||||||
"@tanstack/react-query": "^4.32.6",
|
"@tanstack/react-query": "^4.32.6",
|
||||||
"@trpc/client": "^10.37.1",
|
"@trpc/client": "^10.37.1",
|
||||||
@ -17,6 +18,7 @@
|
|||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"framer-motion": "^10.16.4",
|
"framer-motion": "^10.16.4",
|
||||||
|
"mongodb": "^6.2.0",
|
||||||
"mongoose": "^7.5.3",
|
"mongoose": "^7.5.3",
|
||||||
"next": "^13.4.19",
|
"next": "^13.4.19",
|
||||||
"next-auth": "^4.23.0",
|
"next-auth": "^4.23.0",
|
||||||
@ -66,6 +68,35 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@alpacahq/alpaca-trade-api": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@alpacahq/alpaca-trade-api/-/alpaca-trade-api-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-FOsgA4jREAArWbb7nuKTo2yiUdb8+/4vboyTX2SRJSi+oYBaFrZV+hMNx7fGWtuLuKGRKEdK8Nc+8MFjwcbz4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.21.1",
|
||||||
|
"dotenv": "^6.2.0",
|
||||||
|
"events": "^3.2.0",
|
||||||
|
"just-extend": "^4.1.0",
|
||||||
|
"lodash": "^4.17.19",
|
||||||
|
"minimist": "^1.2.6",
|
||||||
|
"msgpack5": "^5.3.2",
|
||||||
|
"nats": "^1.4.9",
|
||||||
|
"urljoin": "^0.1.5",
|
||||||
|
"ws": "^7.4.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.x",
|
||||||
|
"npm": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@alpacahq/alpaca-trade-api/node_modules/dotenv": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@babel/runtime": {
|
"node_modules/@babel/runtime": {
|
||||||
"version": "7.23.1",
|
"version": "7.23.1",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz",
|
||||||
@ -77,6 +108,14 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@colors/colors": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.1.90"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@cspotcode/source-map-support": {
|
"node_modules/@cspotcode/source-map-support": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||||
@ -97,6 +136,16 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@dabh/diagnostics": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==",
|
||||||
|
"dependencies": {
|
||||||
|
"colorspace": "1.1.x",
|
||||||
|
"enabled": "2.0.x",
|
||||||
|
"kuler": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@emotion/is-prop-valid": {
|
"node_modules/@emotion/is-prop-valid": {
|
||||||
"version": "0.8.8",
|
"version": "0.8.8",
|
||||||
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
|
||||||
@ -168,6 +217,16 @@
|
|||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@finvis/usxi": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "http://gitlab.mregirouard.com/api/v4/projects/12/packages/npm/@finvis/usxi/-/@finvis/usxi-1.7.0.tgz",
|
||||||
|
"integrity": "sha1-BJh1RAFTR/l1JO+P0foxnKV202o=",
|
||||||
|
"dependencies": {
|
||||||
|
"@alpacahq/alpaca-trade-api": "^3.0.1",
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"winston": "^3.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@humanwhocodes/config-array": {
|
"node_modules/@humanwhocodes/config-array": {
|
||||||
"version": "0.11.11",
|
"version": "0.11.11",
|
||||||
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz",
|
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz",
|
||||||
@ -270,7 +329,6 @@
|
|||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.0.tgz",
|
||||||
"integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==",
|
"integrity": "sha512-Xfijy7HvfzzqiOAhAepF4SGN5e9leLkMvg/OPOF97XemjfVCYN/oWa75wnkc6mltMSTwY+XlbhWgUOJmkFspSw==",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sparse-bitfield": "^3.0.3"
|
"sparse-bitfield": "^3.0.3"
|
||||||
}
|
}
|
||||||
@ -691,6 +749,11 @@
|
|||||||
"integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==",
|
"integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/triple-beam": {
|
||||||
|
"version": "1.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz",
|
||||||
|
"integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="
|
||||||
|
},
|
||||||
"node_modules/@types/webidl-conversions": {
|
"node_modules/@types/webidl-conversions": {
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.1.tgz",
|
||||||
@ -1170,6 +1233,11 @@
|
|||||||
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
|
"integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/async": {
|
||||||
|
"version": "3.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
|
||||||
|
"integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg=="
|
||||||
|
},
|
||||||
"node_modules/asynciterator.prototype": {
|
"node_modules/asynciterator.prototype": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
|
||||||
@ -1237,6 +1305,14 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/axios": {
|
||||||
|
"version": "0.21.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
|
||||||
|
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
|
||||||
|
"dependencies": {
|
||||||
|
"follow-redirects": "^1.14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/axobject-query": {
|
"node_modules/axobject-query": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
|
||||||
@ -1251,6 +1327,25 @@
|
|||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/base64-js": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/bcrypt": {
|
"node_modules/bcrypt": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.1.tgz",
|
||||||
@ -1273,6 +1368,16 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bl": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": "^5.5.0",
|
||||||
|
"inherits": "^2.0.4",
|
||||||
|
"readable-stream": "^3.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
@ -1334,6 +1439,29 @@
|
|||||||
"node": ">=14.20.1"
|
"node": ">=14.20.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer": {
|
||||||
|
"version": "5.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
|
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.3.1",
|
||||||
|
"ieee754": "^1.1.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/busboy": {
|
"node_modules/busboy": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||||
@ -1463,6 +1591,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/color": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^1.9.3",
|
||||||
|
"color-string": "^1.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
@ -1478,8 +1615,16 @@
|
|||||||
"node_modules/color-name": {
|
"node_modules/color-name": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||||
"dev": true
|
},
|
||||||
|
"node_modules/color-string": {
|
||||||
|
"version": "1.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
|
||||||
|
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "^1.0.0",
|
||||||
|
"simple-swizzle": "^0.2.2"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/color-support": {
|
"node_modules/color-support": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
@ -1489,6 +1634,28 @@
|
|||||||
"color-support": "bin.js"
|
"color-support": "bin.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/color/node_modules/color-convert": {
|
||||||
|
"version": "1.9.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||||
|
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "1.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color/node_modules/color-name": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
|
||||||
|
},
|
||||||
|
"node_modules/colorspace": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==",
|
||||||
|
"dependencies": {
|
||||||
|
"color": "^3.1.3",
|
||||||
|
"text-hex": "1.0.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/commander": {
|
"node_modules/commander": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||||
@ -1715,6 +1882,11 @@
|
|||||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/enabled": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="
|
||||||
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
"node_modules/enhanced-resolve": {
|
||||||
"version": "5.15.0",
|
"version": "5.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
|
||||||
@ -2282,6 +2454,19 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/events": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/extend": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/extend/-/extend-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-AgFD4VU+lVLP6vjnlNfF7OeInLTyeyckCNPEsuxz1vi786UuK/nk6ynPuhn/h+Ju9++TQyr5EpLRI14fc1QtTQ=="
|
||||||
|
},
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
@ -2337,6 +2522,11 @@
|
|||||||
"reusify": "^1.0.4"
|
"reusify": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fecha": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="
|
||||||
|
},
|
||||||
"node_modules/file-entry-cache": {
|
"node_modules/file-entry-cache": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
||||||
@ -2397,6 +2587,30 @@
|
|||||||
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
|
"integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/fn.name": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
|
||||||
|
},
|
||||||
|
"node_modules/follow-redirects": {
|
||||||
|
"version": "1.15.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
|
||||||
|
"integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"debug": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/for-each": {
|
"node_modules/for-each": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
||||||
@ -2785,6 +2999,25 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ieee754": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||||
|
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.2.4",
|
"version": "5.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||||
@ -2866,6 +3099,11 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-arrayish": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
|
||||||
|
},
|
||||||
"node_modules/is-async-function": {
|
"node_modules/is-async-function": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
|
||||||
@ -3107,6 +3345,17 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-stream": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-string": {
|
"node_modules/is-string": {
|
||||||
"version": "1.0.7",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
|
||||||
@ -3301,6 +3550,11 @@
|
|||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/just-extend": {
|
||||||
|
"version": "4.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz",
|
||||||
|
"integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg=="
|
||||||
|
},
|
||||||
"node_modules/kareem": {
|
"node_modules/kareem": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz",
|
||||||
@ -3318,6 +3572,11 @@
|
|||||||
"json-buffer": "3.0.1"
|
"json-buffer": "3.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/kuler": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="
|
||||||
|
},
|
||||||
"node_modules/language-subtag-registry": {
|
"node_modules/language-subtag-registry": {
|
||||||
"version": "0.3.22",
|
"version": "0.3.22",
|
||||||
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
|
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
|
||||||
@ -3376,12 +3635,33 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
|
},
|
||||||
"node_modules/lodash.merge": {
|
"node_modules/lodash.merge": {
|
||||||
"version": "4.6.2",
|
"version": "4.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
|
||||||
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/logform": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@colors/colors": "1.6.0",
|
||||||
|
"@types/triple-beam": "^1.3.2",
|
||||||
|
"fecha": "^4.2.0",
|
||||||
|
"ms": "^2.1.1",
|
||||||
|
"safe-stable-stringify": "^2.3.1",
|
||||||
|
"triple-beam": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/loose-envify": {
|
"node_modules/loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
@ -3434,8 +3714,7 @@
|
|||||||
"node_modules/memory-pager": {
|
"node_modules/memory-pager": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
|
||||||
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
|
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"node_modules/merge2": {
|
"node_modules/merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
@ -3474,7 +3753,6 @@
|
|||||||
"version": "1.2.8",
|
"version": "1.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
"dev": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
@ -3522,6 +3800,89 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mongodb": {
|
"node_modules/mongodb": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-d7OSuGjGWDZ5usZPqfvb36laQ9CPhnWkAGHT61x5P95p/8nMVeH8asloMwW6GcYFeB0Vj4CB/1wOTDG2RA9BFA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@mongodb-js/saslprep": "^1.1.0",
|
||||||
|
"bson": "^6.2.0",
|
||||||
|
"mongodb-connection-string-url": "^2.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.20.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@aws-sdk/credential-providers": "^3.188.0",
|
||||||
|
"@mongodb-js/zstd": "^1.1.0",
|
||||||
|
"gcp-metadata": "^5.2.0",
|
||||||
|
"kerberos": "^2.0.1",
|
||||||
|
"mongodb-client-encryption": ">=6.0.0 <7",
|
||||||
|
"snappy": "^7.2.2",
|
||||||
|
"socks": "^2.7.1"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@aws-sdk/credential-providers": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@mongodb-js/zstd": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"gcp-metadata": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"kerberos": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"mongodb-client-encryption": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"snappy": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"socks": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mongodb-connection-string-url": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/whatwg-url": "^8.2.1",
|
||||||
|
"whatwg-url": "^11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mongodb/node_modules/bson": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bson/-/bson-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-ID1cI+7bazPDyL9wYy9GaQ8gEEohWvcUl/Yf0dIdutJxnmInEEyCsb4awy/OiBfall7zBA179Pahi3vCdFze3Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.20.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mongoose": {
|
||||||
|
"version": "7.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.6.1.tgz",
|
||||||
|
"integrity": "sha512-Iflr60FL7mabBdgAtumLTwEGdZGV6IKHfF7F75En2JWpPitorwQeCFqWPcPHRnBxncKANl3gwI9nh2Yb4y3/sA==",
|
||||||
|
"dependencies": {
|
||||||
|
"bson": "^5.5.0",
|
||||||
|
"kareem": "2.5.1",
|
||||||
|
"mongodb": "5.9.0",
|
||||||
|
"mpath": "0.9.0",
|
||||||
|
"mquery": "5.0.0",
|
||||||
|
"ms": "2.1.3",
|
||||||
|
"sift": "16.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.20.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/mongoose"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mongoose/node_modules/mongodb": {
|
||||||
"version": "5.9.0",
|
"version": "5.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.0.tgz",
|
||||||
"integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==",
|
"integrity": "sha512-g+GCMHN1CoRUA+wb1Agv0TI4YTSiWr42B5ulkiAfLLHitGK1R+PkSAf3Lr5rPZwi/3F04LiaZEW0Kxro9Fi2TA==",
|
||||||
@ -3561,36 +3922,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mongodb-connection-string-url": {
|
|
||||||
"version": "2.6.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz",
|
|
||||||
"integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/whatwg-url": "^8.2.1",
|
|
||||||
"whatwg-url": "^11.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mongoose": {
|
|
||||||
"version": "7.6.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.6.1.tgz",
|
|
||||||
"integrity": "sha512-Iflr60FL7mabBdgAtumLTwEGdZGV6IKHfF7F75En2JWpPitorwQeCFqWPcPHRnBxncKANl3gwI9nh2Yb4y3/sA==",
|
|
||||||
"dependencies": {
|
|
||||||
"bson": "^5.5.0",
|
|
||||||
"kareem": "2.5.1",
|
|
||||||
"mongodb": "5.9.0",
|
|
||||||
"mpath": "0.9.0",
|
|
||||||
"mquery": "5.0.0",
|
|
||||||
"ms": "2.1.3",
|
|
||||||
"sift": "16.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.20.1"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/mongoose"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mongoose/node_modules/ms": {
|
"node_modules/mongoose/node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
@ -3620,6 +3951,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||||
},
|
},
|
||||||
|
"node_modules/msgpack5": {
|
||||||
|
"version": "5.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/msgpack5/-/msgpack5-5.3.2.tgz",
|
||||||
|
"integrity": "sha512-e9jz+6InQIUb2cGzZ/Mi+rQBs1KFLby+gNi+22VwQ1pnC9ieZjysKGmRMjdlf6IyjsltbgY4tGoHwHmyS7l94A==",
|
||||||
|
"dependencies": {
|
||||||
|
"bl": "^4.0.0",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^3.0.0",
|
||||||
|
"safe-buffer": "^5.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mz": {
|
"node_modules/mz": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
||||||
@ -3648,6 +3990,24 @@
|
|||||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nats": {
|
||||||
|
"version": "1.4.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/nats/-/nats-1.4.12.tgz",
|
||||||
|
"integrity": "sha512-Jf4qesEF0Ay0D4AMw3OZnKMRTQm+6oZ5q8/m4gpy5bTmiDiK6wCXbZpzEslmezGpE93LV3RojNEG6dpK/mysLQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"nuid": "^1.1.4",
|
||||||
|
"ts-nkeys": "^1.0.16"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"node-pub": "examples/node-pub",
|
||||||
|
"node-reply": "examples/node-reply",
|
||||||
|
"node-req": "examples/node-req",
|
||||||
|
"node-sub": "examples/node-sub"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/natural-compare": {
|
"node_modules/natural-compare": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
|
||||||
@ -3850,6 +4210,14 @@
|
|||||||
"set-blocking": "^2.0.0"
|
"set-blocking": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nuid": {
|
||||||
|
"version": "1.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/nuid/-/nuid-1.1.6.tgz",
|
||||||
|
"integrity": "sha512-Eb3CPCupYscP1/S1FQcO5nxtu6l/F3k0MQ69h7f5osnsemVk5pkc8/5AyalVT+NCfra9M71U8POqF6EZa6IHvg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/oauth": {
|
"node_modules/oauth": {
|
||||||
"version": "0.9.15",
|
"version": "0.9.15",
|
||||||
"resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
|
"resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
|
||||||
@ -3996,6 +4364,14 @@
|
|||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/one-time": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==",
|
||||||
|
"dependencies": {
|
||||||
|
"fn.name": "1.x.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/openid-client": {
|
"node_modules/openid-client": {
|
||||||
"version": "5.5.0",
|
"version": "5.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.5.0.tgz",
|
||||||
@ -4690,6 +5066,14 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/safe-stable-stringify": {
|
||||||
|
"version": "2.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz",
|
||||||
|
"integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/scheduler": {
|
"node_modules/scheduler": {
|
||||||
"version": "0.23.0",
|
"version": "0.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
|
||||||
@ -4776,6 +5160,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/simple-swizzle": {
|
||||||
|
"version": "0.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||||
|
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
|
||||||
|
"dependencies": {
|
||||||
|
"is-arrayish": "^0.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/slash": {
|
"node_modules/slash": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||||
@ -4819,11 +5211,18 @@
|
|||||||
"version": "3.0.3",
|
"version": "3.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
|
||||||
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
|
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
|
||||||
"optional": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"memory-pager": "^1.0.2"
|
"memory-pager": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/stack-trace": {
|
||||||
|
"version": "0.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
||||||
|
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/streamsearch": {
|
"node_modules/streamsearch": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||||
@ -5125,6 +5524,11 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/text-hex": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
|
||||||
|
},
|
||||||
"node_modules/text-table": {
|
"node_modules/text-table": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
||||||
@ -5175,6 +5579,14 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/triple-beam": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ts-api-utils": {
|
"node_modules/ts-api-utils": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
|
||||||
@ -5193,6 +5605,14 @@
|
|||||||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/ts-nkeys": {
|
||||||
|
"version": "1.0.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-nkeys/-/ts-nkeys-1.0.16.tgz",
|
||||||
|
"integrity": "sha512-1qrhAlavbm36wtW+7NtKOgxpzl+70NTF8xlz9mEhiA5zHMlMxjj3sEVKWm3pGZhHXE0Q3ykjrj+OSRVaYw+Dqg==",
|
||||||
|
"dependencies": {
|
||||||
|
"tweetnacl": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ts-node": {
|
"node_modules/ts-node": {
|
||||||
"version": "10.9.1",
|
"version": "10.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
|
||||||
@ -5257,6 +5677,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||||
},
|
},
|
||||||
|
"node_modules/tweetnacl": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
@ -5412,6 +5837,14 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/urljoin": {
|
||||||
|
"version": "0.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/urljoin/-/urljoin-0.1.5.tgz",
|
||||||
|
"integrity": "sha512-OSGi+PS3zxk8XfQ+7buaupOdrW9P9p+V9rjxGzJaYEYDe/B2rv3WJCupq5LNERW4w4kWxsduUUrhCxZZiQ2udw==",
|
||||||
|
"dependencies": {
|
||||||
|
"extend": "~2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/use-sync-external-store": {
|
"node_modules/use-sync-external-store": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
||||||
@ -5569,11 +6002,65 @@
|
|||||||
"string-width": "^1.0.2 || 2 || 3 || 4"
|
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/winston": {
|
||||||
|
"version": "3.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz",
|
||||||
|
"integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@colors/colors": "^1.6.0",
|
||||||
|
"@dabh/diagnostics": "^2.0.2",
|
||||||
|
"async": "^3.2.3",
|
||||||
|
"is-stream": "^2.0.0",
|
||||||
|
"logform": "^2.4.0",
|
||||||
|
"one-time": "^1.0.0",
|
||||||
|
"readable-stream": "^3.4.0",
|
||||||
|
"safe-stable-stringify": "^2.3.1",
|
||||||
|
"stack-trace": "0.0.x",
|
||||||
|
"triple-beam": "^1.3.0",
|
||||||
|
"winston-transport": "^4.5.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/winston-transport": {
|
||||||
|
"version": "4.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.6.0.tgz",
|
||||||
|
"integrity": "sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==",
|
||||||
|
"dependencies": {
|
||||||
|
"logform": "^2.3.2",
|
||||||
|
"readable-stream": "^3.6.0",
|
||||||
|
"triple-beam": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/wrappy": {
|
"node_modules/wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "7.5.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||||
|
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": "^5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/yallist": {
|
"node_modules/yallist": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
"name": "finvis",
|
"name": "finvis",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
@ -10,6 +9,7 @@
|
|||||||
"start": "next start"
|
"start": "next start"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@finvis/usxi": "^1.7.0",
|
||||||
"@t3-oss/env-nextjs": "^0.6.0",
|
"@t3-oss/env-nextjs": "^0.6.0",
|
||||||
"@tanstack/react-query": "^4.32.6",
|
"@tanstack/react-query": "^4.32.6",
|
||||||
"@trpc/client": "^10.37.1",
|
"@trpc/client": "^10.37.1",
|
||||||
@ -17,8 +17,9 @@
|
|||||||
"@trpc/react-query": "^10.37.1",
|
"@trpc/react-query": "^10.37.1",
|
||||||
"@trpc/server": "^10.37.1",
|
"@trpc/server": "^10.37.1",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"framer-motion": "^10.16.4",
|
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
|
"framer-motion": "^10.16.4",
|
||||||
|
"mongodb": "^6.2.0",
|
||||||
"mongoose": "^7.5.3",
|
"mongoose": "^7.5.3",
|
||||||
"next": "^13.4.19",
|
"next": "^13.4.19",
|
||||||
"next-auth": "^4.23.0",
|
"next-auth": "^4.23.0",
|
||||||
|
@ -1,23 +1,24 @@
|
|||||||
// Import required modules
|
// Import required modules
|
||||||
import mongoose from 'mongoose'
|
import mongoose from "mongoose";
|
||||||
import UserModel from '../models/users';
|
import { UserModel } from "../models/UserModel";
|
||||||
import * as dotenv from 'dotenv';
|
import * as dotenv from "dotenv";
|
||||||
|
import { api } from '../utils/api'
|
||||||
|
|
||||||
// Load the environment variables from the .env file
|
// Load the environment variables from the .env file
|
||||||
dotenv.config();
|
const dbconnect = async () => {
|
||||||
const url = process.env.MONGODB_URI;
|
dotenv.config();
|
||||||
|
const url = process.env.MONGODB_URI;
|
||||||
|
|
||||||
if (!url) {
|
if (!url) {
|
||||||
throw new Error('MONGODB_URI is not defined in the .env file.');
|
throw new Error("MONGODB_URI is not defined in the .env file.");
|
||||||
}
|
}
|
||||||
|
await mongoose
|
||||||
const dbconnect = async () =>{
|
.connect(url)
|
||||||
mongoose.connect(url)
|
.then(() => {
|
||||||
.then(() =>{
|
console.log("Connected to MongoDB");
|
||||||
console.log('Connected to MongoDB');
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Error connecting to MongoDB:', error);
|
console.error("Error connecting to MongoDB:", error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,16 +16,16 @@ const AnimatedWord: React.FC<AnimatedWordProps> = ({
|
|||||||
|
|
||||||
const container = {
|
const container = {
|
||||||
hidden: { opacity: 0 },
|
hidden: { opacity: 0 },
|
||||||
visible: (i = 1) => ({
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
transition: { staggerChildren: 0.12, delayChildren: 0.04 * i },
|
transition: { staggerChildren: 0.12, delayChildren: 0.04 },
|
||||||
}),
|
},
|
||||||
};
|
};
|
||||||
const child = {
|
const child = {
|
||||||
visible: {
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
y: 0,
|
y: 0,
|
||||||
x:0,
|
x: 0,
|
||||||
transition: {
|
transition: {
|
||||||
type: "spring",
|
type: "spring",
|
||||||
damping: 12,
|
damping: 12,
|
||||||
|
@ -16,16 +16,16 @@ const AnimatedText: React.FC<AnimatedTextProps> = ({
|
|||||||
|
|
||||||
const container = {
|
const container = {
|
||||||
hidden: { opacity: 0 },
|
hidden: { opacity: 0 },
|
||||||
visible: (i = 1) => ({
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
transition: { staggerChildren: 0.04, delayChildren: 0.04 * i },
|
transition: { staggerChildren: 0.04, delayChildren: 0.04 },
|
||||||
}),
|
},
|
||||||
};
|
};
|
||||||
const child = {
|
const child = {
|
||||||
visible: {
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
y: 0,
|
y: 0,
|
||||||
x:0,
|
x: 0,
|
||||||
transition: {
|
transition: {
|
||||||
type: "spring",
|
type: "spring",
|
||||||
damping: 12,
|
damping: 12,
|
||||||
|
@ -14,7 +14,7 @@ const WavingHand: React.FC = () => {
|
|||||||
transition={{
|
transition={{
|
||||||
delay: .7,
|
delay: .7,
|
||||||
duration: 1,
|
duration: 1,
|
||||||
onComplete : () => {
|
onComplete: () => {
|
||||||
const wavinghand = document.getElementById("waving-hand");
|
const wavinghand = document.getElementById("waving-hand");
|
||||||
if (wavinghand) {
|
if (wavinghand) {
|
||||||
wavinghand.style.display="none";
|
wavinghand.style.display="none";
|
||||||
|
@ -22,10 +22,12 @@ const Sidebar: React.FC = () => {
|
|||||||
setSidebarOpen(false);
|
setSidebarOpen(false);
|
||||||
};
|
};
|
||||||
const goToLogin = () => {
|
const goToLogin = () => {
|
||||||
router.push("/Login");
|
router.push("/Login")
|
||||||
|
.catch((err) => console.log(`Failed to navigate to login page with error: ${err}`));
|
||||||
};
|
};
|
||||||
const goToSignup = () => {
|
const goToSignup = () => {
|
||||||
router.push("/Signup");
|
router.push("/Signup")
|
||||||
|
.catch((err) => console.log(`Failed to navigate to signup page with error: ${err}`));
|
||||||
};
|
};
|
||||||
const barItems: SidebarItem[] = [
|
const barItems: SidebarItem[] = [
|
||||||
{
|
{
|
||||||
|
120
src/models/UserModel.ts
Normal file
120
src/models/UserModel.ts
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
import mongoose, {model, Schema } from 'mongoose';
|
||||||
|
import { type Action, ActionSide, type Position } from '@finvis/usxi';
|
||||||
|
|
||||||
|
interface InterfaceUsers{
|
||||||
|
email: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
apiKeys: {
|
||||||
|
name: string;
|
||||||
|
key: string;
|
||||||
|
iv: string;
|
||||||
|
}[];
|
||||||
|
value:{
|
||||||
|
amount: number;
|
||||||
|
date: string;
|
||||||
|
}[];
|
||||||
|
balance: {
|
||||||
|
amount: number;
|
||||||
|
date: string;
|
||||||
|
}[];
|
||||||
|
trades: Action[];
|
||||||
|
positions: Position[];
|
||||||
|
papervalue:{
|
||||||
|
amount: number;
|
||||||
|
date: string;
|
||||||
|
}[];
|
||||||
|
paperbalance: {
|
||||||
|
amount: number;
|
||||||
|
date: string;
|
||||||
|
}[];
|
||||||
|
papertrades: Action[];
|
||||||
|
paperpositions: Position[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const userSchema = new Schema<InterfaceUsers>({
|
||||||
|
email: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
unique: true
|
||||||
|
},
|
||||||
|
username: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
// Ensure username is unique in the dataset:
|
||||||
|
unique: true,
|
||||||
|
},
|
||||||
|
password: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
apiKeys: [
|
||||||
|
{
|
||||||
|
name: String,
|
||||||
|
key: String,
|
||||||
|
iv: String,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
amount: Number,
|
||||||
|
date: String,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
balance: [
|
||||||
|
{
|
||||||
|
amount: Number,
|
||||||
|
date: String,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
trades: [
|
||||||
|
{
|
||||||
|
symbol: String,
|
||||||
|
quantity: Number,
|
||||||
|
side: ActionSide,
|
||||||
|
pricePerShare: Number,
|
||||||
|
timestamp: Date,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
positions: [
|
||||||
|
{
|
||||||
|
symbol: String,
|
||||||
|
quantity: Number,
|
||||||
|
marketValue: Number,
|
||||||
|
costBasis: Number,
|
||||||
|
pricePerShare: Number,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
papervalue: [
|
||||||
|
{
|
||||||
|
amount: Number,
|
||||||
|
date: String,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
paperbalance: [
|
||||||
|
{
|
||||||
|
amount: Number,
|
||||||
|
date: String,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
papertrades: [
|
||||||
|
{
|
||||||
|
symbol: String,
|
||||||
|
quantity: Number,
|
||||||
|
side: ActionSide,
|
||||||
|
pricePerShare: Number,
|
||||||
|
timestamp: Date,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
paperpositions: [
|
||||||
|
{
|
||||||
|
symbol: String,
|
||||||
|
quantity: Number,
|
||||||
|
marketValue: Number,
|
||||||
|
costBasis: Number,
|
||||||
|
pricePerShare: Number,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const UserModel = model<InterfaceUsers>('users', userSchema);
|
@ -1,29 +0,0 @@
|
|||||||
import mongoose from 'mongoose';
|
|
||||||
|
|
||||||
const userSchema = new mongoose.Schema({
|
|
||||||
email: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
unique: true
|
|
||||||
},
|
|
||||||
username: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
unique: true, // Ensures username is unique in the dataset
|
|
||||||
},
|
|
||||||
password: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
apiKeys: [
|
|
||||||
{
|
|
||||||
name: String,
|
|
||||||
key: String,
|
|
||||||
iv: String,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const UserModel = mongoose.model('User', userSchema);
|
|
||||||
|
|
||||||
export default UserModel;
|
|
@ -3,18 +3,39 @@ import Link from "next/link";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import CustomInput from "~/components/CustomInput";
|
import CustomInput from "~/components/CustomInput";
|
||||||
import { IoReturnDownBackOutline } from "react-icons/io5";
|
import { IoReturnDownBackOutline } from "react-icons/io5";
|
||||||
|
import { api } from "~/utils/api";
|
||||||
|
|
||||||
const Login: React.FC = () => {
|
const Login: React.FC = () => {
|
||||||
const [ username, setUserName ] = useState<string>("");
|
const [ username, setUserName ] = useState<string>("");
|
||||||
const [ password, setPassword ] = useState<string>("");
|
const [ password, setPassword ] = useState<string>("");
|
||||||
|
|
||||||
|
const mutation = api.login.Login.useMutation({
|
||||||
|
onSuccess: async () => {
|
||||||
|
alert("Log in successful");
|
||||||
|
await router.push("/");
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.log(error);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
|
const login = (event: React.FormEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
mutation.mutate({
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const returnHome = () => {
|
const returnHome = () => {
|
||||||
router.push("/");
|
router.push("/")
|
||||||
|
.catch((err) => console.log(`Failed to navigate to home page with error: ${err}`));
|
||||||
};
|
};
|
||||||
const goToSignup = () => {
|
const goToSignup = () => {
|
||||||
router.push("/Signup");
|
router.push("/Signup")
|
||||||
|
.catch((err) => console.log(`Failed to navigate to signup page with error: ${err}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -26,7 +47,7 @@ const Login: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<h1>FinVis</h1>
|
<h1>FinVis</h1>
|
||||||
</div>
|
</div>
|
||||||
<form className="login-form" action="POST">
|
<form onSubmit={login} className="login-form" action="POST">
|
||||||
<CustomInput
|
<CustomInput
|
||||||
type="text"
|
type="text"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
112
src/pages/Settings.tsx
Normal file
112
src/pages/Settings.tsx
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import Collapsible from 'react-collapsible';
|
||||||
|
import Layout from "~/components/global/Layout";
|
||||||
|
import { api } from "~/utils/api";
|
||||||
|
// ... (other imports and code)
|
||||||
|
|
||||||
|
const Settings: React.FC = () => {
|
||||||
|
const [apiKey, setApiKey] = useState({
|
||||||
|
username: '',
|
||||||
|
apiKey: {
|
||||||
|
name: '',
|
||||||
|
key: '',
|
||||||
|
iv: '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const [password, setPassword] = useState({
|
||||||
|
oldPass: '',
|
||||||
|
newPass: '',
|
||||||
|
newConfirm: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const addAPIKeys = api.user.addUserApiKey.useMutation();
|
||||||
|
const changePassword = api.user.changeUserPass.useMutation();
|
||||||
|
|
||||||
|
const handleAddApiKey = async () => {
|
||||||
|
try {
|
||||||
|
await addAPIKeys.mutate({ ...apiKey });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error adding API key:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangePassword = async () => {
|
||||||
|
try {
|
||||||
|
await changePassword.mutate({ ...password, username: apiKey.username });
|
||||||
|
// Optionally, you can handle success here, e.g., show a success message.
|
||||||
|
} catch (error) {
|
||||||
|
// Handle errors, e.g., show an error message.
|
||||||
|
console.error('Error changing password:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<div className="flex flex-col justify-center items-center h-full">
|
||||||
|
<Collapsible trigger="Account">
|
||||||
|
|
||||||
|
</Collapsible>
|
||||||
|
<Collapsible trigger="Privacy and Security">
|
||||||
|
{/* Privacy and Security content here */}
|
||||||
|
<p>Privacy and Security</p>
|
||||||
|
|
||||||
|
<p>ADD API KEYS</p>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Username"
|
||||||
|
value={apiKey.username}
|
||||||
|
onChange={(e) => setApiKey({ ...apiKey, username: e.target.value })}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="API Key Name"
|
||||||
|
value={apiKey.apiKey.name}
|
||||||
|
onChange={(e) => setApiKey({ ...apiKey, apiKey: { ...apiKey.apiKey, name: e.target.value } })}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="API Key"
|
||||||
|
value={apiKey.apiKey.key}
|
||||||
|
onChange={(e) => setApiKey({ ...apiKey, apiKey: { ...apiKey.apiKey, key: e.target.value } })}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="IV"
|
||||||
|
value={apiKey.apiKey.iv}
|
||||||
|
onChange={(e) => setApiKey({ ...apiKey, apiKey: { ...apiKey.apiKey, iv: e.target.value } })}
|
||||||
|
/>
|
||||||
|
<button onClick={handleAddApiKey}>Add API Key</button>
|
||||||
|
|
||||||
|
{/* Change Password feature */}
|
||||||
|
<p>CHANGE PASSWORD</p>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
placeholder="Old Password"
|
||||||
|
value={password.oldPass}
|
||||||
|
onChange={(e) => setPassword({ ...password, oldPass: e.target.value })}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
placeholder="New Password"
|
||||||
|
value={password.newPass}
|
||||||
|
onChange={(e) => setPassword({ ...password, newPass: e.target.value })}
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
placeholder="Confirm New Password"
|
||||||
|
value={password.newConfirm}
|
||||||
|
onChange={(e) => setPassword({ ...password, newConfirm: e.target.value })}
|
||||||
|
/>
|
||||||
|
<button onClick={handleChangePassword}>Change Password</button>
|
||||||
|
</Collapsible>
|
||||||
|
|
||||||
|
<Collapsible trigger="Help and Support">
|
||||||
|
<p>Contact Mr. Girouard</p>
|
||||||
|
</Collapsible>
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Settings;
|
@ -3,20 +3,42 @@ import Link from "next/link";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import CustomInput from "~/components/CustomInput";
|
import CustomInput from "~/components/CustomInput";
|
||||||
import { IoReturnDownBackOutline } from "react-icons/io5";
|
import { IoReturnDownBackOutline } from "react-icons/io5";
|
||||||
|
import { api } from "~/utils/api";
|
||||||
|
|
||||||
const Signup: React.FC = () => {
|
const Signup: React.FC = () => {
|
||||||
const [ username, setUserName ] = useState<string>("");
|
const [ username, setUserName ] = useState<string>("");
|
||||||
const [ email, setEmail ] = useState<string>("");
|
const [ email, setEmail ] = useState<string>("");
|
||||||
const [ password, setPassword ] = useState<string>("");
|
const [ password, setPassword ] = useState<string>("");
|
||||||
|
|
||||||
|
const mutation = api.login.create_account.useMutation({
|
||||||
|
onSuccess: async () => {
|
||||||
|
alert("Registration Complete! Now login.");
|
||||||
|
await router.push("/Login");
|
||||||
|
},
|
||||||
|
onError: (error) => {
|
||||||
|
console.log(error);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const returnHome = () => {
|
const returnHome = () => {
|
||||||
router.push("/");
|
router.push("/")
|
||||||
|
.catch((err) => console.log(`Failed to navigate to home page with error: ${err}`));
|
||||||
};
|
};
|
||||||
const goToLogin = () => {
|
const goToLogin = () => {
|
||||||
router.push("/Login");
|
router.push("/Login")
|
||||||
}
|
.catch((err) => console.log(`Failed to navigate to login page with error: ${err}`));
|
||||||
|
};
|
||||||
|
const signup = (event: React.FormEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
mutation.mutate({
|
||||||
|
email: email,
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="signup-container">
|
<div className="signup-container">
|
||||||
<IoReturnDownBackOutline onClick={returnHome} className="return" />
|
<IoReturnDownBackOutline onClick={returnHome} className="return" />
|
||||||
@ -26,7 +48,7 @@ const Signup: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
<h1>FinVis</h1>
|
<h1>FinVis</h1>
|
||||||
</div>
|
</div>
|
||||||
<form className="signup-form" action="POST">
|
<form onSubmit={signup} className="signup-form" action="POST">
|
||||||
<CustomInput
|
<CustomInput
|
||||||
type="text"
|
type="text"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
@ -8,6 +8,7 @@ import "~/styles/globals.css";
|
|||||||
import "~/styles/sidebar.css";
|
import "~/styles/sidebar.css";
|
||||||
import "~/styles/login.css";
|
import "~/styles/login.css";
|
||||||
import "~/styles/signup.css";
|
import "~/styles/signup.css";
|
||||||
|
import "~/styles/collapsible.css";
|
||||||
|
|
||||||
const MyApp: AppType<{ session: Session | null }> = ({
|
const MyApp: AppType<{ session: Session | null }> = ({
|
||||||
Component,
|
Component,
|
||||||
|
@ -11,35 +11,36 @@ import { api } from "~/utils/api";
|
|||||||
import Layout from "~/components/global/Layout";
|
import Layout from "~/components/global/Layout";
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const hello = api.example.hello.useQuery({ text: "from tRPC" });
|
|
||||||
const { data: sessionData } = useSession();
|
const { data: sessionData } = useSession();
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const container = {
|
const container = {
|
||||||
hidden: { opacity: 0 },
|
hidden: { opacity: 0 },
|
||||||
visible: (i = 1) => ({
|
visible: {
|
||||||
opacity: 1,
|
opacity: 1,
|
||||||
transition: { delay: 0.5 },
|
transition: { delay: 0.5 },
|
||||||
}),
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToSignup = () => {
|
const goToSignup = () => {
|
||||||
router.push("/Signup");
|
router.push("/Signup")
|
||||||
|
.catch((err) => console.log(`Failed to navigate to signup page with error: ${err}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
const goToLogin = () => {
|
const goToLogin = () => {
|
||||||
router.push("/Login");
|
router.push("/Login")
|
||||||
|
.catch((err) => console.log(`Failed to navigate to login page with error: ${err}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Layout>
|
<Layout>
|
||||||
<div className="home-container">
|
<div className="home-container flex justify-center items-center h-full ">
|
||||||
{sessionData ? (
|
{sessionData ? (
|
||||||
<div className="signed-in"></div>
|
<div className="signed-in"></div>
|
||||||
) : (
|
) : (
|
||||||
<div className="not-signed-in mt-25 flex flex-col items-center justify-center">
|
<div className="not-signed-in flex flex-col items-center justify-center -mt-14">
|
||||||
<div className="welcome-message flex">
|
<div className="welcome-message flex">
|
||||||
<WavingHand />
|
<WavingHand />
|
||||||
<AnimatedWord
|
<AnimatedWord
|
||||||
@ -66,7 +67,8 @@ export default function Home() {
|
|||||||
className="login-signup flex flex-col items-center justify-center mt-20"
|
className="login-signup flex flex-col items-center justify-center mt-20"
|
||||||
>
|
>
|
||||||
<motion.button
|
<motion.button
|
||||||
className="signup-button w-60 rounded-lg bg-initial-home-buttons pb-3 pl-4 pr-4 pt-3 text-xl font-bold text-gray-700"
|
className="signup-button w-60 rounded-lg bg-initial-home-buttons pb-3 pl-4 pr-4 pt-3 text-xl
|
||||||
|
font-bold text-gray-700"
|
||||||
whileHover={{ scale: 1.1 }}
|
whileHover={{ scale: 1.1 }}
|
||||||
whileTap={{ scale: 0.9 }}
|
whileTap={{ scale: 0.9 }}
|
||||||
onClick={goToSignup}
|
onClick={goToSignup}
|
||||||
@ -78,7 +80,8 @@ export default function Home() {
|
|||||||
whileHover={{ scale: 1.1 }}
|
whileHover={{ scale: 1.1 }}
|
||||||
whileTap={{ scale: 0.9 }}
|
whileTap={{ scale: 0.9 }}
|
||||||
onClick={goToLogin}
|
onClick={goToLogin}
|
||||||
className="login-button w-60 rounded-lg bg-initial-home-buttons pb-3 pl-4 pr-4 pt-3 text-xl font-bold text-gray-700"
|
className="login-button w-60 rounded-lg bg-initial-home-buttons pb-3 pl-4 pr-4 pt-3 text-xl
|
||||||
|
font-bold text-gray-700"
|
||||||
>
|
>
|
||||||
Login
|
Login
|
||||||
</motion.button>
|
</motion.button>
|
||||||
@ -91,6 +94,8 @@ export default function Home() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Commenting out as this is just for the default example router
|
||||||
|
/*
|
||||||
const AuthShowcase = () => {
|
const AuthShowcase = () => {
|
||||||
const { data: sessionData } = useSession();
|
const { data: sessionData } = useSession();
|
||||||
|
|
||||||
@ -119,3 +124,4 @@ const AuthShowcase = () => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { exampleRouter } from "~/server/api/routers/example";
|
|
||||||
import { createTRPCRouter } from "~/server/api/trpc";
|
import { createTRPCRouter } from "~/server/api/trpc";
|
||||||
import { loginRouter } from "./routers/login";
|
import { loginRouter } from "./routers/login";
|
||||||
|
import { userRouter } from "./routers/user";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the primary router for your server.
|
* This is the primary router for your server.
|
||||||
@ -8,8 +8,8 @@ import { loginRouter } from "./routers/login";
|
|||||||
* All routers added in /api/routers should be manually added here.
|
* All routers added in /api/routers should be manually added here.
|
||||||
*/
|
*/
|
||||||
export const appRouter = createTRPCRouter({
|
export const appRouter = createTRPCRouter({
|
||||||
example: exampleRouter,
|
|
||||||
login: loginRouter,
|
login: loginRouter,
|
||||||
|
user: userRouter,
|
||||||
});
|
});
|
||||||
|
|
||||||
// export type definition of API
|
// export type definition of API
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
import { z } from "zod";
|
|
||||||
|
|
||||||
import {
|
|
||||||
createTRPCRouter,
|
|
||||||
protectedProcedure,
|
|
||||||
publicProcedure,
|
|
||||||
} from "~/server/api/trpc";
|
|
||||||
|
|
||||||
export const exampleRouter = createTRPCRouter({
|
|
||||||
hello: publicProcedure
|
|
||||||
.input(z.object({ text: z.string() }))
|
|
||||||
.query(({ input }) => {
|
|
||||||
return {
|
|
||||||
greeting: `Hello ${input.text}`,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
getSecretMessage: protectedProcedure.query(() => {
|
|
||||||
return "you can now see this secret message!";
|
|
||||||
}),
|
|
||||||
});
|
|
@ -6,7 +6,9 @@ import {
|
|||||||
protectedProcedure,
|
protectedProcedure,
|
||||||
publicProcedure,
|
publicProcedure,
|
||||||
} from "~/server/api/trpc";
|
} from "~/server/api/trpc";
|
||||||
|
import { TRPCError } from "@trpc/server";
|
||||||
|
|
||||||
|
import { UserModel } from "~/models/UserModel";
|
||||||
|
|
||||||
// Main login router for backend
|
// Main login router for backend
|
||||||
export const loginRouter = createTRPCRouter({
|
export const loginRouter = createTRPCRouter({
|
||||||
@ -15,46 +17,58 @@ export const loginRouter = createTRPCRouter({
|
|||||||
.input(z.object({email: z.string(), username: z.string(), password: z.string()}))
|
.input(z.object({email: z.string(), username: z.string(), password: z.string()}))
|
||||||
.mutation(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
// Encryption using bcrypt salt and pepper hashing
|
// Encryption using bcrypt salt and pepper hashing
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
const userEmail = await UserModel.findOne({email: input.email});
|
||||||
|
if (user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Username is already taken!",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (userEmail) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Email is already taken!",
|
||||||
|
})
|
||||||
|
}
|
||||||
const saltRounds = 10;
|
const saltRounds = 10;
|
||||||
let password_hash = "";
|
const hashedPassword: string = await bcrypt.hash(input.password, saltRounds);
|
||||||
|
|
||||||
bcrypt.hash(input.password, saltRounds, (err,hash) => {
|
|
||||||
password_hash = hash;
|
|
||||||
});
|
|
||||||
// Store in database
|
// Store in database
|
||||||
const userModelData = ctx.UserModel().create({
|
const newUser = await UserModel.create({username: input.username,
|
||||||
username: input.username,
|
email: input.email ,
|
||||||
password: password_hash,
|
password: hashedPassword });
|
||||||
email: input.email,
|
await newUser.save();
|
||||||
});
|
// Return greeting Żnformation
|
||||||
// Return greeting information
|
|
||||||
return {
|
return {
|
||||||
user_info: userModelData
|
user_info: newUser
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|
||||||
login: publicProcedure
|
Login: publicProcedure
|
||||||
.input(z.object({ username: z.string(), password: z.string(), }))
|
.input(z.object({ username: z.string(), password: z.string()}))
|
||||||
.query(async ({ ctx, input }) => {
|
.mutation(async ({ ctx, input }) => {
|
||||||
// Encryption using bcrypt salt and pepper hashing
|
// Encryption using bcrypt salt and pepper hashing
|
||||||
const saltRounds = 10;
|
const saltRounds = 10;
|
||||||
// Get hash from database
|
// Get hash from database
|
||||||
const password_hash = ctx.UserModel.find({username: input.username},'password');
|
const user = await UserModel.findOne({username: input.username});
|
||||||
let is_valid = false;
|
if (!user) {
|
||||||
bcrypt.compare(input.password, password_hash, (err, result) => {
|
throw new TRPCError ({
|
||||||
// returns result
|
code: "BAD_REQUEST",
|
||||||
is_valid = result;
|
message: "User doesn't exist",
|
||||||
});
|
})
|
||||||
// Return for sign in
|
|
||||||
if(is_valid) {
|
|
||||||
return {
|
|
||||||
user: ctx.UserModel.find({username: input.username}),
|
|
||||||
success: true,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
const isPasswordValid = await bcrypt.compare(input.password, user.password);
|
||||||
|
if (!isPasswordValid) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Username or Password is incorrect",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// Return for sign in
|
||||||
return {
|
return {
|
||||||
user: null,
|
user: user,
|
||||||
success: false,
|
success: true,
|
||||||
};
|
message: "Successfully logged in!",
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
500
src/server/api/routers/user.ts
Normal file
500
src/server/api/routers/user.ts
Normal file
@ -0,0 +1,500 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
import bcrypt from "bcrypt";
|
||||||
|
import { type Action } from '@finvis/usxi'
|
||||||
|
|
||||||
|
import {
|
||||||
|
createTRPCRouter,
|
||||||
|
protectedProcedure,
|
||||||
|
publicProcedure,
|
||||||
|
} from "~/server/api/trpc";
|
||||||
|
import { UserModel } from "~/models/UserModel";
|
||||||
|
import { TRPCError } from "@trpc/server";
|
||||||
|
|
||||||
|
|
||||||
|
// Main login router for backend
|
||||||
|
export const userRouter = createTRPCRouter({
|
||||||
|
|
||||||
|
// Function to add a Api Key to a user
|
||||||
|
addUserApiKey: protectedProcedure
|
||||||
|
.input(z.object({username: z.string(), apiKey: z.object({name: z.string(), key: z.string(), iv: z.string()}) }))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User not found",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the new API key to the user's array
|
||||||
|
user.apiKeys.push(input.apiKey);
|
||||||
|
|
||||||
|
// Save new user
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
// Return greeting information
|
||||||
|
return {
|
||||||
|
user_info: user
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Function to get a users Api Keys
|
||||||
|
getUserApiKeys: protectedProcedure
|
||||||
|
.input(z.object({ username: z.string()}))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User doesn't exist",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has API keys
|
||||||
|
if (!user.apiKeys || user.apiKeys.length) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User has no api keys",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a list of the users API keys
|
||||||
|
return user.apiKeys
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Function to change a users password
|
||||||
|
changeUserPass: protectedProcedure
|
||||||
|
.input(z.object({username: z.string(), oldPass: z.string(), newPass: z.string(), newConfirm: z.string()}))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User not found",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check password validity
|
||||||
|
const isPasswordValid = await bcrypt.compare(input.oldPass, user.password);
|
||||||
|
if (!isPasswordValid) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "Username or Password is incorrect",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check new passwords
|
||||||
|
if (input.newPass !== input.newConfirm) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "New passwords do not match",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const saltRounds = 10;
|
||||||
|
const hashedPassword: string = await bcrypt.hash(input.newPass, saltRounds);
|
||||||
|
|
||||||
|
// Update password
|
||||||
|
user.password = hashedPassword
|
||||||
|
|
||||||
|
// Save new user information
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
// Return updated information
|
||||||
|
return {
|
||||||
|
user_info: user
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Add new balance to user
|
||||||
|
putUserBalanceHist: protectedProcedure
|
||||||
|
.input(z.object({username: z.string(), balance: z.object({ amount: z.number(), date: z.string() })}))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User not found",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
user.balance.push(input.balance);
|
||||||
|
|
||||||
|
// Save new user information
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
// Return updated information
|
||||||
|
return {
|
||||||
|
user_info: user
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Function to get a users balance history
|
||||||
|
getUserBalanceHist: protectedProcedure
|
||||||
|
.input(z.object({ username: z.string(), amount: z.number() }))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User doesn't exist",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has API keys
|
||||||
|
if (!user.balance || user.balance.length === 0) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User has no balance history",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.balance.length < input.amount) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User only has length ${user.balance.length} balance history",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(input.amount === -1){
|
||||||
|
return user.balance
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastBalances = await UserModel.findOne({username: input.username})
|
||||||
|
// Select only balance
|
||||||
|
.select('balance')
|
||||||
|
// Get last n items
|
||||||
|
.slice('balance', -input.amount)
|
||||||
|
// Convert to JavaScript object
|
||||||
|
.lean()
|
||||||
|
|
||||||
|
return lastBalances
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
// Add new trade to user
|
||||||
|
putUserTradeHist: protectedProcedure
|
||||||
|
.input(z.object({username: z.string(), trade: z.custom<Action>()}))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User not found",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
user.trades.push(input.trade);
|
||||||
|
|
||||||
|
// Save new user information
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
// Return updated information
|
||||||
|
return {
|
||||||
|
user_info: user
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Function to get a users Trade history
|
||||||
|
getUserTradeHist: protectedProcedure
|
||||||
|
.input(z.object({ username: z.string(), amount: z.number() }))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User doesn't exist",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has API keys
|
||||||
|
if (!user.trades || user.trades.length === 0) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User has no trades history",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.trades.length < input.amount) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User only has length ${user.trades.length} balance history",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(input.amount === -1){
|
||||||
|
return user.trades
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastTrades = await UserModel.findOne({username: input.username})
|
||||||
|
// Select only balance
|
||||||
|
.select('trades')
|
||||||
|
// Get last n items
|
||||||
|
.slice('trades', -input.amount)
|
||||||
|
// Convert to JavaScript object
|
||||||
|
.lean()
|
||||||
|
|
||||||
|
return lastTrades
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
// Add new position to user
|
||||||
|
putUserPositions: protectedProcedure
|
||||||
|
.input(z.object({username: z.string(), position: z.object({ symbol: z.string(),
|
||||||
|
quantity: z.number(), marketValue: z.number(), costBasis: z.number(), pricePerShare: z.number(), })}))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User not found",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
user.positions.push(input.position);
|
||||||
|
|
||||||
|
// Save new user information
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
// Return updated information
|
||||||
|
return {
|
||||||
|
user_info: user
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Function to get a users positions
|
||||||
|
getUserPositions: protectedProcedure
|
||||||
|
.input(z.object({ username: z.string()}))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User doesn't exist",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has API keys
|
||||||
|
if (!user.positions || user.positions.length === 0) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User has no positions",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return user.positions
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
//Paper trading function
|
||||||
|
|
||||||
|
|
||||||
|
// Add new balance to user
|
||||||
|
putPaperBalanceHist: protectedProcedure
|
||||||
|
.input(z.object({username: z.string(), balance: z.object({ amount: z.number(), date: z.string() })}))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User not found",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
user.paperbalance.push(input.balance);
|
||||||
|
|
||||||
|
// Save new user information
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
// Return updated information
|
||||||
|
return {
|
||||||
|
user_info: user
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Function to get a users balance history
|
||||||
|
getPaperBalanceHist: protectedProcedure
|
||||||
|
.input(z.object({ username: z.string(), amount: z.number() }))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User doesn't exist",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has API keys
|
||||||
|
if (!user.paperbalance || user.paperbalance.length === 0) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User has no balance history",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.paperbalance.length < input.amount) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User only has length ${user.balance.length} balance history",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(input.amount === -1){
|
||||||
|
return user.paperbalance
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastBalances = await UserModel.findOne({username: input.username})
|
||||||
|
// Select only balance
|
||||||
|
.select('paperbalance')
|
||||||
|
// Get last n items
|
||||||
|
.slice('paperbalance', -input.amount)
|
||||||
|
// Convert to JavaScript object
|
||||||
|
.lean()
|
||||||
|
|
||||||
|
return lastBalances
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
// Add new trade to user
|
||||||
|
putPaperTradeHist: protectedProcedure
|
||||||
|
.input(z.object({username: z.string(), trade: z.custom<Action>()}))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User not found",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
user.papertrades.push(input.trade);
|
||||||
|
|
||||||
|
// Save new user information
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
// Return updated information
|
||||||
|
return {
|
||||||
|
user_info: user
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Function to get a users Trade history
|
||||||
|
getPaperTradeHist: protectedProcedure
|
||||||
|
.input(z.object({ username: z.string(), amount: z.number() }))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User doesn't exist",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has API keys
|
||||||
|
if (!user.papertrades || user.papertrades.length === 0) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User has no trades history",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(user.papertrades.length < input.amount) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User only has length ${user.trades.length} balance history",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if(input.amount === -1){
|
||||||
|
return user.papertrades
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastTrades = await UserModel.findOne({username: input.username})
|
||||||
|
// Select only balance
|
||||||
|
.select('papertrades')
|
||||||
|
// Get last n items
|
||||||
|
.slice('papertrades', -input.amount)
|
||||||
|
// Convert to JavaScript object
|
||||||
|
.lean()
|
||||||
|
|
||||||
|
return lastTrades
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
// Add new position to user
|
||||||
|
putPaperPositions: protectedProcedure
|
||||||
|
.input(z.object({username: z.string(), position: z.object({ symbol: z.string(),
|
||||||
|
quantity: z.number(), marketValue: z.number(), costBasis: z.number(), pricePerShare: z.number(), })}))
|
||||||
|
.mutation(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User not found",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
user.paperpositions.push(input.position);
|
||||||
|
|
||||||
|
// Save new user information
|
||||||
|
await user.save();
|
||||||
|
|
||||||
|
// Return updated information
|
||||||
|
return {
|
||||||
|
user_info: user
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
// Function to get a users positions
|
||||||
|
getPaperPositions: protectedProcedure
|
||||||
|
.input(z.object({ username: z.string()}))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const user = await UserModel.findOne({username: input.username});
|
||||||
|
|
||||||
|
// Check if user exists
|
||||||
|
if (!user) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User doesn't exist",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has positions
|
||||||
|
if (!user.paperpositions || user.paperpositions.length === 0) {
|
||||||
|
throw new TRPCError ({
|
||||||
|
code: "BAD_REQUEST",
|
||||||
|
message: "User has no positions",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return user.paperpositions
|
||||||
|
}),
|
||||||
|
});
|
@ -11,7 +11,7 @@ import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
|
|||||||
import { type Session } from "next-auth";
|
import { type Session } from "next-auth";
|
||||||
import superjson from "superjson";
|
import superjson from "superjson";
|
||||||
import { ZodError } from "zod";
|
import { ZodError } from "zod";
|
||||||
|
import { dbconnect } from "~/clients/mongoose";
|
||||||
import { getServerAuthSession } from "~/server/auth";
|
import { getServerAuthSession } from "~/server/auth";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,11 +36,11 @@ interface CreateContextOptions {
|
|||||||
*
|
*
|
||||||
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
|
* @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
|
||||||
*/
|
*/
|
||||||
const createInnerTRPCContext = (opts: CreateContextOptions) => {
|
const createInnerTRPCContext = async (opts: CreateContextOptions) => {
|
||||||
// Connect our database in inner context
|
// Connect our database in inner context
|
||||||
|
await dbconnect();
|
||||||
return {
|
return {
|
||||||
session: opts.session,
|
session: opts.session,
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -80,6 +80,7 @@ const t = initTRPC.context<typeof createTRPCContext>().create({
|
|||||||
zodError:
|
zodError:
|
||||||
error.cause instanceof ZodError ? error.cause.flatten() : null,
|
error.cause instanceof ZodError ? error.cause.flatten() : null,
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
29
src/styles/collapsible.css
Normal file
29
src/styles/collapsible.css
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
.Collapsible {
|
||||||
|
width: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Collapsible__contentInner {
|
||||||
|
padding: 10px;
|
||||||
|
background-color: rgb(223, 216, 216);
|
||||||
|
border: 1px solid white;
|
||||||
|
border-top: 0;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.Collapsible__trigger {
|
||||||
|
display: block;
|
||||||
|
font-weight: 700;
|
||||||
|
font-family: "Poppins", sans-serif;
|
||||||
|
position: relative;
|
||||||
|
padding: 10px;
|
||||||
|
background: #186d49;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -89,7 +89,7 @@
|
|||||||
|
|
||||||
.login-form .input-box input:valid ~ i,
|
.login-form .input-box input:valid ~ i,
|
||||||
.login-form .input-box input:focus ~ i {
|
.login-form .input-box input:focus ~ i {
|
||||||
height: 6vh;
|
height: 6.8vh;
|
||||||
}
|
}
|
||||||
.login-form .forgot-pw {
|
.login-form .forgot-pw {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
}
|
}
|
||||||
.signup-form .input-box:first-child {
|
.signup-form .input-box:first-child {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 4vh;
|
margin-top: 2vh;
|
||||||
}
|
}
|
||||||
.signup-form .input-box input {
|
.signup-form .input-box input {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -93,7 +93,7 @@
|
|||||||
|
|
||||||
.signup-form .input-box input:valid ~ i,
|
.signup-form .input-box input:valid ~ i,
|
||||||
.signup-form .input-box input:focus ~ i {
|
.signup-form .input-box input:focus ~ i {
|
||||||
height: 6vh;
|
height: 6.8vh;
|
||||||
}
|
}
|
||||||
.signup-form .forgot-pw {
|
.signup-form .forgot-pw {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
@ -12,7 +12,7 @@ export default {
|
|||||||
},
|
},
|
||||||
backgroundColor : {
|
backgroundColor : {
|
||||||
'initial-home-buttons' : '#64a88c',
|
'initial-home-buttons' : '#64a88c',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
|
Reference in New Issue
Block a user