@maravilla-labs/platform 0.3.8 → 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -936,6 +936,7 @@ function createRemoteClient(baseUrl, tenant) {
936
936
  const db = new RemoteDatabase(baseUrl, headers);
937
937
  const storage = new RemoteStorage(baseUrl, headers);
938
938
  const media = new RemoteMediaService(baseUrl, headers);
939
+ media.transforms = new RemoteTransformsService(baseUrl, headers);
939
940
  const realtime = new RemoteRealtimeService(baseUrl, headers);
940
941
  const auth = new RemoteAuthService(baseUrl, headers);
941
942
  const policy = new RemotePolicyService();
@@ -953,6 +954,52 @@ function createRemoteClient(baseUrl, tenant) {
953
954
  workflows
954
955
  };
955
956
  }
957
+ var RemoteTransformsService = class {
958
+ constructor(baseUrl, headers) {
959
+ this.baseUrl = baseUrl;
960
+ this.headers = headers;
961
+ }
962
+ baseUrl;
963
+ headers;
964
+ async post(path, body) {
965
+ const res = await fetch(`${this.baseUrl}/api/media/transforms${path}`, {
966
+ method: "POST",
967
+ headers: { "Content-Type": "application/json", ...this.headers, ...getRequestAuthHeader() },
968
+ body: JSON.stringify(body)
969
+ });
970
+ if (!res.ok) {
971
+ const text = await res.text();
972
+ throw new Error(`Transforms error (${res.status}): ${text}`);
973
+ }
974
+ return res.json();
975
+ }
976
+ transcode(srcKey, opts) {
977
+ return this.post("/transcode", { srcKey, opts });
978
+ }
979
+ thumbnail(srcKey, opts) {
980
+ return this.post("/thumbnail", { srcKey, opts });
981
+ }
982
+ resize(srcKey, opts) {
983
+ return this.post("/resize", { srcKey, opts });
984
+ }
985
+ ocr(srcKey, opts) {
986
+ return this.post("/ocr", { srcKey, opts: opts ?? {} });
987
+ }
988
+ probe(srcKey) {
989
+ return this.post("/probe", { srcKey });
990
+ }
991
+ async job(id) {
992
+ const res = await fetch(`${this.baseUrl}/api/media/transforms/jobs/${encodeURIComponent(id)}`, {
993
+ method: "GET",
994
+ headers: { ...this.headers, ...getRequestAuthHeader() }
995
+ });
996
+ if (!res.ok) {
997
+ const text = await res.text();
998
+ throw new Error(`Transforms job lookup error (${res.status}): ${text}`);
999
+ }
1000
+ return res.json();
1001
+ }
1002
+ };
956
1003
 
957
1004
  // src/ren.ts
