feat(ai): update AI settings to use organization-based access control

- Refactor AI-related schemas and services to use organizationId instead of adminId
- Update AI router to check organization-level permissions
- Modify AI settings creation and retrieval to work with organization context
- Adjust server-side props and access checks for AI settings
This commit is contained in:
Mauricio Siu
2025-03-02 00:54:46 -06:00
parent 747c2137c9
commit f78cda9cce
10 changed files with 5326 additions and 64 deletions

View File

@@ -0,0 +1,12 @@
CREATE TABLE "ai" (
"aiId" text PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"apiUrl" text NOT NULL,
"apiKey" text NOT NULL,
"model" text NOT NULL,
"isEnabled" boolean DEFAULT true NOT NULL,
"organizationId" text NOT NULL,
"createdAt" text NOT NULL
);
--> statement-breakpoint
ALTER TABLE "ai" ADD CONSTRAINT "ai_organizationId_organization_id_fk" FOREIGN KEY ("organizationId") REFERENCES "public"."organization"("id") ON DELETE cascade ON UPDATE no action;

File diff suppressed because it is too large Load Diff

View File

@@ -477,6 +477,13 @@
"when": 1740892043121,
"tag": "0067_condemned_sugar_man",
"breakpoints": true
},
{
"idx": 68,
"version": "7",
"when": 1740897756774,
"tag": "0068_complex_rhino",
"breakpoints": true
}
]
}

View File

