diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 4fc3033..5460b73 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -33,7 +33,13 @@ "vitest": "catalog:" }, "dependencies": { + "@lucia-auth/adapter-postgresql": "^3.1.2", + "@node-rs/argon2": "^2.0.2", "@rocicorp/zero": "^0.24.3000000000", + "d3-scale": "^4.0.2", + "d3-shape": "^3.2.0", + "layerchart": "2.0.0-next.43", + "lucia": "^3.2.2", "postgres": "catalog:", "zod": "catalog:" } diff --git a/apps/dashboard/src/app.css b/apps/dashboard/src/app.css index 08bd70a..8856233 100644 --- a/apps/dashboard/src/app.css +++ b/apps/dashboard/src/app.css @@ -21,3 +21,25 @@ html, body { background-color: var(--color-rp-base); } + +/* LayerChart axis styling */ +.lc-axis text { + fill: var(--color-rp-subtle); + stroke: none; + font-size: 12px; +} + +.lc-axis line, +.lc-axis path { + stroke: var(--color-rp-overlay); +} + +/* LayerChart tooltip styling */ +.lc-tooltip { + background-color: var(--color-rp-surface); + border: 1px solid var(--color-rp-overlay); + border-radius: 4px; + padding: 8px; + color: var(--color-rp-text); + font-size: 12px; +} diff --git a/apps/dashboard/src/app.d.ts b/apps/dashboard/src/app.d.ts new file mode 100644 index 0000000..cd6e124 --- /dev/null +++ b/apps/dashboard/src/app.d.ts @@ -0,0 +1,12 @@ +import type { Session, User } from "lucia"; + +declare global { + namespace App { + interface Locals { + user: User | null; + session: Session | null; + } + } +} + +export {}; diff --git a/apps/dashboard/src/app.html b/apps/dashboard/src/app.html index 22bff6b..a1e98f4 100644 --- a/apps/dashboard/src/app.html +++ b/apps/dashboard/src/app.html @@ -2,7 +2,7 @@
- + %sveltekit.head% diff --git a/apps/dashboard/src/hooks.server.ts b/apps/dashboard/src/hooks.server.ts new file mode 100644 index 0000000..cb5477d --- /dev/null +++ b/apps/dashboard/src/hooks.server.ts @@ -0,0 +1,34 @@ +import { lucia } from "$lib/server/auth"; +import type { Handle } from "@sveltejs/kit"; + +export const handle: Handle = async ({ event, resolve }) => { + const sessionId = event.cookies.get(lucia.sessionCookieName); + + if (!sessionId) { + event.locals.user = null; + event.locals.session = null; + return resolve(event); + } + + const { session, user } = await lucia.validateSession(sessionId); + + if (session && session.fresh) { + const sessionCookie = lucia.createSessionCookie(session.id); + event.cookies.set(sessionCookie.name, sessionCookie.value, { + path: ".", + ...sessionCookie.attributes, + }); + } + + if (!session) { + const sessionCookie = lucia.createBlankSessionCookie(); + event.cookies.set(sessionCookie.name, sessionCookie.value, { + path: ".", + ...sessionCookie.attributes, + }); + } + + event.locals.user = user; + event.locals.session = session; + return resolve(event); +}; diff --git a/apps/dashboard/src/lib/components/EventsList.svelte b/apps/dashboard/src/lib/components/EventsList.svelte index dc5c63a..1bcc9a6 100644 --- a/apps/dashboard/src/lib/components/EventsList.svelte +++ b/apps/dashboard/src/lib/components/EventsList.svelte @@ -6,7 +6,8 @@ let { projectId }: { projectId: string } = $props(); // Fetch a larger set and paginate client-side - const eventsQuery = useQueryLoading events...
- {:else if recentEventsList.length === 0} + {:else if recentQuery.data.length === 0}No events yet. Integrate the SDK to start tracking.
{:else}| {event.event_name} |
diff --git a/apps/dashboard/src/lib/components/SessionDetail.svelte b/apps/dashboard/src/lib/components/SessionDetail.svelte
index 927c9e9..7c279b4 100644
--- a/apps/dashboard/src/lib/components/SessionDetail.svelte
+++ b/apps/dashboard/src/lib/components/SessionDetail.svelte
@@ -5,8 +5,9 @@
let { sessionId }: { sessionId: string } = $props();
- const sessionQuery = useQueryOne
+ {#if hasData}
+
diff --git a/apps/dashboard/src/lib/components/charts/SessionsTrendChart.svelte b/apps/dashboard/src/lib/components/charts/SessionsTrendChart.svelte
new file mode 100644
index 0000000..4b2db30
--- /dev/null
+++ b/apps/dashboard/src/lib/components/charts/SessionsTrendChart.svelte
@@ -0,0 +1,94 @@
+
+
+
+ No data available
+
+ {/if}
+
+ {#if hasData}
+
diff --git a/apps/dashboard/src/lib/components/charts/TopEventsChart.svelte b/apps/dashboard/src/lib/components/charts/TopEventsChart.svelte
new file mode 100644
index 0000000..c40c2c8
--- /dev/null
+++ b/apps/dashboard/src/lib/components/charts/TopEventsChart.svelte
@@ -0,0 +1,63 @@
+
+
+
+ No data available
+
+ {/if}
+
+ {#if hasData}
+
diff --git a/apps/dashboard/src/lib/server/auth.ts b/apps/dashboard/src/lib/server/auth.ts
new file mode 100644
index 0000000..8136adc
--- /dev/null
+++ b/apps/dashboard/src/lib/server/auth.ts
@@ -0,0 +1,33 @@
+import { Lucia } from "lucia";
+import { PostgresJsAdapter } from "@lucia-auth/adapter-postgresql";
+import { sql } from "$lib/db";
+import { dev } from "$app/environment";
+
+const adapter = new PostgresJsAdapter(sql, {
+ user: "dashboard_users",
+ session: "dashboard_sessions",
+});
+
+export const lucia = new Lucia(adapter, {
+ sessionCookie: {
+ attributes: {
+ secure: !dev,
+ },
+ },
+ getUserAttributes: (attributes) => {
+ return {
+ email: attributes.email,
+ };
+ },
+});
+
+declare module "lucia" {
+ interface Register {
+ Lucia: typeof lucia;
+ DatabaseUserAttributes: DatabaseUserAttributes;
+ }
+}
+
+interface DatabaseUserAttributes {
+ email: string;
+}
diff --git a/apps/dashboard/src/lib/zero/client.svelte.ts b/apps/dashboard/src/lib/zero/client.svelte.ts
index 8d1faf3..3d79fb9 100644
--- a/apps/dashboard/src/lib/zero/client.svelte.ts
+++ b/apps/dashboard/src/lib/zero/client.svelte.ts
@@ -5,6 +5,25 @@
* Handles subscription lifecycle and cleanup automatically.
*
* Uses Svelte context for proper component tree integration.
+ *
+ * ## Reactive Parameters
+ *
+ * Query hooks support both static queries and getter functions for reactive params.
+ * Use getter functions when query parameters depend on reactive state:
+ *
+ * ```typescript
+ * // Static - query params never change
+ * const events = useQuery(recentEvents('project-123', 100));
+ *
+ * // Reactive - re-runs when `days` state changes
+ * let days = $state(7);
+ * const events = useQuery(() => eventsInWindow(projectId, days));
+ * ```
+ *
+ * Why getter functions? Svelte 5's `$effect` only tracks reactive values that are
+ * **synchronously read** during execution. By passing a getter, the function is
+ * called inside the effect, allowing Svelte to track dependencies like `days`.
+ * Without this, the query would capture `days = 7` at mount time and never update.
*/
import { schema, type Schema } from "./schema";
@@ -23,6 +42,7 @@ let _zeroInstance: ZeroClient | null = null;
/**
* Initialize Zero client and set it in Svelte context.
* Call this once in your root layout (client-side only).
+ * Idempotent - returns existing instance if already created.
*
* @param userID - Unique identifier for the current user (use 'dashboard-admin' for admin)
* @param server - Zero cache server URL (default: http://localhost:4848)
@@ -32,6 +52,11 @@ export function createZero(
userID: string = "dashboard-admin",
server: string = "http://localhost:4848",
): ZeroClient {
+ // Return existing instance if already initialized (idempotent)
+ if (_zeroInstance) {
+ return _zeroInstance;
+ }
+
const zero = new Zero
+ No events recorded
+
+ {/if}
+
-
+{#if user}
+ {#if zeroReady}
+
+ {:else}
+
+
-
+
+ Initializing...
+
+ {/if}
+{:else}
+ {@render children()}
+{/if}
diff --git a/apps/dashboard/src/routes/api/zero/get-queries/+server.ts b/apps/dashboard/src/routes/api/zero/get-queries/+server.ts
index 23a03dd..aef7e79 100644
--- a/apps/dashboard/src/routes/api/zero/get-queries/+server.ts
+++ b/apps/dashboard/src/routes/api/zero/get-queries/+server.ts
@@ -17,10 +17,11 @@ const validatedQueries = Object.fromEntries(
queries.map((q) => [q.queryName, withValidation(q)]),
);
-export const POST: RequestHandler = async ({ request }) => {
- // For now, no auth - pass null context
- // When auth is added, extract from locals.user
- const authContext: AuthContext = null;
+export const POST: RequestHandler = async ({ request, locals }) => {
+ // Extract user from session (set by hooks.server.ts)
+ const authContext: AuthContext = locals.user
+ ? { userId: locals.user.id }
+ : null;
// Query resolver function with auth context in closure
function getQuery(name: string, args: readonly unknown[]) {
diff --git a/apps/dashboard/src/routes/login/+layout.svelte b/apps/dashboard/src/routes/login/+layout.svelte
new file mode 100644
index 0000000..122e0d0
--- /dev/null
+++ b/apps/dashboard/src/routes/login/+layout.svelte
@@ -0,0 +1,7 @@
+
+
+{@render children()}
diff --git a/apps/dashboard/src/routes/login/+page.server.ts b/apps/dashboard/src/routes/login/+page.server.ts
new file mode 100644
index 0000000..762b07e
--- /dev/null
+++ b/apps/dashboard/src/routes/login/+page.server.ts
@@ -0,0 +1,46 @@
+import { fail, redirect } from "@sveltejs/kit";
+import { verify } from "@node-rs/argon2";
+import { lucia } from "$lib/server/auth";
+import { sql } from "$lib/db";
+import type { Actions, PageServerLoad } from "./$types";
+
+export const load: PageServerLoad = async ({ locals }) => {
+ if (locals.user) {
+ redirect(302, "/");
+ }
+ return {};
+};
+
+export const actions: Actions = {
+ default: async ({ request, cookies }) => {
+ const formData = await request.formData();
+ const email = formData.get("email");
+ const password = formData.get("password");
+
+ if (typeof email !== "string" || typeof password !== "string") {
+ return fail(400, { error: "Invalid input" });
+ }
+
+ const [user] = await sql`
+ SELECT id, email, password_hash FROM dashboard_users WHERE email = ${email}
+ `;
+
+ if (!user) {
+ return fail(400, { error: "Invalid email or password" });
+ }
+
+ const validPassword = await verify(user.password_hash, password);
+ if (!validPassword) {
+ return fail(400, { error: "Invalid email or password" });
+ }
+
+ const session = await lucia.createSession(user.id, {});
+ const sessionCookie = lucia.createSessionCookie(session.id);
+ cookies.set(sessionCookie.name, sessionCookie.value, {
+ path: ".",
+ ...sessionCookie.attributes,
+ });
+
+ redirect(302, "/");
+ },
+};
diff --git a/apps/dashboard/src/routes/login/+page.svelte b/apps/dashboard/src/routes/login/+page.svelte
new file mode 100644
index 0000000..62b4c4e
--- /dev/null
+++ b/apps/dashboard/src/routes/login/+page.svelte
@@ -0,0 +1,57 @@
+
+
+
+
diff --git a/apps/dashboard/src/routes/logout/+page.server.ts b/apps/dashboard/src/routes/logout/+page.server.ts
new file mode 100644
index 0000000..51991ff
--- /dev/null
+++ b/apps/dashboard/src/routes/logout/+page.server.ts
@@ -0,0 +1,24 @@
+import { redirect } from "@sveltejs/kit";
+import { lucia } from "$lib/server/auth";
+import type { Actions, PageServerLoad } from "./$types";
+
+export const load: PageServerLoad = async () => {
+ redirect(302, "/");
+};
+
+export const actions: Actions = {
+ default: async ({ locals, cookies }) => {
+ if (!locals.session) {
+ redirect(302, "/login");
+ }
+
+ await lucia.invalidateSession(locals.session.id);
+ const sessionCookie = lucia.createBlankSessionCookie();
+ cookies.set(sessionCookie.name, sessionCookie.value, {
+ path: ".",
+ ...sessionCookie.attributes,
+ });
+
+ redirect(302, "/login");
+ },
+};
diff --git a/apps/dashboard/src/routes/register/+layout.svelte b/apps/dashboard/src/routes/register/+layout.svelte
new file mode 100644
index 0000000..122e0d0
--- /dev/null
+++ b/apps/dashboard/src/routes/register/+layout.svelte
@@ -0,0 +1,7 @@
+
+
+{@render children()}
diff --git a/apps/dashboard/src/routes/register/+page.server.ts b/apps/dashboard/src/routes/register/+page.server.ts
new file mode 100644
index 0000000..4139b16
--- /dev/null
+++ b/apps/dashboard/src/routes/register/+page.server.ts
@@ -0,0 +1,61 @@
+import { fail, redirect } from "@sveltejs/kit";
+import { hash } from "@node-rs/argon2";
+import { lucia } from "$lib/server/auth";
+import { sql } from "$lib/db";
+import type { Actions, PageServerLoad } from "./$types";
+
+export const load: PageServerLoad = async ({ locals }) => {
+ if (locals.user) {
+ redirect(302, "/");
+ }
+ return {};
+};
+
+export const actions: Actions = {
+ default: async ({ request, cookies }) => {
+ const formData = await request.formData();
+ const email = formData.get("email");
+ const password = formData.get("password");
+
+ if (typeof email !== "string" || typeof password !== "string") {
+ return fail(400, { error: "Invalid input" });
+ }
+
+ if (password.length < 8) {
+ return fail(400, { error: "Password must be at least 8 characters" });
+ }
+
+ // Check if email already exists
+ const [existing] = await sql`
+ SELECT id FROM dashboard_users WHERE email = ${email}
+ `;
+
+ if (existing) {
+ return fail(400, { error: "Email already registered" });
+ }
+
+ // Hash password and create user
+ const passwordHash = await hash(password, {
+ memoryCost: 19456,
+ timeCost: 2,
+ outputLen: 32,
+ parallelism: 1,
+ });
+
+ const [user] = await sql`
+ INSERT INTO dashboard_users (email, password_hash)
+ VALUES (${email}, ${passwordHash})
+ RETURNING id
+ `;
+
+ // Create session
+ const session = await lucia.createSession(user.id, {});
+ const sessionCookie = lucia.createSessionCookie(session.id);
+ cookies.set(sessionCookie.name, sessionCookie.value, {
+ path: ".",
+ ...sessionCookie.attributes,
+ });
+
+ redirect(302, "/");
+ },
+};
diff --git a/apps/dashboard/src/routes/register/+page.svelte b/apps/dashboard/src/routes/register/+page.svelte
new file mode 100644
index 0000000..ce7f013
--- /dev/null
+++ b/apps/dashboard/src/routes/register/+page.svelte
@@ -0,0 +1,59 @@
+
+
+
+
+Beacon+Sign in to your account+ + {#if form?.error} +
+ {form.error}
+
+ {/if}
+
+
+
+ + Don't have an account? + Register + +
+
diff --git a/apps/dashboard/static/favicon.svg b/apps/dashboard/static/favicon.svg
new file mode 100644
index 0000000..48f1a37
--- /dev/null
+++ b/apps/dashboard/static/favicon.svg
@@ -0,0 +1,4 @@
+
diff --git a/apps/dashboard/tsconfig.json b/apps/dashboard/tsconfig.json
new file mode 100644
index 0000000..4344710
--- /dev/null
+++ b/apps/dashboard/tsconfig.json
@@ -0,0 +1,14 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true,
+ "moduleResolution": "bundler"
+ }
+}
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 6294c17..0d11e62 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -94,7 +94,7 @@ function MyApp() {
Open http://localhost:5173 to see tracked events and manage feature flags.
-> **WIP**: Dashboard authentication is not yet implemented. Currently open access for local development.
+> **Note**: You'll need to register an account on first visit. Go to `/register` to create credentials.
---
diff --git a/docs/roadmap.md b/docs/roadmap.md
index 5f05be9..cc1f216 100644
--- a/docs/roadmap.md
+++ b/docs/roadmap.md
@@ -15,12 +15,12 @@ Beacon's path to a stable alpha release.
- [x] Documentation (SDK, API, protocol, identity)
- [x] SDK unit tests (95% coverage)
-### 🚧 M1: Examples & Polish
+### ✅ M1: Examples & Polish
- [x] React example app
- [x] Flag management UI
-- [ ] Dashboard authentication
-- [ ] Basic analytics visualizations
+- [x] Dashboard authentication (Lucia + session cookies)
+- [x] Basic analytics visualizations (LayerChart)
### ✅ M2: Benchmarking
diff --git a/infra/migrations/002_dashboard_auth.sql b/infra/migrations/002_dashboard_auth.sql
new file mode 100644
index 0000000..565596f
--- /dev/null
+++ b/infra/migrations/002_dashboard_auth.sql
@@ -0,0 +1,24 @@
+-- migrate:up
+
+-- Dashboard users (separate from analytics users table)
+CREATE TABLE dashboard_users (
+ id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
+ email TEXT UNIQUE NOT NULL,
+ password_hash TEXT NOT NULL,
+ created_at TIMESTAMPTZ DEFAULT NOW()
+);
+
+-- Dashboard sessions (for Lucia auth)
+CREATE TABLE dashboard_sessions (
+ id TEXT PRIMARY KEY,
+ user_id UUID NOT NULL REFERENCES dashboard_users(id) ON DELETE CASCADE,
+ expires_at TIMESTAMPTZ NOT NULL
+);
+
+CREATE INDEX idx_dashboard_sessions_user ON dashboard_sessions(user_id);
+
+
+-- migrate:down
+
+DROP TABLE IF EXISTS dashboard_sessions;
+DROP TABLE IF EXISTS dashboard_users;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0f53533..b45bab7 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -119,9 +119,27 @@ importers:
apps/dashboard:
dependencies:
+ '@lucia-auth/adapter-postgresql':
+ specifier: ^3.1.2
+ version: 3.1.2(lucia@3.2.2)(postgres@3.4.7)
+ '@node-rs/argon2':
+ specifier: ^2.0.2
+ version: 2.0.2
'@rocicorp/zero':
specifier: ^0.24.3000000000
version: 0.24.3000000000(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))
+ d3-scale:
+ specifier: ^4.0.2
+ version: 4.0.2
+ d3-shape:
+ specifier: ^3.2.0
+ version: 3.2.0
+ layerchart:
+ specifier: 2.0.0-next.43
+ version: 2.0.0-next.43(svelte@5.45.3)
+ lucia:
+ specifier: ^3.2.2
+ version: 3.2.2
postgres:
specifier: 'catalog:'
version: 3.4.7
@@ -398,6 +416,13 @@ packages:
resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
engines: {node: '>=18'}
+ '@dagrejs/dagre@1.1.8':
+ resolution: {integrity: sha512-5SEDlndt4W/LaVzPYJW+bSmSEZc9EzTf8rJ20WCKvjS5EAZAN0b+x0Yww7VMT4R3Wootkg+X9bUfUxazYw6Blw==}
+
+ '@dagrejs/graphlib@2.2.4':
+ resolution: {integrity: sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw==}
+ engines: {node: '>17.0.0'}
+
'@databases/escape-identifier@1.0.3':
resolution: {integrity: sha512-Su36iSVzaHxpVdISVMViUX/32sLvzxVgjZpYhzhotxZUuLo11GVWsiHwqkvUZijTLUxcDmUqEwGJO3O/soLuZA==}
@@ -420,6 +445,15 @@ packages:
peerDependencies:
'@noble/ciphers': ^1.0.0
+ '@emnapi/core@1.7.1':
+ resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==}
+
+ '@emnapi/runtime@1.7.1':
+ resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==}
+
+ '@emnapi/wasi-threads@1.1.0':
+ resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
+
'@esbuild/aix-ppc64@0.25.12':
resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==}
engines: {node: '>=18'}
@@ -794,6 +828,15 @@ packages:
'@fastify/websocket@11.2.0':
resolution: {integrity: sha512-3HrDPbAG1CzUCqnslgJxppvzaAZffieOVbLp1DAy1huCSynUWPifSvfdEDUR8HlJLp3sp1A36uOM2tJogADS8w==}
+ '@floating-ui/core@1.7.3':
+ resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==}
+
+ '@floating-ui/dom@1.7.4':
+ resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==}
+
+ '@floating-ui/utils@0.2.10':
+ resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
+
'@google-cloud/precise-date@4.0.0':
resolution: {integrity: sha512-1TUx3KdaU3cN7nfCdNf+UVqA/PSX29Cjcox3fZZBtINlRrXVTmUkQnCKv2MbBUbCopbK4olAT1IHl76uZyCiVA==}
engines: {node: '>=14.0.0'}
@@ -842,6 +885,37 @@ packages:
'@js-sdsl/ordered-map@4.4.2':
resolution: {integrity: sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==}
+ '@layerstack/svelte-actions@1.0.1-next.14':
+ resolution: {integrity: sha512-MPBmVaB+GfNHvBkg5nJkPG18smoXKvsvJRpsdWnrUBfca+TieZLoaEzNxDH+9LG11dIXP9gghsXt1mUqbbyAsA==}
+
+ '@layerstack/svelte-state@0.1.0-next.19':
+ resolution: {integrity: sha512-yCYoQAIbeP8y1xmOB/r0+UundgP4JFnpNURgMki+26TotzoqrZ5oLpHvhPSVm60ks+buR3ebDBTeUFdHzxwzQQ==}
+
+ '@layerstack/tailwind@2.0.0-next.17':
+ resolution: {integrity: sha512-ZSn6ouqpnzB6DKzSKLVwrUBOQsrzpDA/By2/ba9ApxgTGnaD1nyqNwrvmZ+kswdAwB4YnrGEAE4VZkKrB2+DaQ==}
+
+ '@layerstack/utils@2.0.0-next.14':
+ resolution: {integrity: sha512-1I2CS0Cwgs53W35qVg1eBdYhB/CiPvL3s0XE61b8jWkTHxgjBF65yYNgXjW74kv7WI7GsJcWMNBufPd0rnu9kA==}
+
+ '@lucia-auth/adapter-postgresql@3.1.2':
+ resolution: {integrity: sha512-XgScy312JsaiyJZ0OaUHakk01hFBldF1m8abX4Ctk2Dkt7lEVS/u0xZ2Sf6Hlji1wZtEM0uiIWdeMUu79XcXZA==}
+ deprecated: This package has been deprecated. Please see https://lucia-auth.com/lucia-v3/migrate.
+ peerDependencies:
+ '@neondatabase/serverless': 0.7 - 0.9
+ lucia: 3.x
+ pg: ^8.8.0
+ postgres: ^3.3.0
+ peerDependenciesMeta:
+ '@neondatabase/serverless':
+ optional: true
+ pg:
+ optional: true
+ postgres:
+ optional: true
+
+ '@napi-rs/wasm-runtime@0.2.12':
+ resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
+
'@noble/ciphers@1.3.0':
resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==}
engines: {node: ^14.21.3 || >=16}
@@ -854,6 +928,93 @@ packages:
resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
engines: {node: ^14.21.3 || >=16}
+ '@node-rs/argon2-android-arm-eabi@2.0.2':
+ resolution: {integrity: sha512-DV/H8p/jt40lrao5z5g6nM9dPNPGEHL+aK6Iy/og+dbL503Uj0AHLqj1Hk9aVUSCNnsDdUEKp4TVMi0YakDYKw==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [android]
+
+ '@node-rs/argon2-android-arm64@2.0.2':
+ resolution: {integrity: sha512-1LKwskau+8O1ktKx7TbK7jx1oMOMt4YEXZOdSNIar1TQKxm6isZ0cRXgHLibPHEcNHgYRsJWDE9zvDGBB17QDg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [android]
+
+ '@node-rs/argon2-darwin-arm64@2.0.2':
+ resolution: {integrity: sha512-3TTNL/7wbcpNju5YcqUrCgXnXUSbD7ogeAKatzBVHsbpjZQbNb1NDxDjqqrWoTt6XL3z9mJUMGwbAk7zQltHtA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@node-rs/argon2-darwin-x64@2.0.2':
+ resolution: {integrity: sha512-vNPfkLj5Ij5111UTiYuwgxMqE7DRbOS2y58O2DIySzSHbcnu+nipmRKg+P0doRq6eKIJStyBK8dQi5Ic8pFyDw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@node-rs/argon2-freebsd-x64@2.0.2':
+ resolution: {integrity: sha512-M8vQZk01qojQfCqQU0/O1j1a4zPPrz93zc9fSINY7Q/6RhQRBCYwDw7ltDCZXg5JRGlSaeS8cUXWyhPGar3cGg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@node-rs/argon2-linux-arm-gnueabihf@2.0.2':
+ resolution: {integrity: sha512-7EmmEPHLzcu0G2GDh30L6G48CH38roFC2dqlQJmtRCxs6no3tTE/pvgBGatTp/o2n2oyOJcfmgndVFcUpwMnww==}
+ engines: {node: '>= 10'}
+ cpu: [arm]
+ os: [linux]
+
+ '@node-rs/argon2-linux-arm64-gnu@2.0.2':
+ resolution: {integrity: sha512-6lsYh3Ftbk+HAIZ7wNuRF4SZDtxtFTfK+HYFAQQyW7Ig3LHqasqwfUKRXVSV5tJ+xTnxjqgKzvZSUJCAyIfHew==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@node-rs/argon2-linux-arm64-musl@2.0.2':
+ resolution: {integrity: sha512-p3YqVMNT/4DNR67tIHTYGbedYmXxW9QlFmF39SkXyEbGQwpgSf6pH457/fyXBIYznTU/smnG9EH+C1uzT5j4hA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@node-rs/argon2-linux-x64-gnu@2.0.2':
+ resolution: {integrity: sha512-ZM3jrHuJ0dKOhvA80gKJqBpBRmTJTFSo2+xVZR+phQcbAKRlDMSZMFDiKbSTnctkfwNFtjgDdh5g1vaEV04AvA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@node-rs/argon2-linux-x64-musl@2.0.2':
+ resolution: {integrity: sha512-of5uPqk7oCRF/44a89YlWTEfjsftPywyTULwuFDKyD8QtVZoonrJR6ZWvfFE/6jBT68S0okAkAzzMEdBVWdxWw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@node-rs/argon2-wasm32-wasi@2.0.2':
+ resolution: {integrity: sha512-U3PzLYKSQYzTERstgtHLd4ZTkOF9co57zTXT77r0cVUsleGZOrd6ut7rHzeWwoJSiHOVxxa0OhG1JVQeB7lLoQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
+ '@node-rs/argon2-win32-arm64-msvc@2.0.2':
+ resolution: {integrity: sha512-Eisd7/NM0m23ijrGr6xI2iMocdOuyl6gO27gfMfya4C5BODbUSP7ljKJ7LrA0teqZMdYHesRDzx36Js++/vhiQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@node-rs/argon2-win32-ia32-msvc@2.0.2':
+ resolution: {integrity: sha512-GsE2ezwAYwh72f9gIjbGTZOf4HxEksb5M2eCaj+Y5rGYVwAdt7C12Q2e9H5LRYxWcFvLH4m4jiSZpQQ4upnPAQ==}
+ engines: {node: '>= 10'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@node-rs/argon2-win32-x64-msvc@2.0.2':
+ resolution: {integrity: sha512-cJxWXanH4Ew9CfuZ4IAEiafpOBCe97bzoKowHCGk5lG/7kR4WF/eknnBlHW9m8q7t10mKq75kruPLtbSDqgRTw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@node-rs/argon2@2.0.2':
+ resolution: {integrity: sha512-t64wIsPEtNd4aUPuTAyeL2ubxATCBGmeluaKXEMAFk/8w6AJIVVkeLKMBpgLW6LU2t5cQxT+env/c6jxbtTQBg==}
+ engines: {node: '>= 10'}
+
'@opentelemetry/api-logs@0.203.0':
resolution: {integrity: sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ==}
engines: {node: '>=8.0.0'}
@@ -1339,6 +1500,18 @@ packages:
peerDependencies:
'@opentelemetry/api': ^1.1.0
+ '@oslojs/asn1@1.0.0':
+ resolution: {integrity: sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA==}
+
+ '@oslojs/binary@1.0.0':
+ resolution: {integrity: sha512-9RCU6OwXU6p67H4NODbuxv2S3eenuQ4/WFLrsq+K/k682xrznH5EVWA7N4VFk9VYVcbFtKqur5YQQZc0ySGhsQ==}
+
+ '@oslojs/crypto@1.0.1':
+ resolution: {integrity: sha512-7n08G8nWjAr/Yu3vu9zzrd0L9XnrJfpMioQcvCMxBIiF5orECHe5/3J0jmXRVvgfqMm/+4oxlQ+Sq39COYLcNQ==}
+
+ '@oslojs/encoding@1.1.0':
+ resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==}
+
'@pinojs/redact@0.4.0':
resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
@@ -1688,6 +1861,9 @@ packages:
peerDependencies:
vite: ^5.2.0 || ^6 || ^7
+ '@tybys/wasm-util@0.10.1':
+ resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
+
'@types/aws-lambda@8.10.152':
resolution: {integrity: sha512-soT/c2gYBnT5ygwiHPmd9a1bftj462NWVk2tKCc1PYHSIacB2UwbTS2zYG4jzag1mRDuzg/OjtxQjQ2NKRB6Rw==}
@@ -2089,6 +2265,10 @@ packages:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
+ commander@7.2.0:
+ resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+ engines: {node: '>= 10'}
+
commondir@1.0.1:
resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
@@ -2136,6 +2316,109 @@ packages:
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ d3-array@2.12.1:
+ resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==}
+
+ d3-array@3.2.4:
+ resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
+ engines: {node: '>=12'}
+
+ d3-color@3.1.0:
+ resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
+ 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-dsv@3.0.1:
+ resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ 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-voronoi@2.1.0:
+ resolution: {integrity: sha512-kqE4yYuOjPbKdBXG0xztCacPwkVSK2REF1opSNrnqqtXJmNcM++UbwQ8SxvwP6IQTj9RvIjjK4qeiVsEfj0Z2Q==}
+ 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-path@2.3.0:
+ resolution: {integrity: sha512-tZYtGXxBmbgHsIc9Wms6LS5u4w6KbP8C09a4/ZYc4KLMYYqub57rRBUgpUr2CIarIrJEpdAWWxWQvofgaMpbKQ==}
+
+ d3-interpolate@3.0.1:
+ resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
+ engines: {node: '>=12'}
+
+ d3-path@1.0.9:
+ resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==}
+
+ d3-path@3.1.0:
+ resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
+ 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-sankey@0.12.3:
+ resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==}
+
+ 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-shape@1.3.7:
+ resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==}
+
+ d3-shape@3.2.0:
+ resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
+ engines: {node: '>=12'}
+
+ d3-tile@1.0.0:
+ resolution: {integrity: sha512-79fnTKpPMPDS5xQ0xuS9ir0165NEwwkFpe/DSOmc2Gl9ldYzKKRDWogmTTE8wAJ8NA7PMapNfEcyKhI9Lxdu5Q==}
+
+ 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-tricontour@1.1.0:
+ resolution: {integrity: sha512-G7gHKj89n2owmkGb6WX6ixcnQ0Kf/0wpa9VIh9DGdbHu8wdrlaHU4ir3/bFNERl8N8nn4G7e7qbtBG8N9caihQ==}
+ engines: {node: '>=12'}
+
data-urls@6.0.0:
resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==}
engines: {node: '>=20'}
@@ -2174,6 +2457,9 @@ packages:
defu@6.1.4:
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
+ delaunator@5.0.1:
+ resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==}
+
dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
@@ -2569,6 +2855,13 @@ packages:
ini@1.3.8:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+ internmap@1.0.1:
+ resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==}
+
+ internmap@2.0.3:
+ resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
+ engines: {node: '>=12'}
+
ipaddr.js@2.3.0:
resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==}
engines: {node: '>= 10'}
@@ -2730,6 +3023,11 @@ packages:
known-css-properties@0.37.0:
resolution: {integrity: sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==}
+ layerchart@2.0.0-next.43:
+ resolution: {integrity: sha512-1Ywm38NdzHWKwgaAHq3EcqshIgsq+pylntSnVWAVazXUk/NsxPcxdpR3tMt3ySjWV0ZPBBgLs78sdVf7FTgd+g==}
+ peerDependencies:
+ svelte: ^5.0.0
+
levn@0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
engines: {node: '>= 0.8.0'}
@@ -2829,6 +3127,9 @@ packages:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
+ lodash-es@4.17.21:
+ resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+
lodash.camelcase@4.3.0:
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
@@ -2845,6 +3146,10 @@ packages:
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ lucia@3.2.2:
+ resolution: {integrity: sha512-P1FlFBGCMPMXu+EGdVD9W4Mjm0DqsusmKgO7Xc33mI5X1bklmsQb0hfzPhXomQr9waWIBDsiOjvr1e6BTaUqpA==}
+ deprecated: This package has been deprecated. Please see https://lucia-auth.com/lucia-v3/migrate.
+
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
@@ -2862,6 +3167,10 @@ packages:
mdn-data@2.12.2:
resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==}
+ memoize@10.2.0:
+ resolution: {integrity: sha512-DeC6b7QBrZsRs3Y02A6A7lQyzFbsQbqgjI6UW0GigGWV+u1s25TycMr0XHZE4cJce7rY/vyw2ctMQqfDkIhUEA==}
+ engines: {node: '>=18'}
+
merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
@@ -2869,6 +3178,10 @@ packages:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
+ mimic-function@5.0.1:
+ resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
+ engines: {node: '>=18'}
+
mimic-response@3.1.0:
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
engines: {node: '>=10'}
@@ -3225,11 +3538,22 @@ packages:
rfdc@1.4.1:
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
+ robust-predicates@3.0.2:
+ resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==}
+
rollup@4.53.3:
resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
+ runed@0.31.1:
+ resolution: {integrity: sha512-v3czcTnO+EJjiPvD4dwIqfTdHLZ8oH0zJheKqAHh9QMViY7Qb29UlAMRpX7ZtHh7AFqV60KmfxaJ9QMy+L1igQ==}
+ peerDependencies:
+ svelte: ^5.7.0
+
+ rw@1.3.3:
+ resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
+
sade@1.8.1:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'}
@@ -3395,6 +3719,9 @@ packages:
resolution: {integrity: sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==}
engines: {node: '>=12.17'}
+ tailwind-merge@3.4.0:
+ resolution: {integrity: sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==}
+
tailwindcss@4.1.17:
resolution: {integrity: sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==}
@@ -3472,6 +3799,9 @@ packages:
ts-interface-checker@0.1.13:
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
tsup@8.5.1:
resolution: {integrity: sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing==}
engines: {node: '>=18'}
@@ -3909,6 +4239,12 @@ snapshots:
'@csstools/css-tokenizer@3.0.4': {}
+ '@dagrejs/dagre@1.1.8':
+ dependencies:
+ '@dagrejs/graphlib': 2.2.4
+
+ '@dagrejs/graphlib@2.2.4': {}
+
'@databases/escape-identifier@1.0.3':
dependencies:
'@databases/validate-unicode': 1.0.0
@@ -3935,6 +4271,22 @@ snapshots:
dependencies:
'@noble/ciphers': 1.3.0
+ '@emnapi/core@1.7.1':
+ dependencies:
+ '@emnapi/wasi-threads': 1.1.0
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/runtime@1.7.1':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/wasi-threads@1.1.0':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
'@esbuild/aix-ppc64@0.25.12':
optional: true
@@ -4174,6 +4526,17 @@ snapshots:
- bufferutil
- utf-8-validate
+ '@floating-ui/core@1.7.3':
+ dependencies:
+ '@floating-ui/utils': 0.2.10
+
+ '@floating-ui/dom@1.7.4':
+ dependencies:
+ '@floating-ui/core': 1.7.3
+ '@floating-ui/utils': 0.2.10
+
+ '@floating-ui/utils@0.2.10': {}
+
'@google-cloud/precise-date@4.0.0': {}
'@grpc/grpc-js@1.14.1':
@@ -4220,6 +4583,44 @@ snapshots:
'@js-sdsl/ordered-map@4.4.2': {}
+ '@layerstack/svelte-actions@1.0.1-next.14':
+ dependencies:
+ '@floating-ui/dom': 1.7.4
+ '@layerstack/utils': 2.0.0-next.14
+ d3-scale: 4.0.2
+
+ '@layerstack/svelte-state@0.1.0-next.19':
+ dependencies:
+ '@layerstack/utils': 2.0.0-next.14
+
+ '@layerstack/tailwind@2.0.0-next.17':
+ dependencies:
+ '@layerstack/utils': 2.0.0-next.14
+ clsx: 2.1.1
+ d3-array: 3.2.4
+ lodash-es: 4.17.21
+ tailwind-merge: 3.4.0
+
+ '@layerstack/utils@2.0.0-next.14':
+ dependencies:
+ d3-array: 3.2.4
+ d3-time: 3.1.0
+ d3-time-format: 4.1.0
+ lodash-es: 4.17.21
+
+ '@lucia-auth/adapter-postgresql@3.1.2(lucia@3.2.2)(postgres@3.4.7)':
+ dependencies:
+ lucia: 3.2.2
+ optionalDependencies:
+ postgres: 3.4.7
+
+ '@napi-rs/wasm-runtime@0.2.12':
+ dependencies:
+ '@emnapi/core': 1.7.1
+ '@emnapi/runtime': 1.7.1
+ '@tybys/wasm-util': 0.10.1
+ optional: true
+
'@noble/ciphers@1.3.0': {}
'@noble/curves@1.9.7':
@@ -4228,6 +4629,67 @@ snapshots:
'@noble/hashes@1.8.0': {}
+ '@node-rs/argon2-android-arm-eabi@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-android-arm64@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-darwin-arm64@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-darwin-x64@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-freebsd-x64@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-linux-arm-gnueabihf@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-linux-arm64-gnu@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-linux-arm64-musl@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-linux-x64-gnu@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-linux-x64-musl@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-wasm32-wasi@2.0.2':
+ dependencies:
+ '@napi-rs/wasm-runtime': 0.2.12
+ optional: true
+
+ '@node-rs/argon2-win32-arm64-msvc@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-win32-ia32-msvc@2.0.2':
+ optional: true
+
+ '@node-rs/argon2-win32-x64-msvc@2.0.2':
+ optional: true
+
+ '@node-rs/argon2@2.0.2':
+ optionalDependencies:
+ '@node-rs/argon2-android-arm-eabi': 2.0.2
+ '@node-rs/argon2-android-arm64': 2.0.2
+ '@node-rs/argon2-darwin-arm64': 2.0.2
+ '@node-rs/argon2-darwin-x64': 2.0.2
+ '@node-rs/argon2-freebsd-x64': 2.0.2
+ '@node-rs/argon2-linux-arm-gnueabihf': 2.0.2
+ '@node-rs/argon2-linux-arm64-gnu': 2.0.2
+ '@node-rs/argon2-linux-arm64-musl': 2.0.2
+ '@node-rs/argon2-linux-x64-gnu': 2.0.2
+ '@node-rs/argon2-linux-x64-musl': 2.0.2
+ '@node-rs/argon2-wasm32-wasi': 2.0.2
+ '@node-rs/argon2-win32-arm64-msvc': 2.0.2
+ '@node-rs/argon2-win32-ia32-msvc': 2.0.2
+ '@node-rs/argon2-win32-x64-msvc': 2.0.2
+
'@opentelemetry/api-logs@0.203.0':
dependencies:
'@opentelemetry/api': 1.9.0
@@ -4930,6 +5392,19 @@ snapshots:
'@opentelemetry/api': 1.9.0
'@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0)
+ '@oslojs/asn1@1.0.0':
+ dependencies:
+ '@oslojs/binary': 1.0.0
+
+ '@oslojs/binary@1.0.0': {}
+
+ '@oslojs/crypto@1.0.1':
+ dependencies:
+ '@oslojs/asn1': 1.0.0
+ '@oslojs/binary': 1.0.0
+
+ '@oslojs/encoding@1.1.0': {}
+
'@pinojs/redact@0.4.0': {}
'@polka/url@1.0.0-next.29': {}
@@ -5258,6 +5733,11 @@ snapshots:
tailwindcss: 4.1.17
vite: 7.2.6(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)
+ '@tybys/wasm-util@0.10.1':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
'@types/aws-lambda@8.10.152': {}
'@types/babel__core@7.20.5':
@@ -5719,6 +6199,8 @@ snapshots:
commander@4.1.1: {}
+ commander@7.2.0: {}
+
commondir@1.0.1: {}
compare-utf8@0.1.1: {}
@@ -5756,6 +6238,106 @@ snapshots:
csstype@3.2.3: {}
+ d3-array@2.12.1:
+ dependencies:
+ internmap: 1.0.1
+
+ d3-array@3.2.4:
+ dependencies:
+ internmap: 2.0.3
+
+ d3-color@3.1.0: {}
+
+ d3-delaunay@6.0.4:
+ dependencies:
+ delaunator: 5.0.1
+
+ d3-dispatch@3.0.1: {}
+
+ d3-dsv@3.0.1:
+ dependencies:
+ commander: 7.2.0
+ iconv-lite: 0.6.3
+ rw: 1.3.3
+
+ 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-voronoi@2.1.0:
+ dependencies:
+ d3-array: 3.2.4
+ d3-delaunay: 6.0.4
+ d3-geo: 3.1.1
+ d3-tricontour: 1.1.0
+
+ d3-geo@3.1.1:
+ dependencies:
+ d3-array: 3.2.4
+
+ d3-hierarchy@3.1.2: {}
+
+ d3-interpolate-path@2.3.0: {}
+
+ d3-interpolate@3.0.1:
+ dependencies:
+ d3-color: 3.1.0
+
+ d3-path@1.0.9: {}
+
+ d3-path@3.1.0: {}
+
+ d3-quadtree@3.0.1: {}
+
+ d3-random@3.0.1: {}
+
+ d3-sankey@0.12.3:
+ dependencies:
+ d3-array: 2.12.1
+ d3-shape: 1.3.7
+
+ 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-shape@1.3.7:
+ dependencies:
+ d3-path: 1.0.9
+
+ d3-shape@3.2.0:
+ dependencies:
+ d3-path: 3.1.0
+
+ d3-tile@1.0.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-tricontour@1.1.0:
+ dependencies:
+ d3-delaunay: 6.0.4
+ d3-scale: 4.0.2
+
data-urls@6.0.0:
dependencies:
whatwg-mimetype: 4.0.0
@@ -5785,6 +6367,10 @@ snapshots:
defu@6.1.4: {}
+ delaunator@5.0.1:
+ dependencies:
+ robust-predicates: 3.0.2
+
dequal@2.0.3: {}
detect-libc@2.1.2: {}
@@ -6261,6 +6847,10 @@ snapshots:
ini@1.3.8: {}
+ internmap@1.0.1: {}
+
+ internmap@2.0.3: {}
+
ipaddr.js@2.3.0: {}
is-arguments@1.2.0:
@@ -6417,6 +7007,37 @@ snapshots:
known-css-properties@0.37.0: {}
+ layerchart@2.0.0-next.43(svelte@5.45.3):
+ dependencies:
+ '@dagrejs/dagre': 1.1.8
+ '@layerstack/svelte-actions': 1.0.1-next.14
+ '@layerstack/svelte-state': 0.1.0-next.19
+ '@layerstack/tailwind': 2.0.0-next.17
+ '@layerstack/utils': 2.0.0-next.14
+ d3-array: 3.2.4
+ d3-color: 3.1.0
+ d3-delaunay: 6.0.4
+ d3-dsv: 3.0.1
+ d3-force: 3.0.0
+ d3-geo: 3.1.1
+ d3-geo-voronoi: 2.1.0
+ d3-hierarchy: 3.1.2
+ d3-interpolate: 3.0.1
+ d3-interpolate-path: 2.3.0
+ d3-path: 3.1.0
+ d3-quadtree: 3.0.1
+ d3-random: 3.0.1
+ d3-sankey: 0.12.3
+ d3-scale: 4.0.2
+ d3-scale-chromatic: 3.1.0
+ d3-shape: 3.2.0
+ d3-tile: 1.0.0
+ d3-time: 3.1.0
+ lodash-es: 4.17.21
+ memoize: 10.2.0
+ runed: 0.31.1(svelte@5.45.3)
+ svelte: 5.45.3
+
levn@0.4.1:
dependencies:
prelude-ls: 1.2.1
@@ -6491,6 +7112,8 @@ snapshots:
dependencies:
p-locate: 5.0.0
+ lodash-es@4.17.21: {}
+
lodash.camelcase@4.3.0: {}
lodash.merge@4.6.2: {}
@@ -6503,6 +7126,11 @@ snapshots:
dependencies:
yallist: 3.1.1
+ lucia@3.2.2:
+ dependencies:
+ '@oslojs/crypto': 1.0.1
+ '@oslojs/encoding': 1.1.0
+
magic-string@0.30.21:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -6521,10 +7149,16 @@ snapshots:
mdn-data@2.12.2: {}
+ memoize@10.2.0:
+ dependencies:
+ mimic-function: 5.0.1
+
merge-stream@2.0.0: {}
mimic-fn@2.1.0: {}
+ mimic-function@5.0.1: {}
+
mimic-response@3.1.0: {}
minimatch@3.1.2:
@@ -6840,6 +7474,8 @@ snapshots:
rfdc@1.4.1: {}
+ robust-predicates@3.0.2: {}
+
rollup@4.53.3:
dependencies:
'@types/estree': 1.0.8
@@ -6868,6 +7504,13 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.53.3
fsevents: 2.3.3
+ runed@0.31.1(svelte@5.45.3):
+ dependencies:
+ esm-env: 1.2.2
+ svelte: 5.45.3
+
+ rw@1.3.3: {}
+
sade@1.8.1:
dependencies:
mri: 1.2.0
@@ -7039,6 +7682,8 @@ snapshots:
array-back: 6.2.2
wordwrapjs: 5.1.1
+ tailwind-merge@3.4.0: {}
+
tailwindcss@4.1.17: {}
tapable@2.3.0: {}
@@ -7109,6 +7754,9 @@ snapshots:
ts-interface-checker@0.1.13: {}
+ tslib@2.8.1:
+ optional: true
+
tsup@8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3):
dependencies:
bundle-require: 5.1.0(esbuild@0.27.0)
+
+Beacon+Create an account+ + {#if form?.error} +
+ {form.error}
+
+ {/if}
+
+
+
+ + Already have an account? + Sign in + + |