958
1005
  var RenClient = class {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/request-scope.ts","../src/media.ts","../src/remote-client.ts","../src/ren.ts","../src/realtime.ts","../src/media-room.ts","../src/push.ts","../src/transforms.ts","../src/index.ts"],"sourcesContent":["/**\n * Per-request scope for the SDK's remote client. Mirrors the runtime's\n * `REQUEST_CTX` (a `tokio::task_local!` in Rust) so that\n * `platform.auth.setCurrentUser(token)`, `getCurrentUser()`, and `can()`\n * — plus future per-request state like the Layer-2 policy toggle —\n * have a place to live when the SDK is running outside the runtime\n * (Vite SSR, Node.js HTTP servers, edge workers that expose Node APIs).\n *\n * Implementation: Node's `AsyncLocalStorage`. Tenant code wraps each\n * inbound request with `runWithRequest(async () => { ... })` so the\n * store stays scoped to the request's async chain. `setCurrentUser`\n * / `can` read and write that store; if a tenant forgets to wrap, the\n * methods either no-op (set) or throw a clear error (get/can).\n */\n\nimport type { AuthCaller, AuthUser } from './types.js';\n\nexport interface RequestStore {\n /** Bound access-token JWT (set by `auth.setCurrentUser`). */\n token?: string;\n /** Bound user (cached so `getCurrentUser` doesn't re-validate). */\n user?: AuthUser;\n /** Whether Layer-2 policy enforcement is enabled for this request. */\n policyEnabled: boolean;\n}\n\n// Lazy-loaded so this module is safe to import in non-Node environments\n// (browsers, edge workers) where `node:async_hooks` doesn't exist. Calls\n// to runWithRequest in those environments fall back to a synchronous\n// no-op scope (the fn just runs `fn()`).\nlet alsImpl: { run: (s: RequestStore, fn: () => any) => any; getStore: () => RequestStore | undefined } | null = null;\n\nasync function ensureAls() {\n if (alsImpl) return alsImpl;\n try {\n // Dynamic import keeps non-Node environments from crashing at module\n // load time. `node:async_hooks` is unconditionally available in Node.\n const { AsyncLocalStorage } = await import('node:async_hooks');\n const inner = new AsyncLocalStorage<RequestStore>();\n alsImpl = {\n run: (s, fn) => inner.run(s, fn),\n getStore: () => inner.getStore(),\n };\n } catch {\n // Non-Node: stub. Note that without ALS, concurrent requests will\n // share the same `cachedStore`, which is wrong — but in non-Node\n // SDK environments the per-request use case typically doesn't\n // apply (browser code is single-threaded per page).\n let cached: RequestStore | undefined;\n alsImpl = {\n run: (s, fn) => {\n const prev = cached;\n cached = s;\n try {\n return fn();\n } finally {\n cached = prev;\n }\n },\n getStore: () => cached,\n };\n }\n return alsImpl;\n}\n\n/**\n * Wrap a function in a fresh request scope. **Rarely needed** — the\n * Maravilla Vite plugin (`@maravilla-labs/vite-plugin`) auto-opens a\n * scope around every inbound dev HTTP request, so tenant code\n * (SvelteKit `hooks.server.ts`, RR/Remix loaders, etc.) reaches\n * `setCurrentUser/getCurrentUser/can` with a scope already active.\n *\n * Reach for `runWithRequest` only when the SDK runs **outside** an\n * HTTP request: standalone Node scripts, test fixtures, custom\n * servers that don't go through Vite. Inside an active scope,\n * `platform.auth.setCurrentUser/getCurrentUser/can` operate on a\n * per-request store keyed by Node's `AsyncLocalStorage`.\n *\n * @example\n * ```ts\n * // Test fixture that needs to bind a user before exercising the SDK\n * await runWithRequest(async () => {\n * await getPlatform().auth.setCurrentUser(testToken);\n * const result = await getPlatform().env.DB.find('users', {});\n * expect(result).toEqual(...);\n * });\n * ```\n */\nexport async function runWithRequest<T>(fn: () => Promise<T> | T): Promise<T> {\n const als = await ensureAls();\n return als.run({ policyEnabled: true }, () => Promise.resolve(fn())) as Promise<T>;\n}\n\n/**\n * Read the current request's store, if any. Returns undefined when\n * called outside a `runWithRequest` scope. Used by `RemoteAuthService`\n * and (future) other Remote* services to source per-request state.\n *\n * Note: the `als` may not yet be initialised when this is called; in\n * that case the function returns undefined synchronously. Subsequent\n * `runWithRequest` calls will populate it.\n */\nexport function getCurrentRequestStore(): RequestStore | undefined {\n return alsImpl?.getStore();\n}\n\n/**\n * Construct an anonymous `AuthCaller` snapshot — used by\n * `auth.getCurrentUser()` when no identity is bound.\n */\nexport function anonymousCaller(): AuthCaller {\n return {\n user_id: '',\n email: '',\n is_admin: false,\n roles: [],\n is_anonymous: true,\n };\n}\n\n/**\n * Return `Authorization: Bearer <token>` if a token is bound in the\n * current request store, else an empty object. Every Remote* service's\n * fetch helper merges this so dev-server can identify the caller and\n * (eventually) enforce Layer-2 policies on KV/DB/Storage ops.\n *\n * Synchronous so it can be called from inside `headers: { ... }`\n * literals without forcing each fetch helper to be re-shaped.\n */\nexport function getRequestAuthHeader(): Record<string, string> {\n const token = alsImpl?.getStore()?.token;\n return token ? { Authorization: `Bearer ${token}` } : {};\n}\n","/**\n * Media service for video/audio room management.\n *\n * In production (Deno runtime) calls go through `Deno.core.ops`.\n * In development they are proxied as HTTP requests to the dev-server.\n */\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface MediaRoomInfo {\n name: string;\n numParticipants: number;\n maxParticipants: number;\n createdAt: number;\n active: boolean;\n}\n\nexport interface MediaRoomInfoSettings {\n maxParticipants?: number;\n emptyTimeoutSecs?: number;\n}\n\nexport interface MediaParticipantInfo {\n identity: string;\n name: string;\n canPublish?: boolean;\n canSubscribe?: boolean;\n canPublishData?: boolean;\n}\n\nexport interface MediaTokenResult {\n token: string;\n url: string;\n}\n\nexport interface MediaService {\n createRoom(roomId: string, settings?: MediaRoomInfoSettings): Promise<MediaRoomInfo>;\n deleteRoom(roomId: string): Promise<void>;\n listRooms(): Promise<MediaRoomInfo[]>;\n generateToken(roomId: string, participant: MediaParticipantInfo): Promise<MediaTokenResult>;\n mediaUrl(): Promise<string | null>;\n}\n\n// ── Remote (dev-server) implementation ───────────────────────────────\n\nexport class RemoteMediaService implements MediaService {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>,\n ) {}\n\n private async fetch(url: string, options: RequestInit = {}) {\n const { getRequestAuthHeader } = await import('./request-scope.js');\n const response = await fetch(url, {\n ...options,\n headers: { ...this.headers, ...getRequestAuthHeader(), ...options.headers },\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Media API error: ${response.status} - ${error}`);\n }\n\n return response;\n }\n\n async createRoom(roomId: string, settings: MediaRoomInfoSettings = {}): Promise<MediaRoomInfo> {\n const response = await this.fetch(`${this.baseUrl}/api/media/rooms`, {\n method: 'POST',\n body: JSON.stringify({ roomId, settings }),\n });\n return response.json() as Promise<MediaRoomInfo>;\n }\n\n async deleteRoom(roomId: string): Promise<void> {\n await this.fetch(`${this.baseUrl}/api/media/rooms/${encodeURIComponent(roomId)}`, {\n method: 'DELETE',\n });\n }\n\n async listRooms(): Promise<MediaRoomInfo[]> {\n const response = await this.fetch(`${this.baseUrl}/api/media/rooms`);\n return response.json() as Promise<MediaRoomInfo[]>;\n }\n\n async generateToken(roomId: string, participant: MediaParticipantInfo): Promise<MediaTokenResult> {\n const response = await this.fetch(\n `${this.baseUrl}/api/media/rooms/${encodeURIComponent(roomId)}/token`,\n {\n method: 'POST',\n body: JSON.stringify(participant),\n },\n );\n return response.json() as Promise<MediaTokenResult>;\n }\n\n async mediaUrl(): Promise<string | null> {\n const response = await this.fetch(`${this.baseUrl}/api/media/url`);\n const data = (await response.json()) as { url: string | null };\n return data.url;\n }\n}\n","import type { KvNamespace, KvListResult, Database, DbFindOptions, Storage, RealtimeService, PresenceService, AuthService, AuthCaller, AuthUser, AuthSession, AuthField, RegisterOptions, LoginOptions, UserListFilter, UserListResponse, UpdateUserOptions, PolicyService, VectorIndexSpec, VectorIndexDescriptor, VectorQueryWithFilter, VectorSearchHit, IndexSpec, IndexDescriptor, Workflows, WorkflowHandle, WorkflowRun, WorkflowStepRecord } from './types.js';\nimport { RemoteMediaService } from './media.js';\nimport { getRequestAuthHeader } from './request-scope.js';\n\n/**\n * Remote KV namespace implementation that communicates with a development server.\n * This class provides the KV interface by making HTTP requests to the dev server.\n * \n * @internal\n */\nclass RemoteKvNamespace implements KvNamespace {\n constructor(\n private baseUrl: string,\n private namespace: string,\n private headers: Record<string, string>\n ) {}\n\n /**\n * Internal method for making HTTP requests to the dev server.\n * Handles error responses and authentication headers.\n * \n * @internal\n */\n private async fetch(url: string, options: RequestInit = {}) {\n const response = await fetch(url, {\n ...options,\n headers: { ...this.headers, ...getRequestAuthHeader(), ...options.headers },\n });\n\n if (!response.ok && response.status !== 404) {\n const error = await response.text();\n throw new Error(`Platform API error: ${response.status} - ${error}`);\n }\n\n return response;\n }\n\n async get(key: string): Promise<any> {\n const response = await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}/${key}`);\n if (response.status === 404) return null;\n return response.json();\n }\n\n async put(key: string, value: any, options?: { expirationTtl?: number }): Promise<void> {\n const headers: Record<string, string> = {};\n if (options?.expirationTtl) {\n headers['X-TTL'] = options.expirationTtl.toString();\n }\n\n await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}/${key}`, {\n method: 'PUT',\n headers,\n body: JSON.stringify(value),\n });\n }\n\n async delete(key: string): Promise<void> {\n await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}/${key}`, {\n method: 'DELETE',\n });\n }\n\n async list(options?: { prefix?: string; limit?: number; cursor?: string }): Promise<KvListResult> {\n const response = await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}`, {\n method: 'POST',\n body: JSON.stringify(options || {}),\n });\n const data = await response.json() as any;\n return {\n keys: data.result || [],\n list_complete: !data.result_info?.cursor,\n cursor: data.result_info?.cursor,\n };\n }\n}\n\n/**\n * Remote Database implementation that communicates with a development server.\n * This class provides the Database interface by making HTTP requests to the dev server.\n * \n * @internal\n */\nclass RemoteDatabase implements Database {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>\n ) {}\n\n /**\n * Internal method for making HTTP requests to the dev server.\n * Handles error responses and authentication headers.\n * \n * @internal\n */\n private async fetch(url: string, options: RequestInit = {}) {\n const response = await fetch(url, {\n ...options,\n headers: { ...this.headers, ...getRequestAuthHeader(), ...options.headers },\n });\n\n if (!response.ok && response.status !== 404) {\n const error = await response.text();\n throw new Error(`Platform API error: ${response.status} - ${error}`);\n }\n\n return response;\n }\n\n async find(collection: string, filter: any = {}, options: DbFindOptions = {}): Promise<any[]> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}`, {\n method: 'POST',\n body: JSON.stringify({ filter, options }),\n });\n return response.json() as Promise<any[]>;\n }\n\n async findOne(collection: string, filter: any): Promise<any | null> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/findOne`, {\n method: 'POST',\n body: JSON.stringify(filter),\n });\n if (response.status === 404) return null;\n return response.json();\n }\n\n async insertOne(collection: string, document: any): Promise<string> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}`, {\n method: 'PUT',\n body: JSON.stringify(document),\n });\n const result = await response.json() as any;\n return result.id;\n }\n\n async updateOne(collection: string, filter: any, update: any): Promise<{ modified: number }> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/update`, {\n method: 'POST',\n body: JSON.stringify({ filter, update }),\n });\n return response.json() as Promise<{ modified: number }>;\n }\n\n async deleteOne(collection: string, filter: any): Promise<{ deleted: number }> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/delete`, {\n method: 'DELETE',\n body: JSON.stringify(filter),\n });\n return response.json() as Promise<{ deleted: number }>;\n }\n\n async deleteMany(collection: string, filter: any): Promise<{ deleted: number }> {\n // For now, deleteMany is the same as deleteOne in the remote client\n // This would need to be implemented properly in the dev server\n return this.deleteOne(collection, filter);\n }\n\n async createVectorIndex(collection: string, spec: VectorIndexSpec): Promise<void> {\n await this.fetch(`${this.baseUrl}/api/db/${collection}/vectorIndexes`, {\n method: 'POST',\n body: JSON.stringify(spec),\n });\n }\n\n async dropVectorIndex(collection: string, field: string): Promise<{ removed: boolean }> {\n const response = await this.fetch(\n `${this.baseUrl}/api/db/${collection}/vectorIndexes/${encodeURIComponent(field)}`,\n { method: 'DELETE' },\n );\n return response.json() as Promise<{ removed: boolean }>;\n }\n\n async listVectorIndexes(collection: string): Promise<VectorIndexDescriptor[]> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/vectorIndexes`, {\n method: 'GET',\n });\n return response.json() as Promise<VectorIndexDescriptor[]>;\n }\n\n async findSimilar(collection: string, query: VectorQueryWithFilter): Promise<VectorSearchHit[]> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/vectorSearch`, {\n method: 'POST',\n body: JSON.stringify(query),\n });\n return response.json() as Promise<VectorSearchHit[]>;\n }\n\n async createIndex(collection: string, spec: IndexSpec): Promise<IndexDescriptor> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/indexes`, {\n method: 'POST',\n body: JSON.stringify(spec),\n });\n return response.json() as Promise<IndexDescriptor>;\n }\n\n async dropIndex(collection: string, name: string): Promise<{ removed: boolean }> {\n const response = await this.fetch(\n `${this.baseUrl}/api/db/${collection}/indexes/${encodeURIComponent(name)}`,\n { method: 'DELETE' },\n );\n return response.json() as Promise<{ removed: boolean }>;\n }\n\n async listIndexes(collection: string): Promise<IndexDescriptor[]> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/indexes`, {\n method: 'GET',\n });\n return response.json() as Promise<IndexDescriptor[]>;\n }\n}\n\n/**\n * Remote Storage implementation that communicates with a development server.\n * This class provides the Storage interface by making HTTP requests to the dev server.\n * \n * @internal\n */\nclass RemoteStorage implements Storage {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>\n ) {}\n\n /**\n * Internal method for making HTTP requests to the dev server.\n * Handles error responses and authentication headers.\n * \n * @internal\n */\n private async fetch(url: string, options: RequestInit = {}) {\n const response = await fetch(url, {\n ...options,\n headers: { ...this.headers, ...getRequestAuthHeader(), ...options.headers },\n });\n\n if (!response.ok && response.status !== 404) {\n const error = await response.text();\n throw new Error(`Platform API error: ${response.status} - ${error}`);\n }\n\n return response;\n }\n\n async generateUploadUrl(key: string, contentType: string, options?: { sizeLimit?: number }): Promise<{\n url: string;\n method: string;\n headers: Record<string, string>;\n expiresIn: number;\n }> {\n // Pre-flight Layer-2 gate: dev-server runs the bucket policy with\n // `action: \"upload-url\"` and returns the upload URL on success\n // (or 403 on denial). Mirrors prod's\n // platform.storage.generateUploadUrl behaviour.\n const res = await this.fetch(`${this.baseUrl}/api/storage/upload-url`, {\n method: 'POST',\n body: JSON.stringify({ key, content_type: contentType, size_limit: options?.sizeLimit }),\n });\n const data = (await res.json()) as { url: string; method: string; headers: Record<string, string>; expiresIn: number };\n // The dev-server returns a relative URL; absolutise it. Prepend\n // tenant headers so direct PUTs by the caller still carry the\n // X-Tenant-Id (Authorization will be re-added at fetch time by\n // getRequestAuthHeader if a request scope is bound).\n return {\n url: data.url.startsWith('http') ? data.url : `${this.baseUrl}${data.url}`,\n method: data.method,\n headers: { ...data.headers, ...this.headers },\n expiresIn: data.expiresIn,\n };\n }\n\n async generateDownloadUrl(key: string, options?: { expiresIn?: number }): Promise<{\n url: string;\n method: string;\n headers: Record<string, string>;\n expiresIn: number;\n }> {\n const res = await this.fetch(`${this.baseUrl}/api/storage/download-url`, {\n method: 'POST',\n body: JSON.stringify({ key, expires_in: options?.expiresIn }),\n });\n const data = (await res.json()) as { url: string; method: string; headers: Record<string, string>; expiresIn: number };\n return {\n url: data.url.startsWith('http') ? data.url : `${this.baseUrl}${data.url}`,\n method: data.method,\n headers: data.headers,\n expiresIn: data.expiresIn,\n };\n }\n\n // Dev-mode: emit the same `/_assets/<key>` shape production does.\n // Dev-server's /_assets/* handler streams from the same dir\n // STORAGE.put writes to (`{project_root}/.maravilla/storage`), so user\n // JS paths render and load identically across dev and prod.\n // No signing in dev — `expires`/`sig` query params are accepted and\n // ignored by the dev-server handler.\n getAssetUrl(key: string, _opts?: { signed?: boolean; ttl?: number }): string {\n const clean = key.replace(/^\\/+/, '');\n return `${this.baseUrl}/_assets/${clean}`;\n }\n\n async get(key: string): Promise<Uint8Array | null> {\n const response = await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`);\n if (response.status === 404) return null;\n const arrayBuffer = await response.arrayBuffer();\n return new Uint8Array(arrayBuffer);\n }\n\n async put(key: string, data: Uint8Array | string, metadata?: any): Promise<void> {\n // Convert string to Uint8Array if needed\n const bodyData = typeof data === 'string' \n ? new TextEncoder().encode(data)\n : data;\n\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'PUT',\n headers: metadata ? { 'X-Metadata': JSON.stringify(metadata) } : {},\n // Cast because TypeScript's lib.dom.d.ts BodyInit union sometimes misses Uint8Array\n body: bodyData as any,\n });\n }\n\n async putStream(key: string, source: any, metadata?: any): Promise<void> {\n // If it's a Blob we can send directly\n if (typeof Blob !== 'undefined' && source instanceof Blob) {\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'PUT',\n headers: {\n ...(metadata ? { 'X-Metadata': JSON.stringify(metadata) } : {}),\n 'Content-Type': source.type || 'application/octet-stream'\n },\n body: source as any,\n });\n return;\n }\n\n // ReadableStream\n if (source && typeof source.getReader === 'function') {\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'PUT',\n headers: metadata ? { 'X-Metadata': JSON.stringify(metadata) } : {},\n body: source as any,\n });\n return;\n }\n\n // Async iterable -> wrap in ReadableStream\n if (Symbol.asyncIterator in Object(source ?? {})) {\n const asyncIt = source as AsyncIterable<any>;\n const stream = new ReadableStream({\n async pull(controller) {\n const { value, done } = await asyncIt[Symbol.asyncIterator]().next();\n if (done) { controller.close(); return; }\n controller.enqueue(RemoteStorage.normalizeChunk(value));\n }\n });\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'PUT',\n headers: metadata ? { 'X-Metadata': JSON.stringify(metadata) } : {},\n body: stream as any,\n });\n return;\n }\n\n // Synchronous iterable\n if (Symbol.iterator in Object(source ?? {})) {\n const it = (source as Iterable<any>)[Symbol.iterator]();\n const stream = new ReadableStream({\n pull(controller) {\n const res = it.next();\n if (res.done) { controller.close(); return; }\n controller.enqueue(RemoteStorage.normalizeChunk(res.value));\n }\n });\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'PUT',\n headers: metadata ? { 'X-Metadata': JSON.stringify(metadata) } : {},\n body: stream as any,\n });\n return;\n }\n\n // Fallback: primitive/string/Uint8Array/ArrayBuffer\n await this.put(key, RemoteStorage.normalizeChunk(source), metadata);\n }\n private static normalizeChunk(c: any): Uint8Array {\n if (c == null) return new Uint8Array();\n if (typeof c === 'string') return new TextEncoder().encode(c);\n if (c instanceof Uint8Array) return c;\n if (c instanceof ArrayBuffer) return new Uint8Array(c);\n if (Array.isArray(c)) return Uint8Array.from(c);\n throw new Error('Unsupported chunk type in putStream');\n }\n async delete(key: string): Promise<void> {\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'DELETE',\n });\n }\n\n async list(options?: { prefix?: string; limit?: number }): Promise<Array<{\n key: string;\n size: number;\n lastModified: string;\n metadata?: any;\n }>> {\n const params = new URLSearchParams();\n if (options?.prefix) params.set('prefix', options.prefix);\n if (options?.limit) params.set('limit', options.limit.toString());\n\n const response = await this.fetch(`${this.baseUrl}/api/storage?${params}`);\n return response.json();\n }\n\n async getMetadata(key: string): Promise<{\n size: number;\n contentType?: string;\n lastModified: string;\n metadata?: any;\n } | null> {\n const response = await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}/metadata`);\n if (response.status === 404) return null;\n return response.json();\n }\n\n async confirm(key: string): Promise<void> {\n // Mirrors the dev-server route registered in\n // `crates/dev-server/src/router.rs`:\n // POST /api/storage/confirm body: { key: \"...\" }\n // The handler verifies the object actually landed in the backing store\n // and publishes the synthesized `storage.put` RenEvent that any\n // registered handlers (including those synthesized from a `transforms`\n // config block) react to.\n await this.fetch(`${this.baseUrl}/api/storage/confirm`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ key }),\n });\n }\n}\n\n/**\n * Remote Realtime service for development — calls dev server HTTP endpoints.\n * @internal\n */\nclass RemotePresenceService implements PresenceService {\n constructor(private baseUrl: string, private headers: Record<string, string>) {}\n\n async join(channel: string, userId: string, metadata?: any): Promise<boolean> {\n const res = await fetch(`${this.baseUrl}/api/realtime/presence/${encodeURIComponent(channel)}/join`, {\n method: 'POST',\n headers: { ...this.headers, ...getRequestAuthHeader() },\n body: JSON.stringify({ userId, metadata }),\n });\n const data = await res.json() as any;\n return data.isNew ?? true;\n }\n\n async leave(channel: string, userId: string): Promise<boolean> {\n const res = await fetch(`${this.baseUrl}/api/realtime/presence/${encodeURIComponent(channel)}/leave`, {\n method: 'POST',\n headers: { ...this.headers, ...getRequestAuthHeader() },\n body: JSON.stringify({ userId }),\n });\n const data = await res.json() as any;\n return data.wasPresent ?? true;\n }\n\n async members(channel: string): Promise<Array<{ userId: string; metadata?: any; lastSeen?: number }>> {\n const res = await fetch(`${this.baseUrl}/api/realtime/presence/${encodeURIComponent(channel)}`, {\n headers: { ...this.headers, ...getRequestAuthHeader() },\n });\n const data = await res.json() as any;\n return data.members ?? [];\n }\n}\n\nclass RemoteRealtimeService implements RealtimeService {\n presence: PresenceService;\n\n constructor(private baseUrl: string, private headers: Record<string, string>) {\n this.presence = new RemotePresenceService(baseUrl, headers);\n }\n\n async publish(channel: string, data: any, options?: { userId?: string }): Promise<void> {\n await fetch(`${this.baseUrl}/api/realtime/publish`, {\n method: 'POST',\n headers: { ...this.headers, ...getRequestAuthHeader() },\n body: JSON.stringify({ channel, data, userId: options?.userId }),\n });\n }\n\n async channels(): Promise<string[]> {\n const res = await fetch(`${this.baseUrl}/api/realtime/channels`, {\n headers: { ...this.headers, ...getRequestAuthHeader() },\n });\n const data = await res.json() as any;\n return data.channels ?? [];\n }\n}\n\n/**\n * Remote auth service for development environments.\n * Calls the dev-server's platform auth ops via HTTP.\n * @internal\n */\nclass RemoteAuthService implements AuthService {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>\n ) {}\n\n private async post(path: string, body?: any): Promise<any> {\n const res = await fetch(`${this.baseUrl}/api/platform/auth${path}`, {\n method: 'POST',\n headers: { ...this.headers, ...getRequestAuthHeader() },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Auth error (${res.status}): ${text}`);\n }\n if (res.status === 204) return undefined;\n return res.json();\n }\n\n async register(options: RegisterOptions): Promise<AuthUser> {\n return this.post('/register', options);\n }\n\n async login(options: LoginOptions): Promise<AuthSession> {\n return this.post('/login', options);\n }\n\n async validate(accessToken: string): Promise<AuthUser> {\n return this.post('/validate', { token: accessToken });\n }\n\n async refresh(refreshToken: string): Promise<AuthSession> {\n return this.post('/refresh', { token: refreshToken });\n }\n\n async logout(sessionId: string): Promise<void> {\n await this.post('/logout', { session_id: sessionId });\n }\n\n async getUser(userId: string): Promise<AuthUser | null> {\n return this.post('/get-user', { user_id: userId });\n }\n\n async listUsers(filter?: UserListFilter): Promise<UserListResponse> {\n return this.post('/list-users', filter ?? {});\n }\n\n async updateUser(userId: string, update: UpdateUserOptions): Promise<AuthUser> {\n return this.post('/update-user', { user_id: userId, ...update });\n }\n\n async deleteUser(userId: string): Promise<void> {\n await this.post('/delete-user', { user_id: userId });\n }\n\n async sendVerification(userId: string): Promise<{ token: string }> {\n return this.post('/send-verification', { user_id: userId });\n }\n\n async verifyEmail(token: string): Promise<void> {\n await this.post('/verify-email', { token });\n }\n\n async sendPasswordReset(email: string): Promise<{ token: string }> {\n return this.post('/send-password-reset', { email });\n }\n\n async resetPassword(token: string, newPassword: string): Promise<void> {\n await this.post('/reset-password', { token, new_password: newPassword });\n }\n\n async changePassword(userId: string, oldPassword: string, newPassword: string): Promise<void> {\n await this.post('/change-password', { user_id: userId, old_password: oldPassword, new_password: newPassword });\n }\n\n async getFieldConfig(): Promise<{ fields: AuthField[] }> {\n return this.post('/field-config');\n }\n\n async getOAuthUrl(provider: string, options?: { redirectUri?: string }): Promise<{ auth_url: string; state: string }> {\n return this.post('/oauth/start', { provider, redirect_uri: options?.redirectUri || `/_auth/callback/${provider}` });\n }\n\n async handleOAuthCallback(provider: string, params: { code: string; state: string }): Promise<any> {\n return this.post('/oauth/callback', { provider, code: params.code, state: params.state });\n }\n\n // ── Groups ──\n\n async createGroup(options: any): Promise<any> {\n return this.post('/groups/create', options);\n }\n async listGroups(): Promise<any[]> {\n return this.post('/groups/list', {});\n }\n async getGroup(groupId: string): Promise<any> {\n return this.post('/groups/get', { group_id: groupId });\n }\n async updateGroup(groupId: string, options: any): Promise<any> {\n return this.post('/groups/update', { group_id: groupId, ...options });\n }\n async deleteGroup(groupId: string): Promise<void> {\n await this.post('/groups/delete', { group_id: groupId });\n }\n async addUserToGroup(userId: string, groupId: string): Promise<void> {\n await this.post('/groups/add-user', { user_id: userId, group_id: groupId });\n }\n async removeUserFromGroup(userId: string, groupId: string): Promise<void> {\n await this.post('/groups/remove-user', { user_id: userId, group_id: groupId });\n }\n async getUserGroups(userId: string): Promise<any[]> {\n return this.post('/groups/get-user-groups', { user_id: userId });\n }\n async getGroupMembers(groupId: string): Promise<any[]> {\n return this.post('/groups/get-members', { group_id: groupId });\n }\n async getGroupPermissions(groupId: string): Promise<any[]> {\n return this.post('/groups/get-permissions', { group_id: groupId });\n }\n async setGroupPermissions(groupId: string, permissions: any[]): Promise<void> {\n await this.post('/groups/set-permissions', { group_id: groupId, permissions });\n }\n\n // ── Circles ──\n\n async createCircle(options: any): Promise<any> {\n return this.post('/circles/create', options);\n }\n async listCircles(): Promise<any[]> {\n return this.post('/circles/list', {});\n }\n async getCircle(circleId: string): Promise<any> {\n return this.post('/circles/get', { circle_id: circleId });\n }\n async updateCircle(circleId: string, options: any): Promise<any> {\n return this.post('/circles/update', { circle_id: circleId, ...options });\n }\n async deleteCircle(circleId: string): Promise<void> {\n await this.post('/circles/delete', { circle_id: circleId });\n }\n async addCircleMember(circleId: string, options: any): Promise<void> {\n await this.post('/circles/add-member', { circle_id: circleId, ...options });\n }\n async removeCircleMember(circleId: string, userId: string): Promise<void> {\n await this.post('/circles/remove-member', { circle_id: circleId, user_id: userId });\n }\n async getCircleMembers(circleId: string): Promise<any[]> {\n return this.post('/circles/get-members', { circle_id: circleId });\n }\n async getUserCircles(userId: string): Promise<any[]> {\n return this.post('/circles/get-user-circles', { user_id: userId });\n }\n\n // ── Resources ──\n\n async createResource(options: any): Promise<any> {\n return this.post('/resources/create', options);\n }\n async listResources(): Promise<any[]> {\n return this.post('/resources/list', {});\n }\n async updateResource(resourceId: string, options: any): Promise<any> {\n return this.post('/resources/update', { resource_id: resourceId, ...options });\n }\n async deleteResource(resourceId: string): Promise<void> {\n await this.post('/resources/delete', { resource_id: resourceId });\n }\n\n // ── Relation types ──\n\n async createRelationType(options: any): Promise<any> {\n return this.post('/relation-types/create', options);\n }\n async listRelationTypes(): Promise<any[]> {\n return this.post('/relation-types/list', {});\n }\n async updateRelationType(id: string, options: any): Promise<any> {\n return this.post('/relation-types/update', { id, ...options });\n }\n async deleteRelationType(id: string): Promise<void> {\n await this.post('/relation-types/delete', { id });\n }\n\n // ── Profile ──\n\n async getProfile(userId: string): Promise<Record<string, any>> {\n return this.post('/profile/get', { user_id: userId });\n }\n async setProfile(userId: string, data: Record<string, any>): Promise<void> {\n await this.post('/profile/set', { user_id: userId, data });\n }\n\n // ── Auth config ──\n\n async getAuthConfig(): Promise<any> {\n return this.post('/config/get', {});\n }\n async setAuthConfig(config: any): Promise<void> {\n await this.post('/config/set', config);\n }\n\n // ── Stewardship sub-namespace ──\n\n readonly stewardship = {\n resolve: (userId: string) => this.post('/stewardship/resolve', { user_id: userId }),\n createOverride: (options: any) =>\n this.post('/stewardship/create-override', options),\n revoke: async (id: string) => {\n await this.post('/stewardship/revoke', { id });\n },\n checkPermission: async (\n stewardId: string,\n wardId: string,\n resource: string,\n action: string,\n ): Promise<boolean> => {\n const r = await this.post('/stewardship/check-permission', {\n steward_id: stewardId,\n ward_id: wardId,\n resource,\n action,\n });\n return Boolean((r as any)?.allowed);\n },\n createActAs: (stewardId: string, wardId: string) =>\n this.post('/stewardship/create-act-as', { steward_id: stewardId, ward_id: wardId }),\n listAudit: (\n userId: string,\n options: { limit?: number; offset?: number } = {},\n ) =>\n this.post('/stewardship/list-audit', {\n user_id: userId,\n limit: options.limit ?? 50,\n offset: options.offset ?? 0,\n }),\n };\n\n withAuth<T extends (request: Request & { user: AuthUser }) => Promise<Response>>(\n handler: T\n ): (request: Request) => Promise<Response> {\n const self = this;\n return async function(request: Request): Promise<Response> {\n let token: string | null = null;\n const authHeader = request.headers.get('Authorization');\n if (authHeader?.startsWith('Bearer ')) {\n token = authHeader.slice(7);\n } else {\n const cookies = request.headers.get('Cookie') ?? '';\n const match = cookies.match(/__session=([^;]+)/);\n if (match) token = match[1];\n }\n if (!token) {\n return new Response(JSON.stringify({ error: 'Authentication required' }), {\n status: 401, headers: { 'Content-Type': 'application/json' },\n });\n }\n try {\n const user = await self.validate(token);\n (request as any).user = user;\n return handler(request as Request & { user: AuthUser });\n } catch {\n return new Response(JSON.stringify({ error: 'Invalid or expired token' }), {\n status: 401, headers: { 'Content-Type': 'application/json' },\n });\n }\n };\n }\n\n // ── Request-scoped identity + authorization ──\n //\n // In dev mode the SDK uses Node's AsyncLocalStorage (via\n // request-scope.ts) to track per-request state — tenants must wrap\n // their inbound request handler with `runWithRequest(...)`. Without\n // that wrapper, set/get/can fall back to clear errors / anonymous\n // results so the misuse is obvious rather than silent.\n\n async setCurrentUser(token: string | null): Promise<void> {\n const { getCurrentRequestStore } = await import('./request-scope.js');\n const store = getCurrentRequestStore();\n if (!store) {\n // No active request scope (e.g. background task / one-shot\n // script / test that didn't wrap). Silent no-op matches the\n // runtime's op_auth_set_current_user behaviour when\n // REQUEST_CTX isn't set\n // (crates/runtime/src/ops/platform/ops_authz.rs:90-114).\n // The Maravilla Vite plugin auto-opens a scope for every dev\n // HTTP request, so SvelteKit/RR hook code reaches this branch\n // only outside the request lifecycle.\n return;\n }\n if (!token) {\n store.token = undefined;\n store.user = undefined;\n return;\n }\n store.token = token;\n store.user = await this.validate(token);\n }\n\n getCurrentUser(): AuthCaller {\n // Synchronous read: ALS module is already loaded by the time\n // setCurrentUser ran, OR we just return anonymous.\n // Use require-style import via a cached reference to keep this sync.\n const mod = (RemoteAuthService as any)._requestScope as\n | typeof import('./request-scope.js')\n | undefined;\n const store = mod?.getCurrentRequestStore?.();\n const user = store?.user;\n if (!user) {\n return mod?.anonymousCaller?.() ?? {\n user_id: '',\n email: '',\n is_admin: false,\n roles: [],\n is_anonymous: true,\n };\n }\n return {\n user_id: user.id,\n email: user.email,\n is_admin: false,\n roles: user.groups ?? [],\n is_anonymous: false,\n };\n }\n\n async can(\n action: string,\n resourceId: string,\n node?: Record<string, unknown> | null,\n ): Promise<boolean> {\n const { getCurrentRequestStore } = await import('./request-scope.js');\n const store = getCurrentRequestStore();\n const token = store?.token;\n if (!token) {\n // No bound user → fail-closed, like the runtime evaluator.\n return false;\n }\n const r = await this.post('/can', {\n token,\n action,\n resource_id: resourceId,\n node: node ?? null,\n });\n return Boolean((r as any)?.allowed);\n }\n}\n\n// Cache the request-scope module on the class so getCurrentUser can read\n// it synchronously (required by the AuthService interface — getCurrentUser\n// is sync). Lazy-load on first setCurrentUser/can call (which is async).\nimport('./request-scope.js')\n .then((mod) => {\n (RemoteAuthService as any)._requestScope = mod;\n })\n .catch(() => {\n // Non-Node environment — getCurrentUser will return anonymous.\n });\n\n/**\n * Remote stub for the per-request Layer 2 policy toggle. The toggle lives in\n * per-request state inside the runtime and has no remote equivalent.\n */\nclass RemotePolicyService implements PolicyService {\n setEnabled(_enabled: boolean): void {\n throw new Error(\n 'platform.policy.setEnabled is only available inside the Maravilla runtime.'\n );\n }\n\n isEnabled(): boolean {\n throw new Error(\n 'platform.policy.isEnabled is only available inside the Maravilla runtime.'\n );\n }\n}\n\n/**\n * Remote Workflows service — HTTP adaptor over the dev-server's\n * `/api/workflows/*` routes. The runtime (isolate) path uses `Deno.core.ops`\n * instead; both produce handles with the same shape.\n *\n * @internal\n */\nclass RemoteWorkflows implements Workflows {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>,\n ) {}\n\n private async request(path: string, options: RequestInit = {}): Promise<Response> {\n const response = await fetch(`${this.baseUrl}${path}`, {\n ...options,\n headers: { ...this.headers, ...getRequestAuthHeader(), ...options.headers },\n });\n if (!response.ok && response.status !== 404) {\n const error = await response.text();\n throw new Error(`Platform API error: ${response.status} - ${error}`);\n }\n return response;\n }\n\n async start(workflowId: string, input: unknown = {}): Promise<WorkflowHandle> {\n if (typeof workflowId !== 'string' || !workflowId) {\n throw new Error('workflows.start: workflowId must be a non-empty string');\n }\n const res = await this.request(\n `/api/workflows/${encodeURIComponent(workflowId)}/start`,\n { method: 'POST', body: JSON.stringify(input ?? {}) },\n );\n const { runId } = (await res.json()) as { runId: string };\n return makeRemoteWorkflowHandle(this.baseUrl, this.headers, runId);\n }\n\n handle(runId: string): WorkflowHandle {\n if (typeof runId !== 'string' || !runId) {\n throw new Error('workflows.handle: runId must be a non-empty string');\n }\n return makeRemoteWorkflowHandle(this.baseUrl, this.headers, runId);\n }\n\n async sendEvent(eventType: string, payload: unknown = null): Promise<number> {\n if (typeof eventType !== 'string' || !eventType) {\n throw new Error('workflows.sendEvent: eventType must be a non-empty string');\n }\n const res = await this.request(`/api/workflows/signal`, {\n method: 'POST',\n body: JSON.stringify({ eventType, payload }),\n });\n const data = (await res.json()) as { count: number };\n return data.count;\n }\n}\n\nfunction makeRemoteWorkflowHandle(\n baseUrl: string,\n headers: Record<string, string>,\n runId: string,\n): WorkflowHandle {\n const doFetch = async (path: string, init: RequestInit = {}): Promise<Response> => {\n const res = await fetch(`${baseUrl}${path}`, {\n ...init,\n headers: { ...headers, ...init.headers },\n });\n if (!res.ok && res.status !== 404) {\n throw new Error(`Platform API error: ${res.status} - ${await res.text()}`);\n }\n return res;\n };\n\n const handle: WorkflowHandle = {\n runId,\n async status(): Promise<WorkflowRun | null> {\n const res = await doFetch(`/api/workflows/runs/${encodeURIComponent(runId)}`);\n if (res.status === 404) return null;\n return (await res.json()) as WorkflowRun;\n },\n async history(): Promise<WorkflowStepRecord[]> {\n const res = await doFetch(\n `/api/workflows/runs/${encodeURIComponent(runId)}/history`,\n );\n return (await res.json()) as WorkflowStepRecord[];\n },\n async cancel(): Promise<boolean> {\n const res = await doFetch(\n `/api/workflows/runs/${encodeURIComponent(runId)}/cancel`,\n { method: 'POST' },\n );\n const data = (await res.json()) as { cancelled: boolean };\n return data.cancelled;\n },\n async result(options?: { timeoutMs?: number }): Promise<unknown> {\n const timeoutMs = options?.timeoutMs;\n const deadline =\n typeof timeoutMs === 'number' && Number.isFinite(timeoutMs) && timeoutMs > 0\n ? Date.now() + timeoutMs\n : null;\n let delay = 100;\n while (true) {\n const run = await handle.status();\n if (!run) throw new Error(`workflow run not found: ${runId}`);\n if (run.status === 'completed') return run.output;\n if (run.status === 'failed' || run.status === 'cancelled') {\n const err = new Error(`workflow ${run.status}`) as Error & { run: WorkflowRun };\n err.run = run;\n throw err;\n }\n if (deadline !== null && Date.now() >= deadline) {\n throw new Error('workflow result timeout');\n }\n await new Promise((r) => setTimeout(r, delay));\n delay = Math.min(delay * 2, 5000);\n }\n },\n };\n return handle;\n}\n\n/**\n * Create a remote platform client for development environments.\n * \n * This function creates a platform instance that communicates with a development\n * server over HTTP. It's used internally by getPlatform() when running in development\n * mode and no native platform is available.\n * \n * @param baseUrl - The base URL of the development server\n * @param tenant - The tenant identifier for multi-tenancy support\n * @returns A platform instance that proxies requests to the development server\n * \n * @internal\n * \n * @example\n * ```typescript\n * // This is typically called internally by getPlatform()\n * const platform = createRemoteClient('http://localhost:3001', 'dev-tenant');\n * \n * // The returned platform works the same as the native one\n * await platform.env.KV.cache.put('key', 'value');\n * await platform.env.DB.insertOne('users', { name: 'John' });\n * await platform.env.STORAGE.put('file.pdf', pdfData);\n * ```\n */\nexport function createRemoteClient(baseUrl: string, tenant: string) {\n const headers = {\n 'Content-Type': 'application/json',\n 'X-Tenant-Id': tenant,\n };\n\n // Create KV namespaces proxy that dynamically creates namespace instances\n const kvProxy = new Proxy({} as Record<string, KvNamespace>, {\n get(_, namespace: string) {\n return new RemoteKvNamespace(baseUrl, namespace, headers);\n }\n });\n\n const db = new RemoteDatabase(baseUrl, headers);\n const storage = new RemoteStorage(baseUrl, headers);\n const media = new RemoteMediaService(baseUrl, headers);\n const realtime = new RemoteRealtimeService(baseUrl, headers);\n const auth = new RemoteAuthService(baseUrl, headers);\n const policy = new RemotePolicyService();\n const workflows = new RemoteWorkflows(baseUrl, headers);\n\n return {\n env: {\n KV: kvProxy,\n DB: db,\n STORAGE: storage,\n },\n media,\n realtime,\n auth,\n policy,\n workflows,\n };\n}","// REN (Resource Event Notifications) client utilities\n// Thin SSE client for /api/maravilla/ren\n// Reconnect w/ basic backoff; consumer filters self vs others using evt.src\n\nexport interface RenEvent {\n t: string; // event type e.g. storage.object.created, realtime.message, presence.join\n r: string; // resource domain e.g. storage, runtime, realtime, presence\n k?: string; // key (object key, deployment key, etc.)\n v?: string; // version / etag\n ts?: number; // timestamp (ms)\n src?: string;// origin client id (if set on mutation request)\n ns?: string; // future namespace / tenant\n ch?: string; // channel name (for realtime pub/sub)\n data?: any; // arbitrary payload (for realtime messages)\n uid?: string;// user identity (for presence)\n [extra: string]: any;\n}\n\nexport interface RenClientOptions {\n endpoint?: string; // override (default /api/maravilla/ren)\n subscriptions?: string[]; // resource filters, ['*'] means all\n clientId?: string; // supply existing client id\n autoReconnect?: boolean; // default true\n maxBackoffMs?: number; // default 15000\n debug?: boolean; // enable console debug logging\n}\n\ntype Listener = (event: RenEvent) => void;\n\nexport class RenClient {\n private endpoint: string;\n private subs: string[];\n private clientId: string;\n private listeners = new Set<Listener>();\n private es: EventSource | null = null;\n private closed = false;\n private attempt = 0;\n private autoReconnect: boolean;\n private maxBackoff: number;\n private debug: boolean;\n\n constructor(opts: RenClientOptions = {}) {\n this.endpoint = opts.endpoint || this.detectEndpoint();\n this.subs = (opts.subscriptions && opts.subscriptions.length) ? opts.subscriptions : ['*'];\n this.clientId = opts.clientId || getOrCreateClientId();\n this.autoReconnect = opts.autoReconnect !== false;\n this.maxBackoff = opts.maxBackoffMs ?? 15000;\n this.debug = !!opts.debug || (typeof localStorage !== 'undefined' && localStorage.getItem('REN_DEBUG') === '1');\n this.connect();\n }\n\n private detectEndpoint(): string {\n // Port check FIRST — catches any dev server (Vite, SvelteKit, etc.)\n // regardless of whether globalThis.platform was set by getPlatform().\n //\n // This is the **fallback path** for projects that haven't wired\n // `@maravilla-labs/vite-plugin` into their Vite config. With the plugin,\n // `/api/*` is proxied from the framework dev port to :3001, so\n // `window.location.port === '5173'` (or wherever) but the relative\n // `/api/maravilla/ren` URL works without rewriting. Without the plugin,\n // we keep this absolute-URL rewrite so existing setups don't break.\n if (typeof window !== 'undefined') {\n const port = window.location.port;\n if (port && port !== '3001' && port !== '80' && port !== '443' && port !== '') {\n return `http://${window.location.hostname}:3001/api/maravilla/ren`;\n }\n }\n\n // Production runtime (native Deno platform) — use relative URL\n if (typeof globalThis !== 'undefined' && (globalThis as any).platform) {\n return '/api/maravilla/ren';\n }\n\n // Default to relative URL (works in preview mode and production)\n console.log('[REN detectEndpoint] Using default relative endpoint (preview/production mode)');\n return '/api/maravilla/ren';\n }\n\n private log(...args: any[]) { if (this.debug) console.debug('[RenClient]', ...args); }\n\n private buildUrl(): string {\n const s = (this.subs.length === 1 && this.subs[0] === '*') ? '*' : this.subs.join(',');\n const qs = new URLSearchParams({ cid: this.clientId, s });\n return `${this.endpoint}?${qs.toString()}`;\n }\n\n private connect() {\n const url = this.buildUrl();\n this.log('connecting', { url });\n this.es = new EventSource(url);\n this.closed = false;\n\n const forward = (e: MessageEvent) => {\n try {\n const evt: RenEvent = JSON.parse(e.data);\n this.log('event', evt);\n this.listeners.forEach(l => l(evt));\n } catch (err) {\n this.log('malformed event data', e.data, err);\n }\n };\n\n // Attach generic message handler for events without a specific event: type\n this.es.onmessage = forward;\n\n // Register listeners for all known event types\n // The browser EventSource API does NOT call onmessage for events with an event: field\n // We must explicitly register listeners for each event type we want to handle\n const knownEventTypes = [\n // Database events\n 'db.document.created',\n 'db.document.updated',\n 'db.document.deleted',\n // KV events\n 'kv.put',\n 'kv.delete',\n 'kv.expired',\n // Storage events\n 'storage.object.created',\n 'storage.object.updated',\n 'storage.object.deleted',\n // Runtime events\n 'runtime.snapshot.ready',\n 'runtime.worker.started',\n 'runtime.worker.stopped',\n // Realtime channel events\n 'realtime.message',\n // Presence events\n 'presence.join',\n 'presence.leave',\n 'presence.update',\n // Media transform lifecycle (emitted by media-transforms-worker)\n 'transform.queued',\n 'transform.started',\n 'transform.progress',\n 'transform.complete',\n 'transform.failed',\n // Meta events\n 'ren.meta'\n ];\n // Use the more general addEventListener signature to avoid TypeScript issues\n knownEventTypes.forEach(k => this.es?.addEventListener(k, forward as EventListener));\n\n this.es.onerror = (ev) => {\n this.log('error', ev);\n if (this.closed) return;\n this.es?.close();\n if (!this.autoReconnect) return;\n const delay = Math.min(1000 * Math.pow(2, this.attempt++), this.maxBackoff);\n this.log('reconnecting in', delay, 'ms');\n setTimeout(() => this.connect(), delay);\n };\n\n this.es.onopen = () => { this.attempt = 0; this.log('open'); };\n }\n\n on(listener: Listener): () => void {\n this.listeners.add(listener);\n this.log('listener added; total', this.listeners.size);\n return () => { this.listeners.delete(listener); this.log('listener removed; total', this.listeners.size); };\n }\n\n getClientId() { return this.clientId; }\n\n close() {\n this.closed = true;\n this.es?.close();\n this.log('closed');\n }\n}\n\nexport function getOrCreateClientId(storage?: Storage): string {\n if (!storage) {\n storage = (typeof window !== 'undefined' && window.localStorage) ? window.localStorage : (typeof globalThis !== 'undefined' && (globalThis as any).localStorage) ? (globalThis as any).localStorage : undefined as any;\n if (!storage) {\n // Return a random ID if no storage is available\n return (globalThis.crypto?.randomUUID?.() || randomFallback());\n }\n }\n const key = 'maravillaClientId';\n let id = storage.getItem(key);\n if (!id) {\n id = (globalThis.crypto?.randomUUID?.() || randomFallback());\n try { storage.setItem(key, id); } catch {} // ignore quota errors\n }\n return id;\n}\n\nfunction randomFallback(): string {\n // Very small UUID-ish fallback\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n// Helper to add client header to fetch\nexport async function renFetch(input: string | URL | Request, init: RequestInit = {}, clientId?: string) {\n const cid = clientId || getOrCreateClientId();\n const headers = new Headers(init.headers || {});\n headers.set('X-Ren-Client', cid);\n return fetch(input, { ...init, headers });\n}\n\n// Storage convenience wrappers (example)\nexport async function storageUpload(path: string, file: Blob | File, clientId?: string) {\n const res = await renFetch(`/api/storage/upload?path=${encodeURIComponent(path)}`, { method: 'POST', body: file }, clientId);\n if (!res.ok) throw new Error('upload failed');\n return res.json().catch(() => ({}));\n}\n\nexport async function storageDelete(path: string, clientId?: string) {\n const res = await renFetch(`/api/storage/delete?path=${encodeURIComponent(path)}`, { method: 'DELETE' }, clientId);\n if (!res.ok) throw new Error('delete failed');\n return res.json().catch(() => ({}));\n}\n","// Maravilla Realtime Client\n// Extends REN with channels, pub/sub, and presence support\n// Uses WebSocket for bidirectional communication, SSE as fallback\n\nimport { getOrCreateClientId } from './ren.js';\n\nexport interface RealtimeEvent {\n event: string;\n channel: string;\n data?: any;\n from?: string;\n userId?: string;\n ts?: number;\n metadata?: any;\n}\n\nexport interface PresenceMember {\n userId: string;\n metadata?: any;\n lastSeen?: number;\n}\n\nexport interface RealtimeClientOptions {\n /** WebSocket endpoint (default: auto-detect) */\n wsEndpoint?: string;\n /** Client ID (persistent across sessions) */\n clientId?: string;\n /** Auto-reconnect on disconnect (default: true) */\n autoReconnect?: boolean;\n /** Max reconnect backoff in ms (default: 15000) */\n maxBackoffMs?: number;\n /** Enable debug logging (default: false) */\n debug?: boolean;\n}\n\ntype EventCallback = (event: RealtimeEvent) => void;\ntype Unsubscribe = () => void;\n\nexport class RealtimeClient {\n private wsEndpoint: string;\n private clientId: string;\n private ws: WebSocket | null = null;\n private closed = false;\n private attempt = 0;\n private autoReconnect: boolean;\n private maxBackoff: number;\n private debug: boolean;\n\n private channelListeners = new Map<string, Set<EventCallback>>();\n private globalListeners = new Set<EventCallback>();\n private presenceListeners = new Map<string, {\n onJoin: Set<(member: PresenceMember) => void>;\n onLeave: Set<(member: PresenceMember) => void>;\n onUpdate: Set<(member: PresenceMember) => void>;\n }>();\n private subscribedChannels = new Set<string>();\n private pendingMessages: string[] = [];\n private pingInterval: ReturnType<typeof setInterval> | null = null;\n private joinedPresence = new Map<string, { userId: string; metadata?: any }>();\n\n constructor(opts: RealtimeClientOptions = {}) {\n this.wsEndpoint = opts.wsEndpoint || this.detectEndpoint();\n this.clientId = opts.clientId || getOrCreateClientId();\n this.autoReconnect = opts.autoReconnect !== false;\n this.maxBackoff = opts.maxBackoffMs ?? 15000;\n this.debug = !!opts.debug;\n }\n\n private detectEndpoint(): string {\n if (typeof window !== 'undefined') {\n const port = window.location.port;\n const proto = window.location.protocol === 'https:' ? 'wss:' : 'ws:';\n // Development mode: any non-standard port that isn't the dev server (3001)\n // Vite uses 5173+ but can pick any available port\n if (port && port !== '3001' && port !== '80' && port !== '443') {\n return `ws://${window.location.hostname}:3001/_rt/ws`;\n }\n return `${proto}//${window.location.host}/_rt/ws`;\n }\n return 'ws://localhost:3001/_rt/ws';\n }\n\n private log(...args: any[]) {\n if (this.debug) console.debug('[RealtimeClient]', ...args);\n }\n\n /** Connect to the realtime WebSocket server */\n connect(): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) return;\n\n const url = `${this.wsEndpoint}?cid=${encodeURIComponent(this.clientId)}`;\n this.log('connecting', url);\n this.closed = false;\n\n try {\n this.ws = new WebSocket(url);\n } catch (e) {\n this.log('WebSocket constructor failed', e);\n this.scheduleReconnect();\n return;\n }\n\n this.ws.onopen = () => {\n this.attempt = 0;\n this.log('connected');\n\n // Re-subscribe to channels\n for (const ch of this.subscribedChannels) {\n this.sendRaw({ action: 'subscribe', channel: ch });\n }\n\n // Re-join presence channels (reconnect after drop)\n for (const [channel, info] of this.joinedPresence) {\n this.sendRaw({ action: 'presence:join', channel, userId: info.userId, metadata: info.metadata });\n }\n\n // Flush pending messages\n for (const msg of this.pendingMessages) {\n this.ws?.send(msg);\n }\n this.pendingMessages = [];\n\n // Start auto-ping to keep connection alive (25s interval)\n this.stopPing();\n this.pingInterval = setInterval(() => this.sendRaw({ action: 'ping' }), 25000);\n };\n\n this.ws.onmessage = (ev) => {\n try {\n const event: RealtimeEvent = JSON.parse(ev.data);\n this.log('received', event);\n this.dispatch(event);\n } catch (e) {\n this.log('malformed message', ev.data, e);\n }\n };\n\n this.ws.onerror = (ev) => {\n this.log('error', ev);\n };\n\n this.ws.onclose = () => {\n this.log('disconnected');\n this.ws = null;\n this.stopPing();\n if (!this.closed && this.autoReconnect) {\n this.scheduleReconnect();\n }\n };\n }\n\n private stopPing() {\n if (this.pingInterval) { clearInterval(this.pingInterval); this.pingInterval = null; }\n }\n\n private scheduleReconnect() {\n const delay = Math.min(1000 * Math.pow(2, this.attempt++), this.maxBackoff);\n this.log('reconnecting in', delay, 'ms');\n setTimeout(() => this.connect(), delay);\n }\n\n private sendRaw(msg: Record<string, any>) {\n const json = JSON.stringify(msg);\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(json);\n } else {\n this.pendingMessages.push(json);\n }\n }\n\n private dispatch(event: RealtimeEvent) {\n // Notify global listeners\n this.globalListeners.forEach(cb => cb(event));\n\n // Notify channel-specific listeners\n if (event.channel) {\n const listeners = this.channelListeners.get(event.channel);\n if (listeners) {\n listeners.forEach(cb => cb(event));\n }\n }\n\n // Handle presence events\n if (event.event === 'presence:join' || event.event === 'presence:leave' || event.event === 'presence:update') {\n const presenceSet = this.presenceListeners.get(event.channel);\n if (presenceSet) {\n const member: PresenceMember = {\n userId: event.userId || '',\n metadata: event.metadata,\n lastSeen: event.ts,\n };\n if (event.event === 'presence:join') {\n presenceSet.onJoin.forEach(cb => cb(member));\n } else if (event.event === 'presence:update') {\n presenceSet.onUpdate.forEach(cb => cb(member));\n } else {\n presenceSet.onLeave.forEach(cb => cb(member));\n }\n }\n }\n }\n\n /** Subscribe to messages on a channel */\n subscribe(channel: string, callback: EventCallback, options?: { token?: string }): Unsubscribe {\n if (!this.channelListeners.has(channel)) {\n this.channelListeners.set(channel, new Set());\n }\n this.channelListeners.get(channel)!.add(callback);\n\n // Send subscribe message if not already subscribed\n if (!this.subscribedChannels.has(channel)) {\n this.subscribedChannels.add(channel);\n const msg: Record<string, any> = { action: 'subscribe', channel };\n if (options?.token) {\n msg.token = options.token;\n }\n this.sendRaw(msg);\n }\n\n return () => {\n const listeners = this.channelListeners.get(channel);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.channelListeners.delete(channel);\n this.subscribedChannels.delete(channel);\n this.sendRaw({ action: 'unsubscribe', channel });\n }\n }\n };\n }\n\n /** Listen to all events across all channels */\n onAny(callback: EventCallback): Unsubscribe {\n this.globalListeners.add(callback);\n return () => { this.globalListeners.delete(callback); };\n }\n\n /** Publish a message to a channel */\n publish(channel: string, data: any, options?: { userId?: string }): void {\n this.sendRaw({\n action: 'publish',\n channel,\n data,\n userId: options?.userId,\n });\n }\n\n /** Get a presence handle for a channel */\n presence(channel: string) {\n if (!this.presenceListeners.has(channel)) {\n this.presenceListeners.set(channel, {\n onJoin: new Set(),\n onLeave: new Set(),\n onUpdate: new Set(),\n });\n }\n const listeners = this.presenceListeners.get(channel)!;\n\n return {\n /** Join the channel with presence (auto-rejoins on reconnect) */\n join: (userId: string, metadata?: any): void => {\n this.joinedPresence.set(channel, { userId, metadata });\n this.sendRaw({\n action: 'presence:join',\n channel,\n userId,\n metadata,\n });\n },\n\n /** Update metadata for the current presence (must have joined first) */\n update: (metadata?: any): void => {\n const info = this.joinedPresence.get(channel);\n if (!info) return;\n info.metadata = metadata;\n this.sendRaw({\n action: 'presence:update',\n channel,\n userId: info.userId,\n metadata,\n });\n },\n\n /** Leave the channel */\n leave: (): void => {\n this.joinedPresence.delete(channel);\n this.sendRaw({ action: 'presence:leave', channel });\n },\n\n /** Listen for users joining */\n onJoin: (callback: (member: PresenceMember) => void): Unsubscribe => {\n listeners.onJoin.add(callback);\n return () => { listeners.onJoin.delete(callback); };\n },\n\n /** Listen for metadata updates */\n onUpdate: (callback: (member: PresenceMember) => void): Unsubscribe => {\n listeners.onUpdate.add(callback);\n return () => { listeners.onUpdate.delete(callback); };\n },\n\n /** Listen for users leaving */\n onLeave: (callback: (member: PresenceMember) => void): Unsubscribe => {\n listeners.onLeave.add(callback);\n return () => { listeners.onLeave.delete(callback); };\n },\n };\n }\n\n /** Get current client ID */\n getClientId(): string {\n return this.clientId;\n }\n\n /** Check if connected */\n isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n /** Disconnect and stop reconnecting */\n disconnect(): void {\n this.closed = true;\n this.stopPing();\n // Send leave for all joined presence channels before closing\n for (const [channel] of this.joinedPresence) {\n this.sendRaw({ action: 'presence:leave', channel });\n }\n this.joinedPresence.clear();\n this.ws?.close();\n this.ws = null;\n this.pendingMessages = [];\n this.log('disconnected (manual)');\n }\n}\n","// MediaRoom — SFU-agnostic browser client for video/audio rooms\n// Wraps livekit-client internally. If the SFU is swapped, only this file changes.\n\nimport {\n Room,\n RoomEvent,\n type RemoteParticipant,\n type RemoteTrackPublication,\n type RemoteTrack,\n type LocalParticipant as LKLocalParticipant,\n type Participant as LKParticipant,\n type TrackPublication,\n Track,\n ConnectionState,\n type DisconnectReason,\n type RoomConnectOptions,\n} from 'livekit-client';\n\n// ─── Events ───\n\nexport enum MediaRoomEvent {\n Connected = 'connected',\n Reconnecting = 'reconnecting',\n Reconnected = 'reconnected',\n Disconnected = 'disconnected',\n ParticipantJoined = 'participantJoined',\n ParticipantLeft = 'participantLeft',\n TrackSubscribed = 'trackSubscribed',\n TrackUnsubscribed = 'trackUnsubscribed',\n TrackMuted = 'trackMuted',\n TrackUnmuted = 'trackUnmuted',\n ActiveSpeakersChanged = 'activeSpeakersChanged',\n DataReceived = 'dataReceived',\n RecordingStatusChanged = 'recordingStatusChanged',\n MediaDevicesChanged = 'mediaDevicesChanged',\n}\n\n// ─── Types ───\n\nexport type TrackSource = 'camera' | 'microphone' | 'screen_share' | 'screen_share_audio';\nexport type TrackKind = 'audio' | 'video';\n\nexport interface MediaTrackPublication {\n trackSid: string;\n source: TrackSource;\n kind: TrackKind;\n muted: boolean;\n track?: MediaStreamTrack;\n}\n\nexport interface MediaParticipant {\n identity: string;\n name?: string;\n metadata?: string;\n isSpeaking: boolean;\n audioLevel: number;\n tracks: MediaTrackPublication[];\n}\n\nexport interface VideoResolution {\n width: number;\n height: number;\n frameRate?: number;\n}\n\nexport interface MediaRoomOptions {\n autoSubscribe?: boolean;\n adaptiveStream?: boolean;\n dynacast?: boolean;\n}\n\n// ─── Helpers ───\n\nfunction mapSource(source: Track.Source): TrackSource {\n switch (source) {\n case Track.Source.Camera: return 'camera';\n case Track.Source.Microphone: return 'microphone';\n case Track.Source.ScreenShare: return 'screen_share';\n case Track.Source.ScreenShareAudio: return 'screen_share_audio';\n default: return 'camera';\n }\n}\n\nfunction mapParticipant(p: LKParticipant): MediaParticipant {\n const tracks: MediaTrackPublication[] = [];\n p.trackPublications.forEach((pub: TrackPublication) => {\n tracks.push({\n trackSid: pub.trackSid,\n source: mapSource(pub.source),\n kind: pub.kind === Track.Kind.Video ? 'video' : 'audio',\n muted: pub.isMuted,\n track: pub.track?.mediaStreamTrack,\n });\n });\n return {\n identity: p.identity,\n name: p.name,\n metadata: p.metadata,\n isSpeaking: p.isSpeaking,\n audioLevel: p.audioLevel,\n tracks,\n };\n}\n\n/** Attach a media track to a video or audio element */\nexport function attachTrack(track: MediaStreamTrack, element: HTMLVideoElement | HTMLAudioElement): void {\n if (!track || !element) return;\n const stream = new MediaStream([track]);\n element.srcObject = stream;\n if (element instanceof HTMLVideoElement) {\n element.playsInline = true;\n }\n element.play().catch(() => {}); // autoplay may be blocked\n}\n\n/** Detach media from an element */\nexport function detachTrack(element: HTMLVideoElement | HTMLAudioElement): void {\n if (!element) return;\n element.srcObject = null;\n}\n\n// ─── MediaLocalParticipant ───\n\nexport class MediaLocalParticipant implements MediaParticipant {\n private lp: LKLocalParticipant;\n\n /** @internal */\n constructor(lp: LKLocalParticipant) { this.lp = lp; }\n\n get identity() { return this.lp.identity; }\n get name() { return this.lp.name; }\n get metadata() { return this.lp.metadata; }\n get isSpeaking() { return this.lp.isSpeaking; }\n get audioLevel() { return this.lp.audioLevel; }\n\n get tracks(): MediaTrackPublication[] {\n return mapParticipant(this.lp).tracks;\n }\n\n // Camera\n get isCameraEnabled(): boolean {\n return !!this.lp.getTrackPublication(Track.Source.Camera)?.track && !this.lp.getTrackPublication(Track.Source.Camera)?.isMuted;\n }\n async enableCamera(options?: { deviceId?: string; resolution?: VideoResolution }): Promise<void> {\n await this.lp.setCameraEnabled(true, {\n deviceId: options?.deviceId,\n resolution: options?.resolution ? { width: options.resolution.width, height: options.resolution.height, frameRate: options.resolution.frameRate } : undefined,\n });\n }\n async disableCamera(): Promise<void> {\n await this.lp.setCameraEnabled(false);\n }\n\n // Microphone\n get isMicrophoneEnabled(): boolean {\n return !!this.lp.getTrackPublication(Track.Source.Microphone)?.track && !this.lp.getTrackPublication(Track.Source.Microphone)?.isMuted;\n }\n async enableMicrophone(options?: { deviceId?: string }): Promise<void> {\n await this.lp.setMicrophoneEnabled(true, { deviceId: options?.deviceId });\n }\n async disableMicrophone(): Promise<void> {\n await this.lp.setMicrophoneEnabled(false);\n }\n\n // Screen share\n get isScreenShareEnabled(): boolean {\n return !!this.lp.getTrackPublication(Track.Source.ScreenShare)?.track;\n }\n async enableScreenShare(options?: { audio?: boolean }): Promise<void> {\n await this.lp.setScreenShareEnabled(true, { audio: options?.audio });\n }\n async disableScreenShare(): Promise<void> {\n await this.lp.setScreenShareEnabled(false);\n }\n\n // Metadata\n async setName(name: string): Promise<void> { await this.lp.setName(name); }\n async setMetadata(metadata: string): Promise<void> { await this.lp.setMetadata(metadata); }\n\n // Data\n async sendData(data: Uint8Array, options?: { reliable?: boolean }): Promise<void> {\n await this.lp.publishData(data, { reliable: options?.reliable ?? true });\n }\n}\n\n// ─── MediaRoom ───\n\ntype EventCallback = (...args: any[]) => void;\n\nexport class MediaRoom {\n private room: Room;\n private listeners = new Map<MediaRoomEvent, Set<EventCallback>>();\n private _localParticipant!: MediaLocalParticipant;\n\n constructor() {\n this.room = new Room();\n }\n\n async connect(url: string, token: string, options?: MediaRoomOptions): Promise<void> {\n const opts: RoomConnectOptions = {};\n if (options?.autoSubscribe !== undefined) opts.autoSubscribe = options.autoSubscribe;\n this.room.options.adaptiveStream = options?.adaptiveStream ?? true;\n this.room.options.dynacast = options?.dynacast ?? true;\n\n this.wireEvents();\n await this.room.connect(url, token, opts);\n this._localParticipant = new MediaLocalParticipant(this.room.localParticipant);\n }\n\n async disconnect(): Promise<void> {\n await this.room.disconnect();\n }\n\n get state(): 'disconnected' | 'connecting' | 'connected' | 'reconnecting' {\n switch (this.room.state) {\n case ConnectionState.Connected: return 'connected';\n case ConnectionState.Connecting: return 'connecting';\n case ConnectionState.Reconnecting: return 'reconnecting';\n default: return 'disconnected';\n }\n }\n\n get localParticipant(): MediaLocalParticipant { return this._localParticipant; }\n\n get participants(): Map<string, MediaParticipant> {\n const map = new Map<string, MediaParticipant>();\n this.room.remoteParticipants.forEach((p, id) => map.set(id, mapParticipant(p)));\n return map;\n }\n\n get activeSpeakers(): MediaParticipant[] {\n return this.room.activeSpeakers.map(mapParticipant);\n }\n\n get name(): string { return this.room.name; }\n get numParticipants(): number { return this.room.numParticipants; }\n get isRecording(): boolean { return this.room.isRecording; }\n\n // Events\n on(event: MediaRoomEvent, callback: EventCallback): this {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set());\n this.listeners.get(event)!.add(callback);\n return this;\n }\n\n off(event: MediaRoomEvent, callback: EventCallback): this {\n this.listeners.get(event)?.delete(callback);\n return this;\n }\n\n private emit(event: MediaRoomEvent, ...args: any[]) {\n this.listeners.get(event)?.forEach(cb => cb(...args));\n }\n\n // Device switching\n async switchCamera(deviceId: string): Promise<void> {\n await this.room.switchActiveDevice('videoinput', deviceId);\n }\n async switchMicrophone(deviceId: string): Promise<void> {\n await this.room.switchActiveDevice('audioinput', deviceId);\n }\n async switchSpeaker(deviceId: string): Promise<void> {\n await this.room.switchActiveDevice('audiooutput', deviceId);\n }\n\n // Static device enumeration\n static async getDevices(): Promise<MediaDeviceInfo[]> {\n return navigator.mediaDevices.enumerateDevices();\n }\n static async getCameras(): Promise<MediaDeviceInfo[]> {\n return (await MediaRoom.getDevices()).filter(d => d.kind === 'videoinput');\n }\n static async getMicrophones(): Promise<MediaDeviceInfo[]> {\n return (await MediaRoom.getDevices()).filter(d => d.kind === 'audioinput');\n }\n static async getSpeakers(): Promise<MediaDeviceInfo[]> {\n return (await MediaRoom.getDevices()).filter(d => d.kind === 'audiooutput');\n }\n\n // ─── Event wiring (LiveKit → MediaRoom) ───\n\n private wireEvents() {\n const r = this.room;\n r.on(RoomEvent.Connected, () => this.emit(MediaRoomEvent.Connected));\n r.on(RoomEvent.Reconnecting, () => this.emit(MediaRoomEvent.Reconnecting));\n r.on(RoomEvent.Reconnected, () => this.emit(MediaRoomEvent.Reconnected));\n r.on(RoomEvent.Disconnected, (reason?: DisconnectReason) => this.emit(MediaRoomEvent.Disconnected, reason));\n r.on(RoomEvent.MediaDevicesChanged, () => this.emit(MediaRoomEvent.MediaDevicesChanged));\n r.on(RoomEvent.RecordingStatusChanged, (recording: boolean) => this.emit(MediaRoomEvent.RecordingStatusChanged, recording));\n\n r.on(RoomEvent.ParticipantConnected, (p: RemoteParticipant) =>\n this.emit(MediaRoomEvent.ParticipantJoined, mapParticipant(p)));\n r.on(RoomEvent.ParticipantDisconnected, (p: RemoteParticipant) =>\n this.emit(MediaRoomEvent.ParticipantLeft, mapParticipant(p)));\n\n r.on(RoomEvent.TrackSubscribed, (track: RemoteTrack, pub: RemoteTrackPublication, p: RemoteParticipant) =>\n this.emit(MediaRoomEvent.TrackSubscribed, track.mediaStreamTrack, mapParticipant(p), mapSource(pub.source)));\n r.on(RoomEvent.TrackUnsubscribed, (track: RemoteTrack, pub: RemoteTrackPublication, p: RemoteParticipant) =>\n this.emit(MediaRoomEvent.TrackUnsubscribed, track.mediaStreamTrack, mapParticipant(p), mapSource(pub.source)));\n\n r.on(RoomEvent.TrackMuted, (pub: TrackPublication, p: LKParticipant) =>\n this.emit(MediaRoomEvent.TrackMuted, mapParticipant(p)));\n r.on(RoomEvent.TrackUnmuted, (pub: TrackPublication, p: LKParticipant) =>\n this.emit(MediaRoomEvent.TrackUnmuted, mapParticipant(p)));\n\n r.on(RoomEvent.ActiveSpeakersChanged, (speakers: LKParticipant[]) =>\n this.emit(MediaRoomEvent.ActiveSpeakersChanged, speakers.map(mapParticipant)));\n\n r.on(RoomEvent.DataReceived, (data: Uint8Array, p?: RemoteParticipant) =>\n this.emit(MediaRoomEvent.DataReceived, data, p ? mapParticipant(p) : undefined));\n }\n}\n","/**\n * @fileoverview Web Push client SDK for Maravilla tenants.\n *\n * Talks to the tenant-origin `/_rt/push` endpoints served by delivery:\n * - GET /vapid-public-key — fetch the VAPID public key for subscribe\n * - POST /subscribe — create a subscription\n * - POST /unsubscribe — delete a subscription by id (or endpoint)\n *\n * The matching service worker is served from `/_rt/push/sw.js` on the\n * same tenant origin (browsers require same-origin SW registration).\n */\n\nconst DEFAULT_BASE_PATH = '/_rt/push';\nconst DEFAULT_SW_PATH = '/_rt/push/sw.js';\nconst VISITOR_STORAGE_KEY = 'maravilla.push.visitorId';\nconst REGISTER_TIMEOUT_MS = 10_000;\n\nexport interface RegisterPushOptions {\n /** Free-form topic strings to tag this subscription with. */\n topics?: string[];\n /** Authenticated user id, if any. Takes precedence over visitorId. */\n userId?: string | null;\n /** Anonymous visitor id. If omitted and userId is also omitted, one\n * is generated and persisted to localStorage under `maravilla.push.visitorId`. */\n visitorId?: string | null;\n /** Override the sw.js path (defaults to `/_platform/push/sw.js`). */\n swPath?: string;\n /** Override the API base path (defaults to `/_platform/push`). */\n basePath?: string;\n}\n\nexport interface RegisterPushResult {\n /** The browser PushSubscription (see Web Push spec). */\n subscription: PushSubscription;\n /** Server-issued subscription id — pass this back to unregisterPush. */\n subscriptionId: string;\n}\n\ninterface VapidPublicKeyResponse {\n publicKey: string;\n contactEmail?: string;\n}\n\ninterface ServerSubscription {\n id: string;\n [key: string]: unknown;\n}\n\nfunction assertPushSupported(): void {\n if (typeof navigator === 'undefined' || !('serviceWorker' in navigator)) {\n throw new Error('Web Push is not supported: serviceWorker is unavailable');\n }\n if (typeof window === 'undefined' || !('PushManager' in window)) {\n throw new Error('Web Push is not supported: PushManager is unavailable');\n }\n}\n\nfunction base64UrlToArrayBuffer(input: string): ArrayBuffer {\n const padding = '='.repeat((4 - (input.length % 4)) % 4);\n const base64 = (input + padding).replace(/-/g, '+').replace(/_/g, '/');\n const raw = atob(base64);\n const buffer = new ArrayBuffer(raw.length);\n const view = new Uint8Array(buffer);\n for (let i = 0; i < raw.length; i++) {\n view[i] = raw.charCodeAt(i);\n }\n return buffer;\n}\n\nfunction arrayBufferToBase64Url(buffer: ArrayBuffer | null): string | undefined {\n if (!buffer) return undefined;\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction randomUuid(): string {\n const c = typeof crypto !== 'undefined' ? crypto : undefined;\n if (c && typeof c.randomUUID === 'function') {\n return c.randomUUID();\n }\n const bytes = new Uint8Array(16);\n if (c && typeof c.getRandomValues === 'function') {\n c.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nfunction resolveVisitorId(\n userId: string | null | undefined,\n visitorId: string | null | undefined,\n): string | null {\n if (visitorId) return visitorId;\n if (userId) return null;\n try {\n const stored = window.localStorage.getItem(VISITOR_STORAGE_KEY);\n if (stored) return stored;\n const fresh = randomUuid();\n window.localStorage.setItem(VISITOR_STORAGE_KEY, fresh);\n return fresh;\n } catch {\n return randomUuid();\n }\n}\n\nasync function fetchVapidPublicKey(basePath: string): Promise<string> {\n const res = await fetch(`${basePath}/vapid-public-key`, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { Accept: 'application/json' },\n });\n if (!res.ok) {\n throw new Error(`Failed to fetch VAPID public key: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as VapidPublicKeyResponse;\n if (!body || typeof body.publicKey !== 'string' || body.publicKey.length === 0) {\n throw new Error('VAPID public key response is missing `publicKey`');\n }\n return body.publicKey;\n}\n\nfunction extractKeys(sub: PushSubscription): { p256dh?: string; auth?: string } {\n return {\n p256dh: arrayBufferToBase64Url(sub.getKey('p256dh')),\n auth: arrayBufferToBase64Url(sub.getKey('auth')),\n };\n}\n\nexport async function registerPush(\n opts: RegisterPushOptions = {},\n): Promise<RegisterPushResult> {\n assertPushSupported();\n\n const basePath = opts.basePath ?? DEFAULT_BASE_PATH;\n const swPath = opts.swPath ?? DEFAULT_SW_PATH;\n const topics = opts.topics ?? [];\n const userId = opts.userId ?? null;\n const visitorId = resolveVisitorId(userId, opts.visitorId);\n\n // Whole-flow timeout. Without this, a stuck pushManager.subscribe() or a\n // misbehaving push service can leave the UI hanging forever.\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`registerPush timed out after ${REGISTER_TIMEOUT_MS}ms`)),\n REGISTER_TIMEOUT_MS,\n ),\n );\n\n const flow = (async (): Promise<RegisterPushResult> => {\n const publicKey = await fetchVapidPublicKey(basePath);\n // Register the SW. We deliberately do NOT `await navigator.serviceWorker.ready`\n // here — that promise only resolves when an active SW's scope covers the\n // current page, but our SW is scoped to `/_rt/push/` and the page is at\n // `/`. `pushManager.subscribe()` works against the registration returned\n // by `register()` without needing the SW to control the page.\n const registration = await navigator.serviceWorker.register(swPath);\n\n const existing = await registration.pushManager.getSubscription();\n const subscription =\n existing ??\n (await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: base64UrlToArrayBuffer(publicKey),\n }));\n\n const { p256dh, auth } = extractKeys(subscription);\n\n const res = await fetch(`${basePath}/subscribe`, {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'Content-Type': 'application/json', Accept: 'application/json' },\n body: JSON.stringify({\n provider: 'web-push',\n endpoint: subscription.endpoint,\n p256dh,\n auth,\n userId,\n visitorId,\n topics,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Subscribe failed: ${res.status} ${res.statusText}`);\n }\n\n const saved = (await res.json()) as ServerSubscription;\n if (!saved || typeof saved.id !== 'string' || saved.id.length === 0) {\n throw new Error('Subscribe response is missing `id`');\n }\n\n return { subscription, subscriptionId: saved.id };\n })();\n\n return Promise.race([flow, timeout]);\n}\n\nexport async function unregisterPush(\n subscriptionId: string,\n opts: { basePath?: string } = {},\n): Promise<void> {\n if (!subscriptionId) {\n throw new Error('subscriptionId is required');\n }\n const basePath = opts.basePath ?? DEFAULT_BASE_PATH;\n\n const res = await fetch(`${basePath}/unsubscribe`, {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ subscriptionId }),\n });\n\n if (!res.ok && res.status !== 404) {\n throw new Error(`Unsubscribe failed: ${res.status} ${res.statusText}`);\n }\n}\n\n/**\n * Compute a `Date` that is `offset` before `anchor` — handy for\n * \"X minutes/hours/days before the event\" scheduling.\n *\n * `offset` is a short duration string:\n * - `\"30s\"` — 30 seconds\n * - `\"15m\"` — 15 minutes\n * - `\"1h\"` — 1 hour\n * - `\"2d\"` — 2 days\n * - `\"1w\"` — 1 week\n *\n * Pure function — safe to call on the client. Works with `platform.push.schedule`:\n *\n * @example\n * ```typescript\n * import { offsetBefore } from '@maravilla-labs/platform';\n *\n * await platform.push.schedule(\n * { topic: `invite:${invite.id}` },\n * { title: invite.title, body: 'Your event is in one hour' },\n * {\n * at: offsetBefore(invite.event_date, '1h'),\n * key: `invite:${invite.id}:reminder-1h`,\n * }\n * );\n * ```\n *\n * @throws if `anchor` is an invalid date string or `offset` isn't a\n * recognised duration.\n */\nexport function offsetBefore(anchor: Date | string, offset: string): Date {\n const anchorDate = anchor instanceof Date ? anchor : new Date(anchor);\n if (Number.isNaN(anchorDate.getTime())) {\n throw new Error(`offsetBefore: invalid anchor \"${String(anchor)}\"`);\n }\n\n const match = /^(\\d+)\\s*(s|m|h|d|w)$/i.exec(offset.trim());\n if (!match) {\n throw new Error(\n `offsetBefore: invalid offset \"${offset}\" — expected something like \"30m\", \"1h\", \"2d\", \"1w\"`,\n );\n }\n\n const amount = Number(match[1]);\n const unit = match[2].toLowerCase();\n const UNIT_MS: Record<string, number> = {\n s: 1000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n };\n return new Date(anchorDate.getTime() - amount * UNIT_MS[unit]);\n}\n","/**\n * @fileoverview Media transforms — async ffmpeg / image / OCR jobs.\n *\n * Mirrors the Rust `platform.media.transforms` surface. All mutating\n * methods (transcode/thumbnail/resize/ocr) return a {@link JobHandle}\n * whose `outputKey` is content-addressed via {@link keyFor} and known\n * up front — clients can render placeholder UI for the derived asset\n * before the worker even starts the job.\n *\n * The runtime injects the live JS object as `platform.media.transforms`\n * (see `crates/runtime/src/ops/platform/js_bindings/platform_js.rs`).\n * The static helper {@link keyFor} is exported separately and runs\n * client-side — it must produce byte-for-byte identical output to the\n * Rust `derive_key`. The shared golden-vector fixture\n * `crates/platform/tests/derive_key_vectors.json` is consumed from both\n * the Rust integration test (`crates/platform/tests/derive_key_golden.rs`)\n * and the TS test (`packages/platform/tests/derive-key.test.ts`) to keep\n * the two in lockstep.\n */\n\n// Isomorphic SHA-256 via @noble/hashes — runs in Node, Deno, and every\n// browser without a bundler-specific shim. `node:crypto` would pull\n// Node built-ins into browser bundles and break Vite builds that\n// consume this package client-side.\nimport { sha256 } from '@noble/hashes/sha2';\n\n// ── Types — mirror `crates/platform/src/media/transforms/types.rs` ──────\n\n/** Video container targets supported by v1. */\nexport type VideoFormat = 'mp4' | 'webm';\n\n/** Image output formats supported by v1. */\nexport type ImageFormat = 'jpg' | 'png' | 'webp';\n\n/** Lifecycle state of a transform job. */\nexport type JobStatus = 'pending' | 'running' | 'complete' | 'failed';\n\n/** Options for `transforms.transcode`. */\nexport interface TranscodeOpts {\n format: VideoFormat;\n codec?: string;\n max_width?: number;\n max_height?: number;\n audio_codec?: string;\n bitrate_kbps?: number;\n}\n\n/** Options for `transforms.thumbnail` — extract a single video frame. */\nexport interface ThumbnailOpts {\n /** Offset into the source. Accepts `\"00:00:01\"`, `\"1s\"`, or a plain number-as-string. */\n at: string;\n width?: number;\n height?: number;\n /** Defaults to `\"jpg\"` server-side when omitted. */\n format?: ImageFormat;\n quality?: number;\n}\n\n/** Options for `transforms.resize`. */\nexport interface ResizeOpts {\n width?: number;\n height?: number;\n format: ImageFormat;\n quality?: number;\n strip_metadata?: boolean;\n}\n\n/** Options for `transforms.ocr`. */\nexport interface OcrOpts {\n /** Tesseract language code(s). Defaults to `\"eng\"` server-side when omitted. */\n lang?: string;\n}\n\n/** Tagged union of all transform requests — matches the Rust `TransformSpec`. */\nexport type TransformSpec =\n | ({ kind: 'transcode' } & TranscodeOpts)\n | ({ kind: 'thumbnail' } & ThumbnailOpts)\n | ({ kind: 'resize' } & ResizeOpts)\n | ({ kind: 'ocr' } & OcrOpts);\n\n/** Probe output. All fields optional — ffprobe doesn't fill every one for every input. */\nexport interface MediaInfo {\n duration_secs?: number;\n width?: number;\n height?: number;\n video_codec?: string;\n audio_codec?: string;\n bitrate_bps?: number;\n container?: string;\n}\n\n/** Returned by every mutating transforms method. */\nexport interface JobHandle {\n id: string;\n src_key: string;\n output_key: string;\n status: JobStatus;\n}\n\n/** Returned by `transforms.job(id)`. */\nexport interface JobStatusResponse {\n id: string;\n status: JobStatus;\n}\n\n// ── Service interface (matches the JS object the runtime injects) ───────\n\nexport interface TransformsService {\n transcode(srcKey: string, opts: TranscodeOpts): Promise<JobHandle>;\n thumbnail(srcKey: string, opts: ThumbnailOpts): Promise<JobHandle>;\n resize(srcKey: string, opts: ResizeOpts): Promise<JobHandle>;\n probe(srcKey: string): Promise<MediaInfo>;\n ocr(srcKey: string, opts?: OcrOpts | null): Promise<JobHandle>;\n job(id: string): Promise<JobStatusResponse>;\n}\n\n// ── derive_key mirror ───────────────────────────────────────────────────\n\n/** Sort object keys recursively so the canonical JSON is stable. */\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(value as Record<string, unknown>).sort()) {\n out[k] = sortKeys((value as Record<string, unknown>)[k]);\n }\n return out;\n }\n return value;\n}\n\n/**\n * Canonical JSON encoding — matches `serde_json::to_string` over a\n * recursively key-sorted object. Numbers, booleans, strings, null, and\n * nested objects/arrays only; no `undefined`, no functions.\n */\nfunction canonicalJson(value: unknown): string {\n return JSON.stringify(sortKeys(value));\n}\n\n/** Hex-encoded SHA-256 of the input bytes, truncated to 16 chars (8 bytes). */\nfunction shortHexSha256(input: string): string {\n const bytes = new TextEncoder().encode(input);\n const hash = sha256(bytes);\n return Array.from(hash.slice(0, 8))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Output extension for a spec — drives the `.<ext>` suffix on the\n * derived key. Matches `TransformSpec::output_extension` in Rust.\n */\nfunction outputExtension(spec: TransformSpec): string {\n switch (spec.kind) {\n case 'transcode':\n return spec.format; // 'mp4' | 'webm'\n case 'thumbnail':\n case 'resize': {\n // thumbnail's `format` is optional in TS (defaults to jpg server-side);\n // mirror that default here so keyFor matches the canonical Rust form.\n const fmt = (spec as { format?: ImageFormat }).format ?? 'jpg';\n return fmt;\n }\n case 'ocr':\n return 'txt';\n default: {\n const _exhaust: never = spec;\n throw new Error(`unknown transform kind: ${(_exhaust as { kind: string }).kind}`);\n }\n }\n}\n\n/**\n * Compute the canonical derived-asset key for `(srcKey, spec)`.\n *\n * Shape: `__derived/<srcHash>/<variantHash>.<ext>` where each hash is\n * the first 16 hex chars (8 bytes / 64 bits) of `SHA-256(...)`.\n *\n * **MUST** match Rust `platform::media::transforms::derive_key` byte-for-byte.\n * Cross-language golden vectors live at\n * `crates/platform/tests/derive_key_vectors.json`.\n */\nexport function keyFor(srcKey: string, spec: TransformSpec): string {\n const srcHash = shortHexSha256(srcKey);\n // Re-encode so the canonical JSON includes the `kind` discriminator at\n // a sorted position alongside the inlined opts fields — matches what\n // Rust's `serde_json::to_value(&spec)` produces for the tagged enum.\n const variantHash = shortHexSha256(canonicalJson(spec));\n const ext = outputExtension(spec);\n return `__derived/${srcHash}/${variantHash}.${ext}`;\n}\n\n/** Convenience namespace mirroring the Rust `transforms::keyFor` re-export. */\nexport const transforms = {\n keyFor,\n};\n\n// ── Declarative `transforms` config (consumed by the adapter compiler) ──\n//\n// Mirrors the build-time `TransformsConfig` in `@maravilla-labs/adapter-core`,\n// duplicated here so user code that writes `defineConfig({ transforms: {...} })`\n// gets full IDE completion without depending on adapter-core at runtime.\n//\n// The two type definitions are structurally identical — adapter-core's\n// `compileTransforms` consumes either shape interchangeably (it only walks the\n// JSON-shaped values, not the type-level identity).\n\n/**\n * Per-pattern transforms declaration used inside the `transforms` block of\n * `maravilla.config.ts`. Each field accepts a single opts object or an array.\n *\n * `variants` is sugar for `resize` arrays — convenient for the common\n * \"image → multiple resized renditions\" case.\n */\nexport interface TransformsPatternSpec {\n transcode?: TranscodeOpts | TranscodeOpts[];\n thumbnail?: ThumbnailOpts | ThumbnailOpts[];\n resize?: ResizeOpts | ResizeOpts[];\n /** Sugar for `resize` arrays — same shape, same semantics. */\n variants?: ResizeOpts[];\n ocr?: OcrOpts | OcrOpts[];\n}\n\n/**\n * Top-level `transforms` block. Keys are glob path patterns matched against\n * the storage key of every uploaded object. The adapter compiles each entry\n * into a synthetic `storage.put` event handler that fans out the declared\n * transforms via `Promise.all`.\n *\n * @example\n * ```ts\n * import { defineConfig } from '@maravilla-labs/platform/config';\n *\n * export default defineConfig({\n * transforms: {\n * 'uploads/videos/**': {\n * transcode: [{ format: 'mp4' }, { format: 'webm' }],\n * thumbnail: { at: '1s', width: 640, format: 'jpg' },\n * },\n * 'uploads/photos/**': {\n * variants: [\n * { width: 1600, format: 'webp', quality: 85 },\n * { width: 400, format: 'webp', quality: 80 },\n * ],\n * },\n * },\n * });\n * ```\n */\nexport type TransformsConfig = Record<string, TransformsPatternSpec>;\n","/**\n * @fileoverview Maravilla Platform SDK\n * \n * This package provides the main interface for accessing Maravilla runtime services\n * including Key-Value storage and Database operations. It automatically detects the\n * runtime environment and provides the appropriate implementation.\n * \n * ## Environment Detection\n * \n * The SDK automatically detects and adapts to different environments:\n * - **Production**: Uses native Maravilla runtime APIs\n * - **Development**: Connects to development server via HTTP\n * - **Testing**: Can be mocked or use development server\n * \n * ## Key Features\n * \n * - **KV Storage**: Cloudflare Workers KV-compatible API for key-value operations\n * - **Database**: MongoDB-style document database operations\n * - **Multi-tenancy**: Built-in tenant isolation and support\n * - **TypeScript**: Fully typed APIs with comprehensive JSDoc comments\n * - **Development-friendly**: Seamless development server integration\n * \n * @example\n * ```typescript\n * import { getPlatform } from '@maravilla/platform';\n * \n * const platform = getPlatform();\n * \n * // KV operations\n * await platform.env.KV.cache.put('user:123', { name: 'John' });\n * const user = await platform.env.KV.cache.get('user:123');\n * \n * // Database operations\n * const userId = await platform.env.DB.insertOne('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n * \n * const users = await platform.env.DB.find('users', { active: true });\n * ```\n * \n * @author Maravilla Team\n * @since 1.0.0\n */\n\nimport type { Platform } from './types.js';\nimport { createRemoteClient } from './remote-client.js';\n\nexport * from './types.js';\nexport * from './ren.js';\nexport * from './realtime.js';\nexport * from './media.js';\nexport * from './media-room.js';\nexport * from './push.js';\nexport * from './transforms.js';\n\n/**\n * Global platform instance injected by Maravilla runtime or development tools.\n * This should not be accessed directly - use getPlatform() instead.\n * \n * @internal\n */\n\ndeclare global {\n var __maravilla_platform: Platform | undefined;\n var platform: Platform | undefined;\n}\n\nlet cachedPlatform: Platform | undefined = undefined;\n\n/**\n * Get the platform instance. This will:\n * 1. Check if running in Maravilla runtime (global.platform exists)\n * 2. Check if a platform was injected via vite plugin or hooks\n * 3. Fall back to remote client for development\n * \n * The platform provides access to KV storage and database operations,\n * with automatic environment detection for seamless development and production.\n * \n * @param options - Optional configuration for development mode\n * @param options.devServerUrl - URL of the development server (defaults to MARAVILLA_DEV_SERVER env var or http://localhost:3001)\n * @param options.tenant - Tenant identifier for multi-tenancy (defaults to MARAVILLA_TENANT env var or 'dev-tenant')\n * @returns Platform instance with access to KV and database services\n * \n * @example\n * ```typescript\n * import { getPlatform } from '@maravilla/platform';\n * \n * // Basic usage (auto-detects environment)\n * const platform = getPlatform();\n * \n * // Development with custom server\n * const platform = getPlatform({\n * devServerUrl: 'http://localhost:3001',\n * tenant: 'my-app'\n * });\n * \n * // Use KV storage\n * await platform.env.KV.cache.put('user:123', { name: 'John' });\n * const user = await platform.env.KV.cache.get('user:123');\n * \n * // Use database\n * const userId = await platform.env.DB.insertOne('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n * ```\n */\nexport function getPlatform(options?: {\n devServerUrl?: string;\n tenant?: string;\n}): Platform {\n // Return cached if available\n if (cachedPlatform) {\n return cachedPlatform;\n }\n\n // 1. Check if we're in the real Maravilla runtime\n if (typeof globalThis !== 'undefined') {\n // Check for native platform (in production runtime)\n if (globalThis.platform) {\n console.log('[platform] Using native Maravilla platform');\n cachedPlatform = globalThis.platform;\n return cachedPlatform;\n }\n\n // Check for injected platform (from vite plugin or hooks)\n if (globalThis.__maravilla_platform) {\n console.log('[platform] Using injected platform');\n cachedPlatform = globalThis.__maravilla_platform;\n return cachedPlatform;\n }\n }\n\n // 2. Fall back to remote client for development\n const devServerUrl = options?.devServerUrl || process.env.MARAVILLA_DEV_SERVER || 'http://localhost:3001';\n const tenant = options?.tenant || process.env.MARAVILLA_TENANT || 'dev-tenant-001';\n \n console.log(`[platform] Creating remote client for ${devServerUrl}`);\n cachedPlatform = createRemoteClient(devServerUrl, tenant);\n \n // Cache it globally for other modules\n if (typeof globalThis !== 'undefined') {\n globalThis.__maravilla_platform = cachedPlatform;\n }\n \n return cachedPlatform;\n}\n\n/**\n * Clear the cached platform instance (useful for testing).\n * \n * This function resets the internal platform cache and clears any globally\n * injected platform instances. Subsequent calls to getPlatform() will\n * re-initialize the platform based on the current environment.\n * \n * @example\n * ```typescript\n * import { clearPlatformCache, getPlatform } from '@maravilla/platform';\n * \n * // In tests, clear cache between test cases\n * afterEach(() => {\n * clearPlatformCache();\n * });\n * \n * // Or when switching between different environments\n * clearPlatformCache();\n * const newPlatform = getPlatform({ devServerUrl: 'http://localhost:3002' });\n * ```\n */\nexport function clearPlatformCache(): void {\n cachedPlatform = undefined;\n if (typeof globalThis !== 'undefined') {\n globalThis.__maravilla_platform = undefined;\n }\n}\n\nexport {\n runWithRequest,\n getCurrentRequestStore,\n type RequestStore,\n} from './request-scope.js';"],"mappings":";;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgCA,eAAe,YAAY;AACzB,MAAI,QAAS,QAAO;AACpB,MAAI;AAGF,UAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,aAAkB;AAC7D,UAAM,QAAQ,IAAI,kBAAgC;AAClD,cAAU;AAAA,MACR,KAAK,CAAC,GAAG,OAAO,MAAM,IAAI,GAAG,EAAE;AAAA,MAC/B,UAAU,MAAM,MAAM,SAAS;AAAA,IACjC;AAAA,EACF,QAAQ;AAKN,QAAI;AACJ,cAAU;AAAA,MACR,KAAK,CAAC,GAAG,OAAO;AACd,cAAM,OAAO;AACb,iBAAS;AACT,YAAI;AACF,iBAAO,GAAG;AAAA,QACZ,UAAE;AACA,mBAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,UAAU,MAAM;AAAA,IAClB;AAAA,EACF;AACA,SAAO;AACT;AAyBA,eAAsB,eAAkB,IAAsC;AAC5E,QAAM,MAAM,MAAM,UAAU;AAC5B,SAAO,IAAI,IAAI,EAAE,eAAe,KAAK,GAAG,MAAM,QAAQ,QAAQ,GAAG,CAAC,CAAC;AACrE;AAWO,SAAS,yBAAmD;AACjE,SAAO,SAAS,SAAS;AAC3B;AAMO,SAAS,kBAA8B;AAC5C,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO;AAAA,IACP,UAAU;AAAA,IACV,OAAO,CAAC;AAAA,IACR,cAAc;AAAA,EAChB;AACF;AAWO,SAAS,uBAA+C;AAC7D,QAAM,QAAQ,SAAS,SAAS,GAAG;AACnC,SAAO,QAAQ,EAAE,eAAe,UAAU,KAAK,GAAG,IAAI,CAAC;AACzD;AApIA,IA8BI;AA9BJ;AAAA;AAAA;AA8BA,IAAI,UAA6G;AAAA;AAAA;;;ACe1G,IAAM,qBAAN,MAAiD;AAAA,EACtD,YACU,SACA,SACR;AAFQ;AACA;AAAA,EACP;AAAA,EAFO;AAAA,EACA;AAAA,EAGV,MAAc,MAAM,KAAa,UAAuB,CAAC,GAAG;AAC1D,UAAM,EAAE,sBAAAA,sBAAqB,IAAI,MAAM;AACvC,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,GAAG;AAAA,MACH,SAAS,EAAE,GAAG,KAAK,SAAS,GAAGA,sBAAqB,GAAG,GAAG,QAAQ,QAAQ;AAAA,IAC5E,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,YAAM,IAAI,MAAM,oBAAoB,SAAS,MAAM,MAAM,KAAK,EAAE;AAAA,IAClE;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,QAAgB,WAAkC,CAAC,GAA2B;AAC7F,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,oBAAoB;AAAA,MACnE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,QAAQ,SAAS,CAAC;AAAA,IAC3C,CAAC;AACD,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,WAAW,QAA+B;AAC9C,UAAM,KAAK,MAAM,GAAG,KAAK,OAAO,oBAAoB,mBAAmB,MAAM,CAAC,IAAI;AAAA,MAChF,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YAAsC;AAC1C,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,kBAAkB;AACnE,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,cAAc,QAAgB,aAA8D;AAChG,UAAM,WAAW,MAAM,KAAK;AAAA,MAC1B,GAAG,KAAK,OAAO,oBAAoB,mBAAmB,MAAM,CAAC;AAAA,MAC7D;AAAA,QACE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,WAAW;AAAA,MAClC;AAAA,IACF;AACA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,WAAmC;AACvC,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,gBAAgB;AACjE,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,WAAO,KAAK;AAAA,EACd;AACF;;;ACnGA;AAQA,IAAM,oBAAN,MAA+C;AAAA,EAC7C,YACU,SACA,WACA,SACR;AAHQ;AACA;AACA;AAAA,EACP;AAAA,EAHO;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASV,MAAc,MAAM,KAAa,UAAuB,CAAC,GAAG;AAC1D,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,GAAG;AAAA,MACH,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,qBAAqB,GAAG,GAAG,QAAQ,QAAQ;AAAA,IAC5E,CAAC;AAED,QAAI,CAAC,SAAS,MAAM,SAAS,WAAW,KAAK;AAC3C,YAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,YAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,MAAM,KAAK,EAAE;AAAA,IACrE;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,IAAI,KAA2B;AACnC,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,KAAK,SAAS,IAAI,GAAG,EAAE;AACnF,QAAI,SAAS,WAAW,IAAK,QAAO;AACpC,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,IAAI,KAAa,OAAY,SAAqD;AACtF,UAAM,UAAkC,CAAC;AACzC,QAAI,SAAS,eAAe;AAC1B,cAAQ,OAAO,IAAI,QAAQ,cAAc,SAAS;AAAA,IACpD;AAEA,UAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,KAAK,SAAS,IAAI,GAAG,IAAI;AAAA,MAClE,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,KAAK;AAAA,IAC5B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,OAAO,KAA4B;AACvC,UAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,KAAK,SAAS,IAAI,GAAG,IAAI;AAAA,MAClE,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,KAAK,SAAuF;AAChG,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,KAAK,SAAS,IAAI;AAAA,MAC5E,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,WAAW,CAAC,CAAC;AAAA,IACpC,CAAC;AACD,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,WAAO;AAAA,MACL,MAAM,KAAK,UAAU,CAAC;AAAA,MACtB,eAAe,CAAC,KAAK,aAAa;AAAA,MAClC,QAAQ,KAAK,aAAa;AAAA,IAC5B;AAAA,EACF;AACF;AAQA,IAAM,iBAAN,MAAyC;AAAA,EACvC,YACU,SACA,SACR;AAFQ;AACA;AAAA,EACP;AAAA,EAFO;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASV,MAAc,MAAM,KAAa,UAAuB,CAAC,GAAG;AAC1D,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,GAAG;AAAA,MACH,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,qBAAqB,GAAG,GAAG,QAAQ,QAAQ;AAAA,IAC5E,CAAC;AAED,QAAI,CAAC,SAAS,MAAM,SAAS,WAAW,KAAK;AAC3C,YAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,YAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,MAAM,KAAK,EAAE;AAAA,IACrE;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,YAAoB,SAAc,CAAC,GAAG,UAAyB,CAAC,GAAmB;AAC5F,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,UAAU,IAAI;AAAA,MACxE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,QAAQ,QAAQ,CAAC;AAAA,IAC1C,CAAC;AACD,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,QAAQ,YAAoB,QAAkC;AAClE,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,UAAU,YAAY;AAAA,MAChF,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,MAAM;AAAA,IAC7B,CAAC;AACD,QAAI,SAAS,WAAW,IAAK,QAAO;AACpC,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,UAAU,YAAoB,UAAgC;AAClE,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,UAAU,IAAI;AAAA,MACxE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,QAAQ;AAAA,IAC/B,CAAC;AACD,UAAM,SAAS,MAAM,SAAS,KAAK;AACnC,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAM,UAAU,YAAoB,QAAa,QAA4C;AAC3F,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,UAAU,WAAW;AAAA,MAC/E,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,QAAQ,OAAO,CAAC;AAAA,IACzC,CAAC;AACD,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,UAAU,YAAoB,QAA2C;AAC7E,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,UAAU,WAAW;AAAA,MAC/E,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,MAAM;AAAA,IAC7B,CAAC;AACD,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,WAAW,YAAoB,QAA2C;AAG9E,WAAO,KAAK,UAAU,YAAY,MAAM;AAAA,EAC1C;AAAA,EAEA,MAAM,kBAAkB,YAAoB,MAAsC;AAChF,UAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,UAAU,kBAAkB;AAAA,MACrE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,gBAAgB,YAAoB,OAA8C;AACtF,UAAM,WAAW,MAAM,KAAK;AAAA,MAC1B,GAAG,KAAK,OAAO,WAAW,UAAU,kBAAkB,mBAAmB,KAAK,CAAC;AAAA,MAC/E,EAAE,QAAQ,SAAS;AAAA,IACrB;AACA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,kBAAkB,YAAsD;AAC5E,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,UAAU,kBAAkB;AAAA,MACtF,QAAQ;AAAA,IACV,CAAC;AACD,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,YAAY,YAAoB,OAA0D;AAC9F,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,UAAU,iBAAiB;AAAA,MACrF,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,KAAK;AAAA,IAC5B,CAAC;AACD,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,YAAY,YAAoB,MAA2C;AAC/E,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,UAAU,YAAY;AAAA,MAChF,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,UAAU,YAAoB,MAA6C;AAC/E,UAAM,WAAW,MAAM,KAAK;AAAA,MAC1B,GAAG,KAAK,OAAO,WAAW,UAAU,YAAY,mBAAmB,IAAI,CAAC;AAAA,MACxE,EAAE,QAAQ,SAAS;AAAA,IACrB;AACA,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,YAAY,YAAgD;AAChE,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,WAAW,UAAU,YAAY;AAAA,MAChF,QAAQ;AAAA,IACV,CAAC;AACD,WAAO,SAAS,KAAK;AAAA,EACvB;AACF;AAQA,IAAM,gBAAN,MAAM,eAAiC;AAAA,EACrC,YACU,SACA,SACR;AAFQ;AACA;AAAA,EACP;AAAA,EAFO;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASV,MAAc,MAAM,KAAa,UAAuB,CAAC,GAAG;AAC1D,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,GAAG;AAAA,MACH,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,qBAAqB,GAAG,GAAG,QAAQ,QAAQ;AAAA,IAC5E,CAAC;AAED,QAAI,CAAC,SAAS,MAAM,SAAS,WAAW,KAAK;AAC3C,YAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,YAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,MAAM,KAAK,EAAE;AAAA,IACrE;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,kBAAkB,KAAa,aAAqB,SAKvD;AAKD,UAAM,MAAM,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,2BAA2B;AAAA,MACrE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,KAAK,cAAc,aAAa,YAAY,SAAS,UAAU,CAAC;AAAA,IACzF,CAAC;AACD,UAAM,OAAQ,MAAM,IAAI,KAAK;AAK7B,WAAO;AAAA,MACL,KAAK,KAAK,IAAI,WAAW,MAAM,IAAI,KAAK,MAAM,GAAG,KAAK,OAAO,GAAG,KAAK,GAAG;AAAA,MACxE,QAAQ,KAAK;AAAA,MACb,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,KAAK,QAAQ;AAAA,MAC5C,WAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,MAAM,oBAAoB,KAAa,SAKpC;AACD,UAAM,MAAM,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,6BAA6B;AAAA,MACvE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,KAAK,YAAY,SAAS,UAAU,CAAC;AAAA,IAC9D,CAAC;AACD,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,WAAO;AAAA,MACL,KAAK,KAAK,IAAI,WAAW,MAAM,IAAI,KAAK,MAAM,GAAG,KAAK,OAAO,GAAG,KAAK,GAAG;AAAA,MACxE,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,WAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,KAAa,OAAoD;AAC3E,UAAM,QAAQ,IAAI,QAAQ,QAAQ,EAAE;AACpC,WAAO,GAAG,KAAK,OAAO,YAAY,KAAK;AAAA,EACzC;AAAA,EAEA,MAAM,IAAI,KAAyC;AACjD,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,gBAAgB,mBAAmB,GAAG,CAAC,EAAE;AAC1F,QAAI,SAAS,WAAW,IAAK,QAAO;AACpC,UAAM,cAAc,MAAM,SAAS,YAAY;AAC/C,WAAO,IAAI,WAAW,WAAW;AAAA,EACnC;AAAA,EAEA,MAAM,IAAI,KAAa,MAA2B,UAA+B;AAE/E,UAAM,WAAW,OAAO,SAAS,WAC7B,IAAI,YAAY,EAAE,OAAO,IAAI,IAC7B;AAEJ,UAAM,KAAK,MAAM,GAAG,KAAK,OAAO,gBAAgB,mBAAmB,GAAG,CAAC,IAAI;AAAA,MACzE,QAAQ;AAAA,MACR,SAAS,WAAW,EAAE,cAAc,KAAK,UAAU,QAAQ,EAAE,IAAI,CAAC;AAAA;AAAA,MAElE,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,UAAU,KAAa,QAAa,UAA+B;AAEvE,QAAI,OAAO,SAAS,eAAe,kBAAkB,MAAM;AACzD,YAAM,KAAK,MAAM,GAAG,KAAK,OAAO,gBAAgB,mBAAmB,GAAG,CAAC,IAAI;AAAA,QACzE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,GAAI,WAAW,EAAE,cAAc,KAAK,UAAU,QAAQ,EAAE,IAAI,CAAC;AAAA,UAC7D,gBAAgB,OAAO,QAAQ;AAAA,QACjC;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AACD;AAAA,IACF;AAGA,QAAI,UAAU,OAAO,OAAO,cAAc,YAAY;AACpD,YAAM,KAAK,MAAM,GAAG,KAAK,OAAO,gBAAgB,mBAAmB,GAAG,CAAC,IAAI;AAAA,QACzE,QAAQ;AAAA,QACR,SAAS,WAAW,EAAE,cAAc,KAAK,UAAU,QAAQ,EAAE,IAAI,CAAC;AAAA,QAClE,MAAM;AAAA,MACR,CAAC;AACD;AAAA,IACF;AAGA,QAAI,OAAO,iBAAiB,OAAO,UAAU,CAAC,CAAC,GAAG;AAChD,YAAM,UAAU;AAChB,YAAM,SAAS,IAAI,eAAe;AAAA,QAChC,MAAM,KAAK,YAAY;AACrB,gBAAM,EAAE,OAAO,KAAK,IAAI,MAAM,QAAQ,OAAO,aAAa,EAAE,EAAE,KAAK;AACnE,cAAI,MAAM;AAAE,uBAAW,MAAM;AAAG;AAAA,UAAQ;AACxC,qBAAW,QAAQ,eAAc,eAAe,KAAK,CAAC;AAAA,QACxD;AAAA,MACF,CAAC;AACD,YAAM,KAAK,MAAM,GAAG,KAAK,OAAO,gBAAgB,mBAAmB,GAAG,CAAC,IAAI;AAAA,QACzE,QAAQ;AAAA,QACR,SAAS,WAAW,EAAE,cAAc,KAAK,UAAU,QAAQ,EAAE,IAAI,CAAC;AAAA,QAClE,MAAM;AAAA,MACR,CAAC;AACD;AAAA,IACF;AAGA,QAAI,OAAO,YAAY,OAAO,UAAU,CAAC,CAAC,GAAG;AAC3C,YAAM,KAAM,OAAyB,OAAO,QAAQ,EAAE;AACtD,YAAM,SAAS,IAAI,eAAe;AAAA,QAChC,KAAK,YAAY;AACf,gBAAM,MAAM,GAAG,KAAK;AAClB,cAAI,IAAI,MAAM;AAAE,uBAAW,MAAM;AAAG;AAAA,UAAQ;AAC5C,qBAAW,QAAQ,eAAc,eAAe,IAAI,KAAK,CAAC;AAAA,QAC9D;AAAA,MACF,CAAC;AACD,YAAM,KAAK,MAAM,GAAG,KAAK,OAAO,gBAAgB,mBAAmB,GAAG,CAAC,IAAI;AAAA,QACzE,QAAQ;AAAA,QACR,SAAS,WAAW,EAAE,cAAc,KAAK,UAAU,QAAQ,EAAE,IAAI,CAAC;AAAA,QAClE,MAAM;AAAA,MACR,CAAC;AACD;AAAA,IACF;AAGF,UAAM,KAAK,IAAI,KAAK,eAAc,eAAe,MAAM,GAAG,QAAQ;AAAA,EAClE;AAAA,EACA,OAAe,eAAe,GAAoB;AAChD,QAAI,KAAK,KAAM,QAAO,IAAI,WAAW;AACrC,QAAI,OAAO,MAAM,SAAU,QAAO,IAAI,YAAY,EAAE,OAAO,CAAC;AAC5D,QAAI,aAAa,WAAY,QAAO;AACpC,QAAI,aAAa,YAAa,QAAO,IAAI,WAAW,CAAC;AACrD,QAAI,MAAM,QAAQ,CAAC,EAAG,QAAO,WAAW,KAAK,CAAC;AAC9C,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACvD;AAAA,EACA,MAAM,OAAO,KAA4B;AACvC,UAAM,KAAK,MAAM,GAAG,KAAK,OAAO,gBAAgB,mBAAmB,GAAG,CAAC,IAAI;AAAA,MACzE,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,KAAK,SAKP;AACF,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,SAAS,OAAQ,QAAO,IAAI,UAAU,QAAQ,MAAM;AACxD,QAAI,SAAS,MAAO,QAAO,IAAI,SAAS,QAAQ,MAAM,SAAS,CAAC;AAEhE,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,gBAAgB,MAAM,EAAE;AACzE,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,YAAY,KAKR;AACR,UAAM,WAAW,MAAM,KAAK,MAAM,GAAG,KAAK,OAAO,gBAAgB,mBAAmB,GAAG,CAAC,WAAW;AACnG,QAAI,SAAS,WAAW,IAAK,QAAO;AACpC,WAAO,SAAS,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,QAAQ,KAA4B;AAQxC,UAAM,KAAK,MAAM,GAAG,KAAK,OAAO,wBAAwB;AAAA,MACtD,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,EAAE,IAAI,CAAC;AAAA,IAC9B,CAAC;AAAA,EACH;AACF;AAMA,IAAM,wBAAN,MAAuD;AAAA,EACrD,YAAoB,SAAyB,SAAiC;AAA1D;AAAyB;AAAA,EAAkC;AAAA,EAA3D;AAAA,EAAyB;AAAA,EAE7C,MAAM,KAAK,SAAiB,QAAgB,UAAkC;AAC5E,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,0BAA0B,mBAAmB,OAAO,CAAC,SAAS;AAAA,MACnG,QAAQ;AAAA,MACR,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,qBAAqB,EAAE;AAAA,MACtD,MAAM,KAAK,UAAU,EAAE,QAAQ,SAAS,CAAC;AAAA,IAC3C,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA,EAEA,MAAM,MAAM,SAAiB,QAAkC;AAC7D,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,0BAA0B,mBAAmB,OAAO,CAAC,UAAU;AAAA,MACpG,QAAQ;AAAA,MACR,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,qBAAqB,EAAE;AAAA,MACtD,MAAM,KAAK,UAAU,EAAE,OAAO,CAAC;AAAA,IACjC,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA,EAEA,MAAM,QAAQ,SAAwF;AACpG,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,0BAA0B,mBAAmB,OAAO,CAAC,IAAI;AAAA,MAC9F,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,qBAAqB,EAAE;AAAA,IACxD,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,KAAK,WAAW,CAAC;AAAA,EAC1B;AACF;AAEA,IAAM,wBAAN,MAAuD;AAAA,EAGrD,YAAoB,SAAyB,SAAiC;AAA1D;AAAyB;AAC3C,SAAK,WAAW,IAAI,sBAAsB,SAAS,OAAO;AAAA,EAC5D;AAAA,EAFoB;AAAA,EAAyB;AAAA,EAF7C;AAAA,EAMA,MAAM,QAAQ,SAAiB,MAAW,SAA8C;AACtF,UAAM,MAAM,GAAG,KAAK,OAAO,yBAAyB;AAAA,MAClD,QAAQ;AAAA,MACR,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,qBAAqB,EAAE;AAAA,MACtD,MAAM,KAAK,UAAU,EAAE,SAAS,MAAM,QAAQ,SAAS,OAAO,CAAC;AAAA,IACjE,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,WAA8B;AAClC,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,0BAA0B;AAAA,MAC/D,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,qBAAqB,EAAE;AAAA,IACxD,CAAC;AACD,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,KAAK,YAAY,CAAC;AAAA,EAC3B;AACF;AAOA,IAAM,oBAAN,MAAM,mBAAyC;AAAA,EAC7C,YACU,SACA,SACR;AAFQ;AACA;AAAA,EACP;AAAA,EAFO;AAAA,EACA;AAAA,EAGV,MAAc,KAAK,MAAc,MAA0B;AACzD,UAAM,MAAM,MAAM,MAAM,GAAG,KAAK,OAAO,qBAAqB,IAAI,IAAI;AAAA,MAClE,QAAQ;AAAA,MACR,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,qBAAqB,EAAE;AAAA,MACtD,MAAM,SAAS,SAAY,KAAK,UAAU,IAAI,IAAI;AAAA,IACpD,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,YAAM,IAAI,MAAM,eAAe,IAAI,MAAM,MAAM,IAAI,EAAE;AAAA,IACvD;AACA,QAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,WAAO,IAAI,KAAK;AAAA,EAClB;AAAA,EAEA,MAAM,SAAS,SAA6C;AAC1D,WAAO,KAAK,KAAK,aAAa,OAAO;AAAA,EACvC;AAAA,EAEA,MAAM,MAAM,SAA6C;AACvD,WAAO,KAAK,KAAK,UAAU,OAAO;AAAA,EACpC;AAAA,EAEA,MAAM,SAAS,aAAwC;AACrD,WAAO,KAAK,KAAK,aAAa,EAAE,OAAO,YAAY,CAAC;AAAA,EACtD;AAAA,EAEA,MAAM,QAAQ,cAA4C;AACxD,WAAO,KAAK,KAAK,YAAY,EAAE,OAAO,aAAa,CAAC;AAAA,EACtD;AAAA,EAEA,MAAM,OAAO,WAAkC;AAC7C,UAAM,KAAK,KAAK,WAAW,EAAE,YAAY,UAAU,CAAC;AAAA,EACtD;AAAA,EAEA,MAAM,QAAQ,QAA0C;AACtD,WAAO,KAAK,KAAK,aAAa,EAAE,SAAS,OAAO,CAAC;AAAA,EACnD;AAAA,EAEA,MAAM,UAAU,QAAoD;AAClE,WAAO,KAAK,KAAK,eAAe,UAAU,CAAC,CAAC;AAAA,EAC9C;AAAA,EAEA,MAAM,WAAW,QAAgB,QAA8C;AAC7E,WAAO,KAAK,KAAK,gBAAgB,EAAE,SAAS,QAAQ,GAAG,OAAO,CAAC;AAAA,EACjE;AAAA,EAEA,MAAM,WAAW,QAA+B;AAC9C,UAAM,KAAK,KAAK,gBAAgB,EAAE,SAAS,OAAO,CAAC;AAAA,EACrD;AAAA,EAEA,MAAM,iBAAiB,QAA4C;AACjE,WAAO,KAAK,KAAK,sBAAsB,EAAE,SAAS,OAAO,CAAC;AAAA,EAC5D;AAAA,EAEA,MAAM,YAAY,OAA8B;AAC9C,UAAM,KAAK,KAAK,iBAAiB,EAAE,MAAM,CAAC;AAAA,EAC5C;AAAA,EAEA,MAAM,kBAAkB,OAA2C;AACjE,WAAO,KAAK,KAAK,wBAAwB,EAAE,MAAM,CAAC;AAAA,EACpD;AAAA,EAEA,MAAM,cAAc,OAAe,aAAoC;AACrE,UAAM,KAAK,KAAK,mBAAmB,EAAE,OAAO,cAAc,YAAY,CAAC;AAAA,EACzE;AAAA,EAEA,MAAM,eAAe,QAAgB,aAAqB,aAAoC;AAC5F,UAAM,KAAK,KAAK,oBAAoB,EAAE,SAAS,QAAQ,cAAc,aAAa,cAAc,YAAY,CAAC;AAAA,EAC/G;AAAA,EAEA,MAAM,iBAAmD;AACvD,WAAO,KAAK,KAAK,eAAe;AAAA,EAClC;AAAA,EAEA,MAAM,YAAY,UAAkB,SAAkF;AACpH,WAAO,KAAK,KAAK,gBAAgB,EAAE,UAAU,cAAc,SAAS,eAAe,mBAAmB,QAAQ,GAAG,CAAC;AAAA,EACpH;AAAA,EAEA,MAAM,oBAAoB,UAAkB,QAAuD;AACjG,WAAO,KAAK,KAAK,mBAAmB,EAAE,UAAU,MAAM,OAAO,MAAM,OAAO,OAAO,MAAM,CAAC;AAAA,EAC1F;AAAA;AAAA,EAIA,MAAM,YAAY,SAA4B;AAC5C,WAAO,KAAK,KAAK,kBAAkB,OAAO;AAAA,EAC5C;AAAA,EACA,MAAM,aAA6B;AACjC,WAAO,KAAK,KAAK,gBAAgB,CAAC,CAAC;AAAA,EACrC;AAAA,EACA,MAAM,SAAS,SAA+B;AAC5C,WAAO,KAAK,KAAK,eAAe,EAAE,UAAU,QAAQ,CAAC;AAAA,EACvD;AAAA,EACA,MAAM,YAAY,SAAiB,SAA4B;AAC7D,WAAO,KAAK,KAAK,kBAAkB,EAAE,UAAU,SAAS,GAAG,QAAQ,CAAC;AAAA,EACtE;AAAA,EACA,MAAM,YAAY,SAAgC;AAChD,UAAM,KAAK,KAAK,kBAAkB,EAAE,UAAU,QAAQ,CAAC;AAAA,EACzD;AAAA,EACA,MAAM,eAAe,QAAgB,SAAgC;AACnE,UAAM,KAAK,KAAK,oBAAoB,EAAE,SAAS,QAAQ,UAAU,QAAQ,CAAC;AAAA,EAC5E;AAAA,EACA,MAAM,oBAAoB,QAAgB,SAAgC;AACxE,UAAM,KAAK,KAAK,uBAAuB,EAAE,SAAS,QAAQ,UAAU,QAAQ,CAAC;AAAA,EAC/E;AAAA,EACA,MAAM,cAAc,QAAgC;AAClD,WAAO,KAAK,KAAK,2BAA2B,EAAE,SAAS,OAAO,CAAC;AAAA,EACjE;AAAA,EACA,MAAM,gBAAgB,SAAiC;AACrD,WAAO,KAAK,KAAK,uBAAuB,EAAE,UAAU,QAAQ,CAAC;AAAA,EAC/D;AAAA,EACA,MAAM,oBAAoB,SAAiC;AACzD,WAAO,KAAK,KAAK,2BAA2B,EAAE,UAAU,QAAQ,CAAC;AAAA,EACnE;AAAA,EACA,MAAM,oBAAoB,SAAiB,aAAmC;AAC5E,UAAM,KAAK,KAAK,2BAA2B,EAAE,UAAU,SAAS,YAAY,CAAC;AAAA,EAC/E;AAAA;AAAA,EAIA,MAAM,aAAa,SAA4B;AAC7C,WAAO,KAAK,KAAK,mBAAmB,OAAO;AAAA,EAC7C;AAAA,EACA,MAAM,cAA8B;AAClC,WAAO,KAAK,KAAK,iBAAiB,CAAC,CAAC;AAAA,EACtC;AAAA,EACA,MAAM,UAAU,UAAgC;AAC9C,WAAO,KAAK,KAAK,gBAAgB,EAAE,WAAW,SAAS,CAAC;AAAA,EAC1D;AAAA,EACA,MAAM,aAAa,UAAkB,SAA4B;AAC/D,WAAO,KAAK,KAAK,mBAAmB,EAAE,WAAW,UAAU,GAAG,QAAQ,CAAC;AAAA,EACzE;AAAA,EACA,MAAM,aAAa,UAAiC;AAClD,UAAM,KAAK,KAAK,mBAAmB,EAAE,WAAW,SAAS,CAAC;AAAA,EAC5D;AAAA,EACA,MAAM,gBAAgB,UAAkB,SAA6B;AACnE,UAAM,KAAK,KAAK,uBAAuB,EAAE,WAAW,UAAU,GAAG,QAAQ,CAAC;AAAA,EAC5E;AAAA,EACA,MAAM,mBAAmB,UAAkB,QAA+B;AACxE,UAAM,KAAK,KAAK,0BAA0B,EAAE,WAAW,UAAU,SAAS,OAAO,CAAC;AAAA,EACpF;AAAA,EACA,MAAM,iBAAiB,UAAkC;AACvD,WAAO,KAAK,KAAK,wBAAwB,EAAE,WAAW,SAAS,CAAC;AAAA,EAClE;AAAA,EACA,MAAM,eAAe,QAAgC;AACnD,WAAO,KAAK,KAAK,6BAA6B,EAAE,SAAS,OAAO,CAAC;AAAA,EACnE;AAAA;AAAA,EAIA,MAAM,eAAe,SAA4B;AAC/C,WAAO,KAAK,KAAK,qBAAqB,OAAO;AAAA,EAC/C;AAAA,EACA,MAAM,gBAAgC;AACpC,WAAO,KAAK,KAAK,mBAAmB,CAAC,CAAC;AAAA,EACxC;AAAA,EACA,MAAM,eAAe,YAAoB,SAA4B;AACnE,WAAO,KAAK,KAAK,qBAAqB,EAAE,aAAa,YAAY,GAAG,QAAQ,CAAC;AAAA,EAC/E;AAAA,EACA,MAAM,eAAe,YAAmC;AACtD,UAAM,KAAK,KAAK,qBAAqB,EAAE,aAAa,WAAW,CAAC;AAAA,EAClE;AAAA;AAAA,EAIA,MAAM,mBAAmB,SAA4B;AACnD,WAAO,KAAK,KAAK,0BAA0B,OAAO;AAAA,EACpD;AAAA,EACA,MAAM,oBAAoC;AACxC,WAAO,KAAK,KAAK,wBAAwB,CAAC,CAAC;AAAA,EAC7C;AAAA,EACA,MAAM,mBAAmB,IAAY,SAA4B;AAC/D,WAAO,KAAK,KAAK,0BAA0B,EAAE,IAAI,GAAG,QAAQ,CAAC;AAAA,EAC/D;AAAA,EACA,MAAM,mBAAmB,IAA2B;AAClD,UAAM,KAAK,KAAK,0BAA0B,EAAE,GAAG,CAAC;AAAA,EAClD;AAAA;AAAA,EAIA,MAAM,WAAW,QAA8C;AAC7D,WAAO,KAAK,KAAK,gBAAgB,EAAE,SAAS,OAAO,CAAC;AAAA,EACtD;AAAA,EACA,MAAM,WAAW,QAAgB,MAA0C;AACzE,UAAM,KAAK,KAAK,gBAAgB,EAAE,SAAS,QAAQ,KAAK,CAAC;AAAA,EAC3D;AAAA;AAAA,EAIA,MAAM,gBAA8B;AAClC,WAAO,KAAK,KAAK,eAAe,CAAC,CAAC;AAAA,EACpC;AAAA,EACA,MAAM,cAAc,QAA4B;AAC9C,UAAM,KAAK,KAAK,eAAe,MAAM;AAAA,EACvC;AAAA;AAAA,EAIS,cAAc;AAAA,IACrB,SAAS,CAAC,WAAmB,KAAK,KAAK,wBAAwB,EAAE,SAAS,OAAO,CAAC;AAAA,IAClF,gBAAgB,CAAC,YACf,KAAK,KAAK,gCAAgC,OAAO;AAAA,IACnD,QAAQ,OAAO,OAAe;AAC5B,YAAM,KAAK,KAAK,uBAAuB,EAAE,GAAG,CAAC;AAAA,IAC/C;AAAA,IACA,iBAAiB,OACf,WACA,QACA,UACA,WACqB;AACrB,YAAM,IAAI,MAAM,KAAK,KAAK,iCAAiC;AAAA,QACzD,YAAY;AAAA,QACZ,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,QAAS,GAAW,OAAO;AAAA,IACpC;AAAA,IACA,aAAa,CAAC,WAAmB,WAC/B,KAAK,KAAK,8BAA8B,EAAE,YAAY,WAAW,SAAS,OAAO,CAAC;AAAA,IACpF,WAAW,CACT,QACA,UAA+C,CAAC,MAEhD,KAAK,KAAK,2BAA2B;AAAA,MACnC,SAAS;AAAA,MACT,OAAO,QAAQ,SAAS;AAAA,MACxB,QAAQ,QAAQ,UAAU;AAAA,IAC5B,CAAC;AAAA,EACL;AAAA,EAEA,SACE,SACyC;AACzC,UAAM,OAAO;AACb,WAAO,eAAe,SAAqC;AACzD,UAAI,QAAuB;AAC3B,YAAM,aAAa,QAAQ,QAAQ,IAAI,eAAe;AACtD,UAAI,YAAY,WAAW,SAAS,GAAG;AACrC,gBAAQ,WAAW,MAAM,CAAC;AAAA,MAC5B,OAAO;AACL,cAAM,UAAU,QAAQ,QAAQ,IAAI,QAAQ,KAAK;AACjD,cAAM,QAAQ,QAAQ,MAAM,mBAAmB;AAC/C,YAAI,MAAO,SAAQ,MAAM,CAAC;AAAA,MAC5B;AACA,UAAI,CAAC,OAAO;AACV,eAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,0BAA0B,CAAC,GAAG;AAAA,UACxE,QAAQ;AAAA,UAAK,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC7D,CAAC;AAAA,MACH;AACA,UAAI;AACF,cAAM,OAAO,MAAM,KAAK,SAAS,KAAK;AACtC,QAAC,QAAgB,OAAO;AACxB,eAAO,QAAQ,OAAuC;AAAA,MACxD,QAAQ;AACN,eAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,2BAA2B,CAAC,GAAG;AAAA,UACzE,QAAQ;AAAA,UAAK,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC7D,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,eAAe,OAAqC;AACxD,UAAM,EAAE,wBAAAC,wBAAuB,IAAI,MAAM;AACzC,UAAM,QAAQA,wBAAuB;AACrC,QAAI,CAAC,OAAO;AASV;AAAA,IACF;AACA,QAAI,CAAC,OAAO;AACV,YAAM,QAAQ;AACd,YAAM,OAAO;AACb;AAAA,IACF;AACA,UAAM,QAAQ;AACd,UAAM,OAAO,MAAM,KAAK,SAAS,KAAK;AAAA,EACxC;AAAA,EAEA,iBAA6B;AAI3B,UAAM,MAAO,mBAA0B;AAGvC,UAAM,QAAQ,KAAK,yBAAyB;AAC5C,UAAM,OAAO,OAAO;AACpB,QAAI,CAAC,MAAM;AACT,aAAO,KAAK,kBAAkB,KAAK;AAAA,QACjC,SAAS;AAAA,QACT,OAAO;AAAA,QACP,UAAU;AAAA,QACV,OAAO,CAAC;AAAA,QACR,cAAc;AAAA,MAChB;AAAA,IACF;AACA,WAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,UAAU;AAAA,MACV,OAAO,KAAK,UAAU,CAAC;AAAA,MACvB,cAAc;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,MAAM,IACJ,QACA,YACA,MACkB;AAClB,UAAM,EAAE,wBAAAA,wBAAuB,IAAI,MAAM;AACzC,UAAM,QAAQA,wBAAuB;AACrC,UAAM,QAAQ,OAAO;AACrB,QAAI,CAAC,OAAO;AAEV,aAAO;AAAA,IACT;AACA,UAAM,IAAI,MAAM,KAAK,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA;AAAA,MACA,aAAa;AAAA,MACb,MAAM,QAAQ;AAAA,IAChB,CAAC;AACD,WAAO,QAAS,GAAW,OAAO;AAAA,EACpC;AACF;AAKA,4EACG,KAAK,CAAC,QAAQ;AACb,EAAC,kBAA0B,gBAAgB;AAC7C,CAAC,EACA,MAAM,MAAM;AAEb,CAAC;AAMH,IAAM,sBAAN,MAAmD;AAAA,EACjD,WAAW,UAAyB;AAClC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAqB;AACnB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AASA,IAAM,kBAAN,MAA2C;AAAA,EACzC,YACU,SACA,SACR;AAFQ;AACA;AAAA,EACP;AAAA,EAFO;AAAA,EACA;AAAA,EAGV,MAAc,QAAQ,MAAc,UAAuB,CAAC,GAAsB;AAChF,UAAM,WAAW,MAAM,MAAM,GAAG,KAAK,OAAO,GAAG,IAAI,IAAI;AAAA,MACrD,GAAG;AAAA,MACH,SAAS,EAAE,GAAG,KAAK,SAAS,GAAG,qBAAqB,GAAG,GAAG,QAAQ,QAAQ;AAAA,IAC5E,CAAC;AACD,QAAI,CAAC,SAAS,MAAM,SAAS,WAAW,KAAK;AAC3C,YAAM,QAAQ,MAAM,SAAS,KAAK;AAClC,YAAM,IAAI,MAAM,uBAAuB,SAAS,MAAM,MAAM,KAAK,EAAE;AAAA,IACrE;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,MAAM,YAAoB,QAAiB,CAAC,GAA4B;AAC5E,QAAI,OAAO,eAAe,YAAY,CAAC,YAAY;AACjD,YAAM,IAAI,MAAM,wDAAwD;AAAA,IAC1E;AACA,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB,kBAAkB,mBAAmB,UAAU,CAAC;AAAA,MAChD,EAAE,QAAQ,QAAQ,MAAM,KAAK,UAAU,SAAS,CAAC,CAAC,EAAE;AAAA,IACtD;AACA,UAAM,EAAE,MAAM,IAAK,MAAM,IAAI,KAAK;AAClC,WAAO,yBAAyB,KAAK,SAAS,KAAK,SAAS,KAAK;AAAA,EACnE;AAAA,EAEA,OAAO,OAA+B;AACpC,QAAI,OAAO,UAAU,YAAY,CAAC,OAAO;AACvC,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AACA,WAAO,yBAAyB,KAAK,SAAS,KAAK,SAAS,KAAK;AAAA,EACnE;AAAA,EAEA,MAAM,UAAU,WAAmB,UAAmB,MAAuB;AAC3E,QAAI,OAAO,cAAc,YAAY,CAAC,WAAW;AAC/C,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC7E;AACA,UAAM,MAAM,MAAM,KAAK,QAAQ,yBAAyB;AAAA,MACtD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,WAAW,QAAQ,CAAC;AAAA,IAC7C,CAAC;AACD,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;AAEA,SAAS,yBACP,SACA,SACA,OACgB;AAChB,QAAM,UAAU,OAAO,MAAc,OAAoB,CAAC,MAAyB;AACjF,UAAM,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,IAAI,IAAI;AAAA,MAC3C,GAAG;AAAA,MACH,SAAS,EAAE,GAAG,SAAS,GAAG,KAAK,QAAQ;AAAA,IACzC,CAAC;AACD,QAAI,CAAC,IAAI,MAAM,IAAI,WAAW,KAAK;AACjC,YAAM,IAAI,MAAM,uBAAuB,IAAI,MAAM,MAAM,MAAM,IAAI,KAAK,CAAC,EAAE;AAAA,IAC3E;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAyB;AAAA,IAC7B;AAAA,IACA,MAAM,SAAsC;AAC1C,YAAM,MAAM,MAAM,QAAQ,uBAAuB,mBAAmB,KAAK,CAAC,EAAE;AAC5E,UAAI,IAAI,WAAW,IAAK,QAAO;AAC/B,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB;AAAA,IACA,MAAM,UAAyC;AAC7C,YAAM,MAAM,MAAM;AAAA,QAChB,uBAAuB,mBAAmB,KAAK,CAAC;AAAA,MAClD;AACA,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB;AAAA,IACA,MAAM,SAA2B;AAC/B,YAAM,MAAM,MAAM;AAAA,QAChB,uBAAuB,mBAAmB,KAAK,CAAC;AAAA,QAChD,EAAE,QAAQ,OAAO;AAAA,MACnB;AACA,YAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,aAAO,KAAK;AAAA,IACd;AAAA,IACA,MAAM,OAAO,SAAoD;AAC/D,YAAM,YAAY,SAAS;AAC3B,YAAM,WACJ,OAAO,cAAc,YAAY,OAAO,SAAS,SAAS,KAAK,YAAY,IACvE,KAAK,IAAI,IAAI,YACb;AACN,UAAI,QAAQ;AACZ,aAAO,MAAM;AACX,cAAM,MAAM,MAAM,OAAO,OAAO;AAChC,YAAI,CAAC,IAAK,OAAM,IAAI,MAAM,2BAA2B,KAAK,EAAE;AAC5D,YAAI,IAAI,WAAW,YAAa,QAAO,IAAI;AAC3C,YAAI,IAAI,WAAW,YAAY,IAAI,WAAW,aAAa;AACzD,gBAAM,MAAM,IAAI,MAAM,YAAY,IAAI,MAAM,EAAE;AAC9C,cAAI,MAAM;AACV,gBAAM;AAAA,QACR;AACA,YAAI,aAAa,QAAQ,KAAK,IAAI,KAAK,UAAU;AAC/C,gBAAM,IAAI,MAAM,yBAAyB;AAAA,QAC3C;AACA,cAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC;AAC7C,gBAAQ,KAAK,IAAI,QAAQ,GAAG,GAAI;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AA0BO,SAAS,mBAAmB,SAAiB,QAAgB;AAClE,QAAM,UAAU;AAAA,IACd,gBAAgB;AAAA,IAChB,eAAe;AAAA,EACjB;AAGA,QAAM,UAAU,IAAI,MAAM,CAAC,GAAkC;AAAA,IAC3D,IAAI,GAAG,WAAmB;AACxB,aAAO,IAAI,kBAAkB,SAAS,WAAW,OAAO;AAAA,IAC1D;AAAA,EACF,CAAC;AAED,QAAM,KAAK,IAAI,eAAe,SAAS,OAAO;AAC9C,QAAM,UAAU,IAAI,cAAc,SAAS,OAAO;AAClD,QAAM,QAAQ,IAAI,mBAAmB,SAAS,OAAO;AACrD,QAAM,WAAW,IAAI,sBAAsB,SAAS,OAAO;AAC3D,QAAM,OAAO,IAAI,kBAAkB,SAAS,OAAO;AACnD,QAAM,SAAS,IAAI,oBAAoB;AACvC,QAAM,YAAY,IAAI,gBAAgB,SAAS,OAAO;AAEtD,SAAO;AAAA,IACL,KAAK;AAAA,MACH,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,SAAS;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACtgCO,IAAM,YAAN,MAAgB;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY,oBAAI,IAAc;AAAA,EAC9B,KAAyB;AAAA,EACzB,SAAS;AAAA,EACT,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,OAAyB,CAAC,GAAG;AACvC,SAAK,WAAW,KAAK,YAAY,KAAK,eAAe;AACrD,SAAK,OAAQ,KAAK,iBAAiB,KAAK,cAAc,SAAU,KAAK,gBAAgB,CAAC,GAAG;AACzF,SAAK,WAAW,KAAK,YAAY,oBAAoB;AACrD,SAAK,gBAAgB,KAAK,kBAAkB;AAC5C,SAAK,aAAa,KAAK,gBAAgB;AACvC,SAAK,QAAQ,CAAC,CAAC,KAAK,SAAU,OAAO,iBAAiB,eAAe,aAAa,QAAQ,WAAW,MAAM;AAC3G,SAAK,QAAQ;AAAA,EACf;AAAA,EAEQ,iBAAyB;AAU/B,QAAI,OAAO,WAAW,aAAa;AACjC,YAAM,OAAO,OAAO,SAAS;AAC7B,UAAI,QAAQ,SAAS,UAAU,SAAS,QAAQ,SAAS,SAAS,SAAS,IAAI;AAC7E,eAAO,UAAU,OAAO,SAAS,QAAQ;AAAA,MAC3C;AAAA,IACF;AAGA,QAAI,OAAO,eAAe,eAAgB,WAAmB,UAAU;AACrE,aAAO;AAAA,IACT;AAGA,YAAQ,IAAI,gFAAgF;AAC5F,WAAO;AAAA,EACT;AAAA,EAEQ,OAAO,MAAa;AAAE,QAAI,KAAK,MAAO,SAAQ,MAAM,eAAe,GAAG,IAAI;AAAA,EAAG;AAAA,EAE7E,WAAmB;AACzB,UAAM,IAAK,KAAK,KAAK,WAAW,KAAK,KAAK,KAAK,CAAC,MAAM,MAAO,MAAM,KAAK,KAAK,KAAK,GAAG;AACrF,UAAM,KAAK,IAAI,gBAAgB,EAAE,KAAK,KAAK,UAAU,EAAE,CAAC;AACxD,WAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,SAAS,CAAC;AAAA,EAC1C;AAAA,EAEQ,UAAU;AAChB,UAAM,MAAM,KAAK,SAAS;AAC1B,SAAK,IAAI,cAAc,EAAE,IAAI,CAAC;AAC9B,SAAK,KAAK,IAAI,YAAY,GAAG;AAC7B,SAAK,SAAS;AAEd,UAAM,UAAU,CAAC,MAAoB;AACnC,UAAI;AACF,cAAM,MAAgB,KAAK,MAAM,EAAE,IAAI;AACvC,aAAK,IAAI,SAAS,GAAG;AACrB,aAAK,UAAU,QAAQ,OAAK,EAAE,GAAG,CAAC;AAAA,MACpC,SAAS,KAAK;AACZ,aAAK,IAAI,wBAAwB,EAAE,MAAM,GAAG;AAAA,MAC9C;AAAA,IACF;AAGA,SAAK,GAAG,YAAY;AAKpB,UAAM,kBAAkB;AAAA;AAAA,MAEtB;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAEA;AAAA,IACF;AAEA,oBAAgB,QAAQ,OAAK,KAAK,IAAI,iBAAiB,GAAG,OAAwB,CAAC;AAEnF,SAAK,GAAG,UAAU,CAAC,OAAO;AACxB,WAAK,IAAI,SAAS,EAAE;AACpB,UAAI,KAAK,OAAQ;AACjB,WAAK,IAAI,MAAM;AACf,UAAI,CAAC,KAAK,cAAe;AACzB,YAAM,QAAQ,KAAK,IAAI,MAAO,KAAK,IAAI,GAAG,KAAK,SAAS,GAAG,KAAK,UAAU;AAC1E,WAAK,IAAI,mBAAmB,OAAO,IAAI;AACvC,iBAAW,MAAM,KAAK,QAAQ,GAAG,KAAK;AAAA,IACxC;AAEA,SAAK,GAAG,SAAS,MAAM;AAAE,WAAK,UAAU;AAAG,WAAK,IAAI,MAAM;AAAA,IAAG;AAAA,EAC/D;AAAA,EAEA,GAAG,UAAgC;AACjC,SAAK,UAAU,IAAI,QAAQ;AAC3B,SAAK,IAAI,yBAAyB,KAAK,UAAU,IAAI;AACrD,WAAO,MAAM;AAAE,WAAK,UAAU,OAAO,QAAQ;AAAG,WAAK,IAAI,2BAA2B,KAAK,UAAU,IAAI;AAAA,IAAG;AAAA,EAC5G;AAAA,EAEA,cAAc;AAAE,WAAO,KAAK;AAAA,EAAU;AAAA,EAEtC,QAAQ;AACN,SAAK,SAAS;AACd,SAAK,IAAI,MAAM;AACf,SAAK,IAAI,QAAQ;AAAA,EACnB;AACF;AAEO,SAAS,oBAAoB,SAA2B;AAC7D,MAAI,CAAC,SAAS;AACZ,cAAW,OAAO,WAAW,eAAe,OAAO,eAAgB,OAAO,eAAgB,OAAO,eAAe,eAAgB,WAAmB,eAAiB,WAAmB,eAAe;AACtM,QAAI,CAAC,SAAS;AAEZ,aAAQ,WAAW,QAAQ,aAAa,KAAK,eAAe;AAAA,IAC9D;AAAA,EACF;AACA,QAAM,MAAM;AACZ,MAAI,KAAK,QAAQ,QAAQ,GAAG;AAC5B,MAAI,CAAC,IAAI;AACP,SAAM,WAAW,QAAQ,aAAa,KAAK,eAAe;AAC1D,QAAI;AAAE,cAAQ,QAAQ,KAAK,EAAE;AAAA,IAAG,QAAQ;AAAA,IAAC;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,SAAS,iBAAyB;AAEhC,SAAO,uCAAuC,QAAQ,SAAS,OAAK;AAClE,UAAM,IAAI,KAAK,OAAO,IAAI,KAAK;AAC/B,UAAM,IAAI,MAAM,MAAM,IAAK,IAAI,IAAM;AACrC,WAAO,EAAE,SAAS,EAAE;AAAA,EACtB,CAAC;AACH;AAGA,eAAsB,SAAS,OAA+B,OAAoB,CAAC,GAAG,UAAmB;AACvG,QAAM,MAAM,YAAY,oBAAoB;AAC5C,QAAM,UAAU,IAAI,QAAQ,KAAK,WAAW,CAAC,CAAC;AAC9C,UAAQ,IAAI,gBAAgB,GAAG;AAC/B,SAAO,MAAM,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC;AAC1C;AAGA,eAAsB,cAAc,MAAc,MAAmB,UAAmB;AACtF,QAAM,MAAM,MAAM,SAAS,4BAA4B,mBAAmB,IAAI,CAAC,IAAI,EAAE,QAAQ,QAAQ,MAAM,KAAK,GAAG,QAAQ;AAC3H,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,eAAe;AAC5C,SAAO,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpC;AAEA,eAAsB,cAAc,MAAc,UAAmB;AACnE,QAAM,MAAM,MAAM,SAAS,4BAA4B,mBAAmB,IAAI,CAAC,IAAI,EAAE,QAAQ,SAAS,GAAG,QAAQ;AACjH,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,eAAe;AAC5C,SAAO,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AACpC;;;AClLO,IAAM,iBAAN,MAAqB;AAAA,EAClB;AAAA,EACA;AAAA,EACA,KAAuB;AAAA,EACvB,SAAS;AAAA,EACT,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EAEA,mBAAmB,oBAAI,IAAgC;AAAA,EACvD,kBAAkB,oBAAI,IAAmB;AAAA,EACzC,oBAAoB,oBAAI,IAI7B;AAAA,EACK,qBAAqB,oBAAI,IAAY;AAAA,EACrC,kBAA4B,CAAC;AAAA,EAC7B,eAAsD;AAAA,EACtD,iBAAiB,oBAAI,IAAgD;AAAA,EAE7E,YAAY,OAA8B,CAAC,GAAG;AAC5C,SAAK,aAAa,KAAK,cAAc,KAAK,eAAe;AACzD,SAAK,WAAW,KAAK,YAAY,oBAAoB;AACrD,SAAK,gBAAgB,KAAK,kBAAkB;AAC5C,SAAK,aAAa,KAAK,gBAAgB;AACvC,SAAK,QAAQ,CAAC,CAAC,KAAK;AAAA,EACtB;AAAA,EAEQ,iBAAyB;AAC/B,QAAI,OAAO,WAAW,aAAa;AACjC,YAAM,OAAO,OAAO,SAAS;AAC7B,YAAM,QAAQ,OAAO,SAAS,aAAa,WAAW,SAAS;AAG/D,UAAI,QAAQ,SAAS,UAAU,SAAS,QAAQ,SAAS,OAAO;AAC9D,eAAO,QAAQ,OAAO,SAAS,QAAQ;AAAA,MACzC;AACA,aAAO,GAAG,KAAK,KAAK,OAAO,SAAS,IAAI;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,OAAO,MAAa;AAC1B,QAAI,KAAK,MAAO,SAAQ,MAAM,oBAAoB,GAAG,IAAI;AAAA,EAC3D;AAAA;AAAA,EAGA,UAAgB;AACd,QAAI,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,KAAM;AAEtD,UAAM,MAAM,GAAG,KAAK,UAAU,QAAQ,mBAAmB,KAAK,QAAQ,CAAC;AACvE,SAAK,IAAI,cAAc,GAAG;AAC1B,SAAK,SAAS;AAEd,QAAI;AACF,WAAK,KAAK,IAAI,UAAU,GAAG;AAAA,IAC7B,SAAS,GAAG;AACV,WAAK,IAAI,gCAAgC,CAAC;AAC1C,WAAK,kBAAkB;AACvB;AAAA,IACF;AAEA,SAAK,GAAG,SAAS,MAAM;AACrB,WAAK,UAAU;AACf,WAAK,IAAI,WAAW;AAGpB,iBAAW,MAAM,KAAK,oBAAoB;AACxC,aAAK,QAAQ,EAAE,QAAQ,aAAa,SAAS,GAAG,CAAC;AAAA,MACnD;AAGA,iBAAW,CAAC,SAAS,IAAI,KAAK,KAAK,gBAAgB;AACjD,aAAK,QAAQ,EAAE,QAAQ,iBAAiB,SAAS,QAAQ,KAAK,QAAQ,UAAU,KAAK,SAAS,CAAC;AAAA,MACjG;AAGA,iBAAW,OAAO,KAAK,iBAAiB;AACtC,aAAK,IAAI,KAAK,GAAG;AAAA,MACnB;AACA,WAAK,kBAAkB,CAAC;AAGxB,WAAK,SAAS;AACd,WAAK,eAAe,YAAY,MAAM,KAAK,QAAQ,EAAE,QAAQ,OAAO,CAAC,GAAG,IAAK;AAAA,IAC/E;AAEA,SAAK,GAAG,YAAY,CAAC,OAAO;AAC1B,UAAI;AACF,cAAM,QAAuB,KAAK,MAAM,GAAG,IAAI;AAC/C,aAAK,IAAI,YAAY,KAAK;AAC1B,aAAK,SAAS,KAAK;AAAA,MACrB,SAAS,GAAG;AACV,aAAK,IAAI,qBAAqB,GAAG,MAAM,CAAC;AAAA,MAC1C;AAAA,IACF;AAEA,SAAK,GAAG,UAAU,CAAC,OAAO;AACxB,WAAK,IAAI,SAAS,EAAE;AAAA,IACtB;AAEA,SAAK,GAAG,UAAU,MAAM;AACtB,WAAK,IAAI,cAAc;AACvB,WAAK,KAAK;AACV,WAAK,SAAS;AACd,UAAI,CAAC,KAAK,UAAU,KAAK,eAAe;AACtC,aAAK,kBAAkB;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,WAAW;AACjB,QAAI,KAAK,cAAc;AAAE,oBAAc,KAAK,YAAY;AAAG,WAAK,eAAe;AAAA,IAAM;AAAA,EACvF;AAAA,EAEQ,oBAAoB;AAC1B,UAAM,QAAQ,KAAK,IAAI,MAAO,KAAK,IAAI,GAAG,KAAK,SAAS,GAAG,KAAK,UAAU;AAC1E,SAAK,IAAI,mBAAmB,OAAO,IAAI;AACvC,eAAW,MAAM,KAAK,QAAQ,GAAG,KAAK;AAAA,EACxC;AAAA,EAEQ,QAAQ,KAA0B;AACxC,UAAM,OAAO,KAAK,UAAU,GAAG;AAC/B,QAAI,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,MAAM;AACpD,WAAK,GAAG,KAAK,IAAI;AAAA,IACnB,OAAO;AACL,WAAK,gBAAgB,KAAK,IAAI;AAAA,IAChC;AAAA,EACF;AAAA,EAEQ,SAAS,OAAsB;AAErC,SAAK,gBAAgB,QAAQ,QAAM,GAAG,KAAK,CAAC;AAG5C,QAAI,MAAM,SAAS;AACjB,YAAM,YAAY,KAAK,iBAAiB,IAAI,MAAM,OAAO;AACzD,UAAI,WAAW;AACb,kBAAU,QAAQ,QAAM,GAAG,KAAK,CAAC;AAAA,MACnC;AAAA,IACF;AAGA,QAAI,MAAM,UAAU,mBAAmB,MAAM,UAAU,oBAAoB,MAAM,UAAU,mBAAmB;AAC5G,YAAM,cAAc,KAAK,kBAAkB,IAAI,MAAM,OAAO;AAC5D,UAAI,aAAa;AACf,cAAM,SAAyB;AAAA,UAC7B,QAAQ,MAAM,UAAU;AAAA,UACxB,UAAU,MAAM;AAAA,UAChB,UAAU,MAAM;AAAA,QAClB;AACA,YAAI,MAAM,UAAU,iBAAiB;AACnC,sBAAY,OAAO,QAAQ,QAAM,GAAG,MAAM,CAAC;AAAA,QAC7C,WAAW,MAAM,UAAU,mBAAmB;AAC5C,sBAAY,SAAS,QAAQ,QAAM,GAAG,MAAM,CAAC;AAAA,QAC/C,OAAO;AACL,sBAAY,QAAQ,QAAQ,QAAM,GAAG,MAAM,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,UAAU,SAAiB,UAAyB,SAA2C;AAC7F,QAAI,CAAC,KAAK,iBAAiB,IAAI,OAAO,GAAG;AACvC,WAAK,iBAAiB,IAAI,SAAS,oBAAI,IAAI,CAAC;AAAA,IAC9C;AACA,SAAK,iBAAiB,IAAI,OAAO,EAAG,IAAI,QAAQ;AAGhD,QAAI,CAAC,KAAK,mBAAmB,IAAI,OAAO,GAAG;AACzC,WAAK,mBAAmB,IAAI,OAAO;AACnC,YAAM,MAA2B,EAAE,QAAQ,aAAa,QAAQ;AAChE,UAAI,SAAS,OAAO;AAClB,YAAI,QAAQ,QAAQ;AAAA,MACtB;AACA,WAAK,QAAQ,GAAG;AAAA,IAClB;AAEA,WAAO,MAAM;AACX,YAAM,YAAY,KAAK,iBAAiB,IAAI,OAAO;AACnD,UAAI,WAAW;AACb,kBAAU,OAAO,QAAQ;AACzB,YAAI,UAAU,SAAS,GAAG;AACxB,eAAK,iBAAiB,OAAO,OAAO;AACpC,eAAK,mBAAmB,OAAO,OAAO;AACtC,eAAK,QAAQ,EAAE,QAAQ,eAAe,QAAQ,CAAC;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,UAAsC;AAC1C,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM;AAAE,WAAK,gBAAgB,OAAO,QAAQ;AAAA,IAAG;AAAA,EACxD;AAAA;AAAA,EAGA,QAAQ,SAAiB,MAAW,SAAqC;AACvE,SAAK,QAAQ;AAAA,MACX,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,QAAQ,SAAS;AAAA,IACnB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,SAAS,SAAiB;AACxB,QAAI,CAAC,KAAK,kBAAkB,IAAI,OAAO,GAAG;AACxC,WAAK,kBAAkB,IAAI,SAAS;AAAA,QAClC,QAAQ,oBAAI,IAAI;AAAA,QAChB,SAAS,oBAAI,IAAI;AAAA,QACjB,UAAU,oBAAI,IAAI;AAAA,MACpB,CAAC;AAAA,IACH;AACA,UAAM,YAAY,KAAK,kBAAkB,IAAI,OAAO;AAEpD,WAAO;AAAA;AAAA,MAEL,MAAM,CAAC,QAAgB,aAAyB;AAC9C,aAAK,eAAe,IAAI,SAAS,EAAE,QAAQ,SAAS,CAAC;AACrD,aAAK,QAAQ;AAAA,UACX,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA;AAAA,MAGA,QAAQ,CAAC,aAAyB;AAChC,cAAM,OAAO,KAAK,eAAe,IAAI,OAAO;AAC5C,YAAI,CAAC,KAAM;AACX,aAAK,WAAW;AAChB,aAAK,QAAQ;AAAA,UACX,QAAQ;AAAA,UACR;AAAA,UACA,QAAQ,KAAK;AAAA,UACb;AAAA,QACF,CAAC;AAAA,MACH;AAAA;AAAA,MAGA,OAAO,MAAY;AACjB,aAAK,eAAe,OAAO,OAAO;AAClC,aAAK,QAAQ,EAAE,QAAQ,kBAAkB,QAAQ,CAAC;AAAA,MACpD;AAAA;AAAA,MAGA,QAAQ,CAAC,aAA4D;AACnE,kBAAU,OAAO,IAAI,QAAQ;AAC7B,eAAO,MAAM;AAAE,oBAAU,OAAO,OAAO,QAAQ;AAAA,QAAG;AAAA,MACpD;AAAA;AAAA,MAGA,UAAU,CAAC,aAA4D;AACrE,kBAAU,SAAS,IAAI,QAAQ;AAC/B,eAAO,MAAM;AAAE,oBAAU,SAAS,OAAO,QAAQ;AAAA,QAAG;AAAA,MACtD;AAAA;AAAA,MAGA,SAAS,CAAC,aAA4D;AACpE,kBAAU,QAAQ,IAAI,QAAQ;AAC9B,eAAO,MAAM;AAAE,oBAAU,QAAQ,OAAO,QAAQ;AAAA,QAAG;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,cAAsB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,cAAuB;AACrB,WAAO,KAAK,IAAI,eAAe,UAAU;AAAA,EAC3C;AAAA;AAAA,EAGA,aAAmB;AACjB,SAAK,SAAS;AACd,SAAK,SAAS;AAEd,eAAW,CAAC,OAAO,KAAK,KAAK,gBAAgB;AAC3C,WAAK,QAAQ,EAAE,QAAQ,kBAAkB,QAAQ,CAAC;AAAA,IACpD;AACA,SAAK,eAAe,MAAM;AAC1B,SAAK,IAAI,MAAM;AACf,SAAK,KAAK;AACV,SAAK,kBAAkB,CAAC;AACxB,SAAK,IAAI,uBAAuB;AAAA,EAClC;AACF;;;AC3UA;AAAA,EACE;AAAA,EACA;AAAA,EAOA;AAAA,EACA;AAAA,OAGK;AAIA,IAAK,iBAAL,kBAAKC,oBAAL;AACL,EAAAA,gBAAA,eAAY;AACZ,EAAAA,gBAAA,kBAAe;AACf,EAAAA,gBAAA,iBAAc;AACd,EAAAA,gBAAA,kBAAe;AACf,EAAAA,gBAAA,uBAAoB;AACpB,EAAAA,gBAAA,qBAAkB;AAClB,EAAAA,gBAAA,qBAAkB;AAClB,EAAAA,gBAAA,uBAAoB;AACpB,EAAAA,gBAAA,gBAAa;AACb,EAAAA,gBAAA,kBAAe;AACf,EAAAA,gBAAA,2BAAwB;AACxB,EAAAA,gBAAA,kBAAe;AACf,EAAAA,gBAAA,4BAAyB;AACzB,EAAAA,gBAAA,yBAAsB;AAdZ,SAAAA;AAAA,GAAA;AAqDZ,SAAS,UAAU,QAAmC;AACpD,UAAQ,QAAQ;AAAA,IACd,KAAK,MAAM,OAAO;AAAQ,aAAO;AAAA,IACjC,KAAK,MAAM,OAAO;AAAY,aAAO;AAAA,IACrC,KAAK,MAAM,OAAO;AAAa,aAAO;AAAA,IACtC,KAAK,MAAM,OAAO;AAAkB,aAAO;AAAA,IAC3C;AAAS,aAAO;AAAA,EAClB;AACF;AAEA,SAAS,eAAe,GAAoC;AAC1D,QAAM,SAAkC,CAAC;AACzC,IAAE,kBAAkB,QAAQ,CAAC,QAA0B;AACrD,WAAO,KAAK;AAAA,MACV,UAAU,IAAI;AAAA,MACd,QAAQ,UAAU,IAAI,MAAM;AAAA,MAC5B,MAAM,IAAI,SAAS,MAAM,KAAK,QAAQ,UAAU;AAAA,MAChD,OAAO,IAAI;AAAA,MACX,OAAO,IAAI,OAAO;AAAA,IACpB,CAAC;AAAA,EACH,CAAC;AACD,SAAO;AAAA,IACL,UAAU,EAAE;AAAA,IACZ,MAAM,EAAE;AAAA,IACR,UAAU,EAAE;AAAA,IACZ,YAAY,EAAE;AAAA,IACd,YAAY,EAAE;AAAA,IACd;AAAA,EACF;AACF;AAGO,SAAS,YAAY,OAAyB,SAAoD;AACvG,MAAI,CAAC,SAAS,CAAC,QAAS;AACxB,QAAM,SAAS,IAAI,YAAY,CAAC,KAAK,CAAC;AACtC,UAAQ,YAAY;AACpB,MAAI,mBAAmB,kBAAkB;AACvC,YAAQ,cAAc;AAAA,EACxB;AACA,UAAQ,KAAK,EAAE,MAAM,MAAM;AAAA,EAAC,CAAC;AAC/B;AAGO,SAAS,YAAY,SAAoD;AAC9E,MAAI,CAAC,QAAS;AACd,UAAQ,YAAY;AACtB;AAIO,IAAM,wBAAN,MAAwD;AAAA,EACrD;AAAA;AAAA,EAGR,YAAY,IAAwB;AAAE,SAAK,KAAK;AAAA,EAAI;AAAA,EAEpD,IAAI,WAAW;AAAE,WAAO,KAAK,GAAG;AAAA,EAAU;AAAA,EAC1C,IAAI,OAAO;AAAE,WAAO,KAAK,GAAG;AAAA,EAAM;AAAA,EAClC,IAAI,WAAW;AAAE,WAAO,KAAK,GAAG;AAAA,EAAU;AAAA,EAC1C,IAAI,aAAa;AAAE,WAAO,KAAK,GAAG;AAAA,EAAY;AAAA,EAC9C,IAAI,aAAa;AAAE,WAAO,KAAK,GAAG;AAAA,EAAY;AAAA,EAE9C,IAAI,SAAkC;AACpC,WAAO,eAAe,KAAK,EAAE,EAAE;AAAA,EACjC;AAAA;AAAA,EAGA,IAAI,kBAA2B;AAC7B,WAAO,CAAC,CAAC,KAAK,GAAG,oBAAoB,MAAM,OAAO,MAAM,GAAG,SAAS,CAAC,KAAK,GAAG,oBAAoB,MAAM,OAAO,MAAM,GAAG;AAAA,EACzH;AAAA,EACA,MAAM,aAAa,SAA8E;AAC/F,UAAM,KAAK,GAAG,iBAAiB,MAAM;AAAA,MACnC,UAAU,SAAS;AAAA,MACnB,YAAY,SAAS,aAAa,EAAE,OAAO,QAAQ,WAAW,OAAO,QAAQ,QAAQ,WAAW,QAAQ,WAAW,QAAQ,WAAW,UAAU,IAAI;AAAA,IACtJ,CAAC;AAAA,EACH;AAAA,EACA,MAAM,gBAA+B;AACnC,UAAM,KAAK,GAAG,iBAAiB,KAAK;AAAA,EACtC;AAAA;AAAA,EAGA,IAAI,sBAA+B;AACjC,WAAO,CAAC,CAAC,KAAK,GAAG,oBAAoB,MAAM,OAAO,UAAU,GAAG,SAAS,CAAC,KAAK,GAAG,oBAAoB,MAAM,OAAO,UAAU,GAAG;AAAA,EACjI;AAAA,EACA,MAAM,iBAAiB,SAAgD;AACrE,UAAM,KAAK,GAAG,qBAAqB,MAAM,EAAE,UAAU,SAAS,SAAS,CAAC;AAAA,EAC1E;AAAA,EACA,MAAM,oBAAmC;AACvC,UAAM,KAAK,GAAG,qBAAqB,KAAK;AAAA,EAC1C;AAAA;AAAA,EAGA,IAAI,uBAAgC;AAClC,WAAO,CAAC,CAAC,KAAK,GAAG,oBAAoB,MAAM,OAAO,WAAW,GAAG;AAAA,EAClE;AAAA,EACA,MAAM,kBAAkB,SAA8C;AACpE,UAAM,KAAK,GAAG,sBAAsB,MAAM,EAAE,OAAO,SAAS,MAAM,CAAC;AAAA,EACrE;AAAA,EACA,MAAM,qBAAoC;AACxC,UAAM,KAAK,GAAG,sBAAsB,KAAK;AAAA,EAC3C;AAAA;AAAA,EAGA,MAAM,QAAQ,MAA6B;AAAE,UAAM,KAAK,GAAG,QAAQ,IAAI;AAAA,EAAG;AAAA,EAC1E,MAAM,YAAY,UAAiC;AAAE,UAAM,KAAK,GAAG,YAAY,QAAQ;AAAA,EAAG;AAAA;AAAA,EAG1F,MAAM,SAAS,MAAkB,SAAiD;AAChF,UAAM,KAAK,GAAG,YAAY,MAAM,EAAE,UAAU,SAAS,YAAY,KAAK,CAAC;AAAA,EACzE;AACF;AAMO,IAAM,YAAN,MAAM,WAAU;AAAA,EACb;AAAA,EACA,YAAY,oBAAI,IAAwC;AAAA,EACxD;AAAA,EAER,cAAc;AACZ,SAAK,OAAO,IAAI,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,QAAQ,KAAa,OAAe,SAA2C;AACnF,UAAM,OAA2B,CAAC;AAClC,QAAI,SAAS,kBAAkB,OAAW,MAAK,gBAAgB,QAAQ;AACvE,SAAK,KAAK,QAAQ,iBAAiB,SAAS,kBAAkB;AAC9D,SAAK,KAAK,QAAQ,WAAW,SAAS,YAAY;AAElD,SAAK,WAAW;AAChB,UAAM,KAAK,KAAK,QAAQ,KAAK,OAAO,IAAI;AACxC,SAAK,oBAAoB,IAAI,sBAAsB,KAAK,KAAK,gBAAgB;AAAA,EAC/E;AAAA,EAEA,MAAM,aAA4B;AAChC,UAAM,KAAK,KAAK,WAAW;AAAA,EAC7B;AAAA,EAEA,IAAI,QAAsE;AACxE,YAAQ,KAAK,KAAK,OAAO;AAAA,MACvB,KAAK,gBAAgB;AAAW,eAAO;AAAA,MACvC,KAAK,gBAAgB;AAAY,eAAO;AAAA,MACxC,KAAK,gBAAgB;AAAc,eAAO;AAAA,MAC1C;AAAS,eAAO;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,IAAI,mBAA0C;AAAE,WAAO,KAAK;AAAA,EAAmB;AAAA,EAE/E,IAAI,eAA8C;AAChD,UAAM,MAAM,oBAAI,IAA8B;AAC9C,SAAK,KAAK,mBAAmB,QAAQ,CAAC,GAAG,OAAO,IAAI,IAAI,IAAI,eAAe,CAAC,CAAC,CAAC;AAC9E,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,iBAAqC;AACvC,WAAO,KAAK,KAAK,eAAe,IAAI,cAAc;AAAA,EACpD;AAAA,EAEA,IAAI,OAAe;AAAE,WAAO,KAAK,KAAK;AAAA,EAAM;AAAA,EAC5C,IAAI,kBAA0B;AAAE,WAAO,KAAK,KAAK;AAAA,EAAiB;AAAA,EAClE,IAAI,cAAuB;AAAE,WAAO,KAAK,KAAK;AAAA,EAAa;AAAA;AAAA,EAG3D,GAAG,OAAuB,UAA+B;AACvD,QAAI,CAAC,KAAK,UAAU,IAAI,KAAK,EAAG,MAAK,UAAU,IAAI,OAAO,oBAAI,IAAI,CAAC;AACnE,SAAK,UAAU,IAAI,KAAK,EAAG,IAAI,QAAQ;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,OAAuB,UAA+B;AACxD,SAAK,UAAU,IAAI,KAAK,GAAG,OAAO,QAAQ;AAC1C,WAAO;AAAA,EACT;AAAA,EAEQ,KAAK,UAA0B,MAAa;AAClD,SAAK,UAAU,IAAI,KAAK,GAAG,QAAQ,QAAM,GAAG,GAAG,IAAI,CAAC;AAAA,EACtD;AAAA;AAAA,EAGA,MAAM,aAAa,UAAiC;AAClD,UAAM,KAAK,KAAK,mBAAmB,cAAc,QAAQ;AAAA,EAC3D;AAAA,EACA,MAAM,iBAAiB,UAAiC;AACtD,UAAM,KAAK,KAAK,mBAAmB,cAAc,QAAQ;AAAA,EAC3D;AAAA,EACA,MAAM,cAAc,UAAiC;AACnD,UAAM,KAAK,KAAK,mBAAmB,eAAe,QAAQ;AAAA,EAC5D;AAAA;AAAA,EAGA,aAAa,aAAyC;AACpD,WAAO,UAAU,aAAa,iBAAiB;AAAA,EACjD;AAAA,EACA,aAAa,aAAyC;AACpD,YAAQ,MAAM,WAAU,WAAW,GAAG,OAAO,OAAK,EAAE,SAAS,YAAY;AAAA,EAC3E;AAAA,EACA,aAAa,iBAA6C;AACxD,YAAQ,MAAM,WAAU,WAAW,GAAG,OAAO,OAAK,EAAE,SAAS,YAAY;AAAA,EAC3E;AAAA,EACA,aAAa,cAA0C;AACrD,YAAQ,MAAM,WAAU,WAAW,GAAG,OAAO,OAAK,EAAE,SAAS,aAAa;AAAA,EAC5E;AAAA;AAAA,EAIQ,aAAa;AACnB,UAAM,IAAI,KAAK;AACf,MAAE,GAAG,UAAU,WAAW,MAAM,KAAK,KAAK,2BAAwB,CAAC;AACnE,MAAE,GAAG,UAAU,cAAc,MAAM,KAAK,KAAK,iCAA2B,CAAC;AACzE,MAAE,GAAG,UAAU,aAAa,MAAM,KAAK,KAAK,+BAA0B,CAAC;AACvE,MAAE,GAAG,UAAU,cAAc,CAAC,WAA8B,KAAK,KAAK,mCAA6B,MAAM,CAAC;AAC1G,MAAE,GAAG,UAAU,qBAAqB,MAAM,KAAK,KAAK,+CAAkC,CAAC;AACvF,MAAE,GAAG,UAAU,wBAAwB,CAAC,cAAuB,KAAK,KAAK,uDAAuC,SAAS,CAAC;AAE1H,MAAE,GAAG,UAAU,sBAAsB,CAAC,MACpC,KAAK,KAAK,6CAAkC,eAAe,CAAC,CAAC,CAAC;AAChE,MAAE,GAAG,UAAU,yBAAyB,CAAC,MACvC,KAAK,KAAK,yCAAgC,eAAe,CAAC,CAAC,CAAC;AAE9D,MAAE,GAAG,UAAU,iBAAiB,CAAC,OAAoB,KAA6B,MAChF,KAAK,KAAK,yCAAgC,MAAM,kBAAkB,eAAe,CAAC,GAAG,UAAU,IAAI,MAAM,CAAC,CAAC;AAC7G,MAAE,GAAG,UAAU,mBAAmB,CAAC,OAAoB,KAA6B,MAClF,KAAK,KAAK,6CAAkC,MAAM,kBAAkB,eAAe,CAAC,GAAG,UAAU,IAAI,MAAM,CAAC,CAAC;AAE/G,MAAE,GAAG,UAAU,YAAY,CAAC,KAAuB,MACjD,KAAK,KAAK,+BAA2B,eAAe,CAAC,CAAC,CAAC;AACzD,MAAE,GAAG,UAAU,cAAc,CAAC,KAAuB,MACnD,KAAK,KAAK,mCAA6B,eAAe,CAAC,CAAC,CAAC;AAE3D,MAAE,GAAG,UAAU,uBAAuB,CAAC,aACrC,KAAK,KAAK,qDAAsC,SAAS,IAAI,cAAc,CAAC,CAAC;AAE/E,MAAE,GAAG,UAAU,cAAc,CAAC,MAAkB,MAC9C,KAAK,KAAK,mCAA6B,MAAM,IAAI,eAAe,CAAC,IAAI,MAAS,CAAC;AAAA,EACnF;AACF;;;AC3SA,IAAM,oBAAoB;AAC1B,IAAM,kBAAkB;AACxB,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB;AAiC5B,SAAS,sBAA4B;AACnC,MAAI,OAAO,cAAc,eAAe,EAAE,mBAAmB,YAAY;AACvE,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,MAAI,OAAO,WAAW,eAAe,EAAE,iBAAiB,SAAS;AAC/D,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACF;AAEA,SAAS,uBAAuB,OAA4B;AAC1D,QAAM,UAAU,IAAI,QAAQ,IAAK,MAAM,SAAS,KAAM,CAAC;AACvD,QAAM,UAAU,QAAQ,SAAS,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AACrE,QAAM,MAAM,KAAK,MAAM;AACvB,QAAM,SAAS,IAAI,YAAY,IAAI,MAAM;AACzC,QAAM,OAAO,IAAI,WAAW,MAAM;AAClC,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,SAAK,CAAC,IAAI,IAAI,WAAW,CAAC;AAAA,EAC5B;AACA,SAAO;AACT;AAEA,SAAS,uBAAuB,QAAgD;AAC9E,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,QAAQ,IAAI,WAAW,MAAM;AACnC,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,cAAU,OAAO,aAAa,MAAM,CAAC,CAAC;AAAA,EACxC;AACA,SAAO,KAAK,MAAM,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AAC/E;AAEA,SAAS,aAAqB;AAC5B,QAAM,IAAI,OAAO,WAAW,cAAc,SAAS;AACnD,MAAI,KAAK,OAAO,EAAE,eAAe,YAAY;AAC3C,WAAO,EAAE,WAAW;AAAA,EACtB;AACA,QAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,MAAI,KAAK,OAAO,EAAE,oBAAoB,YAAY;AAChD,MAAE,gBAAgB,KAAK;AAAA,EACzB,OAAO;AACL,aAAS,IAAI,GAAG,IAAI,IAAI,IAAK,OAAM,CAAC,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAAA,EACxE;AACA,QAAM,CAAC,IAAK,MAAM,CAAC,IAAI,KAAQ;AAC/B,QAAM,CAAC,IAAK,MAAM,CAAC,IAAI,KAAQ;AAC/B,QAAM,MAAM,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAC7E,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC;AAC1G;AAEA,SAAS,iBACP,QACA,WACe;AACf,MAAI,UAAW,QAAO;AACtB,MAAI,OAAQ,QAAO;AACnB,MAAI;AACF,UAAM,SAAS,OAAO,aAAa,QAAQ,mBAAmB;AAC9D,QAAI,OAAQ,QAAO;AACnB,UAAM,QAAQ,WAAW;AACzB,WAAO,aAAa,QAAQ,qBAAqB,KAAK;AACtD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO,WAAW;AAAA,EACpB;AACF;AAEA,eAAe,oBAAoB,UAAmC;AACpE,QAAM,MAAM,MAAM,MAAM,GAAG,QAAQ,qBAAqB;AAAA,IACtD,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,SAAS,EAAE,QAAQ,mBAAmB;AAAA,EACxC,CAAC;AACD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,qCAAqC,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,EACrF;AACA,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,MAAI,CAAC,QAAQ,OAAO,KAAK,cAAc,YAAY,KAAK,UAAU,WAAW,GAAG;AAC9E,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,SAAO,KAAK;AACd;AAEA,SAAS,YAAY,KAA2D;AAC9E,SAAO;AAAA,IACL,QAAQ,uBAAuB,IAAI,OAAO,QAAQ,CAAC;AAAA,IACnD,MAAM,uBAAuB,IAAI,OAAO,MAAM,CAAC;AAAA,EACjD;AACF;AAEA,eAAsB,aACpB,OAA4B,CAAC,GACA;AAC7B,sBAAoB;AAEpB,QAAM,WAAW,KAAK,YAAY;AAClC,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,SAAS,KAAK,UAAU,CAAC;AAC/B,QAAM,SAAS,KAAK,UAAU;AAC9B,QAAM,YAAY,iBAAiB,QAAQ,KAAK,SAAS;AAIzD,QAAM,UAAU,IAAI;AAAA,IAAe,CAAC,GAAG,WACrC;AAAA,MACE,MAAM,OAAO,IAAI,MAAM,gCAAgC,mBAAmB,IAAI,CAAC;AAAA,MAC/E;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,YAAyC;AACrD,UAAM,YAAY,MAAM,oBAAoB,QAAQ;AAMpD,UAAM,eAAe,MAAM,UAAU,cAAc,SAAS,MAAM;AAElE,UAAM,WAAW,MAAM,aAAa,YAAY,gBAAgB;AAChE,UAAM,eACJ,YACC,MAAM,aAAa,YAAY,UAAU;AAAA,MACxC,iBAAiB;AAAA,MACjB,sBAAsB,uBAAuB,SAAS;AAAA,IACxD,CAAC;AAEH,UAAM,EAAE,QAAQ,KAAK,IAAI,YAAY,YAAY;AAEjD,UAAM,MAAM,MAAM,MAAM,GAAG,QAAQ,cAAc;AAAA,MAC/C,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,SAAS,EAAE,gBAAgB,oBAAoB,QAAQ,mBAAmB;AAAA,MAC1E,MAAM,KAAK,UAAU;AAAA,QACnB,UAAU;AAAA,QACV,UAAU,aAAa;AAAA,QACvB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAED,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,qBAAqB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,IACrE;AAEA,UAAM,QAAS,MAAM,IAAI,KAAK;AAC9B,QAAI,CAAC,SAAS,OAAO,MAAM,OAAO,YAAY,MAAM,GAAG,WAAW,GAAG;AACnE,YAAM,IAAI,MAAM,oCAAoC;AAAA,IACtD;AAEA,WAAO,EAAE,cAAc,gBAAgB,MAAM,GAAG;AAAA,EAClD,GAAG;AAEH,SAAO,QAAQ,KAAK,CAAC,MAAM,OAAO,CAAC;AACrC;AAEA,eAAsB,eACpB,gBACA,OAA8B,CAAC,GAChB;AACf,MAAI,CAAC,gBAAgB;AACnB,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC9C;AACA,QAAM,WAAW,KAAK,YAAY;AAElC,QAAM,MAAM,MAAM,MAAM,GAAG,QAAQ,gBAAgB;AAAA,IACjD,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,EAAE,eAAe,CAAC;AAAA,EACzC,CAAC;AAED,MAAI,CAAC,IAAI,MAAM,IAAI,WAAW,KAAK;AACjC,UAAM,IAAI,MAAM,uBAAuB,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,EACvE;AACF;AAgCO,SAAS,aAAa,QAAuB,QAAsB;AACxE,QAAM,aAAa,kBAAkB,OAAO,SAAS,IAAI,KAAK,MAAM;AACpE,MAAI,OAAO,MAAM,WAAW,QAAQ,CAAC,GAAG;AACtC,UAAM,IAAI,MAAM,iCAAiC,OAAO,MAAM,CAAC,GAAG;AAAA,EACpE;AAEA,QAAM,QAAQ,yBAAyB,KAAK,OAAO,KAAK,CAAC;AACzD,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR,iCAAiC,MAAM;AAAA,IACzC;AAAA,EACF;AAEA,QAAM,SAAS,OAAO,MAAM,CAAC,CAAC;AAC9B,QAAM,OAAO,MAAM,CAAC,EAAE,YAAY;AAClC,QAAM,UAAkC;AAAA,IACtC,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACA,SAAO,IAAI,KAAK,WAAW,QAAQ,IAAI,SAAS,QAAQ,IAAI,CAAC;AAC/D;;;AC/PA,SAAS,cAAc;AA+FvB,SAAS,SAAS,OAAyB;AACzC,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,QAAQ;AACnD,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,UAAM,MAA+B,CAAC;AACtC,eAAW,KAAK,OAAO,KAAK,KAAgC,EAAE,KAAK,GAAG;AACpE,UAAI,CAAC,IAAI,SAAU,MAAkC,CAAC,CAAC;AAAA,IACzD;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAOA,SAAS,cAAc,OAAwB;AAC7C,SAAO,KAAK,UAAU,SAAS,KAAK,CAAC;AACvC;AAGA,SAAS,eAAe,OAAuB;AAC7C,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,KAAK;AAC5C,QAAM,OAAO,OAAO,KAAK;AACzB,SAAO,MAAM,KAAK,KAAK,MAAM,GAAG,CAAC,CAAC,EAC/B,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AACZ;AAMA,SAAS,gBAAgB,MAA6B;AACpD,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,KAAK;AAAA;AAAA,IACd,KAAK;AAAA,IACL,KAAK,UAAU;AAGb,YAAM,MAAO,KAAkC,UAAU;AACzD,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AACH,aAAO;AAAA,IACT,SAAS;AACP,YAAM,WAAkB;AACxB,YAAM,IAAI,MAAM,2BAA4B,SAA8B,IAAI,EAAE;AAAA,IAClF;AAAA,EACF;AACF;AAYO,SAAS,OAAO,QAAgB,MAA6B;AAClE,QAAM,UAAU,eAAe,MAAM;AAIrC,QAAM,cAAc,eAAe,cAAc,IAAI,CAAC;AACtD,QAAM,MAAM,gBAAgB,IAAI;AAChC,SAAO,aAAa,OAAO,IAAI,WAAW,IAAI,GAAG;AACnD;AAGO,IAAM,aAAa;AAAA,EACxB;AACF;;;ACnBA;AA7GA,IAAI,iBAAuC;AAwCpC,SAAS,YAAY,SAGf;AAEX,MAAI,gBAAgB;AAClB,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,eAAe,aAAa;AAErC,QAAI,WAAW,UAAU;AACvB,cAAQ,IAAI,4CAA4C;AACxD,uBAAiB,WAAW;AAC5B,aAAO;AAAA,IACT;AAGA,QAAI,WAAW,sBAAsB;AACnC,cAAQ,IAAI,oCAAoC;AAChD,uBAAiB,WAAW;AAC5B,aAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,eAAe,SAAS,gBAAgB,QAAQ,IAAI,wBAAwB;AAClF,QAAM,SAAS,SAAS,UAAU,QAAQ,IAAI,oBAAoB;AAElE,UAAQ,IAAI,yCAAyC,YAAY,EAAE;AACnE,mBAAiB,mBAAmB,cAAc,MAAM;AAGxD,MAAI,OAAO,eAAe,aAAa;AACrC,eAAW,uBAAuB;AAAA,EACpC;AAEA,SAAO;AACT;AAuBO,SAAS,qBAA2B;AACzC,mBAAiB;AACjB,MAAI,OAAO,eAAe,aAAa;AACrC,eAAW,uBAAuB;AAAA,EACpC;AACF;","names":["getRequestAuthHeader","getCurrentRequestStore","MediaRoomEvent"]}
1
+ {"version":3,"sources":["../src/request-scope.ts","../src/media.ts","../src/remote-client.ts","../src/ren.ts","../src/realtime.ts","../src/media-room.ts","../src/push.ts","../src/transforms.ts","../src/index.ts"],"sourcesContent":["/**\n * Per-request scope for the SDK's remote client. Mirrors the runtime's\n * `REQUEST_CTX` (a `tokio::task_local!` in Rust) so that\n * `platform.auth.setCurrentUser(token)`, `getCurrentUser()`, and `can()`\n * — plus future per-request state like the Layer-2 policy toggle —\n * have a place to live when the SDK is running outside the runtime\n * (Vite SSR, Node.js HTTP servers, edge workers that expose Node APIs).\n *\n * Implementation: Node's `AsyncLocalStorage`. Tenant code wraps each\n * inbound request with `runWithRequest(async () => { ... })` so the\n * store stays scoped to the request's async chain. `setCurrentUser`\n * / `can` read and write that store; if a tenant forgets to wrap, the\n * methods either no-op (set) or throw a clear error (get/can).\n */\n\nimport type { AuthCaller, AuthUser } from './types.js';\n\nexport interface RequestStore {\n /** Bound access-token JWT (set by `auth.setCurrentUser`). */\n token?: string;\n /** Bound user (cached so `getCurrentUser` doesn't re-validate). */\n user?: AuthUser;\n /** Whether Layer-2 policy enforcement is enabled for this request. */\n policyEnabled: boolean;\n}\n\n// Lazy-loaded so this module is safe to import in non-Node environments\n// (browsers, edge workers) where `node:async_hooks` doesn't exist. Calls\n// to runWithRequest in those environments fall back to a synchronous\n// no-op scope (the fn just runs `fn()`).\nlet alsImpl: { run: (s: RequestStore, fn: () => any) => any; getStore: () => RequestStore | undefined } | null = null;\n\nasync function ensureAls() {\n if (alsImpl) return alsImpl;\n try {\n // Dynamic import keeps non-Node environments from crashing at module\n // load time. `node:async_hooks` is unconditionally available in Node.\n const { AsyncLocalStorage } = await import('node:async_hooks');\n const inner = new AsyncLocalStorage<RequestStore>();\n alsImpl = {\n run: (s, fn) => inner.run(s, fn),\n getStore: () => inner.getStore(),\n };\n } catch {\n // Non-Node: stub. Note that without ALS, concurrent requests will\n // share the same `cachedStore`, which is wrong — but in non-Node\n // SDK environments the per-request use case typically doesn't\n // apply (browser code is single-threaded per page).\n let cached: RequestStore | undefined;\n alsImpl = {\n run: (s, fn) => {\n const prev = cached;\n cached = s;\n try {\n return fn();\n } finally {\n cached = prev;\n }\n },\n getStore: () => cached,\n };\n }\n return alsImpl;\n}\n\n/**\n * Wrap a function in a fresh request scope. **Rarely needed** — the\n * Maravilla Vite plugin (`@maravilla-labs/vite-plugin`) auto-opens a\n * scope around every inbound dev HTTP request, so tenant code\n * (SvelteKit `hooks.server.ts`, RR/Remix loaders, etc.) reaches\n * `setCurrentUser/getCurrentUser/can` with a scope already active.\n *\n * Reach for `runWithRequest` only when the SDK runs **outside** an\n * HTTP request: standalone Node scripts, test fixtures, custom\n * servers that don't go through Vite. Inside an active scope,\n * `platform.auth.setCurrentUser/getCurrentUser/can` operate on a\n * per-request store keyed by Node's `AsyncLocalStorage`.\n *\n * @example\n * ```ts\n * // Test fixture that needs to bind a user before exercising the SDK\n * await runWithRequest(async () => {\n * await getPlatform().auth.setCurrentUser(testToken);\n * const result = await getPlatform().env.DB.find('users', {});\n * expect(result).toEqual(...);\n * });\n * ```\n */\nexport async function runWithRequest<T>(fn: () => Promise<T> | T): Promise<T> {\n const als = await ensureAls();\n return als.run({ policyEnabled: true }, () => Promise.resolve(fn())) as Promise<T>;\n}\n\n/**\n * Read the current request's store, if any. Returns undefined when\n * called outside a `runWithRequest` scope. Used by `RemoteAuthService`\n * and (future) other Remote* services to source per-request state.\n *\n * Note: the `als` may not yet be initialised when this is called; in\n * that case the function returns undefined synchronously. Subsequent\n * `runWithRequest` calls will populate it.\n */\nexport function getCurrentRequestStore(): RequestStore | undefined {\n return alsImpl?.getStore();\n}\n\n/**\n * Construct an anonymous `AuthCaller` snapshot — used by\n * `auth.getCurrentUser()` when no identity is bound.\n */\nexport function anonymousCaller(): AuthCaller {\n return {\n user_id: '',\n email: '',\n is_admin: false,\n roles: [],\n is_anonymous: true,\n };\n}\n\n/**\n * Return `Authorization: Bearer <token>` if a token is bound in the\n * current request store, else an empty object. Every Remote* service's\n * fetch helper merges this so dev-server can identify the caller and\n * (eventually) enforce Layer-2 policies on KV/DB/Storage ops.\n *\n * Synchronous so it can be called from inside `headers: { ... }`\n * literals without forcing each fetch helper to be re-shaped.\n */\nexport function getRequestAuthHeader(): Record<string, string> {\n const token = alsImpl?.getStore()?.token;\n return token ? { Authorization: `Bearer ${token}` } : {};\n}\n","/**\n * Media service for video/audio room management.\n *\n * In production (Deno runtime) calls go through `Deno.core.ops`.\n * In development they are proxied as HTTP requests to the dev-server.\n */\n\n// ── Types ────────────────────────────────────────────────────────────\n\nexport interface MediaRoomInfo {\n name: string;\n numParticipants: number;\n maxParticipants: number;\n createdAt: number;\n active: boolean;\n}\n\nexport interface MediaRoomInfoSettings {\n maxParticipants?: number;\n emptyTimeoutSecs?: number;\n}\n\nexport interface MediaParticipantInfo {\n identity: string;\n name: string;\n canPublish?: boolean;\n canSubscribe?: boolean;\n canPublishData?: boolean;\n}\n\nexport interface MediaTokenResult {\n token: string;\n url: string;\n}\n\nexport interface MediaService {\n createRoom(roomId: string, settings?: MediaRoomInfoSettings): Promise<MediaRoomInfo>;\n deleteRoom(roomId: string): Promise<void>;\n listRooms(): Promise<MediaRoomInfo[]>;\n generateToken(roomId: string, participant: MediaParticipantInfo): Promise<MediaTokenResult>;\n mediaUrl(): Promise<string | null>;\n}\n\n// ── Remote (dev-server) implementation ───────────────────────────────\n\nexport class RemoteMediaService implements MediaService {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>,\n ) {}\n\n private async fetch(url: string, options: RequestInit = {}) {\n const { getRequestAuthHeader } = await import('./request-scope.js');\n const response = await fetch(url, {\n ...options,\n headers: { ...this.headers, ...getRequestAuthHeader(), ...options.headers },\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Media API error: ${response.status} - ${error}`);\n }\n\n return response;\n }\n\n async createRoom(roomId: string, settings: MediaRoomInfoSettings = {}): Promise<MediaRoomInfo> {\n const response = await this.fetch(`${this.baseUrl}/api/media/rooms`, {\n method: 'POST',\n body: JSON.stringify({ roomId, settings }),\n });\n return response.json() as Promise<MediaRoomInfo>;\n }\n\n async deleteRoom(roomId: string): Promise<void> {\n await this.fetch(`${this.baseUrl}/api/media/rooms/${encodeURIComponent(roomId)}`, {\n method: 'DELETE',\n });\n }\n\n async listRooms(): Promise<MediaRoomInfo[]> {\n const response = await this.fetch(`${this.baseUrl}/api/media/rooms`);\n return response.json() as Promise<MediaRoomInfo[]>;\n }\n\n async generateToken(roomId: string, participant: MediaParticipantInfo): Promise<MediaTokenResult> {\n const response = await this.fetch(\n `${this.baseUrl}/api/media/rooms/${encodeURIComponent(roomId)}/token`,\n {\n method: 'POST',\n body: JSON.stringify(participant),\n },\n );\n return response.json() as Promise<MediaTokenResult>;\n }\n\n async mediaUrl(): Promise<string | null> {\n const response = await this.fetch(`${this.baseUrl}/api/media/url`);\n const data = (await response.json()) as { url: string | null };\n return data.url;\n }\n}\n","import type { KvNamespace, KvListResult, Database, DbFindOptions, Storage, RealtimeService, PresenceService, AuthService, AuthCaller, AuthUser, AuthSession, AuthField, RegisterOptions, LoginOptions, UserListFilter, UserListResponse, UpdateUserOptions, PolicyService, VectorIndexSpec, VectorIndexDescriptor, VectorQueryWithFilter, VectorSearchHit, IndexSpec, IndexDescriptor, Workflows, WorkflowHandle, WorkflowRun, WorkflowStepRecord } from './types.js';\nimport type { TransformsService, TranscodeOpts, ThumbnailOpts, ResizeOpts, OcrOpts, JobHandle, JobStatusResponse, MediaInfo } from './transforms.js';\nimport { RemoteMediaService } from './media.js';\nimport { getRequestAuthHeader } from './request-scope.js';\n\n/**\n * Remote KV namespace implementation that communicates with a development server.\n * This class provides the KV interface by making HTTP requests to the dev server.\n * \n * @internal\n */\nclass RemoteKvNamespace implements KvNamespace {\n constructor(\n private baseUrl: string,\n private namespace: string,\n private headers: Record<string, string>\n ) {}\n\n /**\n * Internal method for making HTTP requests to the dev server.\n * Handles error responses and authentication headers.\n * \n * @internal\n */\n private async fetch(url: string, options: RequestInit = {}) {\n const response = await fetch(url, {\n ...options,\n headers: { ...this.headers, ...getRequestAuthHeader(), ...options.headers },\n });\n\n if (!response.ok && response.status !== 404) {\n const error = await response.text();\n throw new Error(`Platform API error: ${response.status} - ${error}`);\n }\n\n return response;\n }\n\n async get(key: string): Promise<any> {\n const response = await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}/${key}`);\n if (response.status === 404) return null;\n return response.json();\n }\n\n async put(key: string, value: any, options?: { expirationTtl?: number }): Promise<void> {\n const headers: Record<string, string> = {};\n if (options?.expirationTtl) {\n headers['X-TTL'] = options.expirationTtl.toString();\n }\n\n await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}/${key}`, {\n method: 'PUT',\n headers,\n body: JSON.stringify(value),\n });\n }\n\n async delete(key: string): Promise<void> {\n await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}/${key}`, {\n method: 'DELETE',\n });\n }\n\n async list(options?: { prefix?: string; limit?: number; cursor?: string }): Promise<KvListResult> {\n const response = await this.fetch(`${this.baseUrl}/api/kv/${this.namespace}`, {\n method: 'POST',\n body: JSON.stringify(options || {}),\n });\n const data = await response.json() as any;\n return {\n keys: data.result || [],\n list_complete: !data.result_info?.cursor,\n cursor: data.result_info?.cursor,\n };\n }\n}\n\n/**\n * Remote Database implementation that communicates with a development server.\n * This class provides the Database interface by making HTTP requests to the dev server.\n * \n * @internal\n */\nclass RemoteDatabase implements Database {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>\n ) {}\n\n /**\n * Internal method for making HTTP requests to the dev server.\n * Handles error responses and authentication headers.\n * \n * @internal\n */\n private async fetch(url: string, options: RequestInit = {}) {\n const response = await fetch(url, {\n ...options,\n headers: { ...this.headers, ...getRequestAuthHeader(), ...options.headers },\n });\n\n if (!response.ok && response.status !== 404) {\n const error = await response.text();\n throw new Error(`Platform API error: ${response.status} - ${error}`);\n }\n\n return response;\n }\n\n async find(collection: string, filter: any = {}, options: DbFindOptions = {}): Promise<any[]> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}`, {\n method: 'POST',\n body: JSON.stringify({ filter, options }),\n });\n return response.json() as Promise<any[]>;\n }\n\n async findOne(collection: string, filter: any): Promise<any | null> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/findOne`, {\n method: 'POST',\n body: JSON.stringify(filter),\n });\n if (response.status === 404) return null;\n return response.json();\n }\n\n async insertOne(collection: string, document: any): Promise<string> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}`, {\n method: 'PUT',\n body: JSON.stringify(document),\n });\n const result = await response.json() as any;\n return result.id;\n }\n\n async updateOne(collection: string, filter: any, update: any): Promise<{ modified: number }> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/update`, {\n method: 'POST',\n body: JSON.stringify({ filter, update }),\n });\n return response.json() as Promise<{ modified: number }>;\n }\n\n async deleteOne(collection: string, filter: any): Promise<{ deleted: number }> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/delete`, {\n method: 'DELETE',\n body: JSON.stringify(filter),\n });\n return response.json() as Promise<{ deleted: number }>;\n }\n\n async deleteMany(collection: string, filter: any): Promise<{ deleted: number }> {\n // For now, deleteMany is the same as deleteOne in the remote client\n // This would need to be implemented properly in the dev server\n return this.deleteOne(collection, filter);\n }\n\n async createVectorIndex(collection: string, spec: VectorIndexSpec): Promise<void> {\n await this.fetch(`${this.baseUrl}/api/db/${collection}/vectorIndexes`, {\n method: 'POST',\n body: JSON.stringify(spec),\n });\n }\n\n async dropVectorIndex(collection: string, field: string): Promise<{ removed: boolean }> {\n const response = await this.fetch(\n `${this.baseUrl}/api/db/${collection}/vectorIndexes/${encodeURIComponent(field)}`,\n { method: 'DELETE' },\n );\n return response.json() as Promise<{ removed: boolean }>;\n }\n\n async listVectorIndexes(collection: string): Promise<VectorIndexDescriptor[]> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/vectorIndexes`, {\n method: 'GET',\n });\n return response.json() as Promise<VectorIndexDescriptor[]>;\n }\n\n async findSimilar(collection: string, query: VectorQueryWithFilter): Promise<VectorSearchHit[]> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/vectorSearch`, {\n method: 'POST',\n body: JSON.stringify(query),\n });\n return response.json() as Promise<VectorSearchHit[]>;\n }\n\n async createIndex(collection: string, spec: IndexSpec): Promise<IndexDescriptor> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/indexes`, {\n method: 'POST',\n body: JSON.stringify(spec),\n });\n return response.json() as Promise<IndexDescriptor>;\n }\n\n async dropIndex(collection: string, name: string): Promise<{ removed: boolean }> {\n const response = await this.fetch(\n `${this.baseUrl}/api/db/${collection}/indexes/${encodeURIComponent(name)}`,\n { method: 'DELETE' },\n );\n return response.json() as Promise<{ removed: boolean }>;\n }\n\n async listIndexes(collection: string): Promise<IndexDescriptor[]> {\n const response = await this.fetch(`${this.baseUrl}/api/db/${collection}/indexes`, {\n method: 'GET',\n });\n return response.json() as Promise<IndexDescriptor[]>;\n }\n}\n\n/**\n * Remote Storage implementation that communicates with a development server.\n * This class provides the Storage interface by making HTTP requests to the dev server.\n * \n * @internal\n */\nclass RemoteStorage implements Storage {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>\n ) {}\n\n /**\n * Internal method for making HTTP requests to the dev server.\n * Handles error responses and authentication headers.\n * \n * @internal\n */\n private async fetch(url: string, options: RequestInit = {}) {\n const response = await fetch(url, {\n ...options,\n headers: { ...this.headers, ...getRequestAuthHeader(), ...options.headers },\n });\n\n if (!response.ok && response.status !== 404) {\n const error = await response.text();\n throw new Error(`Platform API error: ${response.status} - ${error}`);\n }\n\n return response;\n }\n\n async generateUploadUrl(key: string, contentType: string, options?: { sizeLimit?: number }): Promise<{\n url: string;\n method: string;\n headers: Record<string, string>;\n expiresIn: number;\n }> {\n // Pre-flight Layer-2 gate: dev-server runs the bucket policy with\n // `action: \"upload-url\"` and returns the upload URL on success\n // (or 403 on denial). Mirrors prod's\n // platform.storage.generateUploadUrl behaviour.\n const res = await this.fetch(`${this.baseUrl}/api/storage/upload-url`, {\n method: 'POST',\n body: JSON.stringify({ key, content_type: contentType, size_limit: options?.sizeLimit }),\n });\n const data = (await res.json()) as { url: string; method: string; headers: Record<string, string>; expiresIn: number };\n // The dev-server returns a relative URL; absolutise it. Prepend\n // tenant headers so direct PUTs by the caller still carry the\n // X-Tenant-Id (Authorization will be re-added at fetch time by\n // getRequestAuthHeader if a request scope is bound).\n return {\n url: data.url.startsWith('http') ? data.url : `${this.baseUrl}${data.url}`,\n method: data.method,\n headers: { ...data.headers, ...this.headers },\n expiresIn: data.expiresIn,\n };\n }\n\n async generateDownloadUrl(key: string, options?: { expiresIn?: number }): Promise<{\n url: string;\n method: string;\n headers: Record<string, string>;\n expiresIn: number;\n }> {\n const res = await this.fetch(`${this.baseUrl}/api/storage/download-url`, {\n method: 'POST',\n body: JSON.stringify({ key, expires_in: options?.expiresIn }),\n });\n const data = (await res.json()) as { url: string; method: string; headers: Record<string, string>; expiresIn: number };\n return {\n url: data.url.startsWith('http') ? data.url : `${this.baseUrl}${data.url}`,\n method: data.method,\n headers: data.headers,\n expiresIn: data.expiresIn,\n };\n }\n\n // Dev-mode: emit the same `/_assets/<key>` shape production does.\n // Dev-server's /_assets/* handler streams from the same dir\n // STORAGE.put writes to (`{project_root}/.maravilla/storage`), so user\n // JS paths render and load identically across dev and prod.\n // No signing in dev — `expires`/`sig` query params are accepted and\n // ignored by the dev-server handler.\n getAssetUrl(key: string, _opts?: { signed?: boolean; ttl?: number }): string {\n const clean = key.replace(/^\\/+/, '');\n return `${this.baseUrl}/_assets/${clean}`;\n }\n\n async get(key: string): Promise<Uint8Array | null> {\n const response = await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`);\n if (response.status === 404) return null;\n const arrayBuffer = await response.arrayBuffer();\n return new Uint8Array(arrayBuffer);\n }\n\n async put(key: string, data: Uint8Array | string, metadata?: any): Promise<void> {\n // Convert string to Uint8Array if needed\n const bodyData = typeof data === 'string' \n ? new TextEncoder().encode(data)\n : data;\n\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'PUT',\n headers: metadata ? { 'X-Metadata': JSON.stringify(metadata) } : {},\n // Cast because TypeScript's lib.dom.d.ts BodyInit union sometimes misses Uint8Array\n body: bodyData as any,\n });\n }\n\n async putStream(key: string, source: any, metadata?: any): Promise<void> {\n // If it's a Blob we can send directly\n if (typeof Blob !== 'undefined' && source instanceof Blob) {\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'PUT',\n headers: {\n ...(metadata ? { 'X-Metadata': JSON.stringify(metadata) } : {}),\n 'Content-Type': source.type || 'application/octet-stream'\n },\n body: source as any,\n });\n return;\n }\n\n // ReadableStream\n if (source && typeof source.getReader === 'function') {\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'PUT',\n headers: metadata ? { 'X-Metadata': JSON.stringify(metadata) } : {},\n body: source as any,\n });\n return;\n }\n\n // Async iterable -> wrap in ReadableStream\n if (Symbol.asyncIterator in Object(source ?? {})) {\n const asyncIt = source as AsyncIterable<any>;\n const stream = new ReadableStream({\n async pull(controller) {\n const { value, done } = await asyncIt[Symbol.asyncIterator]().next();\n if (done) { controller.close(); return; }\n controller.enqueue(RemoteStorage.normalizeChunk(value));\n }\n });\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'PUT',\n headers: metadata ? { 'X-Metadata': JSON.stringify(metadata) } : {},\n body: stream as any,\n });\n return;\n }\n\n // Synchronous iterable\n if (Symbol.iterator in Object(source ?? {})) {\n const it = (source as Iterable<any>)[Symbol.iterator]();\n const stream = new ReadableStream({\n pull(controller) {\n const res = it.next();\n if (res.done) { controller.close(); return; }\n controller.enqueue(RemoteStorage.normalizeChunk(res.value));\n }\n });\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'PUT',\n headers: metadata ? { 'X-Metadata': JSON.stringify(metadata) } : {},\n body: stream as any,\n });\n return;\n }\n\n // Fallback: primitive/string/Uint8Array/ArrayBuffer\n await this.put(key, RemoteStorage.normalizeChunk(source), metadata);\n }\n private static normalizeChunk(c: any): Uint8Array {\n if (c == null) return new Uint8Array();\n if (typeof c === 'string') return new TextEncoder().encode(c);\n if (c instanceof Uint8Array) return c;\n if (c instanceof ArrayBuffer) return new Uint8Array(c);\n if (Array.isArray(c)) return Uint8Array.from(c);\n throw new Error('Unsupported chunk type in putStream');\n }\n async delete(key: string): Promise<void> {\n await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}`, {\n method: 'DELETE',\n });\n }\n\n async list(options?: { prefix?: string; limit?: number }): Promise<Array<{\n key: string;\n size: number;\n lastModified: string;\n metadata?: any;\n }>> {\n const params = new URLSearchParams();\n if (options?.prefix) params.set('prefix', options.prefix);\n if (options?.limit) params.set('limit', options.limit.toString());\n\n const response = await this.fetch(`${this.baseUrl}/api/storage?${params}`);\n return response.json();\n }\n\n async getMetadata(key: string): Promise<{\n size: number;\n contentType?: string;\n lastModified: string;\n metadata?: any;\n } | null> {\n const response = await this.fetch(`${this.baseUrl}/api/storage/${encodeURIComponent(key)}/metadata`);\n if (response.status === 404) return null;\n return response.json();\n }\n\n async confirm(key: string): Promise<void> {\n // Mirrors the dev-server route registered in\n // `crates/dev-server/src/router.rs`:\n // POST /api/storage/confirm body: { key: \"...\" }\n // The handler verifies the object actually landed in the backing store\n // and publishes the synthesized `storage.put` RenEvent that any\n // registered handlers (including those synthesized from a `transforms`\n // config block) react to.\n await this.fetch(`${this.baseUrl}/api/storage/confirm`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ key }),\n });\n }\n}\n\n/**\n * Remote Realtime service for development — calls dev server HTTP endpoints.\n * @internal\n */\nclass RemotePresenceService implements PresenceService {\n constructor(private baseUrl: string, private headers: Record<string, string>) {}\n\n async join(channel: string, userId: string, metadata?: any): Promise<boolean> {\n const res = await fetch(`${this.baseUrl}/api/realtime/presence/${encodeURIComponent(channel)}/join`, {\n method: 'POST',\n headers: { ...this.headers, ...getRequestAuthHeader() },\n body: JSON.stringify({ userId, metadata }),\n });\n const data = await res.json() as any;\n return data.isNew ?? true;\n }\n\n async leave(channel: string, userId: string): Promise<boolean> {\n const res = await fetch(`${this.baseUrl}/api/realtime/presence/${encodeURIComponent(channel)}/leave`, {\n method: 'POST',\n headers: { ...this.headers, ...getRequestAuthHeader() },\n body: JSON.stringify({ userId }),\n });\n const data = await res.json() as any;\n return data.wasPresent ?? true;\n }\n\n async members(channel: string): Promise<Array<{ userId: string; metadata?: any; lastSeen?: number }>> {\n const res = await fetch(`${this.baseUrl}/api/realtime/presence/${encodeURIComponent(channel)}`, {\n headers: { ...this.headers, ...getRequestAuthHeader() },\n });\n const data = await res.json() as any;\n return data.members ?? [];\n }\n}\n\nclass RemoteRealtimeService implements RealtimeService {\n presence: PresenceService;\n\n constructor(private baseUrl: string, private headers: Record<string, string>) {\n this.presence = new RemotePresenceService(baseUrl, headers);\n }\n\n async publish(channel: string, data: any, options?: { userId?: string }): Promise<void> {\n await fetch(`${this.baseUrl}/api/realtime/publish`, {\n method: 'POST',\n headers: { ...this.headers, ...getRequestAuthHeader() },\n body: JSON.stringify({ channel, data, userId: options?.userId }),\n });\n }\n\n async channels(): Promise<string[]> {\n const res = await fetch(`${this.baseUrl}/api/realtime/channels`, {\n headers: { ...this.headers, ...getRequestAuthHeader() },\n });\n const data = await res.json() as any;\n return data.channels ?? [];\n }\n}\n\n/**\n * Remote auth service for development environments.\n * Calls the dev-server's platform auth ops via HTTP.\n * @internal\n */\nclass RemoteAuthService implements AuthService {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>\n ) {}\n\n private async post(path: string, body?: any): Promise<any> {\n const res = await fetch(`${this.baseUrl}/api/platform/auth${path}`, {\n method: 'POST',\n headers: { ...this.headers, ...getRequestAuthHeader() },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Auth error (${res.status}): ${text}`);\n }\n if (res.status === 204) return undefined;\n return res.json();\n }\n\n async register(options: RegisterOptions): Promise<AuthUser> {\n return this.post('/register', options);\n }\n\n async login(options: LoginOptions): Promise<AuthSession> {\n return this.post('/login', options);\n }\n\n async validate(accessToken: string): Promise<AuthUser> {\n return this.post('/validate', { token: accessToken });\n }\n\n async refresh(refreshToken: string): Promise<AuthSession> {\n return this.post('/refresh', { token: refreshToken });\n }\n\n async logout(sessionId: string): Promise<void> {\n await this.post('/logout', { session_id: sessionId });\n }\n\n async getUser(userId: string): Promise<AuthUser | null> {\n return this.post('/get-user', { user_id: userId });\n }\n\n async listUsers(filter?: UserListFilter): Promise<UserListResponse> {\n return this.post('/list-users', filter ?? {});\n }\n\n async updateUser(userId: string, update: UpdateUserOptions): Promise<AuthUser> {\n return this.post('/update-user', { user_id: userId, ...update });\n }\n\n async deleteUser(userId: string): Promise<void> {\n await this.post('/delete-user', { user_id: userId });\n }\n\n async sendVerification(userId: string): Promise<{ token: string }> {\n return this.post('/send-verification', { user_id: userId });\n }\n\n async verifyEmail(token: string): Promise<void> {\n await this.post('/verify-email', { token });\n }\n\n async sendPasswordReset(email: string): Promise<{ token: string }> {\n return this.post('/send-password-reset', { email });\n }\n\n async resetPassword(token: string, newPassword: string): Promise<void> {\n await this.post('/reset-password', { token, new_password: newPassword });\n }\n\n async changePassword(userId: string, oldPassword: string, newPassword: string): Promise<void> {\n await this.post('/change-password', { user_id: userId, old_password: oldPassword, new_password: newPassword });\n }\n\n async getFieldConfig(): Promise<{ fields: AuthField[] }> {\n return this.post('/field-config');\n }\n\n async getOAuthUrl(provider: string, options?: { redirectUri?: string }): Promise<{ auth_url: string; state: string }> {\n return this.post('/oauth/start', { provider, redirect_uri: options?.redirectUri || `/_auth/callback/${provider}` });\n }\n\n async handleOAuthCallback(provider: string, params: { code: string; state: string }): Promise<any> {\n return this.post('/oauth/callback', { provider, code: params.code, state: params.state });\n }\n\n // ── Groups ──\n\n async createGroup(options: any): Promise<any> {\n return this.post('/groups/create', options);\n }\n async listGroups(): Promise<any[]> {\n return this.post('/groups/list', {});\n }\n async getGroup(groupId: string): Promise<any> {\n return this.post('/groups/get', { group_id: groupId });\n }\n async updateGroup(groupId: string, options: any): Promise<any> {\n return this.post('/groups/update', { group_id: groupId, ...options });\n }\n async deleteGroup(groupId: string): Promise<void> {\n await this.post('/groups/delete', { group_id: groupId });\n }\n async addUserToGroup(userId: string, groupId: string): Promise<void> {\n await this.post('/groups/add-user', { user_id: userId, group_id: groupId });\n }\n async removeUserFromGroup(userId: string, groupId: string): Promise<void> {\n await this.post('/groups/remove-user', { user_id: userId, group_id: groupId });\n }\n async getUserGroups(userId: string): Promise<any[]> {\n return this.post('/groups/get-user-groups', { user_id: userId });\n }\n async getGroupMembers(groupId: string): Promise<any[]> {\n return this.post('/groups/get-members', { group_id: groupId });\n }\n async getGroupPermissions(groupId: string): Promise<any[]> {\n return this.post('/groups/get-permissions', { group_id: groupId });\n }\n async setGroupPermissions(groupId: string, permissions: any[]): Promise<void> {\n await this.post('/groups/set-permissions', { group_id: groupId, permissions });\n }\n\n // ── Circles ──\n\n async createCircle(options: any): Promise<any> {\n return this.post('/circles/create', options);\n }\n async listCircles(): Promise<any[]> {\n return this.post('/circles/list', {});\n }\n async getCircle(circleId: string): Promise<any> {\n return this.post('/circles/get', { circle_id: circleId });\n }\n async updateCircle(circleId: string, options: any): Promise<any> {\n return this.post('/circles/update', { circle_id: circleId, ...options });\n }\n async deleteCircle(circleId: string): Promise<void> {\n await this.post('/circles/delete', { circle_id: circleId });\n }\n async addCircleMember(circleId: string, options: any): Promise<void> {\n await this.post('/circles/add-member', { circle_id: circleId, ...options });\n }\n async removeCircleMember(circleId: string, userId: string): Promise<void> {\n await this.post('/circles/remove-member', { circle_id: circleId, user_id: userId });\n }\n async getCircleMembers(circleId: string): Promise<any[]> {\n return this.post('/circles/get-members', { circle_id: circleId });\n }\n async getUserCircles(userId: string): Promise<any[]> {\n return this.post('/circles/get-user-circles', { user_id: userId });\n }\n\n // ── Resources ──\n\n async createResource(options: any): Promise<any> {\n return this.post('/resources/create', options);\n }\n async listResources(): Promise<any[]> {\n return this.post('/resources/list', {});\n }\n async updateResource(resourceId: string, options: any): Promise<any> {\n return this.post('/resources/update', { resource_id: resourceId, ...options });\n }\n async deleteResource(resourceId: string): Promise<void> {\n await this.post('/resources/delete', { resource_id: resourceId });\n }\n\n // ── Relation types ──\n\n async createRelationType(options: any): Promise<any> {\n return this.post('/relation-types/create', options);\n }\n async listRelationTypes(): Promise<any[]> {\n return this.post('/relation-types/list', {});\n }\n async updateRelationType(id: string, options: any): Promise<any> {\n return this.post('/relation-types/update', { id, ...options });\n }\n async deleteRelationType(id: string): Promise<void> {\n await this.post('/relation-types/delete', { id });\n }\n\n // ── Profile ──\n\n async getProfile(userId: string): Promise<Record<string, any>> {\n return this.post('/profile/get', { user_id: userId });\n }\n async setProfile(userId: string, data: Record<string, any>): Promise<void> {\n await this.post('/profile/set', { user_id: userId, data });\n }\n\n // ── Auth config ──\n\n async getAuthConfig(): Promise<any> {\n return this.post('/config/get', {});\n }\n async setAuthConfig(config: any): Promise<void> {\n await this.post('/config/set', config);\n }\n\n // ── Stewardship sub-namespace ──\n\n readonly stewardship = {\n resolve: (userId: string) => this.post('/stewardship/resolve', { user_id: userId }),\n createOverride: (options: any) =>\n this.post('/stewardship/create-override', options),\n revoke: async (id: string) => {\n await this.post('/stewardship/revoke', { id });\n },\n checkPermission: async (\n stewardId: string,\n wardId: string,\n resource: string,\n action: string,\n ): Promise<boolean> => {\n const r = await this.post('/stewardship/check-permission', {\n steward_id: stewardId,\n ward_id: wardId,\n resource,\n action,\n });\n return Boolean((r as any)?.allowed);\n },\n createActAs: (stewardId: string, wardId: string) =>\n this.post('/stewardship/create-act-as', { steward_id: stewardId, ward_id: wardId }),\n listAudit: (\n userId: string,\n options: { limit?: number; offset?: number } = {},\n ) =>\n this.post('/stewardship/list-audit', {\n user_id: userId,\n limit: options.limit ?? 50,\n offset: options.offset ?? 0,\n }),\n };\n\n withAuth<T extends (request: Request & { user: AuthUser }) => Promise<Response>>(\n handler: T\n ): (request: Request) => Promise<Response> {\n const self = this;\n return async function(request: Request): Promise<Response> {\n let token: string | null = null;\n const authHeader = request.headers.get('Authorization');\n if (authHeader?.startsWith('Bearer ')) {\n token = authHeader.slice(7);\n } else {\n const cookies = request.headers.get('Cookie') ?? '';\n const match = cookies.match(/__session=([^;]+)/);\n if (match) token = match[1];\n }\n if (!token) {\n return new Response(JSON.stringify({ error: 'Authentication required' }), {\n status: 401, headers: { 'Content-Type': 'application/json' },\n });\n }\n try {\n const user = await self.validate(token);\n (request as any).user = user;\n return handler(request as Request & { user: AuthUser });\n } catch {\n return new Response(JSON.stringify({ error: 'Invalid or expired token' }), {\n status: 401, headers: { 'Content-Type': 'application/json' },\n });\n }\n };\n }\n\n // ── Request-scoped identity + authorization ──\n //\n // In dev mode the SDK uses Node's AsyncLocalStorage (via\n // request-scope.ts) to track per-request state — tenants must wrap\n // their inbound request handler with `runWithRequest(...)`. Without\n // that wrapper, set/get/can fall back to clear errors / anonymous\n // results so the misuse is obvious rather than silent.\n\n async setCurrentUser(token: string | null): Promise<void> {\n const { getCurrentRequestStore } = await import('./request-scope.js');\n const store = getCurrentRequestStore();\n if (!store) {\n // No active request scope (e.g. background task / one-shot\n // script / test that didn't wrap). Silent no-op matches the\n // runtime's op_auth_set_current_user behaviour when\n // REQUEST_CTX isn't set\n // (crates/runtime/src/ops/platform/ops_authz.rs:90-114).\n // The Maravilla Vite plugin auto-opens a scope for every dev\n // HTTP request, so SvelteKit/RR hook code reaches this branch\n // only outside the request lifecycle.\n return;\n }\n if (!token) {\n store.token = undefined;\n store.user = undefined;\n return;\n }\n store.token = token;\n store.user = await this.validate(token);\n }\n\n getCurrentUser(): AuthCaller {\n // Synchronous read: ALS module is already loaded by the time\n // setCurrentUser ran, OR we just return anonymous.\n // Use require-style import via a cached reference to keep this sync.\n const mod = (RemoteAuthService as any)._requestScope as\n | typeof import('./request-scope.js')\n | undefined;\n const store = mod?.getCurrentRequestStore?.();\n const user = store?.user;\n if (!user) {\n return mod?.anonymousCaller?.() ?? {\n user_id: '',\n email: '',\n is_admin: false,\n roles: [],\n is_anonymous: true,\n };\n }\n return {\n user_id: user.id,\n email: user.email,\n is_admin: false,\n roles: user.groups ?? [],\n is_anonymous: false,\n };\n }\n\n async can(\n action: string,\n resourceId: string,\n node?: Record<string, unknown> | null,\n ): Promise<boolean> {\n const { getCurrentRequestStore } = await import('./request-scope.js');\n const store = getCurrentRequestStore();\n const token = store?.token;\n if (!token) {\n // No bound user → fail-closed, like the runtime evaluator.\n return false;\n }\n const r = await this.post('/can', {\n token,\n action,\n resource_id: resourceId,\n node: node ?? null,\n });\n return Boolean((r as any)?.allowed);\n }\n}\n\n// Cache the request-scope module on the class so getCurrentUser can read\n// it synchronously (required by the AuthService interface — getCurrentUser\n// is sync). Lazy-load on first setCurrentUser/can call (which is async).\nimport('./request-scope.js')\n .then((mod) => {\n (RemoteAuthService as any)._requestScope = mod;\n })\n .catch(() => {\n // Non-Node environment — getCurrentUser will return anonymous.\n });\n\n/**\n * Remote stub for the per-request Layer 2 policy toggle. The toggle lives in\n * per-request state inside the runtime and has no remote equivalent.\n */\nclass RemotePolicyService implements PolicyService {\n setEnabled(_enabled: boolean): void {\n throw new Error(\n 'platform.policy.setEnabled is only available inside the Maravilla runtime.'\n );\n }\n\n isEnabled(): boolean {\n throw new Error(\n 'platform.policy.isEnabled is only available inside the Maravilla runtime.'\n );\n }\n}\n\n/**\n * Remote Workflows service — HTTP adaptor over the dev-server's\n * `/api/workflows/*` routes. The runtime (isolate) path uses `Deno.core.ops`\n * instead; both produce handles with the same shape.\n *\n * @internal\n */\nclass RemoteWorkflows implements Workflows {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>,\n ) {}\n\n private async request(path: string, options: RequestInit = {}): Promise<Response> {\n const response = await fetch(`${this.baseUrl}${path}`, {\n ...options,\n headers: { ...this.headers, ...getRequestAuthHeader(), ...options.headers },\n });\n if (!response.ok && response.status !== 404) {\n const error = await response.text();\n throw new Error(`Platform API error: ${response.status} - ${error}`);\n }\n return response;\n }\n\n async start(workflowId: string, input: unknown = {}): Promise<WorkflowHandle> {\n if (typeof workflowId !== 'string' || !workflowId) {\n throw new Error('workflows.start: workflowId must be a non-empty string');\n }\n const res = await this.request(\n `/api/workflows/${encodeURIComponent(workflowId)}/start`,\n { method: 'POST', body: JSON.stringify(input ?? {}) },\n );\n const { runId } = (await res.json()) as { runId: string };\n return makeRemoteWorkflowHandle(this.baseUrl, this.headers, runId);\n }\n\n handle(runId: string): WorkflowHandle {\n if (typeof runId !== 'string' || !runId) {\n throw new Error('workflows.handle: runId must be a non-empty string');\n }\n return makeRemoteWorkflowHandle(this.baseUrl, this.headers, runId);\n }\n\n async sendEvent(eventType: string, payload: unknown = null): Promise<number> {\n if (typeof eventType !== 'string' || !eventType) {\n throw new Error('workflows.sendEvent: eventType must be a non-empty string');\n }\n const res = await this.request(`/api/workflows/signal`, {\n method: 'POST',\n body: JSON.stringify({ eventType, payload }),\n });\n const data = (await res.json()) as { count: number };\n return data.count;\n }\n}\n\nfunction makeRemoteWorkflowHandle(\n baseUrl: string,\n headers: Record<string, string>,\n runId: string,\n): WorkflowHandle {\n const doFetch = async (path: string, init: RequestInit = {}): Promise<Response> => {\n const res = await fetch(`${baseUrl}${path}`, {\n ...init,\n headers: { ...headers, ...init.headers },\n });\n if (!res.ok && res.status !== 404) {\n throw new Error(`Platform API error: ${res.status} - ${await res.text()}`);\n }\n return res;\n };\n\n const handle: WorkflowHandle = {\n runId,\n async status(): Promise<WorkflowRun | null> {\n const res = await doFetch(`/api/workflows/runs/${encodeURIComponent(runId)}`);\n if (res.status === 404) return null;\n return (await res.json()) as WorkflowRun;\n },\n async history(): Promise<WorkflowStepRecord[]> {\n const res = await doFetch(\n `/api/workflows/runs/${encodeURIComponent(runId)}/history`,\n );\n return (await res.json()) as WorkflowStepRecord[];\n },\n async cancel(): Promise<boolean> {\n const res = await doFetch(\n `/api/workflows/runs/${encodeURIComponent(runId)}/cancel`,\n { method: 'POST' },\n );\n const data = (await res.json()) as { cancelled: boolean };\n return data.cancelled;\n },\n async result(options?: { timeoutMs?: number }): Promise<unknown> {\n const timeoutMs = options?.timeoutMs;\n const deadline =\n typeof timeoutMs === 'number' && Number.isFinite(timeoutMs) && timeoutMs > 0\n ? Date.now() + timeoutMs\n : null;\n let delay = 100;\n while (true) {\n const run = await handle.status();\n if (!run) throw new Error(`workflow run not found: ${runId}`);\n if (run.status === 'completed') return run.output;\n if (run.status === 'failed' || run.status === 'cancelled') {\n const err = new Error(`workflow ${run.status}`) as Error & { run: WorkflowRun };\n err.run = run;\n throw err;\n }\n if (deadline !== null && Date.now() >= deadline) {\n throw new Error('workflow result timeout');\n }\n await new Promise((r) => setTimeout(r, delay));\n delay = Math.min(delay * 2, 5000);\n }\n },\n };\n return handle;\n}\n\n/**\n * Create a remote platform client for development environments.\n * \n * This function creates a platform instance that communicates with a development\n * server over HTTP. It's used internally by getPlatform() when running in development\n * mode and no native platform is available.\n * \n * @param baseUrl - The base URL of the development server\n * @param tenant - The tenant identifier for multi-tenancy support\n * @returns A platform instance that proxies requests to the development server\n * \n * @internal\n * \n * @example\n * ```typescript\n * // This is typically called internally by getPlatform()\n * const platform = createRemoteClient('http://localhost:3001', 'dev-tenant');\n * \n * // The returned platform works the same as the native one\n * await platform.env.KV.cache.put('key', 'value');\n * await platform.env.DB.insertOne('users', { name: 'John' });\n * await platform.env.STORAGE.put('file.pdf', pdfData);\n * ```\n */\nexport function createRemoteClient(baseUrl: string, tenant: string) {\n const headers = {\n 'Content-Type': 'application/json',\n 'X-Tenant-Id': tenant,\n };\n\n // Create KV namespaces proxy that dynamically creates namespace instances\n const kvProxy = new Proxy({} as Record<string, KvNamespace>, {\n get(_, namespace: string) {\n return new RemoteKvNamespace(baseUrl, namespace, headers);\n }\n });\n\n const db = new RemoteDatabase(baseUrl, headers);\n const storage = new RemoteStorage(baseUrl, headers);\n const media = new RemoteMediaService(baseUrl, headers) as RemoteMediaService & { transforms: TransformsService };\n // Mirror the runtime's globalThis.platform.media.transforms surface so\n // tenant code (auto-fired event handlers, +server.ts loaders, scripts)\n // can call platform.media.transforms.transcode/thumbnail/probe/...\n // identically in dev and prod.\n media.transforms = new RemoteTransformsService(baseUrl, headers);\n const realtime = new RemoteRealtimeService(baseUrl, headers);\n const auth = new RemoteAuthService(baseUrl, headers);\n const policy = new RemotePolicyService();\n const workflows = new RemoteWorkflows(baseUrl, headers);\n\n return {\n env: {\n KV: kvProxy,\n DB: db,\n STORAGE: storage,\n },\n media,\n realtime,\n auth,\n policy,\n workflows,\n };\n}\n\n/**\n * Remote `platform.media.transforms` for development. Each method posts\n * to the dev-server's `/api/media/transforms/*` route and returns the\n * same JobHandle / JobStatusResponse / MediaInfo shapes the native\n * runtime returns. Output keys are content-addressed by the platform —\n * tenants can pre-compute them with `keyFor()` and render placeholder\n * UI before the worker writes the file.\n *\n * @internal\n */\nclass RemoteTransformsService implements TransformsService {\n constructor(\n private baseUrl: string,\n private headers: Record<string, string>,\n ) {}\n\n private async post<T>(path: string, body: unknown): Promise<T> {\n const res = await fetch(`${this.baseUrl}/api/media/transforms${path}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...this.headers, ...getRequestAuthHeader() },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Transforms error (${res.status}): ${text}`);\n }\n return res.json() as Promise<T>;\n }\n\n transcode(srcKey: string, opts: TranscodeOpts): Promise<JobHandle> {\n return this.post<JobHandle>('/transcode', { srcKey, opts });\n }\n\n thumbnail(srcKey: string, opts: ThumbnailOpts): Promise<JobHandle> {\n return this.post<JobHandle>('/thumbnail', { srcKey, opts });\n }\n\n resize(srcKey: string, opts: ResizeOpts): Promise<JobHandle> {\n return this.post<JobHandle>('/resize', { srcKey, opts });\n }\n\n ocr(srcKey: string, opts?: OcrOpts | null): Promise<JobHandle> {\n return this.post<JobHandle>('/ocr', { srcKey, opts: opts ?? {} });\n }\n\n probe(srcKey: string): Promise<MediaInfo> {\n return this.post<MediaInfo>('/probe', { srcKey });\n }\n\n async job(id: string): Promise<JobStatusResponse> {\n const res = await fetch(`${this.baseUrl}/api/media/transforms/jobs/${encodeURIComponent(id)}`, {\n method: 'GET',\n headers: { ...this.headers, ...getRequestAuthHeader() },\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Transforms job lookup error (${res.status}): ${text}`);\n }\n return res.json() as Promise<JobStatusResponse>;\n }\n}","// REN (Resource Event Notifications) client utilities\n// Thin SSE client for /api/maravilla/ren\n// Reconnect w/ basic backoff; consumer filters self vs others using evt.src\n\nexport interface RenEvent {\n t: string; // event type e.g. storage.object.created, realtime.message, presence.join\n r: string; // resource domain e.g. storage, runtime, realtime, presence\n k?: string; // key (object key, deployment key, etc.)\n v?: string; // version / etag\n ts?: number; // timestamp (ms)\n src?: string;// origin client id (if set on mutation request)\n ns?: string; // future namespace / tenant\n ch?: string; // channel name (for realtime pub/sub)\n data?: any; // arbitrary payload (for realtime messages)\n uid?: string;// user identity (for presence)\n [extra: string]: any;\n}\n\nexport interface RenClientOptions {\n endpoint?: string; // override (default /api/maravilla/ren)\n subscriptions?: string[]; // resource filters, ['*'] means all\n clientId?: string; // supply existing client id\n autoReconnect?: boolean; // default true\n maxBackoffMs?: number; // default 15000\n debug?: boolean; // enable console debug logging\n}\n\ntype Listener = (event: RenEvent) => void;\n\nexport class RenClient {\n private endpoint: string;\n private subs: string[];\n private clientId: string;\n private listeners = new Set<Listener>();\n private es: EventSource | null = null;\n private closed = false;\n private attempt = 0;\n private autoReconnect: boolean;\n private maxBackoff: number;\n private debug: boolean;\n\n constructor(opts: RenClientOptions = {}) {\n this.endpoint = opts.endpoint || this.detectEndpoint();\n this.subs = (opts.subscriptions && opts.subscriptions.length) ? opts.subscriptions : ['*'];\n this.clientId = opts.clientId || getOrCreateClientId();\n this.autoReconnect = opts.autoReconnect !== false;\n this.maxBackoff = opts.maxBackoffMs ?? 15000;\n this.debug = !!opts.debug || (typeof localStorage !== 'undefined' && localStorage.getItem('REN_DEBUG') === '1');\n this.connect();\n }\n\n private detectEndpoint(): string {\n // Port check FIRST — catches any dev server (Vite, SvelteKit, etc.)\n // regardless of whether globalThis.platform was set by getPlatform().\n //\n // This is the **fallback path** for projects that haven't wired\n // `@maravilla-labs/vite-plugin` into their Vite config. With the plugin,\n // `/api/*` is proxied from the framework dev port to :3001, so\n // `window.location.port === '5173'` (or wherever) but the relative\n // `/api/maravilla/ren` URL works without rewriting. Without the plugin,\n // we keep this absolute-URL rewrite so existing setups don't break.\n if (typeof window !== 'undefined') {\n const port = window.location.port;\n if (port && port !== '3001' && port !== '80' && port !== '443' && port !== '') {\n return `http://${window.location.hostname}:3001/api/maravilla/ren`;\n }\n }\n\n // Production runtime (native Deno platform) — use relative URL\n if (typeof globalThis !== 'undefined' && (globalThis as any).platform) {\n return '/api/maravilla/ren';\n }\n\n // Default to relative URL (works in preview mode and production)\n console.log('[REN detectEndpoint] Using default relative endpoint (preview/production mode)');\n return '/api/maravilla/ren';\n }\n\n private log(...args: any[]) { if (this.debug) console.debug('[RenClient]', ...args); }\n\n private buildUrl(): string {\n const s = (this.subs.length === 1 && this.subs[0] === '*') ? '*' : this.subs.join(',');\n const qs = new URLSearchParams({ cid: this.clientId, s });\n return `${this.endpoint}?${qs.toString()}`;\n }\n\n private connect() {\n const url = this.buildUrl();\n this.log('connecting', { url });\n this.es = new EventSource(url);\n this.closed = false;\n\n const forward = (e: MessageEvent) => {\n try {\n const evt: RenEvent = JSON.parse(e.data);\n this.log('event', evt);\n this.listeners.forEach(l => l(evt));\n } catch (err) {\n this.log('malformed event data', e.data, err);\n }\n };\n\n // Attach generic message handler for events without a specific event: type\n this.es.onmessage = forward;\n\n // Register listeners for all known event types\n // The browser EventSource API does NOT call onmessage for events with an event: field\n // We must explicitly register listeners for each event type we want to handle\n const knownEventTypes = [\n // Database events\n 'db.document.created',\n 'db.document.updated',\n 'db.document.deleted',\n // KV events\n 'kv.put',\n 'kv.delete',\n 'kv.expired',\n // Storage events\n 'storage.object.created',\n 'storage.object.updated',\n 'storage.object.deleted',\n // Runtime events\n 'runtime.snapshot.ready',\n 'runtime.worker.started',\n 'runtime.worker.stopped',\n // Realtime channel events\n 'realtime.message',\n // Presence events\n 'presence.join',\n 'presence.leave',\n 'presence.update',\n // Media transform lifecycle (emitted by media-transforms-worker)\n 'transform.queued',\n 'transform.started',\n 'transform.progress',\n 'transform.complete',\n 'transform.failed',\n // Meta events\n 'ren.meta'\n ];\n // Use the more general addEventListener signature to avoid TypeScript issues\n knownEventTypes.forEach(k => this.es?.addEventListener(k, forward as EventListener));\n\n this.es.onerror = (ev) => {\n this.log('error', ev);\n if (this.closed) return;\n this.es?.close();\n if (!this.autoReconnect) return;\n const delay = Math.min(1000 * Math.pow(2, this.attempt++), this.maxBackoff);\n this.log('reconnecting in', delay, 'ms');\n setTimeout(() => this.connect(), delay);\n };\n\n this.es.onopen = () => { this.attempt = 0; this.log('open'); };\n }\n\n on(listener: Listener): () => void {\n this.listeners.add(listener);\n this.log('listener added; total', this.listeners.size);\n return () => { this.listeners.delete(listener); this.log('listener removed; total', this.listeners.size); };\n }\n\n getClientId() { return this.clientId; }\n\n close() {\n this.closed = true;\n this.es?.close();\n this.log('closed');\n }\n}\n\nexport function getOrCreateClientId(storage?: Storage): string {\n if (!storage) {\n storage = (typeof window !== 'undefined' && window.localStorage) ? window.localStorage : (typeof globalThis !== 'undefined' && (globalThis as any).localStorage) ? (globalThis as any).localStorage : undefined as any;\n if (!storage) {\n // Return a random ID if no storage is available\n return (globalThis.crypto?.randomUUID?.() || randomFallback());\n }\n }\n const key = 'maravillaClientId';\n let id = storage.getItem(key);\n if (!id) {\n id = (globalThis.crypto?.randomUUID?.() || randomFallback());\n try { storage.setItem(key, id); } catch {} // ignore quota errors\n }\n return id;\n}\n\nfunction randomFallback(): string {\n // Very small UUID-ish fallback\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {\n const r = Math.random() * 16 | 0;\n const v = c === 'x' ? r : (r & 0x3 | 0x8);\n return v.toString(16);\n });\n}\n\n// Helper to add client header to fetch\nexport async function renFetch(input: string | URL | Request, init: RequestInit = {}, clientId?: string) {\n const cid = clientId || getOrCreateClientId();\n const headers = new Headers(init.headers || {});\n headers.set('X-Ren-Client', cid);\n return fetch(input, { ...init, headers });\n}\n\n// Storage convenience wrappers (example)\nexport async function storageUpload(path: string, file: Blob | File, clientId?: string) {\n const res = await renFetch(`/api/storage/upload?path=${encodeURIComponent(path)}`, { method: 'POST', body: file }, clientId);\n if (!res.ok) throw new Error('upload failed');\n return res.json().catch(() => ({}));\n}\n\nexport async function storageDelete(path: string, clientId?: string) {\n const res = await renFetch(`/api/storage/delete?path=${encodeURIComponent(path)}`, { method: 'DELETE' }, clientId);\n if (!res.ok) throw new Error('delete failed');\n return res.json().catch(() => ({}));\n}\n","// Maravilla Realtime Client\n// Extends REN with channels, pub/sub, and presence support\n// Uses WebSocket for bidirectional communication, SSE as fallback\n\nimport { getOrCreateClientId } from './ren.js';\n\nexport interface RealtimeEvent {\n event: string;\n channel: string;\n data?: any;\n from?: string;\n userId?: string;\n ts?: number;\n metadata?: any;\n}\n\nexport interface PresenceMember {\n userId: string;\n metadata?: any;\n lastSeen?: number;\n}\n\nexport interface RealtimeClientOptions {\n /** WebSocket endpoint (default: auto-detect) */\n wsEndpoint?: string;\n /** Client ID (persistent across sessions) */\n clientId?: string;\n /** Auto-reconnect on disconnect (default: true) */\n autoReconnect?: boolean;\n /** Max reconnect backoff in ms (default: 15000) */\n maxBackoffMs?: number;\n /** Enable debug logging (default: false) */\n debug?: boolean;\n}\n\ntype EventCallback = (event: RealtimeEvent) => void;\ntype Unsubscribe = () => void;\n\nexport class RealtimeClient {\n private wsEndpoint: string;\n private clientId: string;\n private ws: WebSocket | null = null;\n private closed = false;\n private attempt = 0;\n private autoReconnect: boolean;\n private maxBackoff: number;\n private debug: boolean;\n\n private channelListeners = new Map<string, Set<EventCallback>>();\n private globalListeners = new Set<EventCallback>();\n private presenceListeners = new Map<string, {\n onJoin: Set<(member: PresenceMember) => void>;\n onLeave: Set<(member: PresenceMember) => void>;\n onUpdate: Set<(member: PresenceMember) => void>;\n }>();\n private subscribedChannels = new Set<string>();\n private pendingMessages: string[] = [];\n private pingInterval: ReturnType<typeof setInterval> | null = null;\n private joinedPresence = new Map<string, { userId: string; metadata?: any }>();\n\n constructor(opts: RealtimeClientOptions = {}) {\n this.wsEndpoint = opts.wsEndpoint || this.detectEndpoint();\n this.clientId = opts.clientId || getOrCreateClientId();\n this.autoReconnect = opts.autoReconnect !== false;\n this.maxBackoff = opts.maxBackoffMs ?? 15000;\n this.debug = !!opts.debug;\n }\n\n private detectEndpoint(): string {\n if (typeof window !== 'undefined') {\n const port = window.location.port;\n const proto = window.location.protocol === 'https:' ? 'wss:' : 'ws:';\n // Development mode: any non-standard port that isn't the dev server (3001)\n // Vite uses 5173+ but can pick any available port\n if (port && port !== '3001' && port !== '80' && port !== '443') {\n return `ws://${window.location.hostname}:3001/_rt/ws`;\n }\n return `${proto}//${window.location.host}/_rt/ws`;\n }\n return 'ws://localhost:3001/_rt/ws';\n }\n\n private log(...args: any[]) {\n if (this.debug) console.debug('[RealtimeClient]', ...args);\n }\n\n /** Connect to the realtime WebSocket server */\n connect(): void {\n if (this.ws && this.ws.readyState === WebSocket.OPEN) return;\n\n const url = `${this.wsEndpoint}?cid=${encodeURIComponent(this.clientId)}`;\n this.log('connecting', url);\n this.closed = false;\n\n try {\n this.ws = new WebSocket(url);\n } catch (e) {\n this.log('WebSocket constructor failed', e);\n this.scheduleReconnect();\n return;\n }\n\n this.ws.onopen = () => {\n this.attempt = 0;\n this.log('connected');\n\n // Re-subscribe to channels\n for (const ch of this.subscribedChannels) {\n this.sendRaw({ action: 'subscribe', channel: ch });\n }\n\n // Re-join presence channels (reconnect after drop)\n for (const [channel, info] of this.joinedPresence) {\n this.sendRaw({ action: 'presence:join', channel, userId: info.userId, metadata: info.metadata });\n }\n\n // Flush pending messages\n for (const msg of this.pendingMessages) {\n this.ws?.send(msg);\n }\n this.pendingMessages = [];\n\n // Start auto-ping to keep connection alive (25s interval)\n this.stopPing();\n this.pingInterval = setInterval(() => this.sendRaw({ action: 'ping' }), 25000);\n };\n\n this.ws.onmessage = (ev) => {\n try {\n const event: RealtimeEvent = JSON.parse(ev.data);\n this.log('received', event);\n this.dispatch(event);\n } catch (e) {\n this.log('malformed message', ev.data, e);\n }\n };\n\n this.ws.onerror = (ev) => {\n this.log('error', ev);\n };\n\n this.ws.onclose = () => {\n this.log('disconnected');\n this.ws = null;\n this.stopPing();\n if (!this.closed && this.autoReconnect) {\n this.scheduleReconnect();\n }\n };\n }\n\n private stopPing() {\n if (this.pingInterval) { clearInterval(this.pingInterval); this.pingInterval = null; }\n }\n\n private scheduleReconnect() {\n const delay = Math.min(1000 * Math.pow(2, this.attempt++), this.maxBackoff);\n this.log('reconnecting in', delay, 'ms');\n setTimeout(() => this.connect(), delay);\n }\n\n private sendRaw(msg: Record<string, any>) {\n const json = JSON.stringify(msg);\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(json);\n } else {\n this.pendingMessages.push(json);\n }\n }\n\n private dispatch(event: RealtimeEvent) {\n // Notify global listeners\n this.globalListeners.forEach(cb => cb(event));\n\n // Notify channel-specific listeners\n if (event.channel) {\n const listeners = this.channelListeners.get(event.channel);\n if (listeners) {\n listeners.forEach(cb => cb(event));\n }\n }\n\n // Handle presence events\n if (event.event === 'presence:join' || event.event === 'presence:leave' || event.event === 'presence:update') {\n const presenceSet = this.presenceListeners.get(event.channel);\n if (presenceSet) {\n const member: PresenceMember = {\n userId: event.userId || '',\n metadata: event.metadata,\n lastSeen: event.ts,\n };\n if (event.event === 'presence:join') {\n presenceSet.onJoin.forEach(cb => cb(member));\n } else if (event.event === 'presence:update') {\n presenceSet.onUpdate.forEach(cb => cb(member));\n } else {\n presenceSet.onLeave.forEach(cb => cb(member));\n }\n }\n }\n }\n\n /** Subscribe to messages on a channel */\n subscribe(channel: string, callback: EventCallback, options?: { token?: string }): Unsubscribe {\n if (!this.channelListeners.has(channel)) {\n this.channelListeners.set(channel, new Set());\n }\n this.channelListeners.get(channel)!.add(callback);\n\n // Send subscribe message if not already subscribed\n if (!this.subscribedChannels.has(channel)) {\n this.subscribedChannels.add(channel);\n const msg: Record<string, any> = { action: 'subscribe', channel };\n if (options?.token) {\n msg.token = options.token;\n }\n this.sendRaw(msg);\n }\n\n return () => {\n const listeners = this.channelListeners.get(channel);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.channelListeners.delete(channel);\n this.subscribedChannels.delete(channel);\n this.sendRaw({ action: 'unsubscribe', channel });\n }\n }\n };\n }\n\n /** Listen to all events across all channels */\n onAny(callback: EventCallback): Unsubscribe {\n this.globalListeners.add(callback);\n return () => { this.globalListeners.delete(callback); };\n }\n\n /** Publish a message to a channel */\n publish(channel: string, data: any, options?: { userId?: string }): void {\n this.sendRaw({\n action: 'publish',\n channel,\n data,\n userId: options?.userId,\n });\n }\n\n /** Get a presence handle for a channel */\n presence(channel: string) {\n if (!this.presenceListeners.has(channel)) {\n this.presenceListeners.set(channel, {\n onJoin: new Set(),\n onLeave: new Set(),\n onUpdate: new Set(),\n });\n }\n const listeners = this.presenceListeners.get(channel)!;\n\n return {\n /** Join the channel with presence (auto-rejoins on reconnect) */\n join: (userId: string, metadata?: any): void => {\n this.joinedPresence.set(channel, { userId, metadata });\n this.sendRaw({\n action: 'presence:join',\n channel,\n userId,\n metadata,\n });\n },\n\n /** Update metadata for the current presence (must have joined first) */\n update: (metadata?: any): void => {\n const info = this.joinedPresence.get(channel);\n if (!info) return;\n info.metadata = metadata;\n this.sendRaw({\n action: 'presence:update',\n channel,\n userId: info.userId,\n metadata,\n });\n },\n\n /** Leave the channel */\n leave: (): void => {\n this.joinedPresence.delete(channel);\n this.sendRaw({ action: 'presence:leave', channel });\n },\n\n /** Listen for users joining */\n onJoin: (callback: (member: PresenceMember) => void): Unsubscribe => {\n listeners.onJoin.add(callback);\n return () => { listeners.onJoin.delete(callback); };\n },\n\n /** Listen for metadata updates */\n onUpdate: (callback: (member: PresenceMember) => void): Unsubscribe => {\n listeners.onUpdate.add(callback);\n return () => { listeners.onUpdate.delete(callback); };\n },\n\n /** Listen for users leaving */\n onLeave: (callback: (member: PresenceMember) => void): Unsubscribe => {\n listeners.onLeave.add(callback);\n return () => { listeners.onLeave.delete(callback); };\n },\n };\n }\n\n /** Get current client ID */\n getClientId(): string {\n return this.clientId;\n }\n\n /** Check if connected */\n isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n /** Disconnect and stop reconnecting */\n disconnect(): void {\n this.closed = true;\n this.stopPing();\n // Send leave for all joined presence channels before closing\n for (const [channel] of this.joinedPresence) {\n this.sendRaw({ action: 'presence:leave', channel });\n }\n this.joinedPresence.clear();\n this.ws?.close();\n this.ws = null;\n this.pendingMessages = [];\n this.log('disconnected (manual)');\n }\n}\n","// MediaRoom — SFU-agnostic browser client for video/audio rooms\n// Wraps livekit-client internally. If the SFU is swapped, only this file changes.\n\nimport {\n Room,\n RoomEvent,\n type RemoteParticipant,\n type RemoteTrackPublication,\n type RemoteTrack,\n type LocalParticipant as LKLocalParticipant,\n type Participant as LKParticipant,\n type TrackPublication,\n Track,\n ConnectionState,\n type DisconnectReason,\n type RoomConnectOptions,\n} from 'livekit-client';\n\n// ─── Events ───\n\nexport enum MediaRoomEvent {\n Connected = 'connected',\n Reconnecting = 'reconnecting',\n Reconnected = 'reconnected',\n Disconnected = 'disconnected',\n ParticipantJoined = 'participantJoined',\n ParticipantLeft = 'participantLeft',\n TrackSubscribed = 'trackSubscribed',\n TrackUnsubscribed = 'trackUnsubscribed',\n TrackMuted = 'trackMuted',\n TrackUnmuted = 'trackUnmuted',\n ActiveSpeakersChanged = 'activeSpeakersChanged',\n DataReceived = 'dataReceived',\n RecordingStatusChanged = 'recordingStatusChanged',\n MediaDevicesChanged = 'mediaDevicesChanged',\n}\n\n// ─── Types ───\n\nexport type TrackSource = 'camera' | 'microphone' | 'screen_share' | 'screen_share_audio';\nexport type TrackKind = 'audio' | 'video';\n\nexport interface MediaTrackPublication {\n trackSid: string;\n source: TrackSource;\n kind: TrackKind;\n muted: boolean;\n track?: MediaStreamTrack;\n}\n\nexport interface MediaParticipant {\n identity: string;\n name?: string;\n metadata?: string;\n isSpeaking: boolean;\n audioLevel: number;\n tracks: MediaTrackPublication[];\n}\n\nexport interface VideoResolution {\n width: number;\n height: number;\n frameRate?: number;\n}\n\nexport interface MediaRoomOptions {\n autoSubscribe?: boolean;\n adaptiveStream?: boolean;\n dynacast?: boolean;\n}\n\n// ─── Helpers ───\n\nfunction mapSource(source: Track.Source): TrackSource {\n switch (source) {\n case Track.Source.Camera: return 'camera';\n case Track.Source.Microphone: return 'microphone';\n case Track.Source.ScreenShare: return 'screen_share';\n case Track.Source.ScreenShareAudio: return 'screen_share_audio';\n default: return 'camera';\n }\n}\n\nfunction mapParticipant(p: LKParticipant): MediaParticipant {\n const tracks: MediaTrackPublication[] = [];\n p.trackPublications.forEach((pub: TrackPublication) => {\n tracks.push({\n trackSid: pub.trackSid,\n source: mapSource(pub.source),\n kind: pub.kind === Track.Kind.Video ? 'video' : 'audio',\n muted: pub.isMuted,\n track: pub.track?.mediaStreamTrack,\n });\n });\n return {\n identity: p.identity,\n name: p.name,\n metadata: p.metadata,\n isSpeaking: p.isSpeaking,\n audioLevel: p.audioLevel,\n tracks,\n };\n}\n\n/** Attach a media track to a video or audio element */\nexport function attachTrack(track: MediaStreamTrack, element: HTMLVideoElement | HTMLAudioElement): void {\n if (!track || !element) return;\n const stream = new MediaStream([track]);\n element.srcObject = stream;\n if (element instanceof HTMLVideoElement) {\n element.playsInline = true;\n }\n element.play().catch(() => {}); // autoplay may be blocked\n}\n\n/** Detach media from an element */\nexport function detachTrack(element: HTMLVideoElement | HTMLAudioElement): void {\n if (!element) return;\n element.srcObject = null;\n}\n\n// ─── MediaLocalParticipant ───\n\nexport class MediaLocalParticipant implements MediaParticipant {\n private lp: LKLocalParticipant;\n\n /** @internal */\n constructor(lp: LKLocalParticipant) { this.lp = lp; }\n\n get identity() { return this.lp.identity; }\n get name() { return this.lp.name; }\n get metadata() { return this.lp.metadata; }\n get isSpeaking() { return this.lp.isSpeaking; }\n get audioLevel() { return this.lp.audioLevel; }\n\n get tracks(): MediaTrackPublication[] {\n return mapParticipant(this.lp).tracks;\n }\n\n // Camera\n get isCameraEnabled(): boolean {\n return !!this.lp.getTrackPublication(Track.Source.Camera)?.track && !this.lp.getTrackPublication(Track.Source.Camera)?.isMuted;\n }\n async enableCamera(options?: { deviceId?: string; resolution?: VideoResolution }): Promise<void> {\n await this.lp.setCameraEnabled(true, {\n deviceId: options?.deviceId,\n resolution: options?.resolution ? { width: options.resolution.width, height: options.resolution.height, frameRate: options.resolution.frameRate } : undefined,\n });\n }\n async disableCamera(): Promise<void> {\n await this.lp.setCameraEnabled(false);\n }\n\n // Microphone\n get isMicrophoneEnabled(): boolean {\n return !!this.lp.getTrackPublication(Track.Source.Microphone)?.track && !this.lp.getTrackPublication(Track.Source.Microphone)?.isMuted;\n }\n async enableMicrophone(options?: { deviceId?: string }): Promise<void> {\n await this.lp.setMicrophoneEnabled(true, { deviceId: options?.deviceId });\n }\n async disableMicrophone(): Promise<void> {\n await this.lp.setMicrophoneEnabled(false);\n }\n\n // Screen share\n get isScreenShareEnabled(): boolean {\n return !!this.lp.getTrackPublication(Track.Source.ScreenShare)?.track;\n }\n async enableScreenShare(options?: { audio?: boolean }): Promise<void> {\n await this.lp.setScreenShareEnabled(true, { audio: options?.audio });\n }\n async disableScreenShare(): Promise<void> {\n await this.lp.setScreenShareEnabled(false);\n }\n\n // Metadata\n async setName(name: string): Promise<void> { await this.lp.setName(name); }\n async setMetadata(metadata: string): Promise<void> { await this.lp.setMetadata(metadata); }\n\n // Data\n async sendData(data: Uint8Array, options?: { reliable?: boolean }): Promise<void> {\n await this.lp.publishData(data, { reliable: options?.reliable ?? true });\n }\n}\n\n// ─── MediaRoom ───\n\ntype EventCallback = (...args: any[]) => void;\n\nexport class MediaRoom {\n private room: Room;\n private listeners = new Map<MediaRoomEvent, Set<EventCallback>>();\n private _localParticipant!: MediaLocalParticipant;\n\n constructor() {\n this.room = new Room();\n }\n\n async connect(url: string, token: string, options?: MediaRoomOptions): Promise<void> {\n const opts: RoomConnectOptions = {};\n if (options?.autoSubscribe !== undefined) opts.autoSubscribe = options.autoSubscribe;\n this.room.options.adaptiveStream = options?.adaptiveStream ?? true;\n this.room.options.dynacast = options?.dynacast ?? true;\n\n this.wireEvents();\n await this.room.connect(url, token, opts);\n this._localParticipant = new MediaLocalParticipant(this.room.localParticipant);\n }\n\n async disconnect(): Promise<void> {\n await this.room.disconnect();\n }\n\n get state(): 'disconnected' | 'connecting' | 'connected' | 'reconnecting' {\n switch (this.room.state) {\n case ConnectionState.Connected: return 'connected';\n case ConnectionState.Connecting: return 'connecting';\n case ConnectionState.Reconnecting: return 'reconnecting';\n default: return 'disconnected';\n }\n }\n\n get localParticipant(): MediaLocalParticipant { return this._localParticipant; }\n\n get participants(): Map<string, MediaParticipant> {\n const map = new Map<string, MediaParticipant>();\n this.room.remoteParticipants.forEach((p, id) => map.set(id, mapParticipant(p)));\n return map;\n }\n\n get activeSpeakers(): MediaParticipant[] {\n return this.room.activeSpeakers.map(mapParticipant);\n }\n\n get name(): string { return this.room.name; }\n get numParticipants(): number { return this.room.numParticipants; }\n get isRecording(): boolean { return this.room.isRecording; }\n\n // Events\n on(event: MediaRoomEvent, callback: EventCallback): this {\n if (!this.listeners.has(event)) this.listeners.set(event, new Set());\n this.listeners.get(event)!.add(callback);\n return this;\n }\n\n off(event: MediaRoomEvent, callback: EventCallback): this {\n this.listeners.get(event)?.delete(callback);\n return this;\n }\n\n private emit(event: MediaRoomEvent, ...args: any[]) {\n this.listeners.get(event)?.forEach(cb => cb(...args));\n }\n\n // Device switching\n async switchCamera(deviceId: string): Promise<void> {\n await this.room.switchActiveDevice('videoinput', deviceId);\n }\n async switchMicrophone(deviceId: string): Promise<void> {\n await this.room.switchActiveDevice('audioinput', deviceId);\n }\n async switchSpeaker(deviceId: string): Promise<void> {\n await this.room.switchActiveDevice('audiooutput', deviceId);\n }\n\n // Static device enumeration\n static async getDevices(): Promise<MediaDeviceInfo[]> {\n return navigator.mediaDevices.enumerateDevices();\n }\n static async getCameras(): Promise<MediaDeviceInfo[]> {\n return (await MediaRoom.getDevices()).filter(d => d.kind === 'videoinput');\n }\n static async getMicrophones(): Promise<MediaDeviceInfo[]> {\n return (await MediaRoom.getDevices()).filter(d => d.kind === 'audioinput');\n }\n static async getSpeakers(): Promise<MediaDeviceInfo[]> {\n return (await MediaRoom.getDevices()).filter(d => d.kind === 'audiooutput');\n }\n\n // ─── Event wiring (LiveKit → MediaRoom) ───\n\n private wireEvents() {\n const r = this.room;\n r.on(RoomEvent.Connected, () => this.emit(MediaRoomEvent.Connected));\n r.on(RoomEvent.Reconnecting, () => this.emit(MediaRoomEvent.Reconnecting));\n r.on(RoomEvent.Reconnected, () => this.emit(MediaRoomEvent.Reconnected));\n r.on(RoomEvent.Disconnected, (reason?: DisconnectReason) => this.emit(MediaRoomEvent.Disconnected, reason));\n r.on(RoomEvent.MediaDevicesChanged, () => this.emit(MediaRoomEvent.MediaDevicesChanged));\n r.on(RoomEvent.RecordingStatusChanged, (recording: boolean) => this.emit(MediaRoomEvent.RecordingStatusChanged, recording));\n\n r.on(RoomEvent.ParticipantConnected, (p: RemoteParticipant) =>\n this.emit(MediaRoomEvent.ParticipantJoined, mapParticipant(p)));\n r.on(RoomEvent.ParticipantDisconnected, (p: RemoteParticipant) =>\n this.emit(MediaRoomEvent.ParticipantLeft, mapParticipant(p)));\n\n r.on(RoomEvent.TrackSubscribed, (track: RemoteTrack, pub: RemoteTrackPublication, p: RemoteParticipant) =>\n this.emit(MediaRoomEvent.TrackSubscribed, track.mediaStreamTrack, mapParticipant(p), mapSource(pub.source)));\n r.on(RoomEvent.TrackUnsubscribed, (track: RemoteTrack, pub: RemoteTrackPublication, p: RemoteParticipant) =>\n this.emit(MediaRoomEvent.TrackUnsubscribed, track.mediaStreamTrack, mapParticipant(p), mapSource(pub.source)));\n\n r.on(RoomEvent.TrackMuted, (pub: TrackPublication, p: LKParticipant) =>\n this.emit(MediaRoomEvent.TrackMuted, mapParticipant(p)));\n r.on(RoomEvent.TrackUnmuted, (pub: TrackPublication, p: LKParticipant) =>\n this.emit(MediaRoomEvent.TrackUnmuted, mapParticipant(p)));\n\n r.on(RoomEvent.ActiveSpeakersChanged, (speakers: LKParticipant[]) =>\n this.emit(MediaRoomEvent.ActiveSpeakersChanged, speakers.map(mapParticipant)));\n\n r.on(RoomEvent.DataReceived, (data: Uint8Array, p?: RemoteParticipant) =>\n this.emit(MediaRoomEvent.DataReceived, data, p ? mapParticipant(p) : undefined));\n }\n}\n","/**\n * @fileoverview Web Push client SDK for Maravilla tenants.\n *\n * Talks to the tenant-origin `/_rt/push` endpoints served by delivery:\n * - GET /vapid-public-key — fetch the VAPID public key for subscribe\n * - POST /subscribe — create a subscription\n * - POST /unsubscribe — delete a subscription by id (or endpoint)\n *\n * The matching service worker is served from `/_rt/push/sw.js` on the\n * same tenant origin (browsers require same-origin SW registration).\n */\n\nconst DEFAULT_BASE_PATH = '/_rt/push';\nconst DEFAULT_SW_PATH = '/_rt/push/sw.js';\nconst VISITOR_STORAGE_KEY = 'maravilla.push.visitorId';\nconst REGISTER_TIMEOUT_MS = 10_000;\n\nexport interface RegisterPushOptions {\n /** Free-form topic strings to tag this subscription with. */\n topics?: string[];\n /** Authenticated user id, if any. Takes precedence over visitorId. */\n userId?: string | null;\n /** Anonymous visitor id. If omitted and userId is also omitted, one\n * is generated and persisted to localStorage under `maravilla.push.visitorId`. */\n visitorId?: string | null;\n /** Override the sw.js path (defaults to `/_platform/push/sw.js`). */\n swPath?: string;\n /** Override the API base path (defaults to `/_platform/push`). */\n basePath?: string;\n}\n\nexport interface RegisterPushResult {\n /** The browser PushSubscription (see Web Push spec). */\n subscription: PushSubscription;\n /** Server-issued subscription id — pass this back to unregisterPush. */\n subscriptionId: string;\n}\n\ninterface VapidPublicKeyResponse {\n publicKey: string;\n contactEmail?: string;\n}\n\ninterface ServerSubscription {\n id: string;\n [key: string]: unknown;\n}\n\nfunction assertPushSupported(): void {\n if (typeof navigator === 'undefined' || !('serviceWorker' in navigator)) {\n throw new Error('Web Push is not supported: serviceWorker is unavailable');\n }\n if (typeof window === 'undefined' || !('PushManager' in window)) {\n throw new Error('Web Push is not supported: PushManager is unavailable');\n }\n}\n\nfunction base64UrlToArrayBuffer(input: string): ArrayBuffer {\n const padding = '='.repeat((4 - (input.length % 4)) % 4);\n const base64 = (input + padding).replace(/-/g, '+').replace(/_/g, '/');\n const raw = atob(base64);\n const buffer = new ArrayBuffer(raw.length);\n const view = new Uint8Array(buffer);\n for (let i = 0; i < raw.length; i++) {\n view[i] = raw.charCodeAt(i);\n }\n return buffer;\n}\n\nfunction arrayBufferToBase64Url(buffer: ArrayBuffer | null): string | undefined {\n if (!buffer) return undefined;\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction randomUuid(): string {\n const c = typeof crypto !== 'undefined' ? crypto : undefined;\n if (c && typeof c.randomUUID === 'function') {\n return c.randomUUID();\n }\n const bytes = new Uint8Array(16);\n if (c && typeof c.getRandomValues === 'function') {\n c.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256);\n }\n bytes[6] = (bytes[6] & 0x0f) | 0x40;\n bytes[8] = (bytes[8] & 0x3f) | 0x80;\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\nfunction resolveVisitorId(\n userId: string | null | undefined,\n visitorId: string | null | undefined,\n): string | null {\n if (visitorId) return visitorId;\n if (userId) return null;\n try {\n const stored = window.localStorage.getItem(VISITOR_STORAGE_KEY);\n if (stored) return stored;\n const fresh = randomUuid();\n window.localStorage.setItem(VISITOR_STORAGE_KEY, fresh);\n return fresh;\n } catch {\n return randomUuid();\n }\n}\n\nasync function fetchVapidPublicKey(basePath: string): Promise<string> {\n const res = await fetch(`${basePath}/vapid-public-key`, {\n method: 'GET',\n credentials: 'same-origin',\n headers: { Accept: 'application/json' },\n });\n if (!res.ok) {\n throw new Error(`Failed to fetch VAPID public key: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as VapidPublicKeyResponse;\n if (!body || typeof body.publicKey !== 'string' || body.publicKey.length === 0) {\n throw new Error('VAPID public key response is missing `publicKey`');\n }\n return body.publicKey;\n}\n\nfunction extractKeys(sub: PushSubscription): { p256dh?: string; auth?: string } {\n return {\n p256dh: arrayBufferToBase64Url(sub.getKey('p256dh')),\n auth: arrayBufferToBase64Url(sub.getKey('auth')),\n };\n}\n\nexport async function registerPush(\n opts: RegisterPushOptions = {},\n): Promise<RegisterPushResult> {\n assertPushSupported();\n\n const basePath = opts.basePath ?? DEFAULT_BASE_PATH;\n const swPath = opts.swPath ?? DEFAULT_SW_PATH;\n const topics = opts.topics ?? [];\n const userId = opts.userId ?? null;\n const visitorId = resolveVisitorId(userId, opts.visitorId);\n\n // Whole-flow timeout. Without this, a stuck pushManager.subscribe() or a\n // misbehaving push service can leave the UI hanging forever.\n const timeout = new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`registerPush timed out after ${REGISTER_TIMEOUT_MS}ms`)),\n REGISTER_TIMEOUT_MS,\n ),\n );\n\n const flow = (async (): Promise<RegisterPushResult> => {\n const publicKey = await fetchVapidPublicKey(basePath);\n // Register the SW. We deliberately do NOT `await navigator.serviceWorker.ready`\n // here — that promise only resolves when an active SW's scope covers the\n // current page, but our SW is scoped to `/_rt/push/` and the page is at\n // `/`. `pushManager.subscribe()` works against the registration returned\n // by `register()` without needing the SW to control the page.\n const registration = await navigator.serviceWorker.register(swPath);\n\n const existing = await registration.pushManager.getSubscription();\n const subscription =\n existing ??\n (await registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: base64UrlToArrayBuffer(publicKey),\n }));\n\n const { p256dh, auth } = extractKeys(subscription);\n\n const res = await fetch(`${basePath}/subscribe`, {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'Content-Type': 'application/json', Accept: 'application/json' },\n body: JSON.stringify({\n provider: 'web-push',\n endpoint: subscription.endpoint,\n p256dh,\n auth,\n userId,\n visitorId,\n topics,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Subscribe failed: ${res.status} ${res.statusText}`);\n }\n\n const saved = (await res.json()) as ServerSubscription;\n if (!saved || typeof saved.id !== 'string' || saved.id.length === 0) {\n throw new Error('Subscribe response is missing `id`');\n }\n\n return { subscription, subscriptionId: saved.id };\n })();\n\n return Promise.race([flow, timeout]);\n}\n\nexport async function unregisterPush(\n subscriptionId: string,\n opts: { basePath?: string } = {},\n): Promise<void> {\n if (!subscriptionId) {\n throw new Error('subscriptionId is required');\n }\n const basePath = opts.basePath ?? DEFAULT_BASE_PATH;\n\n const res = await fetch(`${basePath}/unsubscribe`, {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ subscriptionId }),\n });\n\n if (!res.ok && res.status !== 404) {\n throw new Error(`Unsubscribe failed: ${res.status} ${res.statusText}`);\n }\n}\n\n/**\n * Compute a `Date` that is `offset` before `anchor` — handy for\n * \"X minutes/hours/days before the event\" scheduling.\n *\n * `offset` is a short duration string:\n * - `\"30s\"` — 30 seconds\n * - `\"15m\"` — 15 minutes\n * - `\"1h\"` — 1 hour\n * - `\"2d\"` — 2 days\n * - `\"1w\"` — 1 week\n *\n * Pure function — safe to call on the client. Works with `platform.push.schedule`:\n *\n * @example\n * ```typescript\n * import { offsetBefore } from '@maravilla-labs/platform';\n *\n * await platform.push.schedule(\n * { topic: `invite:${invite.id}` },\n * { title: invite.title, body: 'Your event is in one hour' },\n * {\n * at: offsetBefore(invite.event_date, '1h'),\n * key: `invite:${invite.id}:reminder-1h`,\n * }\n * );\n * ```\n *\n * @throws if `anchor` is an invalid date string or `offset` isn't a\n * recognised duration.\n */\nexport function offsetBefore(anchor: Date | string, offset: string): Date {\n const anchorDate = anchor instanceof Date ? anchor : new Date(anchor);\n if (Number.isNaN(anchorDate.getTime())) {\n throw new Error(`offsetBefore: invalid anchor \"${String(anchor)}\"`);\n }\n\n const match = /^(\\d+)\\s*(s|m|h|d|w)$/i.exec(offset.trim());\n if (!match) {\n throw new Error(\n `offsetBefore: invalid offset \"${offset}\" — expected something like \"30m\", \"1h\", \"2d\", \"1w\"`,\n );\n }\n\n const amount = Number(match[1]);\n const unit = match[2].toLowerCase();\n const UNIT_MS: Record<string, number> = {\n s: 1000,\n m: 60_000,\n h: 3_600_000,\n d: 86_400_000,\n w: 604_800_000,\n };\n return new Date(anchorDate.getTime() - amount * UNIT_MS[unit]);\n}\n","/**\n * @fileoverview Media transforms — async ffmpeg / image / OCR jobs.\n *\n * Mirrors the Rust `platform.media.transforms` surface. All mutating\n * methods (transcode/thumbnail/resize/ocr) return a {@link JobHandle}\n * whose `outputKey` is content-addressed via {@link keyFor} and known\n * up front — clients can render placeholder UI for the derived asset\n * before the worker even starts the job.\n *\n * The runtime injects the live JS object as `platform.media.transforms`\n * (see `crates/runtime/src/ops/platform/js_bindings/platform_js.rs`).\n * The static helper {@link keyFor} is exported separately and runs\n * client-side — it must produce byte-for-byte identical output to the\n * Rust `derive_key`. The shared golden-vector fixture\n * `crates/platform/tests/derive_key_vectors.json` is consumed from both\n * the Rust integration test (`crates/platform/tests/derive_key_golden.rs`)\n * and the TS test (`packages/platform/tests/derive-key.test.ts`) to keep\n * the two in lockstep.\n */\n\n// Isomorphic SHA-256 via @noble/hashes — runs in Node, Deno, and every\n// browser without a bundler-specific shim. `node:crypto` would pull\n// Node built-ins into browser bundles and break Vite builds that\n// consume this package client-side.\nimport { sha256 } from '@noble/hashes/sha2';\n\n// ── Types — mirror `crates/platform/src/media/transforms/types.rs` ──────\n\n/** Video container targets supported by v1. */\nexport type VideoFormat = 'mp4' | 'webm';\n\n/** Image output formats supported by v1. */\nexport type ImageFormat = 'jpg' | 'png' | 'webp';\n\n/** Lifecycle state of a transform job. */\nexport type JobStatus = 'pending' | 'running' | 'complete' | 'failed';\n\n/** Options for `transforms.transcode`. */\nexport interface TranscodeOpts {\n format: VideoFormat;\n codec?: string;\n max_width?: number;\n max_height?: number;\n audio_codec?: string;\n bitrate_kbps?: number;\n}\n\n/** Options for `transforms.thumbnail` — extract a single video frame. */\nexport interface ThumbnailOpts {\n /** Offset into the source. Accepts `\"00:00:01\"`, `\"1s\"`, or a plain number-as-string. */\n at: string;\n width?: number;\n height?: number;\n /** Defaults to `\"jpg\"` server-side when omitted. */\n format?: ImageFormat;\n quality?: number;\n}\n\n/** Options for `transforms.resize`. */\nexport interface ResizeOpts {\n width?: number;\n height?: number;\n format: ImageFormat;\n quality?: number;\n strip_metadata?: boolean;\n}\n\n/** Options for `transforms.ocr`. */\nexport interface OcrOpts {\n /** Tesseract language code(s). Defaults to `\"eng\"` server-side when omitted. */\n lang?: string;\n}\n\n/** Tagged union of all transform requests — matches the Rust `TransformSpec`. */\nexport type TransformSpec =\n | ({ kind: 'transcode' } & TranscodeOpts)\n | ({ kind: 'thumbnail' } & ThumbnailOpts)\n | ({ kind: 'resize' } & ResizeOpts)\n | ({ kind: 'ocr' } & OcrOpts);\n\n/** Probe output. All fields optional — ffprobe doesn't fill every one for every input. */\nexport interface MediaInfo {\n duration_secs?: number;\n width?: number;\n height?: number;\n video_codec?: string;\n audio_codec?: string;\n bitrate_bps?: number;\n container?: string;\n}\n\n/** Returned by every mutating transforms method. */\nexport interface JobHandle {\n id: string;\n src_key: string;\n output_key: string;\n status: JobStatus;\n}\n\n/** Returned by `transforms.job(id)`. */\nexport interface JobStatusResponse {\n id: string;\n status: JobStatus;\n}\n\n// ── Service interface (matches the JS object the runtime injects) ───────\n\nexport interface TransformsService {\n transcode(srcKey: string, opts: TranscodeOpts): Promise<JobHandle>;\n thumbnail(srcKey: string, opts: ThumbnailOpts): Promise<JobHandle>;\n resize(srcKey: string, opts: ResizeOpts): Promise<JobHandle>;\n probe(srcKey: string): Promise<MediaInfo>;\n ocr(srcKey: string, opts?: OcrOpts | null): Promise<JobHandle>;\n job(id: string): Promise<JobStatusResponse>;\n}\n\n// ── derive_key mirror ───────────────────────────────────────────────────\n\n/** Sort object keys recursively so the canonical JSON is stable. */\nfunction sortKeys(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(sortKeys);\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(value as Record<string, unknown>).sort()) {\n out[k] = sortKeys((value as Record<string, unknown>)[k]);\n }\n return out;\n }\n return value;\n}\n\n/**\n * Canonical JSON encoding — matches `serde_json::to_string` over a\n * recursively key-sorted object. Numbers, booleans, strings, null, and\n * nested objects/arrays only; no `undefined`, no functions.\n */\nfunction canonicalJson(value: unknown): string {\n return JSON.stringify(sortKeys(value));\n}\n\n/** Hex-encoded SHA-256 of the input bytes, truncated to 16 chars (8 bytes). */\nfunction shortHexSha256(input: string): string {\n const bytes = new TextEncoder().encode(input);\n const hash = sha256(bytes);\n return Array.from(hash.slice(0, 8))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Output extension for a spec — drives the `.<ext>` suffix on the\n * derived key. Matches `TransformSpec::output_extension` in Rust.\n */\nfunction outputExtension(spec: TransformSpec): string {\n switch (spec.kind) {\n case 'transcode':\n return spec.format; // 'mp4' | 'webm'\n case 'thumbnail':\n case 'resize': {\n // thumbnail's `format` is optional in TS (defaults to jpg server-side);\n // mirror that default here so keyFor matches the canonical Rust form.\n const fmt = (spec as { format?: ImageFormat }).format ?? 'jpg';\n return fmt;\n }\n case 'ocr':\n return 'txt';\n default: {\n const _exhaust: never = spec;\n throw new Error(`unknown transform kind: ${(_exhaust as { kind: string }).kind}`);\n }\n }\n}\n\n/**\n * Compute the canonical derived-asset key for `(srcKey, spec)`.\n *\n * Shape: `__derived/<srcHash>/<variantHash>.<ext>` where each hash is\n * the first 16 hex chars (8 bytes / 64 bits) of `SHA-256(...)`.\n *\n * **MUST** match Rust `platform::media::transforms::derive_key` byte-for-byte.\n * Cross-language golden vectors live at\n * `crates/platform/tests/derive_key_vectors.json`.\n */\nexport function keyFor(srcKey: string, spec: TransformSpec): string {\n const srcHash = shortHexSha256(srcKey);\n // Re-encode so the canonical JSON includes the `kind` discriminator at\n // a sorted position alongside the inlined opts fields — matches what\n // Rust's `serde_json::to_value(&spec)` produces for the tagged enum.\n const variantHash = shortHexSha256(canonicalJson(spec));\n const ext = outputExtension(spec);\n return `__derived/${srcHash}/${variantHash}.${ext}`;\n}\n\n/** Convenience namespace mirroring the Rust `transforms::keyFor` re-export. */\nexport const transforms = {\n keyFor,\n};\n\n// ── Declarative `transforms` config (consumed by the adapter compiler) ──\n//\n// Mirrors the build-time `TransformsConfig` in `@maravilla-labs/adapter-core`,\n// duplicated here so user code that writes `defineConfig({ transforms: {...} })`\n// gets full IDE completion without depending on adapter-core at runtime.\n//\n// The two type definitions are structurally identical — adapter-core's\n// `compileTransforms` consumes either shape interchangeably (it only walks the\n// JSON-shaped values, not the type-level identity).\n\n/**\n * Per-pattern transforms declaration used inside the `transforms` block of\n * `maravilla.config.ts`. Each field accepts a single opts object or an array.\n *\n * `variants` is sugar for `resize` arrays — convenient for the common\n * \"image → multiple resized renditions\" case.\n */\nexport interface TransformsPatternSpec {\n transcode?: TranscodeOpts | TranscodeOpts[];\n thumbnail?: ThumbnailOpts | ThumbnailOpts[];\n resize?: ResizeOpts | ResizeOpts[];\n /** Sugar for `resize` arrays — same shape, same semantics. */\n variants?: ResizeOpts[];\n ocr?: OcrOpts | OcrOpts[];\n}\n\n/**\n * Top-level `transforms` block. Keys are glob path patterns matched against\n * the storage key of every uploaded object. The adapter compiles each entry\n * into a synthetic `storage.put` event handler that fans out the declared\n * transforms via `Promise.all`.\n *\n * @example\n * ```ts\n * import { defineConfig } from '@maravilla-labs/platform/config';\n *\n * export default defineConfig({\n * transforms: {\n * 'uploads/videos/**': {\n * transcode: [{ format: 'mp4' }, { format: 'webm' }],\n * thumbnail: { at: '1s', width: 640, format: 'jpg' },\n * },\n * 'uploads/photos/**': {\n * variants: [\n * { width: 1600, format: 'webp', quality: 85 },\n * { width: 400, format: 'webp', quality: 80 },\n * ],\n * },\n * },\n * });\n * ```\n */\nexport type TransformsConfig = Record<string, TransformsPatternSpec>;\n","/**\n * @fileoverview Maravilla Platform SDK\n * \n * This package provides the main interface for accessing Maravilla runtime services\n * including Key-Value storage and Database operations. It automatically detects the\n * runtime environment and provides the appropriate implementation.\n * \n * ## Environment Detection\n * \n * The SDK automatically detects and adapts to different environments:\n * - **Production**: Uses native Maravilla runtime APIs\n * - **Development**: Connects to development server via HTTP\n * - **Testing**: Can be mocked or use development server\n * \n * ## Key Features\n * \n * - **KV Storage**: Cloudflare Workers KV-compatible API for key-value operations\n * - **Database**: MongoDB-style document database operations\n * - **Multi-tenancy**: Built-in tenant isolation and support\n * - **TypeScript**: Fully typed APIs with comprehensive JSDoc comments\n * - **Development-friendly**: Seamless development server integration\n * \n * @example\n * ```typescript\n * import { getPlatform } from '@maravilla/platform';\n * \n * const platform = getPlatform();\n * \n * // KV operations\n * await platform.env.KV.cache.put('user:123', { name: 'John' });\n * const user = await platform.env.KV.cache.get('user:123');\n * \n * // Database operations\n * const userId = await platform.env.DB.insertOne('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n * \n * const users = await platform.env.DB.find('users', { active: true });\n * ```\n * \n * @author Maravilla Team\n * @since 1.0.0\n */\n\nimport type { Platform } from './types.js';\nimport { createRemoteClient } from './remote-client.js';\n\nexport * from './types.js';\nexport * from './ren.js';\nexport * from './realtime.js';\nexport * from './media.js';\nexport * from './media-room.js';\nexport * from './push.js';\nexport * from './transforms.js';\n\n/**\n * Global platform instance injected by Maravilla runtime or development tools.\n * This should not be accessed directly - use getPlatform() instead.\n * \n * @internal\n */\n\ndeclare global {\n var __maravilla_platform: Platform | undefined;\n var platform: Platform | undefined;\n}\n\nlet cachedPlatform: Platform | undefined = undefined;\n\n/**\n * Get the platform instance. This will:\n * 1. Check if running in Maravilla runtime (global.platform exists)\n * 2. Check if a platform was injected via vite plugin or hooks\n * 3. Fall back to remote client for development\n * \n * The platform provides access to KV storage and database operations,\n * with automatic environment detection for seamless development and production.\n * \n * @param options - Optional configuration for development mode\n * @param options.devServerUrl - URL of the development server (defaults to MARAVILLA_DEV_SERVER env var or http://localhost:3001)\n * @param options.tenant - Tenant identifier for multi-tenancy (defaults to MARAVILLA_TENANT env var or 'dev-tenant')\n * @returns Platform instance with access to KV and database services\n * \n * @example\n * ```typescript\n * import { getPlatform } from '@maravilla/platform';\n * \n * // Basic usage (auto-detects environment)\n * const platform = getPlatform();\n * \n * // Development with custom server\n * const platform = getPlatform({\n * devServerUrl: 'http://localhost:3001',\n * tenant: 'my-app'\n * });\n * \n * // Use KV storage\n * await platform.env.KV.cache.put('user:123', { name: 'John' });\n * const user = await platform.env.KV.cache.get('user:123');\n * \n * // Use database\n * const userId = await platform.env.DB.insertOne('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n * ```\n */\nexport function getPlatform(options?: {\n devServerUrl?: string;\n tenant?: string;\n}): Platform {\n // Return cached if available\n if (cachedPlatform) {\n return cachedPlatform;\n }\n\n // 1. Check if we're in the real Maravilla runtime\n if (typeof globalThis !== 'undefined') {\n // Check for native platform (in production runtime)\n if (globalThis.platform) {\n console.log('[platform] Using native Maravilla platform');\n cachedPlatform = globalThis.platform;\n return cachedPlatform;\n }\n\n // Check for injected platform (from vite plugin or hooks)\n if (globalThis.__maravilla_platform) {\n console.log('[platform] Using injected platform');\n cachedPlatform = globalThis.__maravilla_platform;\n return cachedPlatform;\n }\n }\n\n // 2. Fall back to remote client for development\n const devServerUrl = options?.devServerUrl || process.env.MARAVILLA_DEV_SERVER || 'http://localhost:3001';\n const tenant = options?.tenant || process.env.MARAVILLA_TENANT || 'dev-tenant-001';\n \n console.log(`[platform] Creating remote client for ${devServerUrl}`);\n cachedPlatform = createRemoteClient(devServerUrl, tenant);\n \n // Cache it globally for other modules\n if (typeof globalThis !== 'undefined') {\n globalThis.__maravilla_platform = cachedPlatform;\n }\n \n return cachedPlatform;\n}\n\n/**\n * Clear the cached platform instance (useful for testing).\n * \n * This function resets the internal platform cache and clears any globally\n * injected platform instances. Subsequent calls to getPlatform() will\n * re-initialize the platform based on the current environment.\n * \n * @example\n * ```typescript\n * import { clearPlatformCache, getPlatform } from '@maravilla/platform';\n * \n * // In tests, clear cache between test cases\n * afterEach(() => {\n * clearPlatformCache();\n * });\n * \n * // Or when switching between different environments\n * clearPlatformCache();\n * const newPlatform = getPlatform({ devServerUrl: 'http://localhost:3002' });\n * ```\n */\nexport function clearPlatformCache(): void {\n cachedPlatform = undefined;\n if (typeof globalThis !== 'undefined') {\n globalThis.__maravilla_platform = undefined;\n }\n}\n\nexport {\n runWithRequest,\n getCurrentRequestStore,\n type RequestStore,\n} from './request-scope.js';"],"mappings":"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","names":["getRequestAuthHeader","getCurrentRequestStore","MediaRoomEvent"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maravilla-labs/platform",
3
- "version": "0.3.8",
3
+ "version": "0.3.9",
4
4
  "description": "Universal platform client for Maravilla runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,4 +1,5 @@
1
1
  import type { KvNamespace, KvListResult, Database, DbFindOptions, Storage, RealtimeService, PresenceService, AuthService, AuthCaller, AuthUser, AuthSession, AuthField, RegisterOptions, LoginOptions, UserListFilter, UserListResponse, UpdateUserOptions, PolicyService, VectorIndexSpec, VectorIndexDescriptor, VectorQueryWithFilter, VectorSearchHit, IndexSpec, IndexDescriptor, Workflows, WorkflowHandle, WorkflowRun, WorkflowStepRecord } from './types.js';
2
+ import type { TransformsService, TranscodeOpts, ThumbnailOpts, ResizeOpts, OcrOpts, JobHandle, JobStatusResponse, MediaInfo } from './transforms.js';
2
3
  import { RemoteMediaService } from './media.js';
3
4
  import { getRequestAuthHeader } from './request-scope.js';
4
5
 
@@ -1039,7 +1040,12 @@ export function createRemoteClient(baseUrl: string, tenant: string) {
1039
1040
 
1040
1041
  const db = new RemoteDatabase(baseUrl, headers);
1041
1042
  const storage = new RemoteStorage(baseUrl, headers);
1042
- const media = new RemoteMediaService(baseUrl, headers);
1043
+ const media = new RemoteMediaService(baseUrl, headers) as RemoteMediaService & { transforms: TransformsService };
1044
+ // Mirror the runtime's globalThis.platform.media.transforms surface so
1045
+ // tenant code (auto-fired event handlers, +server.ts loaders, scripts)
1046
+ // can call platform.media.transforms.transcode/thumbnail/probe/...
1047
+ // identically in dev and prod.
1048
+ media.transforms = new RemoteTransformsService(baseUrl, headers);
1043
1049
  const realtime = new RemoteRealtimeService(baseUrl, headers);
1044
1050
  const auth = new RemoteAuthService(baseUrl, headers);
1045
1051
  const policy = new RemotePolicyService();
@@ -1057,4 +1063,66 @@ export function createRemoteClient(baseUrl: string, tenant: string) {
1057
1063
  policy,
1058
1064
  workflows,
1059
1065
  };
1066
+ }
1067
+
1068
+ /**
1069
+ * Remote `platform.media.transforms` for development. Each method posts
1070
+ * to the dev-server's `/api/media/transforms/*` route and returns the
1071
+ * same JobHandle / JobStatusResponse / MediaInfo shapes the native
1072
+ * runtime returns. Output keys are content-addressed by the platform —
1073
+ * tenants can pre-compute them with `keyFor()` and render placeholder
1074
+ * UI before the worker writes the file.
1075
+ *
1076
+ * @internal
1077
+ */
1078
+ class RemoteTransformsService implements TransformsService {
1079
+ constructor(
1080
+ private baseUrl: string,
1081
+ private headers: Record<string, string>,
1082
+ ) {}
1083
+
1084
+ private async post<T>(path: string, body: unknown): Promise<T> {
1085
+ const res = await fetch(`${this.baseUrl}/api/media/transforms${path}`, {
1086
+ method: 'POST',
1087
+ headers: { 'Content-Type': 'application/json', ...this.headers, ...getRequestAuthHeader() },
1088
+ body: JSON.stringify(body),
1089
+ });
1090
+ if (!res.ok) {
1091
+ const text = await res.text();
1092
+ throw new Error(`Transforms error (${res.status}): ${text}`);
1093
+ }
1094
+ return res.json() as Promise<T>;
1095
+ }
1096
+
1097
+ transcode(srcKey: string, opts: TranscodeOpts): Promise<JobHandle> {
1098
+ return this.post<JobHandle>('/transcode', { srcKey, opts });
1099
+ }
1100
+
1101
+ thumbnail(srcKey: string, opts: ThumbnailOpts): Promise<JobHandle> {
1102
+ return this.post<JobHandle>('/thumbnail', { srcKey, opts });
1103
+ }
1104
+
1105
+ resize(srcKey: string, opts: ResizeOpts): Promise<JobHandle> {
1106
+ return this.post<JobHandle>('/resize', { srcKey, opts });
1107
+ }
1108
+
1109
+ ocr(srcKey: string, opts?: OcrOpts | null): Promise<JobHandle> {
1110
+ return this.post<JobHandle>('/ocr', { srcKey, opts: opts ?? {} });
1111
+ }
1112
+
1113
+ probe(srcKey: string): Promise<MediaInfo> {
1114
+ return this.post<MediaInfo>('/probe', { srcKey });
1115
+ }
1116
+
1117
+ async job(id: string): Promise<JobStatusResponse> {
1118
+ const res = await fetch(`${this.baseUrl}/api/media/transforms/jobs/${encodeURIComponent(id)}`, {
1119
+ method: 'GET',
1120
+ headers: { ...this.headers, ...getRequestAuthHeader() },
1121
+ });
1122
+ if (!res.ok) {
1123
+ const text = await res.text();
1124
+ throw new Error(`Transforms job lookup error (${res.status}): ${text}`);
1125
+ }
1126
+ return res.json() as Promise<JobStatusResponse>;
1127
+ }
1060
1128
  }