mirror of
https://github.com/diced/zipline.git
synced 2025-05-11 10:26:05 +02:00
feat: stuffs
This commit is contained in:
parent
8775ae2e29
commit
e4761c3f12
49 changed files with 1302 additions and 866 deletions
|
@ -1,11 +1,6 @@
|
||||||
/** @type {import('eslint').Linter.Config} */
|
/** @type {import('eslint').Linter.Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: [
|
extends: ['next/core-web-vitals', 'plugin:prettier/recommended', 'plugin:@typescript-eslint/recommended'],
|
||||||
'@remix-run/eslint-config',
|
|
||||||
'@remix-run/eslint-config/node',
|
|
||||||
'plugin:prettier/recommended',
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
],
|
|
||||||
root: true,
|
root: true,
|
||||||
plugins: ['unused-imports', '@typescript-eslint'],
|
plugins: ['unused-imports', '@typescript-eslint'],
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
|
|
33
.gitignore
vendored
33
.gitignore
vendored
|
@ -1,18 +1,28 @@
|
||||||
node_modules
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
/.cache
|
# dependencies
|
||||||
/build
|
/node_modules
|
||||||
/public/build
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
# yarn
|
# yarn
|
||||||
.yarn/*
|
.yarn/*
|
||||||
!.yarn/releases
|
!.yarn/releases
|
||||||
!.yarn/plugins
|
!.yarn/plugins
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
*.pem
|
*.pem
|
||||||
.idea
|
|
||||||
|
|
||||||
# debug
|
# debug
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
|
@ -20,15 +30,14 @@ yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env
|
.env*
|
||||||
.env.local
|
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
|
|
||||||
# vercel
|
# vercel
|
||||||
.vercel
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
# zipline
|
# zipline
|
||||||
uploads*/
|
uploads*/
|
||||||
dist/
|
|
6
next.config.js
Normal file
6
next.config.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = nextConfig
|
21
package.json
21
package.json
|
@ -6,13 +6,12 @@
|
||||||
"version": "4.0.0-dev.1",
|
"version": "4.0.0-dev.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "run-s build:*",
|
"build": "run-s build:*",
|
||||||
"build:remix": "remix build",
|
"build:remix": "next build",
|
||||||
"build:server": "tsup",
|
"build:server": "tsup",
|
||||||
"dev": "run-p dev:remix & (run-s dev:build && run-s dev:server)",
|
"dev": "run-s dev:build dev:server",
|
||||||
"dev:build": "cross-env NODE_ENV=development run-s build:server",
|
"dev:build": "cross-env NODE_ENV=development run-s build:server",
|
||||||
"dev:remix": "cross-env NODE_ENV=development remix watch",
|
|
||||||
"dev:server": "cross-env NODE_ENV=development DEBUG=zipline node --require ./node_modules/dotenv/config ./build/server.js",
|
"dev:server": "cross-env NODE_ENV=development DEBUG=zipline node --require ./node_modules/dotenv/config ./build/server.js",
|
||||||
"start": "node ./server.mjs",
|
"start": "node ./build/server.mjs",
|
||||||
"lint": "eslint --cache --ignore-path .gitignore --fix .",
|
"lint": "eslint --cache --ignore-path .gitignore --fix .",
|
||||||
"format": "prettier --write --ignore-path .gitignore .",
|
"format": "prettier --write --ignore-path .gitignore .",
|
||||||
"validate": "run-p lint format"
|
"validate": "run-p lint format"
|
||||||
|
@ -26,23 +25,20 @@
|
||||||
"@mantine/form": "^6.0.14",
|
"@mantine/form": "^6.0.14",
|
||||||
"@mantine/hooks": "^6.0.14",
|
"@mantine/hooks": "^6.0.14",
|
||||||
"@mantine/modals": "^6.0.14",
|
"@mantine/modals": "^6.0.14",
|
||||||
|
"@mantine/next": "^6.0.14",
|
||||||
"@mantine/notifications": "^6.0.14",
|
"@mantine/notifications": "^6.0.14",
|
||||||
"@mantine/prism": "^6.0.14",
|
"@mantine/nprogress": "^6.0.14",
|
||||||
"@mantine/remix": "^6.0.14",
|
|
||||||
"@prisma/client": "4.16.1",
|
"@prisma/client": "4.16.1",
|
||||||
"@prisma/internals": "^4.16.1",
|
"@prisma/internals": "^4.16.1",
|
||||||
"@prisma/migrate": "^4.16.1",
|
"@prisma/migrate": "^4.16.1",
|
||||||
"@remix-run/express": "^1.17.1",
|
"@tabler/icons-react": "^2.22.0",
|
||||||
"@remix-run/node": "^1.16.1",
|
"argon2": "^0.30.3",
|
||||||
"@remix-run/react": "^1.16.1",
|
|
||||||
"@remix-run/v1-route-convention": "^0.1.2",
|
|
||||||
"@types/express": "^4.17.17",
|
|
||||||
"bytes": "^3.1.2",
|
"bytes": "^3.1.2",
|
||||||
"colorette": "^2.0.20",
|
"colorette": "^2.0.20",
|
||||||
"dayjs": "^1.11.8",
|
"dayjs": "^1.11.8",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"isbot": "^3.6.10",
|
|
||||||
"ms": "^2.1.3",
|
"ms": "^2.1.3",
|
||||||
|
"next": "^13.4.7",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"znv": "^0.3.2",
|
"znv": "^0.3.2",
|
||||||
|
@ -52,6 +48,7 @@
|
||||||
"@remix-run/dev": "^1.16.1",
|
"@remix-run/dev": "^1.16.1",
|
||||||
"@remix-run/eslint-config": "^1.16.1",
|
"@remix-run/eslint-config": "^1.16.1",
|
||||||
"@types/bytes": "^3.1.1",
|
"@types/bytes": "^3.1.1",
|
||||||
|
"@types/express": "^4.17.17",
|
||||||
"@types/node": "^20.3.1",
|
"@types/node": "^20.3.1",
|
||||||
"@types/react": "^18.2.7",
|
"@types/react": "^18.2.7",
|
||||||
"@types/react-dom": "^18.2.4",
|
"@types/react-dom": "^18.2.4",
|
||||||
|
|
14
postcss.config.js
Normal file
14
postcss.config.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
'postcss-preset-mantine': {},
|
||||||
|
'postcss-simple-vars': {
|
||||||
|
variables: {
|
||||||
|
'mantine-breakpoint-xs': '36em',
|
||||||
|
'mantine-breakpoint-sm': '48em',
|
||||||
|
'mantine-breakpoint-md': '62em',
|
||||||
|
'mantine-breakpoint-lg': '75em',
|
||||||
|
'mantine-breakpoint-xl': '88em',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
|
@ -1,234 +0,0 @@
|
||||||
-- CreateEnum
|
|
||||||
CREATE TYPE "OAuthProviderType" AS ENUM ('DISCORD', 'GOOGLE', 'GITHUB');
|
|
||||||
|
|
||||||
-- CreateEnum
|
|
||||||
CREATE TYPE "LimitType" AS ENUM ('UPLOAD_COUNT', 'UPLOAD_SIZE', 'SHORTEN_COUNT');
|
|
||||||
|
|
||||||
-- CreateEnum
|
|
||||||
CREATE TYPE "LimitTimeframe" AS ENUM ('SECONDLY', 'MINUTELY', 'HOURLY', 'DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY');
|
|
||||||
|
|
||||||
-- CreateEnum
|
|
||||||
CREATE TYPE "IncompleteFileStatus" AS ENUM ('PENDING', 'PROCESSING', 'COMPLETE', 'FAILED');
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "zipline_meta" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"firstSetup" BOOLEAN NOT NULL DEFAULT true,
|
|
||||||
|
|
||||||
CONSTRAINT "zipline_meta_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "User" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"username" TEXT NOT NULL,
|
|
||||||
"password" TEXT,
|
|
||||||
"avatar" TEXT,
|
|
||||||
"token" TEXT NOT NULL,
|
|
||||||
"administrator" BOOLEAN NOT NULL DEFAULT false,
|
|
||||||
"ziplineId" TEXT NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "OAuthProvider" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"userId" TEXT NOT NULL,
|
|
||||||
"provider" "OAuthProviderType" NOT NULL,
|
|
||||||
"accessToken" TEXT NOT NULL,
|
|
||||||
"refreshToken" TEXT NOT NULL,
|
|
||||||
"expiresIn" INTEGER NOT NULL,
|
|
||||||
"scope" TEXT NOT NULL,
|
|
||||||
"tokenType" TEXT NOT NULL,
|
|
||||||
"profile" JSONB NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "OAuthProvider_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "UserLimit" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"type" "LimitType" NOT NULL,
|
|
||||||
"value" INTEGER NOT NULL,
|
|
||||||
"timeframe" "LimitTimeframe" NOT NULL,
|
|
||||||
"userId" TEXT NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "UserLimit_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "File" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"deletesAt" TIMESTAMP(3),
|
|
||||||
"name" TEXT NOT NULL,
|
|
||||||
"originalName" TEXT NOT NULL,
|
|
||||||
"path" TEXT NOT NULL,
|
|
||||||
"size" INTEGER NOT NULL,
|
|
||||||
"type" TEXT NOT NULL,
|
|
||||||
"views" INTEGER NOT NULL DEFAULT 0,
|
|
||||||
"favorite" BOOLEAN NOT NULL DEFAULT false,
|
|
||||||
"password" TEXT,
|
|
||||||
"zeroWidthSpace" TEXT,
|
|
||||||
"userId" TEXT,
|
|
||||||
"folderId" TEXT,
|
|
||||||
|
|
||||||
CONSTRAINT "File_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "Folder" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"name" TEXT NOT NULL,
|
|
||||||
"userId" TEXT NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "Folder_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "IncompleteFile" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"status" "IncompleteFileStatus" NOT NULL,
|
|
||||||
"chunksTotal" INTEGER NOT NULL,
|
|
||||||
"chunksComplete" INTEGER NOT NULL,
|
|
||||||
"metadata" JSONB NOT NULL,
|
|
||||||
"userId" TEXT NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "IncompleteFile_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "Tag" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"name" TEXT NOT NULL,
|
|
||||||
"color" TEXT NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "Tag_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "Url" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"vanity" TEXT,
|
|
||||||
"destination" TEXT NOT NULL,
|
|
||||||
"name" TEXT NOT NULL,
|
|
||||||
"zeroWidthSpace" TEXT,
|
|
||||||
"userId" TEXT,
|
|
||||||
|
|
||||||
CONSTRAINT "Url_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "Metric" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"data" JSONB NOT NULL,
|
|
||||||
"ziplineId" TEXT NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "Metric_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "Invite" (
|
|
||||||
"id" TEXT NOT NULL,
|
|
||||||
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
||||||
"expiresAt" TIMESTAMP(3),
|
|
||||||
"code" TEXT NOT NULL,
|
|
||||||
"used" BOOLEAN NOT NULL DEFAULT false,
|
|
||||||
"inviterId" TEXT NOT NULL,
|
|
||||||
"ziplineId" TEXT NOT NULL,
|
|
||||||
|
|
||||||
CONSTRAINT "Invite_pkey" PRIMARY KEY ("id")
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "_FileToTag" (
|
|
||||||
"A" TEXT NOT NULL,
|
|
||||||
"B" TEXT NOT NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "User_token_key" ON "User"("token");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "OAuthProvider_userId_provider_key" ON "OAuthProvider"("userId", "provider");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "UserLimit_type_key" ON "UserLimit"("type");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "Tag_name_key" ON "Tag"("name");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "Url_name_key" ON "Url"("name");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "Invite_code_key" ON "Invite"("code");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE UNIQUE INDEX "_FileToTag_AB_unique" ON "_FileToTag"("A", "B");
|
|
||||||
|
|
||||||
-- CreateIndex
|
|
||||||
CREATE INDEX "_FileToTag_B_index" ON "_FileToTag"("B");
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "User" ADD CONSTRAINT "User_ziplineId_fkey" FOREIGN KEY ("ziplineId") REFERENCES "zipline_meta"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "OAuthProvider" ADD CONSTRAINT "OAuthProvider_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "UserLimit" ADD CONSTRAINT "UserLimit_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "File" ADD CONSTRAINT "File_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "File" ADD CONSTRAINT "File_folderId_fkey" FOREIGN KEY ("folderId") REFERENCES "Folder"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "Folder" ADD CONSTRAINT "Folder_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "IncompleteFile" ADD CONSTRAINT "IncompleteFile_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "Url" ADD CONSTRAINT "Url_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "Metric" ADD CONSTRAINT "Metric_ziplineId_fkey" FOREIGN KEY ("ziplineId") REFERENCES "zipline_meta"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "Invite" ADD CONSTRAINT "Invite_inviterId_fkey" FOREIGN KEY ("inviterId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "Invite" ADD CONSTRAINT "Invite_ziplineId_fkey" FOREIGN KEY ("ziplineId") REFERENCES "zipline_meta"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "_FileToTag" ADD CONSTRAINT "_FileToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "File"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
||||||
|
|
||||||
-- AddForeignKey
|
|
||||||
ALTER TABLE "_FileToTag" ADD CONSTRAINT "_FileToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
@ -1,3 +0,0 @@
|
||||||
# Please do not edit this file manually
|
|
||||||
# It should be added in your version-control system (i.e. Git)
|
|
||||||
provider = "postgresql"
|
|
|
@ -13,12 +13,6 @@ model Zipline {
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
firstSetup Boolean @default(true)
|
firstSetup Boolean @default(true)
|
||||||
|
|
||||||
metrics Metric[]
|
|
||||||
users User[]
|
|
||||||
invite Invite[]
|
|
||||||
|
|
||||||
@@map("zipline_meta")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
|
@ -39,9 +33,6 @@ model User {
|
||||||
invites Invite[]
|
invites Invite[]
|
||||||
oauthProviders OAuthProvider[]
|
oauthProviders OAuthProvider[]
|
||||||
IncompleteFile IncompleteFile[]
|
IncompleteFile IncompleteFile[]
|
||||||
|
|
||||||
Zipline Zipline @relation(fields: [ziplineId], references: [id], onDelete: Cascade, onUpdate: Cascade)
|
|
||||||
ziplineId String
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model OAuthProvider {
|
model OAuthProvider {
|
||||||
|
@ -191,9 +182,6 @@ model Metric {
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
data Json
|
data Json
|
||||||
|
|
||||||
Zipline Zipline @relation(fields: [ziplineId], references: [id], onDelete: Cascade, onUpdate: Cascade)
|
|
||||||
ziplineId String
|
|
||||||
}
|
}
|
||||||
|
|
||||||
model Invite {
|
model Invite {
|
||||||
|
@ -207,7 +195,4 @@ model Invite {
|
||||||
|
|
||||||
inviter User @relation(fields: [inviterId], references: [id], onDelete: Cascade, onUpdate: Cascade)
|
inviter User @relation(fields: [inviterId], references: [id], onDelete: Cascade, onUpdate: Cascade)
|
||||||
inviterId String
|
inviterId String
|
||||||
|
|
||||||
Zipline Zipline @relation(fields: [ziplineId], references: [id], onDelete: Cascade, onUpdate: Cascade)
|
|
||||||
ziplineId String
|
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.9 KiB |
|
@ -1,27 +0,0 @@
|
||||||
const { createRoutesFromFolders } = require('@remix-run/v1-route-convention');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {import('@remix-run/dev').AppConfig}
|
|
||||||
*/
|
|
||||||
module.exports = {
|
|
||||||
ignoredRouteFiles: ['**/.*'],
|
|
||||||
appDirectory: 'src/app',
|
|
||||||
// assetsBuildDirectory: 'public/build',
|
|
||||||
// serverBuildPath: 'build/index.js',
|
|
||||||
serverModuleFormat: 'cjs',
|
|
||||||
future: {
|
|
||||||
unstable_dev: true,
|
|
||||||
v2_routeConvention: true,
|
|
||||||
v2_errorBoundary: true,
|
|
||||||
v2_meta: true,
|
|
||||||
v2_normalizeFormMethod: true,
|
|
||||||
v2_headers: true,
|
|
||||||
},
|
|
||||||
publicPath: '/modules/',
|
|
||||||
// use directory structure.
|
|
||||||
routes(defineRoutes) {
|
|
||||||
return createRoutesFromFolders(defineRoutes, {
|
|
||||||
appDirectory: 'src/app',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
2
remix.env.d.ts
vendored
2
remix.env.d.ts
vendored
|
@ -1,2 +0,0 @@
|
||||||
/// <reference types="@remix-run/dev" />
|
|
||||||
/// <reference types="@remix-run/node/globals" />
|
|
|
@ -1,11 +0,0 @@
|
||||||
import { RemixBrowser } from '@remix-run/react';
|
|
||||||
import { hydrate } from 'react-dom';
|
|
||||||
import { ClientProvider } from '@mantine/remix';
|
|
||||||
|
|
||||||
hydrate(
|
|
||||||
<ClientProvider>
|
|
||||||
<RemixBrowser />
|
|
||||||
</ClientProvider>,
|
|
||||||
document
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
import { renderToString } from 'react-dom/server';
|
|
||||||
import { RemixServer } from '@remix-run/react';
|
|
||||||
import type { EntryContext } from '@remix-run/node';
|
|
||||||
import { injectStyles, createStylesServer } from '@mantine/remix';
|
|
||||||
|
|
||||||
const server = createStylesServer();
|
|
||||||
|
|
||||||
export default function handleRequest(
|
|
||||||
request: Request,
|
|
||||||
responseStatusCode: number,
|
|
||||||
responseHeaders: Headers,
|
|
||||||
remixContext: EntryContext
|
|
||||||
) {
|
|
||||||
let markup = renderToString(<RemixServer context={remixContext} url={request.url} />);
|
|
||||||
responseHeaders.set('Content-Type', 'text/html');
|
|
||||||
|
|
||||||
return new Response(`<!DOCTYPE html>${injectStyles(markup, server)}`, {
|
|
||||||
status: responseStatusCode,
|
|
||||||
headers: responseHeaders,
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import type { LoaderArgs } from '@remix-run/node';
|
|
||||||
import type { Config } from 'lib/config/Config';
|
|
||||||
|
|
||||||
export type TypedLoaderArgs<T> = {
|
|
||||||
context: T;
|
|
||||||
} & Omit<LoaderArgs, 'context'>;
|
|
||||||
|
|
||||||
export type RouteContext = {
|
|
||||||
config: Config;
|
|
||||||
};
|
|
|
@ -1,32 +0,0 @@
|
||||||
import type { V2_MetaFunction } from '@remix-run/node';
|
|
||||||
import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react';
|
|
||||||
import { MantineProvider, createEmotionCache } from '@mantine/core';
|
|
||||||
import { StylesPlaceholder } from '@mantine/remix';
|
|
||||||
|
|
||||||
export const meta: V2_MetaFunction = () => [
|
|
||||||
{ charSet: 'utf-8' },
|
|
||||||
{ title: 'Zipline' },
|
|
||||||
{ name: 'viewport', content: 'width=device-width,initial-scale=1' },
|
|
||||||
];
|
|
||||||
|
|
||||||
createEmotionCache({ key: 'mantine' });
|
|
||||||
|
|
||||||
export default function App() {
|
|
||||||
return (
|
|
||||||
<MantineProvider withGlobalStyles withNormalizeCSS>
|
|
||||||
<html lang='en'>
|
|
||||||
<head>
|
|
||||||
<StylesPlaceholder />
|
|
||||||
<Meta />
|
|
||||||
<Links />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<Outlet />
|
|
||||||
<ScrollRestoration />
|
|
||||||
<Scripts />
|
|
||||||
<LiveReload />
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
</MantineProvider>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
import { json } from '@remix-run/node';
|
|
||||||
import { isRouteErrorResponse, useRouteError } from '@remix-run/react';
|
|
||||||
import { RouteContext, TypedLoaderArgs } from '~/loader';
|
|
||||||
|
|
||||||
export const loader = async ({ params, context }: TypedLoaderArgs<RouteContext>) => {
|
|
||||||
const slug = params['*']?.split('/').filter(Boolean) ?? [];
|
|
||||||
if (!slug.length) {
|
|
||||||
throw json('Not Found (no slug)', { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(slug, context.config);
|
|
||||||
|
|
||||||
if (slug[0] === context.config.files.route) {
|
|
||||||
} else {
|
|
||||||
throw json('Not Found (catchall)', { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
return json({ slug });
|
|
||||||
};
|
|
||||||
|
|
||||||
export function ErrorBoundary() {
|
|
||||||
const error = useRouteError();
|
|
||||||
|
|
||||||
if (isRouteErrorResponse(error)) {
|
|
||||||
return <pre>{JSON.stringify(error, null, 2)}</pre>;
|
|
||||||
} else if (error instanceof Error) {
|
|
||||||
return <pre>{JSON.stringify(error, null, 2)}</pre>;
|
|
||||||
} else {
|
|
||||||
return <p>Unknown error</p>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// export default function Index() {
|
|
||||||
// return <p>Index</p>;
|
|
||||||
// }
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { LoaderArgs, json } from '@remix-run/node';
|
|
||||||
import { prisma } from '~/db.server';
|
|
||||||
|
|
||||||
export async function loader({ context, request }: LoaderArgs) {
|
|
||||||
try {
|
|
||||||
// test database connection
|
|
||||||
await prisma.user.count();
|
|
||||||
|
|
||||||
return json({ pong: true }, { status: 200 });
|
|
||||||
} catch (e) {
|
|
||||||
return json({ pong: false }, { status: 500 });
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
import { LoaderArgs, json } from '@remix-run/node';
|
|
||||||
import { useLoaderData } from '@remix-run/react';
|
|
||||||
import { prisma } from '~/db.server';
|
|
||||||
|
|
||||||
export async function loader({}: LoaderArgs) {
|
|
||||||
let zipline = await prisma.zipline.findFirst();
|
|
||||||
if (!zipline) {
|
|
||||||
zipline = await prisma.zipline.create({ data: {} });
|
|
||||||
}
|
|
||||||
|
|
||||||
return json({ zipline });
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Index() {
|
|
||||||
const { zipline } = useLoaderData<typeof loader>();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<pre>{JSON.stringify(zipline, null, 2)}</pre>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { createCookieSessionStorage } from "@remix-run/node";
|
|
||||||
|
|
||||||
let sessionSecret = process.env.SESSION_SECRET;
|
|
||||||
if (!sessionSecret) {
|
|
||||||
throw new Error("SESSION_SECRET must be set");
|
|
||||||
}
|
|
||||||
|
|
||||||
export let sessionStorage = createCookieSessionStorage({
|
|
||||||
cookie: {
|
|
||||||
name: "__session",
|
|
||||||
secrets: [sessionSecret],
|
|
||||||
sameSite: "lax",
|
|
||||||
path: "/",
|
|
||||||
maxAge: 60 * 60 * 24 * 30,
|
|
||||||
httpOnly: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const USER_SESSION_KEY = "userId";
|
|
||||||
|
|
||||||
export async function getSession(request: Request) {
|
|
||||||
const cookie = request.headers.get("Cookie");
|
|
||||||
return sessionStorage.getSession(cookie);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
export function sleep<T>(ms: number, value: T) {
|
|
||||||
return new Promise<T>((resolve) => setTimeout(() => resolve(value), ms));
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
export interface Config {
|
|
||||||
core: ConfigCore;
|
|
||||||
files: ConfigFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ConfigCore {
|
|
||||||
port: number;
|
|
||||||
sessionSecret: string;
|
|
||||||
databaseUrl: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ConfigFiles {
|
|
||||||
route: string;
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
import type { ValidatedEnv } from './read';
|
|
||||||
|
|
||||||
export function convertEnv(env: ValidatedEnv) {
|
|
||||||
return {
|
|
||||||
core: {
|
|
||||||
port: env.PORT,
|
|
||||||
sessionSecret: env.SESSION_SECRET,
|
|
||||||
databaseUrl: env.DATABASE_URL,
|
|
||||||
},
|
|
||||||
files: {
|
|
||||||
route: env.FILES_ROUTE,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
16
src/lib/config/index.ts
Normal file
16
src/lib/config/index.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { readEnv } from './read';
|
||||||
|
import { validateEnv, Config } from './validate';
|
||||||
|
|
||||||
|
let config: Config;
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
var __config__: Config;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!global.__config__) {
|
||||||
|
global.__config__ = validateEnv(readEnv());
|
||||||
|
}
|
||||||
|
|
||||||
|
config = global.__config__;
|
||||||
|
|
||||||
|
export { config };
|
|
@ -1,23 +1,120 @@
|
||||||
import { log } from 'src/lib/logger';
|
import bytes from 'bytes';
|
||||||
import { parseEnv } from 'znv';
|
import msFn from 'ms';
|
||||||
import { z } from 'zod';
|
|
||||||
|
|
||||||
const logger = log('config').c('read');
|
type EnvType = 'string' | 'number' | 'boolean' | 'byte' | 'ms';
|
||||||
|
|
||||||
|
export type ParsedEnv = ReturnType<typeof readEnv>;
|
||||||
|
|
||||||
|
export const PROP_TO_ENV: Record<string, string> = {
|
||||||
|
'core.port': 'CORE_PORT',
|
||||||
|
'core.hostname': 'CORE_HOSTNAME',
|
||||||
|
'core.secret': 'CORE_SECRET',
|
||||||
|
'core.databaseUrl': 'CORE_DATABASE_URL',
|
||||||
|
|
||||||
|
'files.route': 'FILES_ROUTE',
|
||||||
|
};
|
||||||
|
|
||||||
export function readEnv() {
|
export function readEnv() {
|
||||||
logger.debug('reading env');
|
const envs = [
|
||||||
|
env(PROP_TO_ENV['core.port'], 'core.port', 'number'),
|
||||||
|
env(PROP_TO_ENV['core.hostname'], 'core.hostname', 'string'),
|
||||||
|
env(PROP_TO_ENV['core.secret'], 'core.secret', 'string'),
|
||||||
|
env(PROP_TO_ENV['core.databaseUrl'], 'core.databaseUrl', 'string'),
|
||||||
|
|
||||||
const validation = parseEnv(process.env, {
|
env(PROP_TO_ENV['files.route'], 'files.route', 'string'),
|
||||||
PORT: z.number().default(3000),
|
];
|
||||||
SESSION_SECRET: z.string(),
|
|
||||||
DATABASE_URL: z.string(),
|
|
||||||
|
|
||||||
FILES_ROUTE: z.string().default('u'),
|
const raw = {
|
||||||
});
|
core: {
|
||||||
|
port: undefined,
|
||||||
|
hostname: undefined,
|
||||||
|
secret: undefined,
|
||||||
|
databaseUrl: undefined,
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
route: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
logger.debug('env read', JSON.stringify(validation));
|
for (let i = 0; i !== envs.length; ++i) {
|
||||||
|
const env = envs[i];
|
||||||
|
const value = process.env[env.variable];
|
||||||
|
if (value === undefined) continue;
|
||||||
|
|
||||||
return validation;
|
const parsed = parse(value, env.type);
|
||||||
|
if (parsed === undefined) continue;
|
||||||
|
|
||||||
|
setDotProp(raw, env.property, parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ValidatedEnv = ReturnType<typeof readEnv>;
|
function env(variable: string, property: string, type: EnvType) {
|
||||||
|
return {
|
||||||
|
variable,
|
||||||
|
property,
|
||||||
|
type,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDotProp(obj: Record<string, any>, property: string, value: unknown) {
|
||||||
|
const parts = property.split('.');
|
||||||
|
const last = parts.pop()!;
|
||||||
|
|
||||||
|
for (let i = 0; i !== parts.length; ++i) {
|
||||||
|
const part = parts[i];
|
||||||
|
const next = obj[part];
|
||||||
|
|
||||||
|
if (typeof next === 'object' && next !== null) {
|
||||||
|
obj = next;
|
||||||
|
} else {
|
||||||
|
obj = obj[part] = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obj[last] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(value: string, type: EnvType) {
|
||||||
|
switch (type) {
|
||||||
|
case 'string':
|
||||||
|
return string(value);
|
||||||
|
case 'number':
|
||||||
|
return number(value);
|
||||||
|
case 'boolean':
|
||||||
|
return boolean(value);
|
||||||
|
case 'byte':
|
||||||
|
return byte(value);
|
||||||
|
case 'ms':
|
||||||
|
return ms(value);
|
||||||
|
default:
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function string(value: string) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function number(value: string) {
|
||||||
|
const num = Number(value);
|
||||||
|
if (isNaN(num)) return undefined;
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
function boolean(value: string) {
|
||||||
|
if (value === 'true') return true;
|
||||||
|
if (value === 'false') return false;
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
function byte(value: string) {
|
||||||
|
return bytes(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ms(value: string) {
|
||||||
|
return msFn(value);
|
||||||
|
}
|
||||||
|
|
68
src/lib/config/validate.ts
Normal file
68
src/lib/config/validate.ts
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
import { ZodError, z } from 'zod';
|
||||||
|
import { PROP_TO_ENV, ParsedEnv } from './read';
|
||||||
|
import { log } from '../logger';
|
||||||
|
|
||||||
|
const schema = z.object({
|
||||||
|
core: z.object({
|
||||||
|
port: z.number().default(3000),
|
||||||
|
hostname: z.string().default('localhost'),
|
||||||
|
secret: z.string().superRefine((s, c) => {
|
||||||
|
if (s === 'changethis')
|
||||||
|
return c.addIssue({
|
||||||
|
code: 'custom',
|
||||||
|
message: 'Secret must be changed from the default value',
|
||||||
|
path: ['core', 'secret'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (s.length <= 16) {
|
||||||
|
return c.addIssue({
|
||||||
|
code: 'too_small',
|
||||||
|
minimum: 16,
|
||||||
|
type: 'string',
|
||||||
|
inclusive: true,
|
||||||
|
message: 'Secret must contain at least 16 characters',
|
||||||
|
path: ['core', 'secret'],
|
||||||
|
exact: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
databaseUrl: z.string().url(),
|
||||||
|
}),
|
||||||
|
files: z.object({
|
||||||
|
route: z.string().default('u'),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type Config = z.infer<typeof schema>;
|
||||||
|
|
||||||
|
export function validateEnv(env: ParsedEnv): Config {
|
||||||
|
const logger = log('config').c('validate');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const validated = schema.parse(env);
|
||||||
|
|
||||||
|
if (!validated) {
|
||||||
|
logger.error('There was an error while validating the environment.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validated;
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof ZodError) {
|
||||||
|
logger.error(`There were ${e.errors.length} error(s) while validating the environment.`);
|
||||||
|
|
||||||
|
for (let i = 0; i !== e.errors.length; ++i) {
|
||||||
|
const error = e.errors[i];
|
||||||
|
logger.debug(JSON.stringify(error));
|
||||||
|
|
||||||
|
const path = PROP_TO_ENV[error.path.join('.')];
|
||||||
|
|
||||||
|
logger.error(`${path}: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
19
src/lib/cookie.ts
Normal file
19
src/lib/cookie.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
export function serializeCookie(
|
||||||
|
name: string,
|
||||||
|
value: string,
|
||||||
|
options: {
|
||||||
|
expires?: Date;
|
||||||
|
maxAge?: number;
|
||||||
|
path?: string;
|
||||||
|
sameSite?: 'strict' | 'lax' | 'none';
|
||||||
|
} = {}
|
||||||
|
) {
|
||||||
|
const cookie = [`${name}=${value}`];
|
||||||
|
|
||||||
|
if (options.expires) cookie.push(`Expires=${options.expires.toUTCString()}`);
|
||||||
|
if (options.maxAge) cookie.push(`Max-Age=${options.maxAge}`);
|
||||||
|
if (options.path) cookie.push(`Path=${options.path}`);
|
||||||
|
if (options.sameSite) cookie.push(`SameSite=${options.sameSite}`);
|
||||||
|
|
||||||
|
return cookie.join('; ');
|
||||||
|
}
|
97
src/lib/crypto.ts
Normal file
97
src/lib/crypto.ts
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import crypto from 'crypto';
|
||||||
|
import { hash, verify } from 'argon2';
|
||||||
|
|
||||||
|
const ALGORITHM = 'aes-256-cbc';
|
||||||
|
|
||||||
|
export function createKey(secret: string) {
|
||||||
|
const hash = crypto.createHash('sha256');
|
||||||
|
hash.update(secret);
|
||||||
|
|
||||||
|
return hash.digest('hex').slice(0, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function encrypt(value: string, secret: string): string {
|
||||||
|
const key = createKey(secret);
|
||||||
|
const iv = crypto.randomBytes(16);
|
||||||
|
|
||||||
|
const cipher = crypto.createCipheriv(ALGORITHM, Buffer.from(key), iv);
|
||||||
|
|
||||||
|
const encrypted = cipher.update(value);
|
||||||
|
const final = cipher.final();
|
||||||
|
|
||||||
|
const buffer = Buffer.alloc(encrypted.length + final.length);
|
||||||
|
buffer.set(encrypted);
|
||||||
|
buffer.set(final, encrypted.length);
|
||||||
|
|
||||||
|
return iv.toString('hex') + '.' + buffer.toString('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decrypt(value: string, secret: string): string {
|
||||||
|
const key = createKey(secret);
|
||||||
|
const [iv, encrypted] = value.split('.');
|
||||||
|
|
||||||
|
const decipher = crypto.createDecipheriv(ALGORITHM, Buffer.from(key), Buffer.from(iv, 'hex'));
|
||||||
|
|
||||||
|
const decrypted = decipher.update(Buffer.from(encrypted, 'hex'));
|
||||||
|
const final = decipher.final();
|
||||||
|
|
||||||
|
const buffer = Buffer.alloc(decrypted.length + final.length);
|
||||||
|
buffer.set(decrypted);
|
||||||
|
buffer.set(final, decrypted.length);
|
||||||
|
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function randomCharacters(length: number): string {
|
||||||
|
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
const charactersLength = characters.length;
|
||||||
|
|
||||||
|
let result = '';
|
||||||
|
|
||||||
|
for (let i = 0; i !== length; ++i) {
|
||||||
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createToken(): string {
|
||||||
|
const date = Date.now();
|
||||||
|
const random = randomCharacters(32);
|
||||||
|
|
||||||
|
const date64 = Buffer.from(date.toString()).toString('base64');
|
||||||
|
const random64 = Buffer.from(random).toString('base64');
|
||||||
|
|
||||||
|
return `${date64}.${random64}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function encryptToken(token: string, secret: string): string {
|
||||||
|
const key = createKey(secret);
|
||||||
|
|
||||||
|
const date = Date.now();
|
||||||
|
const date64 = Buffer.from(date.toString()).toString('base64');
|
||||||
|
|
||||||
|
const encrypted = encrypt(token, key);
|
||||||
|
const encrypted64 = Buffer.from(encrypted).toString('base64');
|
||||||
|
|
||||||
|
return `${date64}.${encrypted64}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function decryptToken(encryptedToken: string, secret: string): [number, string] {
|
||||||
|
const key = createKey(secret);
|
||||||
|
const [date64, encrypted64] = encryptedToken.split('.');
|
||||||
|
|
||||||
|
const date = parseInt(Buffer.from(date64, 'base64').toString('ascii'), 10);
|
||||||
|
|
||||||
|
const encrypted = Buffer.from(encrypted64, 'base64').toString('ascii');
|
||||||
|
|
||||||
|
return [date, decrypt(encrypted, key)];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function hashPassword(password: string) {
|
||||||
|
return hash(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function verifyPassword(password: string, hash: string) {
|
||||||
|
return verify(hash, password);
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import { PrismaClient } from '@prisma/client';
|
import { PrismaClient } from '@prisma/client';
|
||||||
import { log } from 'src/lib/logger';
|
import { log } from '@/lib/logger';
|
||||||
|
|
||||||
let prisma: PrismaClient;
|
let prisma: PrismaClient;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Migrate } from '@prisma/migrate/dist/Migrate';
|
import { Migrate } from '@prisma/migrate/dist/Migrate';
|
||||||
import { ensureDatabaseExists } from '@prisma/migrate/dist/utils/ensureDatabaseExists';
|
import { ensureDatabaseExists } from '@prisma/migrate/dist/utils/ensureDatabaseExists';
|
||||||
import { log } from 'lib/logger';
|
import { log } from '@/lib/logger';
|
||||||
|
|
||||||
export async function runMigrations() {
|
export async function runMigrations() {
|
||||||
const migrate = new Migrate('./prisma/schema.prisma');
|
const migrate = new Migrate('./prisma/schema.prisma');
|
45
src/lib/db/queries/user.ts
Normal file
45
src/lib/db/queries/user.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import { Prisma } from '@prisma/client';
|
||||||
|
import { prisma } from '..';
|
||||||
|
|
||||||
|
export type User = {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
administrator: boolean;
|
||||||
|
avatar?: string | null;
|
||||||
|
password?: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getUser(
|
||||||
|
where: Prisma.UserWhereInput | Prisma.UserWhereUniqueInput,
|
||||||
|
options?: { password?: boolean; avatar?: boolean }
|
||||||
|
): Promise<User | null> {
|
||||||
|
return prisma.user.findFirst({
|
||||||
|
where,
|
||||||
|
select: {
|
||||||
|
administrator: true,
|
||||||
|
avatar: options?.avatar || false,
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true,
|
||||||
|
password: options?.password || false,
|
||||||
|
username: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUserTokenRaw(
|
||||||
|
where: Prisma.UserWhereInput | Prisma.UserWhereUniqueInput
|
||||||
|
): Promise<string | null> {
|
||||||
|
const user = await prisma.user.findFirst({
|
||||||
|
where,
|
||||||
|
select: {
|
||||||
|
token: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) return null;
|
||||||
|
|
||||||
|
return user.token;
|
||||||
|
}
|
12
src/lib/db/queries/zipline.ts
Normal file
12
src/lib/db/queries/zipline.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { prisma } from '..';
|
||||||
|
|
||||||
|
export async function getZipline() {
|
||||||
|
const zipline = await prisma.zipline.findFirst();
|
||||||
|
if (!zipline) {
|
||||||
|
return prisma.zipline.create({
|
||||||
|
data: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return zipline;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import { blue, green, red, yellow, gray, white, bold } from 'colorette';
|
import { green, red, yellow, gray, white, bold } from 'colorette';
|
||||||
|
|
||||||
export type LoggerLevel = 'info' | 'warn' | 'error' | 'debug' | 'trace';
|
export type LoggerLevel = 'info' | 'warn' | 'error' | 'debug' | 'trace';
|
||||||
|
|
||||||
|
|
10
src/lib/middleware/combine.ts
Normal file
10
src/lib/middleware/combine.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { NextApiReq, NextApiRes } from '../response';
|
||||||
|
|
||||||
|
export function combine(middleware: Middleware[], handler: Handler) {
|
||||||
|
return middleware.reduceRight((handler, middleware) => {
|
||||||
|
return middleware(handler);
|
||||||
|
}, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Middleware = (...args: any[]) => Handler;
|
||||||
|
export type Handler = (req: NextApiReq, res: NextApiRes) => Promise<any>;
|
19
src/lib/middleware/cors.ts
Normal file
19
src/lib/middleware/cors.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { NextApiReq, NextApiRes } from '../response';
|
||||||
|
import { Handler } from './combine';
|
||||||
|
|
||||||
|
export function cors() {
|
||||||
|
return (handler: Handler) => {
|
||||||
|
return async (req: NextApiReq, res: NextApiRes) => {
|
||||||
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS');
|
||||||
|
res.setHeader('Access-Control-Allow-Headers', 'Authorization, Content-Type, Accept');
|
||||||
|
res.setHeader('Access-Control-Max-Age', '86400');
|
||||||
|
|
||||||
|
if (req.method === 'OPTIONS') {
|
||||||
|
return res.status(200).end();
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler(req, res);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
19
src/lib/middleware/method.ts
Normal file
19
src/lib/middleware/method.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { NextApiReq, NextApiRes, methodNotAllowed } from '../response';
|
||||||
|
import { Handler } from './combine';
|
||||||
|
|
||||||
|
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS';
|
||||||
|
|
||||||
|
export function method(allowedMethods: HttpMethod[] = []) {
|
||||||
|
return (handler: Handler) => {
|
||||||
|
return async (req: NextApiReq, res: NextApiRes) => {
|
||||||
|
allowedMethods.push('OPTIONS');
|
||||||
|
|
||||||
|
if (!allowedMethods.includes(req.method as HttpMethod)) {
|
||||||
|
res.setHeader('Allow', allowedMethods.join(', '));
|
||||||
|
return methodNotAllowed(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler(req, res);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
40
src/lib/middleware/ziplineAuth.ts
Normal file
40
src/lib/middleware/ziplineAuth.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import { config } from '../config';
|
||||||
|
import { decryptToken } from '../crypto';
|
||||||
|
import { prisma } from '../db';
|
||||||
|
import { NextApiReq, NextApiRes, forbidden, unauthorized } from '../response';
|
||||||
|
import { Handler } from './combine';
|
||||||
|
|
||||||
|
export type ZiplineAuthOptions = {
|
||||||
|
administratorOnly?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ziplineAuth(options: ZiplineAuthOptions) {
|
||||||
|
return (handler: Handler) => {
|
||||||
|
return async (req: NextApiReq, res: NextApiRes) => {
|
||||||
|
let rawToken: string | undefined;
|
||||||
|
|
||||||
|
if (req.cookies.zipline_auth) rawToken = req.cookies.zipline_auth;
|
||||||
|
else if (req.headers.authorization) rawToken = req.headers.authorization;
|
||||||
|
|
||||||
|
if (!rawToken) return unauthorized(res);
|
||||||
|
|
||||||
|
const [date, token] = decryptToken(rawToken, config.core.secret);
|
||||||
|
|
||||||
|
if (isNaN(new Date(date).getTime())) return unauthorized(res);
|
||||||
|
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: {
|
||||||
|
token,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!user) return unauthorized(res);
|
||||||
|
|
||||||
|
req.user = user;
|
||||||
|
|
||||||
|
if (options.administratorOnly && !user.administrator) return forbidden(res);
|
||||||
|
|
||||||
|
return handler(req, res);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
96
src/lib/response.ts
Normal file
96
src/lib/response.ts
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
import { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
import { User } from './db/queries/user';
|
||||||
|
|
||||||
|
export interface NextApiReq<Body = any, Query = any, Headers = any> extends NextApiRequest {
|
||||||
|
query: Query & { [k: string]: string | string[] };
|
||||||
|
body: Body;
|
||||||
|
headers: Headers & { [k: string]: string };
|
||||||
|
|
||||||
|
user?: User;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NextApiRes<Data = any> = NextApiResponse<Data>;
|
||||||
|
|
||||||
|
export function ok(res: NextApiRes, data: Record<string, unknown> = {}) {
|
||||||
|
return res.status(200).json(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client wrong data, etc
|
||||||
|
export function badRequest(
|
||||||
|
res: NextApiRes,
|
||||||
|
message: string = 'Bad Request',
|
||||||
|
data: Record<string, unknown> = {}
|
||||||
|
) {
|
||||||
|
return res.status(400).json({
|
||||||
|
error: message,
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// No authorization
|
||||||
|
export function unauthorized(
|
||||||
|
res: NextApiRes,
|
||||||
|
message: string = 'Unauthorized',
|
||||||
|
data: Record<string, unknown> = {}
|
||||||
|
) {
|
||||||
|
return res.status(401).json({
|
||||||
|
error: message,
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// User's permission level does not meet requirements for this resource
|
||||||
|
export function forbidden(
|
||||||
|
res: NextApiRes,
|
||||||
|
message: string = 'Forbidden',
|
||||||
|
data: Record<string, unknown> = {}
|
||||||
|
) {
|
||||||
|
return res.status(403).json({
|
||||||
|
error: message,
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function notFound(res: NextApiRes, message: string = 'Not Found', data: Record<string, unknown> = {}) {
|
||||||
|
return res.status(404).json({
|
||||||
|
error: message,
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ratelimited(
|
||||||
|
res: NextApiRes,
|
||||||
|
retryAfter: number,
|
||||||
|
message: string = 'Ratelimited',
|
||||||
|
data: Record<string, unknown> = {}
|
||||||
|
) {
|
||||||
|
res.setHeader('Retry-After', retryAfter);
|
||||||
|
return res.status(429).json({
|
||||||
|
error: message,
|
||||||
|
retryAfter,
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function serverError(
|
||||||
|
res: NextApiRes,
|
||||||
|
message: string = 'Internal Server Error',
|
||||||
|
data: Record<string, unknown> = {}
|
||||||
|
) {
|
||||||
|
return res.status(500).json({
|
||||||
|
error: message,
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function methodNotAllowed(
|
||||||
|
res: NextApiRes,
|
||||||
|
message: string = 'Method Not Allowed',
|
||||||
|
data: Record<string, unknown> = {}
|
||||||
|
) {
|
||||||
|
return res.status(405).json({
|
||||||
|
error: message,
|
||||||
|
method: res.req?.method || 'unknown',
|
||||||
|
...data,
|
||||||
|
});
|
||||||
|
}
|
26
src/pages/_app.tsx
Normal file
26
src/pages/_app.tsx
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { AppProps } from 'next/app';
|
||||||
|
import Head from 'next/head';
|
||||||
|
import { MantineProvider } from '@mantine/core';
|
||||||
|
|
||||||
|
export default function App(props: AppProps) {
|
||||||
|
const { Component, pageProps } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Zipline</title>
|
||||||
|
<meta name='viewport' content='minimum-scale=1, initial-scale=1, width=device-width' />
|
||||||
|
</Head>
|
||||||
|
|
||||||
|
<MantineProvider
|
||||||
|
withGlobalStyles
|
||||||
|
withNormalizeCSS
|
||||||
|
theme={{
|
||||||
|
colorScheme: 'dark',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Component {...pageProps} />
|
||||||
|
</MantineProvider>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
20
src/pages/_document.tsx
Normal file
20
src/pages/_document.tsx
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { createGetInitialProps } from '@mantine/next';
|
||||||
|
import Document, { Head, Html, Main, NextScript } from 'next/document';
|
||||||
|
|
||||||
|
const getInitialProps = createGetInitialProps();
|
||||||
|
|
||||||
|
export default class _Document extends Document {
|
||||||
|
static getInitialProps = getInitialProps;
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Html>
|
||||||
|
<Head />
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<NextScript />
|
||||||
|
</body>
|
||||||
|
</Html>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
56
src/pages/api/auth/login.ts
Normal file
56
src/pages/api/auth/login.ts
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import { config } from '@/lib/config';
|
||||||
|
import { serializeCookie } from '@/lib/cookie';
|
||||||
|
import { encryptToken, verifyPassword } from '@/lib/crypto';
|
||||||
|
import { User, getUser, getUserTokenRaw } from '@/lib/db/queries/user';
|
||||||
|
import { combine } from '@/lib/middleware/combine';
|
||||||
|
import { cors } from '@/lib/middleware/cors';
|
||||||
|
import { method } from '@/lib/middleware/method';
|
||||||
|
import { NextApiReq, NextApiRes, badRequest, ok } from '@/lib/response';
|
||||||
|
|
||||||
|
type Data = {
|
||||||
|
user: User;
|
||||||
|
token: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Body = {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handler(req: NextApiReq<Body>, res: NextApiRes<Data>) {
|
||||||
|
const { username, password } = req.body;
|
||||||
|
|
||||||
|
if (!username) return badRequest(res, 'Username is required');
|
||||||
|
if (!password) return badRequest(res, 'Password is required');
|
||||||
|
|
||||||
|
const user = await getUser({ username }, { password: true });
|
||||||
|
if (!user) return badRequest(res, 'Invalid username');
|
||||||
|
|
||||||
|
if (!user.password) return badRequest(res, 'User does not have a password, login through a provider');
|
||||||
|
const valid = await verifyPassword(password, user.password);
|
||||||
|
if (!valid) return badRequest(res, 'Invalid password');
|
||||||
|
|
||||||
|
const rawToken = await getUserTokenRaw({ id: user.id });
|
||||||
|
if (!rawToken) return badRequest(res, 'User does not have a token');
|
||||||
|
|
||||||
|
const token = encryptToken(rawToken, config.core.secret);
|
||||||
|
|
||||||
|
const cookie = serializeCookie('zipline_token', token, {
|
||||||
|
// week
|
||||||
|
maxAge: 60 * 60 * 24 * 7,
|
||||||
|
expires: new Date(Date.now() + 60 * 60 * 24 * 7 * 1000),
|
||||||
|
path: '/',
|
||||||
|
sameSite: 'lax',
|
||||||
|
});
|
||||||
|
|
||||||
|
res.setHeader('Set-Cookie', cookie);
|
||||||
|
|
||||||
|
delete user.password;
|
||||||
|
|
||||||
|
return ok(res, {
|
||||||
|
user,
|
||||||
|
token,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default combine([cors(), method(['POST'])], handler);
|
51
src/pages/api/healthcheck.ts
Normal file
51
src/pages/api/healthcheck.ts
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
|
||||||
|
import { prisma } from '@/lib/db';
|
||||||
|
import { log } from '@/lib/logger';
|
||||||
|
import { badRequest, ok, ratelimited, serverError } from '@/lib/response';
|
||||||
|
import { combine } from '@/lib/middleware/combine';
|
||||||
|
import { cors } from '@/lib/middleware/cors';
|
||||||
|
import { method } from '@/lib/middleware/method';
|
||||||
|
|
||||||
|
type Data = {
|
||||||
|
pass: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ratelimit: Map<string, number> = new Map();
|
||||||
|
|
||||||
|
export async function handler(req: NextApiRequest, res: NextApiResponse<Data>) {
|
||||||
|
const logger = log('api').c('healthcheck');
|
||||||
|
|
||||||
|
const ip = (req.headers['x-forwarded-for'] as string) || req.socket.remoteAddress;
|
||||||
|
if (!ip) {
|
||||||
|
logger.debug(`request without an ip address blocked`);
|
||||||
|
return badRequest(res, 'no ip address found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const last = ratelimit.get(ip);
|
||||||
|
|
||||||
|
if (last) {
|
||||||
|
if (last && Date.now() - last < 10000) {
|
||||||
|
logger.debug(`request from ${ip} blocked due to ratelimit`);
|
||||||
|
return ratelimited(res, Math.ceil((last + 10000 - Date.now()) / 1000));
|
||||||
|
} else {
|
||||||
|
ratelimit.delete(ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await prisma.$queryRaw`SELECT 1;`;
|
||||||
|
ratelimit.set(ip, Date.now());
|
||||||
|
|
||||||
|
return ok(res, { pass: true });
|
||||||
|
} catch (e) {
|
||||||
|
logger.error('there was an error during a healthcheck').error(e);
|
||||||
|
ratelimit.set(ip, Date.now());
|
||||||
|
|
||||||
|
return serverError(res, 'there was an error during a healthcheck', {
|
||||||
|
pass: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default combine([cors(), method(['GET'])], handler);
|
74
src/pages/api/setup.ts
Normal file
74
src/pages/api/setup.ts
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
|
|
||||||
|
import { prisma } from '@/lib/db';
|
||||||
|
import { log } from '@/lib/logger';
|
||||||
|
import { getZipline } from '@/lib/db/queries/zipline';
|
||||||
|
import { NextApiReq, NextApiRes, badRequest, forbidden, methodNotAllowed, ok } from '@/lib/response';
|
||||||
|
import { combine } from '@/lib/middleware/combine';
|
||||||
|
import { cors } from '@/lib/middleware/cors';
|
||||||
|
import { method } from '@/lib/middleware/method';
|
||||||
|
import { createToken, hashPassword } from '@/lib/crypto';
|
||||||
|
import { User } from '@/lib/db/queries/user';
|
||||||
|
|
||||||
|
type Response = {
|
||||||
|
firstSetup: boolean;
|
||||||
|
user: User;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Body = {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function handler(req: NextApiReq<Body>, res: NextApiRes<Response>) {
|
||||||
|
const logger = log('api').c('setup');
|
||||||
|
const { firstSetup, id } = await getZipline();
|
||||||
|
|
||||||
|
if (!firstSetup) return forbidden(res);
|
||||||
|
|
||||||
|
logger.info('first setup running');
|
||||||
|
|
||||||
|
if (req.method === 'GET') {
|
||||||
|
return ok(res, { firstSetup });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { username, password } = req.body;
|
||||||
|
if (!username) return badRequest(res, 'Username is required');
|
||||||
|
if (!password) return badRequest(res, 'Password is required');
|
||||||
|
|
||||||
|
if (password.length < 8) return badRequest(res, 'Password must be at least 8 characters long');
|
||||||
|
|
||||||
|
const user = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
username,
|
||||||
|
password: await hashPassword(password),
|
||||||
|
administrator: true,
|
||||||
|
token: createToken(),
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
administrator: true,
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true,
|
||||||
|
username: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
logger.info('first setup complete');
|
||||||
|
|
||||||
|
await prisma.zipline.update({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
firstSetup: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return ok(res, {
|
||||||
|
firstSetup,
|
||||||
|
user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default combine([cors(), method(['GET', 'POST'])], handler);
|
13
src/pages/api/user/index.ts
Normal file
13
src/pages/api/user/index.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { User } from '@/lib/db/queries/user';
|
||||||
|
import { combine } from '@/lib/middleware/combine';
|
||||||
|
import { cors } from '@/lib/middleware/cors';
|
||||||
|
import { method } from '@/lib/middleware/method';
|
||||||
|
import { NextApiReq, NextApiRes } from '@/lib/response';
|
||||||
|
|
||||||
|
type Response = {
|
||||||
|
user: User;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function handler(req: NextApiReq, res: NextApiRes<Response>) {}
|
||||||
|
|
||||||
|
export default combine([cors(), method(['GET', 'POST', 'PATCH'])], handler);
|
13
src/pages/auth/login.tsx
Normal file
13
src/pages/auth/login.tsx
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { Box, Center, Text, TextInput, Title } from '@mantine/core';
|
||||||
|
|
||||||
|
export default function Login() {
|
||||||
|
return (
|
||||||
|
<Box py='xl'>
|
||||||
|
<Center>
|
||||||
|
<Title order={1}>
|
||||||
|
<b>Zipline</b>
|
||||||
|
</Title>
|
||||||
|
</Center>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
13
src/pages/index.tsx
Normal file
13
src/pages/index.tsx
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import Head from 'next/head';
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Zipline</title>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1' />
|
||||||
|
</Head>
|
||||||
|
<main>hi</main>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,58 +1,50 @@
|
||||||
|
import { validateEnv } from '@/lib/config/validate';
|
||||||
|
import { readEnv } from '@/lib/config/read';
|
||||||
|
import { createToken, decryptToken, encryptToken } from '@/lib/crypto';
|
||||||
|
import { runMigrations } from '@/lib/db/migration';
|
||||||
|
import { log } from '@/lib/logger';
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import { join } from 'path';
|
import next from 'next';
|
||||||
import { createRequestHandler } from '@remix-run/express';
|
import { parse } from 'url';
|
||||||
import { convertEnv } from 'src/lib/config/convert';
|
|
||||||
import { log } from 'src/lib/logger';
|
|
||||||
import { readEnv } from 'src/lib/config/read';
|
|
||||||
import { runMigrations } from 'src/lib/migration';
|
|
||||||
|
|
||||||
const MODE = process.env.NODE_ENV || 'production';
|
const MODE = process.env.NODE_ENV || 'production';
|
||||||
const BUILD_DIR = join(process.cwd(), 'build');
|
|
||||||
|
|
||||||
const logger = log('server');
|
const logger = log('server');
|
||||||
|
|
||||||
logger.info(`starting zipline in ${MODE} mode`);
|
async function main() {
|
||||||
|
logger.info(`starting zipline in ${MODE} mode`);
|
||||||
|
|
||||||
runMigrations().then(() => {});
|
const server = express();
|
||||||
|
|
||||||
const server = express();
|
logger.info('reading environment for configuration');
|
||||||
const config = convertEnv(readEnv());
|
const config = validateEnv(readEnv());
|
||||||
|
|
||||||
server.disable('x-powered-by');
|
process.env.DATABASE_URL = config.core.databaseUrl;
|
||||||
|
|
||||||
server.use('/modules', express.static('public/build', { maxAge: '1y', immutable: true }));
|
await runMigrations();
|
||||||
server.use(express.static('public', { maxAge: '1h' }));
|
|
||||||
|
|
||||||
server.all(
|
server.disable('x-powered-by');
|
||||||
'*',
|
server.use(express.static('public', { maxAge: '1h' }));
|
||||||
MODE === 'production'
|
|
||||||
? createRequestHandler({ build: require(BUILD_DIR) })
|
|
||||||
: (...args) => {
|
|
||||||
purgeRequireCache();
|
|
||||||
const requestHandler = createRequestHandler({
|
|
||||||
build: require(BUILD_DIR),
|
|
||||||
mode: MODE,
|
|
||||||
getLoadContext() {
|
|
||||||
return {
|
|
||||||
config,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return requestHandler(...args);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
server.listen(3000, () => {
|
const app = next({
|
||||||
require(BUILD_DIR);
|
dev: MODE === 'development',
|
||||||
|
quiet: MODE === 'production',
|
||||||
|
hostname: config.core.hostname,
|
||||||
|
port: config.core.port,
|
||||||
|
dir: '.',
|
||||||
|
});
|
||||||
|
const handle = app.getRequestHandler();
|
||||||
|
|
||||||
logger.info(`server listening on port ${config.core.port}`);
|
await app.prepare();
|
||||||
});
|
|
||||||
|
|
||||||
function purgeRequireCache() {
|
server.all('*', (req, res) => {
|
||||||
for (const key in require.cache) {
|
const parsedUrl = parse(req.url!, true);
|
||||||
if (key.startsWith(BUILD_DIR)) {
|
return handle(req, res, parsedUrl);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
});
|
||||||
delete require.cache[key];
|
|
||||||
}
|
server.listen(config.core.port, config.core.hostname, () => {
|
||||||
}
|
logger.info(`server listening on port ${config.core.port}`);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
{
|
{
|
||||||
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
|
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["DOM", "DOM.Iterable", "ES2019"],
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"jsx": "react-jsx",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"strict": true,
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"skipLibCheck": true,
|
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
|
||||||
"~/*": ["src/app/*"],
|
|
||||||
"lib/*": ["src/lib/*"]
|
|
||||||
},
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"isolatedModules": true,
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"noEmit": true
|
"isolatedModules": true,
|
||||||
}
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|
657
yarn.lock
657
yarn.lock
|
@ -3440,6 +3440,20 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@mantine/next@npm:^6.0.14":
|
||||||
|
version: 6.0.14
|
||||||
|
resolution: "@mantine/next@npm:6.0.14"
|
||||||
|
dependencies:
|
||||||
|
"@mantine/ssr": 6.0.14
|
||||||
|
"@mantine/styles": 6.0.14
|
||||||
|
peerDependencies:
|
||||||
|
next: "*"
|
||||||
|
react: ">=16.8.0"
|
||||||
|
react-dom: ">=16.8.0"
|
||||||
|
checksum: d610f6f353b5184610fd2f1cfd51de47d9a7f2006f9c74661c7911ff64e86c41876404e6642a76fb549600579d9a164b4f0b1de645ceeec78094a6ab922a4525
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@mantine/notifications@npm:^6.0.14":
|
"@mantine/notifications@npm:^6.0.14":
|
||||||
version: 6.0.14
|
version: 6.0.14
|
||||||
resolution: "@mantine/notifications@npm:6.0.14"
|
resolution: "@mantine/notifications@npm:6.0.14"
|
||||||
|
@ -3455,33 +3469,17 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@mantine/prism@npm:^6.0.14":
|
"@mantine/nprogress@npm:^6.0.14":
|
||||||
version: 6.0.14
|
version: 6.0.14
|
||||||
resolution: "@mantine/prism@npm:6.0.14"
|
resolution: "@mantine/nprogress@npm:6.0.14"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@mantine/utils": 6.0.14
|
"@mantine/utils": 6.0.14
|
||||||
prism-react-renderer: ^1.2.1
|
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@mantine/core": 6.0.14
|
"@mantine/core": 6.0.14
|
||||||
"@mantine/hooks": 6.0.14
|
"@mantine/hooks": 6.0.14
|
||||||
react: ">=16.8.0"
|
react: ">=16.8.0"
|
||||||
react-dom: ">=16.8.0"
|
react-dom: ">=16.8.0"
|
||||||
checksum: a5e554a4ff310949ee3104e50f7d7b9086046b2a2fdaa705ec6b18c152963f5d2a416e7a165a33f5b053c23a0cf7c95cc2bdc0b9ddd34b0abf9efacb91351c2c
|
checksum: a26d216f3869624a512409d148f5eea6edeee1f29688ef8113f7a5229e051ed3d5d0bed9a13746a53d2d490e391cd8ca5a5ea22133aa868532d920a498620722
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@mantine/remix@npm:^6.0.14":
|
|
||||||
version: 6.0.14
|
|
||||||
resolution: "@mantine/remix@npm:6.0.14"
|
|
||||||
dependencies:
|
|
||||||
"@mantine/ssr": 6.0.14
|
|
||||||
"@mantine/styles": 6.0.14
|
|
||||||
peerDependencies:
|
|
||||||
"@mantine/core": 6.0.14
|
|
||||||
"@mantine/hooks": 6.0.14
|
|
||||||
react: ">=16.8.0"
|
|
||||||
react-dom: ">=16.8.0"
|
|
||||||
checksum: 52a131ebd7369ea240dd96464263e2f4440073ce32cddaa0810f5157924223828715a9644058a1d108e7a6bb56827ead474e110002f37dd771a6043bcb854219
|
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -3523,6 +3521,95 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@mapbox/node-pre-gyp@npm:^1.0.10":
|
||||||
|
version: 1.0.10
|
||||||
|
resolution: "@mapbox/node-pre-gyp@npm:1.0.10"
|
||||||
|
dependencies:
|
||||||
|
detect-libc: ^2.0.0
|
||||||
|
https-proxy-agent: ^5.0.0
|
||||||
|
make-dir: ^3.1.0
|
||||||
|
node-fetch: ^2.6.7
|
||||||
|
nopt: ^5.0.0
|
||||||
|
npmlog: ^5.0.1
|
||||||
|
rimraf: ^3.0.2
|
||||||
|
semver: ^7.3.5
|
||||||
|
tar: ^6.1.11
|
||||||
|
bin:
|
||||||
|
node-pre-gyp: bin/node-pre-gyp
|
||||||
|
checksum: 1a98db05d955b74dad3814679593df293b9194853698f3f5f1ed00ecd93128cdd4b14fb8767fe44ac6981ef05c23effcfdc88710e7c1de99ccb6f647890597c8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@next/env@npm:13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "@next/env@npm:13.4.7"
|
||||||
|
checksum: 5a2bba68fb8c80c87324025f10af7fe7319efdb15777247bfa8ff58e61bcc19b150bce4068396351e6c6df3344294cc06c03a2fb1bb0330659d230830a202c53
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@next/swc-darwin-arm64@npm:13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "@next/swc-darwin-arm64@npm:13.4.7"
|
||||||
|
conditions: os=darwin & cpu=arm64
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@next/swc-darwin-x64@npm:13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "@next/swc-darwin-x64@npm:13.4.7"
|
||||||
|
conditions: os=darwin & cpu=x64
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@next/swc-linux-arm64-gnu@npm:13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "@next/swc-linux-arm64-gnu@npm:13.4.7"
|
||||||
|
conditions: os=linux & cpu=arm64 & libc=glibc
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@next/swc-linux-arm64-musl@npm:13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "@next/swc-linux-arm64-musl@npm:13.4.7"
|
||||||
|
conditions: os=linux & cpu=arm64 & libc=musl
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@next/swc-linux-x64-gnu@npm:13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "@next/swc-linux-x64-gnu@npm:13.4.7"
|
||||||
|
conditions: os=linux & cpu=x64 & libc=glibc
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@next/swc-linux-x64-musl@npm:13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "@next/swc-linux-x64-musl@npm:13.4.7"
|
||||||
|
conditions: os=linux & cpu=x64 & libc=musl
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@next/swc-win32-arm64-msvc@npm:13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "@next/swc-win32-arm64-msvc@npm:13.4.7"
|
||||||
|
conditions: os=win32 & cpu=arm64
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@next/swc-win32-ia32-msvc@npm:13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "@next/swc-win32-ia32-msvc@npm:13.4.7"
|
||||||
|
conditions: os=win32 & cpu=ia32
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@next/swc-win32-x64-msvc@npm:13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "@next/swc-win32-x64-msvc@npm:13.4.7"
|
||||||
|
conditions: os=win32 & cpu=x64
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1":
|
"@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1":
|
||||||
version: 5.1.1-v1
|
version: 5.1.1-v1
|
||||||
resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1"
|
resolution: "@nicolo-ribaudo/eslint-scope-5-internals@npm:5.1.1-v1"
|
||||||
|
@ -3604,6 +3691,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@phc/format@npm:^1.0.0":
|
||||||
|
version: 1.0.0
|
||||||
|
resolution: "@phc/format@npm:1.0.0"
|
||||||
|
checksum: 15ee02504fbc16590923d89b1f1c2f5892df27cf2bf19180e5678511413e87b6e5355815a092749cd01698855ee5a0fc5d2393951c727acd650934eed290e26e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@pkgjs/parseargs@npm:^0.11.0":
|
"@pkgjs/parseargs@npm:^0.11.0":
|
||||||
version: 0.11.0
|
version: 0.11.0
|
||||||
resolution: "@pkgjs/parseargs@npm:0.11.0"
|
resolution: "@pkgjs/parseargs@npm:0.11.0"
|
||||||
|
@ -4041,47 +4135,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@remix-run/express@npm:^1.17.1":
|
|
||||||
version: 1.17.1
|
|
||||||
resolution: "@remix-run/express@npm:1.17.1"
|
|
||||||
dependencies:
|
|
||||||
"@remix-run/node": 1.17.1
|
|
||||||
peerDependencies:
|
|
||||||
express: ^4.17.1
|
|
||||||
checksum: b6109837f0f6d5c91794e137c68ea25eec40e43bcdecf63c6c80a3b38b1c27d34f06c91da54df6e3f2d16e6d65979f743fe58dd18bc85d2fe8bd7e38ef72a13f
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@remix-run/node@npm:1.17.1, @remix-run/node@npm:^1.16.1":
|
|
||||||
version: 1.17.1
|
|
||||||
resolution: "@remix-run/node@npm:1.17.1"
|
|
||||||
dependencies:
|
|
||||||
"@remix-run/server-runtime": 1.17.1
|
|
||||||
"@remix-run/web-fetch": ^4.3.4
|
|
||||||
"@remix-run/web-file": ^3.0.2
|
|
||||||
"@remix-run/web-stream": ^1.0.3
|
|
||||||
"@web3-storage/multipart-parser": ^1.0.0
|
|
||||||
abort-controller: ^3.0.0
|
|
||||||
cookie-signature: ^1.1.0
|
|
||||||
source-map-support: ^0.5.21
|
|
||||||
stream-slice: ^0.1.2
|
|
||||||
checksum: 4e4d984ca1dc01f7c50983f99fbbbc97cb0629cac4cedad3970fc3591207c8d1ff690cfa07451dc3b1f9ad30ae75200bb21006b3793548d89a64daa40d5bf5eb
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@remix-run/react@npm:^1.16.1":
|
|
||||||
version: 1.17.1
|
|
||||||
resolution: "@remix-run/react@npm:1.17.1"
|
|
||||||
dependencies:
|
|
||||||
"@remix-run/router": 1.6.3
|
|
||||||
react-router-dom: 6.13.0
|
|
||||||
peerDependencies:
|
|
||||||
react: ">=16.8"
|
|
||||||
react-dom: ">=16.8"
|
|
||||||
checksum: 59f573c7d78af33b77ae4df76895ccb70cd5e11f73653567732a3a32dd92d192c984a1ccd3d178df214e66505e80a30b8b26b03bc829dc98ed4452db977a3c43
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@remix-run/router@npm:1.6.3":
|
"@remix-run/router@npm:1.6.3":
|
||||||
version: 1.6.3
|
version: 1.6.3
|
||||||
resolution: "@remix-run/router@npm:1.6.3"
|
resolution: "@remix-run/router@npm:1.6.3"
|
||||||
|
@ -4102,69 +4155,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@remix-run/v1-route-convention@npm:^0.1.2":
|
|
||||||
version: 0.1.2
|
|
||||||
resolution: "@remix-run/v1-route-convention@npm:0.1.2"
|
|
||||||
dependencies:
|
|
||||||
minimatch: ^7.4.3
|
|
||||||
peerDependencies:
|
|
||||||
"@remix-run/dev": ^1.15.0
|
|
||||||
checksum: c057b4fd696e4bda869663be757fda2b647604ee65441882a2cf4aa5ea76e6630e293a4110817891cc8eab06574e04c60e6306f1e3b02dbfa21231882fc7a722
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@remix-run/web-blob@npm:^3.0.3, @remix-run/web-blob@npm:^3.0.4":
|
|
||||||
version: 3.0.4
|
|
||||||
resolution: "@remix-run/web-blob@npm:3.0.4"
|
|
||||||
dependencies:
|
|
||||||
"@remix-run/web-stream": ^1.0.0
|
|
||||||
web-encoding: 1.1.5
|
|
||||||
checksum: 07d9a71d1795e8973cdc59c1a325aaaae7b9099a96815849355a34667d7a953cac78a332e02b25e0722d4d7244b7fe6d7ce6fc854e8baf83e42e8403f4a321fd
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@remix-run/web-fetch@npm:^4.3.4":
|
|
||||||
version: 4.3.4
|
|
||||||
resolution: "@remix-run/web-fetch@npm:4.3.4"
|
|
||||||
dependencies:
|
|
||||||
"@remix-run/web-blob": ^3.0.4
|
|
||||||
"@remix-run/web-form-data": ^3.0.3
|
|
||||||
"@remix-run/web-stream": ^1.0.3
|
|
||||||
"@web3-storage/multipart-parser": ^1.0.0
|
|
||||||
abort-controller: ^3.0.0
|
|
||||||
data-uri-to-buffer: ^3.0.1
|
|
||||||
mrmime: ^1.0.0
|
|
||||||
checksum: 0c3370bfde1867722654734cddfab90982ba657a4244bf8e7e4aa49cb5e3c0b3429ed94b760d6881b8bf45d93bf411f29b9ffaf19332ecdc0bae1fa42b9a06fb
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@remix-run/web-file@npm:^3.0.2":
|
|
||||||
version: 3.0.2
|
|
||||||
resolution: "@remix-run/web-file@npm:3.0.2"
|
|
||||||
dependencies:
|
|
||||||
"@remix-run/web-blob": ^3.0.3
|
|
||||||
checksum: f3bda87b62648e3ef0c0049aa560318d64adf493566a6446eae5a9d15a6080eb0c8ba1f450d4d7bbfa6cbad8c8d6a7adf4e72d546a4305ce0c05f63a95f80db0
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@remix-run/web-form-data@npm:^3.0.3":
|
|
||||||
version: 3.0.4
|
|
||||||
resolution: "@remix-run/web-form-data@npm:3.0.4"
|
|
||||||
dependencies:
|
|
||||||
web-encoding: 1.1.5
|
|
||||||
checksum: 75c4c07c3307081d17d63b6d26209c651e5ccb910b96fa467415dcceb3f5e7c82d18cc34f604ffc5e85e2d3e77b93b9c2ef670b97745deccfe03cf85647cca17
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@remix-run/web-stream@npm:^1.0.0, @remix-run/web-stream@npm:^1.0.3":
|
|
||||||
version: 1.0.3
|
|
||||||
resolution: "@remix-run/web-stream@npm:1.0.3"
|
|
||||||
dependencies:
|
|
||||||
web-streams-polyfill: ^3.1.1
|
|
||||||
checksum: 61a76b9e4ddb364fa5faa8cf28484f39800bd9259d4c2b96c235bd436e539d8bb00d433fcf79730d7bdf103255473fe0ccfde5d3c20a152f738c5bb102b26377
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@rollup/pluginutils@npm:^4.0.0":
|
"@rollup/pluginutils@npm:^4.0.0":
|
||||||
version: 4.2.1
|
version: 4.2.1
|
||||||
resolution: "@rollup/pluginutils@npm:4.2.1"
|
resolution: "@rollup/pluginutils@npm:4.2.1"
|
||||||
|
@ -4244,6 +4234,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@swc/helpers@npm:0.5.1":
|
||||||
|
version: 0.5.1
|
||||||
|
resolution: "@swc/helpers@npm:0.5.1"
|
||||||
|
dependencies:
|
||||||
|
tslib: ^2.4.0
|
||||||
|
checksum: 71e0e27234590435e4c62b97ef5e796f88e786841a38c7116a5e27a3eafa7b9ead7cdec5249b32165902076de78446945311c973e59bddf77c1e24f33a8f272a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@szmarczak/http-timer@npm:^4.0.5":
|
"@szmarczak/http-timer@npm:^4.0.5":
|
||||||
version: 4.0.6
|
version: 4.0.6
|
||||||
resolution: "@szmarczak/http-timer@npm:4.0.6"
|
resolution: "@szmarczak/http-timer@npm:4.0.6"
|
||||||
|
@ -4253,6 +4252,25 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@tabler/icons-react@npm:^2.22.0":
|
||||||
|
version: 2.22.0
|
||||||
|
resolution: "@tabler/icons-react@npm:2.22.0"
|
||||||
|
dependencies:
|
||||||
|
"@tabler/icons": 2.22.0
|
||||||
|
prop-types: ^15.7.2
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.5.1 || ^17.0.0 || ^18.0.0
|
||||||
|
checksum: fe2a4c3e5483269ee178195746cdc4b8c1e150dec78aae4bbf3884f33dd819929a7ff1e53eb6ba1426b914ba710e13a30d0e70caf9e588b8df45e500f70941dd
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@tabler/icons@npm:2.22.0":
|
||||||
|
version: 2.22.0
|
||||||
|
resolution: "@tabler/icons@npm:2.22.0"
|
||||||
|
checksum: 3f0aaa801e8739d841ac5d335fbaee41399aaa9eeae03eb21c1dbe77877a29ba3664f16c225323a0635fad6548aca40212220edfb2919797454ea1029c5a5b78
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@tediousjs/connection-string@npm:^0.4.1":
|
"@tediousjs/connection-string@npm:^0.4.1":
|
||||||
version: 0.4.2
|
version: 0.4.2
|
||||||
resolution: "@tediousjs/connection-string@npm:0.4.2"
|
resolution: "@tediousjs/connection-string@npm:0.4.2"
|
||||||
|
@ -4444,6 +4462,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/http-errors@npm:*":
|
||||||
|
version: 2.0.1
|
||||||
|
resolution: "@types/http-errors@npm:2.0.1"
|
||||||
|
checksum: 3bb0c50b0a652e679a84c30cd0340d696c32ef6558518268c238840346c077f899315daaf1c26c09c57ddd5dc80510f2a7f46acd52bf949e339e35ed3ee9654f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/json-schema@npm:^7.0.9":
|
"@types/json-schema@npm:^7.0.9":
|
||||||
version: 7.0.12
|
version: 7.0.12
|
||||||
resolution: "@types/json-schema@npm:7.0.12"
|
resolution: "@types/json-schema@npm:7.0.12"
|
||||||
|
@ -4621,12 +4646,13 @@ __metadata:
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@types/serve-static@npm:*":
|
"@types/serve-static@npm:*":
|
||||||
version: 1.15.1
|
version: 1.15.2
|
||||||
resolution: "@types/serve-static@npm:1.15.1"
|
resolution: "@types/serve-static@npm:1.15.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@types/http-errors": "*"
|
||||||
"@types/mime": "*"
|
"@types/mime": "*"
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
checksum: 2e078bdc1e458c7dfe69e9faa83cc69194b8896cce57cb745016580543c7ab5af07fdaa8ac1765eb79524208c81017546f66056f44d1204f812d72810613de36
|
checksum: 15c261dbfc57890f7cc17c04d5b22b418dfa0330c912b46c5d8ae2064da5d6f844ef7f41b63c7f4bbf07675e97ebe6ac804b032635ec742ae45d6f1274259b3e
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -4847,29 +4873,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@zxing/text-encoding@npm:0.9.0":
|
"abbrev@npm:1, abbrev@npm:^1.0.0":
|
||||||
version: 0.9.0
|
|
||||||
resolution: "@zxing/text-encoding@npm:0.9.0"
|
|
||||||
checksum: c23b12aee7639382e4949961304a1294776afaffa40f579e09ffecd0e5e68cf26ef3edd75009de46da8a536e571448755ca68b3e2ea707d53793c0edb2e2c34a
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"abbrev@npm:^1.0.0":
|
|
||||||
version: 1.1.1
|
version: 1.1.1
|
||||||
resolution: "abbrev@npm:1.1.1"
|
resolution: "abbrev@npm:1.1.1"
|
||||||
checksum: a4a97ec07d7ea112c517036882b2ac22f3109b7b19077dc656316d07d308438aac28e4d9746dc4d84bf6b1e75b4a7b0a5f3cb30592419f128ca9a8cee3bcfa17
|
checksum: a4a97ec07d7ea112c517036882b2ac22f3109b7b19077dc656316d07d308438aac28e4d9746dc4d84bf6b1e75b4a7b0a5f3cb30592419f128ca9a8cee3bcfa17
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"abort-controller@npm:^3.0.0":
|
|
||||||
version: 3.0.0
|
|
||||||
resolution: "abort-controller@npm:3.0.0"
|
|
||||||
dependencies:
|
|
||||||
event-target-shim: ^5.0.0
|
|
||||||
checksum: 170bdba9b47b7e65906a28c8ce4f38a7a369d78e2271706f020849c1bfe0ee2067d4261df8bbb66eb84f79208fd5b710df759d64191db58cfba7ce8ef9c54b75
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"accepts@npm:~1.3.8":
|
"accepts@npm:~1.3.8":
|
||||||
version: 1.3.8
|
version: 1.3.8
|
||||||
resolution: "accepts@npm:1.3.8"
|
resolution: "accepts@npm:1.3.8"
|
||||||
|
@ -5075,6 +5085,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"are-we-there-yet@npm:^2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "are-we-there-yet@npm:2.0.0"
|
||||||
|
dependencies:
|
||||||
|
delegates: ^1.0.0
|
||||||
|
readable-stream: ^3.6.0
|
||||||
|
checksum: 6c80b4fd04ecee6ba6e737e0b72a4b41bdc64b7d279edfc998678567ff583c8df27e27523bc789f2c99be603ffa9eaa612803da1d886962d2086e7ff6fa90c7c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"are-we-there-yet@npm:^3.0.0":
|
"are-we-there-yet@npm:^3.0.0":
|
||||||
version: 3.0.1
|
version: 3.0.1
|
||||||
resolution: "are-we-there-yet@npm:3.0.1"
|
resolution: "are-we-there-yet@npm:3.0.1"
|
||||||
|
@ -5092,6 +5112,17 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"argon2@npm:^0.30.3":
|
||||||
|
version: 0.30.3
|
||||||
|
resolution: "argon2@npm:0.30.3"
|
||||||
|
dependencies:
|
||||||
|
"@mapbox/node-pre-gyp": ^1.0.10
|
||||||
|
"@phc/format": ^1.0.0
|
||||||
|
node-addon-api: ^5.0.0
|
||||||
|
checksum: 36784f69af8adad1e0e155a0f1999320999a3b76fb41a3b8f4674e1d896dc65a6e76bea4385b9433e8f935d0912a9ca81088b5d8d22e5fe4119d5abf9d10761f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"argparse@npm:^2.0.1":
|
"argparse@npm:^2.0.1":
|
||||||
version: 2.0.1
|
version: 2.0.1
|
||||||
resolution: "argparse@npm:2.0.1"
|
resolution: "argparse@npm:2.0.1"
|
||||||
|
@ -5576,6 +5607,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"busboy@npm:1.6.0":
|
||||||
|
version: 1.6.0
|
||||||
|
resolution: "busboy@npm:1.6.0"
|
||||||
|
dependencies:
|
||||||
|
streamsearch: ^1.1.0
|
||||||
|
checksum: 32801e2c0164e12106bf236291a00795c3c4e4b709ae02132883fe8478ba2ae23743b11c5735a0aae8afe65ac4b6ca4568b91f0d9fed1fdbc32ede824a73746e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"bytes@npm:3.1.2, bytes@npm:^3.1.2":
|
"bytes@npm:3.1.2, bytes@npm:^3.1.2":
|
||||||
version: 3.1.2
|
version: 3.1.2
|
||||||
resolution: "bytes@npm:3.1.2"
|
resolution: "bytes@npm:3.1.2"
|
||||||
|
@ -5675,6 +5715,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"caniuse-lite@npm:^1.0.30001406":
|
||||||
|
version: 1.0.30001507
|
||||||
|
resolution: "caniuse-lite@npm:1.0.30001507"
|
||||||
|
checksum: 7044172bdf65140c927cdaaff50368a97676f06a9fd8b515c046613bdf52cb769e9efb832ee491b8f8cc21f82c15f154a896efbab690f431bb064c95f3a2b7a8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"caniuse-lite@npm:^1.0.30001503":
|
"caniuse-lite@npm:^1.0.30001503":
|
||||||
version: 1.0.30001506
|
version: 1.0.30001506
|
||||||
resolution: "caniuse-lite@npm:1.0.30001506"
|
resolution: "caniuse-lite@npm:1.0.30001506"
|
||||||
|
@ -5833,6 +5880,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"client-only@npm:0.0.1":
|
||||||
|
version: 0.0.1
|
||||||
|
resolution: "client-only@npm:0.0.1"
|
||||||
|
checksum: 0c16bf660dadb90610553c1d8946a7fdfb81d624adea073b8440b7d795d5b5b08beb3c950c6a2cf16279365a3265158a236876d92bce16423c485c322d7dfaf8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"clone-response@npm:^1.0.2":
|
"clone-response@npm:^1.0.2":
|
||||||
version: 1.0.3
|
version: 1.0.3
|
||||||
resolution: "clone-response@npm:1.0.3"
|
resolution: "clone-response@npm:1.0.3"
|
||||||
|
@ -5888,7 +5942,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"color-support@npm:^1.1.3":
|
"color-support@npm:^1.1.2, color-support@npm:^1.1.3":
|
||||||
version: 1.1.3
|
version: 1.1.3
|
||||||
resolution: "color-support@npm:1.1.3"
|
resolution: "color-support@npm:1.1.3"
|
||||||
bin:
|
bin:
|
||||||
|
@ -5960,7 +6014,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"console-control-strings@npm:^1.1.0":
|
"console-control-strings@npm:^1.0.0, console-control-strings@npm:^1.1.0":
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
resolution: "console-control-strings@npm:1.1.0"
|
resolution: "console-control-strings@npm:1.1.0"
|
||||||
checksum: 8755d76787f94e6cf79ce4666f0c5519906d7f5b02d4b884cf41e11dcd759ed69c57da0670afd9236d229a46e0f9cf519db0cd829c6dca820bb5a5c3def584ed
|
checksum: 8755d76787f94e6cf79ce4666f0c5519906d7f5b02d4b884cf41e11dcd759ed69c57da0670afd9236d229a46e0f9cf519db0cd829c6dca820bb5a5c3def584ed
|
||||||
|
@ -5997,13 +6051,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"cookie-signature@npm:^1.1.0":
|
|
||||||
version: 1.2.1
|
|
||||||
resolution: "cookie-signature@npm:1.2.1"
|
|
||||||
checksum: bb464aacac390b5d7d8ead2d6fff7c1c3b7378c7d0250921f48923fe889688e081ab33950448929db5f24d4f9f1506589a7ee1c685de8f12a3fdb30c49667ec5
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"cookie@npm:0.5.0":
|
"cookie@npm:0.5.0":
|
||||||
version: 0.5.0
|
version: 0.5.0
|
||||||
resolution: "cookie@npm:0.5.0"
|
resolution: "cookie@npm:0.5.0"
|
||||||
|
@ -6146,7 +6193,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"data-uri-to-buffer@npm:3, data-uri-to-buffer@npm:^3.0.1":
|
"data-uri-to-buffer@npm:3":
|
||||||
version: 3.0.1
|
version: 3.0.1
|
||||||
resolution: "data-uri-to-buffer@npm:3.0.1"
|
resolution: "data-uri-to-buffer@npm:3.0.1"
|
||||||
checksum: c59c3009686a78c071806b72f4810856ec28222f0f4e252aa495ec027ed9732298ceea99c50328cf59b151dd34cbc3ad6150bbb43e41fc56fa19f48c99e9fc30
|
checksum: c59c3009686a78c071806b72f4810856ec28222f0f4e252aa495ec027ed9732298ceea99c50328cf59b151dd34cbc3ad6150bbb43e41fc56fa19f48c99e9fc30
|
||||||
|
@ -6404,6 +6451,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"detect-libc@npm:^2.0.0":
|
||||||
|
version: 2.0.1
|
||||||
|
resolution: "detect-libc@npm:2.0.1"
|
||||||
|
checksum: ccb05fcabbb555beb544d48080179c18523a343face9ee4e1a86605a8715b4169f94d663c21a03c310ac824592f2ba9a5270218819bb411ad7be578a527593d7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"detect-newline@npm:3.1.0":
|
"detect-newline@npm:3.1.0":
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
resolution: "detect-newline@npm:3.1.0"
|
resolution: "detect-newline@npm:3.1.0"
|
||||||
|
@ -7506,13 +7560,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"event-target-shim@npm:^5.0.0":
|
|
||||||
version: 5.0.1
|
|
||||||
resolution: "event-target-shim@npm:5.0.1"
|
|
||||||
checksum: 1ffe3bb22a6d51bdeb6bf6f7cf97d2ff4a74b017ad12284cc9e6a279e727dc30a5de6bb613e5596ff4dc3e517841339ad09a7eec44266eccb1aa201a30448166
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"events@npm:^3.0.0":
|
"events@npm:^3.0.0":
|
||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
resolution: "events@npm:3.3.0"
|
resolution: "events@npm:3.3.0"
|
||||||
|
@ -8024,6 +8071,23 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"gauge@npm:^3.0.0":
|
||||||
|
version: 3.0.2
|
||||||
|
resolution: "gauge@npm:3.0.2"
|
||||||
|
dependencies:
|
||||||
|
aproba: ^1.0.3 || ^2.0.0
|
||||||
|
color-support: ^1.1.2
|
||||||
|
console-control-strings: ^1.0.0
|
||||||
|
has-unicode: ^2.0.1
|
||||||
|
object-assign: ^4.1.1
|
||||||
|
signal-exit: ^3.0.0
|
||||||
|
string-width: ^4.2.3
|
||||||
|
strip-ansi: ^6.0.1
|
||||||
|
wide-align: ^1.1.2
|
||||||
|
checksum: 81296c00c7410cdd48f997800155fbead4f32e4f82109be0719c63edc8560e6579946cc8abd04205297640691ec26d21b578837fd13a4e96288ab4b40b1dc3e9
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"gauge@npm:^4.0.3":
|
"gauge@npm:^4.0.3":
|
||||||
version: 4.0.4
|
version: 4.0.4
|
||||||
resolution: "gauge@npm:4.0.4"
|
resolution: "gauge@npm:4.0.4"
|
||||||
|
@ -8163,6 +8227,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"glob-to-regexp@npm:^0.4.1":
|
||||||
|
version: 0.4.1
|
||||||
|
resolution: "glob-to-regexp@npm:0.4.1"
|
||||||
|
checksum: e795f4e8f06d2a15e86f76e4d92751cf8bbfcf0157cea5c2f0f35678a8195a750b34096b1256e436f0cebc1883b5ff0888c47348443e69546a5a87f9e1eb1167
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"glob@npm:7.1.6":
|
"glob@npm:7.1.6":
|
||||||
version: 7.1.6
|
version: 7.1.6
|
||||||
resolution: "glob@npm:7.1.6"
|
resolution: "glob@npm:7.1.6"
|
||||||
|
@ -8842,7 +8913,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"is-arguments@npm:^1.0.4, is-arguments@npm:^1.1.1":
|
"is-arguments@npm:^1.1.1":
|
||||||
version: 1.1.1
|
version: 1.1.1
|
||||||
resolution: "is-arguments@npm:1.1.1"
|
resolution: "is-arguments@npm:1.1.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -8976,15 +9047,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"is-generator-function@npm:^1.0.7":
|
|
||||||
version: 1.0.10
|
|
||||||
resolution: "is-generator-function@npm:1.0.10"
|
|
||||||
dependencies:
|
|
||||||
has-tostringtag: ^1.0.0
|
|
||||||
checksum: d54644e7dbaccef15ceb1e5d91d680eb5068c9ee9f9eb0a9e04173eb5542c9b51b5ab52c5537f5703e48d5fddfd376817c1ca07a84a407b7115b769d4bdde72b
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1":
|
"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1":
|
||||||
version: 4.0.3
|
version: 4.0.3
|
||||||
resolution: "is-glob@npm:4.0.3"
|
resolution: "is-glob@npm:4.0.3"
|
||||||
|
@ -9165,7 +9227,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.3, is-typed-array@npm:^1.1.9":
|
"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.9":
|
||||||
version: 1.1.10
|
version: 1.1.10
|
||||||
resolution: "is-typed-array@npm:1.1.10"
|
resolution: "is-typed-array@npm:1.1.10"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -9248,13 +9310,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"isbot@npm:^3.6.10":
|
|
||||||
version: 3.6.12
|
|
||||||
resolution: "isbot@npm:3.6.12"
|
|
||||||
checksum: e23782a6633bf60fc3db23171468fc3f4cdc36f5a707b0cf1f3b2aff2686bedb29d036411afec90a9de23901a251ff53596ab9ca31cc85223dd8f03392fc03e6
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"isexe@npm:^2.0.0":
|
"isexe@npm:^2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "isexe@npm:2.0.0"
|
resolution: "isexe@npm:2.0.0"
|
||||||
|
@ -9832,7 +9887,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"make-dir@npm:3.1.0, make-dir@npm:^3.0.0, make-dir@npm:^3.0.2":
|
"make-dir@npm:3.1.0, make-dir@npm:^3.0.0, make-dir@npm:^3.0.2, make-dir@npm:^3.1.0":
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
resolution: "make-dir@npm:3.1.0"
|
resolution: "make-dir@npm:3.1.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -10540,15 +10595,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"minimatch@npm:^7.4.3":
|
|
||||||
version: 7.4.6
|
|
||||||
resolution: "minimatch@npm:7.4.6"
|
|
||||||
dependencies:
|
|
||||||
brace-expansion: ^2.0.1
|
|
||||||
checksum: 1a6c8d22618df9d2a88aabeef1de5622eb7b558e9f8010be791cb6b0fa6e102d39b11c28d75b855a1e377b12edc7db8ff12a99c20353441caa6a05e78deb5da9
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"minimatch@npm:^9.0.0, minimatch@npm:^9.0.1":
|
"minimatch@npm:^9.0.0, minimatch@npm:^9.0.1":
|
||||||
version: 9.0.1
|
version: 9.0.1
|
||||||
resolution: "minimatch@npm:9.0.1"
|
resolution: "minimatch@npm:9.0.1"
|
||||||
|
@ -10756,13 +10802,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"mrmime@npm:^1.0.0":
|
|
||||||
version: 1.0.1
|
|
||||||
resolution: "mrmime@npm:1.0.1"
|
|
||||||
checksum: cc979da44bbbffebaa8eaf7a45117e851f2d4cb46a3ada6ceb78130466a04c15a0de9a9ce1c8b8ba6f6e1b8618866b1352992bf1757d241c0ddca558b9f28a77
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"ms@npm:2.0.0":
|
"ms@npm:2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "ms@npm:2.0.0"
|
resolution: "ms@npm:2.0.0"
|
||||||
|
@ -10828,7 +10867,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"nanoid@npm:^3.3.6":
|
"nanoid@npm:^3.3.4, nanoid@npm:^3.3.6":
|
||||||
version: 3.3.6
|
version: 3.3.6
|
||||||
resolution: "nanoid@npm:3.3.6"
|
resolution: "nanoid@npm:3.3.6"
|
||||||
bin:
|
bin:
|
||||||
|
@ -10879,6 +10918,65 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"next@npm:^13.4.7":
|
||||||
|
version: 13.4.7
|
||||||
|
resolution: "next@npm:13.4.7"
|
||||||
|
dependencies:
|
||||||
|
"@next/env": 13.4.7
|
||||||
|
"@next/swc-darwin-arm64": 13.4.7
|
||||||
|
"@next/swc-darwin-x64": 13.4.7
|
||||||
|
"@next/swc-linux-arm64-gnu": 13.4.7
|
||||||
|
"@next/swc-linux-arm64-musl": 13.4.7
|
||||||
|
"@next/swc-linux-x64-gnu": 13.4.7
|
||||||
|
"@next/swc-linux-x64-musl": 13.4.7
|
||||||
|
"@next/swc-win32-arm64-msvc": 13.4.7
|
||||||
|
"@next/swc-win32-ia32-msvc": 13.4.7
|
||||||
|
"@next/swc-win32-x64-msvc": 13.4.7
|
||||||
|
"@swc/helpers": 0.5.1
|
||||||
|
busboy: 1.6.0
|
||||||
|
caniuse-lite: ^1.0.30001406
|
||||||
|
postcss: 8.4.14
|
||||||
|
styled-jsx: 5.1.1
|
||||||
|
watchpack: 2.4.0
|
||||||
|
zod: 3.21.4
|
||||||
|
peerDependencies:
|
||||||
|
"@opentelemetry/api": ^1.1.0
|
||||||
|
fibers: ">= 3.1.0"
|
||||||
|
react: ^18.2.0
|
||||||
|
react-dom: ^18.2.0
|
||||||
|
sass: ^1.3.0
|
||||||
|
dependenciesMeta:
|
||||||
|
"@next/swc-darwin-arm64":
|
||||||
|
optional: true
|
||||||
|
"@next/swc-darwin-x64":
|
||||||
|
optional: true
|
||||||
|
"@next/swc-linux-arm64-gnu":
|
||||||
|
optional: true
|
||||||
|
"@next/swc-linux-arm64-musl":
|
||||||
|
optional: true
|
||||||
|
"@next/swc-linux-x64-gnu":
|
||||||
|
optional: true
|
||||||
|
"@next/swc-linux-x64-musl":
|
||||||
|
optional: true
|
||||||
|
"@next/swc-win32-arm64-msvc":
|
||||||
|
optional: true
|
||||||
|
"@next/swc-win32-ia32-msvc":
|
||||||
|
optional: true
|
||||||
|
"@next/swc-win32-x64-msvc":
|
||||||
|
optional: true
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@opentelemetry/api":
|
||||||
|
optional: true
|
||||||
|
fibers:
|
||||||
|
optional: true
|
||||||
|
sass:
|
||||||
|
optional: true
|
||||||
|
bin:
|
||||||
|
next: dist/bin/next
|
||||||
|
checksum: 76026a5def68c00064bc4860cd15a5f292220ccc73ff24245b3658a90a46f66c290d3543a59e1cb91310145141d4ad1238d7cf652f41f47cdf434ab8705af7d1
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"nice-try@npm:^1.0.4":
|
"nice-try@npm:^1.0.4":
|
||||||
version: 1.0.5
|
version: 1.0.5
|
||||||
resolution: "nice-try@npm:1.0.5"
|
resolution: "nice-try@npm:1.0.5"
|
||||||
|
@ -10902,7 +11000,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"node-fetch@npm:2.6.11, node-fetch@npm:^2.6.9":
|
"node-addon-api@npm:^5.0.0":
|
||||||
|
version: 5.1.0
|
||||||
|
resolution: "node-addon-api@npm:5.1.0"
|
||||||
|
dependencies:
|
||||||
|
node-gyp: latest
|
||||||
|
checksum: 2508bd2d2981945406243a7bd31362fc7af8b70b8b4d65f869c61731800058fb818cc2fd36c8eac714ddd0e568cc85becf5e165cebbdf7b5024d5151bbc75ea1
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"node-fetch@npm:2.6.11, node-fetch@npm:^2.6.7, node-fetch@npm:^2.6.9":
|
||||||
version: 2.6.11
|
version: 2.6.11
|
||||||
resolution: "node-fetch@npm:2.6.11"
|
resolution: "node-fetch@npm:2.6.11"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -10944,6 +11051,17 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"nopt@npm:^5.0.0":
|
||||||
|
version: 5.0.0
|
||||||
|
resolution: "nopt@npm:5.0.0"
|
||||||
|
dependencies:
|
||||||
|
abbrev: 1
|
||||||
|
bin:
|
||||||
|
nopt: bin/nopt.js
|
||||||
|
checksum: d35fdec187269503843924e0114c0c6533fb54bbf1620d0f28b4b60ba01712d6687f62565c55cc20a504eff0fbe5c63e22340c3fad549ad40469ffb611b04f2f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"nopt@npm:^6.0.0":
|
"nopt@npm:^6.0.0":
|
||||||
version: 6.0.0
|
version: 6.0.0
|
||||||
resolution: "nopt@npm:6.0.0"
|
resolution: "nopt@npm:6.0.0"
|
||||||
|
@ -11050,6 +11168,18 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"npmlog@npm:^5.0.1":
|
||||||
|
version: 5.0.1
|
||||||
|
resolution: "npmlog@npm:5.0.1"
|
||||||
|
dependencies:
|
||||||
|
are-we-there-yet: ^2.0.0
|
||||||
|
console-control-strings: ^1.1.0
|
||||||
|
gauge: ^3.0.0
|
||||||
|
set-blocking: ^2.0.0
|
||||||
|
checksum: 516b2663028761f062d13e8beb3f00069c5664925871a9b57989642ebe09f23ab02145bf3ab88da7866c4e112cafff72401f61a672c7c8a20edc585a7016ef5f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"npmlog@npm:^6.0.0":
|
"npmlog@npm:^6.0.0":
|
||||||
version: 6.0.2
|
version: 6.0.2
|
||||||
resolution: "npmlog@npm:6.0.2"
|
resolution: "npmlog@npm:6.0.2"
|
||||||
|
@ -11835,6 +11965,17 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"postcss@npm:8.4.14":
|
||||||
|
version: 8.4.14
|
||||||
|
resolution: "postcss@npm:8.4.14"
|
||||||
|
dependencies:
|
||||||
|
nanoid: ^3.3.4
|
||||||
|
picocolors: ^1.0.0
|
||||||
|
source-map-js: ^1.0.2
|
||||||
|
checksum: fe58766ff32e4becf65a7d57678995cfd239df6deed2fe0557f038b47c94e4132e7e5f68b5aa820c13adfec32e523b693efaeb65798efb995ce49ccd83953816
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"postcss@npm:^8.4.19, postcss@npm:^8.4.23":
|
"postcss@npm:^8.4.19, postcss@npm:^8.4.23":
|
||||||
version: 8.4.24
|
version: 8.4.24
|
||||||
resolution: "postcss@npm:8.4.24"
|
resolution: "postcss@npm:8.4.24"
|
||||||
|
@ -11919,15 +12060,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"prism-react-renderer@npm:^1.2.1":
|
|
||||||
version: 1.3.5
|
|
||||||
resolution: "prism-react-renderer@npm:1.3.5"
|
|
||||||
peerDependencies:
|
|
||||||
react: ">=0.14.9"
|
|
||||||
checksum: c18806dcbc4c0b4fd6fd15bd06b4f7c0a6da98d93af235c3e970854994eb9b59e23315abb6cfc29e69da26d36709a47e25da85ab27fed81b6812f0a52caf6dfa
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"prisma@npm:^4.16.1":
|
"prisma@npm:^4.16.1":
|
||||||
version: 4.16.1
|
version: 4.16.1
|
||||||
resolution: "prisma@npm:4.16.1"
|
resolution: "prisma@npm:4.16.1"
|
||||||
|
@ -11981,7 +12113,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"prop-types@npm:^15.6.2, prop-types@npm:^15.8.1":
|
"prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1":
|
||||||
version: 15.8.1
|
version: 15.8.1
|
||||||
resolution: "prop-types@npm:15.8.1"
|
resolution: "prop-types@npm:15.8.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -12212,30 +12344,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-router-dom@npm:6.13.0":
|
|
||||||
version: 6.13.0
|
|
||||||
resolution: "react-router-dom@npm:6.13.0"
|
|
||||||
dependencies:
|
|
||||||
"@remix-run/router": 1.6.3
|
|
||||||
react-router: 6.13.0
|
|
||||||
peerDependencies:
|
|
||||||
react: ">=16.8"
|
|
||||||
react-dom: ">=16.8"
|
|
||||||
checksum: f51131063c2d5e127b6b3f3f813c6d4988d0f37694a06697dc9d4a4d9d3825e2a4487ec9b81a1d356eb269018814d884ffc2e3d9ff056a46ae59c99c9e7e1086
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"react-router@npm:6.13.0":
|
|
||||||
version: 6.13.0
|
|
||||||
resolution: "react-router@npm:6.13.0"
|
|
||||||
dependencies:
|
|
||||||
"@remix-run/router": 1.6.3
|
|
||||||
peerDependencies:
|
|
||||||
react: ">=16.8"
|
|
||||||
checksum: 31a187005d05e063c59324564a283cd28052eaf848ad446c87658f4fc48fa9543329fe8a14d7be14d9bbf62410d383f8cf1cf13898a838bf9c1e3201fe93384c
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"react-style-singleton@npm:^2.2.1":
|
"react-style-singleton@npm:^2.2.1":
|
||||||
version: 2.2.1
|
version: 2.2.1
|
||||||
resolution: "react-style-singleton@npm:2.2.1"
|
resolution: "react-style-singleton@npm:2.2.1"
|
||||||
|
@ -12958,7 +13066,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7":
|
"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7":
|
||||||
version: 3.0.7
|
version: 3.0.7
|
||||||
resolution: "signal-exit@npm:3.0.7"
|
resolution: "signal-exit@npm:3.0.7"
|
||||||
checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318
|
checksum: a2f098f247adc367dffc27845853e9959b9e88b01cb301658cfe4194352d8d2bb32e18467c786a7fe15f1d44b233ea35633d076d5e737870b7139949d1ab6318
|
||||||
|
@ -13236,10 +13344,10 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"stream-slice@npm:^0.1.2":
|
"streamsearch@npm:^1.1.0":
|
||||||
version: 0.1.2
|
version: 1.1.0
|
||||||
resolution: "stream-slice@npm:0.1.2"
|
resolution: "streamsearch@npm:1.1.0"
|
||||||
checksum: 027111397bd709f299fb1bb34902baf4707bba8851219c9115df673be1075a2cecf54d8671e6258c94483d1fa4e931c6784e49f2e005b1b6d5e3b8b61028fbe1
|
checksum: 1cce16cea8405d7a233d32ca5e00a00169cc0e19fbc02aa839959985f267335d435c07f96e5e0edd0eadc6d39c98d5435fb5bbbdefc62c41834eadc5622ad942
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -13456,6 +13564,22 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"styled-jsx@npm:5.1.1":
|
||||||
|
version: 5.1.1
|
||||||
|
resolution: "styled-jsx@npm:5.1.1"
|
||||||
|
dependencies:
|
||||||
|
client-only: 0.0.1
|
||||||
|
peerDependencies:
|
||||||
|
react: ">= 16.8.0 || 17.x.x || ^18.0.0-0"
|
||||||
|
peerDependenciesMeta:
|
||||||
|
"@babel/core":
|
||||||
|
optional: true
|
||||||
|
babel-plugin-macros:
|
||||||
|
optional: true
|
||||||
|
checksum: 523a33b38603492547e861b98e29c873939b04e15fbe5ef16132c6f1e15958126647983c7d4675325038b428a5e91183d996e90141b18bdd1bbadf6e2c45b2fa
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"stylis@npm:4.2.0":
|
"stylis@npm:4.2.0":
|
||||||
version: 4.2.0
|
version: 4.2.0
|
||||||
resolution: "stylis@npm:4.2.0"
|
resolution: "stylis@npm:4.2.0"
|
||||||
|
@ -14313,19 +14437,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"util@npm:^0.12.3":
|
|
||||||
version: 0.12.5
|
|
||||||
resolution: "util@npm:0.12.5"
|
|
||||||
dependencies:
|
|
||||||
inherits: ^2.0.3
|
|
||||||
is-arguments: ^1.0.4
|
|
||||||
is-generator-function: ^1.0.7
|
|
||||||
is-typed-array: ^1.1.3
|
|
||||||
which-typed-array: ^1.1.2
|
|
||||||
checksum: 705e51f0de5b446f4edec10739752ac25856541e0254ea1e7e45e5b9f9b0cb105bc4bd415736a6210edc68245a7f903bf085ffb08dd7deb8a0e847f60538a38a
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"utils-merge@npm:1.0.1":
|
"utils-merge@npm:1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "utils-merge@npm:1.0.1"
|
resolution: "utils-merge@npm:1.0.1"
|
||||||
|
@ -14480,6 +14591,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"watchpack@npm:2.4.0":
|
||||||
|
version: 2.4.0
|
||||||
|
resolution: "watchpack@npm:2.4.0"
|
||||||
|
dependencies:
|
||||||
|
glob-to-regexp: ^0.4.1
|
||||||
|
graceful-fs: ^4.1.2
|
||||||
|
checksum: 23d4bc58634dbe13b86093e01c6a68d8096028b664ab7139d58f0c37d962d549a940e98f2f201cecdabd6f9c340338dc73ef8bf094a2249ef582f35183d1a131
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"wcwidth@npm:^1.0.1":
|
"wcwidth@npm:^1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "wcwidth@npm:1.0.1"
|
resolution: "wcwidth@npm:1.0.1"
|
||||||
|
@ -14489,26 +14610,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"web-encoding@npm:1.1.5":
|
|
||||||
version: 1.1.5
|
|
||||||
resolution: "web-encoding@npm:1.1.5"
|
|
||||||
dependencies:
|
|
||||||
"@zxing/text-encoding": 0.9.0
|
|
||||||
util: ^0.12.3
|
|
||||||
dependenciesMeta:
|
|
||||||
"@zxing/text-encoding":
|
|
||||||
optional: true
|
|
||||||
checksum: 2234a2b122f41006ce07859b3c0bf2e18f46144fda2907d5db0b571b76aa5c26977c646100ad9c00d2f8a4f6f2b848bc02147845d8c447ab365ec4eff376338d
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"web-streams-polyfill@npm:^3.1.1":
|
|
||||||
version: 3.2.1
|
|
||||||
resolution: "web-streams-polyfill@npm:3.2.1"
|
|
||||||
checksum: b119c78574b6d65935e35098c2afdcd752b84268e18746606af149e3c424e15621b6f1ff0b42b2676dc012fc4f0d313f964b41a4b5031e525faa03997457da02
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"webidl-conversions@npm:^3.0.0":
|
"webidl-conversions@npm:^3.0.0":
|
||||||
version: 3.0.1
|
version: 3.0.1
|
||||||
resolution: "webidl-conversions@npm:3.0.1"
|
resolution: "webidl-conversions@npm:3.0.1"
|
||||||
|
@ -14586,7 +14687,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"which-typed-array@npm:^1.1.2, which-typed-array@npm:^1.1.9":
|
"which-typed-array@npm:^1.1.9":
|
||||||
version: 1.1.9
|
version: 1.1.9
|
||||||
resolution: "which-typed-array@npm:1.1.9"
|
resolution: "which-typed-array@npm:1.1.9"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -14622,7 +14723,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"wide-align@npm:^1.1.5":
|
"wide-align@npm:^1.1.2, wide-align@npm:^1.1.5":
|
||||||
version: 1.1.5
|
version: 1.1.5
|
||||||
resolution: "wide-align@npm:1.1.5"
|
resolution: "wide-align@npm:1.1.5"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -14807,24 +14908,22 @@ __metadata:
|
||||||
"@mantine/form": ^6.0.14
|
"@mantine/form": ^6.0.14
|
||||||
"@mantine/hooks": ^6.0.14
|
"@mantine/hooks": ^6.0.14
|
||||||
"@mantine/modals": ^6.0.14
|
"@mantine/modals": ^6.0.14
|
||||||
|
"@mantine/next": ^6.0.14
|
||||||
"@mantine/notifications": ^6.0.14
|
"@mantine/notifications": ^6.0.14
|
||||||
"@mantine/prism": ^6.0.14
|
"@mantine/nprogress": ^6.0.14
|
||||||
"@mantine/remix": ^6.0.14
|
|
||||||
"@prisma/client": 4.16.1
|
"@prisma/client": 4.16.1
|
||||||
"@prisma/internals": ^4.16.1
|
"@prisma/internals": ^4.16.1
|
||||||
"@prisma/migrate": ^4.16.1
|
"@prisma/migrate": ^4.16.1
|
||||||
"@remix-run/dev": ^1.16.1
|
"@remix-run/dev": ^1.16.1
|
||||||
"@remix-run/eslint-config": ^1.16.1
|
"@remix-run/eslint-config": ^1.16.1
|
||||||
"@remix-run/express": ^1.17.1
|
"@tabler/icons-react": ^2.22.0
|
||||||
"@remix-run/node": ^1.16.1
|
|
||||||
"@remix-run/react": ^1.16.1
|
|
||||||
"@remix-run/v1-route-convention": ^0.1.2
|
|
||||||
"@types/bytes": ^3.1.1
|
"@types/bytes": ^3.1.1
|
||||||
"@types/express": ^4.17.17
|
"@types/express": ^4.17.17
|
||||||
"@types/node": ^20.3.1
|
"@types/node": ^20.3.1
|
||||||
"@types/react": ^18.2.7
|
"@types/react": ^18.2.7
|
||||||
"@types/react-dom": ^18.2.4
|
"@types/react-dom": ^18.2.4
|
||||||
"@types/signale": ^1.4.4
|
"@types/signale": ^1.4.4
|
||||||
|
argon2: ^0.30.3
|
||||||
bytes: ^3.1.2
|
bytes: ^3.1.2
|
||||||
colorette: ^2.0.20
|
colorette: ^2.0.20
|
||||||
cross-env: ^7.0.3
|
cross-env: ^7.0.3
|
||||||
|
@ -14832,8 +14931,8 @@ __metadata:
|
||||||
dotenv: ^16.1.3
|
dotenv: ^16.1.3
|
||||||
eslint: ^8.41.0
|
eslint: ^8.41.0
|
||||||
express: ^4.18.2
|
express: ^4.18.2
|
||||||
isbot: ^3.6.10
|
|
||||||
ms: ^2.1.3
|
ms: ^2.1.3
|
||||||
|
next: ^13.4.7
|
||||||
npm-run-all: ^4.1.5
|
npm-run-all: ^4.1.5
|
||||||
prisma: ^4.16.1
|
prisma: ^4.16.1
|
||||||
react: ^18.2.0
|
react: ^18.2.0
|
||||||
|
@ -14856,7 +14955,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"zod@npm:^3.21.4":
|
"zod@npm:3.21.4, zod@npm:^3.21.4":
|
||||||
version: 3.21.4
|
version: 3.21.4
|
||||||
resolution: "zod@npm:3.21.4"
|
resolution: "zod@npm:3.21.4"
|
||||||
checksum: f185ba87342ff16f7a06686767c2b2a7af41110c7edf7c1974095d8db7a73792696bcb4a00853de0d2edeb34a5b2ea6a55871bc864227dace682a0a28de33e1f
|
checksum: f185ba87342ff16f7a06686767c2b2a7af41110c7edf7c1974095d8db7a73792696bcb4a00853de0d2edeb34a5b2ea6a55871bc864227dace682a0a28de33e1f
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue