mirror of
https://github.com/LukeHagar/dokploy.git
synced 2025-12-06 04:19:37 +00:00
feat: add migration
This commit is contained in:
255
apps/dokploy/drizzle/0066_broad_marrow.sql
Normal file
255
apps/dokploy/drizzle/0066_broad_marrow.sql
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
CREATE TABLE "account" (
|
||||||
|
"id" text PRIMARY KEY NOT NULL,
|
||||||
|
"account_id" text NOT NULL,
|
||||||
|
"provider_id" text NOT NULL,
|
||||||
|
"user_id" text NOT NULL,
|
||||||
|
"access_token" text,
|
||||||
|
"refresh_token" text,
|
||||||
|
"id_token" text,
|
||||||
|
"access_token_expires_at" timestamp,
|
||||||
|
"refresh_token_expires_at" timestamp,
|
||||||
|
"scope" text,
|
||||||
|
"password" text,
|
||||||
|
"is2FAEnabled" boolean DEFAULT false NOT NULL,
|
||||||
|
"created_at" timestamp NOT NULL,
|
||||||
|
"updated_at" timestamp NOT NULL,
|
||||||
|
"resetPasswordToken" text,
|
||||||
|
"resetPasswordExpiresAt" text,
|
||||||
|
"confirmationToken" text,
|
||||||
|
"confirmationExpiresAt" text
|
||||||
|
);
|
||||||
|
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "verification" (
|
||||||
|
"id" text PRIMARY KEY NOT NULL,
|
||||||
|
"identifier" text NOT NULL,
|
||||||
|
"value" text NOT NULL,
|
||||||
|
"expires_at" timestamp NOT NULL,
|
||||||
|
"created_at" timestamp,
|
||||||
|
"updated_at" timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Primero eliminar las restricciones NOT NULL y foreign keys
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "adminId" DROP NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "authId" DROP NOT NULL;
|
||||||
|
|
||||||
|
ALTER TABLE "user" DROP CONSTRAINT IF EXISTS "user_adminId_admin_adminId_fk";
|
||||||
|
ALTER TABLE "user" DROP CONSTRAINT IF EXISTS "user_authId_auth_id_fk";
|
||||||
|
ALTER TABLE "admin" DROP CONSTRAINT IF EXISTS "admin_authId_auth_id_fk";
|
||||||
|
ALTER TABLE "project" DROP CONSTRAINT IF EXISTS "project_adminId_admin_adminId_fk";
|
||||||
|
ALTER TABLE "destination" DROP CONSTRAINT IF EXISTS "destination_adminId_admin_adminId_fk";
|
||||||
|
ALTER TABLE "certificate" DROP CONSTRAINT IF EXISTS "certificate_adminId_admin_adminId_fk";
|
||||||
|
ALTER TABLE "session" DROP CONSTRAINT IF EXISTS "session_user_id_auth_id_fk";
|
||||||
|
ALTER TABLE "registry" DROP CONSTRAINT IF EXISTS "registry_adminId_admin_adminId_fk";
|
||||||
|
ALTER TABLE "notification" DROP CONSTRAINT IF EXISTS "notification_adminId_admin_adminId_fk";
|
||||||
|
ALTER TABLE "ssh-key" DROP CONSTRAINT IF EXISTS "ssh-key_adminId_admin_adminId_fk";
|
||||||
|
ALTER TABLE "git_provider" DROP CONSTRAINT IF EXISTS "git_provider_adminId_admin_adminId_fk";
|
||||||
|
ALTER TABLE "server" DROP CONSTRAINT IF EXISTS "server_adminId_admin_adminId_fk";
|
||||||
|
|
||||||
|
-- Luego renombrar las columnas
|
||||||
|
ALTER TABLE "user" RENAME COLUMN "userId" TO "id";
|
||||||
|
ALTER TABLE "project" RENAME COLUMN "adminId" TO "userId";
|
||||||
|
ALTER TABLE "destination" RENAME COLUMN "adminId" TO "userId";
|
||||||
|
ALTER TABLE "certificate" RENAME COLUMN "adminId" TO "userId";
|
||||||
|
ALTER TABLE "registry" RENAME COLUMN "adminId" TO "userId";
|
||||||
|
ALTER TABLE "notification" RENAME COLUMN "adminId" TO "userId";
|
||||||
|
ALTER TABLE "ssh-key" RENAME COLUMN "adminId" TO "userId";
|
||||||
|
ALTER TABLE "git_provider" RENAME COLUMN "adminId" TO "userId";
|
||||||
|
ALTER TABLE "server" RENAME COLUMN "adminId" TO "userId";
|
||||||
|
|
||||||
|
-- Primero agregar todas las columnas sin restricciones
|
||||||
|
ALTER TABLE "user" ADD COLUMN "name" text;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "email" text;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "email_verified" boolean;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "image" text;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "role" text;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "banned" boolean;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "ban_reason" text;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "ban_expires" timestamp;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "updated_at" timestamp;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "serverIp" text;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "certificateType" "certificateType" DEFAULT 'none';
|
||||||
|
ALTER TABLE "user" ADD COLUMN "host" text;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "letsEncryptEmail" text;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "sshPrivateKey" text;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "enableDockerCleanup" boolean DEFAULT false;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "enableLogRotation" boolean DEFAULT false;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "enablePaidFeatures" boolean DEFAULT false;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "metricsConfig" jsonb DEFAULT '{"server":{"type":"Dokploy","refreshRate":60,"port":4500,"token":"","retentionDays":2,"cronJob":"","urlCallback":"","thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}';
|
||||||
|
ALTER TABLE "user" ADD COLUMN "cleanupCacheApplications" boolean DEFAULT false;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "cleanupCacheOnPreviews" boolean DEFAULT false;
|
||||||
|
ALTER TABLE "user" ADD COLUMN "cleanupCacheOnCompose" boolean DEFAULT false;
|
||||||
|
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "token" SET DEFAULT '';
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "expirationDate" SET DEFAULT CURRENT_TIMESTAMP + INTERVAL '1 year';
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "createdAt" SET DEFAULT to_char(CURRENT_TIMESTAMP, 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"');
|
||||||
|
|
||||||
|
--> statement-breakpoint
|
||||||
|
-- Luego actualizar los valores nulos
|
||||||
|
UPDATE "user" SET token = '' WHERE token IS NULL;
|
||||||
|
UPDATE "user" SET "expirationDate" = CURRENT_TIMESTAMP + INTERVAL '1 year' WHERE "expirationDate" IS NULL;
|
||||||
|
UPDATE "user" SET "createdAt" = to_char(CURRENT_TIMESTAMP, 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') WHERE "createdAt" IS NULL;
|
||||||
|
UPDATE "user" SET "name" = '' WHERE "name" IS NULL;
|
||||||
|
UPDATE "user" SET "email" = COALESCE("email", '') WHERE true;
|
||||||
|
UPDATE "user" SET "email_verified" = COALESCE("email_verified", false) WHERE true;
|
||||||
|
UPDATE "user" SET "role" = COALESCE("role", 'user') WHERE true;
|
||||||
|
UPDATE "user" SET "banned" = COALESCE("banned", false) WHERE true;
|
||||||
|
UPDATE "user" SET "updated_at" = COALESCE("updated_at", CURRENT_TIMESTAMP) WHERE true;
|
||||||
|
UPDATE "user" SET "certificateType" = COALESCE("certificateType", 'none') WHERE true;
|
||||||
|
UPDATE "user" SET "enableDockerCleanup" = COALESCE("enableDockerCleanup", false) WHERE true;
|
||||||
|
UPDATE "user" SET "enableLogRotation" = COALESCE("enableLogRotation", false) WHERE true;
|
||||||
|
UPDATE "user" SET "enablePaidFeatures" = COALESCE("enablePaidFeatures", false) WHERE true;
|
||||||
|
UPDATE "user" SET "metricsConfig" = COALESCE("metricsConfig", '{"server":{"type":"Dokploy","refreshRate":60,"port":4500,"token":"","retentionDays":2,"cronJob":"","urlCallback":"","thresholds":{"cpu":0,"memory":0}},"containers":{"refreshRate":60,"services":{"include":[],"exclude":[]}}}') WHERE true;
|
||||||
|
UPDATE "user" SET "cleanupCacheApplications" = COALESCE("cleanupCacheApplications", false) WHERE true;
|
||||||
|
UPDATE "user" SET "cleanupCacheOnPreviews" = COALESCE("cleanupCacheOnPreviews", false) WHERE true;
|
||||||
|
UPDATE "user" SET "cleanupCacheOnCompose" = COALESCE("cleanupCacheOnCompose", false) WHERE true;
|
||||||
|
--> statement-breakpoint
|
||||||
|
|
||||||
|
-- Migrar datos de auth a user
|
||||||
|
INSERT INTO "user" (
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
email_verified,
|
||||||
|
image,
|
||||||
|
role,
|
||||||
|
updated_at
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
'' as name,
|
||||||
|
email,
|
||||||
|
true as email_verified,
|
||||||
|
image,
|
||||||
|
CASE
|
||||||
|
WHEN rol = 'admin' THEN 'admin'
|
||||||
|
ELSE 'user'
|
||||||
|
END as role,
|
||||||
|
CAST("createdAt" AS timestamp) as updated_at
|
||||||
|
FROM "auth";
|
||||||
|
|
||||||
|
-- Migrar datos de admin a user
|
||||||
|
UPDATE "user" u
|
||||||
|
SET
|
||||||
|
"serverIp" = a."serverIp",
|
||||||
|
"certificateType" = a."certificateType",
|
||||||
|
"host" = a."host",
|
||||||
|
"letsEncryptEmail" = a."letsEncryptEmail",
|
||||||
|
"sshPrivateKey" = a."sshPrivateKey",
|
||||||
|
"enableDockerCleanup" = a."enableDockerCleanup",
|
||||||
|
"enableLogRotation" = a."enableLogRotation",
|
||||||
|
"enablePaidFeatures" = a."enablePaidFeatures",
|
||||||
|
"metricsConfig" = a."metricsConfig",
|
||||||
|
"cleanupCacheApplications" = a."cleanupCacheApplications",
|
||||||
|
"cleanupCacheOnPreviews" = a."cleanupCacheOnPreviews",
|
||||||
|
"cleanupCacheOnCompose" = a."cleanupCacheOnCompose"
|
||||||
|
FROM "admin" a
|
||||||
|
WHERE u.id = a."authId";
|
||||||
|
|
||||||
|
-- Actualizar referencias en las tablas relacionadas
|
||||||
|
UPDATE "project" p
|
||||||
|
SET "userId" = a."authId"
|
||||||
|
FROM "admin" a
|
||||||
|
WHERE p."userId" = a."adminId";
|
||||||
|
|
||||||
|
UPDATE "destination" d
|
||||||
|
SET "userId" = a."authId"
|
||||||
|
FROM "admin" a
|
||||||
|
WHERE d."userId" = a."adminId";
|
||||||
|
|
||||||
|
UPDATE "certificate" c
|
||||||
|
SET "userId" = a."authId"
|
||||||
|
FROM "admin" a
|
||||||
|
WHERE c."userId" = a."adminId";
|
||||||
|
|
||||||
|
UPDATE "registry" r
|
||||||
|
SET "userId" = a."authId"
|
||||||
|
FROM "admin" a
|
||||||
|
WHERE r."userId" = a."adminId";
|
||||||
|
|
||||||
|
UPDATE "notification" n
|
||||||
|
SET "userId" = a."authId"
|
||||||
|
FROM "admin" a
|
||||||
|
WHERE n."userId" = a."adminId";
|
||||||
|
|
||||||
|
UPDATE "ssh-key" s
|
||||||
|
SET "userId" = a."authId"
|
||||||
|
FROM "admin" a
|
||||||
|
WHERE s."userId" = a."adminId";
|
||||||
|
|
||||||
|
UPDATE "git_provider" g
|
||||||
|
SET "userId" = a."authId"
|
||||||
|
FROM "admin" a
|
||||||
|
WHERE g."userId" = a."adminId";
|
||||||
|
|
||||||
|
UPDATE "server" s
|
||||||
|
SET "userId" = a."authId"
|
||||||
|
FROM "admin" a
|
||||||
|
WHERE s."userId" = a."adminId";
|
||||||
|
|
||||||
|
-- Ahora agregar las restricciones NOT NULL después de migrar los datos
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "name" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "email" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "email_verified" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "updated_at" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "certificateType" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "enableDockerCleanup" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "enableLogRotation" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "enablePaidFeatures" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "metricsConfig" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "cleanupCacheApplications" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "cleanupCacheOnPreviews" SET NOT NULL;
|
||||||
|
ALTER TABLE "user" ALTER COLUMN "cleanupCacheOnCompose" SET NOT NULL;
|
||||||
|
|
||||||
|
-- Modificar session
|
||||||
|
ALTER TABLE "session" ALTER COLUMN "expires_at" SET DATA TYPE timestamp;
|
||||||
|
ALTER TABLE "session" ADD COLUMN "token" text;
|
||||||
|
ALTER TABLE "session" ADD COLUMN "created_at" timestamp;
|
||||||
|
ALTER TABLE "session" ADD COLUMN "updated_at" timestamp;
|
||||||
|
ALTER TABLE "session" ADD COLUMN "ip_address" text;
|
||||||
|
ALTER TABLE "session" ADD COLUMN "user_agent" text;
|
||||||
|
ALTER TABLE "session" ADD COLUMN "impersonated_by" text;
|
||||||
|
|
||||||
|
-- Agregar nuevas restricciones después de migrar todos los datos
|
||||||
|
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
|
||||||
|
ALTER TABLE "project" ADD CONSTRAINT "project_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "destination" ADD CONSTRAINT "destination_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "certificate" ADD CONSTRAINT "certificate_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
|
||||||
|
ALTER TABLE "registry" ADD CONSTRAINT "registry_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "notification" ADD CONSTRAINT "notification_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "ssh-key" ADD CONSTRAINT "ssh-key_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "git_provider" ADD CONSTRAINT "git_provider_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
ALTER TABLE "server" ADD CONSTRAINT "server_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
|
||||||
|
-- Agregar restricciones únicas
|
||||||
|
ALTER TABLE "user" ADD CONSTRAINT "user_email_unique" UNIQUE("email");
|
||||||
|
ALTER TABLE "session" ADD CONSTRAINT "session_token_unique" UNIQUE("token");
|
||||||
|
|
||||||
|
-- Eliminar columnas antiguas
|
||||||
|
ALTER TABLE "user" DROP COLUMN IF EXISTS "adminId";
|
||||||
|
ALTER TABLE "user" DROP COLUMN IF EXISTS "authId";
|
||||||
|
|
||||||
|
-- Eliminar columnas de admin
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "adminId";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "serverIp";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "certificateType";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "host";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "letsEncryptEmail";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "sshPrivateKey";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "enableDockerCleanup";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "enableLogRotation";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "authId";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "createdAt";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "stripeCustomerId";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "stripeSubscriptionId";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "serversQuantity";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "enablePaidFeatures";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "metricsConfig";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "cleanupCacheApplications";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "cleanupCacheOnPreviews";
|
||||||
|
ALTER TABLE "admin" DROP COLUMN IF EXISTS "cleanupCacheOnCompose";
|
||||||
|
|
||||||
|
-- Eliminar tablas antiguas
|
||||||
|
DROP TABLE IF EXISTS "auth" CASCADE;
|
||||||
|
DROP TABLE IF EXISTS "admin" CASCADE;
|
||||||
4686
apps/dokploy/drizzle/meta/0066_snapshot.json
Normal file
4686
apps/dokploy/drizzle/meta/0066_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -463,6 +463,13 @@
|
|||||||
"when": 1739087857244,
|
"when": 1739087857244,
|
||||||
"tag": "0065_daily_zaladane",
|
"tag": "0065_daily_zaladane",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 66,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1739142819089,
|
||||||
|
"tag": "0066_broad_marrow",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
4
apps/dokploy/lib/auth.ts
Normal file
4
apps/dokploy/lib/auth.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { createAuthClient } from "better-auth/react";
|
||||||
|
export const authClient = createAuthClient({
|
||||||
|
baseURL: "http://localhost:3000", // the base url of your auth server
|
||||||
|
});
|
||||||
@@ -35,6 +35,7 @@
|
|||||||
"test": "vitest --config __test__/vitest.config.ts"
|
"test": "vitest --config __test__/vitest.config.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"better-auth":"1.1.16",
|
||||||
"bl": "6.0.11",
|
"bl": "6.0.11",
|
||||||
"rotating-file-stream": "3.2.3",
|
"rotating-file-stream": "3.2.3",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
|
|||||||
7
apps/dokploy/pages/api/auth/[...all].ts
Normal file
7
apps/dokploy/pages/api/auth/[...all].ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { auth } from "@dokploy/server/index";
|
||||||
|
import { toNodeHandler } from "better-auth/node";
|
||||||
|
|
||||||
|
// Disallow body parsing, we will parse it manually
|
||||||
|
export const config = { api: { bodyParser: false } };
|
||||||
|
|
||||||
|
export default toNodeHandler(auth.handler);
|
||||||
@@ -18,224 +18,224 @@ export default async function handler(
|
|||||||
req: NextApiRequest,
|
req: NextApiRequest,
|
||||||
res: NextApiResponse,
|
res: NextApiResponse,
|
||||||
) {
|
) {
|
||||||
if (!endpointSecret) {
|
// if (!endpointSecret) {
|
||||||
return res.status(400).send("Webhook Error: Missing Stripe Secret Key");
|
// return res.status(400).send("Webhook Error: Missing Stripe Secret Key");
|
||||||
}
|
// }
|
||||||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
|
// const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
|
||||||
apiVersion: "2024-09-30.acacia",
|
// apiVersion: "2024-09-30.acacia",
|
||||||
maxNetworkRetries: 3,
|
// maxNetworkRetries: 3,
|
||||||
});
|
// });
|
||||||
|
|
||||||
const buf = await buffer(req);
|
// const buf = await buffer(req);
|
||||||
const sig = req.headers["stripe-signature"] as string;
|
// const sig = req.headers["stripe-signature"] as string;
|
||||||
|
|
||||||
let event: Stripe.Event;
|
// let event: Stripe.Event;
|
||||||
|
|
||||||
try {
|
// try {
|
||||||
event = stripe.webhooks.constructEvent(buf, sig, endpointSecret);
|
// event = stripe.webhooks.constructEvent(buf, sig, endpointSecret);
|
||||||
} catch (err) {
|
// } catch (err) {
|
||||||
console.error(
|
// console.error(
|
||||||
"Webhook signature verification failed.",
|
// "Webhook signature verification failed.",
|
||||||
err instanceof Error ? err.message : err,
|
// err instanceof Error ? err.message : err,
|
||||||
);
|
// );
|
||||||
return res.status(400).send("Webhook Error: ");
|
// return res.status(400).send("Webhook Error: ");
|
||||||
}
|
// }
|
||||||
|
|
||||||
const webhooksAllowed = [
|
// const webhooksAllowed = [
|
||||||
"customer.subscription.created",
|
// "customer.subscription.created",
|
||||||
"customer.subscription.deleted",
|
// "customer.subscription.deleted",
|
||||||
"customer.subscription.updated",
|
// "customer.subscription.updated",
|
||||||
"invoice.payment_succeeded",
|
// "invoice.payment_succeeded",
|
||||||
"invoice.payment_failed",
|
// "invoice.payment_failed",
|
||||||
"customer.deleted",
|
// "customer.deleted",
|
||||||
"checkout.session.completed",
|
// "checkout.session.completed",
|
||||||
];
|
// ];
|
||||||
|
|
||||||
if (!webhooksAllowed.includes(event.type)) {
|
// if (!webhooksAllowed.includes(event.type)) {
|
||||||
return res.status(400).send("Webhook Error: Invalid Event Type");
|
// return res.status(400).send("Webhook Error: Invalid Event Type");
|
||||||
}
|
// }
|
||||||
|
|
||||||
switch (event.type) {
|
// switch (event.type) {
|
||||||
case "checkout.session.completed": {
|
// case "checkout.session.completed": {
|
||||||
const session = event.data.object as Stripe.Checkout.Session;
|
// const session = event.data.object as Stripe.Checkout.Session;
|
||||||
const adminId = session?.metadata?.adminId as string;
|
// const adminId = session?.metadata?.adminId as string;
|
||||||
|
|
||||||
const subscription = await stripe.subscriptions.retrieve(
|
// const subscription = await stripe.subscriptions.retrieve(
|
||||||
session.subscription as string,
|
// session.subscription as string,
|
||||||
);
|
// );
|
||||||
await db
|
// await db
|
||||||
.update(admins)
|
// .update(admins)
|
||||||
.set({
|
// .set({
|
||||||
stripeCustomerId: session.customer as string,
|
// stripeCustomerId: session.customer as string,
|
||||||
stripeSubscriptionId: session.subscription as string,
|
// stripeSubscriptionId: session.subscription as string,
|
||||||
serversQuantity: subscription?.items?.data?.[0]?.quantity ?? 0,
|
// serversQuantity: subscription?.items?.data?.[0]?.quantity ?? 0,
|
||||||
})
|
// })
|
||||||
.where(eq(admins.adminId, adminId))
|
// .where(eq(admins.adminId, adminId))
|
||||||
.returning();
|
// .returning();
|
||||||
|
|
||||||
const admin = await findAdminById(adminId);
|
// const admin = await findAdminById(adminId);
|
||||||
if (!admin) {
|
// if (!admin) {
|
||||||
return res.status(400).send("Webhook Error: Admin not found");
|
// return res.status(400).send("Webhook Error: Admin not found");
|
||||||
}
|
// }
|
||||||
const newServersQuantity = admin.serversQuantity;
|
// const newServersQuantity = admin.serversQuantity;
|
||||||
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
|
// await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case "customer.subscription.created": {
|
// case "customer.subscription.created": {
|
||||||
const newSubscription = event.data.object as Stripe.Subscription;
|
// const newSubscription = event.data.object as Stripe.Subscription;
|
||||||
|
|
||||||
await db
|
// await db
|
||||||
.update(admins)
|
// .update(admins)
|
||||||
.set({
|
// .set({
|
||||||
stripeSubscriptionId: newSubscription.id,
|
// stripeSubscriptionId: newSubscription.id,
|
||||||
stripeCustomerId: newSubscription.customer as string,
|
// stripeCustomerId: newSubscription.customer as string,
|
||||||
})
|
// })
|
||||||
.where(eq(admins.stripeCustomerId, newSubscription.customer as string))
|
// .where(eq(admins.stripeCustomerId, newSubscription.customer as string))
|
||||||
.returning();
|
// .returning();
|
||||||
|
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case "customer.subscription.deleted": {
|
// case "customer.subscription.deleted": {
|
||||||
const newSubscription = event.data.object as Stripe.Subscription;
|
// const newSubscription = event.data.object as Stripe.Subscription;
|
||||||
|
|
||||||
await db
|
// await db
|
||||||
.update(admins)
|
// .update(admins)
|
||||||
.set({
|
// .set({
|
||||||
stripeSubscriptionId: null,
|
// stripeSubscriptionId: null,
|
||||||
serversQuantity: 0,
|
// serversQuantity: 0,
|
||||||
})
|
// })
|
||||||
.where(eq(admins.stripeCustomerId, newSubscription.customer as string));
|
// .where(eq(admins.stripeCustomerId, newSubscription.customer as string));
|
||||||
|
|
||||||
const admin = await findAdminByStripeCustomerId(
|
// const admin = await findAdminByStripeCustomerId(
|
||||||
newSubscription.customer as string,
|
// newSubscription.customer as string,
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (!admin) {
|
// if (!admin) {
|
||||||
return res.status(400).send("Webhook Error: Admin not found");
|
// return res.status(400).send("Webhook Error: Admin not found");
|
||||||
}
|
// }
|
||||||
|
|
||||||
await disableServers(admin.adminId);
|
// await disableServers(admin.adminId);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case "customer.subscription.updated": {
|
// case "customer.subscription.updated": {
|
||||||
const newSubscription = event.data.object as Stripe.Subscription;
|
// const newSubscription = event.data.object as Stripe.Subscription;
|
||||||
|
|
||||||
const admin = await findAdminByStripeCustomerId(
|
// const admin = await findAdminByStripeCustomerId(
|
||||||
newSubscription.customer as string,
|
// newSubscription.customer as string,
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (!admin) {
|
// if (!admin) {
|
||||||
return res.status(400).send("Webhook Error: Admin not found");
|
// return res.status(400).send("Webhook Error: Admin not found");
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (newSubscription.status === "active") {
|
// if (newSubscription.status === "active") {
|
||||||
await db
|
// await db
|
||||||
.update(admins)
|
// .update(admins)
|
||||||
.set({
|
// .set({
|
||||||
serversQuantity: newSubscription?.items?.data?.[0]?.quantity ?? 0,
|
// serversQuantity: newSubscription?.items?.data?.[0]?.quantity ?? 0,
|
||||||
})
|
// })
|
||||||
.where(
|
// .where(
|
||||||
eq(admins.stripeCustomerId, newSubscription.customer as string),
|
// eq(admins.stripeCustomerId, newSubscription.customer as string),
|
||||||
);
|
// );
|
||||||
|
|
||||||
const newServersQuantity = admin.serversQuantity;
|
// const newServersQuantity = admin.serversQuantity;
|
||||||
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
|
// await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
|
||||||
} else {
|
// } else {
|
||||||
await disableServers(admin.adminId);
|
// await disableServers(admin.adminId);
|
||||||
await db
|
// await db
|
||||||
.update(admins)
|
// .update(admins)
|
||||||
.set({ serversQuantity: 0 })
|
// .set({ serversQuantity: 0 })
|
||||||
.where(
|
// .where(
|
||||||
eq(admins.stripeCustomerId, newSubscription.customer as string),
|
// eq(admins.stripeCustomerId, newSubscription.customer as string),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case "invoice.payment_succeeded": {
|
// case "invoice.payment_succeeded": {
|
||||||
const newInvoice = event.data.object as Stripe.Invoice;
|
// const newInvoice = event.data.object as Stripe.Invoice;
|
||||||
|
|
||||||
const suscription = await stripe.subscriptions.retrieve(
|
// const suscription = await stripe.subscriptions.retrieve(
|
||||||
newInvoice.subscription as string,
|
// newInvoice.subscription as string,
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (suscription.status !== "active") {
|
// if (suscription.status !== "active") {
|
||||||
console.log(
|
// console.log(
|
||||||
`Skipping invoice.payment_succeeded for subscription ${suscription.id} with status ${suscription.status}`,
|
// `Skipping invoice.payment_succeeded for subscription ${suscription.id} with status ${suscription.status}`,
|
||||||
);
|
// );
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
await db
|
// await db
|
||||||
.update(admins)
|
// .update(admins)
|
||||||
.set({
|
// .set({
|
||||||
serversQuantity: suscription?.items?.data?.[0]?.quantity ?? 0,
|
// serversQuantity: suscription?.items?.data?.[0]?.quantity ?? 0,
|
||||||
})
|
// })
|
||||||
.where(eq(admins.stripeCustomerId, suscription.customer as string));
|
// .where(eq(admins.stripeCustomerId, suscription.customer as string));
|
||||||
|
|
||||||
const admin = await findAdminByStripeCustomerId(
|
// const admin = await findAdminByStripeCustomerId(
|
||||||
suscription.customer as string,
|
// suscription.customer as string,
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (!admin) {
|
// if (!admin) {
|
||||||
return res.status(400).send("Webhook Error: Admin not found");
|
// return res.status(400).send("Webhook Error: Admin not found");
|
||||||
}
|
// }
|
||||||
const newServersQuantity = admin.serversQuantity;
|
// const newServersQuantity = admin.serversQuantity;
|
||||||
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
|
// await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case "invoice.payment_failed": {
|
// case "invoice.payment_failed": {
|
||||||
const newInvoice = event.data.object as Stripe.Invoice;
|
// const newInvoice = event.data.object as Stripe.Invoice;
|
||||||
|
|
||||||
const subscription = await stripe.subscriptions.retrieve(
|
// const subscription = await stripe.subscriptions.retrieve(
|
||||||
newInvoice.subscription as string,
|
// newInvoice.subscription as string,
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (subscription.status !== "active") {
|
// if (subscription.status !== "active") {
|
||||||
const admin = await findAdminByStripeCustomerId(
|
// const admin = await findAdminByStripeCustomerId(
|
||||||
newInvoice.customer as string,
|
// newInvoice.customer as string,
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (!admin) {
|
// if (!admin) {
|
||||||
return res.status(400).send("Webhook Error: Admin not found");
|
// return res.status(400).send("Webhook Error: Admin not found");
|
||||||
}
|
// }
|
||||||
await db
|
// await db
|
||||||
.update(admins)
|
// .update(admins)
|
||||||
.set({
|
// .set({
|
||||||
serversQuantity: 0,
|
// serversQuantity: 0,
|
||||||
})
|
// })
|
||||||
.where(eq(admins.stripeCustomerId, newInvoice.customer as string));
|
// .where(eq(admins.stripeCustomerId, newInvoice.customer as string));
|
||||||
|
|
||||||
await disableServers(admin.adminId);
|
// await disableServers(admin.adminId);
|
||||||
}
|
// }
|
||||||
|
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
case "customer.deleted": {
|
// case "customer.deleted": {
|
||||||
const customer = event.data.object as Stripe.Customer;
|
// const customer = event.data.object as Stripe.Customer;
|
||||||
|
|
||||||
const admin = await findAdminByStripeCustomerId(customer.id);
|
// const admin = await findAdminByStripeCustomerId(customer.id);
|
||||||
if (!admin) {
|
// if (!admin) {
|
||||||
return res.status(400).send("Webhook Error: Admin not found");
|
// return res.status(400).send("Webhook Error: Admin not found");
|
||||||
}
|
// }
|
||||||
|
|
||||||
await disableServers(admin.adminId);
|
// await disableServers(admin.adminId);
|
||||||
await db
|
// await db
|
||||||
.update(admins)
|
// .update(admins)
|
||||||
.set({
|
// .set({
|
||||||
stripeCustomerId: null,
|
// stripeCustomerId: null,
|
||||||
stripeSubscriptionId: null,
|
// stripeSubscriptionId: null,
|
||||||
serversQuantity: 0,
|
// serversQuantity: 0,
|
||||||
})
|
// })
|
||||||
.where(eq(admins.stripeCustomerId, customer.id));
|
// .where(eq(admins.stripeCustomerId, customer.id));
|
||||||
|
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
default:
|
// default:
|
||||||
console.log(`Unhandled event type: ${event.type}`);
|
// console.log(`Unhandled event type: ${event.type}`);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return res.status(200).json({ received: true });
|
return res.status(200).json({ received: true });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,9 +70,9 @@ import type {
|
|||||||
} from "next";
|
} from "next";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { useMemo, useState, type ReactElement } from "react";
|
import { type ReactElement, useMemo, useState } from "react";
|
||||||
import superjson from "superjson";
|
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
import superjson from "superjson";
|
||||||
|
|
||||||
export type Services = {
|
export type Services = {
|
||||||
appName: string;
|
appName: string;
|
||||||
|
|||||||
@@ -201,51 +201,51 @@ Home.getLayout = (page: ReactElement) => {
|
|||||||
return <OnboardingLayout>{page}</OnboardingLayout>;
|
return <OnboardingLayout>{page}</OnboardingLayout>;
|
||||||
};
|
};
|
||||||
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||||
if (IS_CLOUD) {
|
// if (IS_CLOUD) {
|
||||||
try {
|
// try {
|
||||||
const { user } = await validateRequest(context.req, context.res);
|
// const { user } = await validateRequest(context.req, context.res);
|
||||||
|
|
||||||
if (user) {
|
// if (user) {
|
||||||
return {
|
// return {
|
||||||
redirect: {
|
// redirect: {
|
||||||
permanent: true,
|
// permanent: true,
|
||||||
destination: "/dashboard/projects",
|
// destination: "/dashboard/projects",
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
} catch (error) {}
|
// } catch (error) {}
|
||||||
|
|
||||||
return {
|
// return {
|
||||||
props: {
|
// props: {
|
||||||
IS_CLOUD: IS_CLOUD,
|
// IS_CLOUD: IS_CLOUD,
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
const hasAdmin = await isAdminPresent();
|
// const hasAdmin = await isAdminPresent();
|
||||||
|
|
||||||
if (!hasAdmin) {
|
// if (!hasAdmin) {
|
||||||
return {
|
// return {
|
||||||
redirect: {
|
// redirect: {
|
||||||
permanent: true,
|
// permanent: true,
|
||||||
destination: "/register",
|
// destination: "/register",
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
|
||||||
const { user } = await validateRequest(context.req, context.res);
|
// const { user } = await validateRequest(context.req, context.res);
|
||||||
|
|
||||||
if (user) {
|
// if (user) {
|
||||||
return {
|
// return {
|
||||||
redirect: {
|
// redirect: {
|
||||||
permanent: true,
|
// permanent: true,
|
||||||
destination: "/dashboard/projects",
|
// destination: "/dashboard/projects",
|
||||||
},
|
// },
|
||||||
};
|
// };
|
||||||
}
|
// }
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
hasAdmin,
|
// hasAdmin,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,14 +34,14 @@ void app.prepare().then(async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// WEBSOCKET
|
// WEBSOCKET
|
||||||
setupDrawerLogsWebSocketServer(server);
|
// setupDrawerLogsWebSocketServer(server);
|
||||||
setupDeploymentLogsWebSocketServer(server);
|
// setupDeploymentLogsWebSocketServer(server);
|
||||||
setupDockerContainerLogsWebSocketServer(server);
|
// setupDockerContainerLogsWebSocketServer(server);
|
||||||
setupDockerContainerTerminalWebSocketServer(server);
|
// setupDockerContainerTerminalWebSocketServer(server);
|
||||||
setupTerminalWebSocketServer(server);
|
// setupTerminalWebSocketServer(server);
|
||||||
if (!IS_CLOUD) {
|
// if (!IS_CLOUD) {
|
||||||
setupDockerStatsMonitoringSocketServer(server);
|
// setupDockerStatsMonitoringSocketServer(server);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "production" && !IS_CLOUD) {
|
if (process.env.NODE_ENV === "production" && !IS_CLOUD) {
|
||||||
setupDirectories();
|
setupDirectories();
|
||||||
|
|||||||
62
packages/server/auth-schema.ts
Normal file
62
packages/server/auth-schema.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
import {
|
||||||
|
pgTable,
|
||||||
|
text,
|
||||||
|
integer,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
|
||||||
|
export const user = pgTable("user", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
email: text("email").notNull().unique(),
|
||||||
|
emailVerified: boolean("email_verified").notNull(),
|
||||||
|
image: text("image"),
|
||||||
|
createdAt: timestamp("created_at").notNull(),
|
||||||
|
updatedAt: timestamp("updated_at").notNull(),
|
||||||
|
role: text("role"),
|
||||||
|
banned: boolean("banned"),
|
||||||
|
banReason: text("ban_reason"),
|
||||||
|
banExpires: timestamp("ban_expires"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const session = pgTable("session", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
expiresAt: timestamp("expires_at").notNull(),
|
||||||
|
token: text("token").notNull().unique(),
|
||||||
|
createdAt: timestamp("created_at").notNull(),
|
||||||
|
updatedAt: timestamp("updated_at").notNull(),
|
||||||
|
ipAddress: text("ip_address"),
|
||||||
|
userAgent: text("user_agent"),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => user.id),
|
||||||
|
impersonatedBy: text("impersonated_by"),
|
||||||
|
});
|
||||||
|
|
||||||
|
// export const account = pgTable("account", {
|
||||||
|
// id: text("id").primaryKey(),
|
||||||
|
// accountId: text("account_id").notNull(),
|
||||||
|
// providerId: text("provider_id").notNull(),
|
||||||
|
// userId: text("user_id")
|
||||||
|
// .notNull()
|
||||||
|
// .references(() => user.id),
|
||||||
|
// accessToken: text("access_token"),
|
||||||
|
// refreshToken: text("refresh_token"),
|
||||||
|
// idToken: text("id_token"),
|
||||||
|
// accessTokenExpiresAt: timestamp("access_token_expires_at"),
|
||||||
|
// refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
|
||||||
|
// scope: text("scope"),
|
||||||
|
// password: text("password"),
|
||||||
|
// createdAt: timestamp("created_at").notNull(),
|
||||||
|
// updatedAt: timestamp("updated_at").notNull(),
|
||||||
|
// });
|
||||||
|
|
||||||
|
// export const verification = pgTable("verification", {
|
||||||
|
// id: text("id").primaryKey(),
|
||||||
|
// identifier: text("identifier").notNull(),
|
||||||
|
// value: text("value").notNull(),
|
||||||
|
// expiresAt: timestamp("expires_at").notNull(),
|
||||||
|
// createdAt: timestamp("created_at"),
|
||||||
|
// updatedAt: timestamp("updated_at"),
|
||||||
|
// });
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
"typecheck": "tsc --noEmit"
|
"typecheck": "tsc --noEmit"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"better-auth":"1.1.16",
|
||||||
"rotating-file-stream": "3.2.3",
|
"rotating-file-stream": "3.2.3",
|
||||||
"@faker-js/faker": "^8.4.1",
|
"@faker-js/faker": "^8.4.1",
|
||||||
"@lucia-auth/adapter-drizzle": "1.0.7",
|
"@lucia-auth/adapter-drizzle": "1.0.7",
|
||||||
|
|||||||
34
packages/server/src/db/schema/account.ts
Normal file
34
packages/server/src/db/schema/account.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { boolean, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||||
|
import { users } from "./user";
|
||||||
|
|
||||||
|
export const account = pgTable("account", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
accountId: text("account_id").notNull(),
|
||||||
|
providerId: text("provider_id").notNull(),
|
||||||
|
userId: text("user_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => users.id),
|
||||||
|
accessToken: text("access_token"),
|
||||||
|
refreshToken: text("refresh_token"),
|
||||||
|
idToken: text("id_token"),
|
||||||
|
accessTokenExpiresAt: timestamp("access_token_expires_at"),
|
||||||
|
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
|
||||||
|
scope: text("scope"),
|
||||||
|
password: text("password"),
|
||||||
|
is2FAEnabled: boolean("is2FAEnabled").notNull().default(false),
|
||||||
|
createdAt: timestamp("created_at").notNull(),
|
||||||
|
updatedAt: timestamp("updated_at").notNull(),
|
||||||
|
resetPasswordToken: text("resetPasswordToken"),
|
||||||
|
resetPasswordExpiresAt: text("resetPasswordExpiresAt"),
|
||||||
|
confirmationToken: text("confirmationToken"),
|
||||||
|
confirmationExpiresAt: text("confirmationExpiresAt"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const verification = pgTable("verification", {
|
||||||
|
id: text("id").primaryKey(),
|
||||||
|
identifier: text("identifier").notNull(),
|
||||||
|
value: text("value").notNull(),
|
||||||
|
expiresAt: timestamp("expires_at").notNull(),
|
||||||
|
createdAt: timestamp("created_at"),
|
||||||
|
updatedAt: timestamp("updated_at"),
|
||||||
|
});
|
||||||
@@ -18,128 +18,127 @@ import { sshKeys } from "./ssh-key";
|
|||||||
import { users } from "./user";
|
import { users } from "./user";
|
||||||
|
|
||||||
export const admins = pgTable("admin", {
|
export const admins = pgTable("admin", {
|
||||||
adminId: text("adminId")
|
// adminId: text("adminId")
|
||||||
.notNull()
|
// .notNull()
|
||||||
.primaryKey()
|
// .primaryKey()
|
||||||
.$defaultFn(() => nanoid()),
|
// .$defaultFn(() => nanoid()),
|
||||||
serverIp: text("serverIp"),
|
// serverIp: text("serverIp"),
|
||||||
certificateType: certificateType("certificateType").notNull().default("none"),
|
// certificateType: certificateType("certificateType").notNull().default("none"),
|
||||||
host: text("host"),
|
// host: text("host"),
|
||||||
letsEncryptEmail: text("letsEncryptEmail"),
|
// letsEncryptEmail: text("letsEncryptEmail"),
|
||||||
sshPrivateKey: text("sshPrivateKey"),
|
// sshPrivateKey: text("sshPrivateKey"),
|
||||||
enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false),
|
// enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false),
|
||||||
enableLogRotation: boolean("enableLogRotation").notNull().default(false),
|
// enableLogRotation: boolean("enableLogRotation").notNull().default(false),
|
||||||
authId: text("authId")
|
// authId: text("authId")
|
||||||
.notNull()
|
// .notNull()
|
||||||
.references(() => auth.id, { onDelete: "cascade" }),
|
// .references(() => auth.id, { onDelete: "cascade" }),
|
||||||
createdAt: text("createdAt")
|
// createdAt: text("createdAt")
|
||||||
.notNull()
|
// .notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
// .$defaultFn(() => new Date().toISOString()),
|
||||||
stripeCustomerId: text("stripeCustomerId"),
|
// stripeCustomerId: text("stripeCustomerId"),
|
||||||
stripeSubscriptionId: text("stripeSubscriptionId"),
|
// stripeSubscriptionId: text("stripeSubscriptionId"),
|
||||||
serversQuantity: integer("serversQuantity").notNull().default(0),
|
// serversQuantity: integer("serversQuantity").notNull().default(0),
|
||||||
|
// // Metrics
|
||||||
// Metrics
|
// enablePaidFeatures: boolean("enablePaidFeatures").notNull().default(false),
|
||||||
enablePaidFeatures: boolean("enablePaidFeatures").notNull().default(false),
|
// metricsConfig: jsonb("metricsConfig")
|
||||||
metricsConfig: jsonb("metricsConfig")
|
// .$type<{
|
||||||
.$type<{
|
// server: {
|
||||||
server: {
|
// type: "Dokploy" | "Remote";
|
||||||
type: "Dokploy" | "Remote";
|
// refreshRate: number;
|
||||||
refreshRate: number;
|
// port: number;
|
||||||
port: number;
|
// token: string;
|
||||||
token: string;
|
// urlCallback: string;
|
||||||
urlCallback: string;
|
// retentionDays: number;
|
||||||
retentionDays: number;
|
// cronJob: string;
|
||||||
cronJob: string;
|
// thresholds: {
|
||||||
thresholds: {
|
// cpu: number;
|
||||||
cpu: number;
|
// memory: number;
|
||||||
memory: number;
|
// };
|
||||||
};
|
// };
|
||||||
};
|
// containers: {
|
||||||
containers: {
|
// refreshRate: number;
|
||||||
refreshRate: number;
|
// services: {
|
||||||
services: {
|
// include: string[];
|
||||||
include: string[];
|
// exclude: string[];
|
||||||
exclude: string[];
|
// };
|
||||||
};
|
// };
|
||||||
};
|
// }>()
|
||||||
}>()
|
// .notNull()
|
||||||
.notNull()
|
// .default({
|
||||||
.default({
|
// server: {
|
||||||
server: {
|
// type: "Dokploy",
|
||||||
type: "Dokploy",
|
// refreshRate: 60,
|
||||||
refreshRate: 60,
|
// port: 4500,
|
||||||
port: 4500,
|
// token: "",
|
||||||
token: "",
|
// retentionDays: 2,
|
||||||
retentionDays: 2,
|
// cronJob: "",
|
||||||
cronJob: "",
|
// urlCallback: "",
|
||||||
urlCallback: "",
|
// thresholds: {
|
||||||
thresholds: {
|
// cpu: 0,
|
||||||
cpu: 0,
|
// memory: 0,
|
||||||
memory: 0,
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// containers: {
|
||||||
containers: {
|
// refreshRate: 60,
|
||||||
refreshRate: 60,
|
// services: {
|
||||||
services: {
|
// include: [],
|
||||||
include: [],
|
// exclude: [],
|
||||||
exclude: [],
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// }),
|
||||||
}),
|
// cleanupCacheApplications: boolean("cleanupCacheApplications")
|
||||||
cleanupCacheApplications: boolean("cleanupCacheApplications")
|
// .notNull()
|
||||||
.notNull()
|
// .default(false),
|
||||||
.default(false),
|
// cleanupCacheOnPreviews: boolean("cleanupCacheOnPreviews")
|
||||||
cleanupCacheOnPreviews: boolean("cleanupCacheOnPreviews")
|
// .notNull()
|
||||||
.notNull()
|
// .default(false),
|
||||||
.default(false),
|
// cleanupCacheOnCompose: boolean("cleanupCacheOnCompose")
|
||||||
cleanupCacheOnCompose: boolean("cleanupCacheOnCompose")
|
// .notNull()
|
||||||
.notNull()
|
// .default(false),
|
||||||
.default(false),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const adminsRelations = relations(admins, ({ one, many }) => ({
|
export const adminsRelations = relations(admins, ({ one, many }) => ({
|
||||||
auth: one(auth, {
|
// auth: one(auth, {
|
||||||
fields: [admins.authId],
|
// fields: [admins.authId],
|
||||||
references: [auth.id],
|
// references: [auth.id],
|
||||||
}),
|
// }),
|
||||||
users: many(users),
|
// users: many(users),
|
||||||
registry: many(registry),
|
// registry: many(registry),
|
||||||
sshKeys: many(sshKeys),
|
// sshKeys: many(sshKeys),
|
||||||
certificates: many(certificates),
|
// certificates: many(certificates),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const createSchema = createInsertSchema(admins, {
|
const createSchema = createInsertSchema(admins, {
|
||||||
adminId: z.string(),
|
// adminId: z.string(),
|
||||||
enableDockerCleanup: z.boolean().optional(),
|
// enableDockerCleanup: z.boolean().optional(),
|
||||||
sshPrivateKey: z.string().optional(),
|
// sshPrivateKey: z.string().optional(),
|
||||||
certificateType: z.enum(["letsencrypt", "none"]).default("none"),
|
// certificateType: z.enum(["letsencrypt", "none"]).default("none"),
|
||||||
serverIp: z.string().optional(),
|
// serverIp: z.string().optional(),
|
||||||
letsEncryptEmail: z.string().optional(),
|
// letsEncryptEmail: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const apiUpdateAdmin = createSchema.partial();
|
export const apiUpdateAdmin = createSchema.partial();
|
||||||
|
|
||||||
export const apiSaveSSHKey = createSchema
|
export const apiSaveSSHKey = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
sshPrivateKey: true,
|
// sshPrivateKey: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export const apiAssignDomain = createSchema
|
export const apiAssignDomain = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
host: true,
|
// host: true,
|
||||||
certificateType: true,
|
// certificateType: true,
|
||||||
letsEncryptEmail: true,
|
// letsEncryptEmail: true,
|
||||||
})
|
})
|
||||||
.required()
|
.required()
|
||||||
.partial({
|
.partial({
|
||||||
letsEncryptEmail: true,
|
// letsEncryptEmail: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const apiUpdateDockerCleanup = createSchema
|
export const apiUpdateDockerCleanup = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
enableDockerCleanup: true,
|
// enableDockerCleanup: true,
|
||||||
})
|
})
|
||||||
.required()
|
.required()
|
||||||
.extend({
|
.extend({
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { boolean, pgEnum, pgTable, text } from "drizzle-orm/pg-core";
|
|||||||
import { createInsertSchema } from "drizzle-zod";
|
import { createInsertSchema } from "drizzle-zod";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { admins } from "./admin";
|
// import { admins } from "./admin";
|
||||||
import { users } from "./user";
|
import { users } from "./user";
|
||||||
|
|
||||||
const randomImages = [
|
const randomImages = [
|
||||||
@@ -55,7 +55,7 @@ export const auth = pgTable("auth", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const authRelations = relations(auth, ({ many }) => ({
|
export const authRelations = relations(auth, ({ many }) => ({
|
||||||
admins: many(admins),
|
// admins: many(admins),
|
||||||
users: many(users),
|
users: many(users),
|
||||||
}));
|
}));
|
||||||
const createSchema = createInsertSchema(auth, {
|
const createSchema = createInsertSchema(auth, {
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import { boolean, pgTable, text } from "drizzle-orm/pg-core";
|
|||||||
import { createInsertSchema } from "drizzle-zod";
|
import { createInsertSchema } from "drizzle-zod";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { admins } from "./admin";
|
|
||||||
import { server } from "./server";
|
import { server } from "./server";
|
||||||
import { generateAppName } from "./utils";
|
import { generateAppName } from "./utils";
|
||||||
|
import { users } from "./user";
|
||||||
|
|
||||||
export const certificates = pgTable("certificate", {
|
export const certificates = pgTable("certificate", {
|
||||||
certificateId: text("certificateId")
|
certificateId: text("certificateId")
|
||||||
@@ -20,7 +20,7 @@ export const certificates = pgTable("certificate", {
|
|||||||
.$defaultFn(() => generateAppName("certificate"))
|
.$defaultFn(() => generateAppName("certificate"))
|
||||||
.unique(),
|
.unique(),
|
||||||
autoRenew: boolean("autoRenew"),
|
autoRenew: boolean("autoRenew"),
|
||||||
adminId: text("adminId").references(() => admins.adminId, {
|
userId: text("userId").references(() => users.id, {
|
||||||
onDelete: "cascade",
|
onDelete: "cascade",
|
||||||
}),
|
}),
|
||||||
serverId: text("serverId").references(() => server.serverId, {
|
serverId: text("serverId").references(() => server.serverId, {
|
||||||
@@ -35,9 +35,9 @@ export const certificatesRelations = relations(
|
|||||||
fields: [certificates.serverId],
|
fields: [certificates.serverId],
|
||||||
references: [server.serverId],
|
references: [server.serverId],
|
||||||
}),
|
}),
|
||||||
admin: one(admins, {
|
user: one(users, {
|
||||||
fields: [certificates.adminId],
|
fields: [certificates.userId],
|
||||||
references: [admins.adminId],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { nanoid } from "nanoid";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { admins } from "./admin";
|
import { admins } from "./admin";
|
||||||
import { backups } from "./backups";
|
import { backups } from "./backups";
|
||||||
|
import { users } from "./user";
|
||||||
|
|
||||||
export const destinations = pgTable("destination", {
|
export const destinations = pgTable("destination", {
|
||||||
destinationId: text("destinationId")
|
destinationId: text("destinationId")
|
||||||
@@ -19,18 +20,18 @@ export const destinations = pgTable("destination", {
|
|||||||
region: text("region").notNull(),
|
region: text("region").notNull(),
|
||||||
// maybe it can be null
|
// maybe it can be null
|
||||||
endpoint: text("endpoint").notNull(),
|
endpoint: text("endpoint").notNull(),
|
||||||
adminId: text("adminId")
|
userId: text("userId")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => admins.adminId, { onDelete: "cascade" }),
|
.references(() => users.id, { onDelete: "cascade" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const destinationsRelations = relations(
|
export const destinationsRelations = relations(
|
||||||
destinations,
|
destinations,
|
||||||
({ many, one }) => ({
|
({ many, one }) => ({
|
||||||
backups: many(backups),
|
backups: many(backups),
|
||||||
admin: one(admins, {
|
user: one(users, {
|
||||||
fields: [destinations.adminId],
|
fields: [destinations.userId],
|
||||||
references: [admins.adminId],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { admins } from "./admin";
|
|||||||
import { bitbucket } from "./bitbucket";
|
import { bitbucket } from "./bitbucket";
|
||||||
import { github } from "./github";
|
import { github } from "./github";
|
||||||
import { gitlab } from "./gitlab";
|
import { gitlab } from "./gitlab";
|
||||||
|
import { users } from "./user";
|
||||||
|
|
||||||
export const gitProviderType = pgEnum("gitProviderType", [
|
export const gitProviderType = pgEnum("gitProviderType", [
|
||||||
"github",
|
"github",
|
||||||
@@ -24,7 +25,7 @@ export const gitProvider = pgTable("git_provider", {
|
|||||||
createdAt: text("createdAt")
|
createdAt: text("createdAt")
|
||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
adminId: text("adminId").references(() => admins.adminId, {
|
userId: text("userId").references(() => users.id, {
|
||||||
onDelete: "cascade",
|
onDelete: "cascade",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -42,9 +43,9 @@ export const gitProviderRelations = relations(gitProvider, ({ one, many }) => ({
|
|||||||
fields: [gitProvider.gitProviderId],
|
fields: [gitProvider.gitProviderId],
|
||||||
references: [bitbucket.gitProviderId],
|
references: [bitbucket.gitProviderId],
|
||||||
}),
|
}),
|
||||||
admin: one(admins, {
|
user: one(users, {
|
||||||
fields: [gitProvider.adminId],
|
fields: [gitProvider.userId],
|
||||||
references: [admins.adminId],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -30,3 +30,4 @@ export * from "./gitlab";
|
|||||||
export * from "./server";
|
export * from "./server";
|
||||||
export * from "./utils";
|
export * from "./utils";
|
||||||
export * from "./preview-deployments";
|
export * from "./preview-deployments";
|
||||||
|
export * from "./account";
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { createInsertSchema } from "drizzle-zod";
|
|||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { admins } from "./admin";
|
import { admins } from "./admin";
|
||||||
|
import { users } from "./user";
|
||||||
|
|
||||||
export const notificationType = pgEnum("notificationType", [
|
export const notificationType = pgEnum("notificationType", [
|
||||||
"slack",
|
"slack",
|
||||||
@@ -44,7 +45,7 @@ export const notifications = pgTable("notification", {
|
|||||||
gotifyId: text("gotifyId").references(() => gotify.gotifyId, {
|
gotifyId: text("gotifyId").references(() => gotify.gotifyId, {
|
||||||
onDelete: "cascade",
|
onDelete: "cascade",
|
||||||
}),
|
}),
|
||||||
adminId: text("adminId").references(() => admins.adminId, {
|
userId: text("userId").references(() => users.id, {
|
||||||
onDelete: "cascade",
|
onDelete: "cascade",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -121,9 +122,9 @@ export const notificationsRelations = relations(notifications, ({ one }) => ({
|
|||||||
fields: [notifications.gotifyId],
|
fields: [notifications.gotifyId],
|
||||||
references: [gotify.gotifyId],
|
references: [gotify.gotifyId],
|
||||||
}),
|
}),
|
||||||
admin: one(admins, {
|
user: one(users, {
|
||||||
fields: [notifications.adminId],
|
fields: [notifications.userId],
|
||||||
references: [admins.adminId],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { pgTable, text } from "drizzle-orm/pg-core";
|
|||||||
import { createInsertSchema } from "drizzle-zod";
|
import { createInsertSchema } from "drizzle-zod";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { admins } from "./admin";
|
// import { admins } from "./admin";
|
||||||
import { applications } from "./application";
|
import { applications } from "./application";
|
||||||
import { compose } from "./compose";
|
import { compose } from "./compose";
|
||||||
import { mariadb } from "./mariadb";
|
import { mariadb } from "./mariadb";
|
||||||
@@ -12,6 +12,7 @@ import { mongo } from "./mongo";
|
|||||||
import { mysql } from "./mysql";
|
import { mysql } from "./mysql";
|
||||||
import { postgres } from "./postgres";
|
import { postgres } from "./postgres";
|
||||||
import { redis } from "./redis";
|
import { redis } from "./redis";
|
||||||
|
import { users } from "./user";
|
||||||
|
|
||||||
export const projects = pgTable("project", {
|
export const projects = pgTable("project", {
|
||||||
projectId: text("projectId")
|
projectId: text("projectId")
|
||||||
@@ -23,9 +24,9 @@ export const projects = pgTable("project", {
|
|||||||
createdAt: text("createdAt")
|
createdAt: text("createdAt")
|
||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
adminId: text("adminId")
|
userId: text("userId")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => admins.adminId, { onDelete: "cascade" }),
|
.references(() => users.id, { onDelete: "cascade" }),
|
||||||
env: text("env").notNull().default(""),
|
env: text("env").notNull().default(""),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -37,9 +38,9 @@ export const projectRelations = relations(projects, ({ many, one }) => ({
|
|||||||
mongo: many(mongo),
|
mongo: many(mongo),
|
||||||
redis: many(redis),
|
redis: many(redis),
|
||||||
compose: many(compose),
|
compose: many(compose),
|
||||||
admin: one(admins, {
|
user: one(users, {
|
||||||
fields: [projects.adminId],
|
fields: [projects.userId],
|
||||||
references: [admins.adminId],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { nanoid } from "nanoid";
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { admins } from "./admin";
|
import { admins } from "./admin";
|
||||||
import { applications } from "./application";
|
import { applications } from "./application";
|
||||||
|
import { users } from "./user";
|
||||||
/**
|
/**
|
||||||
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
|
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
|
||||||
* database instance for multiple projects.
|
* database instance for multiple projects.
|
||||||
@@ -27,15 +28,15 @@ export const registry = pgTable("registry", {
|
|||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
registryType: registryType("selfHosted").notNull().default("cloud"),
|
registryType: registryType("selfHosted").notNull().default("cloud"),
|
||||||
adminId: text("adminId")
|
userId: text("userId")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => admins.adminId, { onDelete: "cascade" }),
|
.references(() => users.id, { onDelete: "cascade" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const registryRelations = relations(registry, ({ one, many }) => ({
|
export const registryRelations = relations(registry, ({ one, many }) => ({
|
||||||
admin: one(admins, {
|
user: one(users, {
|
||||||
fields: [registry.adminId],
|
fields: [registry.userId],
|
||||||
references: [admins.adminId],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
applications: many(applications),
|
applications: many(applications),
|
||||||
}));
|
}));
|
||||||
@@ -45,7 +46,7 @@ const createSchema = createInsertSchema(registry, {
|
|||||||
username: z.string().min(1),
|
username: z.string().min(1),
|
||||||
password: z.string().min(1),
|
password: z.string().min(1),
|
||||||
registryUrl: z.string(),
|
registryUrl: z.string(),
|
||||||
adminId: z.string().min(1),
|
userId: z.string().min(1),
|
||||||
registryId: z.string().min(1),
|
registryId: z.string().min(1),
|
||||||
registryType: z.enum(["cloud"]),
|
registryType: z.enum(["cloud"]),
|
||||||
imagePrefix: z.string().nullable().optional(),
|
imagePrefix: z.string().nullable().optional(),
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import { postgres } from "./postgres";
|
|||||||
import { redis } from "./redis";
|
import { redis } from "./redis";
|
||||||
import { sshKeys } from "./ssh-key";
|
import { sshKeys } from "./ssh-key";
|
||||||
import { generateAppName } from "./utils";
|
import { generateAppName } from "./utils";
|
||||||
|
import { users } from "./user";
|
||||||
|
|
||||||
export const serverStatus = pgEnum("serverStatus", ["active", "inactive"]);
|
export const serverStatus = pgEnum("serverStatus", ["active", "inactive"]);
|
||||||
|
|
||||||
@@ -43,9 +44,9 @@ export const server = pgTable("server", {
|
|||||||
createdAt: text("createdAt")
|
createdAt: text("createdAt")
|
||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
adminId: text("adminId")
|
userId: text("userId")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => admins.adminId, { onDelete: "cascade" }),
|
.references(() => users.id, { onDelete: "cascade" }),
|
||||||
serverStatus: serverStatus("serverStatus").notNull().default("active"),
|
serverStatus: serverStatus("serverStatus").notNull().default("active"),
|
||||||
command: text("command").notNull().default(""),
|
command: text("command").notNull().default(""),
|
||||||
sshKeyId: text("sshKeyId").references(() => sshKeys.sshKeyId, {
|
sshKeyId: text("sshKeyId").references(() => sshKeys.sshKeyId, {
|
||||||
@@ -100,9 +101,9 @@ export const server = pgTable("server", {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const serverRelations = relations(server, ({ one, many }) => ({
|
export const serverRelations = relations(server, ({ one, many }) => ({
|
||||||
admin: one(admins, {
|
user: one(users, {
|
||||||
fields: [server.adminId],
|
fields: [server.userId],
|
||||||
references: [admins.adminId],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
deployments: many(deployments),
|
deployments: many(deployments),
|
||||||
sshKey: one(sshKeys, {
|
sshKey: one(sshKeys, {
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
import { pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||||
import { auth } from "./auth";
|
import { users } from "./user";
|
||||||
|
|
||||||
|
// OLD TABLE
|
||||||
export const sessionTable = pgTable("session", {
|
export const sessionTable = pgTable("session", {
|
||||||
id: text("id").primaryKey(),
|
id: text("id").primaryKey(),
|
||||||
|
expiresAt: timestamp("expires_at").notNull(),
|
||||||
|
token: text("token").notNull().unique(),
|
||||||
|
createdAt: timestamp("created_at").notNull(),
|
||||||
|
updatedAt: timestamp("updated_at").notNull(),
|
||||||
|
ipAddress: text("ip_address"),
|
||||||
|
userAgent: text("user_agent"),
|
||||||
userId: text("user_id")
|
userId: text("user_id")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => auth.id, { onDelete: "cascade" }),
|
.references(() => users.id),
|
||||||
expiresAt: timestamp("expires_at", {
|
impersonatedBy: text("impersonated_by"),
|
||||||
withTimezone: true,
|
|
||||||
mode: "date",
|
|
||||||
}).notNull(),
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { admins } from "./admin";
|
|||||||
import { applications } from "./application";
|
import { applications } from "./application";
|
||||||
import { compose } from "./compose";
|
import { compose } from "./compose";
|
||||||
import { server } from "./server";
|
import { server } from "./server";
|
||||||
|
import { users } from "./user";
|
||||||
|
|
||||||
export const sshKeys = pgTable("ssh-key", {
|
export const sshKeys = pgTable("ssh-key", {
|
||||||
sshKeyId: text("sshKeyId")
|
sshKeyId: text("sshKeyId")
|
||||||
@@ -21,7 +22,7 @@ export const sshKeys = pgTable("ssh-key", {
|
|||||||
.notNull()
|
.notNull()
|
||||||
.$defaultFn(() => new Date().toISOString()),
|
.$defaultFn(() => new Date().toISOString()),
|
||||||
lastUsedAt: text("lastUsedAt"),
|
lastUsedAt: text("lastUsedAt"),
|
||||||
adminId: text("adminId").references(() => admins.adminId, {
|
userId: text("userId").references(() => users.id, {
|
||||||
onDelete: "cascade",
|
onDelete: "cascade",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -30,9 +31,9 @@ export const sshKeysRelations = relations(sshKeys, ({ many, one }) => ({
|
|||||||
applications: many(applications),
|
applications: many(applications),
|
||||||
compose: many(compose),
|
compose: many(compose),
|
||||||
servers: many(server),
|
servers: many(server),
|
||||||
admin: one(admins, {
|
user: one(users, {
|
||||||
fields: [sshKeys.adminId],
|
fields: [sshKeys.userId],
|
||||||
references: [admins.adminId],
|
references: [users.id],
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ export const apiCreateSshKey = createSchema
|
|||||||
description: true,
|
description: true,
|
||||||
privateKey: true,
|
privateKey: true,
|
||||||
publicKey: true,
|
publicKey: true,
|
||||||
adminId: true,
|
userId: true,
|
||||||
})
|
})
|
||||||
.merge(sshKeyCreate.pick({ privateKey: true }));
|
.merge(sshKeyCreate.pick({ privateKey: true }));
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { relations, sql } from "drizzle-orm";
|
import { relations, sql } from "drizzle-orm";
|
||||||
import { boolean, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
import { boolean, jsonb, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||||
import { createInsertSchema } from "drizzle-zod";
|
import { createInsertSchema } from "drizzle-zod";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { admins } from "./admin";
|
import { admins } from "./admin";
|
||||||
import { auth } from "./auth";
|
import { auth } from "./auth";
|
||||||
|
import { certificateType } from "./shared";
|
||||||
/**
|
/**
|
||||||
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
|
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
|
||||||
* database instance for multiple projects.
|
* database instance for multiple projects.
|
||||||
@@ -12,12 +13,13 @@ import { auth } from "./auth";
|
|||||||
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
|
* @see https://orm.drizzle.team/docs/goodies#multi-project-schema
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// OLD TABLE
|
||||||
export const users = pgTable("user", {
|
export const users = pgTable("user", {
|
||||||
userId: text("userId")
|
id: text("id")
|
||||||
.notNull()
|
.notNull()
|
||||||
.primaryKey()
|
.primaryKey()
|
||||||
.$defaultFn(() => nanoid()),
|
.$defaultFn(() => nanoid()),
|
||||||
|
name: text("name").notNull().default(""),
|
||||||
token: text("token").notNull(),
|
token: text("token").notNull(),
|
||||||
isRegistered: boolean("isRegistered").notNull().default(false),
|
isRegistered: boolean("isRegistered").notNull().default(false),
|
||||||
expirationDate: timestamp("expirationDate", {
|
expirationDate: timestamp("expirationDate", {
|
||||||
@@ -48,31 +50,102 @@ export const users = pgTable("user", {
|
|||||||
.array()
|
.array()
|
||||||
.notNull()
|
.notNull()
|
||||||
.default(sql`ARRAY[]::text[]`),
|
.default(sql`ARRAY[]::text[]`),
|
||||||
adminId: text("adminId")
|
// authId: text("authId")
|
||||||
|
// .notNull()
|
||||||
|
// .references(() => auth.id, { onDelete: "cascade" }),
|
||||||
|
// Auth
|
||||||
|
email: text("email").notNull().unique(),
|
||||||
|
emailVerified: boolean("email_verified").notNull(),
|
||||||
|
image: text("image"),
|
||||||
|
role: text("role"),
|
||||||
|
banned: boolean("banned"),
|
||||||
|
banReason: text("ban_reason"),
|
||||||
|
banExpires: timestamp("ban_expires"),
|
||||||
|
updatedAt: timestamp("updated_at").notNull(),
|
||||||
|
// Admin
|
||||||
|
serverIp: text("serverIp"),
|
||||||
|
certificateType: certificateType("certificateType").notNull().default("none"),
|
||||||
|
host: text("host"),
|
||||||
|
letsEncryptEmail: text("letsEncryptEmail"),
|
||||||
|
sshPrivateKey: text("sshPrivateKey"),
|
||||||
|
enableDockerCleanup: boolean("enableDockerCleanup").notNull().default(false),
|
||||||
|
enableLogRotation: boolean("enableLogRotation").notNull().default(false),
|
||||||
|
// Metrics
|
||||||
|
enablePaidFeatures: boolean("enablePaidFeatures").notNull().default(false),
|
||||||
|
metricsConfig: jsonb("metricsConfig")
|
||||||
|
.$type<{
|
||||||
|
server: {
|
||||||
|
type: "Dokploy" | "Remote";
|
||||||
|
refreshRate: number;
|
||||||
|
port: number;
|
||||||
|
token: string;
|
||||||
|
urlCallback: string;
|
||||||
|
retentionDays: number;
|
||||||
|
cronJob: string;
|
||||||
|
thresholds: {
|
||||||
|
cpu: number;
|
||||||
|
memory: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
containers: {
|
||||||
|
refreshRate: number;
|
||||||
|
services: {
|
||||||
|
include: string[];
|
||||||
|
exclude: string[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}>()
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => admins.adminId, { onDelete: "cascade" }),
|
.default({
|
||||||
authId: text("authId")
|
server: {
|
||||||
|
type: "Dokploy",
|
||||||
|
refreshRate: 60,
|
||||||
|
port: 4500,
|
||||||
|
token: "",
|
||||||
|
retentionDays: 2,
|
||||||
|
cronJob: "",
|
||||||
|
urlCallback: "",
|
||||||
|
thresholds: {
|
||||||
|
cpu: 0,
|
||||||
|
memory: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
containers: {
|
||||||
|
refreshRate: 60,
|
||||||
|
services: {
|
||||||
|
include: [],
|
||||||
|
exclude: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
cleanupCacheApplications: boolean("cleanupCacheApplications")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => auth.id, { onDelete: "cascade" }),
|
.default(false),
|
||||||
|
cleanupCacheOnPreviews: boolean("cleanupCacheOnPreviews")
|
||||||
|
.notNull()
|
||||||
|
.default(false),
|
||||||
|
cleanupCacheOnCompose: boolean("cleanupCacheOnCompose")
|
||||||
|
.notNull()
|
||||||
|
.default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const usersRelations = relations(users, ({ one }) => ({
|
export const usersRelations = relations(users, ({ one }) => ({
|
||||||
auth: one(auth, {
|
// auth: one(auth, {
|
||||||
fields: [users.authId],
|
// fields: [users.authId],
|
||||||
references: [auth.id],
|
// references: [auth.id],
|
||||||
}),
|
// }),
|
||||||
admin: one(admins, {
|
// admin: one(admins, {
|
||||||
fields: [users.adminId],
|
// fields: [users.adminId],
|
||||||
references: [admins.adminId],
|
// references: [admins.adminId],
|
||||||
}),
|
// }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const createSchema = createInsertSchema(users, {
|
const createSchema = createInsertSchema(users, {
|
||||||
userId: z.string().min(1),
|
id: z.string().min(1),
|
||||||
authId: z.string().min(1),
|
// authId: z.string().min(1),
|
||||||
token: z.string().min(1),
|
token: z.string().min(1),
|
||||||
isRegistered: z.boolean().optional(),
|
isRegistered: z.boolean().optional(),
|
||||||
adminId: z.string(),
|
// adminId: z.string(),
|
||||||
accessedProjects: z.array(z.string()).optional(),
|
accessedProjects: z.array(z.string()).optional(),
|
||||||
accessedServices: z.array(z.string()).optional(),
|
accessedServices: z.array(z.string()).optional(),
|
||||||
canCreateProjects: z.boolean().optional(),
|
canCreateProjects: z.boolean().optional(),
|
||||||
@@ -89,7 +162,7 @@ export const apiCreateUserInvitation = createSchema.pick({}).extend({
|
|||||||
|
|
||||||
export const apiRemoveUser = createSchema
|
export const apiRemoveUser = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
authId: true,
|
// authId: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
@@ -101,7 +174,7 @@ export const apiFindOneToken = createSchema
|
|||||||
|
|
||||||
export const apiAssignPermissions = createSchema
|
export const apiAssignPermissions = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
userId: true,
|
id: true,
|
||||||
canCreateProjects: true,
|
canCreateProjects: true,
|
||||||
canCreateServices: true,
|
canCreateServices: true,
|
||||||
canDeleteProjects: true,
|
canDeleteProjects: true,
|
||||||
@@ -118,12 +191,12 @@ export const apiAssignPermissions = createSchema
|
|||||||
|
|
||||||
export const apiFindOneUser = createSchema
|
export const apiFindOneUser = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
userId: true,
|
id: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|
||||||
export const apiFindOneUserByAuth = createSchema
|
export const apiFindOneUserByAuth = createSchema
|
||||||
.pick({
|
.pick({
|
||||||
authId: true,
|
// authId: true,
|
||||||
})
|
})
|
||||||
.required();
|
.required();
|
||||||
|
|||||||
@@ -118,3 +118,5 @@ export * from "./monitoring/utils";
|
|||||||
export * from "./db/validations/domain";
|
export * from "./db/validations/domain";
|
||||||
export * from "./db/validations/index";
|
export * from "./db/validations/index";
|
||||||
export * from "./utils/gpu-setup";
|
export * from "./utils/gpu-setup";
|
||||||
|
|
||||||
|
export * from "./lib/auth";
|
||||||
|
|||||||
14
packages/server/src/lib/auth.ts
Normal file
14
packages/server/src/lib/auth.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { betterAuth } from "better-auth";
|
||||||
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
||||||
|
import { admin } from "better-auth/plugins";
|
||||||
|
import { db } from "../db";
|
||||||
|
|
||||||
|
export const auth = betterAuth({
|
||||||
|
database: drizzleAdapter(db, {
|
||||||
|
provider: "pg",
|
||||||
|
}),
|
||||||
|
emailAndPassword: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
plugins: [admin()],
|
||||||
|
});
|
||||||
@@ -94,7 +94,9 @@ export const updateAdminById = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const isAdminPresent = async () => {
|
export const isAdminPresent = async () => {
|
||||||
const admin = await db.query.admins.findFirst();
|
const admin = await db.query.users.findFirst({
|
||||||
|
where: eq(users.role, "admin"),
|
||||||
|
});
|
||||||
if (!admin) {
|
if (!admin) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,27 +23,27 @@ class LogRotationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async initialize(): Promise<void> {
|
private async initialize(): Promise<void> {
|
||||||
const isActive = await this.getStateFromDB();
|
// const isActive = await this.getStateFromDB();
|
||||||
if (isActive) {
|
// if (isActive) {
|
||||||
await this.activateStream();
|
// await this.activateStream();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private async getStateFromDB(): Promise<boolean> {
|
// private async getStateFromDB(): Promise<boolean> {
|
||||||
const setting = await db.query.admins.findFirst({});
|
// const setting = await db.query.admins.findFirst({});
|
||||||
return setting?.enableLogRotation ?? false;
|
// return setting?.enableLogRotation ?? false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
private async setStateInDB(active: boolean): Promise<void> {
|
// private async setStateInDB(active: boolean): Promise<void> {
|
||||||
const admin = await db.query.admins.findFirst({});
|
// const admin = await db.query.admins.findFirst({});
|
||||||
|
|
||||||
if (!admin) {
|
// if (!admin) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
await updateAdmin(admin?.authId, {
|
// await updateAdmin(admin?.authId, {
|
||||||
enableLogRotation: active,
|
// enableLogRotation: active,
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
private async activateStream(): Promise<void> {
|
private async activateStream(): Promise<void> {
|
||||||
const { DYNAMIC_TRAEFIK_PATH } = paths();
|
const { DYNAMIC_TRAEFIK_PATH } = paths();
|
||||||
@@ -76,26 +76,26 @@ class LogRotationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async activate(): Promise<boolean> {
|
public async activate(): Promise<boolean> {
|
||||||
const currentState = await this.getStateFromDB();
|
// const currentState = await this.getStateFromDB();
|
||||||
if (currentState) {
|
// if (currentState) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
await this.setStateInDB(true);
|
// await this.setStateInDB(true);
|
||||||
await this.activateStream();
|
// await this.activateStream();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deactivate(): Promise<boolean> {
|
public async deactivate(): Promise<boolean> {
|
||||||
console.log("Deactivating log rotation...");
|
console.log("Deactivating log rotation...");
|
||||||
const currentState = await this.getStateFromDB();
|
// const currentState = await this.getStateFromDB();
|
||||||
if (!currentState) {
|
// if (!currentState) {
|
||||||
console.log("Log rotation is already inactive in DB");
|
// console.log("Log rotation is already inactive in DB");
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
await this.setStateInDB(false);
|
// await this.setStateInDB(false);
|
||||||
await this.deactivateStream();
|
// await this.deactivateStream();
|
||||||
console.log("Log rotation deactivated successfully");
|
console.log("Log rotation deactivated successfully");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -115,8 +115,9 @@ class LogRotationManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async getStatus(): Promise<boolean> {
|
public async getStatus(): Promise<boolean> {
|
||||||
const dbState = await this.getStateFromDB();
|
// const dbState = await this.getStateFromDB();
|
||||||
return dbState;
|
// return dbState;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const logRotationManager = LogRotationManager.getInstance();
|
export const logRotationManager = LogRotationManager.getInstance();
|
||||||
|
|||||||
206
pnpm-lock.yaml
generated
206
pnpm-lock.yaml
generated
@@ -238,6 +238,9 @@ importers:
|
|||||||
bcrypt:
|
bcrypt:
|
||||||
specifier: 5.1.1
|
specifier: 5.1.1
|
||||||
version: 5.1.1(encoding@0.1.13)
|
version: 5.1.1(encoding@0.1.13)
|
||||||
|
better-auth:
|
||||||
|
specifier: 1.1.16
|
||||||
|
version: 1.1.16
|
||||||
bl:
|
bl:
|
||||||
specifier: 6.0.11
|
specifier: 6.0.11
|
||||||
version: 6.0.11
|
version: 6.0.11
|
||||||
@@ -273,10 +276,10 @@ importers:
|
|||||||
version: 16.4.5
|
version: 16.4.5
|
||||||
drizzle-orm:
|
drizzle-orm:
|
||||||
specifier: ^0.39.1
|
specifier: ^0.39.1
|
||||||
version: 0.39.1(@types/react@18.3.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
|
version: 0.39.1(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
|
||||||
drizzle-zod:
|
drizzle-zod:
|
||||||
specifier: 0.5.1
|
specifier: 0.5.1
|
||||||
version: 0.5.1(drizzle-orm@0.39.1(@types/react@18.3.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8)
|
version: 0.5.1(drizzle-orm@0.39.1(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8)
|
||||||
fancy-ansi:
|
fancy-ansi:
|
||||||
specifier: ^0.1.3
|
specifier: ^0.1.3
|
||||||
version: 0.1.3
|
version: 0.1.3
|
||||||
@@ -505,7 +508,7 @@ importers:
|
|||||||
version: 16.4.5
|
version: 16.4.5
|
||||||
drizzle-orm:
|
drizzle-orm:
|
||||||
specifier: ^0.39.1
|
specifier: ^0.39.1
|
||||||
version: 0.39.1(@types/react@18.3.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
|
version: 0.39.1(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
|
||||||
hono:
|
hono:
|
||||||
specifier: ^4.5.8
|
specifier: ^4.5.8
|
||||||
version: 4.5.8
|
version: 4.5.8
|
||||||
@@ -567,6 +570,9 @@ importers:
|
|||||||
bcrypt:
|
bcrypt:
|
||||||
specifier: 5.1.1
|
specifier: 5.1.1
|
||||||
version: 5.1.1(encoding@0.1.13)
|
version: 5.1.1(encoding@0.1.13)
|
||||||
|
better-auth:
|
||||||
|
specifier: 1.1.16
|
||||||
|
version: 1.1.16
|
||||||
bl:
|
bl:
|
||||||
specifier: 6.0.11
|
specifier: 6.0.11
|
||||||
version: 6.0.11
|
version: 6.0.11
|
||||||
@@ -584,10 +590,10 @@ importers:
|
|||||||
version: 16.4.5
|
version: 16.4.5
|
||||||
drizzle-orm:
|
drizzle-orm:
|
||||||
specifier: ^0.39.1
|
specifier: ^0.39.1
|
||||||
version: 0.39.1(@types/react@18.3.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
|
version: 0.39.1(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
|
||||||
drizzle-zod:
|
drizzle-zod:
|
||||||
specifier: 0.5.1
|
specifier: 0.5.1
|
||||||
version: 0.5.1(drizzle-orm@0.39.1(@types/react@18.3.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8)
|
version: 0.5.1(drizzle-orm@0.39.1(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8)
|
||||||
hi-base32:
|
hi-base32:
|
||||||
specifier: ^0.5.1
|
specifier: ^0.5.1
|
||||||
version: 0.5.1
|
version: 0.5.1
|
||||||
@@ -748,6 +754,12 @@ packages:
|
|||||||
'@balena/dockerignore@1.0.2':
|
'@balena/dockerignore@1.0.2':
|
||||||
resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==}
|
resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==}
|
||||||
|
|
||||||
|
'@better-auth/utils@0.2.3':
|
||||||
|
resolution: {integrity: sha512-Ap1GaSmo6JYhJhxJOpUB0HobkKPTNzfta+bLV89HfpyCAHN7p8ntCrmNFHNAVD0F6v0mywFVEUg1FUhNCc81Rw==}
|
||||||
|
|
||||||
|
'@better-fetch/fetch@1.1.12':
|
||||||
|
resolution: {integrity: sha512-B3bfloI/2UBQWIATRN6qmlORrvx3Mp0kkNjmXLv0b+DtbtR+pP4/I5kQA/rDUv+OReLywCCldf6co4LdDmh8JA==}
|
||||||
|
|
||||||
'@biomejs/biome@1.9.4':
|
'@biomejs/biome@1.9.4':
|
||||||
resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==}
|
resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==}
|
||||||
engines: {node: '>=14.21.3'}
|
engines: {node: '>=14.21.3'}
|
||||||
@@ -1518,6 +1530,9 @@ packages:
|
|||||||
'@hapi/bourne@3.0.0':
|
'@hapi/bourne@3.0.0':
|
||||||
resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==}
|
resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==}
|
||||||
|
|
||||||
|
'@hexagon/base64@1.1.28':
|
||||||
|
resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==}
|
||||||
|
|
||||||
'@hono/node-server@1.12.1':
|
'@hono/node-server@1.12.1':
|
||||||
resolution: {integrity: sha512-C9l+08O8xtXB7Ppmy8DjBFH1hYji7JKzsU32Yt1poIIbdPp6S7aOI8IldDHD9YFJ55lv2c21ovNrmxatlHfhAg==}
|
resolution: {integrity: sha512-C9l+08O8xtXB7Ppmy8DjBFH1hYji7JKzsU32Yt1poIIbdPp6S7aOI8IldDHD9YFJ55lv2c21ovNrmxatlHfhAg==}
|
||||||
engines: {node: '>=18.14.1'}
|
engines: {node: '>=18.14.1'}
|
||||||
@@ -1697,6 +1712,9 @@ packages:
|
|||||||
'@leichtgewicht/ip-codec@2.0.5':
|
'@leichtgewicht/ip-codec@2.0.5':
|
||||||
resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==}
|
resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==}
|
||||||
|
|
||||||
|
'@levischuck/tiny-cbor@0.2.11':
|
||||||
|
resolution: {integrity: sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==}
|
||||||
|
|
||||||
'@lezer/common@1.2.1':
|
'@lezer/common@1.2.1':
|
||||||
resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==}
|
resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==}
|
||||||
|
|
||||||
@@ -1807,10 +1825,17 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@noble/ciphers@0.6.0':
|
||||||
|
resolution: {integrity: sha512-mIbq/R9QXk5/cTfESb1OKtyFnk7oc1Om/8onA1158K9/OZUQFDEVy55jVTato+xmp3XX6F6Qh0zz0Nc1AxAlRQ==}
|
||||||
|
|
||||||
'@noble/hashes@1.5.0':
|
'@noble/hashes@1.5.0':
|
||||||
resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==}
|
resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==}
|
||||||
engines: {node: ^14.21.3 || >=16}
|
engines: {node: ^14.21.3 || >=16}
|
||||||
|
|
||||||
|
'@noble/hashes@1.7.1':
|
||||||
|
resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==}
|
||||||
|
engines: {node: ^14.21.3 || >=16}
|
||||||
|
|
||||||
'@node-rs/argon2-android-arm-eabi@1.7.0':
|
'@node-rs/argon2-android-arm-eabi@1.7.0':
|
||||||
resolution: {integrity: sha512-udDqkr5P9E+wYX1SZwAVPdyfYvaF4ry9Tm+R9LkfSHbzWH0uhU6zjIwNRp7m+n4gx691rk+lqqDAIP8RLKwbhg==}
|
resolution: {integrity: sha512-udDqkr5P9E+wYX1SZwAVPdyfYvaF4ry9Tm+R9LkfSHbzWH0uhU6zjIwNRp7m+n4gx691rk+lqqDAIP8RLKwbhg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
@@ -2136,6 +2161,21 @@ packages:
|
|||||||
'@one-ini/wasm@0.1.1':
|
'@one-ini/wasm@0.1.1':
|
||||||
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
|
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
|
||||||
|
|
||||||
|
'@peculiar/asn1-android@2.3.15':
|
||||||
|
resolution: {integrity: sha512-8U2TIj59cRlSXTX2d0mzUKP7whfWGFMzTeC3qPgAbccXFrPNZLaDhpNEdG5U2QZ/tBv/IHlCJ8s+KYXpJeop6w==}
|
||||||
|
|
||||||
|
'@peculiar/asn1-ecc@2.3.15':
|
||||||
|
resolution: {integrity: sha512-/HtR91dvgog7z/WhCVdxZJ/jitJuIu8iTqiyWVgRE9Ac5imt2sT/E4obqIVGKQw7PIy+X6i8lVBoT6wC73XUgA==}
|
||||||
|
|
||||||
|
'@peculiar/asn1-rsa@2.3.15':
|
||||||
|
resolution: {integrity: sha512-p6hsanvPhexRtYSOHihLvUUgrJ8y0FtOM97N5UEpC+VifFYyZa0iZ5cXjTkZoDwxJ/TTJ1IJo3HVTB2JJTpXvg==}
|
||||||
|
|
||||||
|
'@peculiar/asn1-schema@2.3.15':
|
||||||
|
resolution: {integrity: sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==}
|
||||||
|
|
||||||
|
'@peculiar/asn1-x509@2.3.15':
|
||||||
|
resolution: {integrity: sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg==}
|
||||||
|
|
||||||
'@pkgjs/parseargs@0.11.0':
|
'@pkgjs/parseargs@0.11.0':
|
||||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@@ -3147,6 +3187,13 @@ packages:
|
|||||||
'@selderee/plugin-htmlparser2@0.11.0':
|
'@selderee/plugin-htmlparser2@0.11.0':
|
||||||
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
resolution: {integrity: sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==}
|
||||||
|
|
||||||
|
'@simplewebauthn/browser@13.1.0':
|
||||||
|
resolution: {integrity: sha512-WuHZ/PYvyPJ9nxSzgHtOEjogBhwJfC8xzYkPC+rR/+8chl/ft4ngjiK8kSU5HtRJfczupyOh33b25TjYbvwAcg==}
|
||||||
|
|
||||||
|
'@simplewebauthn/server@13.1.1':
|
||||||
|
resolution: {integrity: sha512-1hsLpRHfSuMB9ee2aAdh0Htza/X3f4djhYISrggqGe3xopNjOcePiSDkDDoPzDYaaMCrbqGP1H2TYU7bgL9PmA==}
|
||||||
|
engines: {node: '>=20.0.0'}
|
||||||
|
|
||||||
'@sinclair/typebox@0.27.8':
|
'@sinclair/typebox@0.27.8':
|
||||||
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
|
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
|
||||||
|
|
||||||
@@ -3762,6 +3809,10 @@ packages:
|
|||||||
asn1@0.2.6:
|
asn1@0.2.6:
|
||||||
resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
|
resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
|
||||||
|
|
||||||
|
asn1js@3.0.5:
|
||||||
|
resolution: {integrity: sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==}
|
||||||
|
engines: {node: '>=12.0.0'}
|
||||||
|
|
||||||
assertion-error@1.1.0:
|
assertion-error@1.1.0:
|
||||||
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
||||||
|
|
||||||
@@ -3804,6 +3855,12 @@ packages:
|
|||||||
before-after-hook@2.2.3:
|
before-after-hook@2.2.3:
|
||||||
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
|
resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==}
|
||||||
|
|
||||||
|
better-auth@1.1.16:
|
||||||
|
resolution: {integrity: sha512-Xc5pxafKZw4QVU8WYfkV2z4Hd8KCXXbphrgOpe2gA/EfanysLBhE1G/F7cEi5e0bW2pGR+vw6gf0ARHA7VFihg==}
|
||||||
|
|
||||||
|
better-call@0.3.3:
|
||||||
|
resolution: {integrity: sha512-N4lDVm0NGmFfDJ0XMQ4O83Zm/3dPlvIQdxvwvgSLSkjFX5PM4GUYSVAuxNzXN27QZMHDkrJTWUqxBrm4tPC3eA==}
|
||||||
|
|
||||||
binary-extensions@2.3.0:
|
binary-extensions@2.3.0:
|
||||||
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -5120,6 +5177,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==}
|
resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
jose@5.9.6:
|
||||||
|
resolution: {integrity: sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==}
|
||||||
|
|
||||||
joycon@3.1.1:
|
joycon@3.1.1:
|
||||||
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -5223,6 +5283,10 @@ packages:
|
|||||||
keyv@4.5.4:
|
keyv@4.5.4:
|
||||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||||
|
|
||||||
|
kysely@0.27.5:
|
||||||
|
resolution: {integrity: sha512-s7hZHcQeSNKpzCkHRm8yA+0JPLjncSWnjb+2TIElwS2JAqYr+Kv3Ess+9KFfJS0C1xcQ1i9NkNHpWwCYpHMWsA==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
|
||||||
leac@0.6.0:
|
leac@0.6.0:
|
||||||
resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==}
|
resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==}
|
||||||
|
|
||||||
@@ -5608,6 +5672,10 @@ packages:
|
|||||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
nanostores@0.11.3:
|
||||||
|
resolution: {integrity: sha512-TUes3xKIX33re4QzdxwZ6tdbodjmn3tWXCEc1uokiEmo14sI1EaGYNs2k3bU2pyyGNmBqFGAVl6jAGWd06AVIg==}
|
||||||
|
engines: {node: ^18.0.0 || >=20.0.0}
|
||||||
|
|
||||||
napi-build-utils@1.0.2:
|
napi-build-utils@1.0.2:
|
||||||
resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
|
resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
|
||||||
|
|
||||||
@@ -6058,6 +6126,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
pvtsutils@1.3.6:
|
||||||
|
resolution: {integrity: sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==}
|
||||||
|
|
||||||
|
pvutils@1.1.3:
|
||||||
|
resolution: {integrity: sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
qrcode@1.5.4:
|
qrcode@1.5.4:
|
||||||
resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
|
resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
@@ -6403,6 +6478,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-cfmm3tqdnbuYw2FBmRTPBDaohYEbMJ3211T35o6eZdr4d7v69+ZeK1Av84Br7FLj2dlzyeZSbN6qTuXXE6dawQ==}
|
resolution: {integrity: sha512-cfmm3tqdnbuYw2FBmRTPBDaohYEbMJ3211T35o6eZdr4d7v69+ZeK1Av84Br7FLj2dlzyeZSbN6qTuXXE6dawQ==}
|
||||||
engines: {node: '>=14.0'}
|
engines: {node: '>=14.0'}
|
||||||
|
|
||||||
|
rou3@0.5.1:
|
||||||
|
resolution: {integrity: sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==}
|
||||||
|
|
||||||
run-parallel@1.2.0:
|
run-parallel@1.2.0:
|
||||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||||
|
|
||||||
@@ -6872,6 +6950,9 @@ packages:
|
|||||||
tslib@2.6.3:
|
tslib@2.6.3:
|
||||||
resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
|
resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==}
|
||||||
|
|
||||||
|
tslib@2.8.1:
|
||||||
|
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||||
|
|
||||||
tsx@4.16.2:
|
tsx@4.16.2:
|
||||||
resolution: {integrity: sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==}
|
resolution: {integrity: sha512-C1uWweJDgdtX2x600HjaFaucXTilT7tgUZHbOE4+ypskZ1OP8CRCSDkCxG6Vya9EwaFIVagWwpaVAn5wzypaqQ==}
|
||||||
engines: {node: '>=18.0.0'}
|
engines: {node: '>=18.0.0'}
|
||||||
@@ -7237,6 +7318,9 @@ packages:
|
|||||||
zod@3.23.8:
|
zod@3.23.8:
|
||||||
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
|
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
|
||||||
|
|
||||||
|
zod@3.24.1:
|
||||||
|
resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==}
|
||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
'@alloc/quick-lru@5.2.0': {}
|
'@alloc/quick-lru@5.2.0': {}
|
||||||
@@ -7266,6 +7350,12 @@ snapshots:
|
|||||||
|
|
||||||
'@balena/dockerignore@1.0.2': {}
|
'@balena/dockerignore@1.0.2': {}
|
||||||
|
|
||||||
|
'@better-auth/utils@0.2.3':
|
||||||
|
dependencies:
|
||||||
|
uncrypto: 0.1.3
|
||||||
|
|
||||||
|
'@better-fetch/fetch@1.1.12': {}
|
||||||
|
|
||||||
'@biomejs/biome@1.9.4':
|
'@biomejs/biome@1.9.4':
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@biomejs/cli-darwin-arm64': 1.9.4
|
'@biomejs/cli-darwin-arm64': 1.9.4
|
||||||
@@ -7832,6 +7922,8 @@ snapshots:
|
|||||||
|
|
||||||
'@hapi/bourne@3.0.0': {}
|
'@hapi/bourne@3.0.0': {}
|
||||||
|
|
||||||
|
'@hexagon/base64@1.1.28': {}
|
||||||
|
|
||||||
'@hono/node-server@1.12.1': {}
|
'@hono/node-server@1.12.1': {}
|
||||||
|
|
||||||
'@hono/zod-validator@0.3.0(hono@4.5.8)(zod@3.23.8)':
|
'@hono/zod-validator@0.3.0(hono@4.5.8)(zod@3.23.8)':
|
||||||
@@ -7981,6 +8073,8 @@ snapshots:
|
|||||||
|
|
||||||
'@leichtgewicht/ip-codec@2.0.5': {}
|
'@leichtgewicht/ip-codec@2.0.5': {}
|
||||||
|
|
||||||
|
'@levischuck/tiny-cbor@0.2.11': {}
|
||||||
|
|
||||||
'@lezer/common@1.2.1': {}
|
'@lezer/common@1.2.1': {}
|
||||||
|
|
||||||
'@lezer/highlight@1.2.0':
|
'@lezer/highlight@1.2.0':
|
||||||
@@ -8071,8 +8165,12 @@ snapshots:
|
|||||||
'@next/swc-win32-x64-msvc@15.0.1':
|
'@next/swc-win32-x64-msvc@15.0.1':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@noble/ciphers@0.6.0': {}
|
||||||
|
|
||||||
'@noble/hashes@1.5.0': {}
|
'@noble/hashes@1.5.0': {}
|
||||||
|
|
||||||
|
'@noble/hashes@1.7.1': {}
|
||||||
|
|
||||||
'@node-rs/argon2-android-arm-eabi@1.7.0':
|
'@node-rs/argon2-android-arm-eabi@1.7.0':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -8401,6 +8499,39 @@ snapshots:
|
|||||||
|
|
||||||
'@one-ini/wasm@0.1.1': {}
|
'@one-ini/wasm@0.1.1': {}
|
||||||
|
|
||||||
|
'@peculiar/asn1-android@2.3.15':
|
||||||
|
dependencies:
|
||||||
|
'@peculiar/asn1-schema': 2.3.15
|
||||||
|
asn1js: 3.0.5
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@peculiar/asn1-ecc@2.3.15':
|
||||||
|
dependencies:
|
||||||
|
'@peculiar/asn1-schema': 2.3.15
|
||||||
|
'@peculiar/asn1-x509': 2.3.15
|
||||||
|
asn1js: 3.0.5
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@peculiar/asn1-rsa@2.3.15':
|
||||||
|
dependencies:
|
||||||
|
'@peculiar/asn1-schema': 2.3.15
|
||||||
|
'@peculiar/asn1-x509': 2.3.15
|
||||||
|
asn1js: 3.0.5
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@peculiar/asn1-schema@2.3.15':
|
||||||
|
dependencies:
|
||||||
|
asn1js: 3.0.5
|
||||||
|
pvtsutils: 1.3.6
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
'@peculiar/asn1-x509@2.3.15':
|
||||||
|
dependencies:
|
||||||
|
'@peculiar/asn1-schema': 2.3.15
|
||||||
|
asn1js: 3.0.5
|
||||||
|
pvtsutils: 1.3.6
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@pkgjs/parseargs@0.11.0':
|
'@pkgjs/parseargs@0.11.0':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -9394,6 +9525,18 @@ snapshots:
|
|||||||
domhandler: 5.0.3
|
domhandler: 5.0.3
|
||||||
selderee: 0.11.0
|
selderee: 0.11.0
|
||||||
|
|
||||||
|
'@simplewebauthn/browser@13.1.0': {}
|
||||||
|
|
||||||
|
'@simplewebauthn/server@13.1.1':
|
||||||
|
dependencies:
|
||||||
|
'@hexagon/base64': 1.1.28
|
||||||
|
'@levischuck/tiny-cbor': 0.2.11
|
||||||
|
'@peculiar/asn1-android': 2.3.15
|
||||||
|
'@peculiar/asn1-ecc': 2.3.15
|
||||||
|
'@peculiar/asn1-rsa': 2.3.15
|
||||||
|
'@peculiar/asn1-schema': 2.3.15
|
||||||
|
'@peculiar/asn1-x509': 2.3.15
|
||||||
|
|
||||||
'@sinclair/typebox@0.27.8': {}
|
'@sinclair/typebox@0.27.8': {}
|
||||||
|
|
||||||
'@sindresorhus/is@5.6.0': {}
|
'@sindresorhus/is@5.6.0': {}
|
||||||
@@ -10304,6 +10447,12 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer: 2.1.2
|
safer-buffer: 2.1.2
|
||||||
|
|
||||||
|
asn1js@3.0.5:
|
||||||
|
dependencies:
|
||||||
|
pvtsutils: 1.3.6
|
||||||
|
pvutils: 1.1.3
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
assertion-error@1.1.0: {}
|
assertion-error@1.1.0: {}
|
||||||
|
|
||||||
async-await-queue@2.1.4: {}
|
async-await-queue@2.1.4: {}
|
||||||
@@ -10352,6 +10501,28 @@ snapshots:
|
|||||||
|
|
||||||
before-after-hook@2.2.3: {}
|
before-after-hook@2.2.3: {}
|
||||||
|
|
||||||
|
better-auth@1.1.16:
|
||||||
|
dependencies:
|
||||||
|
'@better-auth/utils': 0.2.3
|
||||||
|
'@better-fetch/fetch': 1.1.12
|
||||||
|
'@noble/ciphers': 0.6.0
|
||||||
|
'@noble/hashes': 1.7.1
|
||||||
|
'@simplewebauthn/browser': 13.1.0
|
||||||
|
'@simplewebauthn/server': 13.1.1
|
||||||
|
better-call: 0.3.3
|
||||||
|
defu: 6.1.4
|
||||||
|
jose: 5.9.6
|
||||||
|
kysely: 0.27.5
|
||||||
|
nanostores: 0.11.3
|
||||||
|
zod: 3.24.1
|
||||||
|
|
||||||
|
better-call@0.3.3:
|
||||||
|
dependencies:
|
||||||
|
'@better-fetch/fetch': 1.1.12
|
||||||
|
rou3: 0.5.1
|
||||||
|
uncrypto: 0.1.3
|
||||||
|
zod: 3.24.1
|
||||||
|
|
||||||
binary-extensions@2.3.0: {}
|
binary-extensions@2.3.0: {}
|
||||||
|
|
||||||
bindings@1.5.0:
|
bindings@1.5.0:
|
||||||
@@ -10957,16 +11128,17 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
drizzle-orm@0.39.1(@types/react@18.3.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7):
|
drizzle-orm@0.39.1(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 18.3.5
|
'@types/react': 18.3.5
|
||||||
|
kysely: 0.27.5
|
||||||
postgres: 3.4.4
|
postgres: 3.4.4
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
sqlite3: 5.1.7
|
sqlite3: 5.1.7
|
||||||
|
|
||||||
drizzle-zod@0.5.1(drizzle-orm@0.39.1(@types/react@18.3.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8):
|
drizzle-zod@0.5.1(drizzle-orm@0.39.1(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))(zod@3.23.8):
|
||||||
dependencies:
|
dependencies:
|
||||||
drizzle-orm: 0.39.1(@types/react@18.3.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
|
drizzle-orm: 0.39.1(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
|
||||||
zod: 3.23.8
|
zod: 3.23.8
|
||||||
|
|
||||||
eastasianwidth@0.2.0: {}
|
eastasianwidth@0.2.0: {}
|
||||||
@@ -11686,6 +11858,8 @@ snapshots:
|
|||||||
|
|
||||||
jiti@1.21.6: {}
|
jiti@1.21.6: {}
|
||||||
|
|
||||||
|
jose@5.9.6: {}
|
||||||
|
|
||||||
joycon@3.1.1: {}
|
joycon@3.1.1: {}
|
||||||
|
|
||||||
js-base64@3.7.7: {}
|
js-base64@3.7.7: {}
|
||||||
@@ -11843,6 +12017,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
json-buffer: 3.0.1
|
json-buffer: 3.0.1
|
||||||
|
|
||||||
|
kysely@0.27.5: {}
|
||||||
|
|
||||||
leac@0.6.0: {}
|
leac@0.6.0: {}
|
||||||
|
|
||||||
lefthook-darwin-arm64@1.8.4:
|
lefthook-darwin-arm64@1.8.4:
|
||||||
@@ -12215,6 +12391,8 @@ snapshots:
|
|||||||
|
|
||||||
nanoid@3.3.7: {}
|
nanoid@3.3.7: {}
|
||||||
|
|
||||||
|
nanostores@0.11.3: {}
|
||||||
|
|
||||||
napi-build-utils@1.0.2:
|
napi-build-utils@1.0.2:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
@@ -12692,6 +12870,12 @@ snapshots:
|
|||||||
|
|
||||||
punycode@2.3.1: {}
|
punycode@2.3.1: {}
|
||||||
|
|
||||||
|
pvtsutils@1.3.6:
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
pvutils@1.1.3: {}
|
||||||
|
|
||||||
qrcode@1.5.4:
|
qrcode@1.5.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
dijkstrajs: 1.0.3
|
dijkstrajs: 1.0.3
|
||||||
@@ -13054,6 +13238,8 @@ snapshots:
|
|||||||
|
|
||||||
rotating-file-stream@3.2.3: {}
|
rotating-file-stream@3.2.3: {}
|
||||||
|
|
||||||
|
rou3@0.5.1: {}
|
||||||
|
|
||||||
run-parallel@1.2.0:
|
run-parallel@1.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
queue-microtask: 1.2.3
|
queue-microtask: 1.2.3
|
||||||
@@ -13617,6 +13803,8 @@ snapshots:
|
|||||||
|
|
||||||
tslib@2.6.3: {}
|
tslib@2.6.3: {}
|
||||||
|
|
||||||
|
tslib@2.8.1: {}
|
||||||
|
|
||||||
tsx@4.16.2:
|
tsx@4.16.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.21.5
|
esbuild: 0.21.5
|
||||||
@@ -13994,3 +14182,5 @@ snapshots:
|
|||||||
zod: 3.23.8
|
zod: 3.23.8
|
||||||
|
|
||||||
zod@3.23.8: {}
|
zod@3.23.8: {}
|
||||||
|
|
||||||
|
zod@3.24.1: {}
|
||||||
|
|||||||
Reference in New Issue
Block a user