Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c3425359d | |||
| 3ce981a06a | |||
| 309eb8ac7e | |||
| 1494492b95 | |||
| 1f3028c25b | |||
| 58b70dd1e8 | |||
| df485b54c9 | |||
| 8b754f9fe6 | |||
| 50472dbba7 | |||
| ab713ba5bc | |||
| da3ce1d2dd |
@@ -1 +1,3 @@
|
|||||||
DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres
|
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/kairos
|
||||||
|
BETTER_AUTH_SECRET=your-secret-key-at-least-32-chars
|
||||||
|
BETTER_AUTH_URL=http://localhost:3000
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import { defineConfig } from 'drizzle-kit'
|
import { defineConfig } from 'drizzle-kit'
|
||||||
import { env } from '@/env'
|
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
out: './drizzle',
|
out: './drizzle',
|
||||||
schema: './src/server/db/schema/index.ts',
|
schema: './src/server/db/schema/index.ts',
|
||||||
dialect: 'postgresql',
|
dialect: 'postgresql',
|
||||||
dbCredentials: {
|
dbCredentials: {
|
||||||
url: env.DATABASE_URL,
|
url: process.env.DATABASE_URL!,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
CREATE TABLE "bookmark" (
|
||||||
|
"id" uuid PRIMARY KEY,
|
||||||
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"url" text NOT NULL,
|
||||||
|
"icon" text,
|
||||||
|
"category_id" uuid NOT NULL,
|
||||||
|
"is_public" boolean DEFAULT true NOT NULL,
|
||||||
|
"order_id" integer DEFAULT 0 NOT NULL,
|
||||||
|
"user_id" text NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "category" (
|
||||||
|
"id" uuid PRIMARY KEY,
|
||||||
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"is_pinned" boolean DEFAULT false NOT NULL,
|
||||||
|
"is_public" boolean DEFAULT true NOT NULL,
|
||||||
|
"order_id" integer DEFAULT 0 NOT NULL,
|
||||||
|
"user_id" text NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "account" (
|
||||||
|
"id" text PRIMARY KEY,
|
||||||
|
"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 with time zone,
|
||||||
|
"refresh_token_expires_at" timestamp with time zone,
|
||||||
|
"scope" text,
|
||||||
|
"password" text,
|
||||||
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "session" (
|
||||||
|
"id" text PRIMARY KEY,
|
||||||
|
"expires_at" timestamp with time zone NOT NULL,
|
||||||
|
"token" text NOT NULL UNIQUE,
|
||||||
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"ip_address" text,
|
||||||
|
"user_agent" text,
|
||||||
|
"user_id" text NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "user" (
|
||||||
|
"id" text PRIMARY KEY,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"email" text NOT NULL UNIQUE,
|
||||||
|
"email_verified" boolean DEFAULT false NOT NULL,
|
||||||
|
"image" text,
|
||||||
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE "verification" (
|
||||||
|
"id" text PRIMARY KEY,
|
||||||
|
"identifier" text NOT NULL,
|
||||||
|
"value" text NOT NULL,
|
||||||
|
"expires_at" timestamp with time zone NOT NULL,
|
||||||
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "bookmark" ADD CONSTRAINT "bookmark_category_id_category_id_fkey" FOREIGN KEY ("category_id") REFERENCES "category"("id") ON DELETE CASCADE;--> statement-breakpoint
|
||||||
|
ALTER TABLE "bookmark" ADD CONSTRAINT "bookmark_user_id_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE;--> statement-breakpoint
|
||||||
|
ALTER TABLE "category" ADD CONSTRAINT "category_user_id_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE;--> statement-breakpoint
|
||||||
|
ALTER TABLE "account" ADD CONSTRAINT "account_user_id_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE;--> statement-breakpoint
|
||||||
|
ALTER TABLE "session" ADD CONSTRAINT "session_user_id_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE CASCADE;
|
||||||
@@ -0,0 +1,852 @@
|
|||||||
|
{
|
||||||
|
"version": "8",
|
||||||
|
"dialect": "postgres",
|
||||||
|
"id": "1521f139-4e9c-4d3f-965b-c9cbe21f80ff",
|
||||||
|
"prevIds": ["00000000-0000-0000-0000-000000000000"],
|
||||||
|
"ddl": [
|
||||||
|
{
|
||||||
|
"isRlsEnabled": false,
|
||||||
|
"name": "bookmark",
|
||||||
|
"entityType": "tables",
|
||||||
|
"schema": "public"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isRlsEnabled": false,
|
||||||
|
"name": "category",
|
||||||
|
"entityType": "tables",
|
||||||
|
"schema": "public"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isRlsEnabled": false,
|
||||||
|
"name": "account",
|
||||||
|
"entityType": "tables",
|
||||||
|
"schema": "public"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isRlsEnabled": false,
|
||||||
|
"name": "session",
|
||||||
|
"entityType": "tables",
|
||||||
|
"schema": "public"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isRlsEnabled": false,
|
||||||
|
"name": "user",
|
||||||
|
"entityType": "tables",
|
||||||
|
"schema": "public"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"isRlsEnabled": false,
|
||||||
|
"name": "verification",
|
||||||
|
"entityType": "tables",
|
||||||
|
"schema": "public"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "uuid",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "created_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "updated_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "name",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "url",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "icon",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "uuid",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "category_id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "true",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "is_public",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "0",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "order_id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "user_id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "uuid",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "created_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "updated_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "name",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "false",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "is_pinned",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "true",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "is_public",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "0",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "order_id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "user_id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "account_id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "provider_id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "user_id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "access_token",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "refresh_token",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "id_token",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "access_token_expires_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "refresh_token_expires_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "scope",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "password",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "created_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "updated_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "expires_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "token",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "created_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "updated_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "ip_address",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "user_agent",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "user_id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "name",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "email",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "false",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "email_verified",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": false,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "image",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "created_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "updated_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "user"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "id",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "verification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "identifier",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "verification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "value",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "verification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": null,
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "expires_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "verification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "created_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "verification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "timestamp with time zone",
|
||||||
|
"typeSchema": null,
|
||||||
|
"notNull": true,
|
||||||
|
"dimensions": 0,
|
||||||
|
"default": "now()",
|
||||||
|
"generated": null,
|
||||||
|
"identity": null,
|
||||||
|
"name": "updated_at",
|
||||||
|
"entityType": "columns",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "verification"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nameExplicit": false,
|
||||||
|
"columns": ["category_id"],
|
||||||
|
"schemaTo": "public",
|
||||||
|
"tableTo": "category",
|
||||||
|
"columnsTo": ["id"],
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"name": "bookmark_category_id_category_id_fkey",
|
||||||
|
"entityType": "fks",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nameExplicit": false,
|
||||||
|
"columns": ["user_id"],
|
||||||
|
"schemaTo": "public",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsTo": ["id"],
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"name": "bookmark_user_id_user_id_fkey",
|
||||||
|
"entityType": "fks",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nameExplicit": false,
|
||||||
|
"columns": ["user_id"],
|
||||||
|
"schemaTo": "public",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsTo": ["id"],
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"name": "category_user_id_user_id_fkey",
|
||||||
|
"entityType": "fks",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "category"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nameExplicit": false,
|
||||||
|
"columns": ["user_id"],
|
||||||
|
"schemaTo": "public",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsTo": ["id"],
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"name": "account_user_id_user_id_fkey",
|
||||||
|
"entityType": "fks",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nameExplicit": false,
|
||||||
|
"columns": ["user_id"],
|
||||||
|
"schemaTo": "public",
|
||||||
|
"tableTo": "user",
|
||||||
|
"columnsTo": ["id"],
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"name": "session_user_id_user_id_fkey",
|
||||||
|
"entityType": "fks",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": ["id"],
|
||||||
|
"nameExplicit": false,
|
||||||
|
"name": "bookmark_pkey",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "bookmark",
|
||||||
|
"entityType": "pks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": ["id"],
|
||||||
|
"nameExplicit": false,
|
||||||
|
"name": "category_pkey",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "category",
|
||||||
|
"entityType": "pks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": ["id"],
|
||||||
|
"nameExplicit": false,
|
||||||
|
"name": "account_pkey",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "account",
|
||||||
|
"entityType": "pks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": ["id"],
|
||||||
|
"nameExplicit": false,
|
||||||
|
"name": "session_pkey",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session",
|
||||||
|
"entityType": "pks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": ["id"],
|
||||||
|
"nameExplicit": false,
|
||||||
|
"name": "user_pkey",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "user",
|
||||||
|
"entityType": "pks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"columns": ["id"],
|
||||||
|
"nameExplicit": false,
|
||||||
|
"name": "verification_pkey",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "verification",
|
||||||
|
"entityType": "pks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nameExplicit": false,
|
||||||
|
"columns": ["token"],
|
||||||
|
"nullsNotDistinct": false,
|
||||||
|
"name": "session_token_key",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "session",
|
||||||
|
"entityType": "uniques"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nameExplicit": false,
|
||||||
|
"columns": ["email"],
|
||||||
|
"nullsNotDistinct": false,
|
||||||
|
"name": "user_email_key",
|
||||||
|
"schema": "public",
|
||||||
|
"table": "user",
|
||||||
|
"entityType": "uniques"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"renames": []
|
||||||
|
}
|
||||||
@@ -38,6 +38,10 @@
|
|||||||
"postgres": "catalog:",
|
"postgres": "catalog:",
|
||||||
"react": "catalog:",
|
"react": "catalog:",
|
||||||
"react-dom": "catalog:",
|
"react-dom": "catalog:",
|
||||||
|
"@dnd-kit/dom": "catalog:",
|
||||||
|
"@dnd-kit/react": "catalog:",
|
||||||
|
"better-auth": "catalog:",
|
||||||
|
"lucide-react": "catalog:",
|
||||||
"uuid": "catalog:",
|
"uuid": "catalog:",
|
||||||
"zod": "catalog:"
|
"zod": "catalog:"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,25 +26,64 @@ const client: RouterClient = getORPCClient()
|
|||||||
|
|
||||||
export const orpc = createTanstackQueryUtils(client, {
|
export const orpc = createTanstackQueryUtils(client, {
|
||||||
experimental_defaults: {
|
experimental_defaults: {
|
||||||
todo: {
|
bookmarks: {
|
||||||
|
category: {
|
||||||
create: {
|
create: {
|
||||||
mutationOptions: {
|
mutationOptions: {
|
||||||
onSuccess: (_, __, ___, ctx) => {
|
onSuccess: (_, __, ___, ctx) => {
|
||||||
ctx.client.invalidateQueries({ queryKey: orpc.todo.list.key() })
|
ctx.client.invalidateQueries({ queryKey: orpc.bookmarks.category.list.key() })
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
update: {
|
update: {
|
||||||
mutationOptions: {
|
mutationOptions: {
|
||||||
onSuccess: (_, __, ___, ctx) => {
|
onSuccess: (_, __, ___, ctx) => {
|
||||||
ctx.client.invalidateQueries({ queryKey: orpc.todo.list.key() })
|
ctx.client.invalidateQueries({ queryKey: orpc.bookmarks.category.list.key() })
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
remove: {
|
remove: {
|
||||||
mutationOptions: {
|
mutationOptions: {
|
||||||
onSuccess: (_, __, ___, ctx) => {
|
onSuccess: (_, __, ___, ctx) => {
|
||||||
ctx.client.invalidateQueries({ queryKey: orpc.todo.list.key() })
|
ctx.client.invalidateQueries({ queryKey: orpc.bookmarks.category.list.key() })
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reorder: {
|
||||||
|
mutationOptions: {
|
||||||
|
onSuccess: (_, __, ___, ctx) => {
|
||||||
|
ctx.client.invalidateQueries({ queryKey: orpc.bookmarks.category.list.key() })
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
bookmark: {
|
||||||
|
create: {
|
||||||
|
mutationOptions: {
|
||||||
|
onSuccess: (_, __, ___, ctx) => {
|
||||||
|
ctx.client.invalidateQueries({ queryKey: orpc.bookmarks.category.list.key() })
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
mutationOptions: {
|
||||||
|
onSuccess: (_, __, ___, ctx) => {
|
||||||
|
ctx.client.invalidateQueries({ queryKey: orpc.bookmarks.category.list.key() })
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
remove: {
|
||||||
|
mutationOptions: {
|
||||||
|
onSuccess: (_, __, ___, ctx) => {
|
||||||
|
ctx.client.invalidateQueries({ queryKey: orpc.bookmarks.category.list.key() })
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reorder: {
|
||||||
|
mutationOptions: {
|
||||||
|
onSuccess: (_, __, ___, ctx) => {
|
||||||
|
ctx.client.invalidateQueries({ queryKey: orpc.bookmarks.category.list.key() })
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { z } from 'zod'
|
|||||||
export const env = createEnv({
|
export const env = createEnv({
|
||||||
server: {
|
server: {
|
||||||
DATABASE_URL: z.url(),
|
DATABASE_URL: z.url(),
|
||||||
|
BETTER_AUTH_SECRET: z.string().min(32),
|
||||||
|
BETTER_AUTH_URL: z.url(),
|
||||||
},
|
},
|
||||||
clientPrefix: 'VITE_',
|
clientPrefix: 'VITE_',
|
||||||
client: {
|
client: {
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import * as icons from 'lucide-react'
|
||||||
|
import { GripVertical, Pencil, Trash2 } from 'lucide-react'
|
||||||
|
|
||||||
|
const allIcons = icons as unknown as Record<string, React.ComponentType<{ className?: string }>>
|
||||||
|
|
||||||
|
interface BookmarkItemProps {
|
||||||
|
bookmark: {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
url: string
|
||||||
|
icon: string | null
|
||||||
|
}
|
||||||
|
onEdit: () => void
|
||||||
|
onDelete: () => void
|
||||||
|
handleRef?: (el: Element | null) => void
|
||||||
|
sortableRef?: (el: Element | null) => void
|
||||||
|
isDragging?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const BookmarkItem = ({ bookmark, onEdit, onDelete, handleRef, sortableRef, isDragging }: BookmarkItemProps) => {
|
||||||
|
const Icon = (bookmark.icon && allIcons[bookmark.icon]) || icons.Globe
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={sortableRef}
|
||||||
|
className={`group flex items-center gap-3 rounded-lg px-3 py-2 transition-all hover:bg-slate-50 ${
|
||||||
|
isDragging ? 'opacity-50' : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div ref={handleRef} className="cursor-grab text-slate-300 hover:text-slate-500 active:cursor-grabbing">
|
||||||
|
<GripVertical className="h-4 w-4" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg bg-slate-100">
|
||||||
|
<Icon className="h-4 w-4 text-slate-600" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href={bookmark.url} target="_blank" rel="noopener noreferrer" className="flex-1 min-w-0">
|
||||||
|
<p className="text-sm font-medium text-slate-700 truncate">{bookmark.name}</p>
|
||||||
|
<p className="text-xs text-slate-400 truncate">{bookmark.url}</p>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onEdit}
|
||||||
|
className="p-1.5 text-slate-400 hover:text-slate-600 hover:bg-slate-100 rounded-md transition-colors"
|
||||||
|
>
|
||||||
|
<Pencil className="h-3.5 w-3.5" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onDelete}
|
||||||
|
className="p-1.5 text-slate-400 hover:text-red-500 hover:bg-red-50 rounded-md transition-colors"
|
||||||
|
>
|
||||||
|
<Trash2 className="h-3.5 w-3.5" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,332 @@
|
|||||||
|
import { DragDropProvider } from '@dnd-kit/react'
|
||||||
|
import { useSortable } from '@dnd-kit/react/sortable'
|
||||||
|
import { useMutation } from '@tanstack/react-query'
|
||||||
|
import { FolderOpen, MoreHorizontal, Pencil, Plus, Trash2, X } from 'lucide-react'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { orpc } from '@/client/orpc'
|
||||||
|
import { BookmarkItem } from './BookmarkItem'
|
||||||
|
import { IconPicker } from './IconPicker'
|
||||||
|
|
||||||
|
interface Bookmark {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
url: string
|
||||||
|
icon: string | null
|
||||||
|
orderId: number
|
||||||
|
categoryId: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Category {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
orderId: number
|
||||||
|
bookmarks: Bookmark[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CategorySectionProps {
|
||||||
|
category: Category
|
||||||
|
}
|
||||||
|
|
||||||
|
const SortableBookmark = ({
|
||||||
|
bookmark,
|
||||||
|
index,
|
||||||
|
groupId,
|
||||||
|
onEdit,
|
||||||
|
onDelete,
|
||||||
|
}: {
|
||||||
|
bookmark: Bookmark
|
||||||
|
index: number
|
||||||
|
groupId: string
|
||||||
|
onEdit: () => void
|
||||||
|
onDelete: () => void
|
||||||
|
}) => {
|
||||||
|
const { ref, handleRef, isDragging } = useSortable({
|
||||||
|
id: bookmark.id,
|
||||||
|
index,
|
||||||
|
group: groupId,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BookmarkItem
|
||||||
|
bookmark={bookmark}
|
||||||
|
onEdit={onEdit}
|
||||||
|
onDelete={onDelete}
|
||||||
|
sortableRef={ref}
|
||||||
|
handleRef={handleRef}
|
||||||
|
isDragging={isDragging}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CategorySection = ({ category }: CategorySectionProps) => {
|
||||||
|
const [showAddForm, setShowAddForm] = useState(false)
|
||||||
|
const [editingName, setEditingName] = useState(false)
|
||||||
|
const [categoryName, setCategoryName] = useState(category.name)
|
||||||
|
const [newBookmark, setNewBookmark] = useState({ name: '', url: '', icon: '' })
|
||||||
|
const [showIconPicker, setShowIconPicker] = useState(false)
|
||||||
|
const [showMenu, setShowMenu] = useState(false)
|
||||||
|
const [editingBookmark, setEditingBookmark] = useState<Bookmark | null>(null)
|
||||||
|
const [editForm, setEditForm] = useState({ name: '', url: '', icon: '' })
|
||||||
|
const [showEditIconPicker, setShowEditIconPicker] = useState(false)
|
||||||
|
const [items, setItems] = useState(category.bookmarks)
|
||||||
|
|
||||||
|
const updateCategory = useMutation(orpc.bookmarks.category.update.mutationOptions())
|
||||||
|
const deleteCategory = useMutation(orpc.bookmarks.category.remove.mutationOptions())
|
||||||
|
const createBookmark = useMutation(orpc.bookmarks.bookmark.create.mutationOptions())
|
||||||
|
const updateBookmark = useMutation(orpc.bookmarks.bookmark.update.mutationOptions())
|
||||||
|
const deleteBookmark = useMutation(orpc.bookmarks.bookmark.remove.mutationOptions())
|
||||||
|
const reorderBookmarks = useMutation(orpc.bookmarks.bookmark.reorder.mutationOptions())
|
||||||
|
|
||||||
|
if (items !== category.bookmarks && !reorderBookmarks.isPending) {
|
||||||
|
setItems(category.bookmarks)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSaveCategoryName = () => {
|
||||||
|
if (categoryName.trim() && categoryName !== category.name) {
|
||||||
|
updateCategory.mutate({ id: category.id, data: { name: categoryName.trim() } })
|
||||||
|
}
|
||||||
|
setEditingName(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAddBookmark = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault()
|
||||||
|
if (newBookmark.name.trim() && newBookmark.url.trim()) {
|
||||||
|
createBookmark.mutate({
|
||||||
|
name: newBookmark.name.trim(),
|
||||||
|
url: newBookmark.url.trim(),
|
||||||
|
icon: newBookmark.icon || null,
|
||||||
|
categoryId: category.id,
|
||||||
|
orderId: category.bookmarks.length,
|
||||||
|
})
|
||||||
|
setNewBookmark({ name: '', url: '', icon: '' })
|
||||||
|
setShowAddForm(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEditBookmark = (bm: Bookmark) => {
|
||||||
|
setEditingBookmark(bm)
|
||||||
|
setEditForm({ name: bm.name, url: bm.url, icon: bm.icon ?? '' })
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSaveEditBookmark = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault()
|
||||||
|
if (editingBookmark && editForm.name.trim() && editForm.url.trim()) {
|
||||||
|
updateBookmark.mutate({
|
||||||
|
id: editingBookmark.id,
|
||||||
|
data: {
|
||||||
|
name: editForm.name.trim(),
|
||||||
|
url: editForm.url.trim(),
|
||||||
|
icon: editForm.icon || null,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
setEditingBookmark(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDragEnd: NonNullable<React.ComponentProps<typeof DragDropProvider>['onDragEnd']> = (event) => {
|
||||||
|
if (event.canceled) return
|
||||||
|
const sourceId = event.operation.source?.id
|
||||||
|
const targetId = event.operation.target?.id
|
||||||
|
if (!sourceId || !targetId || sourceId === targetId) return
|
||||||
|
|
||||||
|
const oldIndex = items.findIndex((b) => b.id === sourceId)
|
||||||
|
const newIndex = items.findIndex((b) => b.id === targetId)
|
||||||
|
if (oldIndex === -1 || newIndex === -1) return
|
||||||
|
|
||||||
|
const reordered = [...items]
|
||||||
|
const [moved] = reordered.splice(oldIndex, 1)
|
||||||
|
if (!moved) return
|
||||||
|
reordered.splice(newIndex, 0, moved)
|
||||||
|
setItems(reordered)
|
||||||
|
|
||||||
|
reorderBookmarks.mutate(reordered.map((b, i) => ({ id: b.id, orderId: i })))
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="rounded-2xl bg-white ring-1 ring-slate-100 shadow-sm overflow-hidden">
|
||||||
|
<div className="flex items-center justify-between px-4 py-3 border-b border-slate-100">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<FolderOpen className="h-4 w-4 text-indigo-500" />
|
||||||
|
{editingName ? (
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={categoryName}
|
||||||
|
onChange={(e) => setCategoryName(e.target.value)}
|
||||||
|
onBlur={handleSaveCategoryName}
|
||||||
|
onKeyDown={(e) => e.key === 'Enter' && handleSaveCategoryName()}
|
||||||
|
className="px-2 py-0.5 text-sm font-semibold text-slate-900 bg-slate-50 rounded-md ring-1 ring-indigo-300 outline-none"
|
||||||
|
// biome-ignore lint/a11y/noAutofocus: inline edit needs immediate focus
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<h3 className="text-sm font-semibold text-slate-900">{category.name}</h3>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="relative">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowMenu(!showMenu)}
|
||||||
|
className="p-1.5 text-slate-400 hover:text-slate-600 hover:bg-slate-100 rounded-md transition-colors"
|
||||||
|
>
|
||||||
|
<MoreHorizontal className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
{showMenu && (
|
||||||
|
<div className="absolute right-0 z-40 mt-1 w-32 rounded-lg bg-white py-1 shadow-lg ring-1 ring-slate-200">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
setEditingName(true)
|
||||||
|
setShowMenu(false)
|
||||||
|
}}
|
||||||
|
className="flex w-full items-center gap-2 px-3 py-2 text-sm text-slate-700 hover:bg-slate-50"
|
||||||
|
>
|
||||||
|
<Pencil className="h-3.5 w-3.5" /> 重命名
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
deleteCategory.mutate({ id: category.id })
|
||||||
|
setShowMenu(false)
|
||||||
|
}}
|
||||||
|
className="flex w-full items-center gap-2 px-3 py-2 text-sm text-red-600 hover:bg-red-50"
|
||||||
|
>
|
||||||
|
<Trash2 className="h-3.5 w-3.5" /> 删除
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-2">
|
||||||
|
<DragDropProvider onDragEnd={handleDragEnd}>
|
||||||
|
{items.map((bm, idx) => (
|
||||||
|
<SortableBookmark
|
||||||
|
key={bm.id}
|
||||||
|
bookmark={bm}
|
||||||
|
index={idx}
|
||||||
|
groupId={category.id}
|
||||||
|
onEdit={() => handleEditBookmark(bm)}
|
||||||
|
onDelete={() => deleteBookmark.mutate({ id: bm.id })}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</DragDropProvider>
|
||||||
|
|
||||||
|
{items.length === 0 && !showAddForm && <p className="py-4 text-center text-sm text-slate-400">暂无书签</p>}
|
||||||
|
|
||||||
|
{editingBookmark && (
|
||||||
|
<form onSubmit={handleSaveEditBookmark} className="mx-2 mt-2 space-y-2 rounded-lg bg-slate-50 p-3">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-xs font-medium text-slate-500">编辑书签</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setEditingBookmark(null)}
|
||||||
|
className="text-slate-400 hover:text-slate-600"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={editForm.name}
|
||||||
|
onChange={(e) => setEditForm((p) => ({ ...p, name: e.target.value }))}
|
||||||
|
placeholder="名称"
|
||||||
|
className="w-full rounded-lg bg-white px-3 py-2 text-sm ring-1 ring-slate-200 outline-none focus:ring-2 focus:ring-indigo-500/50"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="url"
|
||||||
|
value={editForm.url}
|
||||||
|
onChange={(e) => setEditForm((p) => ({ ...p, url: e.target.value }))}
|
||||||
|
placeholder="URL"
|
||||||
|
className="w-full rounded-lg bg-white px-3 py-2 text-sm ring-1 ring-slate-200 outline-none focus:ring-2 focus:ring-indigo-500/50"
|
||||||
|
/>
|
||||||
|
<div className="relative">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowEditIconPicker(!showEditIconPicker)}
|
||||||
|
className="rounded-lg bg-white px-3 py-2 text-sm ring-1 ring-slate-200 hover:bg-slate-50"
|
||||||
|
>
|
||||||
|
{editForm.icon || '选择图标'}
|
||||||
|
</button>
|
||||||
|
{showEditIconPicker && (
|
||||||
|
<IconPicker
|
||||||
|
value={editForm.icon}
|
||||||
|
onChange={(icon) => setEditForm((p) => ({ ...p, icon }))}
|
||||||
|
onClose={() => setShowEditIconPicker(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
className="w-full rounded-lg bg-indigo-600 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700 transition-colors"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{showAddForm ? (
|
||||||
|
<form onSubmit={handleAddBookmark} className="mx-2 mt-2 space-y-2 rounded-lg bg-slate-50 p-3">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-xs font-medium text-slate-500">添加书签</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowAddForm(false)}
|
||||||
|
className="text-slate-400 hover:text-slate-600"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={newBookmark.name}
|
||||||
|
onChange={(e) => setNewBookmark((p) => ({ ...p, name: e.target.value }))}
|
||||||
|
placeholder="名称"
|
||||||
|
required
|
||||||
|
className="w-full rounded-lg bg-white px-3 py-2 text-sm ring-1 ring-slate-200 outline-none focus:ring-2 focus:ring-indigo-500/50"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="url"
|
||||||
|
value={newBookmark.url}
|
||||||
|
onChange={(e) => setNewBookmark((p) => ({ ...p, url: e.target.value }))}
|
||||||
|
placeholder="https://example.com"
|
||||||
|
required
|
||||||
|
className="w-full rounded-lg bg-white px-3 py-2 text-sm ring-1 ring-slate-200 outline-none focus:ring-2 focus:ring-indigo-500/50"
|
||||||
|
/>
|
||||||
|
<div className="relative">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowIconPicker(!showIconPicker)}
|
||||||
|
className="rounded-lg bg-white px-3 py-2 text-sm ring-1 ring-slate-200 hover:bg-slate-50"
|
||||||
|
>
|
||||||
|
{newBookmark.icon || '选择图标'}
|
||||||
|
</button>
|
||||||
|
{showIconPicker && (
|
||||||
|
<IconPicker
|
||||||
|
value={newBookmark.icon}
|
||||||
|
onChange={(icon) => setNewBookmark((p) => ({ ...p, icon }))}
|
||||||
|
onClose={() => setShowIconPicker(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={createBookmark.isPending}
|
||||||
|
className="w-full rounded-lg bg-indigo-600 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700 disabled:opacity-50 transition-colors"
|
||||||
|
>
|
||||||
|
{createBookmark.isPending ? '添加中...' : '添加'}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowAddForm(true)}
|
||||||
|
className="mx-2 mt-1 flex w-[calc(100%-1rem)] items-center justify-center gap-1 rounded-lg py-2 text-sm text-slate-400 hover:bg-slate-50 hover:text-slate-600 transition-colors"
|
||||||
|
>
|
||||||
|
<Plus className="h-4 w-4" /> 添加书签
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
|
const getGreeting = (hour: number): string => {
|
||||||
|
if (hour >= 5 && hour < 12) return '早上好'
|
||||||
|
if (hour >= 12 && hour < 14) return '中午好'
|
||||||
|
if (hour >= 14 && hour < 18) return '下午好'
|
||||||
|
return '晚上好'
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatDate = (date: Date): string => {
|
||||||
|
const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
|
||||||
|
const year = date.getFullYear()
|
||||||
|
const month = date.getMonth() + 1
|
||||||
|
const day = date.getDate()
|
||||||
|
const weekday = weekdays[date.getDay()]
|
||||||
|
return `${year}年${month}月${day}日 ${weekday}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GreetingHeader = () => {
|
||||||
|
const [now, setNow] = useState(() => new Date())
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timer = setInterval(() => setNow(new Date()), 60_000)
|
||||||
|
return () => clearInterval(timer)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-1">
|
||||||
|
<h2 className="text-3xl font-bold text-slate-900 tracking-tight">{getGreeting(now.getHours())}</h2>
|
||||||
|
<p className="text-slate-500">{formatDate(now)}</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
import * as icons from 'lucide-react'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
const ICON_NAMES = [
|
||||||
|
'Globe',
|
||||||
|
'Home',
|
||||||
|
'Code',
|
||||||
|
'Database',
|
||||||
|
'Mail',
|
||||||
|
'MessageSquare',
|
||||||
|
'Music',
|
||||||
|
'Video',
|
||||||
|
'Image',
|
||||||
|
'FileText',
|
||||||
|
'Folder',
|
||||||
|
'Star',
|
||||||
|
'Heart',
|
||||||
|
'Bookmark',
|
||||||
|
'Search',
|
||||||
|
'Settings',
|
||||||
|
'User',
|
||||||
|
'Shield',
|
||||||
|
'Key',
|
||||||
|
'Terminal',
|
||||||
|
'Github',
|
||||||
|
'Chrome',
|
||||||
|
'Cpu',
|
||||||
|
'Server',
|
||||||
|
'Cloud',
|
||||||
|
'Wifi',
|
||||||
|
'Zap',
|
||||||
|
'Coffee',
|
||||||
|
'BookOpen',
|
||||||
|
'Briefcase',
|
||||||
|
'Calendar',
|
||||||
|
'Clock',
|
||||||
|
'Download',
|
||||||
|
'Edit',
|
||||||
|
'ExternalLink',
|
||||||
|
'Eye',
|
||||||
|
'Film',
|
||||||
|
'Gift',
|
||||||
|
'Headphones',
|
||||||
|
'Layout',
|
||||||
|
'Link',
|
||||||
|
'Map',
|
||||||
|
'Monitor',
|
||||||
|
'Package',
|
||||||
|
'Phone',
|
||||||
|
'ShoppingCart',
|
||||||
|
'Smartphone',
|
||||||
|
'Tv',
|
||||||
|
'Upload',
|
||||||
|
'Box',
|
||||||
|
'Compass',
|
||||||
|
'Rss',
|
||||||
|
'Camera',
|
||||||
|
'Printer',
|
||||||
|
'Layers',
|
||||||
|
'Activity',
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const allIcons = icons as unknown as Record<string, React.ComponentType<{ className?: string }>>
|
||||||
|
|
||||||
|
interface IconPickerProps {
|
||||||
|
value?: string | null
|
||||||
|
onChange: (iconName: string) => void
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const IconPicker = ({ value, onChange, onClose }: IconPickerProps) => {
|
||||||
|
const [filter, setFilter] = useState('')
|
||||||
|
|
||||||
|
const filtered = ICON_NAMES.filter((name) => name.toLowerCase().includes(filter.toLowerCase()))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="absolute z-50 mt-1 w-72 rounded-xl bg-white p-3 shadow-lg ring-1 ring-slate-200">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={filter}
|
||||||
|
onChange={(e) => setFilter(e.target.value)}
|
||||||
|
placeholder="搜索图标..."
|
||||||
|
className="mb-2 w-full rounded-lg bg-slate-50 px-3 py-2 text-sm ring-1 ring-slate-200 outline-none focus:ring-2 focus:ring-indigo-500/50"
|
||||||
|
// biome-ignore lint/a11y/noAutofocus: icon picker search needs immediate focus
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
<div className="grid max-h-48 grid-cols-8 gap-1 overflow-y-auto">
|
||||||
|
{filtered.map((name) => {
|
||||||
|
const Icon = allIcons[name]
|
||||||
|
if (!Icon) return null
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={name}
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
onChange(name)
|
||||||
|
onClose()
|
||||||
|
}}
|
||||||
|
className={`flex h-8 w-8 items-center justify-center rounded-lg transition-colors ${
|
||||||
|
value === name ? 'bg-indigo-100 text-indigo-600' : 'hover:bg-slate-100 text-slate-600'
|
||||||
|
}`}
|
||||||
|
title={name}
|
||||||
|
>
|
||||||
|
<Icon className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
{filtered.length === 0 && <p className="py-4 text-center text-sm text-slate-400">未找到匹配图标</p>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { Search } from 'lucide-react'
|
||||||
|
import type { FormEvent } from 'react'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
const SEARCH_ENGINES: Record<string, string> = {
|
||||||
|
g: 'https://google.com/search?q=',
|
||||||
|
d: 'https://duckduckgo.com/?q=',
|
||||||
|
b: 'https://bing.com/search?q=',
|
||||||
|
gh: 'https://github.com/search?q=',
|
||||||
|
yt: 'https://youtube.com/results?search_query=',
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_ENGINE = 'https://google.com/search?q='
|
||||||
|
|
||||||
|
const parseSearchQuery = (raw: string): string => {
|
||||||
|
const trimmed = raw.trim()
|
||||||
|
if (!trimmed) return ''
|
||||||
|
|
||||||
|
if (/^https?:\/\//i.test(trimmed) || /^[^\s]+\.[^\s]+$/.test(trimmed)) {
|
||||||
|
return trimmed.startsWith('http') ? trimmed : `https://${trimmed}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = trimmed.match(/^\/(\w+)\s+(.+)$/)
|
||||||
|
if (match) {
|
||||||
|
const prefix = match[1]?.toLowerCase() ?? ''
|
||||||
|
const query = match[2] ?? ''
|
||||||
|
const engine = SEARCH_ENGINES[prefix]
|
||||||
|
if (engine) return `${engine}${encodeURIComponent(query)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${DEFAULT_ENGINE}${encodeURIComponent(trimmed)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SearchBar = () => {
|
||||||
|
const [query, setQuery] = useState('')
|
||||||
|
|
||||||
|
const handleSubmit = (e: FormEvent) => {
|
||||||
|
e.preventDefault()
|
||||||
|
const url = parseSearchQuery(query)
|
||||||
|
if (url) {
|
||||||
|
window.location.href = url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form onSubmit={handleSubmit} className="w-full">
|
||||||
|
<div className="relative">
|
||||||
|
<Search className="absolute left-4 top-1/2 h-5 w-5 -translate-y-1/2 text-slate-400" />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={query}
|
||||||
|
onChange={(e) => setQuery(e.target.value)}
|
||||||
|
placeholder="搜索或输入 URL · /g Google · /gh GitHub · /yt YouTube"
|
||||||
|
className="w-full rounded-2xl bg-white py-4 pl-12 pr-6 shadow-[0_8px_30px_rgb(0,0,0,0.04)] ring-1 ring-slate-100 outline-none transition-all placeholder:text-slate-400 text-lg text-slate-700 focus:ring-2 focus:ring-indigo-500/50"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { oc } from '@orpc/contract'
|
||||||
|
import { createInsertSchema, createSelectSchema, createUpdateSchema } from 'drizzle-orm/zod'
|
||||||
|
import { z } from 'zod'
|
||||||
|
import { bookmarkTable, categoryTable } from '@/modules/bookmarks/schema'
|
||||||
|
import { generatedFieldKeys } from '@/server/db/fields'
|
||||||
|
|
||||||
|
const categorySelect = createSelectSchema(categoryTable)
|
||||||
|
const categoryInsert = createInsertSchema(categoryTable).omit(generatedFieldKeys).omit({ userId: true })
|
||||||
|
const categoryUpdate = createUpdateSchema(categoryTable).omit(generatedFieldKeys).omit({ userId: true })
|
||||||
|
|
||||||
|
const bookmarkSelect = createSelectSchema(bookmarkTable)
|
||||||
|
const bookmarkInsert = createInsertSchema(bookmarkTable).omit(generatedFieldKeys).omit({ userId: true })
|
||||||
|
const bookmarkUpdate = createUpdateSchema(bookmarkTable).omit(generatedFieldKeys).omit({ userId: true })
|
||||||
|
|
||||||
|
export const category = {
|
||||||
|
list: oc.input(z.void()).output(z.array(categorySelect.extend({ bookmarks: z.array(bookmarkSelect) }))),
|
||||||
|
|
||||||
|
create: oc.input(categoryInsert).output(categorySelect),
|
||||||
|
|
||||||
|
update: oc.input(z.object({ id: z.uuid(), data: categoryUpdate })).output(categorySelect),
|
||||||
|
|
||||||
|
remove: oc.input(z.object({ id: z.uuid() })).output(z.void()),
|
||||||
|
|
||||||
|
reorder: oc.input(z.array(z.object({ id: z.uuid(), orderId: z.number().int() }))).output(z.void()),
|
||||||
|
}
|
||||||
|
|
||||||
|
export const bookmark = {
|
||||||
|
create: oc.input(bookmarkInsert).output(bookmarkSelect),
|
||||||
|
|
||||||
|
update: oc.input(z.object({ id: z.uuid(), data: bookmarkUpdate })).output(bookmarkSelect),
|
||||||
|
|
||||||
|
remove: oc.input(z.object({ id: z.uuid() })).output(z.void()),
|
||||||
|
|
||||||
|
reorder: oc.input(z.array(z.object({ id: z.uuid(), orderId: z.number().int() }))).output(z.void()),
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import type { ModuleMetadata } from '../registry'
|
||||||
|
|
||||||
|
export const bookmarksModule: ModuleMetadata = {
|
||||||
|
id: 'bookmarks',
|
||||||
|
name: '书签导航',
|
||||||
|
description: '常用链接和网站的快速导航',
|
||||||
|
icon: 'Compass',
|
||||||
|
route: '/bookmarks',
|
||||||
|
enabled: true,
|
||||||
|
}
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
import { ORPCError } from '@orpc/server'
|
||||||
|
import { and, eq } from 'drizzle-orm'
|
||||||
|
import { bookmarkTable, categoryTable } from '@/modules/bookmarks/schema'
|
||||||
|
import { authMiddleware, db } from '@/server/api/middlewares'
|
||||||
|
import { os } from '@/server/api/server'
|
||||||
|
|
||||||
|
export const category = {
|
||||||
|
list: os.bookmarks.category.list
|
||||||
|
.use(db)
|
||||||
|
.use(authMiddleware)
|
||||||
|
.handler(async ({ context }) => {
|
||||||
|
return await context.db.query.categoryTable.findMany({
|
||||||
|
where: { userId: context.user.id },
|
||||||
|
orderBy: { orderId: 'asc' },
|
||||||
|
with: {
|
||||||
|
bookmarks: {
|
||||||
|
orderBy: { orderId: 'asc' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
|
||||||
|
create: os.bookmarks.category.create
|
||||||
|
.use(db)
|
||||||
|
.use(authMiddleware)
|
||||||
|
.handler(async ({ context, input }) => {
|
||||||
|
const [created] = await context.db
|
||||||
|
.insert(categoryTable)
|
||||||
|
.values({ ...input, userId: context.user.id })
|
||||||
|
.returning()
|
||||||
|
if (!created) throw new ORPCError('INTERNAL_SERVER_ERROR', { message: 'Failed to create category' })
|
||||||
|
return created
|
||||||
|
}),
|
||||||
|
|
||||||
|
update: os.bookmarks.category.update
|
||||||
|
.use(db)
|
||||||
|
.use(authMiddleware)
|
||||||
|
.handler(async ({ context, input }) => {
|
||||||
|
const [updated] = await context.db
|
||||||
|
.update(categoryTable)
|
||||||
|
.set(input.data)
|
||||||
|
.where(and(eq(categoryTable.id, input.id), eq(categoryTable.userId, context.user.id)))
|
||||||
|
.returning()
|
||||||
|
if (!updated) throw new ORPCError('NOT_FOUND')
|
||||||
|
return updated
|
||||||
|
}),
|
||||||
|
|
||||||
|
remove: os.bookmarks.category.remove
|
||||||
|
.use(db)
|
||||||
|
.use(authMiddleware)
|
||||||
|
.handler(async ({ context, input }) => {
|
||||||
|
const [deleted] = await context.db
|
||||||
|
.delete(categoryTable)
|
||||||
|
.where(and(eq(categoryTable.id, input.id), eq(categoryTable.userId, context.user.id)))
|
||||||
|
.returning({ id: categoryTable.id })
|
||||||
|
if (!deleted) throw new ORPCError('NOT_FOUND')
|
||||||
|
}),
|
||||||
|
|
||||||
|
reorder: os.bookmarks.category.reorder
|
||||||
|
.use(db)
|
||||||
|
.use(authMiddleware)
|
||||||
|
.handler(async ({ context, input }) => {
|
||||||
|
await context.db.transaction(async (tx) => {
|
||||||
|
for (const item of input) {
|
||||||
|
await tx
|
||||||
|
.update(categoryTable)
|
||||||
|
.set({ orderId: item.orderId })
|
||||||
|
.where(and(eq(categoryTable.id, item.id), eq(categoryTable.userId, context.user.id)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
export const bookmark = {
|
||||||
|
create: os.bookmarks.bookmark.create
|
||||||
|
.use(db)
|
||||||
|
.use(authMiddleware)
|
||||||
|
.handler(async ({ context, input }) => {
|
||||||
|
const [created] = await context.db
|
||||||
|
.insert(bookmarkTable)
|
||||||
|
.values({ ...input, userId: context.user.id })
|
||||||
|
.returning()
|
||||||
|
if (!created) throw new ORPCError('INTERNAL_SERVER_ERROR', { message: 'Failed to create bookmark' })
|
||||||
|
return created
|
||||||
|
}),
|
||||||
|
|
||||||
|
update: os.bookmarks.bookmark.update
|
||||||
|
.use(db)
|
||||||
|
.use(authMiddleware)
|
||||||
|
.handler(async ({ context, input }) => {
|
||||||
|
const [updated] = await context.db
|
||||||
|
.update(bookmarkTable)
|
||||||
|
.set(input.data)
|
||||||
|
.where(and(eq(bookmarkTable.id, input.id), eq(bookmarkTable.userId, context.user.id)))
|
||||||
|
.returning()
|
||||||
|
if (!updated) throw new ORPCError('NOT_FOUND')
|
||||||
|
return updated
|
||||||
|
}),
|
||||||
|
|
||||||
|
remove: os.bookmarks.bookmark.remove
|
||||||
|
.use(db)
|
||||||
|
.use(authMiddleware)
|
||||||
|
.handler(async ({ context, input }) => {
|
||||||
|
const [deleted] = await context.db
|
||||||
|
.delete(bookmarkTable)
|
||||||
|
.where(and(eq(bookmarkTable.id, input.id), eq(bookmarkTable.userId, context.user.id)))
|
||||||
|
.returning({ id: bookmarkTable.id })
|
||||||
|
if (!deleted) throw new ORPCError('NOT_FOUND')
|
||||||
|
}),
|
||||||
|
|
||||||
|
reorder: os.bookmarks.bookmark.reorder
|
||||||
|
.use(db)
|
||||||
|
.use(authMiddleware)
|
||||||
|
.handler(async ({ context, input }) => {
|
||||||
|
await context.db.transaction(async (tx) => {
|
||||||
|
for (const item of input) {
|
||||||
|
await tx
|
||||||
|
.update(bookmarkTable)
|
||||||
|
.set({ orderId: item.orderId })
|
||||||
|
.where(and(eq(bookmarkTable.id, item.id), eq(bookmarkTable.userId, context.user.id)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { boolean, integer, pgTable, text, uuid } from 'drizzle-orm/pg-core'
|
||||||
|
import { userTable } from '../../server/auth/schema'
|
||||||
|
import { generatedFields } from '../../server/db/fields'
|
||||||
|
|
||||||
|
export const categoryTable = pgTable('category', {
|
||||||
|
...generatedFields,
|
||||||
|
name: text('name').notNull(),
|
||||||
|
isPinned: boolean('is_pinned').notNull().default(false),
|
||||||
|
isPublic: boolean('is_public').notNull().default(true),
|
||||||
|
orderId: integer('order_id').notNull().default(0),
|
||||||
|
userId: text('user_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => userTable.id, { onDelete: 'cascade' }),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const bookmarkTable = pgTable('bookmark', {
|
||||||
|
...generatedFields,
|
||||||
|
name: text('name').notNull(),
|
||||||
|
url: text('url').notNull(),
|
||||||
|
icon: text('icon'),
|
||||||
|
categoryId: uuid('category_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => categoryTable.id, { onDelete: 'cascade' }),
|
||||||
|
isPublic: boolean('is_public').notNull().default(true),
|
||||||
|
orderId: integer('order_id').notNull().default(0),
|
||||||
|
userId: text('user_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => userTable.id, { onDelete: 'cascade' }),
|
||||||
|
})
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { bookmarksModule } from './bookmarks'
|
||||||
|
|
||||||
|
export interface ModuleMetadata {
|
||||||
|
id: string
|
||||||
|
name: string
|
||||||
|
description: string
|
||||||
|
icon: string
|
||||||
|
route: string
|
||||||
|
enabled: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const modules: ModuleMetadata[] = [bookmarksModule]
|
||||||
@@ -9,15 +9,34 @@
|
|||||||
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified.
|
||||||
|
|
||||||
import { Route as rootRouteImport } from './routes/__root'
|
import { Route as rootRouteImport } from './routes/__root'
|
||||||
import { Route as IndexRouteImport } from './routes/index'
|
import { Route as SignupRouteImport } from './routes/signup'
|
||||||
|
import { Route as LoginRouteImport } from './routes/login'
|
||||||
|
import { Route as ProtectedRouteImport } from './routes/_protected'
|
||||||
|
import { Route as ProtectedIndexRouteImport } from './routes/_protected/index'
|
||||||
import { Route as ApiHealthRouteImport } from './routes/api/health'
|
import { Route as ApiHealthRouteImport } from './routes/api/health'
|
||||||
import { Route as ApiSplatRouteImport } from './routes/api/$'
|
import { Route as ApiSplatRouteImport } from './routes/api/$'
|
||||||
|
import { Route as ProtectedBookmarksIndexRouteImport } from './routes/_protected/bookmarks/index'
|
||||||
import { Route as ApiRpcSplatRouteImport } from './routes/api/rpc.$'
|
import { Route as ApiRpcSplatRouteImport } from './routes/api/rpc.$'
|
||||||
|
import { Route as ApiAuthSplatRouteImport } from './routes/api/auth.$'
|
||||||
|
|
||||||
const IndexRoute = IndexRouteImport.update({
|
const SignupRoute = SignupRouteImport.update({
|
||||||
|
id: '/signup',
|
||||||
|
path: '/signup',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
|
const LoginRoute = LoginRouteImport.update({
|
||||||
|
id: '/login',
|
||||||
|
path: '/login',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
|
const ProtectedRoute = ProtectedRouteImport.update({
|
||||||
|
id: '/_protected',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
|
const ProtectedIndexRoute = ProtectedIndexRouteImport.update({
|
||||||
id: '/',
|
id: '/',
|
||||||
path: '/',
|
path: '/',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => ProtectedRoute,
|
||||||
} as any)
|
} as any)
|
||||||
const ApiHealthRoute = ApiHealthRouteImport.update({
|
const ApiHealthRoute = ApiHealthRouteImport.update({
|
||||||
id: '/api/health',
|
id: '/api/health',
|
||||||
@@ -29,54 +48,127 @@ const ApiSplatRoute = ApiSplatRouteImport.update({
|
|||||||
path: '/api/$',
|
path: '/api/$',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const ProtectedBookmarksIndexRoute = ProtectedBookmarksIndexRouteImport.update({
|
||||||
|
id: '/bookmarks/',
|
||||||
|
path: '/bookmarks/',
|
||||||
|
getParentRoute: () => ProtectedRoute,
|
||||||
|
} as any)
|
||||||
const ApiRpcSplatRoute = ApiRpcSplatRouteImport.update({
|
const ApiRpcSplatRoute = ApiRpcSplatRouteImport.update({
|
||||||
id: '/api/rpc/$',
|
id: '/api/rpc/$',
|
||||||
path: '/api/rpc/$',
|
path: '/api/rpc/$',
|
||||||
getParentRoute: () => rootRouteImport,
|
getParentRoute: () => rootRouteImport,
|
||||||
} as any)
|
} as any)
|
||||||
|
const ApiAuthSplatRoute = ApiAuthSplatRouteImport.update({
|
||||||
|
id: '/api/auth/$',
|
||||||
|
path: '/api/auth/$',
|
||||||
|
getParentRoute: () => rootRouteImport,
|
||||||
|
} as any)
|
||||||
|
|
||||||
export interface FileRoutesByFullPath {
|
export interface FileRoutesByFullPath {
|
||||||
'/': typeof IndexRoute
|
'/': typeof ProtectedIndexRoute
|
||||||
|
'/login': typeof LoginRoute
|
||||||
|
'/signup': typeof SignupRoute
|
||||||
'/api/$': typeof ApiSplatRoute
|
'/api/$': typeof ApiSplatRoute
|
||||||
'/api/health': typeof ApiHealthRoute
|
'/api/health': typeof ApiHealthRoute
|
||||||
|
'/api/auth/$': typeof ApiAuthSplatRoute
|
||||||
'/api/rpc/$': typeof ApiRpcSplatRoute
|
'/api/rpc/$': typeof ApiRpcSplatRoute
|
||||||
|
'/bookmarks/': typeof ProtectedBookmarksIndexRoute
|
||||||
}
|
}
|
||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
'/': typeof IndexRoute
|
'/login': typeof LoginRoute
|
||||||
|
'/signup': typeof SignupRoute
|
||||||
'/api/$': typeof ApiSplatRoute
|
'/api/$': typeof ApiSplatRoute
|
||||||
'/api/health': typeof ApiHealthRoute
|
'/api/health': typeof ApiHealthRoute
|
||||||
|
'/': typeof ProtectedIndexRoute
|
||||||
|
'/api/auth/$': typeof ApiAuthSplatRoute
|
||||||
'/api/rpc/$': typeof ApiRpcSplatRoute
|
'/api/rpc/$': typeof ApiRpcSplatRoute
|
||||||
|
'/bookmarks': typeof ProtectedBookmarksIndexRoute
|
||||||
}
|
}
|
||||||
export interface FileRoutesById {
|
export interface FileRoutesById {
|
||||||
__root__: typeof rootRouteImport
|
__root__: typeof rootRouteImport
|
||||||
'/': typeof IndexRoute
|
'/_protected': typeof ProtectedRouteWithChildren
|
||||||
|
'/login': typeof LoginRoute
|
||||||
|
'/signup': typeof SignupRoute
|
||||||
'/api/$': typeof ApiSplatRoute
|
'/api/$': typeof ApiSplatRoute
|
||||||
'/api/health': typeof ApiHealthRoute
|
'/api/health': typeof ApiHealthRoute
|
||||||
|
'/_protected/': typeof ProtectedIndexRoute
|
||||||
|
'/api/auth/$': typeof ApiAuthSplatRoute
|
||||||
'/api/rpc/$': typeof ApiRpcSplatRoute
|
'/api/rpc/$': typeof ApiRpcSplatRoute
|
||||||
|
'/_protected/bookmarks/': typeof ProtectedBookmarksIndexRoute
|
||||||
}
|
}
|
||||||
export interface FileRouteTypes {
|
export interface FileRouteTypes {
|
||||||
fileRoutesByFullPath: FileRoutesByFullPath
|
fileRoutesByFullPath: FileRoutesByFullPath
|
||||||
fullPaths: '/' | '/api/$' | '/api/health' | '/api/rpc/$'
|
fullPaths:
|
||||||
|
| '/'
|
||||||
|
| '/login'
|
||||||
|
| '/signup'
|
||||||
|
| '/api/$'
|
||||||
|
| '/api/health'
|
||||||
|
| '/api/auth/$'
|
||||||
|
| '/api/rpc/$'
|
||||||
|
| '/bookmarks/'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
to: '/' | '/api/$' | '/api/health' | '/api/rpc/$'
|
to:
|
||||||
id: '__root__' | '/' | '/api/$' | '/api/health' | '/api/rpc/$'
|
| '/login'
|
||||||
|
| '/signup'
|
||||||
|
| '/api/$'
|
||||||
|
| '/api/health'
|
||||||
|
| '/'
|
||||||
|
| '/api/auth/$'
|
||||||
|
| '/api/rpc/$'
|
||||||
|
| '/bookmarks'
|
||||||
|
id:
|
||||||
|
| '__root__'
|
||||||
|
| '/_protected'
|
||||||
|
| '/login'
|
||||||
|
| '/signup'
|
||||||
|
| '/api/$'
|
||||||
|
| '/api/health'
|
||||||
|
| '/_protected/'
|
||||||
|
| '/api/auth/$'
|
||||||
|
| '/api/rpc/$'
|
||||||
|
| '/_protected/bookmarks/'
|
||||||
fileRoutesById: FileRoutesById
|
fileRoutesById: FileRoutesById
|
||||||
}
|
}
|
||||||
export interface RootRouteChildren {
|
export interface RootRouteChildren {
|
||||||
IndexRoute: typeof IndexRoute
|
ProtectedRoute: typeof ProtectedRouteWithChildren
|
||||||
|
LoginRoute: typeof LoginRoute
|
||||||
|
SignupRoute: typeof SignupRoute
|
||||||
ApiSplatRoute: typeof ApiSplatRoute
|
ApiSplatRoute: typeof ApiSplatRoute
|
||||||
ApiHealthRoute: typeof ApiHealthRoute
|
ApiHealthRoute: typeof ApiHealthRoute
|
||||||
|
ApiAuthSplatRoute: typeof ApiAuthSplatRoute
|
||||||
ApiRpcSplatRoute: typeof ApiRpcSplatRoute
|
ApiRpcSplatRoute: typeof ApiRpcSplatRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@tanstack/react-router' {
|
declare module '@tanstack/react-router' {
|
||||||
interface FileRoutesByPath {
|
interface FileRoutesByPath {
|
||||||
'/': {
|
'/signup': {
|
||||||
id: '/'
|
id: '/signup'
|
||||||
|
path: '/signup'
|
||||||
|
fullPath: '/signup'
|
||||||
|
preLoaderRoute: typeof SignupRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
|
'/login': {
|
||||||
|
id: '/login'
|
||||||
|
path: '/login'
|
||||||
|
fullPath: '/login'
|
||||||
|
preLoaderRoute: typeof LoginRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
|
'/_protected': {
|
||||||
|
id: '/_protected'
|
||||||
|
path: ''
|
||||||
|
fullPath: '/'
|
||||||
|
preLoaderRoute: typeof ProtectedRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
|
'/_protected/': {
|
||||||
|
id: '/_protected/'
|
||||||
path: '/'
|
path: '/'
|
||||||
fullPath: '/'
|
fullPath: '/'
|
||||||
preLoaderRoute: typeof IndexRouteImport
|
preLoaderRoute: typeof ProtectedIndexRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof ProtectedRoute
|
||||||
}
|
}
|
||||||
'/api/health': {
|
'/api/health': {
|
||||||
id: '/api/health'
|
id: '/api/health'
|
||||||
@@ -92,6 +184,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof ApiSplatRouteImport
|
preLoaderRoute: typeof ApiSplatRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/_protected/bookmarks/': {
|
||||||
|
id: '/_protected/bookmarks/'
|
||||||
|
path: '/bookmarks'
|
||||||
|
fullPath: '/bookmarks/'
|
||||||
|
preLoaderRoute: typeof ProtectedBookmarksIndexRouteImport
|
||||||
|
parentRoute: typeof ProtectedRoute
|
||||||
|
}
|
||||||
'/api/rpc/$': {
|
'/api/rpc/$': {
|
||||||
id: '/api/rpc/$'
|
id: '/api/rpc/$'
|
||||||
path: '/api/rpc/$'
|
path: '/api/rpc/$'
|
||||||
@@ -99,13 +198,37 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof ApiRpcSplatRouteImport
|
preLoaderRoute: typeof ApiRpcSplatRouteImport
|
||||||
parentRoute: typeof rootRouteImport
|
parentRoute: typeof rootRouteImport
|
||||||
}
|
}
|
||||||
|
'/api/auth/$': {
|
||||||
|
id: '/api/auth/$'
|
||||||
|
path: '/api/auth/$'
|
||||||
|
fullPath: '/api/auth/$'
|
||||||
|
preLoaderRoute: typeof ApiAuthSplatRouteImport
|
||||||
|
parentRoute: typeof rootRouteImport
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ProtectedRouteChildren {
|
||||||
|
ProtectedIndexRoute: typeof ProtectedIndexRoute
|
||||||
|
ProtectedBookmarksIndexRoute: typeof ProtectedBookmarksIndexRoute
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProtectedRouteChildren: ProtectedRouteChildren = {
|
||||||
|
ProtectedIndexRoute: ProtectedIndexRoute,
|
||||||
|
ProtectedBookmarksIndexRoute: ProtectedBookmarksIndexRoute,
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProtectedRouteWithChildren = ProtectedRoute._addFileChildren(
|
||||||
|
ProtectedRouteChildren,
|
||||||
|
)
|
||||||
|
|
||||||
const rootRouteChildren: RootRouteChildren = {
|
const rootRouteChildren: RootRouteChildren = {
|
||||||
IndexRoute: IndexRoute,
|
ProtectedRoute: ProtectedRouteWithChildren,
|
||||||
|
LoginRoute: LoginRoute,
|
||||||
|
SignupRoute: SignupRoute,
|
||||||
ApiSplatRoute: ApiSplatRoute,
|
ApiSplatRoute: ApiSplatRoute,
|
||||||
ApiHealthRoute: ApiHealthRoute,
|
ApiHealthRoute: ApiHealthRoute,
|
||||||
|
ApiAuthSplatRoute: ApiAuthSplatRoute,
|
||||||
ApiRpcSplatRoute: ApiRpcSplatRoute,
|
ApiRpcSplatRoute: ApiRpcSplatRoute,
|
||||||
}
|
}
|
||||||
export const routeTree = rootRouteImport
|
export const routeTree = rootRouteImport
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { createFileRoute, Outlet, redirect } from '@tanstack/react-router'
|
||||||
|
import { getSession } from '@/server/auth/functions'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/_protected' as never)({
|
||||||
|
beforeLoad: async () => {
|
||||||
|
const session = await getSession()
|
||||||
|
if (!session) {
|
||||||
|
throw redirect({ to: '/login' as never })
|
||||||
|
}
|
||||||
|
return { user: session.user, session: session.session }
|
||||||
|
},
|
||||||
|
component: ProtectedLayout,
|
||||||
|
})
|
||||||
|
|
||||||
|
function ProtectedLayout() {
|
||||||
|
return <Outlet />
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import type { QueryClient } from '@tanstack/react-query'
|
||||||
|
import { useMutation, useSuspenseQuery } from '@tanstack/react-query'
|
||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import { Plus, X } from 'lucide-react'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { orpc } from '@/client/orpc'
|
||||||
|
import { CategorySection } from '@/modules/bookmarks/components/CategorySection'
|
||||||
|
import { GreetingHeader } from '@/modules/bookmarks/components/GreetingHeader'
|
||||||
|
import { SearchBar } from '@/modules/bookmarks/components/SearchBar'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/_protected/bookmarks/' as never)({
|
||||||
|
component: BookmarksPage,
|
||||||
|
loader: async ({ context }: { context: { queryClient: QueryClient } }) => {
|
||||||
|
await context.queryClient.ensureQueryData(orpc.bookmarks.category.list.queryOptions())
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
function BookmarksPage() {
|
||||||
|
const categoriesQuery = useSuspenseQuery(orpc.bookmarks.category.list.queryOptions())
|
||||||
|
const createCategory = useMutation(orpc.bookmarks.category.create.mutationOptions())
|
||||||
|
const [showAddCategory, setShowAddCategory] = useState(false)
|
||||||
|
const [newCategoryName, setNewCategoryName] = useState('')
|
||||||
|
|
||||||
|
const handleAddCategory = (e: React.FormEvent) => {
|
||||||
|
e.preventDefault()
|
||||||
|
if (newCategoryName.trim()) {
|
||||||
|
createCategory.mutate({
|
||||||
|
name: newCategoryName.trim(),
|
||||||
|
orderId: categoriesQuery.data.length,
|
||||||
|
})
|
||||||
|
setNewCategoryName('')
|
||||||
|
setShowAddCategory(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-slate-50 py-8 px-4 sm:px-6">
|
||||||
|
<div className="max-w-4xl mx-auto space-y-8">
|
||||||
|
<SearchBar />
|
||||||
|
|
||||||
|
<GreetingHeader />
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
{categoriesQuery.data.map((category) => (
|
||||||
|
<CategorySection key={category.id} category={category} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{categoriesQuery.data.length === 0 && !showAddCategory && (
|
||||||
|
<div className="text-center py-16">
|
||||||
|
<p className="text-slate-400 text-lg">还没有任何分类</p>
|
||||||
|
<p className="text-slate-400 text-sm mt-1">创建一个分类来开始添加书签</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{showAddCategory ? (
|
||||||
|
<form onSubmit={handleAddCategory} className="flex items-center gap-2 max-w-md mx-auto">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={newCategoryName}
|
||||||
|
onChange={(e) => setNewCategoryName(e.target.value)}
|
||||||
|
placeholder="分类名称"
|
||||||
|
className="flex-1 px-4 py-2.5 rounded-xl bg-white ring-1 ring-slate-200 outline-none focus:ring-2 focus:ring-indigo-500/50 text-sm"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={createCategory.isPending || !newCategoryName.trim()}
|
||||||
|
className="px-4 py-2.5 bg-indigo-600 hover:bg-indigo-700 text-white rounded-xl text-sm font-medium transition-colors disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{createCategory.isPending ? '创建中...' : '创建'}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowAddCategory(false)}
|
||||||
|
className="p-2.5 text-slate-400 hover:text-slate-600 hover:bg-slate-100 rounded-xl transition-colors"
|
||||||
|
>
|
||||||
|
<X className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowAddCategory(true)}
|
||||||
|
className="flex items-center justify-center gap-2 w-full py-3 rounded-xl border-2 border-dashed border-slate-200 text-slate-400 hover:border-slate-300 hover:text-slate-500 transition-colors"
|
||||||
|
>
|
||||||
|
<Plus className="h-4 w-4" /> 添加分类
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { createFileRoute, Link, useRouter } from '@tanstack/react-router'
|
||||||
|
import * as icons from 'lucide-react'
|
||||||
|
import { modules } from '@/modules/registry'
|
||||||
|
import { authClient } from '@/server/auth/client'
|
||||||
|
|
||||||
|
const iconComponents = icons as unknown as Record<string, typeof icons.Box>
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/_protected' as never)({
|
||||||
|
component: DashboardPage,
|
||||||
|
})
|
||||||
|
|
||||||
|
function DashboardPage() {
|
||||||
|
const router = useRouter()
|
||||||
|
const { user } = Route.useRouteContext() as {
|
||||||
|
user: {
|
||||||
|
name: string
|
||||||
|
email: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const enabledModules = modules.filter((mod) => mod.enabled)
|
||||||
|
|
||||||
|
const handleSignOut = async () => {
|
||||||
|
await authClient.signOut()
|
||||||
|
router.navigate({ to: '/login' as never })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-slate-50 px-4 py-12 sm:px-6">
|
||||||
|
<div className="mx-auto max-w-4xl space-y-8">
|
||||||
|
<div className="flex items-center justify-between gap-4">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-3xl font-bold tracking-tight text-slate-900">Kairos</h1>
|
||||||
|
<p className="mt-1 text-slate-500">
|
||||||
|
欢迎回来,{user.name} · {user.email}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleSignOut}
|
||||||
|
className="rounded-lg px-4 py-2 text-sm text-slate-600 transition-colors hover:bg-slate-100 hover:text-slate-900"
|
||||||
|
>
|
||||||
|
退出登录
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{enabledModules.length === 0 ? (
|
||||||
|
<div className="py-20 text-center text-slate-400">暂无可用模块</div>
|
||||||
|
) : (
|
||||||
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
|
{enabledModules.map((mod) => {
|
||||||
|
const IconComponent = iconComponents[mod.icon] ?? icons.Box
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={mod.id}
|
||||||
|
to={mod.route as never}
|
||||||
|
className="group block rounded-2xl bg-white p-6 shadow-sm ring-1 ring-slate-100 transition-all hover:shadow-md hover:ring-slate-200"
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-4">
|
||||||
|
<div className="flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-xl bg-indigo-50 transition-colors group-hover:bg-indigo-100">
|
||||||
|
<IconComponent className="h-6 w-6 text-indigo-600" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold text-slate-900">{mod.name}</h3>
|
||||||
|
<p className="mt-0.5 text-sm text-slate-500">{mod.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { createFileRoute } from '@tanstack/react-router'
|
||||||
|
import { auth } from '@/server/auth'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/api/auth/$' as never)({
|
||||||
|
server: {
|
||||||
|
handlers: {
|
||||||
|
GET: ({ request }) => auth.handler(request),
|
||||||
|
POST: ({ request }) => auth.handler(request),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
import { useMutation, useSuspenseQuery } from '@tanstack/react-query'
|
|
||||||
import { createFileRoute } from '@tanstack/react-router'
|
|
||||||
import type { ChangeEventHandler, SubmitEventHandler } from 'react'
|
|
||||||
import { useState } from 'react'
|
|
||||||
import { orpc } from '@/client/orpc'
|
|
||||||
|
|
||||||
export const Route = createFileRoute('/')({
|
|
||||||
component: Todos,
|
|
||||||
loader: async ({ context }) => {
|
|
||||||
await context.queryClient.ensureQueryData(orpc.todo.list.queryOptions())
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
function Todos() {
|
|
||||||
const [newTodoTitle, setNewTodoTitle] = useState('')
|
|
||||||
|
|
||||||
const listQuery = useSuspenseQuery(orpc.todo.list.queryOptions())
|
|
||||||
const createMutation = useMutation(orpc.todo.create.mutationOptions())
|
|
||||||
const updateMutation = useMutation(orpc.todo.update.mutationOptions())
|
|
||||||
const deleteMutation = useMutation(orpc.todo.remove.mutationOptions())
|
|
||||||
|
|
||||||
const handleCreateTodo: SubmitEventHandler<HTMLFormElement> = (e) => {
|
|
||||||
e.preventDefault()
|
|
||||||
if (newTodoTitle.trim()) {
|
|
||||||
createMutation.mutate({ title: newTodoTitle.trim() })
|
|
||||||
setNewTodoTitle('')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleInputChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
|
||||||
setNewTodoTitle(e.target.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleToggleTodo = (id: string, currentCompleted: boolean) => {
|
|
||||||
updateMutation.mutate({
|
|
||||||
id,
|
|
||||||
data: { completed: !currentCompleted },
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDeleteTodo = (id: string) => {
|
|
||||||
deleteMutation.mutate({ id })
|
|
||||||
}
|
|
||||||
|
|
||||||
const todos = listQuery.data
|
|
||||||
const completedCount = todos.filter((todo) => todo.completed).length
|
|
||||||
const totalCount = todos.length
|
|
||||||
const progress = totalCount > 0 ? (completedCount / totalCount) * 100 : 0
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="min-h-screen bg-slate-50 py-12 px-4 sm:px-6 font-sans">
|
|
||||||
<div className="max-w-2xl mx-auto space-y-8">
|
|
||||||
{/* Header */}
|
|
||||||
<div className="flex items-end justify-between">
|
|
||||||
<div>
|
|
||||||
<h1 className="text-3xl font-bold text-slate-900 tracking-tight">我的待办</h1>
|
|
||||||
<p className="text-slate-500 mt-1">保持专注,逐个击破</p>
|
|
||||||
</div>
|
|
||||||
<div className="text-right">
|
|
||||||
<div className="text-2xl font-semibold text-slate-900">
|
|
||||||
{completedCount}
|
|
||||||
<span className="text-slate-400 text-lg">/{totalCount}</span>
|
|
||||||
</div>
|
|
||||||
<div className="text-xs font-medium text-slate-400 uppercase tracking-wider">已完成</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Add Todo Form */}
|
|
||||||
<form onSubmit={handleCreateTodo} className="relative group z-10">
|
|
||||||
<div className="relative transform transition-all duration-200 focus-within:-translate-y-1">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={newTodoTitle}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
placeholder="添加新任务..."
|
|
||||||
className="w-full pl-6 pr-32 py-5 bg-white rounded-2xl shadow-[0_8px_30px_rgb(0,0,0,0.04)] border-0 ring-1 ring-slate-100 focus:ring-2 focus:ring-indigo-500/50 outline-none transition-all placeholder:text-slate-400 text-lg text-slate-700"
|
|
||||||
disabled={createMutation.isPending}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
disabled={createMutation.isPending || !newTodoTitle.trim()}
|
|
||||||
className="absolute right-3 top-3 bottom-3 px-6 bg-indigo-600 hover:bg-indigo-700 text-white rounded-xl font-medium transition-all shadow-md shadow-indigo-200 disabled:opacity-50 disabled:shadow-none hover:shadow-lg hover:shadow-indigo-300 active:scale-95"
|
|
||||||
>
|
|
||||||
{createMutation.isPending ? '添加中' : '添加'}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{/* Progress Bar (Only visible when there are tasks) */}
|
|
||||||
{totalCount > 0 && (
|
|
||||||
<div className="h-1.5 w-full bg-slate-200 rounded-full overflow-hidden">
|
|
||||||
<div
|
|
||||||
className="h-full bg-indigo-500 transition-all duration-500 ease-out rounded-full"
|
|
||||||
style={{ width: `${progress}%` }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Todo List */}
|
|
||||||
<div className="space-y-3">
|
|
||||||
{todos.length === 0 ? (
|
|
||||||
<div className="py-20 text-center">
|
|
||||||
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-slate-100 mb-4">
|
|
||||||
<svg
|
|
||||||
className="w-8 h-8 text-slate-400"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<p className="text-slate-500 text-lg font-medium">没有待办事项</p>
|
|
||||||
<p className="text-slate-400 text-sm mt-1">输入上方内容添加您的第一个任务</p>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
todos.map((todo) => (
|
|
||||||
<div
|
|
||||||
key={todo.id}
|
|
||||||
className={`group relative flex items-center p-4 bg-white rounded-xl border border-slate-100 shadow-sm transition-all duration-200 hover:shadow-md hover:border-slate-200 ${
|
|
||||||
todo.completed ? 'bg-slate-50/50' : ''
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => handleToggleTodo(todo.id, todo.completed)}
|
|
||||||
className={`flex-shrink-0 w-6 h-6 rounded-full border-2 transition-all duration-200 flex items-center justify-center mr-4 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 ${
|
|
||||||
todo.completed
|
|
||||||
? 'bg-indigo-500 border-indigo-500'
|
|
||||||
: 'border-slate-300 hover:border-indigo-500 bg-white'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{todo.completed && (
|
|
||||||
<svg
|
|
||||||
className="w-3.5 h-3.5 text-white"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth={3}
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
|
|
||||||
</svg>
|
|
||||||
)}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div className="flex-1 min-w-0">
|
|
||||||
<p
|
|
||||||
className={`text-lg transition-all duration-200 truncate ${
|
|
||||||
todo.completed
|
|
||||||
? 'text-slate-400 line-through decoration-slate-300 decoration-2'
|
|
||||||
: 'text-slate-700'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{todo.title}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center opacity-0 group-hover:opacity-100 transition-opacity duration-200 absolute right-4 pl-4 bg-gradient-to-l from-white via-white to-transparent sm:static sm:bg-none">
|
|
||||||
<span className="text-xs text-slate-400 mr-3 hidden sm:inline-block">
|
|
||||||
{new Date(todo.createdAt).toLocaleDateString('zh-CN')}
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => handleDeleteTodo(todo.id)}
|
|
||||||
className="p-2 text-slate-400 hover:text-red-500 hover:bg-red-50 rounded-lg transition-colors focus:outline-none"
|
|
||||||
title="删除"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
className="w-5 h-5"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth={1.5}
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
import { createFileRoute, Link, redirect, useRouter } from '@tanstack/react-router'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { authClient } from '@/server/auth/client'
|
||||||
|
import { getSession } from '@/server/auth/functions'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/login' as never)({
|
||||||
|
beforeLoad: async () => {
|
||||||
|
const session = await getSession()
|
||||||
|
if (session) {
|
||||||
|
throw redirect({ to: '/' as never })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
component: LoginPage,
|
||||||
|
})
|
||||||
|
|
||||||
|
function LoginPage() {
|
||||||
|
const router = useRouter()
|
||||||
|
const [email, setEmail] = useState('')
|
||||||
|
const [password, setPassword] = useState('')
|
||||||
|
const [error, setError] = useState('')
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault()
|
||||||
|
setError('')
|
||||||
|
setLoading(true)
|
||||||
|
|
||||||
|
const { error: signInError } = await authClient.signIn.email({
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (signInError) {
|
||||||
|
setError(signInError.message ?? '登录失败,请重试')
|
||||||
|
setLoading(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
router.navigate({ to: '/' as never })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-slate-50 flex items-center justify-center px-4">
|
||||||
|
<div className="w-full max-w-md">
|
||||||
|
<div className="text-center mb-8">
|
||||||
|
<h1 className="text-4xl font-bold text-slate-900 tracking-tight">Kairos</h1>
|
||||||
|
<p className="text-slate-500 mt-2">登录你的人生操作系统</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-white rounded-2xl shadow-[0_8px_30px_rgb(0,0,0,0.04)] ring-1 ring-slate-100 p-8">
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-5">
|
||||||
|
<div>
|
||||||
|
<label htmlFor="email" className="block text-sm font-medium text-slate-700 mb-1.5">
|
||||||
|
邮箱
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="email"
|
||||||
|
type="email"
|
||||||
|
required
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
|
||||||
|
placeholder="your@email.com"
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label htmlFor="password" className="block text-sm font-medium text-slate-700 mb-1.5">
|
||||||
|
密码
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="password"
|
||||||
|
type="password"
|
||||||
|
required
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
|
||||||
|
placeholder="••••••••"
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{error && <p className="text-sm text-red-600">{error}</p>}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={loading}
|
||||||
|
className="w-full py-3 bg-indigo-600 hover:bg-indigo-700 text-white rounded-xl font-medium transition-all shadow-md shadow-indigo-200 disabled:opacity-50 disabled:shadow-none hover:shadow-lg hover:shadow-indigo-300 active:scale-[0.98]"
|
||||||
|
>
|
||||||
|
{loading ? '登录中...' : '登录'}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p className="text-center text-sm text-slate-500 mt-6">
|
||||||
|
还没有账号?{' '}
|
||||||
|
<Link to={'/signup' as never} className="text-indigo-600 hover:text-indigo-700 font-medium">
|
||||||
|
注册
|
||||||
|
</Link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
import { createFileRoute, Link, redirect, useRouter } from '@tanstack/react-router'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import { authClient } from '@/server/auth/client'
|
||||||
|
import { getSession } from '@/server/auth/functions'
|
||||||
|
|
||||||
|
export const Route = createFileRoute('/signup' as never)({
|
||||||
|
beforeLoad: async () => {
|
||||||
|
const session = await getSession()
|
||||||
|
if (session) {
|
||||||
|
throw redirect({ to: '/' as never })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
component: SignupPage,
|
||||||
|
})
|
||||||
|
|
||||||
|
function SignupPage() {
|
||||||
|
const router = useRouter()
|
||||||
|
const [name, setName] = useState('')
|
||||||
|
const [email, setEmail] = useState('')
|
||||||
|
const [password, setPassword] = useState('')
|
||||||
|
const [confirmPassword, setConfirmPassword] = useState('')
|
||||||
|
const [error, setError] = useState('')
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault()
|
||||||
|
setError('')
|
||||||
|
|
||||||
|
if (password !== confirmPassword) {
|
||||||
|
setError('两次输入的密码不一致')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password.length < 8) {
|
||||||
|
setError('密码至少需要 8 个字符')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true)
|
||||||
|
|
||||||
|
const { error: signUpError } = await authClient.signUp.email({
|
||||||
|
name,
|
||||||
|
email,
|
||||||
|
password,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (signUpError) {
|
||||||
|
setError(signUpError.message ?? '注册失败,请重试')
|
||||||
|
setLoading(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
router.navigate({ to: '/' as never })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-slate-50 flex items-center justify-center px-4">
|
||||||
|
<div className="w-full max-w-md">
|
||||||
|
<div className="text-center mb-8">
|
||||||
|
<h1 className="text-4xl font-bold text-slate-900 tracking-tight">Kairos</h1>
|
||||||
|
<p className="text-slate-500 mt-2">创建你的账号</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-white rounded-2xl shadow-[0_8px_30px_rgb(0,0,0,0.04)] ring-1 ring-slate-100 p-8">
|
||||||
|
<form onSubmit={handleSubmit} className="space-y-5">
|
||||||
|
<div>
|
||||||
|
<label htmlFor="name" className="block text-sm font-medium text-slate-700 mb-1.5">
|
||||||
|
用户名
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="name"
|
||||||
|
type="text"
|
||||||
|
required
|
||||||
|
value={name}
|
||||||
|
onChange={(e) => setName(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
|
||||||
|
placeholder="你的名字"
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label htmlFor="email" className="block text-sm font-medium text-slate-700 mb-1.5">
|
||||||
|
邮箱
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="email"
|
||||||
|
type="email"
|
||||||
|
required
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
|
||||||
|
placeholder="your@email.com"
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label htmlFor="password" className="block text-sm font-medium text-slate-700 mb-1.5">
|
||||||
|
密码
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="password"
|
||||||
|
type="password"
|
||||||
|
required
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
|
||||||
|
placeholder="至少 8 个字符"
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label htmlFor="confirmPassword" className="block text-sm font-medium text-slate-700 mb-1.5">
|
||||||
|
确认密码
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="confirmPassword"
|
||||||
|
type="password"
|
||||||
|
required
|
||||||
|
value={confirmPassword}
|
||||||
|
onChange={(e) => setConfirmPassword(e.target.value)}
|
||||||
|
className="w-full px-4 py-3 rounded-xl bg-slate-50 border-0 ring-1 ring-slate-200 focus:ring-2 focus:ring-indigo-500 outline-none transition-all text-slate-700 placeholder:text-slate-400"
|
||||||
|
placeholder="再次输入密码"
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{error && <p className="text-sm text-red-600">{error}</p>}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={loading}
|
||||||
|
className="w-full py-3 bg-indigo-600 hover:bg-indigo-700 text-white rounded-xl font-medium transition-all shadow-md shadow-indigo-200 disabled:opacity-50 disabled:shadow-none hover:shadow-lg hover:shadow-indigo-300 active:scale-[0.98]"
|
||||||
|
>
|
||||||
|
{loading ? '注册中...' : '注册'}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p className="text-center text-sm text-slate-500 mt-6">
|
||||||
|
已有账号?{' '}
|
||||||
|
<Link to={'/login' as never} className="text-indigo-600 hover:text-indigo-700 font-medium">
|
||||||
|
登录
|
||||||
|
</Link>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,25 +1,15 @@
|
|||||||
|
import type { auth } from '@/server/auth'
|
||||||
import type { DB } from '@/server/db'
|
import type { DB } from '@/server/db'
|
||||||
|
|
||||||
/**
|
|
||||||
* 基础 Context - 所有请求都包含的上下文
|
|
||||||
*/
|
|
||||||
export interface BaseContext {
|
export interface BaseContext {
|
||||||
headers: Headers
|
headers: Headers
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据库 Context - 通过 db middleware 扩展
|
|
||||||
*/
|
|
||||||
export interface DBContext extends BaseContext {
|
export interface DBContext extends BaseContext {
|
||||||
db: DB
|
db: DB
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export interface AuthContext extends DBContext {
|
||||||
* 认证 Context - 通过 auth middleware 扩展(未来使用)
|
user: typeof auth.$Infer.Session.user
|
||||||
*
|
session: typeof auth.$Infer.Session.session
|
||||||
* @example
|
}
|
||||||
* export interface AuthContext extends DBContext {
|
|
||||||
* userId: string
|
|
||||||
* user: User
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as todo from './todo.contract'
|
import * as bookmarks from '@/modules/bookmarks/contract'
|
||||||
|
|
||||||
export const contract = {
|
export const contract = {
|
||||||
todo,
|
bookmarks,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Contract = typeof contract
|
export type Contract = typeof contract
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
import { oc } from '@orpc/contract'
|
|
||||||
import { createInsertSchema, createSelectSchema, createUpdateSchema } from 'drizzle-orm/zod'
|
|
||||||
import { z } from 'zod'
|
|
||||||
import { generatedFieldKeys } from '@/server/db/fields'
|
|
||||||
import { todoTable } from '@/server/db/schema'
|
|
||||||
|
|
||||||
const selectSchema = createSelectSchema(todoTable)
|
|
||||||
|
|
||||||
const insertSchema = createInsertSchema(todoTable).omit(generatedFieldKeys)
|
|
||||||
|
|
||||||
const updateSchema = createUpdateSchema(todoTable).omit(generatedFieldKeys)
|
|
||||||
|
|
||||||
export const list = oc.input(z.void()).output(z.array(selectSchema))
|
|
||||||
|
|
||||||
export const create = oc.input(insertSchema).output(selectSchema)
|
|
||||||
|
|
||||||
export const update = oc
|
|
||||||
.input(
|
|
||||||
z.object({
|
|
||||||
id: z.uuid(),
|
|
||||||
data: updateSchema,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.output(selectSchema)
|
|
||||||
|
|
||||||
export const remove = oc
|
|
||||||
.input(
|
|
||||||
z.object({
|
|
||||||
id: z.uuid(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
.output(z.void())
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { ORPCError } from '@orpc/server'
|
||||||
|
import { os } from '@/server/api/server'
|
||||||
|
import { auth } from '@/server/auth'
|
||||||
|
|
||||||
|
export const authMiddleware = os.middleware(async ({ context, next }) => {
|
||||||
|
const sessionData = await auth.api.getSession({ headers: context.headers })
|
||||||
|
|
||||||
|
if (!sessionData?.session || !sessionData?.user) {
|
||||||
|
throw new ORPCError('UNAUTHORIZED')
|
||||||
|
}
|
||||||
|
|
||||||
|
return next({
|
||||||
|
context: {
|
||||||
|
...context,
|
||||||
|
session: sessionData.session,
|
||||||
|
user: sessionData.user,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1 +1,2 @@
|
|||||||
|
export * from './auth.middleware'
|
||||||
export * from './db.middleware'
|
export * from './db.middleware'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import * as bookmarks from '@/modules/bookmarks/router'
|
||||||
import { os } from '../server'
|
import { os } from '../server'
|
||||||
import * as todo from './todo.router'
|
|
||||||
|
|
||||||
export const router = os.router({
|
export const router = os.router({
|
||||||
todo,
|
bookmarks,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
import { ORPCError } from '@orpc/server'
|
|
||||||
import { eq } from 'drizzle-orm'
|
|
||||||
import { todoTable } from '@/server/db/schema'
|
|
||||||
import { db } from '../middlewares'
|
|
||||||
import { os } from '../server'
|
|
||||||
|
|
||||||
export const list = os.todo.list.use(db).handler(async ({ context }) => {
|
|
||||||
const todos = await context.db.query.todoTable.findMany({
|
|
||||||
orderBy: { createdAt: 'desc' },
|
|
||||||
})
|
|
||||||
return todos
|
|
||||||
})
|
|
||||||
|
|
||||||
export const create = os.todo.create.use(db).handler(async ({ context, input }) => {
|
|
||||||
const [newTodo] = await context.db.insert(todoTable).values(input).returning()
|
|
||||||
|
|
||||||
if (!newTodo) {
|
|
||||||
throw new ORPCError('INTERNAL_SERVER_ERROR', { message: 'Failed to create todo' })
|
|
||||||
}
|
|
||||||
|
|
||||||
return newTodo
|
|
||||||
})
|
|
||||||
|
|
||||||
export const update = os.todo.update.use(db).handler(async ({ context, input }) => {
|
|
||||||
const [updatedTodo] = await context.db.update(todoTable).set(input.data).where(eq(todoTable.id, input.id)).returning()
|
|
||||||
|
|
||||||
if (!updatedTodo) {
|
|
||||||
throw new ORPCError('NOT_FOUND')
|
|
||||||
}
|
|
||||||
|
|
||||||
return updatedTodo
|
|
||||||
})
|
|
||||||
|
|
||||||
export const remove = os.todo.remove.use(db).handler(async ({ context, input }) => {
|
|
||||||
const [deleted] = await context.db.delete(todoTable).where(eq(todoTable.id, input.id)).returning({ id: todoTable.id })
|
|
||||||
|
|
||||||
if (!deleted) {
|
|
||||||
throw new ORPCError('NOT_FOUND')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { createAuthClient } from 'better-auth/react'
|
||||||
|
|
||||||
|
export const authClient = createAuthClient()
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { createServerFn } from '@tanstack/react-start'
|
||||||
|
import { getRequestHeaders } from '@tanstack/react-start/server'
|
||||||
|
import { auth } from '@/server/auth'
|
||||||
|
|
||||||
|
export const getSession = createServerFn({ method: 'GET' }).handler(async () => {
|
||||||
|
const headers = getRequestHeaders()
|
||||||
|
return await auth.api.getSession({ headers })
|
||||||
|
})
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { betterAuth } from 'better-auth'
|
||||||
|
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
|
||||||
|
import { tanstackStartCookies } from 'better-auth/tanstack-start'
|
||||||
|
import { env } from '@/env'
|
||||||
|
import * as authSchema from '@/server/auth/schema'
|
||||||
|
import { getDB } from '@/server/db'
|
||||||
|
|
||||||
|
export const auth = betterAuth({
|
||||||
|
baseURL: env.BETTER_AUTH_URL,
|
||||||
|
secret: env.BETTER_AUTH_SECRET,
|
||||||
|
database: drizzleAdapter(getDB(), {
|
||||||
|
provider: 'pg',
|
||||||
|
schema: authSchema,
|
||||||
|
}),
|
||||||
|
emailAndPassword: { enabled: true },
|
||||||
|
session: {
|
||||||
|
expiresIn: 60 * 60 * 24 * 7,
|
||||||
|
updateAge: 60 * 60 * 24,
|
||||||
|
cookieCache: {
|
||||||
|
enabled: true,
|
||||||
|
maxAge: 5 * 60,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [tanstackStartCookies()],
|
||||||
|
})
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import { boolean, pgTable, text, timestamp } from 'drizzle-orm/pg-core'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Better Auth 认证表
|
||||||
|
*
|
||||||
|
* 注意:所有 ID 使用 text 类型(Better Auth 自管 ID 生成),
|
||||||
|
* 不使用项目的 generatedFields(UUID v7)。
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const userTable = pgTable('user', {
|
||||||
|
id: text('id').primaryKey(),
|
||||||
|
name: text('name').notNull(),
|
||||||
|
email: text('email').notNull().unique(),
|
||||||
|
emailVerified: boolean('email_verified').notNull().default(false),
|
||||||
|
image: text('image'),
|
||||||
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
|
updatedAt: timestamp('updated_at', { withTimezone: true })
|
||||||
|
.notNull()
|
||||||
|
.defaultNow()
|
||||||
|
.$onUpdateFn(() => new Date()),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const sessionTable = pgTable('session', {
|
||||||
|
id: text('id').primaryKey(),
|
||||||
|
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
||||||
|
token: text('token').notNull().unique(),
|
||||||
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
|
updatedAt: timestamp('updated_at', { withTimezone: true })
|
||||||
|
.notNull()
|
||||||
|
.defaultNow()
|
||||||
|
.$onUpdateFn(() => new Date()),
|
||||||
|
ipAddress: text('ip_address'),
|
||||||
|
userAgent: text('user_agent'),
|
||||||
|
userId: text('user_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => userTable.id, { onDelete: 'cascade' }),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const accountTable = pgTable('account', {
|
||||||
|
id: text('id').primaryKey(),
|
||||||
|
accountId: text('account_id').notNull(),
|
||||||
|
providerId: text('provider_id').notNull(),
|
||||||
|
userId: text('user_id')
|
||||||
|
.notNull()
|
||||||
|
.references(() => userTable.id, { onDelete: 'cascade' }),
|
||||||
|
accessToken: text('access_token'),
|
||||||
|
refreshToken: text('refresh_token'),
|
||||||
|
idToken: text('id_token'),
|
||||||
|
accessTokenExpiresAt: timestamp('access_token_expires_at', { withTimezone: true }),
|
||||||
|
refreshTokenExpiresAt: timestamp('refresh_token_expires_at', { withTimezone: true }),
|
||||||
|
scope: text('scope'),
|
||||||
|
password: text('password'),
|
||||||
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
|
updatedAt: timestamp('updated_at', { withTimezone: true })
|
||||||
|
.notNull()
|
||||||
|
.defaultNow()
|
||||||
|
.$onUpdateFn(() => new Date()),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const verificationTable = pgTable('verification', {
|
||||||
|
id: text('id').primaryKey(),
|
||||||
|
identifier: text('identifier').notNull(),
|
||||||
|
value: text('value').notNull(),
|
||||||
|
expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
|
||||||
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
||||||
|
updatedAt: timestamp('updated_at', { withTimezone: true })
|
||||||
|
.notNull()
|
||||||
|
.defaultNow()
|
||||||
|
.$onUpdateFn(() => new Date()),
|
||||||
|
})
|
||||||
@@ -1,4 +1,26 @@
|
|||||||
import { defineRelations } from 'drizzle-orm'
|
import { defineRelations } from 'drizzle-orm'
|
||||||
import * as schema from './schema'
|
import * as schema from './schema'
|
||||||
|
|
||||||
export const relations = defineRelations(schema, (_r) => ({}))
|
export const relations = defineRelations(schema, (r) => ({
|
||||||
|
userTable: {
|
||||||
|
categories: r.many.categoryTable(),
|
||||||
|
bookmarks: r.many.bookmarkTable(),
|
||||||
|
},
|
||||||
|
categoryTable: {
|
||||||
|
user: r.one.userTable({
|
||||||
|
from: r.categoryTable.userId,
|
||||||
|
to: r.userTable.id,
|
||||||
|
}),
|
||||||
|
bookmarks: r.many.bookmarkTable(),
|
||||||
|
},
|
||||||
|
bookmarkTable: {
|
||||||
|
user: r.one.userTable({
|
||||||
|
from: r.bookmarkTable.userId,
|
||||||
|
to: r.userTable.id,
|
||||||
|
}),
|
||||||
|
category: r.one.categoryTable({
|
||||||
|
from: r.bookmarkTable.categoryId,
|
||||||
|
to: r.categoryTable.id,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
export * from './todo'
|
export * from '../../../modules/bookmarks/schema'
|
||||||
|
export * from '../../auth/schema'
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import { boolean, pgTable, text } from 'drizzle-orm/pg-core'
|
|
||||||
import { generatedFields } from '../fields'
|
|
||||||
|
|
||||||
export const todoTable = pgTable('todo', {
|
|
||||||
...generatedFields,
|
|
||||||
title: text('title').notNull(),
|
|
||||||
completed: boolean('completed').notNull().default(false),
|
|
||||||
})
|
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
"name": "@furtherverse/server",
|
"name": "@furtherverse/server",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@dnd-kit/dom": "catalog:",
|
||||||
|
"@dnd-kit/react": "catalog:",
|
||||||
"@orpc/client": "catalog:",
|
"@orpc/client": "catalog:",
|
||||||
"@orpc/contract": "catalog:",
|
"@orpc/contract": "catalog:",
|
||||||
"@orpc/openapi": "catalog:",
|
"@orpc/openapi": "catalog:",
|
||||||
@@ -25,7 +27,9 @@
|
|||||||
"@tanstack/react-router": "catalog:",
|
"@tanstack/react-router": "catalog:",
|
||||||
"@tanstack/react-router-ssr-query": "catalog:",
|
"@tanstack/react-router-ssr-query": "catalog:",
|
||||||
"@tanstack/react-start": "catalog:",
|
"@tanstack/react-start": "catalog:",
|
||||||
|
"better-auth": "catalog:",
|
||||||
"drizzle-orm": "catalog:",
|
"drizzle-orm": "catalog:",
|
||||||
|
"lucide-react": "catalog:",
|
||||||
"postgres": "catalog:",
|
"postgres": "catalog:",
|
||||||
"react": "catalog:",
|
"react": "catalog:",
|
||||||
"react-dom": "catalog:",
|
"react-dom": "catalog:",
|
||||||
@@ -54,6 +58,8 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"catalog": {
|
"catalog": {
|
||||||
|
"@dnd-kit/dom": "^0.3.2",
|
||||||
|
"@dnd-kit/react": "^0.3.2",
|
||||||
"@orpc/client": "^1.13.11",
|
"@orpc/client": "^1.13.11",
|
||||||
"@orpc/contract": "^1.13.11",
|
"@orpc/contract": "^1.13.11",
|
||||||
"@orpc/openapi": "^1.13.11",
|
"@orpc/openapi": "^1.13.11",
|
||||||
@@ -73,8 +79,10 @@
|
|||||||
"@tanstack/react-start": "^1.167.6",
|
"@tanstack/react-start": "^1.167.6",
|
||||||
"@types/bun": "^1.3.11",
|
"@types/bun": "^1.3.11",
|
||||||
"@vitejs/plugin-react": "^6.0.1",
|
"@vitejs/plugin-react": "^6.0.1",
|
||||||
|
"better-auth": "^1.2.8",
|
||||||
"drizzle-kit": "1.0.0-beta.15-859cf75",
|
"drizzle-kit": "1.0.0-beta.15-859cf75",
|
||||||
"drizzle-orm": "1.0.0-beta.15-859cf75",
|
"drizzle-orm": "1.0.0-beta.15-859cf75",
|
||||||
|
"lucide-react": "^0.513.0",
|
||||||
"nitro": "npm:nitro-nightly@3.0.1-20260324-103046-9ce219ca",
|
"nitro": "npm:nitro-nightly@3.0.1-20260324-103046-9ce219ca",
|
||||||
"postgres": "^3.4.8",
|
"postgres": "^3.4.8",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
@@ -113,7 +121,7 @@
|
|||||||
|
|
||||||
"@azure/logger": ["@azure/logger@1.3.0", "", { "dependencies": { "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA=="],
|
"@azure/logger": ["@azure/logger@1.3.0", "", { "dependencies": { "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA=="],
|
||||||
|
|
||||||
"@azure/msal-browser": ["@azure/msal-browser@5.6.1", "", { "dependencies": { "@azure/msal-common": "16.4.0" } }, "sha512-Ylmp8yngH7YRLV5mA1aF4CNS6WsJTPbVXaA0Tb1x1Gv/J3BM3hE4Q7nDaf7dRfU00FcxDBBudTjqlpH74ZSsgw=="],
|
"@azure/msal-browser": ["@azure/msal-browser@5.6.2", "", { "dependencies": { "@azure/msal-common": "16.4.0" } }, "sha512-ZgcN9ToRJ80f+wNPBBKYJ+DG0jlW7ktEjYtSNkNsTrlHVMhKB8tKMdI1yIG1I9BJtykkXtqnuOjlJaEMC7J6aw=="],
|
||||||
|
|
||||||
"@azure/msal-common": ["@azure/msal-common@16.4.0", "", {}, "sha512-twXt09PYtj1PffNNIAzQlrBd0DS91cdA6i1gAfzJ6BnPM4xNk5k9q/5xna7jLIjU3Jnp0slKYtucshGM8OGNAw=="],
|
"@azure/msal-common": ["@azure/msal-common@16.4.0", "", {}, "sha512-twXt09PYtj1PffNNIAzQlrBd0DS91cdA6i1gAfzJ6BnPM4xNk5k9q/5xna7jLIjU3Jnp0slKYtucshGM8OGNAw=="],
|
||||||
|
|
||||||
@@ -157,6 +165,24 @@
|
|||||||
|
|
||||||
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
|
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
|
||||||
|
|
||||||
|
"@better-auth/core": ["@better-auth/core@1.5.6", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.39.0", "@standard-schema/spec": "^1.1.0", "zod": "^4.3.6" }, "peerDependencies": { "@better-auth/utils": "0.3.1", "@better-fetch/fetch": "1.1.21", "@cloudflare/workers-types": ">=4", "@opentelemetry/api": "^1.9.0", "better-call": "1.3.2", "jose": "^6.1.0", "kysely": "^0.28.5", "nanostores": "^1.0.1" }, "optionalPeers": ["@cloudflare/workers-types"] }, "sha512-Ez9DZdIMFyxHremmoLz1emFPGNQomDC1jqqBPnZ6Ci+6TiGN3R9w/Y03cJn6I8r1ycKgOzeVMZtJ/erOZ27Gsw=="],
|
||||||
|
|
||||||
|
"@better-auth/drizzle-adapter": ["@better-auth/drizzle-adapter@1.5.6", "", { "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "^0.3.0", "drizzle-orm": ">=0.41.0" }, "optionalPeers": ["drizzle-orm"] }, "sha512-VfFFmaoFw3ug12SiSuIwzrMoHyIVmkMGWm9gZ4sXdYYVX4HboCL4m3fjzOhppcmK5OGatRuU+N1UX6wxCITcXw=="],
|
||||||
|
|
||||||
|
"@better-auth/kysely-adapter": ["@better-auth/kysely-adapter@1.5.6", "", { "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "^0.3.0", "kysely": "^0.27.0 || ^0.28.0" }, "optionalPeers": ["kysely"] }, "sha512-Fnf+h8WVKtw6lEOmVmiVVzDf3shJtM60AYf9XTnbdCeUd6MxN/KnaJZpkgtYnRs7a+nwtkVB+fg4lGETebGFXQ=="],
|
||||||
|
|
||||||
|
"@better-auth/memory-adapter": ["@better-auth/memory-adapter@1.5.6", "", { "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "^0.3.0" } }, "sha512-rS7ZsrIl5uvloUgNN0u9LOZJMMXnsZXVdUZ3MrTBKWM2KpoJjzPr9yN3Szyma5+0V7SltnzSGHPkYj2bEzzmlA=="],
|
||||||
|
|
||||||
|
"@better-auth/mongo-adapter": ["@better-auth/mongo-adapter@1.5.6", "", { "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "^0.3.0", "mongodb": "^6.0.0 || ^7.0.0" }, "optionalPeers": ["mongodb"] }, "sha512-6+M3MS2mor8fTUV3EI1FBLP0cs6QfbN+Ovx9+XxR/GdfKIBoNFzmPEPRbdGt+ft6PvrITsUm+T70+kkHgVSP6w=="],
|
||||||
|
|
||||||
|
"@better-auth/prisma-adapter": ["@better-auth/prisma-adapter@1.5.6", "", { "peerDependencies": { "@better-auth/core": "1.5.6", "@better-auth/utils": "^0.3.0", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@prisma/client", "prisma"] }, "sha512-UxY9vQJs1Tt+O+T2YQnseDMlWmUSQvFZSBb5YiFRg7zcm+TEzujh4iX2/csA0YiZptLheovIuVWTP9nriewEBA=="],
|
||||||
|
|
||||||
|
"@better-auth/telemetry": ["@better-auth/telemetry@1.5.6", "", { "dependencies": { "@better-auth/utils": "0.3.1", "@better-fetch/fetch": "1.1.21" }, "peerDependencies": { "@better-auth/core": "1.5.6" } }, "sha512-yXC7NSxnIFlxDkGdpD7KA+J9nqIQAPCJKe77GoaC5bWoe/DALo1MYorZfTgOafS7wrslNtsPT4feV/LJi1ubqQ=="],
|
||||||
|
|
||||||
|
"@better-auth/utils": ["@better-auth/utils@0.3.1", "", {}, "sha512-+CGp4UmZSUrHHnpHhLPYu6cV+wSUSvVbZbNykxhUDocpVNTo9uFFxw/NqJlh1iC4wQ9HKKWGCKuZ5wUgS0v6Kg=="],
|
||||||
|
|
||||||
|
"@better-fetch/fetch": ["@better-fetch/fetch@1.1.21", "", {}, "sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A=="],
|
||||||
|
|
||||||
"@biomejs/biome": ["@biomejs/biome@2.4.9", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.9", "@biomejs/cli-darwin-x64": "2.4.9", "@biomejs/cli-linux-arm64": "2.4.9", "@biomejs/cli-linux-arm64-musl": "2.4.9", "@biomejs/cli-linux-x64": "2.4.9", "@biomejs/cli-linux-x64-musl": "2.4.9", "@biomejs/cli-win32-arm64": "2.4.9", "@biomejs/cli-win32-x64": "2.4.9" }, "bin": { "biome": "bin/biome" } }, "sha512-wvZW92FrwitTcacvCBT8xdAbfbxWfDLwjYMmU3djjqQTh7Ni4ZdiWIT/x5VcZ+RQuxiKzIOzi5D+dcyJDFZMsA=="],
|
"@biomejs/biome": ["@biomejs/biome@2.4.9", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.4.9", "@biomejs/cli-darwin-x64": "2.4.9", "@biomejs/cli-linux-arm64": "2.4.9", "@biomejs/cli-linux-arm64-musl": "2.4.9", "@biomejs/cli-linux-x64": "2.4.9", "@biomejs/cli-linux-x64-musl": "2.4.9", "@biomejs/cli-win32-arm64": "2.4.9", "@biomejs/cli-win32-x64": "2.4.9" }, "bin": { "biome": "bin/biome" } }, "sha512-wvZW92FrwitTcacvCBT8xdAbfbxWfDLwjYMmU3djjqQTh7Ni4ZdiWIT/x5VcZ+RQuxiKzIOzi5D+dcyJDFZMsA=="],
|
||||||
|
|
||||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-d5G8Gf2RpH5pYwiHLPA+UpG3G9TLQu4WM+VK6sfL7K68AmhcEQ9r+nkj/DvR/GYhYox6twsHUtmWWWIKfcfQQA=="],
|
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.4.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-d5G8Gf2RpH5pYwiHLPA+UpG3G9TLQu4WM+VK6sfL7K68AmhcEQ9r+nkj/DvR/GYhYox6twsHUtmWWWIKfcfQQA=="],
|
||||||
@@ -175,6 +201,18 @@
|
|||||||
|
|
||||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.9", "", { "os": "win32", "cpu": "x64" }, "sha512-NS4g/2G9SoQ4ktKtz31pvyc/rmgzlcIDCGU/zWbmHJAqx6gcRj2gj5Q/guXhoWTzCUaQZDIqiCQXHS7BcGYc0w=="],
|
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.4.9", "", { "os": "win32", "cpu": "x64" }, "sha512-NS4g/2G9SoQ4ktKtz31pvyc/rmgzlcIDCGU/zWbmHJAqx6gcRj2gj5Q/guXhoWTzCUaQZDIqiCQXHS7BcGYc0w=="],
|
||||||
|
|
||||||
|
"@dnd-kit/abstract": ["@dnd-kit/abstract@0.3.2", "", { "dependencies": { "@dnd-kit/geometry": "^0.3.2", "@dnd-kit/state": "^0.3.2", "tslib": "^2.6.2" } }, "sha512-uvPVK+SZYD6Viddn9M0K0JQdXknuVSxA/EbMlFRanve3P/XTc18oLa5zGftKSGjfQGmuzkZ34E26DSbly1zi3Q=="],
|
||||||
|
|
||||||
|
"@dnd-kit/collision": ["@dnd-kit/collision@0.3.2", "", { "dependencies": { "@dnd-kit/abstract": "^0.3.2", "@dnd-kit/geometry": "^0.3.2", "tslib": "^2.6.2" } }, "sha512-pNmNSLCI8S9fNQ7QJ3fBCDjiT0sqBhUFcKgmyYaGvGCAU+kq0AP8OWlh0JSisc9k5mFyxmRpmFQcnJpILz/RPA=="],
|
||||||
|
|
||||||
|
"@dnd-kit/dom": ["@dnd-kit/dom@0.3.2", "", { "dependencies": { "@dnd-kit/abstract": "^0.3.2", "@dnd-kit/collision": "^0.3.2", "@dnd-kit/geometry": "^0.3.2", "@dnd-kit/state": "^0.3.2", "tslib": "^2.6.2" } }, "sha512-cIUAVgt2szQyz6JRy7I+0r+xeyOAGH21Y15hb5bIyHoDEaZBvIDH+OOlD9eoLjCbsxDLN9WloU2CBi3OE6LYDg=="],
|
||||||
|
|
||||||
|
"@dnd-kit/geometry": ["@dnd-kit/geometry@0.3.2", "", { "dependencies": { "@dnd-kit/state": "^0.3.2", "tslib": "^2.6.2" } }, "sha512-3UBPuIS7E3oGiHxOE8h810QA+0pnrnCtGxl4Os1z3yy5YkC/BEYGY+TxWPTQaY1/OMV7GCX7ZNMlama2QN3n3w=="],
|
||||||
|
|
||||||
|
"@dnd-kit/react": ["@dnd-kit/react@0.3.2", "", { "dependencies": { "@dnd-kit/abstract": "^0.3.2", "@dnd-kit/dom": "^0.3.2", "@dnd-kit/state": "^0.3.2", "tslib": "^2.6.2" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-1Opg1xw6I75Z95c+rF2NJa0pdGb8rLAENtuopKtJ1J0PudWlz+P6yL137xy/6DV43uaRmNGtsdbMbR0yRYJ72g=="],
|
||||||
|
|
||||||
|
"@dnd-kit/state": ["@dnd-kit/state@0.3.2", "", { "dependencies": { "@preact/signals-core": "^1.10.0", "tslib": "^2.6.2" } }, "sha512-dLUIkoYrIJhGXfF2wGLTfb46vUokEsO/OoE21TSfmahYrx7ysTmnwbePsznFaHlwgZhQEh6AlLvthLCeY21b1A=="],
|
||||||
|
|
||||||
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.11.0", "", {}, "sha512-hD3pekGiPg0WPCCGAZmusBBJsDqGUR66Y452YgQsZOnkdQ7ViEPKuyP4huUGEZQefp8g34RRodXYmJ2TbCH+tg=="],
|
"@drizzle-team/brocli": ["@drizzle-team/brocli@0.11.0", "", {}, "sha512-hD3pekGiPg0WPCCGAZmusBBJsDqGUR66Y452YgQsZOnkdQ7ViEPKuyP4huUGEZQefp8g34RRodXYmJ2TbCH+tg=="],
|
||||||
|
|
||||||
"@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
|
"@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
|
||||||
@@ -253,7 +291,11 @@
|
|||||||
|
|
||||||
"@js-temporal/polyfill": ["@js-temporal/polyfill@0.5.1", "", { "dependencies": { "jsbi": "^4.3.0" } }, "sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ=="],
|
"@js-temporal/polyfill": ["@js-temporal/polyfill@0.5.1", "", { "dependencies": { "jsbi": "^4.3.0" } }, "sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ=="],
|
||||||
|
|
||||||
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
|
"@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw=="],
|
||||||
|
|
||||||
|
"@noble/ciphers": ["@noble/ciphers@2.1.1", "", {}, "sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw=="],
|
||||||
|
|
||||||
|
"@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="],
|
||||||
|
|
||||||
"@oozcitak/dom": ["@oozcitak/dom@2.0.2", "", { "dependencies": { "@oozcitak/infra": "^2.0.2", "@oozcitak/url": "^3.0.0", "@oozcitak/util": "^10.0.0" } }, "sha512-GjpKhkSYC3Mj4+lfwEyI1dqnsKTgwGy48ytZEhm4A/xnH/8z9M3ZVXKr/YGQi3uCLs1AEBS+x5T2JPiueEDW8w=="],
|
"@oozcitak/dom": ["@oozcitak/dom@2.0.2", "", { "dependencies": { "@oozcitak/infra": "^2.0.2", "@oozcitak/url": "^3.0.0", "@oozcitak/util": "^10.0.0" } }, "sha512-GjpKhkSYC3Mj4+lfwEyI1dqnsKTgwGy48ytZEhm4A/xnH/8z9M3ZVXKr/YGQi3uCLs1AEBS+x5T2JPiueEDW8w=="],
|
||||||
|
|
||||||
@@ -263,69 +305,75 @@
|
|||||||
|
|
||||||
"@oozcitak/util": ["@oozcitak/util@10.0.0", "", {}, "sha512-hAX0pT/73190NLqBPPWSdBVGtbY6VOhWYK3qqHqtXQ1gK7kS2yz4+ivsN07hpJ6I3aeMtKP6J6npsEKOAzuTLA=="],
|
"@oozcitak/util": ["@oozcitak/util@10.0.0", "", {}, "sha512-hAX0pT/73190NLqBPPWSdBVGtbY6VOhWYK3qqHqtXQ1gK7kS2yz4+ivsN07hpJ6I3aeMtKP6J6npsEKOAzuTLA=="],
|
||||||
|
|
||||||
"@orpc/client": ["@orpc/client@1.13.11", "", { "dependencies": { "@orpc/shared": "1.13.11", "@orpc/standard-server": "1.13.11", "@orpc/standard-server-fetch": "1.13.11", "@orpc/standard-server-peer": "1.13.11" } }, "sha512-Hng/2evjsk58N+fU5X+1pqP5xucT/pvAGfKz14JOEo1IsdwBteJZq2ePCcvlqiNxBNdqEY45gio/JCK/zXv7VQ=="],
|
"@opentelemetry/api": ["@opentelemetry/api@1.9.1", "", {}, "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q=="],
|
||||||
|
|
||||||
"@orpc/contract": ["@orpc/contract@1.13.11", "", { "dependencies": { "@orpc/client": "1.13.11", "@orpc/shared": "1.13.11", "@standard-schema/spec": "^1.1.0", "openapi-types": "^12.1.3" } }, "sha512-Y8vVId49wVfQfnuhhsJM2haBJSxvs7OczXjb7YO4PhEwWahBnaqb+FG+zFJpfRWJl+cSJx+g8tkix7Z+Yq4UHw=="],
|
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.40.0", "", {}, "sha512-cifvXDhcqMwwTlTK04GBNeIe7yyo28Mfby85QXFe1Yk8nmi36Ab/5UQwptOx84SsoGNRg+EVSjwzfSZMy6pmlw=="],
|
||||||
|
|
||||||
"@orpc/interop": ["@orpc/interop@1.13.11", "", {}, "sha512-zBTqkKErpa5gdy+CZgUhnzYyDwBYxdARkcIILfbGr1yAKnbvRw53OPpJ2muPHSyJkEFD2xU8Y2f2719YmOYKBA=="],
|
"@orpc/client": ["@orpc/client@1.13.13", "", { "dependencies": { "@orpc/shared": "1.13.13", "@orpc/standard-server": "1.13.13", "@orpc/standard-server-fetch": "1.13.13", "@orpc/standard-server-peer": "1.13.13" } }, "sha512-jagx/Sa+9K4HEC5lBrUlMSrmR/06hvZctWh93/sKZc8GBk4zM0+71oT1kXQVw1oRYFV2XAq3xy3m6NdM6gfKYA=="],
|
||||||
|
|
||||||
"@orpc/json-schema": ["@orpc/json-schema@1.13.11", "", { "dependencies": { "@orpc/contract": "1.13.11", "@orpc/interop": "1.13.11", "@orpc/openapi": "1.13.11", "@orpc/server": "1.13.11", "@orpc/shared": "1.13.11", "json-schema-typed": "^8.0.2" } }, "sha512-InFaF7DBcBIVoGEiOBTYugYLwGBcC4+xQPnP0/Z2XxWtv3+mAYACfje4KffmT77krcUEgZWyK7xr9s/fnYgM/A=="],
|
"@orpc/contract": ["@orpc/contract@1.13.13", "", { "dependencies": { "@orpc/client": "1.13.13", "@orpc/shared": "1.13.13", "@standard-schema/spec": "^1.1.0", "openapi-types": "^12.1.3" } }, "sha512-md6iyrYkePBSJNs1VnVEEnAUORMDPHIf3JGRSHxyssIcNakev/iOjP0HvpH0Sx0MlTBhihAJo6uFL8Vpth58Nw=="],
|
||||||
|
|
||||||
"@orpc/openapi": ["@orpc/openapi@1.13.11", "", { "dependencies": { "@orpc/client": "1.13.11", "@orpc/contract": "1.13.11", "@orpc/interop": "1.13.11", "@orpc/openapi-client": "1.13.11", "@orpc/server": "1.13.11", "@orpc/shared": "1.13.11", "@orpc/standard-server": "1.13.11", "json-schema-typed": "^8.0.2", "rou3": "^0.7.12" } }, "sha512-buLA5deYXJXDGU8wKVGuALa6It9pL3fooUfD1yUjbEtfZPaROUuHOxzm/WsM6DNdMUKVDsMWuhLQ0hbpBaLaJg=="],
|
"@orpc/interop": ["@orpc/interop@1.13.13", "", {}, "sha512-S8edIRA7ekD3/gHx5MrsO9CxZ0QvCaVDkVbNf42SZbLYPXuvxtdH0CYwaB1q9uQg2Jk0PBP8AquLH6WFwjMSbQ=="],
|
||||||
|
|
||||||
"@orpc/openapi-client": ["@orpc/openapi-client@1.13.11", "", { "dependencies": { "@orpc/client": "1.13.11", "@orpc/contract": "1.13.11", "@orpc/shared": "1.13.11", "@orpc/standard-server": "1.13.11" } }, "sha512-Wx2z3jG3MRgNUPQzWlr6vL3r/QSGE579IG5IDOUzgSqSHyB3JGmA0cqLEM0ljOCndRDuxyRVe9UG9zeyZil/AQ=="],
|
"@orpc/json-schema": ["@orpc/json-schema@1.13.13", "", { "dependencies": { "@orpc/contract": "1.13.13", "@orpc/interop": "1.13.13", "@orpc/openapi": "1.13.13", "@orpc/server": "1.13.13", "@orpc/shared": "1.13.13", "json-schema-typed": "^8.0.2" } }, "sha512-48CgMrWIKG/t8l4OBlFRcYOj2ZCrIXfw1LA2Q6qRGdyBPzSLmQCMhh3Y4eoFXfz/wKvQIfyoUmBIdd91BxSyLg=="],
|
||||||
|
|
||||||
"@orpc/server": ["@orpc/server@1.13.11", "", { "dependencies": { "@orpc/client": "1.13.11", "@orpc/contract": "1.13.11", "@orpc/interop": "1.13.11", "@orpc/shared": "1.13.11", "@orpc/standard-server": "1.13.11", "@orpc/standard-server-aws-lambda": "1.13.11", "@orpc/standard-server-fastify": "1.13.11", "@orpc/standard-server-fetch": "1.13.11", "@orpc/standard-server-node": "1.13.11", "@orpc/standard-server-peer": "1.13.11", "cookie": "^1.1.1" }, "peerDependencies": { "crossws": ">=0.3.4", "ws": ">=8.18.1" }, "optionalPeers": ["crossws", "ws"] }, "sha512-BlVUwB5ArzaS2v/8V7tQ4w0Q2+rrjO8TntaLOoGxWnQOkH4gLznBEO5n8FgX3bKKlkwzTr5sbmuWwCCiV7yMGA=="],
|
"@orpc/openapi": ["@orpc/openapi@1.13.13", "", { "dependencies": { "@orpc/client": "1.13.13", "@orpc/contract": "1.13.13", "@orpc/interop": "1.13.13", "@orpc/openapi-client": "1.13.13", "@orpc/server": "1.13.13", "@orpc/shared": "1.13.13", "@orpc/standard-server": "1.13.13", "json-schema-typed": "^8.0.2", "rou3": "^0.7.12" } }, "sha512-lm3cAR1KJ1xp5WyDKCIqvhzYlDC914oevwYPWC7GFvTU1cTEmFP4lkQRdzLfvo06BprCg+UtHjzdLUDrBOF/zQ=="],
|
||||||
|
|
||||||
"@orpc/shared": ["@orpc/shared@1.13.11", "", { "dependencies": { "radash": "^12.1.1", "type-fest": "^5.4.4" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0" }, "optionalPeers": ["@opentelemetry/api"] }, "sha512-ia9y7gKdBaoV4pzSnvIuvedKYd3v9AJQ5FGzQl0Gcu6o9uXNZYB6j+oB/L91ULAmabDloWupd1tikSrw71DJmQ=="],
|
"@orpc/openapi-client": ["@orpc/openapi-client@1.13.13", "", { "dependencies": { "@orpc/client": "1.13.13", "@orpc/contract": "1.13.13", "@orpc/shared": "1.13.13", "@orpc/standard-server": "1.13.13" } }, "sha512-k8od+bD7MqysKPPybAkxgfaNIaNseFPXtbidWkZAdCZ5w34SnDc7QPZJ0PQbyt9n9B+jOXSADNwQSTWSuGpjyA=="],
|
||||||
|
|
||||||
"@orpc/standard-server": ["@orpc/standard-server@1.13.11", "", { "dependencies": { "@orpc/shared": "1.13.11" } }, "sha512-4Mx8LvruDSM6ZZIg/9nE7sErhBu/Y8wHAwCJ3Bbgq+I9C+A6qp1M8FiNU9Rxv37l0GVYQq/Gr1r+nzIcsBbWkg=="],
|
"@orpc/server": ["@orpc/server@1.13.13", "", { "dependencies": { "@orpc/client": "1.13.13", "@orpc/contract": "1.13.13", "@orpc/interop": "1.13.13", "@orpc/shared": "1.13.13", "@orpc/standard-server": "1.13.13", "@orpc/standard-server-aws-lambda": "1.13.13", "@orpc/standard-server-fastify": "1.13.13", "@orpc/standard-server-fetch": "1.13.13", "@orpc/standard-server-node": "1.13.13", "@orpc/standard-server-peer": "1.13.13", "cookie": "^1.1.1" }, "peerDependencies": { "crossws": ">=0.3.4", "ws": ">=8.18.1" }, "optionalPeers": ["crossws", "ws"] }, "sha512-l3OfiaqfLiLQqamXufKiEzT8K9Zq8VHvijADV5eDJOaz6sFzK1Mg6q2D8l9wcmuyG7ga0HfMT+cf3JQsh5WDIA=="],
|
||||||
|
|
||||||
"@orpc/standard-server-aws-lambda": ["@orpc/standard-server-aws-lambda@1.13.11", "", { "dependencies": { "@orpc/shared": "1.13.11", "@orpc/standard-server": "1.13.11", "@orpc/standard-server-fetch": "1.13.11", "@orpc/standard-server-node": "1.13.11" } }, "sha512-n3CR+yW6ZnW1nNBBWYVL8VFH4YzTySWkKRjkMfDxjkkbI0ocC8o/c4fNd2gDzzti5evOzPsuqF92fZHQs03EQw=="],
|
"@orpc/shared": ["@orpc/shared@1.13.13", "", { "dependencies": { "radash": "^12.1.1", "type-fest": "^5.4.4" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0" }, "optionalPeers": ["@opentelemetry/api"] }, "sha512-kNpYOBjHvmgKHla6munWOaEeA0utEfAvoiZpXjiRjjt1RxTibdwQvVHgxRIBNMXfQsb+ON3Q/wDkoaUhvvSnIw=="],
|
||||||
|
|
||||||
"@orpc/standard-server-fastify": ["@orpc/standard-server-fastify@1.13.11", "", { "dependencies": { "@orpc/shared": "1.13.11", "@orpc/standard-server": "1.13.11", "@orpc/standard-server-node": "1.13.11" }, "peerDependencies": { "fastify": ">=5.6.1" }, "optionalPeers": ["fastify"] }, "sha512-4gJITrIUb89btyv9yzfhVYRbkDatyHjiyeVBvHipp3SWIDPBE2GHrNFIDJp/7Vykxivbw56GeGhQrd/02Q9hwQ=="],
|
"@orpc/standard-server": ["@orpc/standard-server@1.13.13", "", { "dependencies": { "@orpc/shared": "1.13.13" } }, "sha512-9pgS8XvauuRQElkyuD8F3om+nN0KBEnTkhblDHCBzkZERjWkmfirJmshQrWHoFaDTk+nnXHIaY6d7TBTxXdPRw=="],
|
||||||
|
|
||||||
"@orpc/standard-server-fetch": ["@orpc/standard-server-fetch@1.13.11", "", { "dependencies": { "@orpc/shared": "1.13.11", "@orpc/standard-server": "1.13.11" } }, "sha512-A7L2ZlnYGeIV2FmC/do9DQT4As68FlbFWzUnPco7kmJt+GK37yY1MsuZYIhi2/Mi4LPqSYMR9IGuJsI/0K1e9A=="],
|
"@orpc/standard-server-aws-lambda": ["@orpc/standard-server-aws-lambda@1.13.13", "", { "dependencies": { "@orpc/shared": "1.13.13", "@orpc/standard-server": "1.13.13", "@orpc/standard-server-fetch": "1.13.13", "@orpc/standard-server-node": "1.13.13" } }, "sha512-e7310DnN6FSpRgR5gQpwvwg2B3uR+NoT7qlnyQWsjxQGr95L4GST3hRNSsQdQyXmFx1jvCCp0i3kAE9SJyvU6A=="],
|
||||||
|
|
||||||
"@orpc/standard-server-node": ["@orpc/standard-server-node@1.13.11", "", { "dependencies": { "@orpc/shared": "1.13.11", "@orpc/standard-server": "1.13.11", "@orpc/standard-server-fetch": "1.13.11" } }, "sha512-exU8WomH1wEEQw+vxzK+u1S3haVMZXz0flMxVkQETiSIzoAwnS2Z4HYLnF9BQQvck0t59tp6JpCovPuP3LqDTA=="],
|
"@orpc/standard-server-fastify": ["@orpc/standard-server-fastify@1.13.13", "", { "dependencies": { "@orpc/shared": "1.13.13", "@orpc/standard-server": "1.13.13", "@orpc/standard-server-node": "1.13.13" }, "peerDependencies": { "fastify": ">=5.6.1" }, "optionalPeers": ["fastify"] }, "sha512-G5Sq+rZDPwHvWJHsAA6bYWoJ7LcGyBby+SjjEGwz+viRdBk/inZnZafKpM+pL89aDdq6iw99Bcbug5WFPP6KdA=="],
|
||||||
|
|
||||||
"@orpc/standard-server-peer": ["@orpc/standard-server-peer@1.13.11", "", { "dependencies": { "@orpc/shared": "1.13.11", "@orpc/standard-server": "1.13.11" } }, "sha512-xIjB8reoKH1VYyR5KNyEKAfr+BntciuJxrewjVHNkdktDoRSo9sLpuGRdcT0Zl8biJUi8iys0xniY/Z25eZxSg=="],
|
"@orpc/standard-server-fetch": ["@orpc/standard-server-fetch@1.13.13", "", { "dependencies": { "@orpc/shared": "1.13.13", "@orpc/standard-server": "1.13.13" } }, "sha512-Lffy26+WtCQkwOUacsrdyeJF1GNzrhm75O3LXKVFXqmSdyVVdyI6zuqLn/YKGODU2L9IqGxZ2CwsV2tE298SSA=="],
|
||||||
|
|
||||||
"@orpc/tanstack-query": ["@orpc/tanstack-query@1.13.11", "", { "dependencies": { "@orpc/shared": "1.13.11" }, "peerDependencies": { "@orpc/client": "1.13.11", "@tanstack/query-core": ">=5.80.2" } }, "sha512-X+8+T9+ETTVMOey1HV4PA+dIPzBkkjh0QbDeeZvMp2N+oSQ1PxbZ9P3uiRO9Y9ljsl5gScfKhzwF6w4I9eCZHA=="],
|
"@orpc/standard-server-node": ["@orpc/standard-server-node@1.13.13", "", { "dependencies": { "@orpc/shared": "1.13.13", "@orpc/standard-server": "1.13.13", "@orpc/standard-server-fetch": "1.13.13" } }, "sha512-wI45h/bVWn7lgvqqm5aM7vj5BblmmBdFG2wbEhmpY85DslbCtMNJrIw/x+zxm1XgYAzsKLExLp6L01hzjeHmEA=="],
|
||||||
|
|
||||||
"@orpc/zod": ["@orpc/zod@1.13.11", "", { "dependencies": { "@orpc/json-schema": "1.13.11", "@orpc/openapi": "1.13.11", "@orpc/shared": "1.13.11", "escape-string-regexp": "^5.0.0", "wildcard-match": "^5.1.4" }, "peerDependencies": { "@orpc/contract": "1.13.11", "@orpc/server": "1.13.11", "zod": ">=3.25.0" } }, "sha512-1ORSiTSGjG4C/VrB436vrTFjpEPgemHEdsNUmkNUkgJo8vGd9ddiz/nTApWZDx9qKffFm0vGkXWZbaRViu214Q=="],
|
"@orpc/standard-server-peer": ["@orpc/standard-server-peer@1.13.13", "", { "dependencies": { "@orpc/shared": "1.13.13", "@orpc/standard-server": "1.13.13" } }, "sha512-FeWAbXfnZDPYQRajM0hD6GJvHeC3DZILngAjdcLHy5zt3riu6nL2lLPSWDv5yNWWscmYU+CfKmXWd0Z01BOeWA=="],
|
||||||
|
|
||||||
|
"@orpc/tanstack-query": ["@orpc/tanstack-query@1.13.13", "", { "dependencies": { "@orpc/shared": "1.13.13" }, "peerDependencies": { "@orpc/client": "1.13.13", "@tanstack/query-core": ">=5.80.2" } }, "sha512-6+Cheaiu+RDPdszdeRKoBINrF8MQp64zSeZB+L3gqgF43zlYDhLOgELZMzYa6U3U6bLk4rmIeubpk+i1kACfRg=="],
|
||||||
|
|
||||||
|
"@orpc/zod": ["@orpc/zod@1.13.13", "", { "dependencies": { "@orpc/json-schema": "1.13.13", "@orpc/openapi": "1.13.13", "@orpc/shared": "1.13.13", "escape-string-regexp": "^5.0.0", "wildcard-match": "^5.1.4" }, "peerDependencies": { "@orpc/contract": "1.13.13", "@orpc/server": "1.13.13", "zod": ">=3.25.0" } }, "sha512-K2iWGHopi3apExqNVb6EWJJqmq7cgytY3PjJyJ/Uy98UfJJ17Kwz7rAZKffNc7E967rNk9IH8MIcUcGkT7dmzQ=="],
|
||||||
|
|
||||||
"@oxc-project/types": ["@oxc-project/types@0.122.0", "", {}, "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA=="],
|
"@oxc-project/types": ["@oxc-project/types@0.122.0", "", {}, "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA=="],
|
||||||
|
|
||||||
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.11", "", { "os": "android", "cpu": "arm64" }, "sha512-SJ+/g+xNnOh6NqYxD0V3uVN4W3VfnrGsC9/hoglicgTNfABFG9JjISvkkU0dNY84MNHLWyOgxP9v9Y9pX4S7+A=="],
|
"@preact/signals-core": ["@preact/signals-core@1.14.0", "", {}, "sha512-AowtCcCU/33lFlh1zRFf/u+12rfrhtNakj7UpaGEsmMwUKpKWMVvcktOGcwBBNiB4lWrZWc01LhiyyzVklJyaQ=="],
|
||||||
|
|
||||||
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-7WQgR8SfOPwmDZGFkThUvsmd/nwAWv91oCO4I5LS7RKrssPZmOt7jONN0cW17ydGC1n/+puol1IpoieKqQidmg=="],
|
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.12", "", { "os": "android", "cpu": "arm64" }, "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA=="],
|
||||||
|
|
||||||
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-39Ks6UvIHq4rEogIfQBoBRusj0Q0nPVWIvqmwBLaT6aqQGIakHdESBVOPRRLacy4WwUPIx4ZKzfZ9PMW+IeyUQ=="],
|
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg=="],
|
||||||
|
|
||||||
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.11", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jfsm0ZHfhiqrvWjJAmzsqiIFPz5e7mAoCOPBNTcNgkiid/LaFKiq92+0ojH+nmJmKYkre4t71BWXUZDNp7vsag=="],
|
"@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.11", "", { "os": "linux", "cpu": "arm" }, "sha512-zjQaUtSyq1nVe3nxmlSCuR96T1LPlpvmJ0SZy0WJFEsV4kFbXcq2u68L4E6O0XeFj4aex9bEauqjW8UQBeAvfQ=="],
|
"@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-WMW1yE6IOnehTcFE9eipFkm3XN63zypWlrJQ2iF7NrQ9b2LDRjumFoOGJE8RJJTJCTBAdmLMnJ8uVitACUUo1Q=="],
|
"@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12", "", { "os": "linux", "cpu": "arm" }, "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-jfndI9tsfm4APzjNt6QdBkYwre5lRPUgHeDHoI7ydKUuJvz3lZeCfMsI56BZj+7BYqiKsJm7cfd/6KYV7ubrBg=="],
|
"@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.11", "", { "os": "linux", "cpu": "ppc64" }, "sha512-ZlFgw46NOAGMgcdvdYwAGu2Q+SLFA9LzbJLW+iyMOJyhj5wk6P3KEE9Gct4xWwSzFoPI7JCdYmYMzVtlgQ+zfw=="],
|
"@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.11", "", { "os": "linux", "cpu": "s390x" }, "sha512-hIOYmuT6ofM4K04XAZd3OzMySEO4K0/nc9+jmNcxNAxRi6c5UWpqfw3KMFV4MVFWL+jQsSh+bGw2VqmaPMTLyw=="],
|
"@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.11", "", { "os": "linux", "cpu": "x64" }, "sha512-qXBQQO9OvkjjQPLdUVr7Nr2t3QTZI7s4KZtfw7HzBgjbmAPSFwSv4rmET9lLSgq3rH/ndA3ngv3Qb8l2njoPNA=="],
|
"@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og=="],
|
||||||
|
|
||||||
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.11", "", { "os": "linux", "cpu": "x64" }, "sha512-/tpFfoSTzUkH9LPY+cYbqZBDyyX62w5fICq9qzsHLL8uTI6BHip3Q9Uzft0wylk/i8OOwKik8OxW+QAhDmzwmg=="],
|
"@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "x64" }, "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg=="],
|
||||||
|
|
||||||
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.11", "", { "os": "none", "cpu": "arm64" }, "sha512-mcp3Rio2w72IvdZG0oQ4bM2c2oumtwHfUfKncUM6zGgz0KgPz4YmDPQfnXEiY5t3+KD/i8HG2rOB/LxdmieK2g=="],
|
"@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.12", "", { "os": "linux", "cpu": "x64" }, "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig=="],
|
||||||
|
|
||||||
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.11", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-LXk5Hii1Ph9asuGRjBuz8TUxdc1lWzB7nyfdoRgI0WGPZKmCxvlKk8KfYysqtr4MfGElu/f/pEQRh8fcEgkrWw=="],
|
"@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.12", "", { "os": "none", "cpu": "arm64" }, "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA=="],
|
||||||
|
|
||||||
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-dDwf5otnx0XgRY1yqxOC4ITizcdzS/8cQ3goOWv3jFAo4F+xQYni+hnMuO6+LssHHdJW7+OCVL3CoU4ycnh35Q=="],
|
"@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.12", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg=="],
|
||||||
|
|
||||||
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.11", "", { "os": "win32", "cpu": "x64" }, "sha512-LN4/skhSggybX71ews7dAj6r2geaMJfm3kMbK2KhFMg9B10AZXnKoLCVVgzhMHL0S+aKtr4p8QbAW8k+w95bAA=="],
|
"@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q=="],
|
||||||
|
|
||||||
|
"@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.12", "", { "os": "win32", "cpu": "x64" }, "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw=="],
|
||||||
|
|
||||||
"@rolldown/plugin-babel": ["@rolldown/plugin-babel@0.2.2", "", { "dependencies": { "picomatch": "^4.0.3" }, "peerDependencies": { "@babel/core": "^7.29.0 || ^8.0.0-rc.1", "@babel/plugin-transform-runtime": "^7.29.0 || ^8.0.0-rc.1", "@babel/runtime": "^7.27.0 || ^8.0.0-rc.1", "rolldown": "^1.0.0-rc.5", "vite": "^8.0.0" }, "optionalPeers": ["@babel/plugin-transform-runtime", "@babel/runtime", "vite"] }, "sha512-q9pE8+47bQNHb5eWVcE6oXppA+JTSwvnrhH53m0ZuHuK5MLvwsLoWrWzBTFQqQ06BVxz1gp0HblLsch8o6pvZw=="],
|
"@rolldown/plugin-babel": ["@rolldown/plugin-babel@0.2.2", "", { "dependencies": { "picomatch": "^4.0.3" }, "peerDependencies": { "@babel/core": "^7.29.0 || ^8.0.0-rc.1", "@babel/plugin-transform-runtime": "^7.29.0 || ^8.0.0-rc.1", "@babel/runtime": "^7.27.0 || ^8.0.0-rc.1", "rolldown": "^1.0.0-rc.5", "vite": "^8.0.0" }, "optionalPeers": ["@babel/plugin-transform-runtime", "@babel/runtime", "vite"] }, "sha512-q9pE8+47bQNHb5eWVcE6oXppA+JTSwvnrhH53m0ZuHuK5MLvwsLoWrWzBTFQqQ06BVxz1gp0HblLsch8o6pvZw=="],
|
||||||
|
|
||||||
@@ -401,67 +449,67 @@
|
|||||||
|
|
||||||
"@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.95.2", "", { "dependencies": { "@tanstack/query-devtools": "5.95.2" }, "peerDependencies": { "@tanstack/react-query": "^5.95.2", "react": "^18 || ^19" } }, "sha512-AFQFmbznVkbtfpx8VJ2DylW17wWagQel/qLstVLkYmNRo2CmJt3SNej5hvl6EnEeljJIdC3BTB+W7HZtpsH+3g=="],
|
"@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.95.2", "", { "dependencies": { "@tanstack/query-devtools": "5.95.2" }, "peerDependencies": { "@tanstack/react-query": "^5.95.2", "react": "^18 || ^19" } }, "sha512-AFQFmbznVkbtfpx8VJ2DylW17wWagQel/qLstVLkYmNRo2CmJt3SNej5hvl6EnEeljJIdC3BTB+W7HZtpsH+3g=="],
|
||||||
|
|
||||||
"@tanstack/react-router": ["@tanstack/react-router@1.168.3", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-store": "^0.9.2", "@tanstack/router-core": "1.168.3", "isbot": "^5.1.22" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-hMWXhckeaSvjepHT5x9tUYJVXMvT/kUjaVHOUDmCfyOBtjxJNYJKbEWClXoopGwWlHjRTAzhsndhnQQRbIiKmA=="],
|
"@tanstack/react-router": ["@tanstack/react-router@1.168.8", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-store": "^0.9.3", "@tanstack/router-core": "1.168.7", "isbot": "^5.1.22" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-t0S0QueXubBKmI9eLPcN/A1sLQgTu8/yHerjrvvsGeD12zMdw0uJPKwEKpStQF2OThQtw64cs34uUSYXBUTSNw=="],
|
||||||
|
|
||||||
"@tanstack/react-router-devtools": ["@tanstack/react-router-devtools@1.166.11", "", { "dependencies": { "@tanstack/router-devtools-core": "1.167.1" }, "peerDependencies": { "@tanstack/react-router": "^1.168.2", "@tanstack/router-core": "^1.168.2", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["@tanstack/router-core"] }, "sha512-WYR3q4Xui5yPT/5PXtQh8i03iUA7q8dONBjWpV3nsGdM8Cs1FxpfhLstW0wZO1dOvSyElscwTRCJ6nO5N8r3Lg=="],
|
"@tanstack/react-router-devtools": ["@tanstack/react-router-devtools@1.166.11", "", { "dependencies": { "@tanstack/router-devtools-core": "1.167.1" }, "peerDependencies": { "@tanstack/react-router": "^1.168.2", "@tanstack/router-core": "^1.168.2", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["@tanstack/router-core"] }, "sha512-WYR3q4Xui5yPT/5PXtQh8i03iUA7q8dONBjWpV3nsGdM8Cs1FxpfhLstW0wZO1dOvSyElscwTRCJ6nO5N8r3Lg=="],
|
||||||
|
|
||||||
"@tanstack/react-router-ssr-query": ["@tanstack/react-router-ssr-query@1.166.10", "", { "dependencies": { "@tanstack/router-ssr-query-core": "1.167.0" }, "peerDependencies": { "@tanstack/query-core": ">=5.90.0", "@tanstack/react-query": ">=5.90.0", "@tanstack/react-router": ">=1.127.0", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-Ny5jKZPSy+RBXICJBJkW2q3SKjEwVooIn2zuWfIFL1MNVImQPh/p+yvqDqKdJseIQ45B4JsqFtWVcdy/6rQ0Rg=="],
|
"@tanstack/react-router-ssr-query": ["@tanstack/react-router-ssr-query@1.166.10", "", { "dependencies": { "@tanstack/router-ssr-query-core": "1.167.0" }, "peerDependencies": { "@tanstack/query-core": ">=5.90.0", "@tanstack/react-query": ">=5.90.0", "@tanstack/react-router": ">=1.127.0", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-Ny5jKZPSy+RBXICJBJkW2q3SKjEwVooIn2zuWfIFL1MNVImQPh/p+yvqDqKdJseIQ45B4JsqFtWVcdy/6rQ0Rg=="],
|
||||||
|
|
||||||
"@tanstack/react-start": ["@tanstack/react-start@1.167.6", "", { "dependencies": { "@tanstack/react-router": "1.168.3", "@tanstack/react-start-client": "1.166.18", "@tanstack/react-start-server": "1.166.18", "@tanstack/router-utils": "^1.161.6", "@tanstack/start-client-core": "1.167.3", "@tanstack/start-plugin-core": "1.167.9", "@tanstack/start-server-core": "1.167.3", "pathe": "^2.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0", "vite": ">=7.0.0" }, "bin": { "intent": "bin/intent.js" } }, "sha512-O/0O9QjC2Q5Wlftc7e9SsCWYDR/IK9Qz18q0T3yrm3kp11npW8EHuazHMrU+SXtAwHNJeg9oDRyxleR4Xcw90Q=="],
|
"@tanstack/react-start": ["@tanstack/react-start@1.167.13", "", { "dependencies": { "@tanstack/react-router": "1.168.8", "@tanstack/react-start-client": "1.166.23", "@tanstack/react-start-server": "1.166.23", "@tanstack/router-utils": "^1.161.6", "@tanstack/start-client-core": "1.167.7", "@tanstack/start-plugin-core": "1.167.14", "@tanstack/start-server-core": "1.167.7", "pathe": "^2.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0", "vite": ">=7.0.0" }, "bin": { "intent": "bin/intent.js" } }, "sha512-AM1mrQxoEu4/cWGmTO0RpWpZuryiPiMn75Il0fnYin4+PCKtqpvT6M5BjB5MEdoQ8NIhYdMZaC4D9IVEC0kESw=="],
|
||||||
|
|
||||||
"@tanstack/react-start-client": ["@tanstack/react-start-client@1.166.18", "", { "dependencies": { "@tanstack/react-router": "1.168.3", "@tanstack/router-core": "1.168.3", "@tanstack/start-client-core": "1.167.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-Z1KPQRKRI0wRMapFLk4Pv2TFr+MGq4PFCTv1GVv1cDP/74J3xavkF4wuFA2D/ljsl2wNLXAdDAtsJffc6Q8xkg=="],
|
"@tanstack/react-start-client": ["@tanstack/react-start-client@1.166.23", "", { "dependencies": { "@tanstack/react-router": "1.168.8", "@tanstack/router-core": "1.168.7", "@tanstack/start-client-core": "1.167.7" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-lNIdRuK6hIeUfDQEO9pLnFAnQ1/Q8tpMt297lixsci2u+g+EcTh0CwEFzkZRDq7py8Jiv53/cx1orq+RAMjUMg=="],
|
||||||
|
|
||||||
"@tanstack/react-start-server": ["@tanstack/react-start-server@1.166.18", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-router": "1.168.3", "@tanstack/router-core": "1.168.3", "@tanstack/start-client-core": "1.167.3", "@tanstack/start-server-core": "1.167.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-Eu0YJj2uR6IW0xV2ITQfp8V83HF3Ks0xwDkirRpOUk3QmQIUBdwEwQd+yStaOIQfPcMyIcpI92YxGCWFVu/jUA=="],
|
"@tanstack/react-start-server": ["@tanstack/react-start-server@1.166.23", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/react-router": "1.168.8", "@tanstack/router-core": "1.168.7", "@tanstack/start-client-core": "1.167.7", "@tanstack/start-server-core": "1.167.7" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-+ijM4apEyZSbPa5d27uxbaNWQP1xYnyVbCZg9ZbognhQob797e023lCK0yxaGYAGPltT7w/FC4msjTfFW+afNg=="],
|
||||||
|
|
||||||
"@tanstack/react-store": ["@tanstack/react-store@0.9.2", "", { "dependencies": { "@tanstack/store": "0.9.2", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Vt5usJE5sHG/cMechQfmwvwne6ktGCELe89Lmvoxe3LKRoFrhPa8OCKWs0NliG8HTJElEIj7PLtaBQIcux5pAQ=="],
|
"@tanstack/react-store": ["@tanstack/react-store@0.9.3", "", { "dependencies": { "@tanstack/store": "0.9.3", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-y2iHd/N9OkoQbFJLUX1T9vbc2O9tjH0pQRgTcx1/Nz4IlwLvkgpuglXUx+mXt0g5ZDFrEeDnONPqkbfxXJKwRg=="],
|
||||||
|
|
||||||
"@tanstack/router-core": ["@tanstack/router-core@1.168.3", "", { "dependencies": { "@tanstack/history": "1.161.6", "cookie-es": "^2.0.0", "seroval": "^1.4.2", "seroval-plugins": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-qcjArls3v12UQQkEpU0+todc0/MCyrEZeXxhtgZZ0e5gxZDG25BUe/HlNcIjzyb7NZaw0TQAUBXbTClmFaHZiw=="],
|
"@tanstack/router-core": ["@tanstack/router-core@1.168.7", "", { "dependencies": { "@tanstack/history": "1.161.6", "cookie-es": "^2.0.0", "seroval": "^1.4.2", "seroval-plugins": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-z4UEdlzMrFaKBsG4OIxlZEm+wsYBtEp//fnX6kW18jhQpETNcM6u2SXNdX+bcIYp6AaR7ERS3SBENzjC/xxwQQ=="],
|
||||||
|
|
||||||
"@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.167.1", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16" }, "peerDependencies": { "@tanstack/router-core": "^1.168.2", "csstype": "^3.0.10" }, "optionalPeers": ["csstype"] }, "sha512-ECMM47J4KmifUvJguGituSiBpfN8SyCUEoxQks5RY09hpIBfR2eswCv2e6cJimjkKwBQXOVTPkTUk/yRvER+9w=="],
|
"@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.167.1", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16" }, "peerDependencies": { "@tanstack/router-core": "^1.168.2", "csstype": "^3.0.10" }, "optionalPeers": ["csstype"] }, "sha512-ECMM47J4KmifUvJguGituSiBpfN8SyCUEoxQks5RY09hpIBfR2eswCv2e6cJimjkKwBQXOVTPkTUk/yRvER+9w=="],
|
||||||
|
|
||||||
"@tanstack/router-generator": ["@tanstack/router-generator@1.166.17", "", { "dependencies": { "@tanstack/router-core": "1.168.3", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-sBs6lyvA+B51hpUWYLx0KdaAIO/m9Ml2bsAdfVYyvs5DZXiAZZEbVD0myndyIkWaPR5x+kzuBakkrgTxJ9/m9Q=="],
|
"@tanstack/router-generator": ["@tanstack/router-generator@1.166.22", "", { "dependencies": { "@tanstack/router-core": "1.168.7", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-wQ7H8/Q2rmSPuaxWnurJ3DATNnqWV2tajxri9TSiW4QHsG7cWPD34+goeIinKG+GajJyEdfVpz6w/gRJXfbAPw=="],
|
||||||
|
|
||||||
"@tanstack/router-plugin": ["@tanstack/router-plugin@1.167.4", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@tanstack/router-core": "1.168.3", "@tanstack/router-generator": "1.166.17", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.168.3", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"], "bin": { "intent": "bin/intent.js" } }, "sha512-VChByI+CHdHMW350E6winbgqdX4tzmZIHovys8vXidRZkxGAhlygj/zhbnepF/TGX88rubj+SXDwSHY25qEcpQ=="],
|
"@tanstack/router-plugin": ["@tanstack/router-plugin@1.167.9", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5", "@tanstack/router-core": "1.168.7", "@tanstack/router-generator": "1.166.22", "@tanstack/router-utils": "1.161.6", "@tanstack/virtual-file-routes": "1.161.7", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.168.8", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"], "bin": { "intent": "bin/intent.js" } }, "sha512-h/VV05FEHd4PVyc5Zy8B3trWLcdLt/Pmp+mfifmBKGRw+MUtvdQKbBHhmy4ouOf67s5zDJMc+n8R3xgU7bDwFA=="],
|
||||||
|
|
||||||
"@tanstack/router-ssr-query-core": ["@tanstack/router-ssr-query-core@1.167.0", "", { "peerDependencies": { "@tanstack/query-core": ">=5.90.0", "@tanstack/router-core": ">=1.127.0" } }, "sha512-+fpK1U+NR8YzcUmXhEy2tdPfT/XxIn1AMd/ODkYGMExAAUWnV8Zptptf41djK5eBj6718P6YTfxLRkxtfUdnVA=="],
|
"@tanstack/router-ssr-query-core": ["@tanstack/router-ssr-query-core@1.167.0", "", { "peerDependencies": { "@tanstack/query-core": ">=5.90.0", "@tanstack/router-core": ">=1.127.0" } }, "sha512-+fpK1U+NR8YzcUmXhEy2tdPfT/XxIn1AMd/ODkYGMExAAUWnV8Zptptf41djK5eBj6718P6YTfxLRkxtfUdnVA=="],
|
||||||
|
|
||||||
"@tanstack/router-utils": ["@tanstack/router-utils@1.161.6", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "ansis": "^4.1.0", "babel-dead-code-elimination": "^1.0.12", "diff": "^8.0.2", "pathe": "^2.0.3", "tinyglobby": "^0.2.15" } }, "sha512-nRcYw+w2OEgK6VfjirYvGyPLOK+tZQz1jkYcmH5AjMamQ9PycnlxZF2aEZtPpNoUsaceX2bHptn6Ub5hGXqNvw=="],
|
"@tanstack/router-utils": ["@tanstack/router-utils@1.161.6", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/generator": "^7.28.5", "@babel/parser": "^7.28.5", "@babel/types": "^7.28.5", "ansis": "^4.1.0", "babel-dead-code-elimination": "^1.0.12", "diff": "^8.0.2", "pathe": "^2.0.3", "tinyglobby": "^0.2.15" } }, "sha512-nRcYw+w2OEgK6VfjirYvGyPLOK+tZQz1jkYcmH5AjMamQ9PycnlxZF2aEZtPpNoUsaceX2bHptn6Ub5hGXqNvw=="],
|
||||||
|
|
||||||
"@tanstack/start-client-core": ["@tanstack/start-client-core@1.167.3", "", { "dependencies": { "@tanstack/router-core": "1.168.3", "@tanstack/start-fn-stubs": "1.161.6", "@tanstack/start-storage-context": "1.166.17", "seroval": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-BdRCsV4aAvx+Nt2+uQFid0V+BaYCIRVhcHckgfQj+DIuk7w7fE4whTEqGYN9YAguOeqHvjrwNLdX2G3iW+Q1CA=="],
|
"@tanstack/start-client-core": ["@tanstack/start-client-core@1.167.7", "", { "dependencies": { "@tanstack/router-core": "1.168.7", "@tanstack/start-fn-stubs": "1.161.6", "@tanstack/start-storage-context": "1.166.21", "seroval": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-WKQYbaSKZzKdi7kaZHtIVlb2EFZin+EFNoE3sl53rcJjQNEcrmUHjLMBjxYQejD13dmIeQtPpKvPAM2s3uJ42g=="],
|
||||||
|
|
||||||
"@tanstack/start-fn-stubs": ["@tanstack/start-fn-stubs@1.161.6", "", {}, "sha512-Y6QSlGiLga8cHfvxGGaonXIlt2bIUTVdH6AMjmpMp7+ANNCp+N96GQbjjhLye3JkaxDfP68x5iZA8NK4imgRig=="],
|
"@tanstack/start-fn-stubs": ["@tanstack/start-fn-stubs@1.161.6", "", {}, "sha512-Y6QSlGiLga8cHfvxGGaonXIlt2bIUTVdH6AMjmpMp7+ANNCp+N96GQbjjhLye3JkaxDfP68x5iZA8NK4imgRig=="],
|
||||||
|
|
||||||
"@tanstack/start-plugin-core": ["@tanstack/start-plugin-core@1.167.9", "", { "dependencies": { "@babel/code-frame": "7.27.1", "@babel/core": "^7.28.5", "@babel/types": "^7.28.5", "@rolldown/pluginutils": "1.0.0-beta.40", "@tanstack/router-core": "1.168.3", "@tanstack/router-generator": "1.166.17", "@tanstack/router-plugin": "1.167.4", "@tanstack/router-utils": "1.161.6", "@tanstack/start-client-core": "1.167.3", "@tanstack/start-server-core": "1.167.3", "cheerio": "^1.0.0", "exsolve": "^1.0.7", "pathe": "^2.0.3", "picomatch": "^4.0.3", "source-map": "^0.7.6", "srvx": "^0.11.9", "tinyglobby": "^0.2.15", "ufo": "^1.5.4", "vitefu": "^1.1.1", "xmlbuilder2": "^4.0.3", "zod": "^3.24.2" }, "peerDependencies": { "vite": ">=7.0.0" } }, "sha512-ZXtwoaoEB/K0vDI3fkouu+Mkgy1BDc7er9p22aYEXDFUlGaP8wtMSW8hWsCAZayAoWSsEEvRj+4a1KLm9FSIgA=="],
|
"@tanstack/start-plugin-core": ["@tanstack/start-plugin-core@1.167.14", "", { "dependencies": { "@babel/code-frame": "7.27.1", "@babel/core": "^7.28.5", "@babel/types": "^7.28.5", "@rolldown/pluginutils": "1.0.0-beta.40", "@tanstack/router-core": "1.168.7", "@tanstack/router-generator": "1.166.22", "@tanstack/router-plugin": "1.167.9", "@tanstack/router-utils": "1.161.6", "@tanstack/start-client-core": "1.167.7", "@tanstack/start-server-core": "1.167.7", "cheerio": "^1.0.0", "exsolve": "^1.0.7", "pathe": "^2.0.3", "picomatch": "^4.0.3", "source-map": "^0.7.6", "srvx": "^0.11.9", "tinyglobby": "^0.2.15", "ufo": "^1.5.4", "vitefu": "^1.1.1", "xmlbuilder2": "^4.0.3", "zod": "^3.24.2" }, "peerDependencies": { "vite": ">=7.0.0" } }, "sha512-jSAyrmhMNe1b0UrBD/IB3ttLdmt5//jylOujxa39mUuyDzQGXITC5kacm26j/uJ713qfc3u17UtVKyo47UHmKA=="],
|
||||||
|
|
||||||
"@tanstack/start-server-core": ["@tanstack/start-server-core@1.167.3", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/router-core": "1.168.3", "@tanstack/start-client-core": "1.167.3", "@tanstack/start-storage-context": "1.166.17", "h3-v2": "npm:h3@2.0.1-rc.16", "seroval": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-w50a8R/8pxn+Ew5FdPuI6bC0LXNF70Mb4rogx9bckOKPS9FXLuRoitC5A3kMY+ibe5LJg/vkCZBAySdnsNWpZA=="],
|
"@tanstack/start-server-core": ["@tanstack/start-server-core@1.167.7", "", { "dependencies": { "@tanstack/history": "1.161.6", "@tanstack/router-core": "1.168.7", "@tanstack/start-client-core": "1.167.7", "@tanstack/start-storage-context": "1.166.21", "h3-v2": "npm:h3@2.0.1-rc.16", "seroval": "^1.4.2" }, "bin": { "intent": "bin/intent.js" } }, "sha512-P60/B0bj5bYFRGbHzHu/3RU0uIpoUwV+9f06lBUccaONyPuDbcP54d/vB6kJ109yvgREocilU5E83aOEnNPUkg=="],
|
||||||
|
|
||||||
"@tanstack/start-storage-context": ["@tanstack/start-storage-context@1.166.17", "", { "dependencies": { "@tanstack/router-core": "1.168.3" } }, "sha512-ZNADa14PLyc9FXMnD5YKTjaFKdDQoknm/5ddol5oXy6nN98TtnD4KuyxNC6cCzb0L416jwcbo6lQ0pqkKaQXDg=="],
|
"@tanstack/start-storage-context": ["@tanstack/start-storage-context@1.166.21", "", { "dependencies": { "@tanstack/router-core": "1.168.7" } }, "sha512-//vNgC2WK5Dw/j01i9AWq3VW7k8dqudDH9O86LFPmygfoKAhVONYs0CgWReoLVpjcc5QsMrjLI2Y95DF656acQ=="],
|
||||||
|
|
||||||
"@tanstack/store": ["@tanstack/store@0.9.2", "", {}, "sha512-K013lUJEFJK2ofFQ/hZKJUmCnpcV00ebLyOyFOWQvyQHUOZp/iYO84BM6aOGiV81JzwbX0APTVmW8YI7yiG5oA=="],
|
"@tanstack/store": ["@tanstack/store@0.9.3", "", {}, "sha512-8reSzl/qGWGGVKhBoxXPMWzATSbZLZFWhwBAFO9NAyp0TxzfBP0mIrGb8CP8KrQTmvzXlR/vFPPUrHTLBGyFyw=="],
|
||||||
|
|
||||||
"@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.161.7", "", { "bin": { "intent": "bin/intent.js" } }, "sha512-olW33+Cn+bsCsZKPwEGhlkqS6w3M2slFv11JIobdnCFKMLG97oAI2kWKdx5/zsywTL8flpnoIgaZZPlQTFYhdQ=="],
|
"@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.161.7", "", { "bin": { "intent": "bin/intent.js" } }, "sha512-olW33+Cn+bsCsZKPwEGhlkqS6w3M2slFv11JIobdnCFKMLG97oAI2kWKdx5/zsywTL8flpnoIgaZZPlQTFYhdQ=="],
|
||||||
|
|
||||||
"@tediousjs/connection-string": ["@tediousjs/connection-string@0.5.0", "", {}, "sha512-7qSgZbincDDDFyRweCIEvZULFAw5iz/DeunhvuxpL31nfntX3P4Yd4HkHBRg9H8CdqY1e5WFN1PZIz/REL9MVQ=="],
|
"@tediousjs/connection-string": ["@tediousjs/connection-string@0.5.0", "", {}, "sha512-7qSgZbincDDDFyRweCIEvZULFAw5iz/DeunhvuxpL31nfntX3P4Yd4HkHBRg9H8CdqY1e5WFN1PZIz/REL9MVQ=="],
|
||||||
|
|
||||||
"@turbo/darwin-64": ["@turbo/darwin-64@2.8.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-FQ9EX1xMU5nbwjxXxM3yU88AQQ6Sqc6S44exPRroMcx9XZHqqppl5ymJF0Ig/z3nvQNwDmz1Gsnvxubo+nXWjQ=="],
|
"@turbo/darwin-64": ["@turbo/darwin-64@2.8.21", "", { "os": "darwin", "cpu": "x64" }, "sha512-kfGoM0Iw8ZNZpbds+4IzOe0hjvHldqJwUPRAjXJi3KBxg/QOZL95N893SRoMtf2aJ+jJ3dk32yPkp8rvcIjP9g=="],
|
||||||
|
|
||||||
"@turbo/darwin-arm64": ["@turbo/darwin-arm64@2.8.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Gpyh9ATFGThD6/s9L95YWY54cizg/VRWl2B67h0yofG8BpHf67DFAh9nuJVKG7bY0+SBJDAo5cMur+wOl9YOYw=="],
|
"@turbo/darwin-arm64": ["@turbo/darwin-arm64@2.8.21", "", { "os": "darwin", "cpu": "arm64" }, "sha512-o9HEflxUEyr987x0cTUzZBhDOyL6u95JmdmlkH2VyxAw7zq2sdtM5e72y9ufv2N5SIoOBw1fVn9UES5VY5H6vQ=="],
|
||||||
|
|
||||||
"@turbo/linux-64": ["@turbo/linux-64@2.8.20", "", { "os": "linux", "cpu": "x64" }, "sha512-p2QxWUYyYUgUFG0b0kR+pPi8t7c9uaVlRtjTTI1AbCvVqkpjUfCcReBn6DgG/Hu8xrWdKLuyQFaLYFzQskZbcA=="],
|
"@turbo/linux-64": ["@turbo/linux-64@2.8.21", "", { "os": "linux", "cpu": "x64" }, "sha512-uTxlCcXWy5h1fSSymP8XSJ+AudzEHMDV3IDfKX7+DGB8kgJ+SLoTUAH7z4OFA7I/l2sznz0upPdbNNZs91YMag=="],
|
||||||
|
|
||||||
"@turbo/linux-arm64": ["@turbo/linux-arm64@2.8.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-Gn5yjlZGLRZWarLWqdQzv0wMqyBNIdq1QLi48F1oY5Lo9kiohuf7BPQWtWxeNVS2NgJ1+nb/DzK1JduYC4AWOA=="],
|
"@turbo/linux-arm64": ["@turbo/linux-arm64@2.8.21", "", { "os": "linux", "cpu": "arm64" }, "sha512-cdHIcxNcihHHkCHp0Y4Zb60K4Qz+CK4xw1gb6s/t/9o4SMeMj+hTBCtoW6QpPnl9xPYmxuTou8Zw6+cylTnREg=="],
|
||||||
|
|
||||||
"@turbo/windows-64": ["@turbo/windows-64@2.8.20", "", { "os": "win32", "cpu": "x64" }, "sha512-vyaDpYk/8T6Qz5V/X+ihKvKFEZFUoC0oxYpC1sZanK6gaESJlmV3cMRT3Qhcg4D2VxvtC2Jjs9IRkrZGL+exLw=="],
|
"@turbo/windows-64": ["@turbo/windows-64@2.8.21", "", { "os": "win32", "cpu": "x64" }, "sha512-/iBj4OzbqEY8CX+eaeKbBTMZv2CLXNrt0692F7HnK7LcyYwyDecaAiSET6ZzL4opT7sbwkKvzAC/fhqT3Quu1A=="],
|
||||||
|
|
||||||
"@turbo/windows-arm64": ["@turbo/windows-arm64@2.8.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-voicVULvUV5yaGXo0Iue13BcHGYW3u0VgqSbfQwBaHbpj1zLjYV4KIe+7fYIo6DO8FVUJzxFps3ODCQG/Wy2Qw=="],
|
"@turbo/windows-arm64": ["@turbo/windows-arm64@2.8.21", "", { "os": "win32", "cpu": "arm64" }, "sha512-95tMA/ZbIidJFUUtkmqioQ1gf3n3I1YbRP3ZgVdWTVn2qVbkodcIdGXBKRHHrIbRsLRl99SiHi/L7IxhpZDagQ=="],
|
||||||
|
|
||||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
|
|
||||||
"@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="],
|
"@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="],
|
||||||
|
|
||||||
"@types/mssql": ["@types/mssql@9.1.10", "", { "dependencies": { "@types/node": "*", "tarn": "^3.0.1", "tedious": "*" } }, "sha512-h3ImCiKdO7SM+2P1ToAZ+O0Ip23iISUHplH5GgMGnM9AwjmusDv8QqoNztoNj6vXpFbX29axsIybte7J2Q3XNg=="],
|
"@types/mssql": ["@types/mssql@9.1.11", "", { "dependencies": { "@types/node": "*", "tarn": "^3.0.1", "tedious": "*" } }, "sha512-vcujgrDbDezCxNDO4KY6gjwduLYOKfrexpRUwhoysRvcXZ3+IgZ/PMYFDgh8c3cQIxZ6skAwYo+H6ibMrBWPjQ=="],
|
||||||
|
|
||||||
"@types/node": ["@types/node@24.12.0", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ=="],
|
"@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
|
||||||
|
|
||||||
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||||
|
|
||||||
@@ -489,11 +537,13 @@
|
|||||||
|
|
||||||
"babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.12", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig=="],
|
"babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.12", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig=="],
|
||||||
|
|
||||||
"babel-plugin-react-compiler": ["babel-plugin-react-compiler@1.0.0", "", { "dependencies": { "@babel/types": "^7.26.0" } }, "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw=="],
|
|
||||||
|
|
||||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||||
|
|
||||||
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.10", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-sUoJ3IMxx4AyRqO4MLeHlnGDkyXRoUG0/AI9fjK+vS72ekpV0yWVY7O0BVjmBcRtkNcsAO2QDZ4tdKKGoI6YaQ=="],
|
"baseline-browser-mapping": ["baseline-browser-mapping@2.10.12", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ=="],
|
||||||
|
|
||||||
|
"better-auth": ["better-auth@1.5.6", "", { "dependencies": { "@better-auth/core": "1.5.6", "@better-auth/drizzle-adapter": "1.5.6", "@better-auth/kysely-adapter": "1.5.6", "@better-auth/memory-adapter": "1.5.6", "@better-auth/mongo-adapter": "1.5.6", "@better-auth/prisma-adapter": "1.5.6", "@better-auth/telemetry": "1.5.6", "@better-auth/utils": "0.3.1", "@better-fetch/fetch": "1.1.21", "@noble/ciphers": "^2.1.1", "@noble/hashes": "^2.0.1", "better-call": "1.3.2", "defu": "^6.1.4", "jose": "^6.1.3", "kysely": "^0.28.12", "nanostores": "^1.1.1", "zod": "^4.3.6" }, "peerDependencies": { "@lynx-js/react": "*", "@prisma/client": "^5.0.0 || ^6.0.0 || ^7.0.0", "@sveltejs/kit": "^2.0.0", "@tanstack/react-start": "^1.0.0", "@tanstack/solid-start": "^1.0.0", "better-sqlite3": "^12.0.0", "drizzle-kit": ">=0.31.4", "drizzle-orm": ">=0.41.0", "mongodb": "^6.0.0 || ^7.0.0", "mysql2": "^3.0.0", "next": "^14.0.0 || ^15.0.0 || ^16.0.0", "pg": "^8.0.0", "prisma": "^5.0.0 || ^6.0.0 || ^7.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0", "solid-js": "^1.0.0", "svelte": "^4.0.0 || ^5.0.0", "vitest": "^2.0.0 || ^3.0.0 || ^4.0.0", "vue": "^3.0.0" }, "optionalPeers": ["@lynx-js/react", "@prisma/client", "@sveltejs/kit", "@tanstack/react-start", "@tanstack/solid-start", "better-sqlite3", "drizzle-kit", "drizzle-orm", "mongodb", "mysql2", "next", "pg", "prisma", "react", "react-dom", "solid-js", "svelte", "vitest", "vue"] }, "sha512-QSpJTqaT1XVfWRQe/fm3PgeuwOIlz1nWX/Dx7nsHStJ382bLzmDbQk2u7IT0IJ6wS5SRxfqEE1Ev9TXontgyAQ=="],
|
||||||
|
|
||||||
|
"better-call": ["better-call@1.3.2", "", { "dependencies": { "@better-auth/utils": "^0.3.1", "@better-fetch/fetch": "^1.1.21", "rou3": "^0.7.12", "set-cookie-parser": "^3.0.1" }, "peerDependencies": { "zod": "^4.0.0" }, "optionalPeers": ["zod"] }, "sha512-4cZIfrerDsNTn3cm+MhLbUePN0gdwkhSXEuG7r/zuQ8c/H7iU0/jSK5TD3FW7U0MgKHce/8jGpPYNO4Ve+4NBw=="],
|
||||||
|
|
||||||
"binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
|
"binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
|
||||||
|
|
||||||
@@ -513,7 +563,7 @@
|
|||||||
|
|
||||||
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
|
"bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
|
||||||
|
|
||||||
"caniuse-lite": ["caniuse-lite@1.0.30001781", "", {}, "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw=="],
|
"caniuse-lite": ["caniuse-lite@1.0.30001782", "", {}, "sha512-dZcaJLJeDMh4rELYFw1tvSn1bhZWYFOt468FcbHHxx/Z/dFidd1I6ciyFdi3iwfQCyOjqo9upF6lGQYtMiJWxw=="],
|
||||||
|
|
||||||
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
||||||
|
|
||||||
@@ -555,6 +605,8 @@
|
|||||||
|
|
||||||
"define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
|
"define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
|
||||||
|
|
||||||
|
"defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="],
|
||||||
|
|
||||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||||
|
|
||||||
"diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
|
"diff": ["diff@8.0.4", "", {}, "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw=="],
|
||||||
@@ -567,15 +619,13 @@
|
|||||||
|
|
||||||
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
|
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
|
||||||
|
|
||||||
"dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
|
|
||||||
|
|
||||||
"drizzle-kit": ["drizzle-kit@1.0.0-beta.15-859cf75", "", { "dependencies": { "@drizzle-team/brocli": "^0.11.0", "@js-temporal/polyfill": "^0.5.1", "esbuild": "^0.25.10", "jiti": "^2.6.1" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-Y36s1XQGVb1PgU3aRNgufp1K3D2VkIifu8kv4Ubsmxi+Dq+N7KMklnpp7Knu/XC4FZi2MHPPG3v3o097r0/TcQ=="],
|
"drizzle-kit": ["drizzle-kit@1.0.0-beta.15-859cf75", "", { "dependencies": { "@drizzle-team/brocli": "^0.11.0", "@js-temporal/polyfill": "^0.5.1", "esbuild": "^0.25.10", "jiti": "^2.6.1" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-Y36s1XQGVb1PgU3aRNgufp1K3D2VkIifu8kv4Ubsmxi+Dq+N7KMklnpp7Knu/XC4FZi2MHPPG3v3o097r0/TcQ=="],
|
||||||
|
|
||||||
"drizzle-orm": ["drizzle-orm@1.0.0-beta.15-859cf75", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@effect/sql": "^0.48.5", "@effect/sql-pg": "^0.49.7", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@sinclair/typebox": ">=0.34.8", "@sqlitecloud/drivers": ">=1.0.653", "@tidbcloud/serverless": "*", "@tursodatabase/database": ">=0.2.1", "@tursodatabase/database-common": ">=0.2.1", "@tursodatabase/database-wasm": ">=0.2.1", "@types/better-sqlite3": "*", "@types/mssql": "^9.1.4", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "arktype": ">=2.0.0", "better-sqlite3": ">=9.3.0", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "mssql": "^11.0.1", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5", "typebox": ">=1.0.0", "valibot": ">=1.0.0-beta.7", "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@effect/sql", "@effect/sql-pg", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@sinclair/typebox", "@sqlitecloud/drivers", "@tidbcloud/serverless", "@tursodatabase/database", "@tursodatabase/database-common", "@tursodatabase/database-wasm", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "arktype", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "mysql2", "pg", "postgres", "sql.js", "sqlite3", "typebox", "valibot", "zod"] }, "sha512-dGVb2Q70H2AV6513hkOXR3Ud0FeGXLdugVq3YehoqkGIVTJrkuo0gRnCcW/dfI00O07t3T4HSh4clF/D/o/IsQ=="],
|
"drizzle-orm": ["drizzle-orm@1.0.0-beta.15-859cf75", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@effect/sql": "^0.48.5", "@effect/sql-pg": "^0.49.7", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@sinclair/typebox": ">=0.34.8", "@sqlitecloud/drivers": ">=1.0.653", "@tidbcloud/serverless": "*", "@tursodatabase/database": ">=0.2.1", "@tursodatabase/database-common": ">=0.2.1", "@tursodatabase/database-wasm": ">=0.2.1", "@types/better-sqlite3": "*", "@types/mssql": "^9.1.4", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "arktype": ">=2.0.0", "better-sqlite3": ">=9.3.0", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "mssql": "^11.0.1", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5", "typebox": ">=1.0.0", "valibot": ">=1.0.0-beta.7", "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@effect/sql", "@effect/sql-pg", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@sinclair/typebox", "@sqlitecloud/drivers", "@tidbcloud/serverless", "@tursodatabase/database", "@tursodatabase/database-common", "@tursodatabase/database-wasm", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "arktype", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "mysql2", "pg", "postgres", "sql.js", "sqlite3", "typebox", "valibot", "zod"] }, "sha512-dGVb2Q70H2AV6513hkOXR3Ud0FeGXLdugVq3YehoqkGIVTJrkuo0gRnCcW/dfI00O07t3T4HSh4clF/D/o/IsQ=="],
|
||||||
|
|
||||||
"ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
|
"ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
|
||||||
|
|
||||||
"electron-to-chromium": ["electron-to-chromium@1.5.322", "", {}, "sha512-vFU34OcrvMcH66T+dYC3G4nURmgfDVewMIu6Q2urXpumAPSMmzvcn04KVVV8Opikq8Vs5nUbO/8laNhNRqSzYw=="],
|
"electron-to-chromium": ["electron-to-chromium@1.5.328", "", {}, "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w=="],
|
||||||
|
|
||||||
"encoding-sniffer": ["encoding-sniffer@0.2.1", "", { "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" } }, "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw=="],
|
"encoding-sniffer": ["encoding-sniffer@0.2.1", "", { "dependencies": { "iconv-lite": "^0.6.3", "whatwg-encoding": "^3.1.1" } }, "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw=="],
|
||||||
|
|
||||||
@@ -583,7 +633,7 @@
|
|||||||
|
|
||||||
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||||
|
|
||||||
"env-runner": ["env-runner@0.1.6", "", { "dependencies": { "crossws": "^0.4.4", "httpxy": "^0.3.1", "srvx": "^0.11.9" }, "peerDependencies": { "miniflare": "^4.0.0" }, "optionalPeers": ["miniflare"], "bin": { "env-runner": "dist/cli.mjs" } }, "sha512-fSb7X1zdda8k6611a6/SdSQpDe7a/bqMz2UWdbHjk9YWzpUR4/fn9YtE/hqgGQ2nhvVN0zUtcL1SRMKwIsDbAA=="],
|
"env-runner": ["env-runner@0.1.7", "", { "dependencies": { "crossws": "^0.4.4", "exsolve": "^1.0.8", "httpxy": "^0.5.0", "srvx": "^0.11.13" }, "peerDependencies": { "@netlify/runtime": "^4", "miniflare": "^4.20260317.3" }, "optionalPeers": ["@netlify/runtime", "miniflare"], "bin": { "env-runner": "dist/cli.mjs" } }, "sha512-i7h96jxETJYhXy5grgHNJ9xNzCzWIn9Ck/VkkYgOlE4gOqknsLX3CmlVb5LmwNex8sOoLFVZLz+TIw/+b5rktA=="],
|
||||||
|
|
||||||
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
|
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
|
||||||
|
|
||||||
@@ -615,7 +665,7 @@
|
|||||||
|
|
||||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||||
|
|
||||||
"h3": ["h3@2.0.1-rc.19", "", { "dependencies": { "rou3": "^0.8.1", "srvx": "^0.11.12" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"], "bin": { "h3": "bin/h3.mjs" } }, "sha512-47er/mh8eGA7+0nvNUloalj+yTJ1ku8M0BVzA2I1ZHSlpfbUNdBK4LpWztfH7TwW6kuhF8MfAvl0AwB+X9B+2w=="],
|
"h3": ["h3@2.0.1-rc.20", "", { "dependencies": { "rou3": "^0.8.1", "srvx": "^0.11.13" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"], "bin": { "h3": "bin/h3.mjs" } }, "sha512-28ljodXuUp0fZovdiSRq4G9OgrxCztrJe5VdYzXAB7ueRvI7pIUqLU14Xi3XqdYJ/khXjfpUOOD2EQa6CmBgsg=="],
|
||||||
|
|
||||||
"h3-v2": ["h3@2.0.1-rc.16", "", { "dependencies": { "rou3": "^0.8.0", "srvx": "^0.11.9" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"], "bin": { "h3": "bin/h3.mjs" } }, "sha512-h+pjvyujdo9way8qj6FUbhaQcHlR8FEq65EhTX9ViT5pK8aLj68uFl4hBkF+hsTJAH+H1END2Yv6hTIsabGfag=="],
|
"h3-v2": ["h3@2.0.1-rc.16", "", { "dependencies": { "rou3": "^0.8.0", "srvx": "^0.11.9" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"], "bin": { "h3": "bin/h3.mjs" } }, "sha512-h+pjvyujdo9way8qj6FUbhaQcHlR8FEq65EhTX9ViT5pK8aLj68uFl4hBkF+hsTJAH+H1END2Yv6hTIsabGfag=="],
|
||||||
|
|
||||||
@@ -627,7 +677,7 @@
|
|||||||
|
|
||||||
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
||||||
|
|
||||||
"httpxy": ["httpxy@0.3.1", "", {}, "sha512-XjG/CEoofEisMrnFr0D6U6xOZ4mRfnwcYQ9qvvnT4lvnX8BoeA3x3WofB75D+vZwpaobFVkBIHrZzoK40w8XSw=="],
|
"httpxy": ["httpxy@0.5.0", "", {}, "sha512-qwX7QX/rK2visT10/b7bSeZWQOMlSm3svTD0pZpU+vJjNUP0YHtNv4c3z+MO+MSnGuRFWJFdCZiV+7F7dXIOzg=="],
|
||||||
|
|
||||||
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
||||||
|
|
||||||
@@ -653,6 +703,8 @@
|
|||||||
|
|
||||||
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
||||||
|
|
||||||
|
"jose": ["jose@6.2.2", "", {}, "sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ=="],
|
||||||
|
|
||||||
"js-md4": ["js-md4@0.3.2", "", {}, "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA=="],
|
"js-md4": ["js-md4@0.3.2", "", {}, "sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA=="],
|
||||||
|
|
||||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||||
@@ -673,6 +725,8 @@
|
|||||||
|
|
||||||
"jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
|
"jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
|
||||||
|
|
||||||
|
"kysely": ["kysely@0.28.14", "", {}, "sha512-SU3lgh0rPvq7upc6vvdVrCsSMUG1h3ChvHVOY7wJ2fw4C9QEB7X3d5eyYEyULUX7UQtxZJtZXGuT6U2US72UYA=="],
|
||||||
|
|
||||||
"launch-editor": ["launch-editor@2.13.2", "", { "dependencies": { "picocolors": "^1.1.1", "shell-quote": "^1.8.3" } }, "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg=="],
|
"launch-editor": ["launch-editor@2.13.2", "", { "dependencies": { "picocolors": "^1.1.1", "shell-quote": "^1.8.3" } }, "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg=="],
|
||||||
|
|
||||||
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
"lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
|
||||||
@@ -713,7 +767,9 @@
|
|||||||
|
|
||||||
"lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="],
|
"lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="],
|
||||||
|
|
||||||
"lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
|
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||||
|
|
||||||
|
"lucide-react": ["lucide-react@0.513.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-CJZKq2g8Y8yN4Aq002GahSXbG2JpFv9kXwyiOAMvUBv7pxeOFHUWKB0mO7MiY4ZVFCV4aNjv2BJFq/z3DgKPQg=="],
|
||||||
|
|
||||||
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
||||||
|
|
||||||
@@ -723,9 +779,11 @@
|
|||||||
|
|
||||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||||
|
|
||||||
|
"nanostores": ["nanostores@1.2.0", "", {}, "sha512-F0wCzbsH80G7XXo0Jd9/AVQC7ouWY6idUCTnMwW5t/Rv9W8qmO6endavDwg7TNp5GbugwSukFMVZqzPSrSMndg=="],
|
||||||
|
|
||||||
"native-duplexpair": ["native-duplexpair@1.0.0", "", {}, "sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA=="],
|
"native-duplexpair": ["native-duplexpair@1.0.0", "", {}, "sha512-E7QQoM+3jvNtlmyfqRZ0/U75VFgCls+fSkbml2MpgWkWyz3ox8Y58gNhfuziuQYGNNQAbFZJQck55LHCnCK6CA=="],
|
||||||
|
|
||||||
"nf3": ["nf3@0.3.13", "", {}, "sha512-drDt0yl4d/yUhlpD0GzzqahSpA5eUNeIfFq0/aoZb0UlPY0ZwP4u1EfREVvZrYdEnJ3OU9Le9TrzbvWgEkkeKw=="],
|
"nf3": ["nf3@0.3.14", "", {}, "sha512-MjG9u/IlvSq5txxY0oug1sjrGZ2l37IuhExI1iPuwV4S3RcyRNGoy6xLwznH3ATK6PUAM4fbQVb4Rzy1L1nlzw=="],
|
||||||
|
|
||||||
"nitro": ["nitro-nightly@3.0.1-20260324-103046-9ce219ca", "", { "dependencies": { "consola": "^3.4.2", "crossws": "^0.4.4", "db0": "^0.3.4", "env-runner": "^0.1.6", "h3": "^2.0.1-rc.19", "hookable": "^6.1.0", "nf3": "^0.3.13", "ocache": "^0.1.4", "ofetch": "^2.0.0-alpha.3", "ohash": "^2.0.11", "rolldown": "^1.0.0-rc.11", "srvx": "^0.11.13", "unenv": "^2.0.0-rc.24", "unstorage": "^2.0.0-alpha.7" }, "peerDependencies": { "dotenv": "*", "giget": "*", "jiti": "^2.6.1", "rollup": "^4.60.0", "vite": "^7 || ^8", "xml2js": "^0.6.2", "zephyr-agent": "^0.1.15" }, "optionalPeers": ["dotenv", "giget", "jiti", "rollup", "vite", "xml2js", "zephyr-agent"], "bin": { "nitro": "dist/cli/index.mjs" } }, "sha512-N9ZennO7ZNNZT0/mBwfA288zGC5l+fp2MVu8QPjCwpyNSS+yvZacQrgVzWJsrl2UAAPVRgTroKbAo+m1Fds/sw=="],
|
"nitro": ["nitro-nightly@3.0.1-20260324-103046-9ce219ca", "", { "dependencies": { "consola": "^3.4.2", "crossws": "^0.4.4", "db0": "^0.3.4", "env-runner": "^0.1.6", "h3": "^2.0.1-rc.19", "hookable": "^6.1.0", "nf3": "^0.3.13", "ocache": "^0.1.4", "ofetch": "^2.0.0-alpha.3", "ohash": "^2.0.11", "rolldown": "^1.0.0-rc.11", "srvx": "^0.11.13", "unenv": "^2.0.0-rc.24", "unstorage": "^2.0.0-alpha.7" }, "peerDependencies": { "dotenv": "*", "giget": "*", "jiti": "^2.6.1", "rollup": "^4.60.0", "vite": "^7 || ^8", "xml2js": "^0.6.2", "zephyr-agent": "^0.1.15" }, "optionalPeers": ["dotenv", "giget", "jiti", "rollup", "vite", "xml2js", "zephyr-agent"], "bin": { "nitro": "dist/cli/index.mjs" } }, "sha512-N9ZennO7ZNNZT0/mBwfA288zGC5l+fp2MVu8QPjCwpyNSS+yvZacQrgVzWJsrl2UAAPVRgTroKbAo+m1Fds/sw=="],
|
||||||
|
|
||||||
@@ -781,7 +839,7 @@
|
|||||||
|
|
||||||
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
"rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
|
||||||
|
|
||||||
"rolldown": ["rolldown@1.0.0-rc.11", "", { "dependencies": { "@oxc-project/types": "=0.122.0", "@rolldown/pluginutils": "1.0.0-rc.11" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.11", "@rolldown/binding-darwin-arm64": "1.0.0-rc.11", "@rolldown/binding-darwin-x64": "1.0.0-rc.11", "@rolldown/binding-freebsd-x64": "1.0.0-rc.11", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.11", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.11", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.11", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.11", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.11", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.11", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.11", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.11", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.11", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.11", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.11" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-NRjoKMusSjfRbSYiH3VSumlkgFe7kYAa3pzVOsVYVFY3zb5d7nS+a3KGQ7hJKXuYWbzJKPVQ9Wxq2UvyK+ENpw=="],
|
"rolldown": ["rolldown@1.0.0-rc.12", "", { "dependencies": { "@oxc-project/types": "=0.122.0", "@rolldown/pluginutils": "1.0.0-rc.12" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.12", "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", "@rolldown/binding-darwin-x64": "1.0.0-rc.12", "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A=="],
|
||||||
|
|
||||||
"rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="],
|
"rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="],
|
||||||
|
|
||||||
@@ -799,6 +857,8 @@
|
|||||||
|
|
||||||
"seroval-plugins": ["seroval-plugins@1.5.1", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-4FbuZ/TMl02sqv0RTFexu0SP6V+ywaIe5bAWCCEik0fk17BhALgwvUDVF7e3Uvf9pxmwCEJsRPmlkUE6HdzLAw=="],
|
"seroval-plugins": ["seroval-plugins@1.5.1", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-4FbuZ/TMl02sqv0RTFexu0SP6V+ywaIe5bAWCCEik0fk17BhALgwvUDVF7e3Uvf9pxmwCEJsRPmlkUE6HdzLAw=="],
|
||||||
|
|
||||||
|
"set-cookie-parser": ["set-cookie-parser@3.1.0", "", {}, "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw=="],
|
||||||
|
|
||||||
"shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="],
|
"shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="],
|
||||||
|
|
||||||
"solid-js": ["solid-js@1.9.12", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", "seroval-plugins": "~1.5.0" } }, "sha512-QzKaSJq2/iDrWR1As6MHZQ8fQkdOBf8GReYb7L5iKwMGceg7HxDcaOHk0at66tNgn9U2U7dXo8ZZpLIAmGMzgw=="],
|
"solid-js": ["solid-js@1.9.12", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", "seroval-plugins": "~1.5.0" } }, "sha512-QzKaSJq2/iDrWR1As6MHZQ8fQkdOBf8GReYb7L5iKwMGceg7HxDcaOHk0at66tNgn9U2U7dXo8ZZpLIAmGMzgw=="],
|
||||||
@@ -833,7 +893,7 @@
|
|||||||
|
|
||||||
"tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],
|
"tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],
|
||||||
|
|
||||||
"turbo": ["turbo@2.8.20", "", { "optionalDependencies": { "@turbo/darwin-64": "2.8.20", "@turbo/darwin-arm64": "2.8.20", "@turbo/linux-64": "2.8.20", "@turbo/linux-arm64": "2.8.20", "@turbo/windows-64": "2.8.20", "@turbo/windows-arm64": "2.8.20" }, "bin": { "turbo": "bin/turbo" } }, "sha512-Rb4qk5YT8RUwwdXtkLpkVhNEe/lor6+WV7S5tTlLpxSz6MjV5Qi8jGNn4gS6NAvrYGA/rNrE6YUQM85sCZUDbQ=="],
|
"turbo": ["turbo@2.8.21", "", { "optionalDependencies": { "@turbo/darwin-64": "2.8.21", "@turbo/darwin-arm64": "2.8.21", "@turbo/linux-64": "2.8.21", "@turbo/linux-arm64": "2.8.21", "@turbo/windows-64": "2.8.21", "@turbo/windows-arm64": "2.8.21" }, "bin": { "turbo": "bin/turbo" } }, "sha512-FlJ8OD5Qcp0jTAM7E4a/RhUzRNds2GzKlyxHKA6N247VLy628rrxAGlMpIXSz6VB430+TiQDJ/SMl6PL1lu6wQ=="],
|
||||||
|
|
||||||
"type-fest": ["type-fest@5.5.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g=="],
|
"type-fest": ["type-fest@5.5.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g=="],
|
||||||
|
|
||||||
@@ -841,9 +901,9 @@
|
|||||||
|
|
||||||
"ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
|
"ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
|
||||||
|
|
||||||
"undici": ["undici@7.24.5", "", {}, "sha512-3IWdCpjgxp15CbJnsi/Y9TCDE7HWVN19j1hmzVhoAkY/+CJx449tVxT5wZc1Gwg8J+P0LWvzlBzxYRnHJ+1i7Q=="],
|
"undici": ["undici@7.24.6", "", {}, "sha512-Xi4agocCbRzt0yYMZGMA6ApD7gvtUFaxm4ZmeacWI4cZxaF6C+8I8QfofC20NAePiB/IcvZmzkJ7XPa471AEtA=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
|
"undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
|
||||||
|
|
||||||
"unenv": ["unenv@2.0.0-rc.24", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw=="],
|
"unenv": ["unenv@2.0.0-rc.24", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw=="],
|
||||||
|
|
||||||
@@ -857,7 +917,7 @@
|
|||||||
|
|
||||||
"uuid": ["uuid@13.0.0", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w=="],
|
"uuid": ["uuid@13.0.0", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w=="],
|
||||||
|
|
||||||
"vite": ["vite@8.0.2", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.3", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.11", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-1gFhNi+bHhRE/qKZOJXACm6tX4bA3Isy9KuKF15AgSRuRazNBOJfdDemPBU16/mpMxApDPrWvZ08DcLPEoRnuA=="],
|
"vite": ["vite@8.0.3", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.12", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ=="],
|
||||||
|
|
||||||
"vitefu": ["vitefu@1.1.2", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw=="],
|
"vitefu": ["vitefu@1.1.2", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw=="],
|
||||||
|
|
||||||
@@ -875,21 +935,19 @@
|
|||||||
|
|
||||||
"xmlbuilder2": ["xmlbuilder2@4.0.3", "", { "dependencies": { "@oozcitak/dom": "^2.0.2", "@oozcitak/infra": "^2.0.2", "@oozcitak/util": "^10.0.0", "js-yaml": "^4.1.1" } }, "sha512-bx8Q1STctnNaaDymWnkfQLKofs0mGNN7rLLapJlGuV3VlvegD7Ls4ggMjE3aUSWItCCzU0PEv45lI87iSigiCA=="],
|
"xmlbuilder2": ["xmlbuilder2@4.0.3", "", { "dependencies": { "@oozcitak/dom": "^2.0.2", "@oozcitak/infra": "^2.0.2", "@oozcitak/util": "^10.0.0", "js-yaml": "^4.1.1" } }, "sha512-bx8Q1STctnNaaDymWnkfQLKofs0mGNN7rLLapJlGuV3VlvegD7Ls4ggMjE3aUSWItCCzU0PEv45lI87iSigiCA=="],
|
||||||
|
|
||||||
"yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
"yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
||||||
|
|
||||||
"zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
|
"zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
|
||||||
|
|
||||||
"@azure/msal-node/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
|
"@azure/msal-node/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="],
|
||||||
|
|
||||||
"@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
|
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" }, "bundled": true }, "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw=="],
|
||||||
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||||
|
|
||||||
@@ -921,12 +979,10 @@
|
|||||||
|
|
||||||
"recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
"recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
||||||
|
|
||||||
"rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.11", "", {}, "sha512-xQO9vbwBecJRv9EUcQ/y0dzSTJgA7Q6UVN7xp6B81+tBGSLVAK03yJ9NkJaUA7JFD91kbjxRSC/mDnmvXzbHoQ=="],
|
"rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.12", "", {}, "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw=="],
|
||||||
|
|
||||||
"tsx/esbuild": ["esbuild@0.27.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.4", "@esbuild/android-arm": "0.27.4", "@esbuild/android-arm64": "0.27.4", "@esbuild/android-x64": "0.27.4", "@esbuild/darwin-arm64": "0.27.4", "@esbuild/darwin-x64": "0.27.4", "@esbuild/freebsd-arm64": "0.27.4", "@esbuild/freebsd-x64": "0.27.4", "@esbuild/linux-arm": "0.27.4", "@esbuild/linux-arm64": "0.27.4", "@esbuild/linux-ia32": "0.27.4", "@esbuild/linux-loong64": "0.27.4", "@esbuild/linux-mips64el": "0.27.4", "@esbuild/linux-ppc64": "0.27.4", "@esbuild/linux-riscv64": "0.27.4", "@esbuild/linux-s390x": "0.27.4", "@esbuild/linux-x64": "0.27.4", "@esbuild/netbsd-arm64": "0.27.4", "@esbuild/netbsd-x64": "0.27.4", "@esbuild/openbsd-arm64": "0.27.4", "@esbuild/openbsd-x64": "0.27.4", "@esbuild/openharmony-arm64": "0.27.4", "@esbuild/sunos-x64": "0.27.4", "@esbuild/win32-arm64": "0.27.4", "@esbuild/win32-ia32": "0.27.4", "@esbuild/win32-x64": "0.27.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ=="],
|
"tsx/esbuild": ["esbuild@0.27.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.4", "@esbuild/android-arm": "0.27.4", "@esbuild/android-arm64": "0.27.4", "@esbuild/android-x64": "0.27.4", "@esbuild/darwin-arm64": "0.27.4", "@esbuild/darwin-x64": "0.27.4", "@esbuild/freebsd-arm64": "0.27.4", "@esbuild/freebsd-x64": "0.27.4", "@esbuild/linux-arm": "0.27.4", "@esbuild/linux-arm64": "0.27.4", "@esbuild/linux-ia32": "0.27.4", "@esbuild/linux-loong64": "0.27.4", "@esbuild/linux-mips64el": "0.27.4", "@esbuild/linux-ppc64": "0.27.4", "@esbuild/linux-riscv64": "0.27.4", "@esbuild/linux-s390x": "0.27.4", "@esbuild/linux-x64": "0.27.4", "@esbuild/netbsd-arm64": "0.27.4", "@esbuild/netbsd-x64": "0.27.4", "@esbuild/openbsd-arm64": "0.27.4", "@esbuild/openbsd-x64": "0.27.4", "@esbuild/openharmony-arm64": "0.27.4", "@esbuild/sunos-x64": "0.27.4", "@esbuild/win32-arm64": "0.27.4", "@esbuild/win32-ia32": "0.27.4", "@esbuild/win32-x64": "0.27.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ=="],
|
||||||
|
|
||||||
"@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
|
|
||||||
|
|
||||||
"tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="],
|
"tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q=="],
|
||||||
|
|
||||||
"tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.4", "", { "os": "android", "cpu": "arm" }, "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ=="],
|
"tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.4", "", { "os": "android", "cpu": "arm" }, "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ=="],
|
||||||
|
|||||||
@@ -49,6 +49,10 @@
|
|||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.4",
|
||||||
"tailwindcss": "^4.2.2",
|
"tailwindcss": "^4.2.2",
|
||||||
|
"@dnd-kit/dom": "^0.3.2",
|
||||||
|
"@dnd-kit/react": "^0.3.2",
|
||||||
|
"better-auth": "^1.2.8",
|
||||||
|
"lucide-react": "^0.513.0",
|
||||||
"uuid": "^13.0.0",
|
"uuid": "^13.0.0",
|
||||||
"vite": "^8.0.2",
|
"vite": "^8.0.2",
|
||||||
"zod": "^4.3.6"
|
"zod": "^4.3.6"
|
||||||
|
|||||||
Reference in New Issue
Block a user