feat(drizzle-duckdb-wasm): graph query visualization
Signed-off-by: Neko Ayaka <neko@ayaka.moe>
This commit is contained in:
@@ -75,21 +75,25 @@
|
||||
"date-fns": "^4.1.0",
|
||||
"defu": "^6.1.4",
|
||||
"drizzle-orm": "^0.40.0",
|
||||
"es-toolkit": "^1.32.0",
|
||||
"vue-router": "^4.5.0"
|
||||
"es-toolkit": "^1.32.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/solar": "^1.2.2",
|
||||
"@types/d3": "^7.4.3",
|
||||
"@types/d3-force": "^3.0.10",
|
||||
"@unocss/reset": "^66.1.0-beta.3",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"@vitest/browser": "^3.0.7",
|
||||
"@vueuse/core": "^12.7.0",
|
||||
"d3": "^7.9.0",
|
||||
"d3-force": "^3.0.0",
|
||||
"drizzle-kit": "^0.30.5",
|
||||
"playwright": "^1.50.1",
|
||||
"superjson": "^2.2.2",
|
||||
"unplugin-vue-router": "^0.11.2",
|
||||
"vite": "^6.2.0",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0",
|
||||
"vue-tsc": "^2.2.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,3 +45,42 @@ export const users = pgTable('users', () => ({
|
||||
timestamp: timestamp().notNull().default(sql`'2020-01-01 00:00:00'`),
|
||||
interval: interval().notNull().default(sql`'1 day'`),
|
||||
}))
|
||||
|
||||
export const nodeUsers = pgTable('node_users', () => ({
|
||||
id: uuid().primaryKey().unique().default(sql`gen_random_uuid()`),
|
||||
name: text().notNull().default(''),
|
||||
}))
|
||||
|
||||
export const nodePets = pgTable('node_pets', () => ({
|
||||
id: uuid().primaryKey().unique().default(sql`gen_random_uuid()`),
|
||||
name: text().notNull().default(''),
|
||||
}))
|
||||
|
||||
export const nodeGroups = pgTable('node_groups', () => ({
|
||||
id: uuid().primaryKey().unique().default(sql`gen_random_uuid()`),
|
||||
name: text().notNull().default(''),
|
||||
}))
|
||||
|
||||
export const edgePets = pgTable('edge_pets', () => ({
|
||||
id: uuid().primaryKey().unique().default(sql`gen_random_uuid()`),
|
||||
source: uuid(),
|
||||
target: uuid(),
|
||||
}))
|
||||
|
||||
export const edgeOwners = pgTable('edge_owners', () => ({
|
||||
id: uuid().primaryKey().unique().default(sql`gen_random_uuid()`),
|
||||
source: uuid(),
|
||||
target: uuid(),
|
||||
}))
|
||||
|
||||
export const edgeUsers = pgTable('edge_users', () => ({
|
||||
id: uuid().primaryKey().unique().default(sql`gen_random_uuid()`),
|
||||
source: uuid(),
|
||||
target: uuid(),
|
||||
}))
|
||||
|
||||
export const edgeGroups = pgTable('edge_groups', () => ({
|
||||
id: uuid().primaryKey().unique().default(sql`gen_random_uuid()`),
|
||||
source: uuid(),
|
||||
target: uuid(),
|
||||
}))
|
||||
|
||||
@@ -17,6 +17,6 @@ CREATE TABLE "users" (
|
||||
"date" date DEFAULT '2020-01-01' NOT NULL,
|
||||
"time" time DEFAULT '00:00:00' NOT NULL,
|
||||
"timestamp" timestamp DEFAULT '2020-01-01 00:00:00' NOT NULL,
|
||||
"interval" interval DEFAULT '0 day' NOT NULL,
|
||||
"interval" interval DEFAULT '1 day' NOT NULL,
|
||||
CONSTRAINT "users_id_unique" UNIQUE("id")
|
||||
);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
CREATE TABLE "edge_groups" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"source" uuid,
|
||||
"target" uuid,
|
||||
CONSTRAINT "edge_groups_id_unique" UNIQUE("id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "edge_owners" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"source" uuid,
|
||||
"target" uuid,
|
||||
CONSTRAINT "edge_owners_id_unique" UNIQUE("id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "edge_pets" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"source" uuid,
|
||||
"target" uuid,
|
||||
CONSTRAINT "edge_pets_id_unique" UNIQUE("id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "edge_users" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"source" uuid,
|
||||
"target" uuid,
|
||||
CONSTRAINT "edge_users_id_unique" UNIQUE("id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "node_groups" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"name" text DEFAULT '' NOT NULL,
|
||||
CONSTRAINT "node_groups_id_unique" UNIQUE("id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "node_pets" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"name" text DEFAULT '' NOT NULL,
|
||||
CONSTRAINT "node_pets_id_unique" UNIQUE("id")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE "node_users" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||
"name" text DEFAULT '' NOT NULL,
|
||||
CONSTRAINT "node_users_id_unique" UNIQUE("id")
|
||||
);
|
||||
@@ -0,0 +1,438 @@
|
||||
{
|
||||
"id": "f64005fe-f9b9-4673-84cb-a24695abff11",
|
||||
"prevId": "5305094b-45db-4a61-a74f-340b2b7da250",
|
||||
"version": "7",
|
||||
"dialect": "postgresql",
|
||||
"tables": {
|
||||
"public.edge_groups": {
|
||||
"name": "edge_groups",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"source": {
|
||||
"name": "source",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"target": {
|
||||
"name": "target",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"edge_groups_id_unique": {
|
||||
"name": "edge_groups_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.edge_owners": {
|
||||
"name": "edge_owners",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"source": {
|
||||
"name": "source",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"target": {
|
||||
"name": "target",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"edge_owners_id_unique": {
|
||||
"name": "edge_owners_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.edge_pets": {
|
||||
"name": "edge_pets",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"source": {
|
||||
"name": "source",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"target": {
|
||||
"name": "target",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"edge_pets_id_unique": {
|
||||
"name": "edge_pets_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.edge_users": {
|
||||
"name": "edge_users",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"source": {
|
||||
"name": "source",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
},
|
||||
"target": {
|
||||
"name": "target",
|
||||
"type": "uuid",
|
||||
"primaryKey": false,
|
||||
"notNull": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"edge_users_id_unique": {
|
||||
"name": "edge_users_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.node_groups": {
|
||||
"name": "node_groups",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "''"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"node_groups_id_unique": {
|
||||
"name": "node_groups_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.node_pets": {
|
||||
"name": "node_pets",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "''"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"node_pets_id_unique": {
|
||||
"name": "node_pets_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.node_users": {
|
||||
"name": "node_users",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "''"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"node_users_id_unique": {
|
||||
"name": "node_users_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
},
|
||||
"public.users": {
|
||||
"name": "users",
|
||||
"schema": "",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "uuid",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"default": "gen_random_uuid()"
|
||||
},
|
||||
"int16": {
|
||||
"name": "int16",
|
||||
"type": "smallint",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 0
|
||||
},
|
||||
"int32": {
|
||||
"name": "int32",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": 0
|
||||
},
|
||||
"int64": {
|
||||
"name": "int64",
|
||||
"type": "bigint",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "0"
|
||||
},
|
||||
"int64BigInt": {
|
||||
"name": "int64BigInt",
|
||||
"type": "bigint",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "0"
|
||||
},
|
||||
"decimal": {
|
||||
"name": "decimal",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "0"
|
||||
},
|
||||
"numeric": {
|
||||
"name": "numeric",
|
||||
"type": "numeric",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "0"
|
||||
},
|
||||
"real": {
|
||||
"name": "real",
|
||||
"type": "real",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "0"
|
||||
},
|
||||
"double": {
|
||||
"name": "double",
|
||||
"type": "double precision",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "0"
|
||||
},
|
||||
"vector": {
|
||||
"name": "vector",
|
||||
"type": "vector(4)",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "[0,0,0,0]"
|
||||
},
|
||||
"bool": {
|
||||
"name": "bool",
|
||||
"type": "boolean",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": false
|
||||
},
|
||||
"char": {
|
||||
"name": "char",
|
||||
"type": "char",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "''"
|
||||
},
|
||||
"varchar": {
|
||||
"name": "varchar",
|
||||
"type": "varchar",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "''"
|
||||
},
|
||||
"text": {
|
||||
"name": "text",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "''"
|
||||
},
|
||||
"json": {
|
||||
"name": "json",
|
||||
"type": "json",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'{}'"
|
||||
},
|
||||
"date": {
|
||||
"name": "date",
|
||||
"type": "date",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'2020-01-01'"
|
||||
},
|
||||
"time": {
|
||||
"name": "time",
|
||||
"type": "time",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'00:00:00'"
|
||||
},
|
||||
"timestamp": {
|
||||
"name": "timestamp",
|
||||
"type": "timestamp",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'2020-01-01 00:00:00'"
|
||||
},
|
||||
"interval": {
|
||||
"name": "interval",
|
||||
"type": "interval",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"default": "'1 day'"
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {
|
||||
"users_id_unique": {
|
||||
"name": "users_id_unique",
|
||||
"nullsNotDistinct": false,
|
||||
"columns": [
|
||||
"id"
|
||||
]
|
||||
}
|
||||
},
|
||||
"policies": {},
|
||||
"checkConstraints": {},
|
||||
"isRLSEnabled": false
|
||||
}
|
||||
},
|
||||
"enums": {},
|
||||
"schemas": {},
|
||||
"sequences": {},
|
||||
"roles": {},
|
||||
"policies": {},
|
||||
"views": {},
|
||||
"_meta": {
|
||||
"columns": {},
|
||||
"schemas": {},
|
||||
"tables": {}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,13 @@
|
||||
"when": 1739121102268,
|
||||
"tag": "0000_cute_kulan_gath",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"version": "7",
|
||||
"when": 1740841981623,
|
||||
"tag": "0001_parched_silver_centurion",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -7,7 +7,7 @@ const toggleDark = useToggle(isDark)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div flex flex-col gap-2 p-4>
|
||||
<div mx-auto max-w-screen-lg flex flex-col gap-2 p-4>
|
||||
<header flex flex-row items-center justify-between>
|
||||
<h1 text-2xl>
|
||||
<a href="https://github.com/duckdb/duckdb-wasm">🦆 <code>@duckdb/duckdb-wasm</code></a> + <a
|
||||
@@ -43,3 +43,24 @@ const toggleDark = useToggle(isDark)
|
||||
<RouterView />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
html {
|
||||
background: #fff;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
background: #121212;
|
||||
color-scheme: dark;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,859 @@
|
||||
<script setup lang="ts">
|
||||
import type { SimulationLinkDatum, SimulationNodeDatum } from 'd3'
|
||||
import type { DuckDBWasmDrizzleDatabase } from '../../../src'
|
||||
|
||||
import * as d3 from 'd3'
|
||||
// import { eq, inArray } from 'drizzle-orm'
|
||||
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
|
||||
import { drizzle } from '../../../src'
|
||||
import { buildDSN } from '../../../src/dsn'
|
||||
import * as schema from '../../db/schema'
|
||||
import { edgeGroups, edgeOwners, edgePets, edgeUsers, nodeGroups, nodePets, nodeUsers } from '../../db/schema'
|
||||
import migration1 from '../../drizzle/0001_parched_silver_centurion.sql?raw'
|
||||
|
||||
const db = ref<DuckDBWasmDrizzleDatabase<typeof schema>>()
|
||||
const results = ref<Record<string, unknown>[]>()
|
||||
// const schemaResults = ref<Record<string, unknown>[]>()
|
||||
const isMigrated = ref(false)
|
||||
|
||||
interface Node extends SimulationNodeDatum {
|
||||
id: string
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
|
||||
const graphData = ref<{ nodes: Node[], links: (SimulationLinkDatum<Node> & { type: string })[] }>({ nodes: [], links: [] })
|
||||
const queryResult = ref(null)
|
||||
const queryType = ref('simple') // 'simple', 'recursive', 'path'
|
||||
const selectedStartNode = ref(null)
|
||||
const selectedEndNode = ref(null)
|
||||
|
||||
async function connect() {
|
||||
isMigrated.value = false
|
||||
db.value = drizzle(buildDSN({
|
||||
scheme: 'duckdb-wasm:',
|
||||
bundles: 'import-url',
|
||||
logger: true,
|
||||
}), { schema })
|
||||
|
||||
await db.value?.execute('INSTALL vss;')
|
||||
await db.value?.execute('LOAD vss;')
|
||||
}
|
||||
|
||||
// Manual multi-level traversal: group -> users -> pets
|
||||
// async function getPetsInGroup(groupId: string) {
|
||||
// // First get all users in the group
|
||||
// const groupUsers = await db.value.select({ id: nodeUsers.id })
|
||||
// .from(nodeUsers)
|
||||
// .innerJoin(edgeGroups, eq(edgeGroups.target, nodeUsers.id))
|
||||
// .where(eq(edgeGroups.source, groupId))
|
||||
|
||||
// // Then get all pets owned by these users
|
||||
// const userIds = groupUsers.map(u => u.id)
|
||||
|
||||
// return await db.value.select({ pet: nodePets })
|
||||
// .from(nodePets)
|
||||
// .innerJoin(edgePets, eq(edgePets.target, nodePets.id))
|
||||
// .where(inArray(edgePets.source, userIds))
|
||||
// }
|
||||
|
||||
async function migrate() {
|
||||
await db.value?.execute(migration1)
|
||||
|
||||
const group1 = await db.value?.insert(nodeGroups).values({ id: crypto.randomUUID().replace(/-/g, ''), name: 'Group 1' }).returning()
|
||||
const group2 = await db.value?.insert(nodeGroups).values({ id: crypto.randomUUID().replace(/-/g, ''), name: 'Group 2' }).returning()
|
||||
const user1 = await db.value?.insert(nodeUsers).values({ id: crypto.randomUUID().replace(/-/g, ''), name: 'User 1' }).returning()
|
||||
const user2 = await db.value?.insert(nodeUsers).values({ id: crypto.randomUUID().replace(/-/g, ''), name: 'User 2' }).returning()
|
||||
const user3 = await db.value?.insert(nodeUsers).values({ id: crypto.randomUUID().replace(/-/g, ''), name: 'User 3' }).returning()
|
||||
const user4 = await db.value?.insert(nodeUsers).values({ id: crypto.randomUUID().replace(/-/g, ''), name: 'User 4' }).returning()
|
||||
const pet1 = await db.value?.insert(nodePets).values({ id: crypto.randomUUID().replace(/-/g, ''), name: 'Pet 1' }).returning()
|
||||
const pet2 = await db.value?.insert(nodePets).values({ id: crypto.randomUUID().replace(/-/g, ''), name: 'Pet 2' }).returning()
|
||||
|
||||
// Insert edges
|
||||
// User to Group edges (One to M)
|
||||
await db.value?.insert(edgeGroups).values({ id: crypto.randomUUID().replace(/-/g, ''), source: group1[0].id, target: user1[0].id }).returning()
|
||||
await db.value?.insert(edgeGroups).values({ id: crypto.randomUUID().replace(/-/g, ''), source: group1[0].id, target: user2[0].id }).returning()
|
||||
await db.value?.insert(edgeGroups).values({ id: crypto.randomUUID().replace(/-/g, ''), source: group2[0].id, target: user3[0].id }).returning()
|
||||
// Group to User edges (M to M)
|
||||
await db.value?.insert(edgeUsers).values({ id: crypto.randomUUID().replace(/-/g, ''), source: user1[0].id, target: group1[0].id }).returning()
|
||||
await db.value?.insert(edgeUsers).values({ id: crypto.randomUUID().replace(/-/g, ''), source: user2[0].id, target: group2[0].id }).returning()
|
||||
await db.value?.insert(edgeUsers).values({ id: crypto.randomUUID().replace(/-/g, ''), source: user3[0].id, target: group2[0].id }).returning()
|
||||
// User to Pet edges (One to M)
|
||||
await db.value?.insert(edgePets).values({ id: crypto.randomUUID().replace(/-/g, ''), source: user1[0].id, target: pet1[0].id }).returning()
|
||||
await db.value?.insert(edgePets).values({ id: crypto.randomUUID().replace(/-/g, ''), source: user2[0].id, target: pet2[0].id }).returning()
|
||||
// Pet to User edges (M to One)
|
||||
await db.value?.insert(edgeOwners).values({ id: crypto.randomUUID().replace(/-/g, ''), source: pet1[0].id, target: user1[0].id }).returning()
|
||||
await db.value?.insert(edgeOwners).values({ id: crypto.randomUUID().replace(/-/g, ''), source: pet2[0].id, target: user2[0].id }).returning()
|
||||
// // Create a more complex relationship - user4 has both pets
|
||||
await db.value?.insert(edgePets).values({ id: crypto.randomUUID().replace(/-/g, ''), source: user4[0].id, target: pet1[0].id }).returning()
|
||||
await db.value?.insert(edgePets).values({ id: crypto.randomUUID().replace(/-/g, ''), source: user4[0].id, target: pet2[0].id }).returning()
|
||||
|
||||
// First, let's check if our data was inserted correctly
|
||||
// console.log('Users:', await db.value?.select().from(nodeUsers))
|
||||
// console.log('Groups:', await db.value?.select().from(nodeGroups))
|
||||
// console.log('User-Group edges:', await db.value?.select().from(edgeGroups))
|
||||
// console.log('Group-User edges:', await db.value?.select().from(edgeGroups))
|
||||
|
||||
// console.log(await db.value?.execute(`
|
||||
// WITH RECURSIVE user_network AS (
|
||||
// -- Base case: start with the given user
|
||||
// SELECT id, name, 0 AS depth
|
||||
// FROM node_users
|
||||
// WHERE id = '${user1[0].id}'
|
||||
|
||||
// UNION ALL
|
||||
|
||||
// -- Find connections through groups
|
||||
// SELECT nu.id, nu.name, un.depth + 1
|
||||
// FROM user_network un
|
||||
// JOIN edge_users eu ON un.id = eu.source
|
||||
// JOIN node_groups ng ON eu.target = ng.id
|
||||
// JOIN edge_groups eg ON ng.id = eg.source
|
||||
// JOIN node_users nu ON eg.target = nu.id
|
||||
// WHERE un.depth < 3
|
||||
// )
|
||||
|
||||
// SELECT id, name, depth
|
||||
// FROM user_network
|
||||
// ORDER BY depth;`))
|
||||
|
||||
isMigrated.value = true
|
||||
}
|
||||
|
||||
// Fetch all nodes and edges for visualization
|
||||
async function fetchGraphData() {
|
||||
const users = await db.value?.select().from(nodeUsers)
|
||||
const groups = await db.value?.select().from(nodeGroups)
|
||||
const pets = await db.value?.select().from(nodePets)
|
||||
|
||||
const userEdges = await db.value?.select().from(edgeUsers)
|
||||
const groupEdges = await db.value?.select().from(edgeGroups)
|
||||
const petEdges = await db.value?.select().from(edgePets)
|
||||
const ownerEdges = await db.value?.select().from(edgeOwners)
|
||||
|
||||
// Prepare nodes with different types
|
||||
const nodes = [
|
||||
...users.map(u => ({ id: u.id, name: u.name, type: 'user' } satisfies Node)),
|
||||
...groups.map(g => ({ id: g.id, name: g.name, type: 'group' } satisfies Node)),
|
||||
...pets.map(p => ({ id: p.id, name: p.name, type: 'pet' } satisfies Node)),
|
||||
]
|
||||
|
||||
// Prepare links with different types
|
||||
const links = [
|
||||
...userEdges.map(e => ({ source: e.source, target: e.target, type: 'user-group' })),
|
||||
...groupEdges.map(e => ({ source: e.source, target: e.target, type: 'group-user' })),
|
||||
...petEdges.map(e => ({ source: e.source, target: e.target, type: 'user-pet' })),
|
||||
...ownerEdges.map(e => ({ source: e.source, target: e.target, type: 'pet-owner' })),
|
||||
]
|
||||
|
||||
graphData.value = { nodes, links }
|
||||
|
||||
// Set default selected nodes for queries
|
||||
if (nodes.length > 0) {
|
||||
selectedStartNode.value = nodes.find(n => n.type === 'user')?.id
|
||||
selectedEndNode.value = nodes.find(n => n.type === 'user' && n.id !== selectedStartNode.value)?.id
|
||||
}
|
||||
}
|
||||
|
||||
// Run a simple query to find direct connections
|
||||
async function runSimpleQuery() {
|
||||
if (!selectedStartNode.value)
|
||||
return
|
||||
|
||||
const result = await db.value?.execute(`
|
||||
-- Find direct connections from the selected node
|
||||
SELECT
|
||||
n.id, n.name,
|
||||
CASE
|
||||
WHEN n.id IN (SELECT id FROM node_users) THEN 'user'
|
||||
WHEN n.id IN (SELECT id FROM node_groups) THEN 'group'
|
||||
WHEN n.id IN (SELECT id FROM node_pets) THEN 'pet'
|
||||
END as type,
|
||||
e.source, e.target
|
||||
FROM (
|
||||
-- User to Group
|
||||
SELECT eu.source, eu.target, ng.id, ng.name
|
||||
FROM edge_users eu
|
||||
JOIN node_groups ng ON eu.target = ng.id
|
||||
WHERE eu.source = '${selectedStartNode.value}'
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- User to Pet
|
||||
SELECT ep.source, ep.target, np.id, np.name
|
||||
FROM edge_pets ep
|
||||
JOIN node_pets np ON ep.target = np.id
|
||||
WHERE ep.source = '${selectedStartNode.value}'
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- Group to User
|
||||
SELECT eg.source, eg.target, nu.id, nu.name
|
||||
FROM edge_groups eg
|
||||
JOIN node_users nu ON eg.target = nu.id
|
||||
WHERE eg.source = '${selectedStartNode.value}'
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- Pet to Owner
|
||||
SELECT eo.source, eo.target, nu.id, nu.name
|
||||
FROM edge_owners eo
|
||||
JOIN node_users nu ON eo.target = nu.id
|
||||
WHERE eo.source = '${selectedStartNode.value}'
|
||||
) e
|
||||
JOIN (
|
||||
SELECT id, name FROM node_users
|
||||
UNION ALL
|
||||
SELECT id, name FROM node_groups
|
||||
UNION ALL
|
||||
SELECT id, name FROM node_pets
|
||||
) n ON e.id = n.id
|
||||
`)
|
||||
|
||||
queryResult.value = result
|
||||
highlightQueryResults(result)
|
||||
}
|
||||
|
||||
// Run a recursive query to find paths
|
||||
async function runRecursiveQuery() {
|
||||
if (!selectedStartNode.value)
|
||||
return
|
||||
|
||||
const result = await db.value?.execute(`
|
||||
WITH RECURSIVE path_search AS (
|
||||
-- Base case: start with the given node
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
CASE
|
||||
WHEN id IN (SELECT id FROM node_users) THEN 'user'
|
||||
WHEN id IN (SELECT id FROM node_groups) THEN 'group'
|
||||
WHEN id IN (SELECT id FROM node_pets) THEN 'pet'
|
||||
END as type,
|
||||
0 AS depth,
|
||||
ARRAY[id] AS path
|
||||
FROM (
|
||||
SELECT id, name FROM node_users
|
||||
UNION ALL
|
||||
SELECT id, name FROM node_groups
|
||||
UNION ALL
|
||||
SELECT id, name FROM node_pets
|
||||
) nodes
|
||||
WHERE id = '${selectedStartNode.value}'
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- Recursive case: follow all possible edges
|
||||
SELECT
|
||||
target_node.id,
|
||||
target_node.name,
|
||||
CASE
|
||||
WHEN target_node.id IN (SELECT id FROM node_users) THEN 'user'
|
||||
WHEN target_node.id IN (SELECT id FROM node_groups) THEN 'group'
|
||||
WHEN target_node.id IN (SELECT id FROM node_pets) THEN 'pet'
|
||||
END as type,
|
||||
ps.depth + 1,
|
||||
ps.path || ARRAY[target_node.id]
|
||||
FROM path_search ps
|
||||
JOIN (
|
||||
-- All possible edges
|
||||
SELECT source, target FROM edge_users
|
||||
UNION ALL
|
||||
SELECT source, target FROM edge_groups
|
||||
UNION ALL
|
||||
SELECT source, target FROM edge_pets
|
||||
UNION ALL
|
||||
SELECT source, target FROM edge_owners
|
||||
) edges ON ps.id = edges.source
|
||||
JOIN (
|
||||
SELECT id, name FROM node_users
|
||||
UNION ALL
|
||||
SELECT id, name FROM node_groups
|
||||
UNION ALL
|
||||
SELECT id, name FROM node_pets
|
||||
) target_node ON edges.target = target_node.id
|
||||
WHERE ps.depth < 3
|
||||
AND NOT target_node.id = ANY(ps.path) -- Avoid cycles
|
||||
)
|
||||
|
||||
SELECT id, name, type, depth, path
|
||||
FROM path_search
|
||||
WHERE depth > 0 -- Exclude the starting node
|
||||
ORDER BY depth, name
|
||||
`)
|
||||
|
||||
queryResult.value = result
|
||||
highlightQueryResults(result)
|
||||
}
|
||||
|
||||
// Run a path finding query between two nodes
|
||||
async function runPathQuery() {
|
||||
if (!selectedStartNode.value || !selectedEndNode.value)
|
||||
return
|
||||
|
||||
const result = await db.value?.execute(`
|
||||
WITH RECURSIVE path_search AS (
|
||||
-- Base case: start with the given node
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
CASE
|
||||
WHEN id IN (SELECT id FROM node_users) THEN 'user'
|
||||
WHEN id IN (SELECT id FROM node_groups) THEN 'group'
|
||||
WHEN id IN (SELECT id FROM node_pets) THEN 'pet'
|
||||
END as type,
|
||||
0 AS depth,
|
||||
ARRAY[id] AS path,
|
||||
id = '${selectedEndNode.value}' AS found
|
||||
FROM (
|
||||
SELECT id, name FROM node_users
|
||||
UNION ALL
|
||||
SELECT id, name FROM node_groups
|
||||
UNION ALL
|
||||
SELECT id, name FROM node_pets
|
||||
) nodes
|
||||
WHERE id = '${selectedStartNode.value}'
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- Recursive case: follow all possible edges
|
||||
SELECT
|
||||
target_node.id,
|
||||
target_node.name,
|
||||
CASE
|
||||
WHEN target_node.id IN (SELECT id FROM node_users) THEN 'user'
|
||||
WHEN target_node.id IN (SELECT id FROM node_groups) THEN 'group'
|
||||
WHEN target_node.id IN (SELECT id FROM node_pets) THEN 'pet'
|
||||
END as type,
|
||||
ps.depth + 1,
|
||||
ps.path || ARRAY[target_node.id],
|
||||
target_node.id = '${selectedEndNode.value}' AS found
|
||||
FROM path_search ps
|
||||
JOIN (
|
||||
-- All possible edges
|
||||
SELECT source, target FROM edge_users
|
||||
UNION ALL
|
||||
SELECT source, target FROM edge_groups
|
||||
UNION ALL
|
||||
SELECT source, target FROM edge_pets
|
||||
UNION ALL
|
||||
SELECT source, target FROM edge_owners
|
||||
) edges ON ps.id = edges.source
|
||||
JOIN (
|
||||
SELECT id, name FROM node_users
|
||||
UNION ALL
|
||||
SELECT id, name FROM node_groups
|
||||
UNION ALL
|
||||
SELECT id, name FROM node_pets
|
||||
) target_node ON edges.target = target_node.id
|
||||
WHERE ps.depth < 5
|
||||
AND NOT target_node.id = ANY(ps.path) -- Avoid cycles
|
||||
AND NOT ps.found -- Stop once we've found the target
|
||||
)
|
||||
|
||||
SELECT id, name, type, depth, path
|
||||
FROM path_search
|
||||
WHERE found = true
|
||||
ORDER BY depth
|
||||
LIMIT 1
|
||||
`)
|
||||
|
||||
queryResult.value = result
|
||||
highlightQueryResults(result)
|
||||
}
|
||||
|
||||
// Highlight nodes and edges based on query results
|
||||
function highlightQueryResults(results) {
|
||||
// Reset all highlights
|
||||
d3.selectAll('.node').classed('highlighted', false).classed('in-path', false)
|
||||
d3.selectAll('.link').classed('highlighted', false).classed('in-path', false)
|
||||
|
||||
if (!results || !results.length)
|
||||
return
|
||||
|
||||
// For path queries, highlight the entire path
|
||||
if (results[0].path) {
|
||||
const pathIds = new Set()
|
||||
const pathLinks = new Set()
|
||||
|
||||
results.forEach((row) => {
|
||||
if (row.path && row.path.length > 1) {
|
||||
// Add all nodes in the path
|
||||
row.path.forEach(id => pathIds.add(id))
|
||||
|
||||
// Add all links in the path
|
||||
for (let i = 0; i < row.path.length - 1; i++) {
|
||||
pathLinks.add(`${row.path[i]}-${row.path[i + 1]}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// Highlight nodes in the path
|
||||
d3.selectAll('.node')
|
||||
.classed('in-path', (d: { id: string }) => pathIds.has(d.id))
|
||||
|
||||
// Highlight links in the path
|
||||
d3.selectAll('.link')
|
||||
.classed('in-path', (d: { source: { id: string }, target: { id: string } }) => {
|
||||
return pathLinks.has(`${d.source.id}-${d.target.id}`)
|
||||
|| pathLinks.has(`${d.target.id}-${d.source.id}`)
|
||||
})
|
||||
}
|
||||
// For simple queries, just highlight the direct connections
|
||||
else {
|
||||
const nodeIds = new Set(results.map(r => r.id))
|
||||
|
||||
// Highlight nodes
|
||||
d3.selectAll('.node')
|
||||
.classed('highlighted', (d: { id: string }) => nodeIds.has(d.id))
|
||||
|
||||
// Highlight links
|
||||
d3.selectAll('.link')
|
||||
.classed('highlighted', (d: { source: { id: string }, target: { id: string } }) => {
|
||||
return (d.source.id === selectedStartNode.value && nodeIds.has(d.target.id))
|
||||
|| (d.target.id === selectedStartNode.value && nodeIds.has(d.source.id))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Run the appropriate query based on the selected type
|
||||
function runQuery() {
|
||||
switch (queryType.value) {
|
||||
case 'simple':
|
||||
runSimpleQuery()
|
||||
break
|
||||
case 'recursive':
|
||||
runRecursiveQuery()
|
||||
break
|
||||
case 'path':
|
||||
runPathQuery()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Create the D3 force-directed graph
|
||||
function createGraph() {
|
||||
const width = 800
|
||||
const height = 600
|
||||
|
||||
// Clear previous graph
|
||||
d3.select('#graph-container').selectAll('*').remove()
|
||||
|
||||
// Create tooltip div
|
||||
const tooltip = d3.select('#graph-container')
|
||||
.append('div')
|
||||
.attr('class', 'tooltip w-full bg-neutral-100 dark:bg-neutral-800')
|
||||
.style('opacity', 0)
|
||||
.style('position', 'absolute')
|
||||
.style('padding', '8px')
|
||||
.style('border-radius', '4px')
|
||||
.style('pointer-events', 'none')
|
||||
.style('z-index', 10)
|
||||
.style('font-size', '12px')
|
||||
.style('max-width', '200px')
|
||||
|
||||
const svg = d3.select('#graph-container')
|
||||
.append('svg')
|
||||
.attr('width', width)
|
||||
.attr('height', height)
|
||||
.attr('viewBox', [0, 0, width, height])
|
||||
|
||||
// Define arrow markers for links
|
||||
svg.append('defs').selectAll('marker').data(['user-group', 'group-user', 'user-pet', 'pet-owner']).join('marker').attr('id', d => `arrow-${d}`).attr('viewBox', '0 -5 10 10').attr('refX', 15).attr('refY', 0).attr('markerWidth', 6).attr('markerHeight', 6).attr('orient', 'auto').append('path').attr('fill', (d) => {
|
||||
switch (d) {
|
||||
case 'user-group': return '#4CAF50'
|
||||
case 'group-user': return '#2196F3'
|
||||
case 'user-pet': return '#FF9800'
|
||||
case 'pet-owner': return '#9C27B0'
|
||||
default: return '#999'
|
||||
}
|
||||
}).attr('d', 'M0,-5L10,0L0,5')
|
||||
|
||||
// Create the simulation
|
||||
const simulation = d3.forceSimulation(graphData.value.nodes)
|
||||
.force('link', d3.forceLink(graphData.value.links).id(d => ('id' in d ? d.id : d) as string).distance(100))
|
||||
.force('charge', d3.forceManyBody().strength(-300))
|
||||
.force('center', d3.forceCenter(width / 2, height / 2))
|
||||
.force('collision', d3.forceCollide().radius(40))
|
||||
|
||||
// Create links
|
||||
const link = svg.append('g')
|
||||
.selectAll('line')
|
||||
.data(graphData.value.links)
|
||||
.join('line')
|
||||
.attr('class', 'link')
|
||||
.attr('stroke', (d) => {
|
||||
switch (d.type) {
|
||||
case 'user-group': return '#4CAF50'
|
||||
case 'group-user': return '#2196F3'
|
||||
case 'user-pet': return '#FF9800'
|
||||
case 'pet-owner': return '#9C27B0'
|
||||
default: return '#999'
|
||||
}
|
||||
})
|
||||
.attr('stroke-width', 2)
|
||||
.attr('marker-end', d => `url(#arrow-${d.type})`)
|
||||
.on('mouseover', function (event, d) {
|
||||
// Highlight the link
|
||||
d3.select(this).attr('stroke-width', 4)
|
||||
|
||||
// Show tooltip with edge information
|
||||
tooltip.transition()
|
||||
.duration(100)
|
||||
.style('opacity', 0.9)
|
||||
.ease()
|
||||
|
||||
let relationshipText = ''
|
||||
switch (d.type) {
|
||||
case 'user-group':
|
||||
relationshipText = 'User belongs to Group'
|
||||
break
|
||||
case 'group-user':
|
||||
relationshipText = 'Group contains User'
|
||||
break
|
||||
case 'user-pet':
|
||||
relationshipText = 'User owns Pet'
|
||||
break
|
||||
case 'pet-owner':
|
||||
relationshipText = 'Pet owned by User'
|
||||
break
|
||||
}
|
||||
|
||||
// Find source and target node names
|
||||
const sourceNode = graphData.value.nodes.find(n => n.id === (d.source as Node).id || n.id === d.source)
|
||||
const targetNode = graphData.value.nodes.find(n => n.id === (d.target as Node).id || n.id === d.target)
|
||||
|
||||
tooltip.html(`
|
||||
<div class="font-bold">${relationshipText}</div>
|
||||
<div>From: ${sourceNode?.name || 'Unknown'}</div>
|
||||
<div>To: ${targetNode?.name || 'Unknown'}</div>
|
||||
`)
|
||||
.style('left', `${event.pageX + 10}px`)
|
||||
.style('top', `${event.pageY - 28}px`)
|
||||
})
|
||||
.on('mouseout', function () {
|
||||
// Reset link thickness
|
||||
d3.select(this).attr('stroke-width', 2)
|
||||
|
||||
// Hide tooltip
|
||||
tooltip.transition()
|
||||
.duration(100)
|
||||
.style('opacity', 0)
|
||||
.ease()
|
||||
})
|
||||
|
||||
// Create node groups
|
||||
const node = svg.append('g')
|
||||
.selectAll('.node')
|
||||
.data(graphData.value.nodes)
|
||||
.join('g')
|
||||
.attr('class', 'node')
|
||||
.call(d3.drag<SVGCircleElement, Node>()
|
||||
.on('start', dragstarted)
|
||||
.on('drag', dragged)
|
||||
.on('end', dragended))
|
||||
.on('click', (event, d) => {
|
||||
// Toggle selection of nodes for queries
|
||||
if (event.ctrlKey || event.metaKey) {
|
||||
selectedEndNode.value = d.id
|
||||
}
|
||||
else {
|
||||
selectedStartNode.value = d.id
|
||||
}
|
||||
runQuery()
|
||||
})
|
||||
.on('mouseover', function (event, d) {
|
||||
// Show tooltip with node information
|
||||
tooltip.transition()
|
||||
.duration(100)
|
||||
.style('opacity', 0.9)
|
||||
.ease()
|
||||
|
||||
// Show if this is the selected start or end node
|
||||
let selectionStatus = ''
|
||||
if (d.id === selectedStartNode.value) {
|
||||
selectionStatus = '<div class="text-green-400">Start Node</div>'
|
||||
}
|
||||
else if (d.id === selectedEndNode.value) {
|
||||
selectionStatus = '<div class="text-red-400">End Node</div>'
|
||||
}
|
||||
|
||||
tooltip.html(`
|
||||
<div class="font-bold">${d.name}</div>
|
||||
<div class="text-xs dark:text-neutral-300 text-neutral-500">Type: ${d.type}</div>
|
||||
<div class="text-xs dark:text-neutral-300 text-neutral-500">ID: ${d.id}</div>
|
||||
${selectionStatus}
|
||||
`)
|
||||
.style('left', `${event.pageX + 10}px`)
|
||||
.style('top', `${event.pageY - 28}px`)
|
||||
|
||||
// Highlight the node
|
||||
d3.select(this).select('circle').transition().duration(100).attr('r', 25).ease()
|
||||
})
|
||||
.on('mouseout', function () {
|
||||
// Hide tooltip
|
||||
tooltip.transition()
|
||||
.duration(100)
|
||||
.style('opacity', 0)
|
||||
.ease()
|
||||
|
||||
// Reset node size
|
||||
d3.select(this).select('circle').transition().duration(100).attr('r', 20).ease()
|
||||
})
|
||||
|
||||
// Add circles to nodes
|
||||
node.append('circle')
|
||||
.attr('r', 20)
|
||||
.attr('fill', (d) => {
|
||||
switch (d.type) {
|
||||
case 'user': return '#E91E63'
|
||||
case 'group': return '#3F51B5'
|
||||
case 'pet': return '#FFC107'
|
||||
default: return '#999'
|
||||
}
|
||||
})
|
||||
|
||||
// Add small icons or initials inside nodes instead of full text
|
||||
node.append('text')
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('dy', '.35em')
|
||||
.attr('fill', 'white')
|
||||
.attr('font-size', '10px')
|
||||
.text((d) => {
|
||||
switch (d.type) {
|
||||
case 'user': return 'U'
|
||||
case 'group': return 'G'
|
||||
case 'pet': return 'P'
|
||||
default: return ''
|
||||
}
|
||||
})
|
||||
|
||||
// Update positions on each tick
|
||||
simulation.on('tick', () => {
|
||||
link
|
||||
.attr('x1', d => (d.source as SimulationNodeDatum).x)
|
||||
.attr('y1', d => (d.source as SimulationNodeDatum).y)
|
||||
.attr('x2', d => (d.target as SimulationNodeDatum).x)
|
||||
.attr('y2', d => (d.target as SimulationNodeDatum).y)
|
||||
|
||||
node.attr('transform', d => `translate(${d.x},${d.y})`)
|
||||
})
|
||||
|
||||
// Drag functions
|
||||
function dragstarted(event) {
|
||||
if (!event.active)
|
||||
simulation.alphaTarget(0.3).restart()
|
||||
event.subject.fx = event.subject.x
|
||||
event.subject.fy = event.subject.y
|
||||
}
|
||||
|
||||
function dragged(event) {
|
||||
event.subject.fx = event.x
|
||||
event.subject.fy = event.y
|
||||
}
|
||||
|
||||
function dragended(event) {
|
||||
if (!event.active)
|
||||
simulation.alphaTarget(0)
|
||||
event.subject.fx = null
|
||||
event.subject.fy = null
|
||||
}
|
||||
}
|
||||
|
||||
// Watch for changes in graph data and recreate the visualization
|
||||
watch(graphData, () => {
|
||||
if (graphData.value.nodes.length > 0) {
|
||||
createGraph()
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
await connect()
|
||||
await migrate()
|
||||
|
||||
results.value = await db.value?.execute('SHOW TABLES;')
|
||||
// const usersResults = await db.value?.select().from(users)
|
||||
// schemaResults.value = usersResults
|
||||
// console.log(results.value)
|
||||
|
||||
await fetchGraphData()
|
||||
isMigrated.value = true
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
db.value?.$client.then(client => client.close())
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Graph</h1>
|
||||
<div class="p-4">
|
||||
<div v-if="!isMigrated" class="py-8 text-center">
|
||||
<div class="mx-auto h-8 w-8 animate-spin border-4 border-blue-500 border-t-transparent rounded-full" />
|
||||
<p class="mt-4">
|
||||
Initializing database...
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div v-else class="grid grid-cols-1 gap-4 lg:grid-cols-3">
|
||||
<!-- Graph Visualization -->
|
||||
<div class="rounded-lg p-4 shadow lg:col-span-2">
|
||||
<h2 class="mb-2 text-lg font-semibold">
|
||||
Visualize
|
||||
</h2>
|
||||
<div id="graph-container" class="h-[600px] w-full" />
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
<div class="flex items-center">
|
||||
<div class="mr-2 h-4 w-4 rounded-full bg-[#E91E63]" />
|
||||
<span>User</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="mr-2 h-4 w-4 rounded-full bg-[#3F51B5]" />
|
||||
<span>Group</span>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="mr-2 h-4 w-4 rounded-full bg-[#FFC107]" />
|
||||
<span>Pet</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Controls and Results -->
|
||||
<div class="space-y-4">
|
||||
<!-- Query Controls -->
|
||||
<div class="rounded-lg p-4 shadow">
|
||||
<h2 class="mb-2 text-lg font-semibold">
|
||||
Query Controls
|
||||
</h2>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="mb-1 block text-sm font-medium">Query Type</label>
|
||||
<select v-model="queryType" class="w-full border rounded p-2">
|
||||
<option value="recursive">
|
||||
Recursive (All Paths)
|
||||
</option>
|
||||
<option value="path">
|
||||
Find Path Between Nodes
|
||||
</option>
|
||||
<option value="simple">
|
||||
Direct Connections
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="mb-1 block text-sm font-medium">Start Node</label>
|
||||
<select v-model="selectedStartNode" class="w-full border rounded p-2">
|
||||
<option v-for="node in graphData.nodes" :key="`start-${node.id}`" :value="node.id">
|
||||
{{ node.name }} ({{ node.type }})
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div v-if="queryType === 'path'" class="mb-4">
|
||||
<label class="mb-1 block text-sm font-medium">End Node</label>
|
||||
<select v-model="selectedEndNode" class="w-full border rounded p-2">
|
||||
<option v-for="node in graphData.nodes" :key="`end-${node.id}`" :value="node.id">
|
||||
{{ node.name }} ({{ node.type }})
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button class="w-full rounded bg-blue-100 px-4 py-2 dark:bg-blue-900" @click="runQuery">
|
||||
Run Query
|
||||
</button>
|
||||
|
||||
<div class="mt-2 text-sm text-neutral-500">
|
||||
<p>Click a node to select it as start node.</p>
|
||||
<p>Ctrl+Click to select as end node.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Query Results -->
|
||||
<div v-if="queryResult" class="rounded-lg p-4 shadow">
|
||||
<h2 class="mb-2 text-lg font-semibold">
|
||||
Query Results
|
||||
</h2>
|
||||
<div class="max-h-[300px] overflow-auto">
|
||||
<table class="min-w-full">
|
||||
<thead mb-2>
|
||||
<tr>
|
||||
<th
|
||||
class="border-b px-2 py-1 text-left text-xs text-neutral-500 font-medium tracking-wider uppercase"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
class="border-b px-2 py-1 text-left text-xs text-neutral-500 font-medium tracking-wider uppercase"
|
||||
>
|
||||
Type
|
||||
</th>
|
||||
<th
|
||||
class="border-b px-2 py-1 text-left text-xs text-neutral-500 font-medium tracking-wider uppercase"
|
||||
>
|
||||
Depth
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="(row, i) in queryResult" :key="i" class="hover:bg-neutral-50 dark:hover:bg-neutral-800"
|
||||
transition="all duration-250 ease-in-out" of-hidden
|
||||
>
|
||||
<td class="whitespace-nowrap px-2 py-1 text-sm" rounded-l-lg>
|
||||
{{ row.name }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-2 py-1 text-sm">
|
||||
{{ row.type }}
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-2 py-1 text-sm" rounded-r-lg>
|
||||
{{ row.depth }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.node circle {
|
||||
stroke: #fff;
|
||||
stroke-width: 2px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.node.highlighted circle {
|
||||
stroke: #ff0;
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
.node.in-path circle {
|
||||
stroke: #ff0;
|
||||
stroke-width: 3px;
|
||||
filter: drop-shadow(0 0 5px rgba(255, 255, 0, 0.7));
|
||||
}
|
||||
|
||||
.link {
|
||||
stroke-opacity: 0.6;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.link.highlighted {
|
||||
stroke-opacity: 1;
|
||||
stroke-width: 3px;
|
||||
}
|
||||
|
||||
.link.in-path {
|
||||
stroke-opacity: 1;
|
||||
stroke-width: 3px;
|
||||
filter: drop-shadow(0 0 3px rgba(255, 255, 0, 0.5));
|
||||
}
|
||||
|
||||
.tooltip {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -265,24 +265,3 @@ await db.select().from(users)
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overscroll-behavior: none;
|
||||
}
|
||||
|
||||
html {
|
||||
background: #fff;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
background: #121212;
|
||||
color-scheme: dark;
|
||||
}
|
||||
</style>
|
||||
|
||||
Generated
+615
-60
@@ -465,7 +465,7 @@ importers:
|
||||
version: 0.8.2
|
||||
'@gcornut/valibot-json-schema':
|
||||
specifier: ^0.42.0
|
||||
version: 0.42.0(esbuild@0.25.0)(typescript@5.8.2)
|
||||
version: 0.42.0(esbuild@0.19.12)(typescript@5.8.2)
|
||||
'@huggingface/transformers':
|
||||
specifier: ^3.3.3
|
||||
version: 3.3.3
|
||||
@@ -537,7 +537,7 @@ importers:
|
||||
version: 2.10.3
|
||||
'@typeschema/valibot':
|
||||
specifier: ^0.14.0
|
||||
version: 0.14.0(@gcornut/valibot-json-schema@0.42.0(esbuild@0.25.0)(typescript@5.8.2))(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2))
|
||||
version: 0.14.0(@gcornut/valibot-json-schema@0.42.0(esbuild@0.19.12)(typescript@5.8.2))(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2))
|
||||
'@unhead/vue':
|
||||
specifier: ^2.0.0-beta.2
|
||||
version: 2.0.0-beta.2(vue@3.5.13(typescript@5.8.2))
|
||||
@@ -736,7 +736,7 @@ importers:
|
||||
version: 28.4.1(@babel/parser@7.26.7)(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.34.9))(vue@3.5.13(typescript@5.8.2))
|
||||
unplugin-vue-macros:
|
||||
specifier: ^2.14.5
|
||||
version: 2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.25.0)(rollup@4.34.9)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
|
||||
version: 2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.19.12)(rollup@4.34.9)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
|
||||
unplugin-vue-markdown:
|
||||
specifier: ^28.3.1
|
||||
version: 28.3.1(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
|
||||
@@ -831,9 +831,6 @@ importers:
|
||||
es-toolkit:
|
||||
specifier: ^1.32.0
|
||||
version: 1.32.0
|
||||
vue-router:
|
||||
specifier: ^4.5.0
|
||||
version: 4.5.0(vue@3.5.13(typescript@5.8.2))
|
||||
web-worker:
|
||||
specifier: ^1.5.0
|
||||
version: 1.5.0
|
||||
@@ -841,6 +838,12 @@ importers:
|
||||
'@iconify-json/solar':
|
||||
specifier: ^1.2.2
|
||||
version: 1.2.2
|
||||
'@types/d3':
|
||||
specifier: ^7.4.3
|
||||
version: 7.4.3
|
||||
'@types/d3-force':
|
||||
specifier: ^3.0.10
|
||||
version: 3.0.10
|
||||
'@unocss/reset':
|
||||
specifier: ^66.1.0-beta.3
|
||||
version: 66.1.0-beta.3
|
||||
@@ -853,6 +856,12 @@ importers:
|
||||
'@vueuse/core':
|
||||
specifier: ^12.7.0
|
||||
version: 12.7.0(typescript@5.8.2)
|
||||
d3:
|
||||
specifier: ^7.9.0
|
||||
version: 7.9.0
|
||||
d3-force:
|
||||
specifier: ^3.0.0
|
||||
version: 3.0.0
|
||||
drizzle-kit:
|
||||
specifier: ^0.30.5
|
||||
version: 0.30.5
|
||||
@@ -871,6 +880,9 @@ importers:
|
||||
vue:
|
||||
specifier: ^3.5.13
|
||||
version: 3.5.13(typescript@5.8.2)
|
||||
vue-router:
|
||||
specifier: ^4.5.0
|
||||
version: 4.5.0(vue@3.5.13(typescript@5.8.2))
|
||||
vue-tsc:
|
||||
specifier: ^2.2.6
|
||||
version: 2.2.6(typescript@5.8.2)
|
||||
@@ -4227,6 +4239,99 @@ packages:
|
||||
'@types/cors@2.8.17':
|
||||
resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==}
|
||||
|
||||
'@types/d3-array@3.2.1':
|
||||
resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==}
|
||||
|
||||
'@types/d3-axis@3.0.6':
|
||||
resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==}
|
||||
|
||||
'@types/d3-brush@3.0.6':
|
||||
resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==}
|
||||
|
||||
'@types/d3-chord@3.0.6':
|
||||
resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==}
|
||||
|
||||
'@types/d3-color@3.1.3':
|
||||
resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==}
|
||||
|
||||
'@types/d3-contour@3.0.6':
|
||||
resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==}
|
||||
|
||||
'@types/d3-delaunay@6.0.4':
|
||||
resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==}
|
||||
|
||||
'@types/d3-dispatch@3.0.6':
|
||||
resolution: {integrity: sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==}
|
||||
|
||||
'@types/d3-drag@3.0.7':
|
||||
resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==}
|
||||
|
||||
'@types/d3-dsv@3.0.7':
|
||||
resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==}
|
||||
|
||||
'@types/d3-ease@3.0.2':
|
||||
resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==}
|
||||
|
||||
'@types/d3-fetch@3.0.7':
|
||||
resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==}
|
||||
|
||||
'@types/d3-force@3.0.10':
|
||||
resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==}
|
||||
|
||||
'@types/d3-format@3.0.4':
|
||||
resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==}
|
||||
|
||||
'@types/d3-geo@3.1.0':
|
||||
resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==}
|
||||
|
||||
'@types/d3-hierarchy@3.1.7':
|
||||
resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==}
|
||||
|
||||
'@types/d3-interpolate@3.0.4':
|
||||
resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==}
|
||||
|
||||
'@types/d3-path@3.1.1':
|
||||
resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==}
|
||||
|
||||
'@types/d3-polygon@3.0.2':
|
||||
resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==}
|
||||
|
||||
'@types/d3-quadtree@3.0.6':
|
||||
resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==}
|
||||
|
||||
'@types/d3-random@3.0.3':
|
||||
resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==}
|
||||
|
||||
'@types/d3-scale-chromatic@3.1.0':
|
||||
resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==}
|
||||
|
||||
'@types/d3-scale@4.0.9':
|
||||
resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==}
|
||||
|
||||
'@types/d3-selection@3.0.11':
|
||||
resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==}
|
||||
|
||||
'@types/d3-shape@3.1.7':
|
||||
resolution: {integrity: sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==}
|
||||
|
||||
'@types/d3-time-format@4.0.3':
|
||||
resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==}
|
||||
|
||||
'@types/d3-time@3.0.4':
|
||||
resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==}
|
||||
|
||||
'@types/d3-timer@3.0.2':
|
||||
resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==}
|
||||
|
||||
'@types/d3-transition@3.0.9':
|
||||
resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==}
|
||||
|
||||
'@types/d3-zoom@3.0.8':
|
||||
resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==}
|
||||
|
||||
'@types/d3@7.4.3':
|
||||
resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==}
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
|
||||
|
||||
@@ -4254,6 +4359,9 @@ packages:
|
||||
'@types/fs-extra@9.0.13':
|
||||
resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==}
|
||||
|
||||
'@types/geojson@7946.0.16':
|
||||
resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
|
||||
|
||||
'@types/glob-to-regexp@0.4.4':
|
||||
resolution: {integrity: sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg==}
|
||||
|
||||
@@ -5928,6 +6036,133 @@ packages:
|
||||
csstype@3.1.3:
|
||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||
|
||||
d3-array@3.2.4:
|
||||
resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-axis@3.0.0:
|
||||
resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-brush@3.0.0:
|
||||
resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-chord@3.0.1:
|
||||
resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-color@3.1.0:
|
||||
resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-contour@4.0.2:
|
||||
resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-delaunay@6.0.4:
|
||||
resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-dispatch@3.0.1:
|
||||
resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-drag@3.0.0:
|
||||
resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-dsv@3.0.1:
|
||||
resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==}
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
|
||||
d3-ease@3.0.1:
|
||||
resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-fetch@3.0.1:
|
||||
resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-force@3.0.0:
|
||||
resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-format@3.1.0:
|
||||
resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-geo@3.1.1:
|
||||
resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-hierarchy@3.1.2:
|
||||
resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-interpolate@3.0.1:
|
||||
resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-path@3.1.0:
|
||||
resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-polygon@3.0.1:
|
||||
resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-quadtree@3.0.1:
|
||||
resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-random@3.0.1:
|
||||
resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-scale-chromatic@3.1.0:
|
||||
resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-scale@4.0.2:
|
||||
resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-selection@3.0.0:
|
||||
resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-shape@3.2.0:
|
||||
resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-time-format@4.1.0:
|
||||
resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-time@3.1.0:
|
||||
resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-timer@3.0.1:
|
||||
resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3-transition@3.0.1:
|
||||
resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
d3-selection: 2 - 3
|
||||
|
||||
d3-zoom@3.0.0:
|
||||
resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d3@7.9.0:
|
||||
resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
d@1.0.2:
|
||||
resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
|
||||
engines: {node: '>=0.12'}
|
||||
@@ -6028,6 +6263,9 @@ packages:
|
||||
defu@6.1.4:
|
||||
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
|
||||
|
||||
delaunator@5.0.1:
|
||||
resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==}
|
||||
|
||||
delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
@@ -7446,6 +7684,10 @@ packages:
|
||||
resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
internmap@2.0.3:
|
||||
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
ip-address@9.0.5:
|
||||
resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==}
|
||||
engines: {node: '>= 12'}
|
||||
@@ -9690,6 +9932,9 @@ packages:
|
||||
resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==}
|
||||
engines: {node: '>=8.0'}
|
||||
|
||||
robust-predicates@3.0.2:
|
||||
resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==}
|
||||
|
||||
rollup-plugin-dts@6.1.1:
|
||||
resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==}
|
||||
engines: {node: '>=16'}
|
||||
@@ -9727,6 +9972,9 @@ packages:
|
||||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
rw@1.3.3:
|
||||
resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
|
||||
|
||||
rxjs@7.8.1:
|
||||
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
|
||||
|
||||
@@ -13035,6 +13283,16 @@ snapshots:
|
||||
|
||||
'@formkit/auto-animate@0.8.2': {}
|
||||
|
||||
'@gcornut/valibot-json-schema@0.42.0(esbuild@0.19.12)(typescript@5.8.2)':
|
||||
dependencies:
|
||||
valibot: 0.42.1(typescript@5.8.2)
|
||||
optionalDependencies:
|
||||
'@types/json-schema': 7.0.15
|
||||
esbuild-runner: 2.2.2(esbuild@0.19.12)
|
||||
transitivePeerDependencies:
|
||||
- esbuild
|
||||
- typescript
|
||||
|
||||
'@gcornut/valibot-json-schema@0.42.0(esbuild@0.25.0)(typescript@5.8.2)':
|
||||
dependencies:
|
||||
valibot: 0.42.1(typescript@5.8.2)
|
||||
@@ -14439,6 +14697,123 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/node': 22.13.8
|
||||
|
||||
'@types/d3-array@3.2.1': {}
|
||||
|
||||
'@types/d3-axis@3.0.6':
|
||||
dependencies:
|
||||
'@types/d3-selection': 3.0.11
|
||||
|
||||
'@types/d3-brush@3.0.6':
|
||||
dependencies:
|
||||
'@types/d3-selection': 3.0.11
|
||||
|
||||
'@types/d3-chord@3.0.6': {}
|
||||
|
||||
'@types/d3-color@3.1.3': {}
|
||||
|
||||
'@types/d3-contour@3.0.6':
|
||||
dependencies:
|
||||
'@types/d3-array': 3.2.1
|
||||
'@types/geojson': 7946.0.16
|
||||
|
||||
'@types/d3-delaunay@6.0.4': {}
|
||||
|
||||
'@types/d3-dispatch@3.0.6': {}
|
||||
|
||||
'@types/d3-drag@3.0.7':
|
||||
dependencies:
|
||||
'@types/d3-selection': 3.0.11
|
||||
|
||||
'@types/d3-dsv@3.0.7': {}
|
||||
|
||||
'@types/d3-ease@3.0.2': {}
|
||||
|
||||
'@types/d3-fetch@3.0.7':
|
||||
dependencies:
|
||||
'@types/d3-dsv': 3.0.7
|
||||
|
||||
'@types/d3-force@3.0.10': {}
|
||||
|
||||
'@types/d3-format@3.0.4': {}
|
||||
|
||||
'@types/d3-geo@3.1.0':
|
||||
dependencies:
|
||||
'@types/geojson': 7946.0.16
|
||||
|
||||
'@types/d3-hierarchy@3.1.7': {}
|
||||
|
||||
'@types/d3-interpolate@3.0.4':
|
||||
dependencies:
|
||||
'@types/d3-color': 3.1.3
|
||||
|
||||
'@types/d3-path@3.1.1': {}
|
||||
|
||||
'@types/d3-polygon@3.0.2': {}
|
||||
|
||||
'@types/d3-quadtree@3.0.6': {}
|
||||
|
||||
'@types/d3-random@3.0.3': {}
|
||||
|
||||
'@types/d3-scale-chromatic@3.1.0': {}
|
||||
|
||||
'@types/d3-scale@4.0.9':
|
||||
dependencies:
|
||||
'@types/d3-time': 3.0.4
|
||||
|
||||
'@types/d3-selection@3.0.11': {}
|
||||
|
||||
'@types/d3-shape@3.1.7':
|
||||
dependencies:
|
||||
'@types/d3-path': 3.1.1
|
||||
|
||||
'@types/d3-time-format@4.0.3': {}
|
||||
|
||||
'@types/d3-time@3.0.4': {}
|
||||
|
||||
'@types/d3-timer@3.0.2': {}
|
||||
|
||||
'@types/d3-transition@3.0.9':
|
||||
dependencies:
|
||||
'@types/d3-selection': 3.0.11
|
||||
|
||||
'@types/d3-zoom@3.0.8':
|
||||
dependencies:
|
||||
'@types/d3-interpolate': 3.0.4
|
||||
'@types/d3-selection': 3.0.11
|
||||
|
||||
'@types/d3@7.4.3':
|
||||
dependencies:
|
||||
'@types/d3-array': 3.2.1
|
||||
'@types/d3-axis': 3.0.6
|
||||
'@types/d3-brush': 3.0.6
|
||||
'@types/d3-chord': 3.0.6
|
||||
'@types/d3-color': 3.1.3
|
||||
'@types/d3-contour': 3.0.6
|
||||
'@types/d3-delaunay': 6.0.4
|
||||
'@types/d3-dispatch': 3.0.6
|
||||
'@types/d3-drag': 3.0.7
|
||||
'@types/d3-dsv': 3.0.7
|
||||
'@types/d3-ease': 3.0.2
|
||||
'@types/d3-fetch': 3.0.7
|
||||
'@types/d3-force': 3.0.10
|
||||
'@types/d3-format': 3.0.4
|
||||
'@types/d3-geo': 3.1.0
|
||||
'@types/d3-hierarchy': 3.1.7
|
||||
'@types/d3-interpolate': 3.0.4
|
||||
'@types/d3-path': 3.1.1
|
||||
'@types/d3-polygon': 3.0.2
|
||||
'@types/d3-quadtree': 3.0.6
|
||||
'@types/d3-random': 3.0.3
|
||||
'@types/d3-scale': 4.0.9
|
||||
'@types/d3-scale-chromatic': 3.1.0
|
||||
'@types/d3-selection': 3.0.11
|
||||
'@types/d3-shape': 3.1.7
|
||||
'@types/d3-time': 3.0.4
|
||||
'@types/d3-time-format': 4.0.3
|
||||
'@types/d3-timer': 3.0.2
|
||||
'@types/d3-transition': 3.0.9
|
||||
'@types/d3-zoom': 3.0.8
|
||||
|
||||
'@types/debug@4.1.12':
|
||||
dependencies:
|
||||
'@types/ms': 0.7.34
|
||||
@@ -14466,6 +14841,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/node': 22.13.8
|
||||
|
||||
'@types/geojson@7946.0.16': {}
|
||||
|
||||
'@types/glob-to-regexp@0.4.4': {}
|
||||
|
||||
'@types/hast@3.0.4':
|
||||
@@ -14619,11 +14996,20 @@ snapshots:
|
||||
dependencies:
|
||||
'@typeschema/core': 0.14.0(@types/json-schema@7.0.15)
|
||||
optionalDependencies:
|
||||
'@typeschema/valibot': 0.14.0(@gcornut/valibot-json-schema@0.42.0(esbuild@0.25.0)(typescript@5.8.2))(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2))
|
||||
'@typeschema/valibot': 0.14.0(@gcornut/valibot-json-schema@0.42.0(esbuild@0.19.12)(typescript@5.8.2))(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2))
|
||||
'@typeschema/zod': 0.14.0(@types/json-schema@7.0.15)(zod-to-json-schema@3.24.3(zod@3.24.2))(zod@3.24.2)
|
||||
transitivePeerDependencies:
|
||||
- '@types/json-schema'
|
||||
|
||||
'@typeschema/valibot@0.14.0(@gcornut/valibot-json-schema@0.42.0(esbuild@0.19.12)(typescript@5.8.2))(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2))':
|
||||
dependencies:
|
||||
'@typeschema/core': 0.14.0(@types/json-schema@7.0.15)
|
||||
optionalDependencies:
|
||||
'@gcornut/valibot-json-schema': 0.42.0(esbuild@0.19.12)(typescript@5.8.2)
|
||||
valibot: 1.0.0-beta.9(typescript@5.8.2)
|
||||
transitivePeerDependencies:
|
||||
- '@types/json-schema'
|
||||
|
||||
'@typeschema/valibot@0.14.0(@gcornut/valibot-json-schema@0.42.0(esbuild@0.25.0)(typescript@5.8.2))(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2))':
|
||||
dependencies:
|
||||
'@typeschema/core': 0.14.0(@types/json-schema@7.0.15)
|
||||
@@ -16736,6 +17122,158 @@ snapshots:
|
||||
|
||||
csstype@3.1.3: {}
|
||||
|
||||
d3-array@3.2.4:
|
||||
dependencies:
|
||||
internmap: 2.0.3
|
||||
|
||||
d3-axis@3.0.0: {}
|
||||
|
||||
d3-brush@3.0.0:
|
||||
dependencies:
|
||||
d3-dispatch: 3.0.1
|
||||
d3-drag: 3.0.0
|
||||
d3-interpolate: 3.0.1
|
||||
d3-selection: 3.0.0
|
||||
d3-transition: 3.0.1(d3-selection@3.0.0)
|
||||
|
||||
d3-chord@3.0.1:
|
||||
dependencies:
|
||||
d3-path: 3.1.0
|
||||
|
||||
d3-color@3.1.0: {}
|
||||
|
||||
d3-contour@4.0.2:
|
||||
dependencies:
|
||||
d3-array: 3.2.4
|
||||
|
||||
d3-delaunay@6.0.4:
|
||||
dependencies:
|
||||
delaunator: 5.0.1
|
||||
|
||||
d3-dispatch@3.0.1: {}
|
||||
|
||||
d3-drag@3.0.0:
|
||||
dependencies:
|
||||
d3-dispatch: 3.0.1
|
||||
d3-selection: 3.0.0
|
||||
|
||||
d3-dsv@3.0.1:
|
||||
dependencies:
|
||||
commander: 7.2.0
|
||||
iconv-lite: 0.6.3
|
||||
rw: 1.3.3
|
||||
|
||||
d3-ease@3.0.1: {}
|
||||
|
||||
d3-fetch@3.0.1:
|
||||
dependencies:
|
||||
d3-dsv: 3.0.1
|
||||
|
||||
d3-force@3.0.0:
|
||||
dependencies:
|
||||
d3-dispatch: 3.0.1
|
||||
d3-quadtree: 3.0.1
|
||||
d3-timer: 3.0.1
|
||||
|
||||
d3-format@3.1.0: {}
|
||||
|
||||
d3-geo@3.1.1:
|
||||
dependencies:
|
||||
d3-array: 3.2.4
|
||||
|
||||
d3-hierarchy@3.1.2: {}
|
||||
|
||||
d3-interpolate@3.0.1:
|
||||
dependencies:
|
||||
d3-color: 3.1.0
|
||||
|
||||
d3-path@3.1.0: {}
|
||||
|
||||
d3-polygon@3.0.1: {}
|
||||
|
||||
d3-quadtree@3.0.1: {}
|
||||
|
||||
d3-random@3.0.1: {}
|
||||
|
||||
d3-scale-chromatic@3.1.0:
|
||||
dependencies:
|
||||
d3-color: 3.1.0
|
||||
d3-interpolate: 3.0.1
|
||||
|
||||
d3-scale@4.0.2:
|
||||
dependencies:
|
||||
d3-array: 3.2.4
|
||||
d3-format: 3.1.0
|
||||
d3-interpolate: 3.0.1
|
||||
d3-time: 3.1.0
|
||||
d3-time-format: 4.1.0
|
||||
|
||||
d3-selection@3.0.0: {}
|
||||
|
||||
d3-shape@3.2.0:
|
||||
dependencies:
|
||||
d3-path: 3.1.0
|
||||
|
||||
d3-time-format@4.1.0:
|
||||
dependencies:
|
||||
d3-time: 3.1.0
|
||||
|
||||
d3-time@3.1.0:
|
||||
dependencies:
|
||||
d3-array: 3.2.4
|
||||
|
||||
d3-timer@3.0.1: {}
|
||||
|
||||
d3-transition@3.0.1(d3-selection@3.0.0):
|
||||
dependencies:
|
||||
d3-color: 3.1.0
|
||||
d3-dispatch: 3.0.1
|
||||
d3-ease: 3.0.1
|
||||
d3-interpolate: 3.0.1
|
||||
d3-selection: 3.0.0
|
||||
d3-timer: 3.0.1
|
||||
|
||||
d3-zoom@3.0.0:
|
||||
dependencies:
|
||||
d3-dispatch: 3.0.1
|
||||
d3-drag: 3.0.0
|
||||
d3-interpolate: 3.0.1
|
||||
d3-selection: 3.0.0
|
||||
d3-transition: 3.0.1(d3-selection@3.0.0)
|
||||
|
||||
d3@7.9.0:
|
||||
dependencies:
|
||||
d3-array: 3.2.4
|
||||
d3-axis: 3.0.0
|
||||
d3-brush: 3.0.0
|
||||
d3-chord: 3.0.1
|
||||
d3-color: 3.1.0
|
||||
d3-contour: 4.0.2
|
||||
d3-delaunay: 6.0.4
|
||||
d3-dispatch: 3.0.1
|
||||
d3-drag: 3.0.0
|
||||
d3-dsv: 3.0.1
|
||||
d3-ease: 3.0.1
|
||||
d3-fetch: 3.0.1
|
||||
d3-force: 3.0.0
|
||||
d3-format: 3.1.0
|
||||
d3-geo: 3.1.1
|
||||
d3-hierarchy: 3.1.2
|
||||
d3-interpolate: 3.0.1
|
||||
d3-path: 3.1.0
|
||||
d3-polygon: 3.0.1
|
||||
d3-quadtree: 3.0.1
|
||||
d3-random: 3.0.1
|
||||
d3-scale: 4.0.2
|
||||
d3-scale-chromatic: 3.1.0
|
||||
d3-selection: 3.0.0
|
||||
d3-shape: 3.2.0
|
||||
d3-time: 3.1.0
|
||||
d3-time-format: 4.1.0
|
||||
d3-timer: 3.0.1
|
||||
d3-transition: 3.0.1(d3-selection@3.0.0)
|
||||
d3-zoom: 3.0.0
|
||||
|
||||
d@1.0.2:
|
||||
dependencies:
|
||||
es5-ext: 0.10.64
|
||||
@@ -16810,6 +17348,10 @@ snapshots:
|
||||
|
||||
defu@6.1.4: {}
|
||||
|
||||
delaunator@5.0.1:
|
||||
dependencies:
|
||||
robust-predicates: 3.0.2
|
||||
|
||||
delayed-stream@1.0.0: {}
|
||||
|
||||
delegates@1.0.0:
|
||||
@@ -17255,6 +17797,13 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
esbuild-runner@2.2.2(esbuild@0.19.12):
|
||||
dependencies:
|
||||
esbuild: 0.19.12
|
||||
source-map-support: 0.5.21
|
||||
tslib: 2.4.0
|
||||
optional: true
|
||||
|
||||
esbuild-runner@2.2.2(esbuild@0.25.0):
|
||||
dependencies:
|
||||
esbuild: 0.25.0
|
||||
@@ -18737,6 +19286,8 @@ snapshots:
|
||||
has: 1.0.3
|
||||
side-channel: 1.0.6
|
||||
|
||||
internmap@2.0.3: {}
|
||||
|
||||
ip-address@9.0.5:
|
||||
dependencies:
|
||||
jsbn: 1.1.0
|
||||
@@ -21630,6 +22181,8 @@ snapshots:
|
||||
sprintf-js: 1.1.3
|
||||
optional: true
|
||||
|
||||
robust-predicates@3.0.2: {}
|
||||
|
||||
rollup-plugin-dts@6.1.1(rollup@4.34.9)(typescript@5.8.2):
|
||||
dependencies:
|
||||
magic-string: 0.30.17
|
||||
@@ -21694,6 +22247,8 @@ snapshots:
|
||||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
|
||||
rw@1.3.3: {}
|
||||
|
||||
rxjs@7.8.1:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
@@ -22824,6 +23379,13 @@ snapshots:
|
||||
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.34.9)
|
||||
'@vueuse/core': 12.7.0(typescript@5.8.2)
|
||||
|
||||
unplugin-combine@1.2.0(esbuild@0.19.12)(rollup@4.34.9)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)):
|
||||
optionalDependencies:
|
||||
esbuild: 0.19.12
|
||||
rollup: 4.34.9
|
||||
unplugin: 1.16.1
|
||||
vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)
|
||||
|
||||
unplugin-combine@1.2.0(esbuild@0.25.0)(rollup@2.79.1)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)):
|
||||
optionalDependencies:
|
||||
esbuild: 0.25.0
|
||||
@@ -22831,13 +23393,6 @@ snapshots:
|
||||
unplugin: 1.16.1
|
||||
vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)
|
||||
|
||||
unplugin-combine@1.2.0(esbuild@0.25.0)(rollup@4.34.9)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)):
|
||||
optionalDependencies:
|
||||
esbuild: 0.25.0
|
||||
rollup: 4.34.9
|
||||
unplugin: 1.16.1
|
||||
vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)
|
||||
|
||||
unplugin-utils@0.2.4:
|
||||
dependencies:
|
||||
pathe: 2.0.3
|
||||
@@ -22885,6 +23440,52 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- vue
|
||||
|
||||
unplugin-vue-macros@2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.19.12)(rollup@4.34.9)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2)):
|
||||
dependencies:
|
||||
'@vue-macros/better-define': 1.11.4(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/boolean-prop': 0.5.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/chain-call': 0.4.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/common': 1.16.1(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/config': 0.6.1(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-emit': 0.5.4(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-models': 1.3.5(@vueuse/core@12.7.0(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-prop': 0.6.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-props': 4.0.6(@vue-macros/reactivity-transform@1.1.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-props-refs': 1.3.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-render': 1.6.6(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-slots': 1.2.6(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-stylex': 0.2.3(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/devtools': 0.4.1(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
|
||||
'@vue-macros/export-expose': 0.3.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/export-props': 0.6.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/export-render': 0.3.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/hoist-static': 1.7.0(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/jsx-directive': 0.10.6(typescript@5.8.2)
|
||||
'@vue-macros/named-template': 0.5.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/reactivity-transform': 1.1.6(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/script-lang': 0.2.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/setup-block': 0.4.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/setup-component': 0.18.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/setup-sfc': 0.18.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/short-bind': 1.1.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/short-emits': 1.6.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/short-vmodel': 1.5.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/volar': 0.30.15(rollup@4.34.9)(typescript@5.8.2)(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
|
||||
unplugin: 1.16.1
|
||||
unplugin-combine: 1.2.0(esbuild@0.19.12)(rollup@4.34.9)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
|
||||
unplugin-vue-define-options: 1.5.5(vue@3.5.13(typescript@5.8.2))
|
||||
vue: 3.5.13(typescript@5.8.2)
|
||||
transitivePeerDependencies:
|
||||
- '@rspack/core'
|
||||
- '@vueuse/core'
|
||||
- esbuild
|
||||
- rolldown
|
||||
- rollup
|
||||
- typescript
|
||||
- vite
|
||||
- vue-tsc
|
||||
- webpack
|
||||
|
||||
unplugin-vue-macros@2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.25.0)(rollup@2.79.1)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2)):
|
||||
dependencies:
|
||||
'@vue-macros/better-define': 1.11.4(vue@3.5.13(typescript@5.8.2))
|
||||
@@ -22931,52 +23532,6 @@ snapshots:
|
||||
- vue-tsc
|
||||
- webpack
|
||||
|
||||
unplugin-vue-macros@2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.25.0)(rollup@4.34.9)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2)):
|
||||
dependencies:
|
||||
'@vue-macros/better-define': 1.11.4(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/boolean-prop': 0.5.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/chain-call': 0.4.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/common': 1.16.1(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/config': 0.6.1(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-emit': 0.5.4(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-models': 1.3.5(@vueuse/core@12.7.0(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-prop': 0.6.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-props': 4.0.6(@vue-macros/reactivity-transform@1.1.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-props-refs': 1.3.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-render': 1.6.6(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-slots': 1.2.6(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/define-stylex': 0.2.3(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/devtools': 0.4.1(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
|
||||
'@vue-macros/export-expose': 0.3.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/export-props': 0.6.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/export-render': 0.3.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/hoist-static': 1.7.0(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/jsx-directive': 0.10.6(typescript@5.8.2)
|
||||
'@vue-macros/named-template': 0.5.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/reactivity-transform': 1.1.6(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/script-lang': 0.2.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/setup-block': 0.4.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/setup-component': 0.18.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/setup-sfc': 0.18.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/short-bind': 1.1.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/short-emits': 1.6.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/short-vmodel': 1.5.5(vue@3.5.13(typescript@5.8.2))
|
||||
'@vue-macros/volar': 0.30.15(rollup@4.34.9)(typescript@5.8.2)(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
|
||||
unplugin: 1.16.1
|
||||
unplugin-combine: 1.2.0(esbuild@0.25.0)(rollup@4.34.9)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
|
||||
unplugin-vue-define-options: 1.5.5(vue@3.5.13(typescript@5.8.2))
|
||||
vue: 3.5.13(typescript@5.8.2)
|
||||
transitivePeerDependencies:
|
||||
- '@rspack/core'
|
||||
- '@vueuse/core'
|
||||
- esbuild
|
||||
- rolldown
|
||||
- rollup
|
||||
- typescript
|
||||
- vite
|
||||
- vue-tsc
|
||||
- webpack
|
||||
|
||||
unplugin-vue-markdown@28.3.1(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)):
|
||||
dependencies:
|
||||
'@mdit-vue/plugin-component': 2.1.3
|
||||
|
||||
Reference in New Issue
Block a user