@@ -143,7 +143,8 @@
"xterm-addon-fit": "^0.8.0",
"zod": "^3.23.4",
"zod-form-data": "^2.0.2",
"@faker-js/faker": "^8.4.1"
"@faker-js/faker": "^8.4.1",
"@tailwindcss/typography": "0.5.16"
},
"devDependencies": {
"@types/qrcode": "^1.5.5",

View File

@@ -25,7 +25,7 @@ export async function getServerSideProps(
ctx: GetServerSidePropsContext<{ serviceId: string }>,
) {
const { req, res } = ctx;
const { user, session } = await validateRequest(req, res);
const { user, session } = await validateRequest(req);
const locale = getLocale(req.cookies);
const helpers = createServerSideHelpers({
@@ -34,22 +34,17 @@ export async function getServerSideProps(
req: req as any,
res: res as any,
db: null as any,
session: session,
user: user,
session: session as any,
user: user as any,
},
transformer: superjson,
});
await helpers.settings.isCloud.prefetch();
await helpers.auth.get.prefetch();
if (user?.rol === "user") {
await helpers.user.byAuthId.prefetch({
authId: user.authId,
});
}
await helpers.user.get.prefetch();
if (!user) {
if (!user || user.role === "member") {
return {
redirect: {
permanent: true,

View File

@@ -15,7 +15,7 @@ import { createDomain } from "@dokploy/server/index";
import {
deleteAiSettings,
getAiSettingById,
getAiSettingsByAdminId,
getAiSettingsByOrganizationId,
saveAiSettings,
suggestVariants,
} from "@dokploy/server/services/ai";
@@ -33,7 +33,7 @@ export const aiRouter = createTRPCRouter({
.input(z.object({ aiId: z.string() }))
.query(async ({ ctx, input }) => {
const aiSetting = await getAiSettingById(input.aiId);
if (aiSetting.adminId !== ctx.user.adminId) {
if (aiSetting.organizationId !== ctx.session.activeOrganizationId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You don't have access to this AI configuration",
@@ -42,24 +42,26 @@ export const aiRouter = createTRPCRouter({
return aiSetting;
}),
create: adminProcedure.input(apiCreateAi).mutation(async ({ ctx, input }) => {
return await saveAiSettings(ctx.user.adminId, input);
return await saveAiSettings(ctx.session.activeOrganizationId, input);
}),
update: protectedProcedure
.input(apiUpdateAi)
.mutation(async ({ ctx, input }) => {
return await saveAiSettings(ctx.user.adminId, input);
return await saveAiSettings(ctx.session.activeOrganizationId, input);
}),
getAll: adminProcedure.query(async ({ ctx }) => {
return await getAiSettingsByAdminId(ctx.user.adminId);
return await getAiSettingsByOrganizationId(
ctx.session.activeOrganizationId,
);
}),
get: protectedProcedure
.input(z.object({ aiId: z.string() }))
.query(async ({ ctx, input }) => {
const aiSetting = await getAiSettingById(input.aiId);
if (aiSetting.adminId !== ctx.user.authId) {
if (aiSetting.organizationId !== ctx.session.activeOrganizationId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You don't have access to this AI configuration",
@@ -72,7 +74,7 @@ export const aiRouter = createTRPCRouter({
.input(z.object({ aiId: z.string() }))
.mutation(async ({ ctx, input }) => {
const aiSetting = await getAiSettingById(input.aiId);
if (aiSetting.adminId !== ctx.user.adminId) {
if (aiSetting.organizationId !== ctx.session.activeOrganizationId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You don't have access to this AI configuration",
@@ -93,7 +95,7 @@ export const aiRouter = createTRPCRouter({
try {
return await suggestVariants({
...input,
adminId: ctx.user.adminId,
organizationId: ctx.session.activeOrganizationId,
});
} catch (error) {
throw new TRPCError({
@@ -105,8 +107,12 @@ export const aiRouter = createTRPCRouter({
deploy: protectedProcedure
.input(deploySuggestionSchema)
.mutation(async ({ ctx, input }) => {
if (ctx.user.rol === "user") {
await checkServiceAccess(ctx.user.adminId, input.projectId, "create");
if (ctx.user.rol === "member") {
await checkServiceAccess(
ctx.session.activeOrganizationId,
input.projectId,
"create",
);
}
if (IS_CLOUD && !input.serverId) {
@@ -143,8 +149,12 @@ export const aiRouter = createTRPCRouter({
}
}
if (ctx.user.rol === "user") {
await addNewService(ctx.user.authId, compose.composeId);
if (ctx.user.rol === "member") {
await addNewService(
ctx.session.activeOrganizationId,
ctx.user.ownerId,
compose.composeId,
);
}
return null;

View File

@@ -3,8 +3,7 @@ import { boolean, pgTable, text } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { nanoid } from "nanoid";
import { z } from "zod";
import { admins } from "./admin";
import { organization } from "./account";
export const ai = pgTable("ai", {
aiId: text("aiId")
.notNull()
@@ -15,18 +14,18 @@ export const ai = pgTable("ai", {
apiKey: text("apiKey").notNull(),
model: text("model").notNull(),
isEnabled: boolean("isEnabled").notNull().default(true),
adminId: text("adminId")
organizationId: text("organizationId")
.notNull()
.references(() => admins.adminId, { onDelete: "cascade" }), // Admin ID who created the AI settings
.references(() => organization.id, { onDelete: "cascade" }), // Admin ID who created the AI settings
createdAt: text("createdAt")
.notNull()
.$defaultFn(() => new Date().toISOString()),
});
export const aiRelations = relations(ai, ({ one }) => ({
admin: one(admins, {
fields: [ai.adminId],
references: [admins.adminId],
organization: one(organization, {
fields: [ai.organizationId],
references: [organization.id],
}),
}));
@@ -53,7 +52,7 @@ export const apiUpdateAi = createSchema
.extend({
aiId: z.string().min(1),
})
.omit({ adminId: true });
.omit({ organizationId: true });
export const deploySuggestionSchema = z.object({
projectId: z.string().min(1),

View File

@@ -28,6 +28,9 @@ export const findUserById = async (userId: string) => {
export const findOrganizationById = async (organizationId: string) => {
const organizationResult = await db.query.organization.findFirst({
where: eq(organization.id, organizationId),
with: {
owner: true,
},
});
return organizationResult;
};

View File

@@ -6,12 +6,12 @@ import { generateObject } from "ai";
import { desc, eq } from "drizzle-orm";
import { z } from "zod";
import { IS_CLOUD } from "../constants";
import { findAdminById } from "./admin";
import { findServerById } from "./server";
import { findOrganizationById } from "./admin";
export const getAiSettingsByAdminId = async (adminId: string) => {
export const getAiSettingsByOrganizationId = async (organizationId: string) => {
const aiSettings = await db.query.ai.findMany({
where: eq(ai.adminId, adminId),
where: eq(ai.organizationId, organizationId),
orderBy: desc(ai.createdAt),
});
return aiSettings;
@@ -30,14 +30,14 @@ export const getAiSettingById = async (aiId: string) => {
return aiSetting;
};
export const saveAiSettings = async (adminId: string, settings: any) => {
export const saveAiSettings = async (organizationId: string, settings: any) => {
const aiId = settings.aiId;
return db
.insert(ai)
.values({
aiId,
adminId,
organizationId,
...settings,
})
.onConflictDoUpdate({
@@ -53,14 +53,14 @@ export const deleteAiSettings = async (aiId: string) => {
};
interface Props {
adminId: string;
organizationId: string;
aiId: string;
input: string;
serverId?: string | undefined;
}
export const suggestVariants = async ({
adminId,
organizationId,
aiId,
input,
serverId,
@@ -79,8 +79,8 @@ export const suggestVariants = async ({
let ip = "";
if (!IS_CLOUD) {
const admin = await findAdminById(adminId);
ip = admin?.serverIp || "";
const organization = await findOrganizationById(organizationId);
ip = organization?.owner.serverIp || "";
}
if (serverId) {

165
pnpm-lock.yaml generated
View File

@@ -202,6 +202,9 @@ importers:
'@stripe/stripe-js':
specifier: 4.8.0
version: 4.8.0
'@tailwindcss/typography':
specifier: 0.5.16
version: 0.5.16(tailwindcss@3.4.7(ts-node@10.9.2(@types/node@18.19.42)(typescript@5.5.3)))
'@tanstack/react-query':
specifier: ^4.36.1
version: 4.36.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
@@ -282,10 +285,10 @@ importers:
version: 16.4.5
drizzle-orm:
specifier: ^0.39.1
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)
version: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
drizzle-zod:
specifier: 0.5.1
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)
version: 0.5.1(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@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:
specifier: ^0.1.3
version: 0.1.3
@@ -324,7 +327,7 @@ importers:
version: 15.3.1(i18next@23.16.5)(next@15.0.1(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-i18next@15.1.1(i18next@23.16.5)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0)
next-themes:
specifier: ^0.2.1
version: 0.2.1(next@15.0.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
version: 0.2.1(next@15.0.1(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
node-os-utils:
specifier: 1.3.7
version: 1.3.7
@@ -422,9 +425,6 @@ importers:
specifier: ^2.0.2
version: 2.0.2(zod@3.23.8)
devDependencies:
'@tailwindcss/typography':
specifier: ^0.5.15
version: 0.5.16(tailwindcss@3.4.7)
'@types/adm-zip':
specifier: ^0.5.5
version: 0.5.5
@@ -520,7 +520,7 @@ importers:
version: 16.4.5
drizzle-orm:
specifier: ^0.39.1
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)
version: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
hono:
specifier: ^4.5.8
version: 4.5.8
@@ -561,6 +561,27 @@ importers:
packages/server:
dependencies:
'@ai-sdk/anthropic':
specifier: ^1.0.6
version: 1.0.8(zod@3.23.8)
'@ai-sdk/azure':
specifier: ^1.0.15
version: 1.0.18(zod@3.23.8)
'@ai-sdk/cohere':
specifier: ^1.0.6
version: 1.0.8(zod@3.23.8)
'@ai-sdk/deepinfra':
specifier: ^0.0.4
version: 0.0.4(zod@3.23.8)
'@ai-sdk/mistral':
specifier: ^1.0.6
version: 1.0.8(zod@3.23.8)
'@ai-sdk/openai':
specifier: ^1.0.12
version: 1.0.16(zod@3.23.8)
'@ai-sdk/openai-compatible':
specifier: ^0.0.13
version: 0.0.13(zod@3.23.8)
'@better-auth/utils':
specifier: 0.2.3
version: 0.2.3
@@ -614,13 +635,13 @@ importers:
version: 16.4.5
drizzle-dbml-generator:
specifier: 0.10.0
version: 0.10.0(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))
version: 0.10.0(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7))
drizzle-orm:
specifier: ^0.39.1
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)
version: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
drizzle-zod:
specifier: 0.5.1
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)
version: 0.5.1(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@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:
specifier: ^0.5.1
version: 0.5.1
@@ -2280,6 +2301,10 @@ packages:
'@one-ini/wasm@0.1.1':
resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==}
'@opentelemetry/api@1.9.0':
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
engines: {node: '>=8.0.0'}
'@oslojs/asn1@1.0.0':
resolution: {integrity: sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==}
@@ -4912,6 +4937,9 @@ packages:
resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
engines: {node: '>=6'}
extend@3.0.2:
resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
fancy-ansi@0.1.3:
resolution: {integrity: sha512-tRQVTo5jjdSIiydqgzIIEZpKddzSsfGLsSVt6vWdjVm7fbvDTiQkyoPu6Z3dIPlAM4OZk0jP5jmTCX4G8WGgBw==}
@@ -5393,6 +5421,10 @@ packages:
resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
engines: {node: '>=8'}
is-plain-obj@4.1.0:
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
engines: {node: '>=12'}
is-stream@3.0.0:
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -6015,6 +6047,11 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
nanoid@3.3.8:
resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
nanostores@0.11.3:
resolution: {integrity: sha512-TUes3xKIX33re4QzdxwZ6tdbodjmn3tWXCEc1uokiEmo14sI1EaGYNs2k3bU2pyyGNmBqFGAVl6jAGWd06AVIg==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -7417,12 +7454,30 @@ packages:
resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==}
engines: {node: '>=18'}
unified@11.0.5:
resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
unique-filename@1.1.1:
resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==}
unique-slug@2.0.2:
resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==}
unist-util-is@6.0.0:
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
unist-util-position@5.0.0:
resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
unist-util-stringify-position@4.0.0:
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
unist-util-visit-parents@6.0.1:
resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
unist-util-visit@5.0.0:
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
universal-github-app-jwt@1.1.2:
resolution: {integrity: sha512-t1iB2FmLFE+yyJY9+3wMx0ejB+MQpEVkH0gQv7dR6FZyltyq+ZZO0uDpbopxhrZ3SLEO4dCEkIujOMldEQ2iOA==}
@@ -7502,6 +7557,12 @@ packages:
typescript:
optional: true
vfile-message@4.0.2:
resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
vfile@6.0.3:
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
victory-vendor@36.9.2:
resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==}
@@ -7743,6 +7804,9 @@ packages:
zod@3.24.1:
resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==}
zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
snapshots:
'@ai-sdk/anthropic@1.0.8(zod@3.23.8)':
@@ -8106,17 +8170,17 @@ snapshots:
'@emnapi/core@0.45.0':
dependencies:
tslib: 2.6.3
tslib: 2.8.1
optional: true
'@emnapi/runtime@0.45.0':
dependencies:
tslib: 2.6.3
tslib: 2.8.1
optional: true
'@emnapi/runtime@1.3.1':
dependencies:
tslib: 2.6.3
tslib: 2.8.1
optional: true
'@emotion/is-prop-valid@0.7.3':
@@ -9009,6 +9073,8 @@ snapshots:
'@one-ini/wasm@0.1.1': {}
'@opentelemetry/api@1.9.0': {}
'@oslojs/asn1@1.0.0':
dependencies:
'@oslojs/binary': 1.0.0
@@ -10409,19 +10475,19 @@ snapshots:
'@swc/helpers@0.5.13':
dependencies:
tslib: 2.6.3
tslib: 2.8.1
'@szmarczak/http-timer@5.0.1':
dependencies:
defer-to-connect: 2.0.1
'@tailwindcss/typography@0.5.16(tailwindcss@3.4.7)':
'@tailwindcss/typography@0.5.16(tailwindcss@3.4.7(ts-node@10.9.2(@types/node@18.19.42)(typescript@5.5.3)))':
dependencies:
lodash.castarray: 4.4.0
lodash.isplainobject: 4.0.6
lodash.merge: 4.6.2
postcss-selector-parser: 6.0.10
tailwindcss: 3.4.7
tailwindcss: 3.4.7(ts-node@10.9.2(@types/node@18.19.42)(typescript@5.5.3))
'@tanstack/query-core@4.36.1': {}
@@ -10482,7 +10548,7 @@ snapshots:
'@tybys/wasm-util@0.8.3':
dependencies:
tslib: 2.6.3
tslib: 2.8.1
optional: true
'@types/adm-zip@0.5.5':
@@ -11716,9 +11782,9 @@ snapshots:
drange@1.1.1: {}
drizzle-dbml-generator@0.10.0(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)):
drizzle-dbml-generator@0.10.0(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)):
dependencies:
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)
drizzle-orm: 0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7)
drizzle-kit@0.30.4:
dependencies:
@@ -11729,7 +11795,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
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):
drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@types/react@18.3.5)(kysely@0.27.5)(postgres@3.4.4)(react@18.2.0)(sqlite3@5.1.7):
optionalDependencies:
'@opentelemetry/api': 1.9.0
'@types/react': 18.3.5
@@ -11738,9 +11804,9 @@ snapshots:
react: 18.2.0
sqlite3: 5.1.7
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):
drizzle-zod@0.5.1(drizzle-orm@0.39.1(@opentelemetry/api@1.9.0)(@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:
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)
drizzle-orm: 0.39.1(@opentelemetry/api@1.9.0)(@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
eastasianwidth@0.2.0: {}
@@ -11963,6 +12029,8 @@ snapshots:
expand-template@2.0.3:
optional: true
extend@3.0.2: {}
fancy-ansi@0.1.3:
dependencies:
escape-html: 1.0.3
@@ -12479,6 +12547,8 @@ snapshots:
is-obj@2.0.0: {}
is-plain-obj@4.1.0: {}
is-stream@3.0.0: {}
is-text-path@2.0.0:
@@ -12497,7 +12567,7 @@ snapshots:
jest-worker@27.5.1:
dependencies:
'@types/node': 18.19.42
'@types/node': 20.14.10
merge-stream: 2.0.0
supports-color: 8.1.1
@@ -13270,6 +13340,8 @@ snapshots:
nanoid@3.3.7: {}
nanoid@3.3.8: {}
nanostores@0.11.3: {}
napi-build-utils@1.0.2:
@@ -13299,7 +13371,7 @@ snapshots:
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
next@15.0.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
next@15.0.1(@opentelemetry/api@1.9.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
dependencies:
'@next/env': 15.0.1
'@swc/counter': 0.1.3
@@ -14822,6 +14894,16 @@ snapshots:
unicorn-magic@0.1.0: {}
unified@11.0.5:
dependencies:
'@types/unist': 3.0.3
bail: 2.0.2
devlop: 1.1.0
extend: 3.0.2
is-plain-obj: 4.1.0
trough: 2.2.0
vfile: 6.0.3
unique-filename@1.1.1:
dependencies:
unique-slug: 2.0.2
@@ -14832,6 +14914,29 @@ snapshots:
imurmurhash: 0.1.4
optional: true
unist-util-is@6.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-position@5.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-stringify-position@4.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-visit-parents@6.0.1:
dependencies:
'@types/unist': 3.0.3
unist-util-is: 6.0.0
unist-util-visit@5.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-is: 6.0.0
unist-util-visit-parents: 6.0.1
universal-github-app-jwt@1.1.2:
dependencies:
'@types/jsonwebtoken': 9.0.6
@@ -14898,6 +15003,16 @@ snapshots:
optionalDependencies:
typescript: 5.5.3
vfile-message@4.0.2:
dependencies:
'@types/unist': 3.0.3
unist-util-stringify-position: 4.0.0
vfile@6.0.3:
dependencies:
'@types/unist': 3.0.3
vfile-message: 4.0.2
victory-vendor@36.9.2:
dependencies:
'@types/d3-array': 3.2.1
@@ -15162,3 +15277,5 @@ snapshots:
zod@3.23.8: {}
zod@3.24.1: {}
zwitch@2.0.4: {}