@tinycloud/sdk-services 2.1.0-beta.4 → 2.2.0-beta.7
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.cjs +73 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/types.schema.ts","../src/context.ts","../src/errors.ts","../src/base/BaseService.ts","../src/kv/PrefixedKVService.ts","../src/kv/types.ts","../src/kv/KVService.ts","../src/sql/DatabaseHandle.ts","../src/sql/types.ts","../src/sql/SQLService.ts","../src/duckdb/DuckDbDatabaseHandle.ts","../src/duckdb/types.ts","../src/duckdb/DuckDbService.ts","../src/hooks/HooksService.ts","../src/quota/TinyCloudQuota.ts","../src/vault/types.ts","../src/vault/SignatureCache.ts","../src/vault/DataVaultService.ts","../src/vault/createVaultCrypto.ts"],"sourcesContent":["/**\n * TinyCloud SDK Services\n *\n * Platform-agnostic services with plugin architecture for TinyCloud.\n *\n * @packageDocumentation\n * @module @tinycloud/sdk-services\n *\n * @example\n * ```typescript\n * import {\n * ServiceContext,\n * BaseService,\n * Result,\n * ErrorCodes,\n * } from '@tinycloud/sdk-services';\n *\n * // Create a context\n * const context = new ServiceContext({\n * invoke: wasmInvoke,\n * hosts: ['https://node.tinycloud.xyz'],\n * });\n *\n * // Create and register a service\n * const kv = new KVService({ prefix: 'myapp' });\n * context.registerService('kv', kv);\n * kv.initialize(context);\n *\n * // Use the service\n * const result = await kv.get('key');\n * if (result.ok) {\n * console.log(result.data);\n * }\n * ```\n */\n\n// Core types\nexport type {\n Result,\n ServiceError,\n StorageQuotaInfo,\n ErrorCode,\n IServiceContext,\n IService,\n ServiceSession,\n RetryPolicy,\n InvokeFunction,\n InvokeAnyFunction,\n InvokeAnyEntry,\n InvocationFact,\n InvocationFacts,\n FetchFunction,\n FetchRequestInit,\n FetchResponse,\n ServiceHeaders,\n EventHandler,\n ServiceRequestEvent,\n ServiceResponseEvent,\n ServiceErrorEvent,\n ServiceRetryEvent,\n} from \"./types\";\n\nexport {\n ErrorCodes,\n defaultRetryPolicy,\n TelemetryEvents,\n ok,\n err,\n serviceError,\n} from \"./types\";\n\n// Zod schemas and validation\nexport {\n // Schemas\n ServiceErrorSchema,\n KVResponseHeadersSchema,\n KVListResponseSchema,\n ServiceRequestEventSchema,\n ServiceResponseEventSchema,\n ServiceErrorEventSchema,\n ServiceRetryEventSchema,\n RetryPolicySchema,\n ServiceSessionSchema,\n GenericResultSchema,\n GenericKVResponseSchema,\n KVListResultSchema,\n // Schema factories\n createResultSchema,\n createKVResponseSchema,\n // Validation functions\n validateServiceError,\n validateKVListResponse,\n validateKVResponseHeaders,\n validateServiceSession,\n validateRetryPolicy,\n validateServiceRequestEvent,\n validateServiceResponseEvent,\n} from \"./types.schema\";\n\nexport type {\n // Inferred types from schemas\n ValidationError,\n ServiceErrorType,\n KVResponseHeadersType,\n KVListResponseType,\n GenericKVResponseType,\n KVListResultType,\n ServiceRequestEventType,\n ServiceResponseEventType,\n ServiceErrorEventType,\n ServiceRetryEventType,\n RetryPolicyType,\n ServiceSessionType,\n} from \"./types.schema\";\n\n// Context\nexport { ServiceContext } from \"./context\";\nexport type { ServiceContextConfig } from \"./context\";\n\n// Errors\nexport {\n authRequiredError,\n authExpiredError,\n networkError,\n timeoutError,\n abortedError,\n notFoundError,\n permissionDeniedError,\n wrapError,\n errorResult,\n storageQuotaExceededError,\n storageLimitReachedError,\n parseAuthError,\n authUnauthorizedError,\n} from \"./errors\";\n\n// Base service\nexport { BaseService } from \"./base/index\";\nexport type {\n ServiceConstructor,\n ServiceRegistration,\n BaseServiceOptions,\n} from \"./base/index\";\n\n// KV service\nexport { KVService, PrefixedKVService, IKVService, KVAction } from \"./kv\";\nexport type {\n IPrefixedKVService,\n KVServiceConfig,\n KVGetOptions,\n KVPutOptions,\n KVListOptions,\n KVDeleteOptions,\n KVHeadOptions,\n KVResponse,\n KVListResponse,\n KVResponseHeaders,\n KVActionType,\n} from \"./kv\";\n\n// SQL service\nexport { SQLService, DatabaseHandle, SQLAction } from \"./sql\";\nexport type { ISQLService, IDatabaseHandle } from \"./sql\";\nexport type {\n SQLServiceConfig,\n QueryOptions,\n ExecuteOptions,\n BatchOptions,\n SqlValue,\n SqlStatement,\n QueryResponse,\n ExecuteResponse,\n BatchResponse,\n SQLActionType,\n} from \"./sql\";\n\n// DuckDB service\nexport { DuckDbService, DuckDbDatabaseHandle, DuckDbAction } from \"./duckdb\";\nexport type { IDuckDbService, IDuckDbDatabaseHandle } from \"./duckdb\";\nexport type {\n DuckDbServiceConfig,\n DuckDbQueryOptions,\n DuckDbExecuteOptions,\n DuckDbBatchOptions,\n DuckDbOptions,\n DuckDbValue,\n DuckDbStatement,\n DuckDbQueryResponse,\n DuckDbExecuteResponse,\n DuckDbBatchResponse,\n DuckDbActionType,\n SchemaInfo,\n TableInfo,\n ColumnInfo,\n ViewInfo,\n} from \"./duckdb\";\n\n// Hooks service\nexport { HooksService } from \"./hooks\";\nexport type {\n IHooksService,\n HookServiceName,\n HookSubscription,\n HookEvent,\n HookStreamEvent,\n HookWebhookScope,\n HookWebhookRegistration,\n HookWebhookRecord,\n HookWebhookListOptions,\n HookWebhookUnregisterOptions,\n SubscribeOptions,\n HooksServiceConfig,\n} from \"./hooks\";\n\n// Quota\nexport { TinyCloudQuota } from \"./quota\";\nexport type { QuotaConfig, QuotaStatus } from \"./quota\";\n\n// Vault service\nexport {\n DataVaultService,\n VaultHeaders,\n VaultPublicSpaceKVActions,\n createVaultCrypto,\n} from \"./vault\";\nexport type {\n IDataVaultService,\n VaultCrypto,\n WasmVaultFunctions,\n} from \"./vault\";\nexport type {\n DataVaultConfig,\n VaultPutOptions,\n VaultGetOptions,\n VaultListOptions,\n VaultGrantOptions,\n VaultEntry,\n VaultError,\n} from \"./vault\";\n","/**\n * SDK Services - Core Types\n *\n * These types define the service architecture for TinyCloud SDK.\n * Services use dependency injection via IServiceContext for platform independence.\n */\n\n// =============================================================================\n// Result Type Pattern\n// =============================================================================\n\n/**\n * Result type for service operations.\n * Services return Result instead of throwing, making error handling explicit.\n *\n * @template T - The success data type\n * @template E - The error type (defaults to ServiceError)\n *\n * @example\n * ```typescript\n * const result = await kv.get('key');\n * if (result.ok) {\n * console.log(result.data);\n * } else {\n * console.error(result.error.code);\n * }\n * ```\n */\nexport type Result<T, E = ServiceError> =\n | { ok: true; data: T }\n | { ok: false; error: E };\n\n/**\n * Service error with structured information.\n */\nexport interface ServiceError {\n /** Error code for programmatic handling (e.g., 'KV_NOT_FOUND', 'AUTH_EXPIRED') */\n code: string;\n /** Human-readable error message */\n message: string;\n /** Service that produced the error (e.g., 'kv', 'sql') */\n service: string;\n /** Original error if this wraps another error */\n cause?: Error;\n /** Additional metadata about the error */\n meta?: Record<string, unknown>;\n}\n\n/**\n * Storage quota information returned with quota-related errors.\n */\nexport interface StorageQuotaInfo {\n usedBytes: number;\n limitBytes: number;\n service: string;\n}\n\n/**\n * Standard error codes used across services.\n */\nexport const ErrorCodes = {\n // Common errors\n NOT_FOUND: \"NOT_FOUND\",\n AUTH_EXPIRED: \"AUTH_EXPIRED\",\n AUTH_REQUIRED: \"AUTH_REQUIRED\",\n AUTH_UNAUTHORIZED: \"AUTH_UNAUTHORIZED\",\n NETWORK_ERROR: \"NETWORK_ERROR\",\n TIMEOUT: \"TIMEOUT\",\n ABORTED: \"ABORTED\",\n INVALID_INPUT: \"INVALID_INPUT\",\n PERMISSION_DENIED: \"PERMISSION_DENIED\",\n\n // KV-specific errors\n KV_NOT_FOUND: \"KV_NOT_FOUND\",\n KV_WRITE_FAILED: \"KV_WRITE_FAILED\",\n\n // SQL-specific errors\n SQL_ERROR: \"SQL_ERROR\",\n SQL_PERMISSION_DENIED: \"SQL_PERMISSION_DENIED\",\n SQL_DATABASE_NOT_FOUND: \"SQL_DATABASE_NOT_FOUND\",\n SQL_RESPONSE_TOO_LARGE: \"SQL_RESPONSE_TOO_LARGE\",\n SQL_QUOTA_EXCEEDED: \"SQL_QUOTA_EXCEEDED\",\n SQL_INVALID_STATEMENT: \"SQL_INVALID_STATEMENT\",\n SQL_SCHEMA_ERROR: \"SQL_SCHEMA_ERROR\",\n SQL_READONLY_VIOLATION: \"SQL_READONLY_VIOLATION\",\n\n // Storage quota errors\n STORAGE_QUOTA_EXCEEDED: \"STORAGE_QUOTA_EXCEEDED\",\n STORAGE_LIMIT_REACHED: \"STORAGE_LIMIT_REACHED\",\n\n // DuckDB-specific errors\n DUCKDB_ERROR: \"DUCKDB_ERROR\",\n DUCKDB_PERMISSION_DENIED: \"DUCKDB_PERMISSION_DENIED\",\n DUCKDB_DATABASE_NOT_FOUND: \"DUCKDB_DATABASE_NOT_FOUND\",\n DUCKDB_RESPONSE_TOO_LARGE: \"DUCKDB_RESPONSE_TOO_LARGE\",\n DUCKDB_QUOTA_EXCEEDED: \"DUCKDB_QUOTA_EXCEEDED\",\n DUCKDB_INVALID_STATEMENT: \"DUCKDB_INVALID_STATEMENT\",\n DUCKDB_SCHEMA_ERROR: \"DUCKDB_SCHEMA_ERROR\",\n DUCKDB_READONLY_VIOLATION: \"DUCKDB_READONLY_VIOLATION\",\n} as const;\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n\n// =============================================================================\n// Service Session\n// =============================================================================\n\n/**\n * Session data required for authenticated service operations.\n * Both TinyCloudSession and web-sdk Session can be cast to this interface.\n */\nexport interface ServiceSession {\n /** The delegation header containing the UCAN */\n delegationHeader: { Authorization: string };\n /** The delegation CID */\n delegationCid: string;\n /** The space ID for this session */\n spaceId: string;\n /** The verification method DID */\n verificationMethod: string;\n /** The session key JWK (required for invoke) */\n jwk: object;\n}\n\n// =============================================================================\n// Platform Dependencies (Injected)\n// =============================================================================\n\n/**\n * Headers type - compatible with both browser and Node.js.\n */\nexport type ServiceHeaders = Record<string, string> | [string, string][];\n\n/**\n * A single fact object to include in the UCAN invocation.\n * Facts are key-value objects that the server reads from the UCAN facts field.\n */\nexport interface InvocationFact {\n [key: string]: unknown;\n}\n\n/**\n * Facts to include in the UCAN invocation.\n * This is an array of fact objects per the UCAN spec.\n * Used to pass additional parameters that the server reads from the UCAN facts field.\n */\nexport type InvocationFacts = InvocationFact[];\n\n/**\n * Invoke function signature - platform-specific implementation injected via DI.\n * Both node-sdk-wasm and web-sdk-wasm export this with identical signature.\n *\n * @param session - The service session with delegation data\n * @param service - Service name (e.g., \"kv\")\n * @param path - Resource path or key\n * @param action - Action to perform (e.g., \"tinycloud.kv/get\")\n * @param facts - Optional facts to include in the UCAN (e.g., for capabilities/read params)\n * @returns Headers to include in the request\n */\nexport type InvokeFunction = (\n session: ServiceSession,\n service: string,\n path: string,\n action: string,\n facts?: InvocationFacts\n) => ServiceHeaders;\n\n/**\n * Multi-resource invocation entry.\n */\nexport interface InvokeAnyEntry {\n spaceId: string;\n service: string;\n path: string;\n action: string;\n}\n\n/**\n * Invoke function for minting a single authorization header that covers\n * multiple capabilities across one effective invoker.\n */\nexport type InvokeAnyFunction = (\n session: ServiceSession,\n entries: InvokeAnyEntry[],\n facts?: InvocationFacts\n) => ServiceHeaders;\n\n/**\n * Fetch request options - compatible with standard fetch API.\n */\nexport interface FetchRequestInit {\n method?: string;\n headers?: ServiceHeaders;\n body?: Blob | string;\n signal?: AbortSignal;\n}\n\n/**\n * Fetch response interface - compatible with standard Response.\n */\nexport interface FetchResponse {\n ok: boolean;\n status: number;\n statusText: string;\n body?: unknown;\n headers: {\n get(name: string): string | null;\n };\n json(): Promise<unknown>;\n text(): Promise<string>;\n arrayBuffer(): Promise<ArrayBuffer>;\n blob(): Promise<Blob>;\n}\n\n/**\n * Fetch function signature - allows for custom fetch implementations.\n * Compatible with both browser fetch and Node.js fetch.\n */\nexport type FetchFunction = (\n url: string,\n init?: FetchRequestInit\n) => Promise<FetchResponse>;\n\n// =============================================================================\n// Retry Policy\n// =============================================================================\n\n/**\n * Configuration for automatic retry of failed requests.\n */\nexport interface RetryPolicy {\n /** Maximum number of attempts (including initial) */\n maxAttempts: number;\n /** Backoff strategy between retries */\n backoff: \"none\" | \"linear\" | \"exponential\";\n /** Base delay in milliseconds for backoff calculation */\n baseDelayMs: number;\n /** Maximum delay in milliseconds between retries */\n maxDelayMs: number;\n /** Error codes that should trigger a retry */\n retryableErrors: string[];\n}\n\n/**\n * Default retry policy.\n */\nexport const defaultRetryPolicy: RetryPolicy = {\n maxAttempts: 3,\n backoff: \"exponential\",\n baseDelayMs: 1000,\n maxDelayMs: 10000,\n retryableErrors: [ErrorCodes.NETWORK_ERROR, ErrorCodes.TIMEOUT],\n};\n\n// =============================================================================\n// Service Context\n// =============================================================================\n\n/**\n * Event handler function type.\n */\nexport type EventHandler = (data: unknown) => void;\n\n/**\n * Service interface - base contract for all services.\n */\nexport interface IService {\n /** Initialize service with context */\n initialize(context: IServiceContext): void;\n\n /** Called when session changes (sign-in, sign-out, refresh) */\n onSessionChange(session: ServiceSession | null): void;\n\n /** Called when SDK signs out - should abort pending operations */\n onSignOut(): void;\n\n /** Service-specific configuration */\n readonly config: Record<string, unknown>;\n}\n\n/**\n * Context provided to services for accessing platform dependencies.\n * The SDK creates this context and passes it to services during initialization.\n */\nexport interface IServiceContext {\n // Session management\n /** Current active session, or null if not authenticated */\n readonly session: ServiceSession | null;\n /** Whether there is an active authenticated session */\n readonly isAuthenticated: boolean;\n\n // Platform dependencies (injected by SDK)\n /** Platform-specific invoke function from WASM binding */\n readonly invoke: InvokeFunction;\n /** Optional multi-resource invoke function */\n readonly invokeAny?: InvokeAnyFunction;\n /** Fetch function (defaults to globalThis.fetch) */\n readonly fetch: FetchFunction;\n /** Available TinyCloud host URLs */\n readonly hosts: string[];\n\n // Cross-service access\n /** Get another registered service by name */\n getService<T extends IService>(name: string): T | undefined;\n\n // Telemetry/Events\n /** Emit a telemetry event */\n emit(event: string, data: unknown): void;\n /** Subscribe to events */\n on(event: string, handler: EventHandler): () => void;\n\n // Lifecycle\n /** Abort signal that fires when SDK signs out */\n readonly abortSignal: AbortSignal;\n\n // Retry policy\n /** Retry policy for failed requests */\n readonly retryPolicy: RetryPolicy;\n}\n\n// =============================================================================\n// Telemetry Events\n// =============================================================================\n\n/**\n * Event emitted before a service request.\n */\nexport interface ServiceRequestEvent {\n service: string;\n action: string;\n key?: string;\n timestamp: number;\n}\n\n/**\n * Event emitted after a service response.\n */\nexport interface ServiceResponseEvent {\n service: string;\n action: string;\n ok: boolean;\n duration: number;\n status?: number;\n}\n\n/**\n * Event emitted on service error.\n */\nexport interface ServiceErrorEvent {\n service: string;\n error: ServiceError;\n}\n\n/**\n * Event emitted on retry attempt.\n */\nexport interface ServiceRetryEvent {\n service: string;\n attempt: number;\n maxAttempts: number;\n error: ServiceError;\n}\n\n/**\n * Telemetry event names.\n */\nexport const TelemetryEvents = {\n SERVICE_REQUEST: \"service.request\",\n SERVICE_RESPONSE: \"service.response\",\n SERVICE_ERROR: \"service.error\",\n SERVICE_RETRY: \"service.retry\",\n SESSION_CHANGED: \"session.changed\",\n SESSION_EXPIRED: \"session.expired\",\n} as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Create a success result.\n */\nexport function ok<T>(data: T): Result<T> {\n return { ok: true, data };\n}\n\n/**\n * Create an error result.\n */\nexport function err<E = ServiceError>(error: E): Result<never, E> {\n return { ok: false, error };\n}\n\n/**\n * Create a ServiceError.\n */\nexport function serviceError(\n code: string,\n message: string,\n service: string,\n options?: { cause?: Error; meta?: Record<string, unknown> }\n): ServiceError {\n return {\n code,\n message,\n service,\n cause: options?.cause,\n meta: options?.meta,\n };\n}\n","/**\n * Zod schemas for SDK Services API response types.\n *\n * This is the source of truth for service response types. TypeScript types\n * are derived from these schemas using z.infer<>.\n *\n * @packageDocumentation\n */\n\nimport { z } from \"zod\";\n\n// =============================================================================\n// Validation Error Type\n// =============================================================================\n\n/**\n * Validation error type for schema validation failures.\n */\nexport interface ValidationError {\n code: \"VALIDATION_ERROR\";\n message: string;\n service: string;\n meta?: {\n issues: z.ZodIssue[];\n path?: string;\n };\n}\n\n// =============================================================================\n// Service Error Schema\n// =============================================================================\n\n/**\n * Schema for service error with structured information.\n */\nexport const ServiceErrorSchema = z.object({\n /** Error code for programmatic handling (e.g., 'KV_NOT_FOUND', 'AUTH_EXPIRED') */\n code: z.string(),\n /** Human-readable error message */\n message: z.string(),\n /** Service that produced the error (e.g., 'kv', 'sql') */\n service: z.string(),\n /** Original error if this wraps another error - not validated since Error is a class */\n cause: z.unknown().optional(),\n /** Additional metadata about the error - passthrough allows any object properties */\n meta: z.object({}).passthrough().optional(),\n});\n\nexport type ServiceErrorType = z.infer<typeof ServiceErrorSchema>;\n\n// =============================================================================\n// Result Schema Factory\n// =============================================================================\n\n/**\n * Creates a Result schema for a given data type.\n * Result is a discriminated union: { ok: true, data: T } | { ok: false, error: E }\n *\n * @param dataSchema - Zod schema for the success data type\n * @param errorSchema - Zod schema for the error type (defaults to ServiceErrorSchema)\n * @returns A Zod schema for Result<T, E>\n *\n * @example\n * ```typescript\n * const KVGetResultSchema = createResultSchema(z.string());\n * type KVGetResult = z.infer<typeof KVGetResultSchema>;\n * ```\n */\nexport function createResultSchema<T extends z.ZodTypeAny, E extends z.ZodTypeAny>(\n dataSchema: T,\n errorSchema: E = ServiceErrorSchema as unknown as E\n) {\n return z.discriminatedUnion(\"ok\", [\n z.object({\n ok: z.literal(true),\n data: dataSchema,\n }),\n z.object({\n ok: z.literal(false),\n error: errorSchema,\n }),\n ]);\n}\n\n/**\n * Pre-built Result schema with unknown data and ServiceError.\n * Useful for generic validation before type narrowing.\n */\nexport const GenericResultSchema = createResultSchema(z.unknown(), ServiceErrorSchema);\n\n// =============================================================================\n// KV Response Schemas\n// =============================================================================\n\n/**\n * Schema for KV response headers metadata.\n * Note: The `get` method is a function and cannot be validated with Zod.\n * This schema validates the data properties only.\n */\nexport const KVResponseHeadersSchema = z.object({\n /** ETag for conditional requests */\n etag: z.string().optional(),\n /** Content type of the stored value */\n contentType: z.string().optional(),\n /** Last modification timestamp */\n lastModified: z.string().optional(),\n /** Content length in bytes */\n contentLength: z.number().optional(),\n});\n\nexport type KVResponseHeadersType = z.infer<typeof KVResponseHeadersSchema>;\n\n/**\n * Creates a KVResponse schema for a given data type.\n *\n * @param dataSchema - Zod schema for the data payload type\n * @returns A Zod schema for KVResponse<T>\n *\n * @example\n * ```typescript\n * const UserResponseSchema = createKVResponseSchema(UserSchema);\n * type UserResponse = z.infer<typeof UserResponseSchema>;\n * ```\n */\nexport function createKVResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n /** The data payload */\n data: dataSchema,\n /** Response headers with metadata */\n headers: KVResponseHeadersSchema,\n });\n}\n\n/**\n * Generic KVResponse schema with unknown data.\n * Useful for generic validation before type narrowing.\n */\nexport const GenericKVResponseSchema = createKVResponseSchema(z.unknown());\n\nexport type GenericKVResponseType = z.infer<typeof GenericKVResponseSchema>;\n\n/**\n * Schema for KV list response.\n */\nexport const KVListResponseSchema = z.object({\n /** Array of keys matching the list criteria */\n keys: z.array(z.string()),\n});\n\nexport type KVListResponseType = z.infer<typeof KVListResponseSchema>;\n\n/**\n * Result schema for KV list operations.\n */\nexport const KVListResultSchema = createResultSchema(KVListResponseSchema);\n\nexport type KVListResultType = z.infer<typeof KVListResultSchema>;\n\n// =============================================================================\n// Telemetry Event Schemas\n// =============================================================================\n\n/**\n * Schema for service request event.\n */\nexport const ServiceRequestEventSchema = z.object({\n service: z.string(),\n action: z.string(),\n key: z.string().optional(),\n timestamp: z.number(),\n});\n\nexport type ServiceRequestEventType = z.infer<typeof ServiceRequestEventSchema>;\n\n/**\n * Schema for service response event.\n */\nexport const ServiceResponseEventSchema = z.object({\n service: z.string(),\n action: z.string(),\n ok: z.boolean(),\n duration: z.number(),\n status: z.number().optional(),\n});\n\nexport type ServiceResponseEventType = z.infer<typeof ServiceResponseEventSchema>;\n\n/**\n * Schema for service error event.\n */\nexport const ServiceErrorEventSchema = z.object({\n service: z.string(),\n error: ServiceErrorSchema,\n});\n\nexport type ServiceErrorEventType = z.infer<typeof ServiceErrorEventSchema>;\n\n/**\n * Schema for service retry event.\n */\nexport const ServiceRetryEventSchema = z.object({\n service: z.string(),\n attempt: z.number().int().positive(),\n maxAttempts: z.number().int().positive(),\n error: ServiceErrorSchema,\n});\n\nexport type ServiceRetryEventType = z.infer<typeof ServiceRetryEventSchema>;\n\n// =============================================================================\n// Retry Policy Schema\n// =============================================================================\n\n/**\n * Schema for retry policy configuration.\n */\nexport const RetryPolicySchema = z.object({\n /** Maximum number of attempts (including initial) */\n maxAttempts: z.number().int().positive(),\n /** Backoff strategy between retries */\n backoff: z.enum([\"none\", \"linear\", \"exponential\"]),\n /** Base delay in milliseconds for backoff calculation */\n baseDelayMs: z.number().nonnegative(),\n /** Maximum delay in milliseconds between retries */\n maxDelayMs: z.number().nonnegative(),\n /** Error codes that should trigger a retry */\n retryableErrors: z.array(z.string()),\n});\n\nexport type RetryPolicyType = z.infer<typeof RetryPolicySchema>;\n\n// =============================================================================\n// Service Session Schema\n// =============================================================================\n\n/**\n * Schema for service session data required for authenticated operations.\n */\nexport const ServiceSessionSchema = z.object({\n /** The delegation header containing the UCAN */\n delegationHeader: z.object({\n Authorization: z.string(),\n }),\n /** The delegation CID */\n delegationCid: z.string(),\n /** The space ID for this session */\n spaceId: z.string(),\n /** The verification method DID */\n verificationMethod: z.string(),\n /** The session key JWK (required for invoke) */\n jwk: z.object({}).passthrough(),\n});\n\nexport type ServiceSessionType = z.infer<typeof ServiceSessionSchema>;\n\n// =============================================================================\n// Validation Helpers\n// =============================================================================\n\n/**\n * Validate service error against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateServiceError(\n data: unknown\n): { ok: true; data: ServiceErrorType } | { ok: false; error: ValidationError } {\n const result = ServiceErrorSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"validation\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate KV list response against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateKVListResponse(\n data: unknown\n): { ok: true; data: KVListResponseType } | { ok: false; error: ValidationError } {\n const result = KVListResponseSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"kv\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate KV response headers against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateKVResponseHeaders(\n data: unknown\n): { ok: true; data: KVResponseHeadersType } | { ok: false; error: ValidationError } {\n const result = KVResponseHeadersSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"kv\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate service session against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateServiceSession(\n data: unknown\n): { ok: true; data: ServiceSessionType } | { ok: false; error: ValidationError } {\n const result = ServiceSessionSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"session\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate retry policy against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateRetryPolicy(\n data: unknown\n): { ok: true; data: RetryPolicyType } | { ok: false; error: ValidationError } {\n const result = RetryPolicySchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"config\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate service request event against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateServiceRequestEvent(\n data: unknown\n): { ok: true; data: ServiceRequestEventType } | { ok: false; error: ValidationError } {\n const result = ServiceRequestEventSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"telemetry\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate service response event against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateServiceResponseEvent(\n data: unknown\n): { ok: true; data: ServiceResponseEventType } | { ok: false; error: ValidationError } {\n const result = ServiceResponseEventSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"telemetry\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n","/**\n * ServiceContext implementation for TinyCloud SDK Services\n * @module @tinycloud/sdk-services\n */\n\nimport {\n IServiceContext,\n IService,\n ServiceSession,\n RetryPolicy,\n InvokeFunction,\n InvokeAnyFunction,\n FetchFunction,\n defaultRetryPolicy,\n} from \"./types\";\n\n/**\n * Event handler type for telemetry events.\n */\ntype EventHandler = (data: unknown) => void;\n\n/**\n * Configuration options for ServiceContext.\n */\nexport interface ServiceContextConfig {\n /** Function to invoke WASM operations */\n invoke: InvokeFunction;\n /** Optional function to mint a single authorization header for multiple capabilities */\n invokeAny?: InvokeAnyFunction;\n /** Function to make HTTP requests (defaults to globalThis.fetch) */\n fetch?: FetchFunction;\n /** List of TinyCloud host URLs */\n hosts: string[];\n /** Initial session (optional) */\n session?: ServiceSession | null;\n /** Retry policy configuration */\n retryPolicy?: Partial<RetryPolicy>;\n}\n\n/**\n * ServiceContext provides platform dependencies and cross-service access to services.\n * This is the primary interface services use to interact with the SDK runtime.\n *\n * @example\n * ```typescript\n * const context = new ServiceContext({\n * invoke: wasmInvoke,\n * hosts: ['https://node.tinycloud.xyz'],\n * retryPolicy: { maxAttempts: 5 },\n * });\n *\n * // Register a service\n * const kvService = new KVService({});\n * context.registerService('kv', kvService);\n * kvService.initialize(context);\n *\n * // Update session when user signs in\n * context.setSession(userSession);\n * ```\n */\nexport class ServiceContext implements IServiceContext {\n private _session: ServiceSession | null = null;\n private _services: Map<string, IService> = new Map();\n private _eventHandlers: Map<string, Set<EventHandler>> = new Map();\n private _abortController: AbortController = new AbortController();\n private readonly _invoke: InvokeFunction;\n private readonly _invokeAny?: InvokeAnyFunction;\n private readonly _fetch: FetchFunction;\n private readonly _hosts: string[];\n private readonly _retryPolicy: RetryPolicy;\n\n constructor(config: ServiceContextConfig) {\n this._invoke = config.invoke;\n this._invokeAny = config.invokeAny;\n this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);\n this._hosts = config.hosts;\n this._session = config.session ?? null;\n this._retryPolicy = {\n ...defaultRetryPolicy,\n ...config.retryPolicy,\n };\n }\n\n // ============================================================\n // Session Management\n // ============================================================\n\n /**\n * Get the current session.\n */\n get session(): ServiceSession | null {\n return this._session;\n }\n\n /**\n * Check if the context has an authenticated session.\n */\n get isAuthenticated(): boolean {\n return this._session !== null;\n }\n\n /**\n * Update the session and notify all registered services.\n *\n * @param session - New session or null to clear\n */\n setSession(session: ServiceSession | null): void {\n this._session = session;\n this.emit('session.changed', { authenticated: session !== null });\n\n // Notify all services of session change\n for (const service of this._services.values()) {\n service.onSessionChange(session);\n }\n }\n\n // ============================================================\n // Platform Dependencies\n // ============================================================\n\n /**\n * Get the invoke function for WASM operations.\n */\n get invoke(): InvokeFunction {\n return this._invoke;\n }\n\n /**\n * Get the multi-resource invoke function when available.\n */\n get invokeAny(): InvokeAnyFunction | undefined {\n return this._invokeAny;\n }\n\n /**\n * Get the fetch function for HTTP requests.\n */\n get fetch(): FetchFunction {\n return this._fetch;\n }\n\n /**\n * Get the list of TinyCloud host URLs.\n */\n get hosts(): string[] {\n return this._hosts;\n }\n\n // ============================================================\n // Service Registry\n // ============================================================\n\n /**\n * Register a service with the context.\n *\n * @param name - Service name (e.g., 'kv')\n * @param service - Service instance\n */\n registerService(name: string, service: IService): void {\n this._services.set(name, service);\n }\n\n /**\n * Unregister a service from the context.\n *\n * @param name - Service name to remove\n */\n unregisterService(name: string): void {\n this._services.delete(name);\n }\n\n /**\n * Get a registered service by name.\n *\n * @param name - Service name\n * @returns The service instance or undefined if not registered\n */\n getService<T extends IService>(name: string): T | undefined {\n return this._services.get(name) as T | undefined;\n }\n\n // ============================================================\n // Event System (Telemetry)\n // ============================================================\n\n /**\n * Emit a telemetry event.\n *\n * @param event - Event name\n * @param data - Event data\n */\n emit(event: string, data: unknown): void {\n const handlers = this._eventHandlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(data);\n } catch (error) {\n // Don't let event handler errors break the flow\n console.error(`Error in event handler for \"${event}\":`, error);\n }\n }\n }\n }\n\n /**\n * Subscribe to telemetry events.\n *\n * @param event - Event name to subscribe to\n * @param handler - Handler function\n * @returns Unsubscribe function\n */\n on(event: string, handler: EventHandler): () => void {\n if (!this._eventHandlers.has(event)) {\n this._eventHandlers.set(event, new Set());\n }\n this._eventHandlers.get(event)!.add(handler);\n\n // Return unsubscribe function\n return () => {\n const handlers = this._eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this._eventHandlers.delete(event);\n }\n }\n };\n }\n\n /**\n * Remove all event handlers for an event.\n *\n * @param event - Event name (if omitted, clears all events)\n */\n clearEventHandlers(event?: string): void {\n if (event) {\n this._eventHandlers.delete(event);\n } else {\n this._eventHandlers.clear();\n }\n }\n\n // ============================================================\n // Lifecycle\n // ============================================================\n\n /**\n * Get the abort signal for cancelling operations.\n */\n get abortSignal(): AbortSignal {\n return this._abortController.signal;\n }\n\n /**\n * Abort all pending operations and notify services.\n * Creates a new AbortController for future operations.\n */\n abort(): void {\n this._abortController.abort();\n this._abortController = new AbortController();\n\n // Notify all services\n for (const service of this._services.values()) {\n service.onSignOut();\n }\n }\n\n /**\n * Sign out - abort operations and clear session.\n */\n signOut(): void {\n this.abort();\n this.setSession(null);\n this.emit('session.expired', {});\n }\n\n // ============================================================\n // Retry Policy\n // ============================================================\n\n /**\n * Get the retry policy configuration.\n */\n get retryPolicy(): RetryPolicy {\n return this._retryPolicy;\n }\n}\n","/**\n * SDK Services - Error Utilities\n *\n * Utilities for creating and handling service errors.\n */\n\nimport { ServiceError, ErrorCodes, err, serviceError } from \"./types\";\n\n/**\n * Create a service error for authentication required.\n */\nexport function authRequiredError(service: string): ServiceError {\n return {\n code: ErrorCodes.AUTH_REQUIRED,\n message: \"Authentication required. Please sign in first.\",\n service,\n };\n}\n\n/**\n * Create a service error for expired authentication.\n */\nexport function authExpiredError(service: string): ServiceError {\n return {\n code: ErrorCodes.AUTH_EXPIRED,\n message: \"Session has expired. Please sign in again.\",\n service,\n };\n}\n\n/**\n * Create a service error for network issues.\n */\nexport function networkError(\n service: string,\n message: string,\n cause?: Error\n): ServiceError {\n return {\n code: ErrorCodes.NETWORK_ERROR,\n message,\n service,\n cause,\n };\n}\n\n/**\n * Create a service error for timeouts.\n */\nexport function timeoutError(service: string): ServiceError {\n return {\n code: ErrorCodes.TIMEOUT,\n message: \"Request timed out.\",\n service,\n };\n}\n\n/**\n * Create a service error for aborted requests.\n */\nexport function abortedError(service: string): ServiceError {\n return {\n code: ErrorCodes.ABORTED,\n message: \"Request was aborted.\",\n service,\n };\n}\n\n/**\n * Create a service error for not found resources.\n */\nexport function notFoundError(\n service: string,\n resource: string\n): ServiceError {\n return {\n code: ErrorCodes.NOT_FOUND,\n message: `Resource not found: ${resource}`,\n service,\n };\n}\n\n/**\n * Create a service error for permission denied.\n */\nexport function permissionDeniedError(\n service: string,\n action: string\n): ServiceError {\n return {\n code: ErrorCodes.PERMISSION_DENIED,\n message: `Permission denied for action: ${action}`,\n service,\n };\n}\n\n/**\n * Parse the server's \"Unauthorized Action: {resource} / {ability}\" pattern.\n */\nexport function parseAuthError(responseText: string): { resource?: string; action?: string } {\n const match = responseText.match(/^Unauthorized Action:\\s*(.+?)\\s*\\/\\s*(tinycloud\\.\\S+)$/m);\n if (match) {\n return { resource: match[1].trim(), action: match[2].trim() };\n }\n return {};\n}\n\n/**\n * Create a service error for unauthorized action (missing capability).\n */\nexport function authUnauthorizedError(\n service: string,\n message: string,\n meta?: Record<string, unknown>\n): ServiceError {\n return serviceError(ErrorCodes.AUTH_UNAUTHORIZED, message, service, { meta });\n}\n\n/**\n * Create a service error for storage quota exceeded (402 Payment Required).\n */\nexport function storageQuotaExceededError(\n service: string,\n message: string,\n meta?: Record<string, unknown>\n): ServiceError {\n return {\n code: ErrorCodes.STORAGE_QUOTA_EXCEEDED,\n message,\n service,\n meta,\n };\n}\n\n/**\n * Create a service error for storage limit reached (413 Payload Too Large).\n */\nexport function storageLimitReachedError(\n service: string,\n message: string,\n meta?: Record<string, unknown>\n): ServiceError {\n return {\n code: ErrorCodes.STORAGE_LIMIT_REACHED,\n message,\n service,\n meta,\n };\n}\n\n/**\n * Wrap an unknown error in a ServiceError.\n */\nexport function wrapError(\n service: string,\n error: unknown,\n defaultCode: string = ErrorCodes.NETWORK_ERROR\n): ServiceError {\n if (error instanceof Error) {\n // Check for abort errors\n if (error.name === \"AbortError\") {\n return abortedError(service);\n }\n\n // Check for timeout errors (varies by platform)\n if (\n error.name === \"TimeoutError\" ||\n error.message.toLowerCase().includes(\"timeout\")\n ) {\n return timeoutError(service);\n }\n\n return {\n code: defaultCode,\n message: error.message,\n service,\n cause: error,\n };\n }\n\n return {\n code: defaultCode,\n message: String(error),\n service,\n };\n}\n\n/**\n * Create an error Result from a ServiceError.\n */\nexport function errorResult(error: ServiceError) {\n return err(error);\n}\n","/**\n * BaseService - Abstract base class for all TinyCloud services.\n *\n * Provides common functionality:\n * - Context management\n * - Session lifecycle hooks\n * - Abort signal handling\n * - Telemetry emission\n */\n\nimport {\n IService,\n IServiceContext,\n ServiceSession,\n ServiceError,\n TelemetryEvents,\n err,\n Result,\n} from \"../types\";\nimport { authRequiredError, wrapError } from \"../errors\";\n\n/**\n * Abstract base class for TinyCloud services.\n *\n * Services extend this class to get common functionality like\n * context management, session lifecycle, and abort handling.\n *\n * @example\n * ```typescript\n * class MyService extends BaseService implements IMyService {\n * static readonly serviceName = 'myservice';\n *\n * constructor(config: MyServiceConfig = {}) {\n * super();\n * this._config = config;\n * }\n *\n * async doSomething(): Promise<Result<Data>> {\n * if (!this.requireAuth()) {\n * return err(authRequiredError('myservice'));\n * }\n * // ... implementation\n * }\n * }\n * ```\n */\nexport abstract class BaseService implements IService {\n /**\n * Service identifier used for registration.\n * Must be overridden by subclasses.\n */\n static readonly serviceName: string;\n\n /**\n * Service context providing access to platform dependencies.\n * Set during initialize().\n */\n protected context!: IServiceContext;\n\n /**\n * Abort controller for this service's operations.\n * Reset on sign-out.\n */\n protected abortController: AbortController = new AbortController();\n\n /**\n * Service-specific configuration.\n */\n protected _config: Record<string, unknown> = {};\n\n /**\n * Get the service configuration.\n */\n get config(): Record<string, unknown> {\n return this._config;\n }\n\n /**\n * Initialize the service with context.\n * Called by the SDK after instantiation.\n *\n * @param context - The service context\n */\n initialize(context: IServiceContext): void {\n this.context = context;\n }\n\n /**\n * Called when session changes (sign-in, sign-out, refresh).\n * Override in subclasses to handle session changes.\n *\n * @param session - The new session, or null if signed out\n */\n onSessionChange(session: ServiceSession | null): void {\n // Override in subclass if needed\n }\n\n /**\n * Called when SDK signs out.\n * Aborts all pending operations.\n */\n onSignOut(): void {\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n /**\n * Get the abort signal for this service.\n * Combines the service-level abort with context-level abort.\n */\n protected get abortSignal(): AbortSignal {\n return this.abortController.signal;\n }\n\n /**\n * Check if the service is authenticated.\n */\n protected get isAuthenticated(): boolean {\n return this.context?.isAuthenticated ?? false;\n }\n\n /**\n * Get the current session.\n * Throws if not authenticated.\n */\n protected get session(): ServiceSession {\n if (!this.context?.session) {\n throw new Error(\"Not authenticated\");\n }\n return this.context.session;\n }\n\n /**\n * Check authentication and return error result if not authenticated.\n * Use this at the start of methods that require authentication.\n *\n * @returns true if authenticated, false otherwise\n */\n protected requireAuth(): boolean {\n return this.isAuthenticated;\n }\n\n /**\n * Emit a telemetry event.\n *\n * @param event - Event name\n * @param data - Event data\n */\n protected emit(event: string, data: unknown): void {\n this.context?.emit(event, data);\n }\n\n /**\n * Emit a service request event.\n *\n * @param action - The action being performed\n * @param key - Optional key/path being accessed\n */\n protected emitRequest(action: string, key?: string): void {\n this.emit(TelemetryEvents.SERVICE_REQUEST, {\n service: this.getServiceName(),\n action,\n key,\n timestamp: Date.now(),\n });\n }\n\n /**\n * Emit a service response event.\n *\n * @param action - The action that was performed\n * @param ok - Whether the request was successful\n * @param startTime - Start time for duration calculation\n * @param status - Optional HTTP status code\n */\n protected emitResponse(\n action: string,\n ok: boolean,\n startTime: number,\n status?: number\n ): void {\n this.emit(TelemetryEvents.SERVICE_RESPONSE, {\n service: this.getServiceName(),\n action,\n ok,\n duration: Date.now() - startTime,\n status,\n });\n }\n\n /**\n * Emit a service error event.\n *\n * @param error - The service error\n */\n protected emitError(error: ServiceError): void {\n this.emit(TelemetryEvents.SERVICE_ERROR, {\n service: this.getServiceName(),\n error,\n });\n }\n\n /**\n * Get the service name from the static property.\n * Subclasses must define static serviceName.\n */\n protected getServiceName(): string {\n return (this.constructor as typeof BaseService).serviceName;\n }\n\n /**\n * Create a combined abort signal from multiple sources.\n *\n * @param signals - Additional abort signals to combine\n * @returns A combined abort signal\n */\n protected combineSignals(...signals: (AbortSignal | undefined)[]): AbortSignal {\n const controller = new AbortController();\n const allSignals = [this.abortSignal, ...signals.filter(Boolean)] as AbortSignal[];\n\n for (const signal of allSignals) {\n if (signal.aborted) {\n controller.abort(signal.reason);\n return controller.signal;\n }\n signal.addEventListener(\"abort\", () => controller.abort(signal.reason), {\n once: true,\n });\n }\n\n return controller.signal;\n }\n\n /**\n * Wrap an operation with error handling and telemetry.\n *\n * @param action - The action name for telemetry\n * @param key - Optional key for telemetry\n * @param operation - The operation to execute\n * @returns Result of the operation\n */\n protected async withTelemetry<T>(\n action: string,\n key: string | undefined,\n operation: () => Promise<Result<T>>\n ): Promise<Result<T>> {\n const startTime = Date.now();\n this.emitRequest(action, key);\n\n try {\n const result = await operation();\n\n if (result.ok) {\n this.emitResponse(action, true, startTime);\n } else {\n this.emitResponse(action, false, startTime);\n this.emitError(result.error);\n }\n\n return result;\n } catch (error) {\n const serviceError = wrapError(this.getServiceName(), error);\n this.emitResponse(action, false, startTime);\n this.emitError(serviceError);\n return err(serviceError);\n }\n }\n}\n","/**\n * PrefixedKVService - A prefix-scoped view of KVService.\n *\n * Provides key-value operations scoped to a specific prefix.\n * All operations automatically prefix keys, enabling app data isolation\n * within a shared space.\n *\n * @example\n * ```typescript\n * const space = sdk.space('default');\n *\n * // Create prefix-scoped views\n * const myApp = space.kv.withPrefix('/app.myapp.com');\n * const sharedPhotos = space.kv.withPrefix('/photos');\n *\n * // Operations are automatically prefixed\n * await myApp.put('settings.json', { theme: 'dark' });\n * // -> Actually writes to: /app.myapp.com/settings.json\n *\n * await myApp.get('settings.json');\n * // -> Actually reads from: /app.myapp.com/settings.json\n *\n * await sharedPhotos.list();\n * // -> Lists: /photos/*\n *\n * // Nested prefixes\n * const settings = myApp.withPrefix('/settings');\n * await settings.get('theme.json'); // -> /app.myapp.com/settings/theme.json\n * ```\n */\n\nimport { Result } from \"../types\";\nimport {\n KVGetOptions,\n KVPutOptions,\n KVListOptions,\n KVDeleteOptions,\n KVHeadOptions,\n KVResponse,\n KVListResponse,\n} from \"./types\";\n\n/**\n * Interface for prefixed KV operations.\n *\n * Provides the same operations as IKVService but scoped to a prefix.\n * Supports nested prefixes via withPrefix().\n */\nexport interface IPrefixedKVService {\n /**\n * The current prefix for this scoped view.\n */\n readonly prefix: string;\n\n /**\n * Get a value by key.\n *\n * The key is automatically prefixed with this service's prefix.\n *\n * @param key - The key to retrieve (will be prefixed)\n * @param options - Optional get configuration\n * @returns Result with the stored value and headers\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * const result = await myApp.get('settings.json');\n * // -> Reads from: /app.myapp.com/settings.json\n * ```\n */\n get<T = unknown>(\n key: string,\n options?: Omit<KVGetOptions, 'prefix'>\n ): Promise<Result<KVResponse<T>>>;\n\n /**\n * Store a value at a key.\n *\n * The key is automatically prefixed with this service's prefix.\n *\n * @param key - The key to store under (will be prefixed)\n * @param value - The value to store\n * @param options - Optional put configuration\n * @returns Result indicating success/failure\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * await myApp.put('settings.json', { theme: 'dark' });\n * // -> Stores at: /app.myapp.com/settings.json\n * ```\n */\n put(\n key: string,\n value: unknown,\n options?: Omit<KVPutOptions, 'prefix'>\n ): Promise<Result<KVResponse<void>>>;\n\n /**\n * List keys within this prefix.\n *\n * Returns keys that match the prefix, with keys returned relative\n * to the prefix when removePrefix is true (default for prefixed service).\n *\n * @param options - Optional list configuration\n * @returns Result with array of matching keys\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * const result = await myApp.list();\n * // -> Lists keys under: /app.myapp.com/*\n * // Returns: ['settings.json', 'data/user.json', ...]\n * ```\n */\n list(options?: Omit<KVListOptions, 'prefix'>): Promise<Result<KVListResponse>>;\n\n /**\n * Delete a key.\n *\n * The key is automatically prefixed with this service's prefix.\n *\n * @param key - The key to delete (will be prefixed)\n * @param options - Optional delete configuration\n * @returns Result indicating success/failure\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * await myApp.delete('old-settings.json');\n * // -> Deletes: /app.myapp.com/old-settings.json\n * ```\n */\n delete(key: string, options?: Omit<KVDeleteOptions, 'prefix'>): Promise<Result<void>>;\n\n /**\n * Get metadata for a key without retrieving the value.\n *\n * The key is automatically prefixed with this service's prefix.\n *\n * @param key - The key to check (will be prefixed)\n * @param options - Optional head configuration\n * @returns Result with headers only\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * const result = await myApp.head('large-file.bin');\n * // -> Gets metadata for: /app.myapp.com/large-file.bin\n * ```\n */\n head(key: string, options?: Omit<KVHeadOptions, 'prefix'>): Promise<Result<KVResponse<void>>>;\n\n /**\n * Create a nested prefix-scoped view.\n *\n * The subPrefix is appended to the current prefix.\n *\n * @param subPrefix - The sub-prefix to append\n * @returns A new PrefixedKVService with the combined prefix\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * const settings = myApp.withPrefix('/settings');\n * await settings.get('theme.json');\n * // -> Reads from: /app.myapp.com/settings/theme.json\n * ```\n */\n withPrefix(subPrefix: string): IPrefixedKVService;\n}\n\n/**\n * Interface for a KV service that supports prefix delegation.\n *\n * This is the subset of IKVService methods needed by PrefixedKVService.\n */\ninterface IKVServiceLike {\n get<T = unknown>(\n key: string,\n options?: KVGetOptions\n ): Promise<Result<KVResponse<T>>>;\n\n put(\n key: string,\n value: unknown,\n options?: KVPutOptions\n ): Promise<Result<KVResponse<void>>>;\n\n list(options?: KVListOptions): Promise<Result<KVListResponse>>;\n\n delete(key: string, options?: KVDeleteOptions): Promise<Result<void>>;\n\n head(key: string, options?: KVHeadOptions): Promise<Result<KVResponse<void>>>;\n}\n\n/**\n * PrefixedKVService - Implementation of prefix-scoped KV operations.\n *\n * This class wraps a KVService (or another PrefixedKVService) and\n * automatically prefixes all key operations with the configured prefix.\n *\n * ## Prefix Convention\n *\n * | Pattern | Use Case | Example |\n * | -- | -- | -- |\n * | `/app.{domain}/` | App-private data | `/app.photos.xyz/settings.json` |\n * | `/{type}/` | Shared data type | `/photos/vacation.jpg` |\n * | `/.{name}/` | Hidden/system data | `/.cache/thumbnails/` |\n * | `/public/` | Explicitly shareable | `/public/profile.json` |\n *\n * @example\n * ```typescript\n * // Create from KVService\n * const prefixed = new PrefixedKVService(kvService, '/app.myapp.com');\n *\n * // Or use the withPrefix factory method on KVService\n * const prefixed = kvService.withPrefix('/app.myapp.com');\n *\n * // All operations are automatically prefixed\n * await prefixed.put('settings.json', { theme: 'dark' });\n * await prefixed.get('settings.json');\n *\n * // Nested prefixes\n * const nested = prefixed.withPrefix('/settings');\n * await nested.get('theme.json'); // -> /app.myapp.com/settings/theme.json\n * ```\n */\nexport class PrefixedKVService implements IPrefixedKVService {\n /**\n * The underlying KV service.\n */\n private readonly _kv: IKVServiceLike;\n\n /**\n * The prefix for this scoped view.\n */\n private readonly _prefix: string;\n\n /**\n * Create a new PrefixedKVService.\n *\n * @param kv - The underlying KV service to delegate to\n * @param prefix - The prefix to apply to all operations\n */\n constructor(kv: IKVServiceLike, prefix: string) {\n this._kv = kv;\n // Normalize prefix: ensure it doesn't end with slash\n this._prefix = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n }\n\n /**\n * The current prefix for this scoped view.\n */\n get prefix(): string {\n return this._prefix;\n }\n\n /**\n * Compute the full key path by combining prefix and key.\n *\n * @param key - The key to prefix\n * @returns The full path including prefix\n */\n private getFullKey(key: string): string {\n // Handle keys that start with slash\n const normalizedKey = key.startsWith('/') ? key : `/${key}`;\n return `${this._prefix}${normalizedKey}`;\n }\n\n /**\n * Get a value by key.\n */\n async get<T = unknown>(\n key: string,\n options?: Omit<KVGetOptions, 'prefix'>\n ): Promise<Result<KVResponse<T>>> {\n const fullKey = this.getFullKey(key);\n // Use empty prefix override to use the full key as-is\n return this._kv.get<T>(fullKey, { ...options, prefix: '' });\n }\n\n /**\n * Store a value at a key.\n */\n async put(\n key: string,\n value: unknown,\n options?: Omit<KVPutOptions, 'prefix'>\n ): Promise<Result<KVResponse<void>>> {\n const fullKey = this.getFullKey(key);\n return this._kv.put(fullKey, value, { ...options, prefix: '' });\n }\n\n /**\n * List keys within this prefix.\n */\n async list(options?: Omit<KVListOptions, 'prefix'>): Promise<Result<KVListResponse>> {\n // List uses the prefix directly, and by default removes the prefix from results\n const removePrefix = options?.removePrefix ?? true;\n return this._kv.list({\n ...options,\n prefix: this._prefix,\n removePrefix,\n });\n }\n\n /**\n * Delete a key.\n */\n async delete(key: string, options?: Omit<KVDeleteOptions, 'prefix'>): Promise<Result<void>> {\n const fullKey = this.getFullKey(key);\n return this._kv.delete(fullKey, { ...options, prefix: '' });\n }\n\n /**\n * Get metadata for a key without retrieving the value.\n */\n async head(\n key: string,\n options?: Omit<KVHeadOptions, 'prefix'>\n ): Promise<Result<KVResponse<void>>> {\n const fullKey = this.getFullKey(key);\n return this._kv.head(fullKey, { ...options, prefix: '' });\n }\n\n /**\n * Create a nested prefix-scoped view.\n */\n withPrefix(subPrefix: string): IPrefixedKVService {\n // Normalize subPrefix\n const normalizedSubPrefix = subPrefix.startsWith('/')\n ? subPrefix\n : `/${subPrefix}`;\n const combinedPrefix = `${this._prefix}${normalizedSubPrefix}`;\n return new PrefixedKVService(this._kv, combinedPrefix);\n }\n}\n","/**\n * KV Service Types\n *\n * Type definitions for the KV (Key-Value) service operations.\n */\n\n/**\n * Configuration for KVService.\n */\nexport interface KVServiceConfig {\n /**\n * Default prefix for all keys.\n * Useful for namespacing data within a space.\n *\n * @example\n * ```typescript\n * const kv = new KVService({ prefix: 'myapp/settings' });\n * await kv.put('theme', 'dark'); // Stores at 'myapp/settings/theme'\n * ```\n */\n prefix?: string;\n\n /**\n * Default timeout in milliseconds for KV operations.\n * Overrides the context-level timeout if set.\n */\n timeout?: number;\n\n /** Allow additional config properties */\n [key: string]: unknown;\n}\n\n/**\n * Options for KV get operations.\n */\nexport interface KVGetOptions {\n /**\n * Override the default prefix for this operation.\n */\n prefix?: string;\n\n /**\n * Return raw response instead of parsed JSON.\n * When true, data will be the raw response text.\n */\n raw?: boolean;\n\n /**\n * Custom timeout for this operation in milliseconds.\n */\n timeout?: number;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for KV put operations.\n */\nexport interface KVPutOptions {\n /**\n * Override the default prefix for this operation.\n */\n prefix?: string;\n\n /**\n * Content type for the value.\n * Defaults to 'application/json' for objects.\n */\n contentType?: string;\n\n /**\n * Custom metadata headers to store with the value.\n */\n metadata?: Record<string, string>;\n\n /**\n * Custom timeout for this operation in milliseconds.\n */\n timeout?: number;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for KV list operations.\n */\nexport interface KVListOptions {\n /**\n * Override the default prefix for this operation.\n */\n prefix?: string;\n\n /**\n * Additional path to append to the prefix.\n */\n path?: string;\n\n /**\n * Whether to remove the prefix from returned keys.\n * When true, keys are returned relative to the prefix.\n */\n removePrefix?: boolean;\n\n /**\n * Return raw response instead of parsed JSON.\n */\n raw?: boolean;\n\n /**\n * Custom timeout for this operation in milliseconds.\n */\n timeout?: number;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for KV delete operations.\n */\nexport interface KVDeleteOptions {\n /**\n * Override the default prefix for this operation.\n */\n prefix?: string;\n\n /**\n * Custom timeout for this operation in milliseconds.\n */\n timeout?: number;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for KV head (metadata) operations.\n */\nexport interface KVHeadOptions {\n /**\n * Override the default prefix for this operation.\n */\n prefix?: string;\n\n /**\n * Custom timeout for this operation in milliseconds.\n */\n timeout?: number;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Response headers from KV operations.\n */\nexport interface KVResponseHeaders {\n /**\n * ETag for conditional requests.\n */\n etag?: string;\n\n /**\n * Content type of the stored value.\n */\n contentType?: string;\n\n /**\n * Last modification timestamp.\n */\n lastModified?: string;\n\n /**\n * Content length in bytes.\n */\n contentLength?: number;\n\n /**\n * Get a header value by name.\n * @param name - Header name (case-insensitive)\n */\n get(name: string): string | null;\n}\n\n/**\n * Response from KV get/put operations.\n *\n * @template T - Type of the data payload\n */\nexport interface KVResponse<T = unknown> {\n /**\n * The data payload.\n * For get: the stored value.\n * For put: undefined.\n */\n data: T;\n\n /**\n * Response headers with metadata.\n */\n headers: KVResponseHeaders;\n}\n\n/**\n * Response from KV list operations.\n */\nexport interface KVListResponse {\n /**\n * Array of keys matching the list criteria.\n */\n keys: string[];\n}\n\n/**\n * KV service action types.\n */\nexport const KVAction = {\n GET: \"tinycloud.kv/get\",\n PUT: \"tinycloud.kv/put\",\n LIST: \"tinycloud.kv/list\",\n DELETE: \"tinycloud.kv/del\",\n HEAD: \"tinycloud.kv/metadata\",\n} as const;\n\nexport type KVActionType = (typeof KVAction)[keyof typeof KVAction];\n","/**\n * KVService - Key-Value storage service implementation.\n *\n * Platform-agnostic KV service that works with both web-sdk and node-sdk.\n * Uses dependency injection via IServiceContext for platform dependencies.\n */\n\nimport { BaseService } from \"../base/BaseService\";\nimport {\n Result,\n ok,\n err,\n ErrorCodes,\n serviceError,\n FetchResponse,\n} from \"../types\";\nimport {\n authRequiredError,\n wrapError,\n storageQuotaExceededError,\n storageLimitReachedError,\n parseAuthError,\n authUnauthorizedError,\n} from \"../errors\";\nimport { IKVService } from \"./IKVService\";\nimport { PrefixedKVService, IPrefixedKVService } from \"./PrefixedKVService\";\nimport {\n KVServiceConfig,\n KVGetOptions,\n KVPutOptions,\n KVListOptions,\n KVDeleteOptions,\n KVHeadOptions,\n KVResponse,\n KVListResponse,\n KVResponseHeaders,\n KVAction,\n} from \"./types\";\n\n/**\n * KV service implementation.\n *\n * Provides key-value storage operations using TinyCloud's KV API.\n * Uses the Result type pattern for explicit error handling.\n *\n * @example\n * ```typescript\n * // Register with SDK\n * const sdk = new TinyCloud({\n * services: { kv: KVService },\n * serviceConfigs: { kv: { prefix: 'myapp' } },\n * });\n *\n * // Use the service\n * const result = await sdk.kv.get('settings');\n * if (result.ok) {\n * console.log(result.data.data);\n * }\n * ```\n */\nexport class KVService extends BaseService implements IKVService {\n /**\n * Service identifier for registration.\n */\n static readonly serviceName = \"kv\";\n\n /**\n * Service configuration.\n */\n declare protected _config: KVServiceConfig;\n\n /**\n * Create a new KVService instance.\n *\n * @param config - Service configuration\n */\n constructor(config: KVServiceConfig = {}) {\n super();\n this._config = config;\n }\n\n /**\n * Get the service configuration.\n */\n get config(): KVServiceConfig {\n return this._config;\n }\n\n // Parses \"Used: X bytes, Limit: Y bytes\" from tinycloud-node error responses\n private parseQuotaInfo(\n errorText: string\n ): { usedBytes: number; limitBytes: number } | undefined {\n const match = errorText.match(\n /Used:\\s*(\\d+)\\s*bytes,\\s*Limit:\\s*(\\d+)\\s*bytes/i\n );\n if (match) {\n return {\n usedBytes: parseInt(match[1], 10),\n limitBytes: parseInt(match[2], 10),\n };\n }\n return undefined;\n }\n\n private handleQuotaErrorResponse(\n response: FetchResponse,\n errorText: string,\n key: string\n ): Result<never> | undefined {\n if (response.status === 402) {\n const quotaInfo = this.parseQuotaInfo(errorText);\n return err(\n storageQuotaExceededError(\n \"kv\",\n `Storage quota exceeded for key \"${key}\": ${errorText}`,\n {\n status: response.status,\n ...(quotaInfo\n ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes }\n : {}),\n }\n )\n );\n }\n\n if (response.status === 413) {\n const quotaInfo = this.parseQuotaInfo(errorText);\n return err(\n storageLimitReachedError(\n \"kv\",\n `Storage limit reached for key \"${key}\": ${errorText}`,\n {\n status: response.status,\n ...(quotaInfo\n ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes }\n : {}),\n }\n )\n );\n }\n\n return undefined;\n }\n\n /**\n * Get the full path with optional prefix.\n *\n * @param key - The key\n * @param prefixOverride - Optional prefix override\n * @returns The full path\n */\n private getFullPath(key: string, prefixOverride?: string): string {\n const prefix = prefixOverride ?? this._config.prefix ?? \"\";\n return prefix ? `${prefix}/${key}` : key;\n }\n\n /**\n * Get the host URL.\n */\n private get host(): string {\n return this.context.hosts[0];\n }\n\n /**\n * Execute an invoke operation.\n *\n * @param path - Resource path\n * @param action - KV action\n * @param body - Optional request body\n * @param signal - Optional abort signal\n * @returns Fetch response\n */\n private async invokeOperation(\n path: string,\n action: string,\n body?: Blob | string,\n signal?: AbortSignal\n ): Promise<FetchResponse> {\n const session = this.context.session!;\n const headers = this.context.invoke(\n session,\n \"kv\",\n path,\n action\n );\n\n return this.context.fetch(`${this.host}/invoke`, {\n method: \"POST\",\n headers,\n body,\n signal: this.combineSignals(signal),\n });\n }\n\n /**\n * Create KVResponseHeaders from fetch response headers.\n *\n * @param headers - Fetch response headers\n * @returns KVResponseHeaders object\n */\n private createResponseHeaders(headers: {\n get(name: string): string | null;\n }): KVResponseHeaders {\n return {\n etag: headers.get(\"etag\") ?? undefined,\n contentType: headers.get(\"content-type\") ?? undefined,\n lastModified: headers.get(\"last-modified\") ?? undefined,\n contentLength: headers.get(\"content-length\")\n ? parseInt(headers.get(\"content-length\")!, 10)\n : undefined,\n get: (name: string) => headers.get(name),\n };\n }\n\n /**\n * Parse response body based on content type.\n *\n * @param response - Fetch response\n * @param raw - Whether to return raw text\n * @returns Parsed data\n */\n private async parseResponse<T>(\n response: FetchResponse,\n raw: boolean = false\n ): Promise<T | undefined> {\n if (!response.ok) {\n return undefined;\n }\n\n if (raw) {\n return (await response.text()) as unknown as T;\n }\n\n const contentType = response.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n return (await response.json()) as T;\n } else if (contentType?.startsWith(\"text/\")) {\n return (await response.text()) as unknown as T;\n }\n\n // No content-type header - try to parse as JSON, fall back to text\n const text = await response.text();\n if (!text) {\n return undefined;\n }\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as unknown as T;\n }\n }\n\n /**\n * Get a value by key.\n */\n async get<T = unknown>(\n key: string,\n options?: KVGetOptions\n ): Promise<Result<KVResponse<T>>> {\n return this.withTelemetry(\"get\", key, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"kv\"));\n }\n\n const path = this.getFullPath(key, options?.prefix);\n\n try {\n const response = await this.invokeOperation(\n path,\n KVAction.GET,\n undefined,\n options?.signal\n );\n\n if (!response.ok) {\n if (response.status === 401) {\n const errorText = await response.text();\n const { resource, action } = parseAuthError(errorText);\n return err(authUnauthorizedError(\"kv\", errorText, {\n status: response.status,\n ...(action && { requiredAction: action }),\n ...(resource && { resource }),\n }));\n }\n\n if (response.status === 404) {\n return err(\n serviceError(\n ErrorCodes.KV_NOT_FOUND,\n `Key not found: ${key}`,\n \"kv\"\n )\n );\n }\n\n const errorText = await response.text();\n return err(\n serviceError(\n ErrorCodes.NETWORK_ERROR,\n `Failed to get key \"${key}\": ${response.status} - ${errorText}`,\n \"kv\",\n { meta: { status: response.status, statusText: response.statusText } }\n )\n );\n }\n\n const data = await this.parseResponse<T>(response, options?.raw);\n return ok({\n data: data as T,\n headers: this.createResponseHeaders(response.headers),\n });\n } catch (error) {\n return err(wrapError(\"kv\", error));\n }\n });\n }\n\n /**\n * Store a value at a key.\n */\n async put(\n key: string,\n value: unknown,\n options?: KVPutOptions\n ): Promise<Result<KVResponse<void>>> {\n return this.withTelemetry(\"put\", key, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"kv\"));\n }\n\n const path = this.getFullPath(key, options?.prefix);\n\n // Serialize value to string\n let body: string;\n if (typeof value === \"string\") {\n body = value;\n } else {\n body = JSON.stringify(value);\n }\n\n try {\n const response = await this.invokeOperation(\n path,\n KVAction.PUT,\n body,\n options?.signal\n );\n\n if (!response.ok) {\n if (response.status === 401) {\n const errorText = await response.text();\n const { resource, action } = parseAuthError(errorText);\n return err(authUnauthorizedError(\"kv\", errorText, {\n status: response.status,\n ...(action && { requiredAction: action }),\n ...(resource && { resource }),\n }));\n }\n\n const errorText = await response.text();\n\n // Check for storage quota errors (402, 413)\n const quotaError = this.handleQuotaErrorResponse(\n response,\n errorText,\n key\n );\n if (quotaError) {\n return quotaError;\n }\n\n return err(\n serviceError(\n ErrorCodes.KV_WRITE_FAILED,\n `Failed to put key \"${key}\": ${response.status} - ${errorText}`,\n \"kv\",\n { meta: { status: response.status, statusText: response.statusText } }\n )\n );\n }\n\n return ok({\n data: undefined as void,\n headers: this.createResponseHeaders(response.headers),\n });\n } catch (error) {\n return err(wrapError(\"kv\", error));\n }\n });\n }\n\n /**\n * List keys with optional prefix filtering.\n */\n async list(options?: KVListOptions): Promise<Result<KVListResponse>> {\n return this.withTelemetry(\"list\", options?.prefix, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"kv\"));\n }\n\n // Build the path from prefix and optional path\n let listPath = options?.prefix ?? this._config.prefix ?? \"\";\n if (options?.path) {\n listPath = listPath ? `${listPath}/${options.path}` : options.path;\n }\n\n try {\n const response = await this.invokeOperation(\n listPath,\n KVAction.LIST,\n undefined,\n options?.signal\n );\n\n if (!response.ok) {\n if (response.status === 401) {\n const errorText = await response.text();\n const { resource, action } = parseAuthError(errorText);\n return err(authUnauthorizedError(\"kv\", errorText, {\n status: response.status,\n ...(action && { requiredAction: action }),\n ...(resource && { resource }),\n }));\n }\n\n const errorText = await response.text();\n return err(\n serviceError(\n ErrorCodes.NETWORK_ERROR,\n `Failed to list keys: ${response.status} - ${errorText}`,\n \"kv\",\n { meta: { status: response.status, statusText: response.statusText } }\n )\n );\n }\n\n let keys = await this.parseResponse<string[]>(response, options?.raw);\n keys = keys ?? [];\n\n // Optionally remove prefix from keys\n if (options?.removePrefix && listPath) {\n const prefixWithSlash = listPath.endsWith(\"/\")\n ? listPath\n : `${listPath}/`;\n keys = keys.map((key) =>\n key.startsWith(prefixWithSlash)\n ? key.slice(prefixWithSlash.length)\n : key\n );\n }\n\n return ok({ keys });\n } catch (error) {\n return err(wrapError(\"kv\", error));\n }\n });\n }\n\n /**\n * Delete a key.\n */\n async delete(key: string, options?: KVDeleteOptions): Promise<Result<void>> {\n return this.withTelemetry(\"delete\", key, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"kv\"));\n }\n\n const path = this.getFullPath(key, options?.prefix);\n\n try {\n const response = await this.invokeOperation(\n path,\n KVAction.DELETE,\n undefined,\n options?.signal\n );\n\n if (!response.ok) {\n if (response.status === 401) {\n const errorText = await response.text();\n const { resource, action } = parseAuthError(errorText);\n return err(authUnauthorizedError(\"kv\", errorText, {\n status: response.status,\n ...(action && { requiredAction: action }),\n ...(resource && { resource }),\n }));\n }\n\n if (response.status === 404) {\n return err(\n serviceError(\n ErrorCodes.KV_NOT_FOUND,\n `Key not found: ${key}`,\n \"kv\"\n )\n );\n }\n\n const errorText = await response.text();\n return err(\n serviceError(\n ErrorCodes.NETWORK_ERROR,\n `Failed to delete key \"${key}\": ${response.status} - ${errorText}`,\n \"kv\",\n { meta: { status: response.status, statusText: response.statusText } }\n )\n );\n }\n\n return ok(undefined);\n } catch (error) {\n return err(wrapError(\"kv\", error));\n }\n });\n }\n\n /**\n * Get metadata for a key without retrieving the value.\n */\n async head(\n key: string,\n options?: KVHeadOptions\n ): Promise<Result<KVResponse<void>>> {\n return this.withTelemetry(\"head\", key, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"kv\"));\n }\n\n const path = this.getFullPath(key, options?.prefix);\n\n try {\n const response = await this.invokeOperation(\n path,\n KVAction.HEAD,\n undefined,\n options?.signal\n );\n\n if (!response.ok) {\n if (response.status === 401) {\n const errorText = await response.text();\n const { resource, action } = parseAuthError(errorText);\n return err(authUnauthorizedError(\"kv\", errorText, {\n status: response.status,\n ...(action && { requiredAction: action }),\n ...(resource && { resource }),\n }));\n }\n\n if (response.status === 404) {\n return err(\n serviceError(\n ErrorCodes.KV_NOT_FOUND,\n `Key not found: ${key}`,\n \"kv\"\n )\n );\n }\n\n const errorText = await response.text();\n return err(\n serviceError(\n ErrorCodes.NETWORK_ERROR,\n `Failed to get metadata for key \"${key}\": ${response.status} - ${errorText}`,\n \"kv\",\n { meta: { status: response.status, statusText: response.statusText } }\n )\n );\n }\n\n return ok({\n data: undefined as void,\n headers: this.createResponseHeaders(response.headers),\n });\n } catch (error) {\n return err(wrapError(\"kv\", error));\n }\n });\n }\n\n /**\n * Create a prefix-scoped view of this KV service.\n *\n * Returns a PrefixedKVService that automatically prefixes all\n * key operations with the specified prefix. This enables apps\n * to isolate their data within a shared space.\n *\n * @param prefix - The prefix to apply to all operations\n * @returns A PrefixedKVService scoped to the prefix\n *\n * ## Prefix Conventions\n *\n * | Pattern | Use Case | Example |\n * | -- | -- | -- |\n * | `/app.{domain}/` | App-private data | `/app.photos.xyz/settings.json` |\n * | `/{type}/` | Shared data type | `/photos/vacation.jpg` |\n * | `/.{name}/` | Hidden/system data | `/.cache/thumbnails/` |\n * | `/public/` | Explicitly shareable | `/public/profile.json` |\n *\n * @example\n * ```typescript\n * const space = sdk.space('default');\n *\n * // Create prefix-scoped views\n * const myApp = space.kv.withPrefix('/app.myapp.com');\n * const sharedPhotos = space.kv.withPrefix('/photos');\n *\n * // Operations are automatically prefixed\n * await myApp.put('settings.json', { theme: 'dark' });\n * // -> Actually writes to: /app.myapp.com/settings.json\n *\n * await myApp.get('settings.json');\n * // -> Actually reads from: /app.myapp.com/settings.json\n *\n * await sharedPhotos.list();\n * // -> Lists: /photos/*\n *\n * // Nested prefixes\n * const settings = myApp.withPrefix('/settings');\n * await settings.get('theme.json'); // -> /app.myapp.com/settings/theme.json\n * ```\n */\n withPrefix(prefix: string): IPrefixedKVService {\n return new PrefixedKVService(this, prefix);\n }\n}\n","/**\n * DatabaseHandle - Handle for operations on a specific named database.\n *\n * Delegates all operations to the parent SQLService with the database name.\n */\n\nimport type { Result } from \"../types\";\nimport type { IDatabaseHandle } from \"./ISQLService\";\nimport type { SQLService } from \"./SQLService\";\nimport type {\n SqlValue,\n SqlStatement,\n QueryResponse,\n ExecuteResponse,\n BatchResponse,\n QueryOptions,\n ExecuteOptions,\n BatchOptions,\n} from \"./types\";\n\nexport class DatabaseHandle implements IDatabaseHandle {\n private service: SQLService;\n public readonly name: string;\n\n constructor(service: SQLService, name: string) {\n this.service = service;\n this.name = name;\n }\n\n async query<T = Record<string, unknown>>(\n sql: string,\n params?: SqlValue[],\n options?: QueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.service.queryOnDb<T>(this.name, sql, params, options);\n }\n\n async execute(\n sql: string,\n params?: SqlValue[],\n options?: ExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.service.executeOnDb(this.name, sql, params, options);\n }\n\n async batch(\n statements: SqlStatement[],\n options?: BatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.service.batchOnDb(this.name, statements, options);\n }\n\n async executeStatement(\n name: string,\n params?: SqlValue[],\n options?: QueryOptions\n ): Promise<Result<QueryResponse | ExecuteResponse>> {\n return this.service.executeStatementOnDb(this.name, name, params, options);\n }\n\n async export(options?: QueryOptions): Promise<Result<Blob>> {\n return this.service.exportDb(this.name, options);\n }\n}\n","/**\n * SQL Service Types\n *\n * Type definitions for the SQL service operations.\n */\n\n/**\n * Configuration for SQLService.\n */\nexport interface SQLServiceConfig {\n /**\n * Default database name.\n * If not set, operations default to \"default\".\n */\n defaultDatabase?: string;\n\n /**\n * Default timeout in milliseconds for SQL operations.\n */\n timeout?: number;\n\n /** Allow additional config properties */\n [key: string]: unknown;\n}\n\n/**\n * Options for SQL query operations.\n */\nexport interface QueryOptions {\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for SQL execute operations.\n */\nexport interface ExecuteOptions {\n /**\n * Schema initialization statements (CREATE TABLE IF NOT EXISTS ...).\n * Executed before the main statement on first write.\n */\n schema?: string[];\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for SQL batch operations.\n */\nexport interface BatchOptions {\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A SQL value: null, number, string, or binary data.\n */\nexport type SqlValue = null | number | string | Uint8Array;\n\n/**\n * A SQL statement with optional parameters.\n */\nexport interface SqlStatement {\n sql: string;\n params?: SqlValue[];\n}\n\n/**\n * Response from SQL query operations.\n */\nexport interface QueryResponse<T = Record<string, unknown>> {\n columns: string[];\n rows: T[][];\n rowCount: number;\n}\n\n/**\n * Response from SQL execute operations.\n */\nexport interface ExecuteResponse {\n changes: number;\n lastInsertRowId: number;\n}\n\n/**\n * Response from SQL batch operations.\n */\nexport interface BatchResponse {\n results: ExecuteResponse[];\n}\n\n/**\n * SQL service action types.\n */\nexport const SQLAction = {\n READ: \"tinycloud.sql/read\",\n WRITE: \"tinycloud.sql/write\",\n ADMIN: \"tinycloud.sql/admin\",\n SELECT: \"tinycloud.sql/select\",\n INSERT: \"tinycloud.sql/insert\",\n UPDATE: \"tinycloud.sql/update\",\n DELETE: \"tinycloud.sql/delete\",\n EXECUTE: \"tinycloud.sql/execute\",\n EXPORT: \"tinycloud.sql/export\",\n ALL: \"tinycloud.sql/*\",\n} as const;\n\nexport type SQLActionType = (typeof SQLAction)[keyof typeof SQLAction];\n","/**\n * SQLService - SQL database service implementation.\n *\n * Platform-agnostic SQL service that works with both web-sdk and node-sdk.\n * Uses dependency injection via IServiceContext for platform dependencies.\n */\n\nimport { BaseService } from \"../base/BaseService\";\nimport {\n Result,\n ok,\n err,\n ErrorCodes,\n serviceError,\n type FetchResponse,\n} from \"../types\";\nimport { authRequiredError, wrapError, parseAuthError } from \"../errors\";\nimport type { ISQLService } from \"./ISQLService\";\nimport type { IDatabaseHandle } from \"./ISQLService\";\nimport { DatabaseHandle } from \"./DatabaseHandle\";\nimport {\n type SQLServiceConfig,\n type QueryOptions,\n type ExecuteOptions,\n type BatchOptions,\n type SqlValue,\n type SqlStatement,\n type QueryResponse,\n type ExecuteResponse,\n type BatchResponse,\n SQLAction,\n} from \"./types\";\n\nexport class SQLService extends BaseService implements ISQLService {\n static readonly serviceName = \"sql\";\n\n declare protected _config: SQLServiceConfig;\n\n constructor(config: SQLServiceConfig = {}) {\n super();\n this._config = config;\n }\n\n get config(): SQLServiceConfig {\n return this._config;\n }\n\n private get defaultDbName(): string {\n return this._config.defaultDatabase ?? \"default\";\n }\n\n private get host(): string {\n return this.context.hosts[0];\n }\n\n /**\n * Get a handle to a named database.\n */\n db(name?: string): IDatabaseHandle {\n return new DatabaseHandle(this, name ?? this.defaultDbName);\n }\n\n /**\n * Shortcut: query the default database.\n */\n async query<T = Record<string, unknown>>(\n sql: string,\n params?: SqlValue[],\n options?: QueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.queryOnDb<T>(this.defaultDbName, sql, params, options);\n }\n\n /**\n * Shortcut: execute on the default database.\n */\n async execute(\n sql: string,\n params?: SqlValue[],\n options?: ExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.executeOnDb(this.defaultDbName, sql, params, options);\n }\n\n /**\n * Shortcut: batch on the default database.\n */\n async batch(\n statements: SqlStatement[],\n options?: BatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.batchOnDb(this.defaultDbName, statements, options);\n }\n\n // === Internal methods called by DatabaseHandle ===\n\n async queryOnDb<T = Record<string, unknown>>(\n dbName: string,\n sql: string,\n params?: SqlValue[],\n options?: QueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.withTelemetry(\"query\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"sql\"));\n }\n\n try {\n const response = await this.invokeSQL(\n dbName,\n SQLAction.READ,\n { action: \"query\", sql, params: params ?? [] },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"query\");\n }\n\n const data = (await response.json()) as QueryResponse<T>;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"sql\", error));\n }\n });\n }\n\n async executeOnDb(\n dbName: string,\n sql: string,\n params?: SqlValue[],\n options?: ExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.withTelemetry(\"execute\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"sql\"));\n }\n\n try {\n const body: Record<string, unknown> = {\n action: \"execute\",\n sql,\n params: params ?? [],\n };\n if (options?.schema) {\n body.schema = options.schema;\n }\n\n const response = await this.invokeSQL(\n dbName,\n SQLAction.WRITE,\n body,\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"execute\");\n }\n\n const data = (await response.json()) as ExecuteResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"sql\", error));\n }\n });\n }\n\n async batchOnDb(\n dbName: string,\n statements: SqlStatement[],\n options?: BatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.withTelemetry(\"batch\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"sql\"));\n }\n\n try {\n const response = await this.invokeSQL(\n dbName,\n SQLAction.WRITE,\n { action: \"batch\", statements },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"batch\");\n }\n\n const data = (await response.json()) as BatchResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"sql\", error));\n }\n });\n }\n\n async executeStatementOnDb(\n dbName: string,\n name: string,\n params?: SqlValue[],\n options?: QueryOptions\n ): Promise<Result<QueryResponse | ExecuteResponse>> {\n return this.withTelemetry(\"executeStatement\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"sql\"));\n }\n\n try {\n const response = await this.invokeSQL(\n dbName,\n SQLAction.EXECUTE,\n { action: \"execute_statement\", name, params: params ?? [] },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"executeStatement\");\n }\n\n const data = (await response.json()) as\n | QueryResponse\n | ExecuteResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"sql\", error));\n }\n });\n }\n\n async exportDb(\n dbName: string,\n options?: QueryOptions\n ): Promise<Result<Blob>> {\n return this.withTelemetry(\"export\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"sql\"));\n }\n\n try {\n const response = await this.invokeSQL(\n dbName,\n SQLAction.EXPORT,\n { action: \"export\" },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"export\");\n }\n\n // FetchResponse doesn't expose blob(), so access it from the\n // underlying response which is a standard fetch Response at runtime\n const resp = response as any;\n if (typeof resp.blob === \"function\") {\n const blob = await resp.blob();\n return ok(blob as Blob);\n }\n // If blob() is not available, return the raw text as a Blob-like\n const text = await response.text();\n return ok(text as unknown as Blob);\n } catch (error) {\n return err(wrapError(\"sql\", error));\n }\n });\n }\n\n // === Private helpers ===\n\n private async invokeSQL(\n dbName: string,\n action: string,\n body: Record<string, unknown>,\n signal?: AbortSignal\n ): Promise<FetchResponse> {\n const session = this.context.session!;\n const headers = this.context.invoke(session, \"sql\", dbName, action);\n\n return this.context.fetch(`${this.host}/invoke`, {\n method: \"POST\",\n headers: {\n ...(headers as Record<string, string>),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body) as any,\n signal: this.combineSignals(signal),\n });\n }\n\n private async handleErrorResponse(\n response: FetchResponse,\n operation: string\n ): Promise<Result<never>> {\n const errorText = await response.text();\n\n let errorBody: { error?: string; message?: string; code?: string } = {};\n try {\n errorBody = JSON.parse(errorText);\n } catch {\n // Not JSON\n }\n\n const errorCode = this.mapHttpStatusToErrorCode(\n response.status,\n errorBody.error\n );\n const message =\n errorBody.message ||\n `SQL ${operation} failed: ${response.status} - ${errorText}`;\n\n const meta: Record<string, unknown> = { status: response.status, statusText: response.statusText };\n\n if (response.status === 401) {\n const { resource, action } = parseAuthError(errorText);\n if (action) meta.requiredAction = action;\n if (resource) meta.resource = resource;\n }\n\n return err(\n serviceError(errorCode, message, \"sql\", { meta })\n );\n }\n\n private mapHttpStatusToErrorCode(\n status: number,\n serverError?: string\n ): string {\n switch (status) {\n case 400:\n return ErrorCodes.SQL_ERROR;\n case 401:\n return ErrorCodes.AUTH_UNAUTHORIZED;\n case 403:\n if (serverError === \"sql_readonly_violation\") {\n return ErrorCodes.SQL_READONLY_VIOLATION;\n }\n return ErrorCodes.SQL_PERMISSION_DENIED;\n case 404:\n return ErrorCodes.SQL_DATABASE_NOT_FOUND;\n case 413:\n return ErrorCodes.SQL_RESPONSE_TOO_LARGE;\n case 429:\n return ErrorCodes.SQL_QUOTA_EXCEEDED;\n default:\n return ErrorCodes.NETWORK_ERROR;\n }\n }\n}\n","/**\n * DuckDbDatabaseHandle - Handle for operations on a specific named database.\n *\n * Delegates all operations to the parent DuckDbService with the database name.\n */\n\nimport type { Result } from \"../types\";\nimport type { IDuckDbDatabaseHandle } from \"./IDuckDbService\";\nimport type { DuckDbService } from \"./DuckDbService\";\nimport type {\n DuckDbValue,\n DuckDbStatement,\n QueryResponse,\n ExecuteResponse,\n BatchResponse,\n SchemaInfo,\n DuckDbQueryOptions,\n DuckDbExecuteOptions,\n DuckDbBatchOptions,\n DuckDbOptions,\n} from \"./types\";\n\nexport class DuckDbDatabaseHandle implements IDuckDbDatabaseHandle {\n private service: DuckDbService;\n public readonly name: string;\n\n constructor(service: DuckDbService, name: string) {\n this.service = service;\n this.name = name;\n }\n\n async query<T = Record<string, unknown>>(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.service.queryOnDb<T>(this.name, sql, params, options);\n }\n\n async queryArrow(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<ArrayBuffer>> {\n return this.service.queryArrowOnDb(this.name, sql, params, options);\n }\n\n async execute(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.service.executeOnDb(this.name, sql, params, options);\n }\n\n async batch(\n statements: DuckDbStatement[],\n options?: DuckDbBatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.service.batchOnDb(this.name, statements, options);\n }\n\n async executeStatement(\n name: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<QueryResponse | ExecuteResponse>> {\n return this.service.executeStatementOnDb(this.name, name, params, options);\n }\n\n async describe(options?: DuckDbOptions): Promise<Result<SchemaInfo>> {\n return this.service.describeDb(this.name, options);\n }\n\n async export(options?: DuckDbOptions): Promise<Result<Blob>> {\n return this.service.exportOnDb(this.name, options);\n }\n\n async import(data: Uint8Array, options?: DuckDbOptions): Promise<Result<void>> {\n return this.service.importOnDb(this.name, data, options);\n }\n}\n","/**\n * DuckDB Service Types\n *\n * Type definitions for the DuckDB service operations.\n */\n\n/**\n * Configuration for DuckDbService.\n */\nexport interface DuckDbServiceConfig {\n /**\n * Default database name.\n * If not set, operations default to \"default\".\n */\n defaultDatabase?: string;\n\n /**\n * Default timeout in milliseconds for DuckDB operations.\n */\n timeout?: number;\n\n /** Allow additional config properties */\n [key: string]: unknown;\n}\n\n/**\n * Options for DuckDB query operations.\n */\nexport interface DuckDbQueryOptions {\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for DuckDB execute operations.\n */\nexport interface DuckDbExecuteOptions {\n /**\n * Schema initialization statements (CREATE TABLE IF NOT EXISTS ...).\n * Executed before the main statement on first write.\n */\n schema?: string[];\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for DuckDB batch operations.\n */\nexport interface DuckDbBatchOptions {\n /**\n * Whether to run statements in a transaction.\n */\n transactional?: boolean;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for DuckDB operations that only need an abort signal.\n */\nexport interface DuckDbOptions {\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A DuckDB value: null, boolean, number, string, binary, array, or object.\n */\nexport type DuckDbValue =\n | null\n | boolean\n | number\n | string\n | Uint8Array\n | DuckDbValueArray\n | DuckDbValueRecord;\n\n/** Array of DuckDB values (workaround for circular type alias). */\nexport interface DuckDbValueArray extends Array<DuckDbValue> {}\n\n/** Record of DuckDB values (workaround for circular type alias). */\nexport interface DuckDbValueRecord {\n [key: string]: DuckDbValue;\n}\n\n/**\n * A DuckDB statement with optional parameters.\n */\nexport interface DuckDbStatement {\n sql: string;\n params?: DuckDbValue[];\n}\n\n/**\n * Response from DuckDB query operations.\n */\nexport interface QueryResponse<T = Record<string, unknown>> {\n columns: string[];\n rows: T[][];\n rowCount: number;\n}\n\n/**\n * Response from DuckDB execute operations.\n */\nexport interface ExecuteResponse {\n changes: number;\n}\n\n/**\n * Response from DuckDB batch operations.\n */\nexport interface BatchResponse {\n results: ExecuteResponse[];\n}\n\n/**\n * Schema information for a DuckDB database.\n */\nexport interface SchemaInfo {\n tables: TableInfo[];\n views: ViewInfo[];\n}\n\n/**\n * Information about a table.\n */\nexport interface TableInfo {\n name: string;\n columns: ColumnInfo[];\n}\n\n/**\n * Information about a column.\n */\nexport interface ColumnInfo {\n name: string;\n type: string;\n nullable: boolean;\n}\n\n/**\n * Information about a view.\n */\nexport interface ViewInfo {\n name: string;\n sql: string;\n}\n\n/**\n * DuckDB service action types.\n */\nexport const DuckDbAction = {\n READ: \"tinycloud.duckdb/read\",\n WRITE: \"tinycloud.duckdb/write\",\n ADMIN: \"tinycloud.duckdb/admin\",\n DESCRIBE: \"tinycloud.duckdb/describe\",\n EXPORT: \"tinycloud.duckdb/export\",\n IMPORT: \"tinycloud.duckdb/import\",\n EXECUTE: \"tinycloud.duckdb/execute\",\n ALL: \"tinycloud.duckdb/*\",\n} as const;\n\nexport type DuckDbActionType = (typeof DuckDbAction)[keyof typeof DuckDbAction];\n","/**\n * DuckDbService - DuckDB database service implementation.\n *\n * Platform-agnostic DuckDB service that works with both web-sdk and node-sdk.\n * Uses dependency injection via IServiceContext for platform dependencies.\n */\n\nimport { BaseService } from \"../base/BaseService\";\nimport {\n Result,\n ok,\n err,\n ErrorCodes,\n serviceError,\n type FetchResponse,\n} from \"../types\";\nimport { authRequiredError, wrapError, parseAuthError } from \"../errors\";\nimport type { IDuckDbService, IDuckDbDatabaseHandle } from \"./IDuckDbService\";\nimport { DuckDbDatabaseHandle } from \"./DuckDbDatabaseHandle\";\nimport {\n type DuckDbServiceConfig,\n type DuckDbQueryOptions,\n type DuckDbExecuteOptions,\n type DuckDbBatchOptions,\n type DuckDbOptions,\n type DuckDbValue,\n type DuckDbStatement,\n type QueryResponse,\n type ExecuteResponse,\n type BatchResponse,\n type SchemaInfo,\n DuckDbAction,\n} from \"./types\";\n\nexport class DuckDbService extends BaseService implements IDuckDbService {\n static readonly serviceName = \"duckdb\";\n\n declare protected _config: DuckDbServiceConfig;\n\n constructor(config: DuckDbServiceConfig = {}) {\n super();\n this._config = config;\n }\n\n get config(): DuckDbServiceConfig {\n return this._config;\n }\n\n private get defaultDbName(): string {\n return this._config.defaultDatabase ?? \"default\";\n }\n\n private get host(): string {\n return this.context.hosts[0];\n }\n\n /**\n * Get a handle to a named database.\n */\n db(name?: string): IDuckDbDatabaseHandle {\n return new DuckDbDatabaseHandle(this, name ?? this.defaultDbName);\n }\n\n /**\n * Shortcut: query the default database (JSON format).\n */\n async query<T = Record<string, unknown>>(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.queryOnDb<T>(this.defaultDbName, sql, params, options);\n }\n\n /**\n * Shortcut: query the default database (Arrow IPC format).\n */\n async queryArrow(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<ArrayBuffer>> {\n return this.queryArrowOnDb(this.defaultDbName, sql, params, options);\n }\n\n /**\n * Shortcut: execute on the default database.\n */\n async execute(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.executeOnDb(this.defaultDbName, sql, params, options);\n }\n\n /**\n * Shortcut: batch on the default database.\n */\n async batch(\n statements: DuckDbStatement[],\n options?: DuckDbBatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.batchOnDb(this.defaultDbName, statements, options);\n }\n\n // === Internal methods called by DuckDbDatabaseHandle ===\n\n async queryOnDb<T = Record<string, unknown>>(\n dbName: string,\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.withTelemetry<QueryResponse<T>>(\"query\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.READ,\n { action: \"query\", sql, params: params ?? [] },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"query\");\n }\n\n const data = (await response.json()) as QueryResponse<T>;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async queryArrowOnDb(\n dbName: string,\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<ArrayBuffer>> {\n return this.withTelemetry<ArrayBuffer>(\"queryArrow\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.READ,\n { action: \"query\", sql, params: params ?? [] },\n options?.signal,\n { Accept: \"application/vnd.apache.arrow.stream\" }\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"queryArrow\");\n }\n\n const buffer = await response.arrayBuffer();\n return ok(buffer);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async executeOnDb(\n dbName: string,\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.withTelemetry(\"execute\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const body: Record<string, unknown> = {\n action: \"execute\",\n sql,\n params: params ?? [],\n };\n if (options?.schema) {\n body.schema = options.schema;\n }\n\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.WRITE,\n body,\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"execute\");\n }\n\n const data = (await response.json()) as ExecuteResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async batchOnDb(\n dbName: string,\n statements: DuckDbStatement[],\n options?: DuckDbBatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.withTelemetry(\"batch\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const body: Record<string, unknown> = {\n action: \"batch\",\n statements,\n };\n if (options?.transactional !== undefined) {\n body.transactional = options.transactional;\n }\n\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.WRITE,\n body,\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"batch\");\n }\n\n const data = (await response.json()) as BatchResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async executeStatementOnDb(\n dbName: string,\n name: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<QueryResponse | ExecuteResponse>> {\n return this.withTelemetry(\"executeStatement\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.EXECUTE,\n { action: \"executeStatement\", name, params: params ?? [] },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"executeStatement\");\n }\n\n const data = (await response.json()) as\n | QueryResponse\n | ExecuteResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async describeDb(\n dbName: string,\n options?: DuckDbOptions\n ): Promise<Result<SchemaInfo>> {\n return this.withTelemetry(\"describe\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.DESCRIBE,\n { action: \"describe\" },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"describe\");\n }\n\n const data = (await response.json()) as SchemaInfo;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async exportOnDb(\n dbName: string,\n options?: DuckDbOptions\n ): Promise<Result<Blob>> {\n return this.withTelemetry(\"export\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.EXPORT,\n { action: \"export\" },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"export\");\n }\n\n const blob = await response.blob();\n return ok(blob);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async importOnDb(\n dbName: string,\n data: Uint8Array,\n options?: DuckDbOptions\n ): Promise<Result<void>> {\n return this.withTelemetry(\"import\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const session = this.context.session!;\n const headers = this.context.invoke(\n session,\n \"duckdb\",\n dbName,\n DuckDbAction.IMPORT\n );\n\n const response = await this.context.fetch(`${this.host}/invoke`, {\n method: \"POST\",\n headers: {\n ...(headers as Record<string, string>),\n \"Content-Type\": \"application/x-duckdb\",\n },\n body: new Blob([data]),\n signal: this.combineSignals(options?.signal),\n });\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"import\");\n }\n\n return ok(undefined);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n // === Private helpers ===\n\n private async invokeDuckDb(\n dbName: string,\n action: string,\n body: Record<string, unknown>,\n signal?: AbortSignal,\n extraHeaders?: Record<string, string>\n ): Promise<FetchResponse> {\n const session = this.context.session!;\n const headers = this.context.invoke(session, \"duckdb\", dbName, action);\n\n return this.context.fetch(`${this.host}/invoke`, {\n method: \"POST\",\n headers: {\n ...(headers as Record<string, string>),\n \"Content-Type\": \"application/json\",\n ...extraHeaders,\n },\n body: JSON.stringify(body),\n signal: this.combineSignals(signal),\n });\n }\n\n private async handleErrorResponse(\n response: FetchResponse,\n operation: string\n ): Promise<Result<never>> {\n const errorText = await response.text();\n\n let errorBody: { error?: string; message?: string; code?: string } = {};\n try {\n errorBody = JSON.parse(errorText);\n } catch {\n // Not JSON\n }\n\n const errorCode = this.mapHttpStatusToErrorCode(\n response.status,\n errorBody.error\n );\n const message =\n errorBody.message ||\n `DuckDB ${operation} failed: ${response.status} - ${errorText}`;\n\n const meta: Record<string, unknown> = { status: response.status, statusText: response.statusText };\n\n if (response.status === 401) {\n const { resource, action } = parseAuthError(errorText);\n if (action) meta.requiredAction = action;\n if (resource) meta.resource = resource;\n }\n\n return err(\n serviceError(errorCode, message, \"duckdb\", { meta })\n );\n }\n\n private mapHttpStatusToErrorCode(\n status: number,\n serverError?: string\n ): string {\n switch (status) {\n case 400:\n return ErrorCodes.DUCKDB_ERROR;\n case 401:\n return ErrorCodes.AUTH_UNAUTHORIZED;\n case 403:\n if (serverError === \"duckdb_readonly_violation\") {\n return ErrorCodes.DUCKDB_READONLY_VIOLATION;\n }\n return ErrorCodes.DUCKDB_PERMISSION_DENIED;\n case 404:\n return ErrorCodes.DUCKDB_DATABASE_NOT_FOUND;\n case 413:\n return ErrorCodes.DUCKDB_RESPONSE_TOO_LARGE;\n case 429:\n return ErrorCodes.DUCKDB_QUOTA_EXCEEDED;\n default:\n return ErrorCodes.NETWORK_ERROR;\n }\n }\n}\n","import { BaseService } from \"../base/BaseService\";\nimport type {\n FetchResponse,\n InvokeAnyEntry,\n ServiceHeaders,\n Result,\n} from \"../types\";\nimport { ErrorCodes, err, ok, serviceError } from \"../types\";\nimport { authRequiredError, wrapError } from \"../errors\";\nimport type { IHooksService } from \"./IHooksService\";\nimport type {\n HookEvent,\n HookStreamEvent,\n HookSubscription,\n HooksServiceConfig,\n SubscribeOptions,\n HookWebhookListOptions,\n HookWebhookRecord,\n HookWebhookRegistration,\n HookWebhookUnregisterOptions,\n} from \"./types\";\n\ninterface HookTicketResponse {\n ticket: string;\n expiresAt: string;\n}\n\ninterface HookSubscriber {\n requested: HookSubscription[];\n ttlSeconds?: number;\n queue: AsyncQueue<HookEvent>;\n}\n\nclass AsyncQueue<T> implements AsyncIterable<T>, AsyncIterator<T> {\n private readonly values: T[] = [];\n private readonly waiters: Array<(result: IteratorResult<T>) => void> = [];\n private closed = false;\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return this;\n }\n\n push(value: T): void {\n if (this.closed) {\n return;\n }\n\n const waiter = this.waiters.shift();\n if (waiter) {\n waiter({ value, done: false });\n return;\n }\n\n this.values.push(value);\n }\n\n close(): void {\n if (this.closed) {\n return;\n }\n\n this.closed = true;\n while (this.waiters.length > 0) {\n const waiter = this.waiters.shift();\n waiter?.({ value: undefined as never, done: true });\n }\n }\n\n next(): Promise<IteratorResult<T>> {\n if (this.values.length > 0) {\n const value = this.values.shift()!;\n return Promise.resolve({ value, done: false });\n }\n\n if (this.closed) {\n return Promise.resolve({ value: undefined as never, done: true });\n }\n\n return new Promise<IteratorResult<T>>((resolve) => {\n this.waiters.push(resolve);\n });\n }\n}\n\nexport class HooksService extends BaseService implements IHooksService {\n static readonly serviceName = \"hooks\";\n\n declare protected _config: HooksServiceConfig;\n private readonly _subscribers: Set<HookSubscriber> = new Set();\n private _sharedStreamTask?: Promise<void>;\n private _sharedStreamAbort?: AbortController;\n private _refreshChain: Promise<void> = Promise.resolve();\n private _activeSignature = \"\";\n\n constructor(config: HooksServiceConfig = {}) {\n super();\n this._config = config;\n }\n\n get config(): HooksServiceConfig {\n return this._config;\n }\n\n private get host(): string {\n return this._config.host ?? this.context.hosts[0];\n }\n\n async *subscribe(\n subscriptions: HookSubscription[],\n options: SubscribeOptions = {},\n ): AsyncIterable<HookEvent> {\n if (!this.requireAuth()) {\n throw new Error(\"Authentication required for hooks subscription\");\n }\n if (subscriptions.length === 0) {\n throw new Error(\"At least one hook subscription is required\");\n }\n\n const normalized = subscriptions.map(normalizeSubscription);\n const subscriber: HookSubscriber = {\n requested: normalized,\n ttlSeconds: options.ttlSeconds,\n queue: new AsyncQueue<HookEvent>(),\n };\n\n this._subscribers.add(subscriber);\n const abortHandler = () => {\n this._subscribers.delete(subscriber);\n subscriber.queue.close();\n void this.scheduleSharedStreamRefresh();\n };\n\n if (options.signal) {\n if (options.signal.aborted) {\n abortHandler();\n } else {\n options.signal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n }\n\n void this.scheduleSharedStreamRefresh();\n\n try {\n for await (const event of subscriber.queue) {\n yield event;\n }\n } finally {\n if (options.signal) {\n options.signal.removeEventListener(\"abort\", abortHandler);\n }\n abortHandler();\n }\n }\n\n async register(\n webhook: HookWebhookRegistration,\n ): Promise<Result<HookWebhookRecord>> {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"hooks\"));\n }\n\n if (typeof webhook.secret !== \"string\" || webhook.secret.trim().length === 0) {\n return err(\n serviceError(\n ErrorCodes.INVALID_INPUT,\n \"Webhook secret is required\",\n \"hooks\",\n { meta: { field: \"secret\" } },\n ),\n );\n }\n\n try {\n const response = await this.context.fetch(`${this.host}/hooks/webhooks`, {\n method: \"POST\",\n headers: {\n ...serviceHeadersToRecord(\n this.createHookHeaders(\n \"tinycloud.hooks/register\",\n buildScopePath(webhook.service, webhook.pathPrefix),\n ),\n ),\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n space: webhook.space,\n service: webhook.service,\n pathPrefix: normalizePathPrefix(webhook.pathPrefix),\n abilities: webhook.abilities ?? [],\n callbackUrl: webhook.callbackUrl,\n secret: webhook.secret,\n }),\n });\n\n if (!response.ok) {\n return err(\n await responseError(\"hooks\", \"failed to register webhook\", response),\n );\n }\n\n const data = normalizeWebhookRecord(await response.json());\n if (!data) {\n return err(\n wrapError(\n \"hooks\",\n new Error(\"Webhook registration response did not include a record\"),\n ),\n );\n }\n\n return ok(data);\n } catch (error) {\n return err(wrapError(\"hooks\", error));\n }\n }\n\n async list(\n options: HookWebhookListOptions = {},\n ): Promise<Result<HookWebhookRecord[]>> {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"hooks\"));\n }\n\n try {\n const query = new URLSearchParams();\n if (options.space) {\n query.set(\"space\", options.space);\n }\n if (options.service) {\n query.set(\"service\", options.service);\n }\n if (options.pathPrefix) {\n const normalizedPrefix = normalizePathPrefix(options.pathPrefix);\n if (normalizedPrefix) {\n query.set(\"prefix\", normalizedPrefix);\n }\n }\n\n const response = await this.context.fetch(\n `${this.host}/hooks/webhooks${query.size > 0 ? `?${query.toString()}` : \"\"}`,\n {\n method: \"GET\",\n headers: serviceHeadersToRecord(\n this.createHookHeaders(\n \"tinycloud.hooks/list\",\n options.service\n ? buildScopePath(options.service, options.pathPrefix)\n : \"webhooks\",\n ),\n ),\n },\n );\n\n if (!response.ok) {\n return err(\n await responseError(\"hooks\", \"failed to list webhooks\", response),\n );\n }\n\n const payload = await response.json();\n const records = normalizeWebhookRecordList(payload);\n if (!records) {\n return err(\n wrapError(\n \"hooks\",\n new Error(\"Webhook list response did not include records\"),\n ),\n );\n }\n\n return ok(records);\n } catch (error) {\n return err(wrapError(\"hooks\", error));\n }\n }\n\n async unregister(\n id: string,\n options: HookWebhookUnregisterOptions = {},\n ): Promise<Result<void>> {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"hooks\"));\n }\n\n try {\n const response = await this.context.fetch(\n `${this.host}/hooks/webhooks/${encodeURIComponent(id)}`,\n {\n method: \"DELETE\",\n headers: serviceHeadersToRecord(\n this.createHookHeaders(\n \"tinycloud.hooks/unregister\",\n options.target\n ? buildScopePath(\n options.target.service,\n options.target.pathPrefix,\n )\n : `webhooks/${id}`,\n ),\n ),\n },\n );\n\n if (!response.ok) {\n return err(\n await responseError(\n \"hooks\",\n \"failed to unregister webhook\",\n response,\n ),\n );\n }\n\n return ok(undefined);\n } catch (error) {\n return err(wrapError(\"hooks\", error));\n }\n }\n\n private async scheduleSharedStreamRefresh(): Promise<void> {\n this._refreshChain = this._refreshChain\n .then(() => this.refreshSharedStream())\n .catch(() => undefined);\n await this._refreshChain;\n }\n\n private async refreshSharedStream(): Promise<void> {\n if (!this.requireAuth() || this._subscribers.size === 0) {\n this.abortSharedStream();\n this._activeSignature = \"\";\n return;\n }\n\n const state = this.collectSharedStreamState();\n if (state.signature !== this._activeSignature) {\n this._activeSignature = state.signature;\n this.abortSharedStream();\n }\n\n if (!this._sharedStreamTask) {\n this._sharedStreamTask = this.runSharedStream(state)\n .catch((error: unknown) => {\n if (!isAbortError(error)) {\n throw error;\n }\n })\n .finally(() => {\n this._sharedStreamTask = undefined;\n this._sharedStreamAbort = undefined;\n if (this._subscribers.size > 0) {\n void this.scheduleSharedStreamRefresh();\n }\n });\n }\n }\n\n private collectSharedStreamState(): {\n subscriptions: HookSubscription[];\n ttlSeconds?: number;\n signature: string;\n } {\n const merged = new Map<string, HookSubscription>();\n const ttlCandidates: number[] = [];\n\n for (const subscriber of this._subscribers) {\n if (typeof subscriber.ttlSeconds === \"number\") {\n ttlCandidates.push(subscriber.ttlSeconds);\n }\n for (const subscription of subscriber.requested) {\n merged.set(subscriptionSignature(subscription), subscription);\n }\n }\n\n const subscriptions = [...merged.values()].sort((left, right) =>\n subscriptionSignature(left).localeCompare(subscriptionSignature(right)),\n );\n const ttlSeconds =\n ttlCandidates.length > 0 ? Math.min(...ttlCandidates) : undefined;\n const signature = JSON.stringify({\n subscriptions: subscriptions.map(subscriptionSignature),\n ttlSeconds,\n });\n\n return {\n subscriptions,\n ttlSeconds,\n signature,\n };\n }\n\n private async runSharedStream(state: {\n subscriptions: HookSubscription[];\n ttlSeconds?: number;\n }): Promise<void> {\n const abortController = new AbortController();\n this._sharedStreamAbort = abortController;\n\n try {\n const host = this._config.host ?? this.context.hosts[0];\n const ticketResponse = await this.mintHookTicket(\n state.subscriptions,\n state.ttlSeconds,\n abortController.signal,\n );\n const streamResponse = await this.openHookStream(\n host,\n ticketResponse.ticket,\n abortController.signal,\n );\n\n for await (const message of parseSseStream(\n streamResponse.body,\n abortController.signal,\n )) {\n if (!message.data) {\n continue;\n }\n const event = parseHookEvent(message);\n for (const subscriber of this._subscribers) {\n if (matchesAnySubscription(event, subscriber.requested)) {\n subscriber.queue.push(event);\n }\n }\n }\n } finally {\n if (this._sharedStreamAbort === abortController) {\n this._sharedStreamAbort = undefined;\n }\n }\n }\n\n private abortSharedStream(): void {\n this._sharedStreamAbort?.abort();\n }\n\n private createHookHeaders(action: string, path: string): ServiceHeaders {\n return this.context.invoke(this.session, \"hooks\", path, action);\n }\n\n private async mintHookTicket(\n subscriptions: HookSubscription[],\n ttlSeconds: number | undefined,\n signal?: AbortSignal,\n ): Promise<HookTicketResponse> {\n const host = this._config.host ?? this.context.hosts[0];\n const headers = this.createInvokeHeaders(subscriptions);\n const ticketResponse = await this.context.fetch(`${host}/hooks/tickets`, {\n method: \"POST\",\n headers: {\n ...serviceHeadersToRecord(headers),\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n subscriptions,\n ttlSeconds,\n }),\n signal,\n });\n\n if (!ticketResponse.ok) {\n throw await responseError(\n \"hooks\",\n \"failed to mint hook ticket\",\n ticketResponse,\n );\n }\n\n const ticketJson = (await ticketResponse.json()) as HookTicketResponse;\n if (!ticketJson?.ticket) {\n throw new Error(\"Hook ticket response did not include a ticket\");\n }\n\n return ticketJson;\n }\n\n private async openHookStream(\n host: string,\n ticket: string,\n signal?: AbortSignal,\n ): Promise<FetchResponse> {\n const streamResponse = await this.context.fetch(\n `${host}/hooks/events?ticket=${encodeURIComponent(ticket)}`,\n {\n method: \"GET\",\n headers: { accept: \"text/event-stream\" },\n signal,\n },\n );\n\n if (!streamResponse.ok) {\n throw await responseError(\n \"hooks\",\n \"failed to open hook stream\",\n streamResponse,\n );\n }\n\n return streamResponse;\n }\n\n private createInvokeHeaders(\n subscriptions: HookSubscription[],\n ): ServiceHeaders {\n const entries: InvokeAnyEntry[] = subscriptions.map((subscription) => ({\n spaceId: subscription.space,\n service: \"hooks\",\n path: subscription.pathPrefix\n ? `${subscription.service}/${subscription.pathPrefix}`\n : subscription.service,\n action: \"tinycloud.hooks/subscribe\",\n }));\n\n if (this.context.invokeAny) {\n return this.context.invokeAny(this.session, entries);\n }\n\n if (entries.length === 1) {\n const entry = entries[0];\n return this.context.invoke(\n this.session,\n entry.service,\n entry.path,\n entry.action,\n );\n }\n\n throw new Error(\n \"This SDK runtime does not support multi-scope hook invocations\",\n );\n }\n}\n\nfunction buildScopePath(\n service: HookSubscription[\"service\"],\n pathPrefix?: string,\n): string {\n const normalized = normalizePathPrefix(pathPrefix);\n return normalized ? `${service}/${normalized}` : service;\n}\n\nfunction normalizeSubscription(\n subscription: HookSubscription,\n): HookSubscription {\n return {\n ...subscription,\n pathPrefix: normalizePathPrefix(subscription.pathPrefix),\n abilities: subscription.abilities ?? [],\n };\n}\n\nfunction subscriptionSignature(subscription: HookSubscription): string {\n return JSON.stringify({\n space: subscription.space,\n service: subscription.service,\n pathPrefix: subscription.pathPrefix ?? \"\",\n abilities: [...(subscription.abilities ?? [])].sort(),\n });\n}\n\nfunction matchesAnySubscription(\n event: HookEvent,\n subscriptions: HookSubscription[],\n): boolean {\n return subscriptions.some((subscription) =>\n matchesSubscription(event, subscription),\n );\n}\n\nfunction matchesSubscription(\n event: HookEvent,\n subscription: HookSubscription,\n): boolean {\n if (event.space !== subscription.space) {\n return false;\n }\n if (event.service !== subscription.service) {\n return false;\n }\n if (subscription.pathPrefix) {\n const prefix = subscription.pathPrefix.endsWith(\"/\")\n ? subscription.pathPrefix\n : `${subscription.pathPrefix}/`;\n if (\n event.path &&\n event.path !== subscription.pathPrefix &&\n !event.path.startsWith(prefix)\n ) {\n return false;\n }\n }\n const abilities = subscription.abilities ?? [];\n if (abilities.length > 0 && !abilities.includes(event.ability)) {\n return false;\n }\n return true;\n}\n\nfunction normalizePathPrefix(pathPrefix?: string): string | undefined {\n if (!pathPrefix) {\n return undefined;\n }\n const trimmed = pathPrefix.replace(/^\\/+|\\/+$/g, \"\");\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction serviceHeadersToRecord(\n headers: ServiceHeaders,\n): Record<string, string> {\n if (Array.isArray(headers)) {\n return Object.fromEntries(headers);\n }\n return { ...headers };\n}\n\nasync function responseError(\n service: string,\n message: string,\n response: FetchResponse,\n): Promise<ReturnType<typeof wrapError>> {\n let detail = response.statusText;\n try {\n const text = await response.text();\n if (text) {\n detail = text;\n }\n } catch {\n // Ignore secondary body read failure.\n }\n return wrapError(\n service,\n new Error(`${message}: ${response.status} ${detail}`),\n );\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof DOMException && error.name === \"AbortError\";\n}\n\nasync function* parseSseStream(\n body: unknown,\n signal?: AbortSignal,\n): AsyncIterable<HookStreamEvent> {\n if (!body) {\n throw new Error(\"Hook stream response does not expose a readable body\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n for await (const chunk of readBodyChunks(body, signal)) {\n buffer += decoder.decode(chunk, { stream: true }).replace(/\\r\\n/g, \"\\n\");\n\n let separatorIndex = buffer.indexOf(\"\\n\\n\");\n while (separatorIndex >= 0) {\n const rawEvent = buffer.slice(0, separatorIndex);\n buffer = buffer.slice(separatorIndex + 2);\n const parsed = parseSseEvent(rawEvent);\n if (parsed) {\n yield parsed;\n }\n separatorIndex = buffer.indexOf(\"\\n\\n\");\n }\n }\n\n buffer += decoder.decode();\n const trailing = parseSseEvent(buffer.trim());\n if (trailing) {\n yield trailing;\n }\n}\n\nasync function* readBodyChunks(\n body: unknown,\n signal?: AbortSignal,\n): AsyncIterable<Uint8Array> {\n const asyncIterable = body as AsyncIterable<Uint8Array>;\n if (typeof asyncIterable?.[Symbol.asyncIterator] === \"function\") {\n for await (const chunk of asyncIterable) {\n if (signal?.aborted) {\n break;\n }\n yield chunk;\n }\n return;\n }\n\n const stream = body as {\n getReader?: () => {\n read: () => Promise<{ done: boolean; value?: Uint8Array }>;\n releaseLock?: () => void;\n cancel?: () => Promise<void>;\n };\n };\n\n if (typeof stream.getReader !== \"function\") {\n throw new Error(\"Unsupported hook stream body type\");\n }\n\n const reader = stream.getReader();\n try {\n while (!signal?.aborted) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (value) {\n yield value;\n }\n }\n } finally {\n try {\n await reader.cancel?.();\n } catch {\n // Ignore cancellation failures.\n }\n reader.releaseLock?.();\n }\n}\n\nfunction parseSseEvent(rawEvent: string): HookStreamEvent | null {\n if (!rawEvent) {\n return null;\n }\n\n let event = \"message\";\n let id: string | undefined;\n const dataLines: string[] = [];\n\n for (const line of rawEvent.split(\"\\n\")) {\n if (!line || line.startsWith(\":\")) {\n continue;\n }\n const [field, ...rest] = line.split(\":\");\n const value = rest.join(\":\").replace(/^ /, \"\");\n switch (field) {\n case \"event\":\n event = value;\n break;\n case \"id\":\n id = value;\n break;\n case \"data\":\n dataLines.push(value);\n break;\n default:\n break;\n }\n }\n\n if (dataLines.length === 0) {\n return null;\n }\n\n return {\n event,\n id,\n data: dataLines.join(\"\\n\"),\n };\n}\n\nfunction parseHookEvent(message: HookStreamEvent): HookEvent {\n const parsed = JSON.parse(message.data) as Partial<HookEvent>;\n return {\n type: \"write\",\n id: parsed.id ?? message.id ?? \"\",\n space: parsed.space ?? \"\",\n service: parsed.service ?? \"\",\n ability: parsed.ability ?? \"\",\n path: parsed.path,\n actor: parsed.actor ?? \"\",\n epoch: parsed.epoch ?? \"\",\n eventIndex: parsed.eventIndex ?? 0,\n timestamp: parsed.timestamp ?? \"\",\n };\n}\n\nfunction normalizeWebhookRecord(data: unknown): HookWebhookRecord | null {\n if (!data || typeof data !== \"object\") {\n return null;\n }\n\n const record = isRecordContainer(data);\n const candidate =\n pickWebhookRecord(record) ??\n normalizeWebhookRecord(record.webhook) ??\n normalizeWebhookRecord(record.hook) ??\n normalizeWebhookRecord(record.subscription) ??\n normalizeWebhookRecord(record.data);\n return candidate ?? null;\n}\n\nfunction normalizeWebhookRecordList(data: unknown): HookWebhookRecord[] | null {\n if (Array.isArray(data)) {\n const records = data\n .map((entry) => normalizeWebhookRecord(entry))\n .filter((entry): entry is HookWebhookRecord => entry !== null);\n return records;\n }\n\n if (!data || typeof data !== \"object\") {\n return null;\n }\n\n const record = isRecordContainer(data);\n const nested =\n maybeRecordArray(record.webhooks) ??\n maybeRecordArray(record.subscriptions) ??\n maybeRecordArray(record.hooks) ??\n maybeRecordArray(record.data);\n if (nested) {\n return nested;\n }\n\n const single = pickWebhookRecord(record);\n return single ? [single] : null;\n}\n\nfunction maybeRecordArray(value: unknown): HookWebhookRecord[] | null {\n if (!Array.isArray(value)) {\n return null;\n }\n\n const records = value\n .map((entry) => normalizeWebhookRecord(entry))\n .filter((entry): entry is HookWebhookRecord => entry !== null);\n return records;\n}\n\nfunction pickWebhookRecord(\n value: Record<string, unknown>,\n): HookWebhookRecord | null {\n const id = stringField(value, \"id\");\n const space = stringField(value, \"space\") ?? stringField(value, \"spaceId\");\n const service = stringField(value, \"service\");\n const callbackUrl =\n stringField(value, \"callbackUrl\") ?? stringField(value, \"callback_url\");\n if (!id || !space || !service || !callbackUrl) {\n return null;\n }\n\n return {\n id,\n space,\n service: service as HookWebhookRecord[\"service\"],\n pathPrefix:\n optionalStringField(value, \"pathPrefix\") ??\n optionalStringField(value, \"path_prefix\"),\n abilities:\n stringArrayField(value, \"abilities\") ??\n parsedStringArrayField(value, \"abilitiesJson\") ??\n parsedStringArrayField(value, \"abilities_json\"),\n callbackUrl,\n active: booleanField(value, \"active\") ?? true,\n createdAt:\n stringField(value, \"createdAt\") ??\n stringField(value, \"created_at\") ??\n new Date().toISOString(),\n subscriberDid:\n optionalStringField(value, \"subscriberDid\") ??\n optionalStringField(value, \"subscriber_did\"),\n };\n}\n\nfunction isRecordContainer(value: object): Record<string, unknown> {\n return value as Record<string, unknown>;\n}\n\nfunction stringField(\n value: Record<string, unknown>,\n key: string,\n): string | undefined {\n const field = value[key];\n return typeof field === \"string\" ? field : undefined;\n}\n\nfunction optionalStringField(\n value: Record<string, unknown>,\n key: string,\n): string | undefined {\n return stringField(value, key);\n}\n\nfunction booleanField(\n value: Record<string, unknown>,\n key: string,\n): boolean | undefined {\n const field = value[key];\n return typeof field === \"boolean\" ? field : undefined;\n}\n\nfunction stringArrayField(\n value: Record<string, unknown>,\n key: string,\n): string[] | undefined {\n const field = value[key];\n if (!Array.isArray(field)) {\n return undefined;\n }\n const strings = field.filter(\n (item): item is string => typeof item === \"string\",\n );\n return strings.length === field.length ? strings : undefined;\n}\n\nfunction parsedStringArrayField(\n value: Record<string, unknown>,\n key: string,\n): string[] | undefined {\n const field = value[key];\n if (typeof field !== \"string\") {\n return undefined;\n }\n\n try {\n const parsed = JSON.parse(field) as unknown;\n if (!Array.isArray(parsed)) {\n return undefined;\n }\n const strings = parsed.filter(\n (item): item is string => typeof item === \"string\",\n );\n return strings.length === parsed.length ? strings : undefined;\n } catch {\n return undefined;\n }\n}\n","import type { StorageQuotaInfo } from \"../types\";\n\nexport interface QuotaConfig {\n /** Called when a storage quota error is detected (402/413) */\n onUpgradeRequired?: (info: StorageQuotaInfo) => void;\n}\n\nexport interface QuotaStatus {\n /** Storage limit in bytes for this space */\n limitBytes: number;\n /** Storage used in bytes for this space */\n usedBytes?: number;\n /** Remaining storage in bytes */\n remainingBytes?: number;\n}\n\nexport class TinyCloudQuota {\n private config: QuotaConfig;\n private quotaUrl: string | null = null;\n\n constructor(config: QuotaConfig = {}) {\n this.config = config;\n }\n\n /** Set the quota URL discovered from the /info endpoint */\n setQuotaUrl(url: string | null): void {\n this.quotaUrl = url;\n }\n\n /** Whether a quota service is available */\n get available(): boolean {\n return this.quotaUrl !== null;\n }\n\n /** Query quota status for a space from the quota URL */\n async getQuota(spaceId: string): Promise<QuotaStatus | null> {\n if (!this.quotaUrl) return null;\n\n const resp = await fetch(\n `${this.quotaUrl}/api/quota/${encodeURIComponent(spaceId)}`\n );\n if (!resp.ok) return null;\n\n const data = (await resp.json()) as { storage_limit_bytes?: number };\n return {\n limitBytes: data.storage_limit_bytes ?? 0,\n };\n }\n\n /** Trigger the upgrade callback when a quota error is encountered */\n handleQuotaError(info: StorageQuotaInfo): void {\n this.config.onUpgradeRequired?.(info);\n }\n}\n","/**\n * Data Vault Service Types\n *\n * Type definitions for the Data Vault (encrypted KV) service operations.\n */\n\n/**\n * Configuration for DataVaultService.\n */\nexport interface DataVaultConfig {\n /** Space ID for encrypted data storage */\n spaceId: string;\n /** Key rotation policy */\n keyRotation?: \"per-write\" | \"per-key\"; // default: \"per-write\"\n}\n\n/**\n * Options for vault put operations.\n */\nexport interface VaultPutOptions {\n /** Custom metadata tags appended to the envelope */\n metadata?: Record<string, string>;\n /** Content type hint for deserialization (default: auto-detect) */\n contentType?: string;\n /** Custom serializer (default: JSON.stringify for objects) */\n serialize?: (value: unknown) => Uint8Array;\n}\n\n/**\n * Options for vault get operations.\n */\nexport interface VaultGetOptions<T = unknown> {\n /** Custom deserializer (default: JSON.parse if content-type is JSON) */\n deserialize?: (data: Uint8Array) => T;\n /** Return raw decrypted bytes without deserialization */\n raw?: boolean;\n /** Delegated KV service for reading from the grantor's space (used by getShared) */\n kv?: { get<V>(key: string, options?: { raw?: boolean }): Promise<{ ok: boolean; data?: { data: V }; error?: { message: string } }> };\n}\n\n/**\n * Options for vault list operations.\n */\nexport interface VaultListOptions {\n /** Prefix filter for key names */\n prefix?: string;\n /** Remove prefix from returned keys */\n removePrefix?: boolean;\n}\n\n/**\n * Options for vault grant (sharing) operations.\n */\nexport interface VaultGrantOptions {\n /** Additional metadata on the grant */\n metadata?: Record<string, string>;\n}\n\n/**\n * A decrypted vault entry returned by get operations.\n *\n * @template T - Type of the decrypted value\n */\nexport interface VaultEntry<T> {\n /** Decrypted value */\n value: T;\n /** Envelope metadata */\n metadata: Record<string, string>;\n /** Key ID used for encryption */\n keyId: string;\n}\n\n/**\n * Structured error codes for vault operations.\n */\n/**\n * Input types for creating vault errors (service field added automatically).\n */\nexport type VaultErrorInput =\n | { code: \"DECRYPTION_FAILED\"; message?: string; cause?: Error }\n | { code: \"KEY_NOT_FOUND\"; key: string; message?: string }\n | { code: \"INTEGRITY_ERROR\"; message?: string; cause?: Error }\n | { code: \"GRANT_NOT_FOUND\"; grantor: string; key: string; message?: string }\n | { code: \"VAULT_LOCKED\"; message?: string }\n | { code: \"PUBLIC_KEY_NOT_FOUND\"; did: string; message?: string }\n | { code: \"STORAGE_ERROR\"; cause: Error; message?: string };\n\n/**\n * Vault error with service field (compatible with ServiceError).\n */\nexport type VaultError = VaultErrorInput & { service: \"vault\"; message: string };\n\n\n/** KV actions the vault needs on the public space for key publishing. */\nexport const VaultPublicSpaceKVActions = [\n \"tinycloud.kv/get\",\n \"tinycloud.kv/put\",\n \"tinycloud.kv/metadata\",\n] as const;\n\n/** Version-keyed signing message configuration for vault key derivation. */\nexport const VaultVersionConfig = {\n \"1\": {\n masterMessage: (spaceId: string) => `tinycloud-vault-master-v1:${spaceId}`,\n identityMessage: \"tinycloud-encryption-identity-v1\",\n },\n} as const;\n\nexport const CURRENT_VAULT_VERSION = \"1\" as const;\n\n/** Metadata header keys used in vault envelopes */\nexport const VaultHeaders = {\n VERSION: \"x-vault-version\",\n CIPHER: \"x-vault-cipher\",\n KEY_ID: \"x-vault-key-id\",\n CONTENT_TYPE: \"x-vault-content-type\",\n KDF: \"x-vault-kdf\",\n KEY_ROTATION: \"x-vault-key-rotation\",\n GRANT_VERSION: \"x-vault-grant-version\",\n GRANTOR: \"x-vault-grantor\",\n} as const;\n","/**\n * Caches vault signatures in IndexedDB, encrypted with a\n * non-extractable CryptoKey. Browser-only — no-ops in Node.\n */\n\n// Minimal type declarations for browser APIs used below.\n// The sdk-services tsconfig targets ES2020 without DOM lib;\n// these declarations let the file compile while the runtime\n// guards (isBrowser()) ensure we never call them in Node.\ndeclare const indexedDB: {\n open(name: string, version?: number): IDBOpenDBRequest;\n};\ninterface IDBOpenDBRequest {\n result: IDBDatabase;\n error: DOMException | null;\n onupgradeneeded: ((this: IDBOpenDBRequest) => void) | null;\n onsuccess: ((this: IDBOpenDBRequest) => void) | null;\n onerror: ((this: IDBOpenDBRequest) => void) | null;\n}\ninterface IDBDatabase {\n objectStoreNames: { contains(name: string): boolean };\n createObjectStore(name: string): void;\n transaction(storeNames: string | string[], mode?: string): IDBTransaction;\n}\ninterface IDBTransaction {\n objectStore(name: string): IDBObjectStore;\n}\ninterface IDBObjectStore {\n get(key: string): IDBRequest;\n put(value: unknown, key: string): IDBRequest;\n delete(key: string): IDBRequest;\n getAllKeys(): IDBRequest;\n}\ninterface IDBRequest<T = unknown> {\n result: T;\n error: DOMException | null;\n onsuccess: ((this: IDBRequest<T>) => void) | null;\n onerror: ((this: IDBRequest<T>) => void) | null;\n}\ntype IDBValidKey = string | number | Date | ArrayBuffer | Uint8Array | IDBValidKey[];\n\nconst DB_NAME = \"tinycloud-vault-cache\";\nconst DB_VERSION = 1;\nconst STORE_NAME = \"signatures\";\nconst WRAP_KEY_ID = \"__wrap_key__\";\n\n/** Check whether we're in a browser with IndexedDB + SubtleCrypto support. */\nfunction isBrowser(): boolean {\n try {\n return (\n typeof indexedDB !== \"undefined\" &&\n typeof crypto !== \"undefined\" &&\n typeof crypto.subtle !== \"undefined\"\n );\n } catch {\n return false;\n }\n}\n\n/** Open (or create) the IndexedDB database. */\nfunction openDB(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\n/** Generic IDB get helper. */\nfunction idbGet<T>(db: IDBDatabase, key: string): Promise<T | undefined> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, \"readonly\");\n const store = tx.objectStore(STORE_NAME);\n const req = store.get(key);\n req.onsuccess = () => resolve(req.result as T | undefined);\n req.onerror = () => reject(req.error);\n });\n}\n\n/** Generic IDB put helper. */\nfunction idbPut(db: IDBDatabase, key: string, value: unknown): Promise<void> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, \"readwrite\");\n const store = tx.objectStore(STORE_NAME);\n const req = store.put(value, key);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n });\n}\n\n/** Generic IDB delete helper. */\nfunction idbDelete(db: IDBDatabase, key: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, \"readwrite\");\n const store = tx.objectStore(STORE_NAME);\n const req = store.delete(key);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n });\n}\n\n/** List all keys in the store. */\nfunction idbKeys(db: IDBDatabase): Promise<string[]> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, \"readonly\");\n const store = tx.objectStore(STORE_NAME);\n const req = store.getAllKeys();\n req.onsuccess = () =>\n resolve((req.result as IDBValidKey[]).filter((k) => typeof k === \"string\") as string[]);\n req.onerror = () => reject(req.error);\n });\n}\n\ninterface EncryptedEntry {\n iv: Uint8Array;\n ciphertext: Uint8Array;\n}\n\n/**\n * Get or create the non-extractable AES-GCM wrapping key.\n * The key is stored directly in IndexedDB (structured-clone preserves CryptoKey).\n */\nasync function getWrapKey(db: IDBDatabase): Promise<CryptoKey> {\n const existing = await idbGet<CryptoKey>(db, WRAP_KEY_ID);\n if (existing) return existing;\n\n const key = await crypto.subtle.generateKey(\n { name: \"AES-GCM\", length: 256 },\n false, // non-extractable\n [\"encrypt\", \"decrypt\"]\n );\n await idbPut(db, WRAP_KEY_ID, key);\n return key;\n}\n\n/** Encrypt signature bytes with the wrap key. */\nasync function encryptSig(\n wrapKey: CryptoKey,\n sigBytes: Uint8Array\n): Promise<EncryptedEntry> {\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const ciphertext = new Uint8Array(\n await crypto.subtle.encrypt({ name: \"AES-GCM\", iv }, wrapKey, sigBytes)\n );\n return { iv, ciphertext };\n}\n\n/** Decrypt an encrypted entry back to signature bytes. */\nasync function decryptSig(\n wrapKey: CryptoKey,\n entry: EncryptedEntry\n): Promise<Uint8Array> {\n const plaintext = await crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv: entry.iv },\n wrapKey,\n entry.ciphertext\n );\n return new Uint8Array(plaintext);\n}\n\n/** Cache key for a given spaceId. */\nfunction cacheKey(spaceId: string): string {\n return `sig:${spaceId}`;\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Load a cached signature for the given spaceId.\n * Returns null on cache miss or in non-browser environments.\n */\nexport async function loadCachedSignature(\n spaceId: string\n): Promise<Uint8Array | null> {\n if (!isBrowser()) return null;\n try {\n const db = await openDB();\n const entry = await idbGet<EncryptedEntry>(db, cacheKey(spaceId));\n if (!entry) return null;\n const wrapKey = await getWrapKey(db);\n return await decryptSig(wrapKey, entry);\n } catch {\n return null;\n }\n}\n\n/**\n * Cache a signature for the given spaceId.\n * No-ops in non-browser environments.\n */\nexport async function cacheSignature(\n spaceId: string,\n sigBytes: Uint8Array\n): Promise<void> {\n if (!isBrowser()) return;\n try {\n const db = await openDB();\n const wrapKey = await getWrapKey(db);\n const encrypted = await encryptSig(wrapKey, sigBytes);\n await idbPut(db, cacheKey(spaceId), encrypted);\n } catch {\n // Best-effort — swallow errors\n }\n}\n\n/**\n * Clear cached signature(s).\n * If spaceId is provided, clears only that entry; otherwise clears all.\n */\nexport async function clearSignatureCache(\n spaceId?: string\n): Promise<void> {\n if (!isBrowser()) return;\n try {\n const db = await openDB();\n if (spaceId) {\n await idbDelete(db, cacheKey(spaceId));\n } else {\n // Clear all sig entries but keep the wrap key\n const keys = await idbKeys(db);\n for (const k of keys) {\n if (k.startsWith(\"sig:\")) {\n await idbDelete(db, k);\n }\n }\n }\n } catch {\n // Best-effort\n }\n}\n","/**\n * DataVaultService - Encrypted key-value storage service implementation.\n *\n * Platform-agnostic encrypted KV service that wraps KVService internally.\n * Uses dependency injection via VaultCrypto for WASM crypto operations\n * and DataVaultServiceConfig for platform dependencies.\n *\n * Architecture:\n * - Extends BaseService (not KVService)\n * - Wraps two KV instances: dataKV (prefix \"vault/\") and keyKV (prefix \"keys/\")\n * - Master key and encryption identity live in memory only (cleared on lock)\n */\n\nimport { BaseService } from \"../base/BaseService\";\nimport {\n Result,\n ok,\n err,\n serviceError,\n IServiceContext,\n ServiceSession,\n} from \"../types\";\nimport { wrapError } from \"../errors\";\nimport type { IKVService } from \"../kv/IKVService\";\nimport type { KVService } from \"../kv/KVService\";\nimport type { IDataVaultService } from \"./IDataVaultService\";\nimport {\n DataVaultConfig,\n VaultPutOptions,\n VaultGetOptions,\n VaultListOptions,\n VaultGrantOptions,\n VaultEntry,\n VaultError,\n VaultErrorInput,\n VaultHeaders,\n VaultVersionConfig,\n CURRENT_VAULT_VERSION,\n} from \"./types\";\nimport {\n loadCachedSignature,\n cacheSignature,\n clearSignatureCache,\n} from \"./SignatureCache\";\n\n// =============================================================================\n// Crypto Interface\n// =============================================================================\n\n/**\n * Crypto operations interface - implementations provided by WASM bindings.\n * Passed via DataVaultServiceConfig to keep the service platform-agnostic.\n */\nexport interface VaultCrypto {\n encrypt(key: Uint8Array, plaintext: Uint8Array): Uint8Array;\n decrypt(key: Uint8Array, blob: Uint8Array): Uint8Array;\n deriveKey(\n signature: Uint8Array,\n salt: Uint8Array,\n info: Uint8Array\n ): Uint8Array;\n x25519FromSeed(\n seed: Uint8Array\n ): { publicKey: Uint8Array; privateKey: Uint8Array };\n x25519Dh(privateKey: Uint8Array, publicKey: Uint8Array): Uint8Array;\n randomBytes(length: number): Uint8Array;\n sha256(data: Uint8Array): Uint8Array;\n}\n\n// =============================================================================\n// Extended Config\n// =============================================================================\n\n/**\n * Extended config used internally by DataVaultService.\n * Includes crypto operations and TinyCloud instance references.\n */\ninterface DataVaultServiceConfig extends DataVaultConfig {\n [key: string]: unknown;\n /** Crypto operations (WASM bindings) */\n crypto: VaultCrypto;\n /** TinyCloud instance for space/kv/delegation operations */\n tc: {\n kv: IKVService;\n ensurePublicSpace(): Promise<Result<void>>;\n publicKV: IKVService;\n readPublicSpace<T>(\n host: string,\n spaceId: string,\n key: string\n ): Promise<Result<T>>;\n makePublicSpaceId(address: string, chainId: number): string;\n did: string;\n address: string;\n chainId: number;\n hosts: string[];\n };\n}\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/** Convert a caught value to an Error. WASM throws plain objects, not Error instances. */\nfunction toError(error: unknown): Error {\n if (error instanceof Error) return error;\n if (typeof error === \"object\" && error !== null) {\n return new Error(JSON.stringify(error));\n }\n return new Error(String(error));\n}\n\nfunction toBytes(str: string): Uint8Array {\n return new TextEncoder().encode(str);\n}\n\nfunction fromBytes(bytes: Uint8Array): string {\n return new TextDecoder().decode(bytes);\n}\n\nfunction hexEncode(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nfunction concatBytes(...arrays: Uint8Array[]): Uint8Array {\n const total = arrays.reduce((acc, arr) => acc + arr.length, 0);\n const result = new Uint8Array(total);\n let offset = 0;\n for (const arr of arrays) {\n result.set(arr, offset);\n offset += arr.length;\n }\n return result;\n}\n\nfunction base64Encode(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\nfunction base64Decode(str: string): Uint8Array {\n const binary = atob(str);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\nfunction defaultVaultMessage(input: VaultErrorInput): string {\n switch (input.code) {\n case \"DECRYPTION_FAILED\": return input.message ?? \"Decryption failed\";\n case \"KEY_NOT_FOUND\": return input.message ?? `Key not found: ${input.key}`;\n case \"INTEGRITY_ERROR\": return input.message ?? \"Integrity check failed\";\n case \"GRANT_NOT_FOUND\": return input.message ?? `Grant not found: ${input.grantor} / ${input.key}`;\n case \"VAULT_LOCKED\": return input.message ?? \"Vault is locked\";\n case \"PUBLIC_KEY_NOT_FOUND\": return input.message ?? `Public key not found for ${input.did}`;\n case \"STORAGE_ERROR\": return input.message ?? input.cause.message;\n }\n}\n\nfunction vaultError(input: VaultErrorInput): Result<never, VaultError> {\n const error: VaultError = {\n ...input,\n service: \"vault\",\n message: defaultVaultMessage(input),\n };\n return { ok: false, error };\n}\n\n// =============================================================================\n// DataVaultService\n// =============================================================================\n\n/**\n * Data Vault service implementation.\n *\n * Provides encrypted key-value storage with client-side encryption,\n * key management, and sharing via X25519 grants.\n *\n * @example\n * ```typescript\n * // Unlock the vault\n * await vault.unlock(signer);\n *\n * // Store encrypted data\n * await vault.put('secret/notes', { content: 'Hello' });\n *\n * // Retrieve and decrypt\n * const entry = await vault.get<{ content: string }>('secret/notes');\n * if (entry.ok) {\n * console.log(entry.data.value.content); // 'Hello'\n * }\n *\n * // Share with another user\n * await vault.grant('secret/notes', recipientDID);\n * ```\n */\nexport class DataVaultService extends BaseService implements IDataVaultService {\n /**\n * Service identifier for registration.\n */\n static readonly serviceName = \"vault\";\n\n /**\n * Service configuration.\n */\n declare protected _config: DataVaultServiceConfig;\n\n private masterKey: Uint8Array | null = null;\n private encryptionIdentity: {\n publicKey: Uint8Array;\n privateKey: Uint8Array;\n } | null = null;\n private _isUnlocked = false;\n private vaultConfig: DataVaultServiceConfig;\n\n /**\n * Create a new DataVaultService instance.\n *\n * @param config - Service configuration including crypto and tc references\n */\n constructor(config: DataVaultServiceConfig) {\n super();\n this.vaultConfig = config;\n this._config = config;\n }\n\n /**\n * Get the service configuration.\n */\n get config(): DataVaultServiceConfig {\n return this._config;\n }\n\n /**\n * Whether the vault is currently unlocked.\n */\n get isUnlocked(): boolean {\n return this._isUnlocked;\n }\n\n /**\n * The vault's public encryption key (X25519).\n * Throws if vault is locked.\n */\n get publicKey(): Uint8Array {\n if (!this.encryptionIdentity) {\n throw new Error(\"Vault is locked\");\n }\n return this.encryptionIdentity.publicKey;\n }\n\n /**\n * Convenience accessor for crypto operations.\n */\n private get crypto(): VaultCrypto {\n return this.vaultConfig.crypto;\n }\n\n /**\n * Convenience accessor for TinyCloud instance.\n */\n private get tc() {\n return this.vaultConfig.tc;\n }\n\n /**\n * Get the host URL.\n */\n private get host(): string {\n return this.tc.hosts[0];\n }\n\n // =========================================================================\n // Phase 1: Core Operations\n // =========================================================================\n\n /**\n * Unlock the vault. Derives keys from two wallet signatures:\n * 1. Master signature (per-space) — used to derive the master encryption key\n * 2. Identity signature (per-address) — used to derive X25519 encryption identity\n *\n * If the identity public key already exists in the public space, the identity\n * signature is skipped entirely (no wallet popup). The identity private key is\n * only needed for sharing operations.\n *\n * @param signer - Object with signMessage method. Optional when cached\n * signatures exist (browser only).\n */\n async unlock(\n signer?: { signMessage(message: string): Promise<string> } | unknown\n ): Promise<Result<void, VaultError>> {\n return this.withTelemetry(\"unlock\", undefined, async () => {\n const spaceId = this.vaultConfig.spaceId;\n const versionConfig = VaultVersionConfig[CURRENT_VAULT_VERSION];\n const masterCacheKey = `vault-master:${spaceId}`;\n const identityCacheKey = `vault-identity:${this.tc.address}`;\n\n try {\n // -----------------------------------------------------------------\n // Step 1: Master signature → master key\n // -----------------------------------------------------------------\n let masterSigBytes = await loadCachedSignature(masterCacheKey);\n\n if (!masterSigBytes) {\n if (!signer) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Signer is required when no cached master signature exists\",\n });\n }\n const s = signer as { signMessage(message: string): Promise<string> };\n const sig = await s.signMessage(versionConfig.masterMessage(spaceId));\n masterSigBytes = toBytes(sig);\n await cacheSignature(masterCacheKey, masterSigBytes);\n }\n\n // Derive master key: deriveKey(sigBytes, sha256(spaceId), \"vault-master\")\n this.masterKey = this.crypto.deriveKey(\n masterSigBytes,\n this.crypto.sha256(toBytes(spaceId)),\n toBytes(\"vault-master\")\n );\n\n // -----------------------------------------------------------------\n // Step 2: Identity — check public space first, then sign if needed\n // -----------------------------------------------------------------\n const publicSpaceId = this.tc.makePublicSpaceId(this.tc.address, this.tc.chainId);\n\n // Check public space for existing vault pubkey\n let existingPubKey: string | null = null;\n try {\n const existing = await this.tc.readPublicSpace<string>(\n this.host, publicSpaceId, \".well-known/vault-pubkey\"\n );\n if (existing.ok && existing.data) {\n existingPubKey = existing.data as string;\n }\n } catch {\n // Read failed — treat as missing\n }\n\n if (existingPubKey) {\n // Public key exists — trust it, skip identity signing entirely\n this.encryptionIdentity = {\n publicKey: base64Decode(existingPubKey),\n privateKey: new Uint8Array(0), // private key not available without signing\n };\n } else {\n // Public key missing — need identity signature to derive keypair\n let identitySigBytes = await loadCachedSignature(identityCacheKey);\n\n if (!identitySigBytes) {\n if (!signer) {\n // No signer available — skip identity derivation.\n // Vault still works for get/put (only needs master key).\n this.encryptionIdentity = null;\n this._isUnlocked = true;\n return ok(undefined);\n }\n const s = signer as { signMessage(message: string): Promise<string> };\n const sig = await s.signMessage(versionConfig.identityMessage);\n identitySigBytes = toBytes(sig);\n await cacheSignature(identityCacheKey, identitySigBytes);\n }\n\n // Derive X25519 keypair from identity signature\n const seed = this.crypto.deriveKey(\n identitySigBytes,\n toBytes(\"tinycloud-x25519\"),\n toBytes(\"encryption-identity\")\n );\n this.encryptionIdentity = this.crypto.x25519FromSeed(seed);\n\n // Publish public key to public space\n try {\n const pubKeyB64 = base64Encode(this.encryptionIdentity.publicKey);\n await this.tc.ensurePublicSpace();\n await this.tc.publicKV.put(\".well-known/vault-pubkey\", pubKeyB64);\n await this.tc.publicKV.put(\".well-known/vault-version\", CURRENT_VAULT_VERSION);\n await this.tc.publicKV.put(\".well-known/vault-space\", this.vaultConfig.spaceId);\n } catch {\n // Publishing failed — vault still usable\n }\n }\n\n this._isUnlocked = true;\n return ok(undefined);\n } catch (error) {\n // Clear key material on failure\n this.masterKey = null;\n this.encryptionIdentity = null;\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<void, VaultError>>;\n }\n\n /**\n * Clear the cached vault signatures.\n *\n * @param spaceId - Clear only this space's master cache. If omitted, clears all.\n */\n async clearCache(spaceId?: string): Promise<void> {\n if (spaceId) {\n await clearSignatureCache(`vault-master:${spaceId}`);\n } else {\n await clearSignatureCache();\n }\n }\n\n /**\n * Lock the vault, clearing all key material from memory.\n */\n lock(): void {\n this.masterKey = null;\n this.encryptionIdentity = null;\n this._isUnlocked = false;\n }\n\n /**\n * Called when SDK signs out. Locks the vault and aborts operations.\n */\n onSignOut(): void {\n this.lock();\n super.onSignOut();\n }\n\n /**\n * Encrypt and store a value at the given key.\n *\n * @param key - The key to store under\n * @param value - The value to encrypt and store\n * @param options - Optional put configuration\n */\n async put(\n key: string,\n value: unknown,\n options?: VaultPutOptions\n ): Promise<Result<void, VaultError>> {\n return this.withTelemetry(\"put\", key, async () => {\n if (!this._isUnlocked || !this.masterKey) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before storing data\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Serialize value\n let plaintext: Uint8Array;\n if (value instanceof Uint8Array) {\n plaintext = value;\n } else if (options?.serialize) {\n plaintext = options.serialize(value);\n } else if (typeof value === \"string\") {\n plaintext = toBytes(value);\n } else {\n plaintext = toBytes(JSON.stringify(value));\n }\n\n const contentType =\n options?.contentType ??\n (value instanceof Uint8Array\n ? \"application/octet-stream\"\n : \"application/json\");\n\n // Generate per-entry key\n const entryKey = this.crypto.randomBytes(32);\n const keyId = hexEncode(this.crypto.sha256(entryKey)).slice(0, 16);\n\n // Encrypt value with entry key\n const encrypted = this.crypto.encrypt(entryKey, plaintext);\n\n // Encrypt entry key with master key\n const keyBlob = this.crypto.encrypt(this.masterKey, entryKey);\n\n // Build metadata\n const metadata: Record<string, string> = {\n [VaultHeaders.VERSION]: \"1\",\n [VaultHeaders.CIPHER]: \"aes-256-gcm\",\n [VaultHeaders.KEY_ID]: keyId,\n [VaultHeaders.CONTENT_TYPE]: contentType,\n [VaultHeaders.KDF]: \"hkdf-sha256\",\n [VaultHeaders.KEY_ROTATION]:\n this.vaultConfig.keyRotation ?? \"per-write\",\n ...(options?.metadata ?? {}),\n };\n\n // Store encrypted entry key in key space\n const keyMetadata = JSON.stringify({\n keyId,\n contentType,\n ...metadata,\n });\n const keyPayload = JSON.stringify({\n key: base64Encode(keyBlob),\n metadata: keyMetadata,\n });\n const keyPutResult = await this.tc.kv.put(\n `keys/${key}`,\n keyPayload\n );\n if (!keyPutResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to store key blob: ${keyPutResult.error.message}`\n ),\n });\n }\n\n // Store encrypted value in data space\n const valuePayload = JSON.stringify({\n data: base64Encode(encrypted),\n metadata,\n });\n const valuePutResult = await this.tc.kv.put(\n `vault/${key}`,\n valuePayload\n );\n if (!valuePutResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to store encrypted value: ${valuePutResult.error.message}`\n ),\n });\n }\n\n return ok(undefined);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<void, VaultError>>;\n }\n\n /**\n * Retrieve and decrypt a value by key.\n *\n * @param key - The key to retrieve\n * @param options - Optional get configuration\n * @returns Result with the decrypted entry\n */\n async get<T = unknown>(\n key: string,\n options?: VaultGetOptions<T>\n ): Promise<Result<VaultEntry<T>, VaultError>> {\n return this.withTelemetry(\"get\", key, async () => {\n if (!this._isUnlocked || !this.masterKey) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before reading data\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Fetch encrypted entry key from key space\n const keyResult = await this.tc.kv.get<string>(`keys/${key}`, {\n raw: true,\n });\n if (!keyResult.ok) {\n return vaultError({ code: \"KEY_NOT_FOUND\", key });\n }\n\n const keyEnvelope = JSON.parse(keyResult.data.data as string);\n const keyBlobBytes = base64Decode(keyEnvelope.key);\n const entryKey = this.crypto.decrypt(this.masterKey, keyBlobBytes);\n\n // Fetch encrypted value from data space\n const valueResult = await this.tc.kv.get<string>(`vault/${key}`, {\n raw: true,\n });\n if (!valueResult.ok) {\n return vaultError({ code: \"KEY_NOT_FOUND\", key });\n }\n\n const valueEnvelope = JSON.parse(valueResult.data.data as string);\n const encryptedBytes = base64Decode(valueEnvelope.data);\n const plaintext = this.crypto.decrypt(entryKey, encryptedBytes);\n\n // Read metadata\n const metadata: Record<string, string> = valueEnvelope.metadata ?? {};\n const contentType =\n metadata[VaultHeaders.CONTENT_TYPE] ?? \"application/json\";\n const keyId = metadata[VaultHeaders.KEY_ID] ?? \"\";\n\n // Deserialize\n let value: T;\n if (options?.raw) {\n value = plaintext as unknown as T;\n } else if (options?.deserialize) {\n value = options.deserialize(plaintext);\n } else if (contentType === \"application/json\") {\n value = JSON.parse(fromBytes(plaintext)) as T;\n } else {\n value = plaintext as unknown as T;\n }\n\n return ok({ value, metadata, keyId });\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes(\"decryption\")\n ) {\n return vaultError({\n code: \"DECRYPTION_FAILED\",\n message: error.message,\n });\n }\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<VaultEntry<T>, VaultError>>;\n }\n\n /**\n * Delete an encrypted key.\n * Removes both the encrypted value and the key blob.\n *\n * @param key - The key to delete\n */\n async delete(key: string): Promise<Result<void, VaultError>> {\n return this.withTelemetry(\"delete\", key, async () => {\n if (!this._isUnlocked) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before deleting data\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Delete from both key space and data space\n const [keyDelResult, valueDelResult] = await Promise.all([\n this.tc.kv.delete(`keys/${key}`),\n this.tc.kv.delete(`vault/${key}`),\n ]);\n\n if (!keyDelResult.ok && !valueDelResult.ok) {\n return vaultError({ code: \"KEY_NOT_FOUND\", key });\n }\n\n return ok(undefined);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<void, VaultError>>;\n }\n\n /**\n * List vault keys with optional prefix filtering.\n *\n * @param options - Optional list configuration\n * @returns Result with array of key names (vault/ prefix stripped)\n */\n async list(\n options?: VaultListOptions\n ): Promise<Result<string[], VaultError>> {\n return this.withTelemetry(\"list\", options?.prefix, async () => {\n if (!this._isUnlocked) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before listing data\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n const listPrefix = options?.prefix\n ? `vault/${options.prefix}`\n : \"vault/\";\n\n const listResult = await this.tc.kv.list({\n prefix: listPrefix,\n removePrefix: true,\n });\n\n if (!listResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to list vault keys: ${listResult.error.message}`\n ),\n });\n }\n\n // Keys are already stripped of the \"vault/\" prefix by removePrefix\n let keys = listResult.data.keys;\n\n // If a user prefix was provided, strip it too if requested\n if (options?.removePrefix && options.prefix) {\n const userPrefix = options.prefix.endsWith(\"/\")\n ? options.prefix\n : `${options.prefix}/`;\n keys = keys.map((k) =>\n k.startsWith(userPrefix) ? k.slice(userPrefix.length) : k\n );\n }\n\n return ok(keys);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<string[], VaultError>>;\n }\n\n /**\n * Get envelope metadata for a key without decrypting the value.\n *\n * @param key - The key to inspect\n * @returns Result with metadata headers\n */\n async head(\n key: string\n ): Promise<Result<Record<string, string>, VaultError>> {\n return this.withTelemetry(\"head\", key, async () => {\n if (!this._isUnlocked) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before reading metadata\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Fetch envelope without decrypting\n const valueResult = await this.tc.kv.get<string>(`vault/${key}`, {\n raw: true,\n });\n if (!valueResult.ok) {\n return vaultError({ code: \"KEY_NOT_FOUND\", key });\n }\n\n const valueEnvelope = JSON.parse(valueResult.data.data as string);\n const metadata: Record<string, string> = valueEnvelope.metadata ?? {};\n return ok(metadata);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<Record<string, string>, VaultError>>;\n }\n\n // =========================================================================\n // Batch Operations\n // =========================================================================\n\n /**\n * Encrypt and store multiple entries.\n *\n * @param entries - Array of key/value pairs with optional per-entry options\n * @returns Array of results, one per entry\n */\n async putMany(\n entries: Array<{ key: string; value: unknown; options?: VaultPutOptions }>\n ): Promise<Result<void, VaultError>[]> {\n return Promise.all(\n entries.map((entry) => this.put(entry.key, entry.value, entry.options))\n );\n }\n\n /**\n * Retrieve and decrypt multiple keys.\n *\n * @param keys - Array of keys to retrieve\n * @param options - Optional get configuration applied to all entries\n * @returns Array of results, one per key\n */\n async getMany<T = unknown>(\n keys: string[],\n options?: VaultGetOptions<T>\n ): Promise<Result<VaultEntry<T>, VaultError>[]> {\n return Promise.all(keys.map((key) => this.get<T>(key, options)));\n }\n\n // =========================================================================\n // Phase 2: Sharing\n // =========================================================================\n\n /**\n * Re-encrypt a vault key for another user (renamed from grant).\n * Re-encrypts the data key to the recipient's public key via X25519 DH.\n *\n * @param key - The key to share\n * @param recipientDID - The recipient's primary DID (did:pkh:...)\n * @param options - Optional grant configuration\n */\n async reencrypt(\n key: string,\n recipientDID: string,\n options?: VaultGrantOptions\n ): Promise<Result<void, VaultError>> {\n return this.withTelemetry(\"reencrypt\", key, async () => {\n if (!this._isUnlocked || !this.masterKey) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before granting access\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Step 1: Resolve recipient's public key\n const pubKeyResult = await this.resolvePublicKey(recipientDID);\n if (!pubKeyResult.ok) {\n return pubKeyResult;\n }\n const bobPubKey = pubKeyResult.data;\n\n // Step 2: Fetch and decrypt entry key from key space\n const keyResult = await this.tc.kv.get<string>(`keys/${key}`, {\n raw: true,\n });\n if (!keyResult.ok) {\n return vaultError({ code: \"KEY_NOT_FOUND\", key });\n }\n\n const keyEnvelope = JSON.parse(keyResult.data.data as string);\n const keyBlobBytes = base64Decode(keyEnvelope.key);\n const entryKey = this.crypto.decrypt(this.masterKey, keyBlobBytes);\n\n // Step 3: Create ephemeral X25519 key pair\n const ephemeralSeed = this.crypto.randomBytes(32);\n const ephemeralKeyPair = this.crypto.x25519FromSeed(ephemeralSeed);\n\n // Step 4: Compute shared secret via DH\n const sharedSecret = this.crypto.x25519Dh(\n ephemeralKeyPair.privateKey,\n bobPubKey\n );\n\n // Step 5: Derive encryption key from shared secret\n const encryptionKey = this.crypto.deriveKey(\n sharedSecret,\n toBytes(\"tinycloud-x25519\"),\n toBytes(\"vault-grant\")\n );\n\n // Step 6: Encrypt entry key with derived key\n const encryptedGrant = this.crypto.encrypt(encryptionKey, entryKey);\n\n // Step 7: Concatenate ephemeral public key + encrypted grant\n const grantBlob = concatBytes(\n ephemeralKeyPair.publicKey,\n encryptedGrant\n );\n\n // Step 8: Store grant in key space\n const grantPayload = JSON.stringify({\n grant: base64Encode(grantBlob),\n spaceId: this.vaultConfig.spaceId,\n metadata: {\n [VaultHeaders.GRANT_VERSION]: \"1\",\n [VaultHeaders.GRANTOR]: this.tc.did,\n ...(options?.metadata ?? {}),\n },\n });\n // Store grant in the vault's space (main space)\n const grantPutResult = await this.tc.kv.put(\n `grants/${recipientDID}/${key}`,\n grantPayload\n );\n if (!grantPutResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to store grant: ${grantPutResult.error.message}`\n ),\n });\n }\n\n return ok(undefined);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<void, VaultError>>;\n }\n\n /**\n * @deprecated Use reencrypt() instead.\n */\n async grant(\n key: string,\n recipientDID: string,\n options?: VaultGrantOptions\n ): Promise<Result<void, VaultError>> {\n return this.reencrypt(key, recipientDID, options);\n }\n\n /**\n * Retrieve and decrypt a value shared by another user.\n *\n * @param grantorDID - The DID of the user who shared the data\n * @param key - The key that was shared\n * @param options - Optional get configuration\n * @returns Result with the decrypted entry\n */\n async getShared<T = unknown>(\n grantorDID: string,\n key: string,\n options?: VaultGetOptions<T>\n ): Promise<Result<VaultEntry<T>, VaultError>> {\n return this.withTelemetry(\"getShared\", key, async () => {\n if (\n !this._isUnlocked ||\n !this.masterKey ||\n !this.encryptionIdentity\n ) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before reading shared data\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n const myDID = this.tc.did;\n const grantorKV = options?.kv;\n\n if (!grantorKV) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n \"getShared requires a delegated KV service via options.kv. \" +\n \"Use useDelegation() to get delegated access, then pass { kv: access.kv }.\"\n ),\n });\n }\n\n // Step 1: Fetch grant from grantor's space via delegated KV\n const grantResult = await grantorKV.get<string>(`grants/${myDID}/${key}`, {\n raw: true,\n });\n if (!grantResult.ok) {\n return vaultError({\n code: \"GRANT_NOT_FOUND\",\n grantor: grantorDID,\n key,\n });\n }\n\n const grantEnvelope = typeof grantResult.data?.data === \"string\"\n ? JSON.parse(grantResult.data.data as string)\n : grantResult.data?.data;\n const grantBlobBytes = base64Decode((grantEnvelope as any).grant);\n\n // Step 2: Extract ephemeral public key and encrypted grant\n const ephemeralPubKey = grantBlobBytes.slice(0, 32);\n const encryptedGrant = grantBlobBytes.slice(32);\n\n // Step 3: Compute shared secret using our private key\n const sharedSecret = this.crypto.x25519Dh(\n this.encryptionIdentity.privateKey,\n ephemeralPubKey\n );\n\n // Step 4: Derive decryption key\n const encryptionKey = this.crypto.deriveKey(\n sharedSecret,\n toBytes(\"tinycloud-x25519\"),\n toBytes(\"vault-grant\")\n );\n\n // Step 5: Decrypt entry key\n const entryKey = this.crypto.decrypt(encryptionKey, encryptedGrant);\n\n // Step 6: Fetch encrypted value from grantor's space via delegated KV\n const valueResult = await grantorKV.get<string>(`vault/${key}`, {\n raw: true,\n });\n if (!valueResult.ok) {\n return vaultError({\n code: \"KEY_NOT_FOUND\",\n key,\n });\n }\n\n const valueEnvelope = typeof valueResult.data?.data === \"string\"\n ? JSON.parse(valueResult.data.data as string)\n : valueResult.data?.data;\n const encryptedBytes = base64Decode((valueEnvelope as any).data);\n const plaintext = this.crypto.decrypt(entryKey, encryptedBytes);\n\n // Read metadata\n const metadata: Record<string, string> = (valueEnvelope as any).metadata ?? {};\n const contentType =\n metadata[VaultHeaders.CONTENT_TYPE] ?? \"application/json\";\n const keyId = metadata[VaultHeaders.KEY_ID] ?? \"\";\n\n // Deserialize\n let value: T;\n if (options?.raw) {\n value = plaintext as unknown as T;\n } else if (options?.deserialize) {\n value = options.deserialize(plaintext);\n } else if (contentType === \"application/json\") {\n value = JSON.parse(fromBytes(plaintext)) as T;\n } else {\n value = plaintext as unknown as T;\n }\n\n return ok({ value, metadata, keyId });\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes(\"decryption\")\n ) {\n return vaultError({\n code: \"DECRYPTION_FAILED\",\n message: error.message,\n });\n }\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<VaultEntry<T>, VaultError>>;\n }\n\n /**\n * Resolve another user's public encryption key from their DID.\n *\n * @param did - The DID to resolve (did:pkh:eip155:{chainId}:{address})\n * @returns Result with the public key bytes\n */\n async resolvePublicKey(\n did: string\n ): Promise<Result<Uint8Array, VaultError>> {\n try {\n const parts = this.parseDID(did);\n if (!parts) {\n return vaultError({ code: \"PUBLIC_KEY_NOT_FOUND\", did });\n }\n\n const spaceId = this.tc.makePublicSpaceId(\n parts.address,\n parts.chainId\n );\n\n const result = await this.tc.readPublicSpace<string>(\n this.host,\n spaceId,\n \".well-known/vault-pubkey\"\n );\n\n if (!result.ok) {\n return vaultError({ code: \"PUBLIC_KEY_NOT_FOUND\", did });\n }\n\n const pubKeyBytes = base64Decode(result.data as string);\n return { ok: true, data: pubKeyBytes } as Result<Uint8Array, VaultError>;\n } catch (error) {\n return vaultError({ code: \"PUBLIC_KEY_NOT_FOUND\", did });\n }\n }\n\n /**\n * List DIDs that have been granted access to a key.\n *\n * @param key - The key to list grants for\n * @returns Result with array of recipient DIDs\n */\n async listGrants(\n key: string\n ): Promise<Result<string[], VaultError>> {\n return this.withTelemetry(\"listGrants\", key, async () => {\n if (!this._isUnlocked) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before listing grants\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n const listResult = await this.tc.kv.list({\n prefix: \"grants/\",\n removePrefix: true,\n });\n\n if (!listResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to list grants: ${listResult.error.message}`\n ),\n });\n }\n\n // Grant paths are: {recipientDID}/{key}\n // Filter for the specific key and extract DIDs\n const dids: string[] = [];\n for (const grantPath of listResult.data.keys) {\n // Path format: {recipientDID}/{key}\n // The key may contain slashes, so we need to match the suffix\n if (grantPath.endsWith(`/${key}`)) {\n const did = grantPath.slice(\n 0,\n grantPath.length - key.length - 1\n );\n if (did) {\n dids.push(did);\n }\n }\n }\n\n return ok(dids);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<string[], VaultError>>;\n }\n\n // =========================================================================\n // Phase 3: Key Rotation / Revocation\n // =========================================================================\n\n /**\n * Revoke a previously issued grant.\n *\n * This performs a full key rotation:\n * 1. Lists current grantees\n * 2. Removes the revoked recipient\n * 3. Re-encrypts the value with a new entry key\n * 4. Re-issues grants to remaining recipients\n *\n * @param key - The key to revoke access to\n * @param recipientDID - The recipient whose access to revoke\n */\n async revoke(\n key: string,\n recipientDID: string\n ): Promise<Result<void, VaultError>> {\n return this.withTelemetry(\"revoke\", key, async () => {\n if (!this._isUnlocked || !this.masterKey) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before revoking access\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Step 1: List all current grantees\n const granteesResult = await this.listGrants(key);\n if (!granteesResult.ok) {\n return granteesResult;\n }\n\n const remainingGrantees = granteesResult.data.filter(\n (did) => did !== recipientDID\n );\n\n // Step 2: Delete the grant for the revoked recipient\n const deleteGrantResult = await this.tc.kv.delete(\n `grants/${recipientDID}/${key}`\n );\n // Grant may already be deleted, that's fine\n\n // Step 3: Fetch and decrypt current value\n const getResult = await this.get(key);\n if (!getResult.ok) {\n return getResult as Result<never, VaultError>;\n }\n\n const currentEntry = getResult.data;\n\n // Step 4: Generate new entry key\n const newEntryKey = this.crypto.randomBytes(32);\n const newKeyId = hexEncode(this.crypto.sha256(newEntryKey)).slice(\n 0,\n 16\n );\n\n // Step 5: Re-serialize and re-encrypt value with new key\n let plaintext: Uint8Array;\n if (currentEntry.value instanceof Uint8Array) {\n plaintext = currentEntry.value;\n } else {\n plaintext = toBytes(JSON.stringify(currentEntry.value));\n }\n\n const encrypted = this.crypto.encrypt(newEntryKey, plaintext);\n\n // Step 6: Encrypt new entry key with master key\n const newKeyBlob = this.crypto.encrypt(this.masterKey, newEntryKey);\n\n // Step 7: Update metadata with new key ID\n const metadata: Record<string, string> = {\n ...currentEntry.metadata,\n [VaultHeaders.KEY_ID]: newKeyId,\n };\n\n // Step 8: Store updated key blob\n const keyPayload = JSON.stringify({\n key: base64Encode(newKeyBlob),\n metadata: JSON.stringify({\n keyId: newKeyId,\n ...metadata,\n }),\n });\n const keyPutResult = await this.tc.kv.put(\n `keys/${key}`,\n keyPayload\n );\n if (!keyPutResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to store rotated key blob: ${keyPutResult.error.message}`\n ),\n });\n }\n\n // Step 9: Store re-encrypted value\n const valuePayload = JSON.stringify({\n data: base64Encode(encrypted),\n metadata,\n });\n const valuePutResult = await this.tc.kv.put(\n `vault/${key}`,\n valuePayload\n );\n if (!valuePutResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to store re-encrypted value: ${valuePutResult.error.message}`\n ),\n });\n }\n\n // Step 10: Re-issue grants to remaining recipients\n for (const did of remainingGrantees) {\n const grantResult = await this.reencrypt(key, did);\n if (!grantResult.ok) {\n // Continue re-issuing to other recipients even if one fails\n // The failed grant can be re-issued manually\n }\n }\n\n return ok(undefined);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<void, VaultError>>;\n }\n\n // =========================================================================\n // Internal Helpers\n // =========================================================================\n\n /**\n * Parse a DID string to extract address and chainId.\n * Expected format: did:pkh:eip155:{chainId}:{address}\n *\n * @param did - The DID to parse\n * @returns Parsed address and chainId, or null if invalid\n */\n private parseDID(\n did: string\n ): { address: string; chainId: number } | null {\n // did:pkh:eip155:{chainId}:{address}\n const parts = did.split(\":\");\n if (\n parts.length !== 5 ||\n parts[0] !== \"did\" ||\n parts[1] !== \"pkh\" ||\n parts[2] !== \"eip155\"\n ) {\n return null;\n }\n\n const chainId = parseInt(parts[3], 10);\n const address = parts[4];\n if (isNaN(chainId) || !address) {\n return null;\n }\n\n return { address, chainId };\n }\n}\n","import type { VaultCrypto } from \"./DataVaultService\";\n\nexport interface WasmVaultFunctions {\n vault_encrypt(key: Uint8Array, plaintext: Uint8Array): Uint8Array;\n vault_decrypt(key: Uint8Array, blob: Uint8Array): Uint8Array;\n /** WASM order: (salt, signature, info) — NOT (signature, salt, info) */\n vault_derive_key(salt: Uint8Array, signature: Uint8Array, info: Uint8Array): Uint8Array;\n vault_x25519_from_seed(seed: Uint8Array): { publicKey: Uint8Array; privateKey: Uint8Array };\n vault_x25519_dh(privateKey: Uint8Array, publicKey: Uint8Array): Uint8Array;\n vault_random_bytes(length: number): Uint8Array;\n vault_sha256(data: Uint8Array): Uint8Array;\n}\n\nexport function createVaultCrypto(wasm: WasmVaultFunctions): VaultCrypto {\n return {\n encrypt: (key, plaintext) => wasm.vault_encrypt(key, plaintext),\n decrypt: (key, blob) => wasm.vault_decrypt(key, blob),\n deriveKey: (signature, salt, info) => wasm.vault_derive_key(salt, signature, info),\n x25519FromSeed: (seed) => wasm.vault_x25519_from_seed(seed),\n x25519Dh: (privateKey, publicKey) => wasm.vault_x25519_dh(privateKey, publicKey),\n randomBytes: (length) => wasm.vault_random_bytes(length),\n sha256: (data) => wasm.vault_sha256(data),\n };\n}\n"],"mappings":"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","names":["ok","serviceError","errorText"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/types.schema.ts","../src/context.ts","../src/errors.ts","../src/base/BaseService.ts","../src/kv/PrefixedKVService.ts","../src/kv/types.ts","../src/kv/KVService.ts","../src/sql/DatabaseHandle.ts","../src/sql/types.ts","../src/sql/SQLService.ts","../src/duckdb/DuckDbDatabaseHandle.ts","../src/duckdb/types.ts","../src/duckdb/DuckDbService.ts","../src/hooks/HooksService.ts","../src/quota/TinyCloudQuota.ts","../src/vault/types.ts","../src/vault/SignatureCache.ts","../src/vault/DataVaultService.ts","../src/vault/createVaultCrypto.ts","../src/secrets/SecretsService.ts"],"sourcesContent":["/**\n * TinyCloud SDK Services\n *\n * Platform-agnostic services with plugin architecture for TinyCloud.\n *\n * @packageDocumentation\n * @module @tinycloud/sdk-services\n *\n * @example\n * ```typescript\n * import {\n * ServiceContext,\n * BaseService,\n * Result,\n * ErrorCodes,\n * } from '@tinycloud/sdk-services';\n *\n * // Create a context\n * const context = new ServiceContext({\n * invoke: wasmInvoke,\n * hosts: ['https://node.tinycloud.xyz'],\n * });\n *\n * // Create and register a service\n * const kv = new KVService({ prefix: 'myapp' });\n * context.registerService('kv', kv);\n * kv.initialize(context);\n *\n * // Use the service\n * const result = await kv.get('key');\n * if (result.ok) {\n * console.log(result.data);\n * }\n * ```\n */\n\n// Core types\nexport type {\n Result,\n ServiceError,\n StorageQuotaInfo,\n ErrorCode,\n IServiceContext,\n IService,\n ServiceSession,\n RetryPolicy,\n InvokeFunction,\n InvokeAnyFunction,\n InvokeAnyEntry,\n InvocationFact,\n InvocationFacts,\n FetchFunction,\n FetchRequestInit,\n FetchResponse,\n ServiceHeaders,\n EventHandler,\n ServiceRequestEvent,\n ServiceResponseEvent,\n ServiceErrorEvent,\n ServiceRetryEvent,\n} from \"./types\";\n\nexport {\n ErrorCodes,\n defaultRetryPolicy,\n TelemetryEvents,\n ok,\n err,\n serviceError,\n} from \"./types\";\n\n// Zod schemas and validation\nexport {\n // Schemas\n ServiceErrorSchema,\n KVResponseHeadersSchema,\n KVListResponseSchema,\n ServiceRequestEventSchema,\n ServiceResponseEventSchema,\n ServiceErrorEventSchema,\n ServiceRetryEventSchema,\n RetryPolicySchema,\n ServiceSessionSchema,\n GenericResultSchema,\n GenericKVResponseSchema,\n KVListResultSchema,\n // Schema factories\n createResultSchema,\n createKVResponseSchema,\n // Validation functions\n validateServiceError,\n validateKVListResponse,\n validateKVResponseHeaders,\n validateServiceSession,\n validateRetryPolicy,\n validateServiceRequestEvent,\n validateServiceResponseEvent,\n} from \"./types.schema\";\n\nexport type {\n // Inferred types from schemas\n ValidationError,\n ServiceErrorType,\n KVResponseHeadersType,\n KVListResponseType,\n GenericKVResponseType,\n KVListResultType,\n ServiceRequestEventType,\n ServiceResponseEventType,\n ServiceErrorEventType,\n ServiceRetryEventType,\n RetryPolicyType,\n ServiceSessionType,\n} from \"./types.schema\";\n\n// Context\nexport { ServiceContext } from \"./context\";\nexport type { ServiceContextConfig } from \"./context\";\n\n// Errors\nexport {\n authRequiredError,\n authExpiredError,\n networkError,\n timeoutError,\n abortedError,\n notFoundError,\n permissionDeniedError,\n wrapError,\n errorResult,\n storageQuotaExceededError,\n storageLimitReachedError,\n parseAuthError,\n authUnauthorizedError,\n} from \"./errors\";\n\n// Base service\nexport { BaseService } from \"./base/index\";\nexport type {\n ServiceConstructor,\n ServiceRegistration,\n BaseServiceOptions,\n} from \"./base/index\";\n\n// KV service\nexport { KVService, PrefixedKVService, IKVService, KVAction } from \"./kv\";\nexport type {\n IPrefixedKVService,\n KVServiceConfig,\n KVGetOptions,\n KVPutOptions,\n KVListOptions,\n KVDeleteOptions,\n KVHeadOptions,\n KVResponse,\n KVListResponse,\n KVResponseHeaders,\n KVActionType,\n} from \"./kv\";\n\n// SQL service\nexport { SQLService, DatabaseHandle, SQLAction } from \"./sql\";\nexport type { ISQLService, IDatabaseHandle } from \"./sql\";\nexport type {\n SQLServiceConfig,\n QueryOptions,\n ExecuteOptions,\n BatchOptions,\n SqlValue,\n SqlStatement,\n QueryResponse,\n ExecuteResponse,\n BatchResponse,\n SQLActionType,\n} from \"./sql\";\n\n// DuckDB service\nexport { DuckDbService, DuckDbDatabaseHandle, DuckDbAction } from \"./duckdb\";\nexport type { IDuckDbService, IDuckDbDatabaseHandle } from \"./duckdb\";\nexport type {\n DuckDbServiceConfig,\n DuckDbQueryOptions,\n DuckDbExecuteOptions,\n DuckDbBatchOptions,\n DuckDbOptions,\n DuckDbValue,\n DuckDbStatement,\n DuckDbQueryResponse,\n DuckDbExecuteResponse,\n DuckDbBatchResponse,\n DuckDbActionType,\n SchemaInfo,\n TableInfo,\n ColumnInfo,\n ViewInfo,\n} from \"./duckdb\";\n\n// Hooks service\nexport { HooksService } from \"./hooks\";\nexport type {\n IHooksService,\n HookServiceName,\n HookSubscription,\n HookEvent,\n HookStreamEvent,\n HookWebhookScope,\n HookWebhookRegistration,\n HookWebhookRecord,\n HookWebhookListOptions,\n HookWebhookUnregisterOptions,\n SubscribeOptions,\n HooksServiceConfig,\n} from \"./hooks\";\n\n// Quota\nexport { TinyCloudQuota } from \"./quota\";\nexport type { QuotaConfig, QuotaStatus } from \"./quota\";\n\n// Vault service\nexport {\n DataVaultService,\n VaultHeaders,\n VaultPublicSpaceKVActions,\n createVaultCrypto,\n} from \"./vault\";\nexport type {\n IDataVaultService,\n VaultCrypto,\n WasmVaultFunctions,\n} from \"./vault\";\nexport type {\n DataVaultConfig,\n VaultPutOptions,\n VaultGetOptions,\n VaultListOptions,\n VaultGrantOptions,\n VaultEntry,\n VaultError,\n} from \"./vault\";\n\nexport { SecretsService } from \"./secrets\";\nexport type {\n ISecretsService,\n SecretPayload,\n SecretsError,\n} from \"./secrets\";\n","/**\n * SDK Services - Core Types\n *\n * These types define the service architecture for TinyCloud SDK.\n * Services use dependency injection via IServiceContext for platform independence.\n */\n\n// =============================================================================\n// Result Type Pattern\n// =============================================================================\n\n/**\n * Result type for service operations.\n * Services return Result instead of throwing, making error handling explicit.\n *\n * @template T - The success data type\n * @template E - The error type (defaults to ServiceError)\n *\n * @example\n * ```typescript\n * const result = await kv.get('key');\n * if (result.ok) {\n * console.log(result.data);\n * } else {\n * console.error(result.error.code);\n * }\n * ```\n */\nexport type Result<T, E = ServiceError> =\n | { ok: true; data: T }\n | { ok: false; error: E };\n\n/**\n * Service error with structured information.\n */\nexport interface ServiceError {\n /** Error code for programmatic handling (e.g., 'KV_NOT_FOUND', 'AUTH_EXPIRED') */\n code: string;\n /** Human-readable error message */\n message: string;\n /** Service that produced the error (e.g., 'kv', 'sql') */\n service: string;\n /** Original error if this wraps another error */\n cause?: Error;\n /** Additional metadata about the error */\n meta?: Record<string, unknown>;\n}\n\n/**\n * Storage quota information returned with quota-related errors.\n */\nexport interface StorageQuotaInfo {\n usedBytes: number;\n limitBytes: number;\n service: string;\n}\n\n/**\n * Standard error codes used across services.\n */\nexport const ErrorCodes = {\n // Common errors\n NOT_FOUND: \"NOT_FOUND\",\n AUTH_EXPIRED: \"AUTH_EXPIRED\",\n AUTH_REQUIRED: \"AUTH_REQUIRED\",\n AUTH_UNAUTHORIZED: \"AUTH_UNAUTHORIZED\",\n NETWORK_ERROR: \"NETWORK_ERROR\",\n TIMEOUT: \"TIMEOUT\",\n ABORTED: \"ABORTED\",\n INVALID_INPUT: \"INVALID_INPUT\",\n PERMISSION_DENIED: \"PERMISSION_DENIED\",\n\n // KV-specific errors\n KV_NOT_FOUND: \"KV_NOT_FOUND\",\n KV_WRITE_FAILED: \"KV_WRITE_FAILED\",\n\n // SQL-specific errors\n SQL_ERROR: \"SQL_ERROR\",\n SQL_PERMISSION_DENIED: \"SQL_PERMISSION_DENIED\",\n SQL_DATABASE_NOT_FOUND: \"SQL_DATABASE_NOT_FOUND\",\n SQL_RESPONSE_TOO_LARGE: \"SQL_RESPONSE_TOO_LARGE\",\n SQL_QUOTA_EXCEEDED: \"SQL_QUOTA_EXCEEDED\",\n SQL_INVALID_STATEMENT: \"SQL_INVALID_STATEMENT\",\n SQL_SCHEMA_ERROR: \"SQL_SCHEMA_ERROR\",\n SQL_READONLY_VIOLATION: \"SQL_READONLY_VIOLATION\",\n\n // Storage quota errors\n STORAGE_QUOTA_EXCEEDED: \"STORAGE_QUOTA_EXCEEDED\",\n STORAGE_LIMIT_REACHED: \"STORAGE_LIMIT_REACHED\",\n\n // DuckDB-specific errors\n DUCKDB_ERROR: \"DUCKDB_ERROR\",\n DUCKDB_PERMISSION_DENIED: \"DUCKDB_PERMISSION_DENIED\",\n DUCKDB_DATABASE_NOT_FOUND: \"DUCKDB_DATABASE_NOT_FOUND\",\n DUCKDB_RESPONSE_TOO_LARGE: \"DUCKDB_RESPONSE_TOO_LARGE\",\n DUCKDB_QUOTA_EXCEEDED: \"DUCKDB_QUOTA_EXCEEDED\",\n DUCKDB_INVALID_STATEMENT: \"DUCKDB_INVALID_STATEMENT\",\n DUCKDB_SCHEMA_ERROR: \"DUCKDB_SCHEMA_ERROR\",\n DUCKDB_READONLY_VIOLATION: \"DUCKDB_READONLY_VIOLATION\",\n} as const;\n\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n\n// =============================================================================\n// Service Session\n// =============================================================================\n\n/**\n * Session data required for authenticated service operations.\n * Both TinyCloudSession and web-sdk Session can be cast to this interface.\n */\nexport interface ServiceSession {\n /** The delegation header containing the UCAN */\n delegationHeader: { Authorization: string };\n /** The delegation CID */\n delegationCid: string;\n /** The space ID for this session */\n spaceId: string;\n /** The verification method DID */\n verificationMethod: string;\n /** The session key JWK (required for invoke) */\n jwk: object;\n}\n\n// =============================================================================\n// Platform Dependencies (Injected)\n// =============================================================================\n\n/**\n * Headers type - compatible with both browser and Node.js.\n */\nexport type ServiceHeaders = Record<string, string> | [string, string][];\n\n/**\n * A single fact object to include in the UCAN invocation.\n * Facts are key-value objects that the server reads from the UCAN facts field.\n */\nexport interface InvocationFact {\n [key: string]: unknown;\n}\n\n/**\n * Facts to include in the UCAN invocation.\n * This is an array of fact objects per the UCAN spec.\n * Used to pass additional parameters that the server reads from the UCAN facts field.\n */\nexport type InvocationFacts = InvocationFact[];\n\n/**\n * Invoke function signature - platform-specific implementation injected via DI.\n * Both node-sdk-wasm and web-sdk-wasm export this with identical signature.\n *\n * @param session - The service session with delegation data\n * @param service - Service name (e.g., \"kv\")\n * @param path - Resource path or key\n * @param action - Action to perform (e.g., \"tinycloud.kv/get\")\n * @param facts - Optional facts to include in the UCAN (e.g., for capabilities/read params)\n * @returns Headers to include in the request\n */\nexport type InvokeFunction = (\n session: ServiceSession,\n service: string,\n path: string,\n action: string,\n facts?: InvocationFacts\n) => ServiceHeaders;\n\n/**\n * Multi-resource invocation entry.\n */\nexport interface InvokeAnyEntry {\n spaceId: string;\n service: string;\n path: string;\n action: string;\n}\n\n/**\n * Invoke function for minting a single authorization header that covers\n * multiple capabilities across one effective invoker.\n */\nexport type InvokeAnyFunction = (\n session: ServiceSession,\n entries: InvokeAnyEntry[],\n facts?: InvocationFacts\n) => ServiceHeaders;\n\n/**\n * Fetch request options - compatible with standard fetch API.\n */\nexport interface FetchRequestInit {\n method?: string;\n headers?: ServiceHeaders;\n body?: Blob | string;\n signal?: AbortSignal;\n}\n\n/**\n * Fetch response interface - compatible with standard Response.\n */\nexport interface FetchResponse {\n ok: boolean;\n status: number;\n statusText: string;\n body?: unknown;\n headers: {\n get(name: string): string | null;\n };\n json(): Promise<unknown>;\n text(): Promise<string>;\n arrayBuffer(): Promise<ArrayBuffer>;\n blob(): Promise<Blob>;\n}\n\n/**\n * Fetch function signature - allows for custom fetch implementations.\n * Compatible with both browser fetch and Node.js fetch.\n */\nexport type FetchFunction = (\n url: string,\n init?: FetchRequestInit\n) => Promise<FetchResponse>;\n\n// =============================================================================\n// Retry Policy\n// =============================================================================\n\n/**\n * Configuration for automatic retry of failed requests.\n */\nexport interface RetryPolicy {\n /** Maximum number of attempts (including initial) */\n maxAttempts: number;\n /** Backoff strategy between retries */\n backoff: \"none\" | \"linear\" | \"exponential\";\n /** Base delay in milliseconds for backoff calculation */\n baseDelayMs: number;\n /** Maximum delay in milliseconds between retries */\n maxDelayMs: number;\n /** Error codes that should trigger a retry */\n retryableErrors: string[];\n}\n\n/**\n * Default retry policy.\n */\nexport const defaultRetryPolicy: RetryPolicy = {\n maxAttempts: 3,\n backoff: \"exponential\",\n baseDelayMs: 1000,\n maxDelayMs: 10000,\n retryableErrors: [ErrorCodes.NETWORK_ERROR, ErrorCodes.TIMEOUT],\n};\n\n// =============================================================================\n// Service Context\n// =============================================================================\n\n/**\n * Event handler function type.\n */\nexport type EventHandler = (data: unknown) => void;\n\n/**\n * Service interface - base contract for all services.\n */\nexport interface IService {\n /** Initialize service with context */\n initialize(context: IServiceContext): void;\n\n /** Called when session changes (sign-in, sign-out, refresh) */\n onSessionChange(session: ServiceSession | null): void;\n\n /** Called when SDK signs out - should abort pending operations */\n onSignOut(): void;\n\n /** Service-specific configuration */\n readonly config: Record<string, unknown>;\n}\n\n/**\n * Context provided to services for accessing platform dependencies.\n * The SDK creates this context and passes it to services during initialization.\n */\nexport interface IServiceContext {\n // Session management\n /** Current active session, or null if not authenticated */\n readonly session: ServiceSession | null;\n /** Whether there is an active authenticated session */\n readonly isAuthenticated: boolean;\n\n // Platform dependencies (injected by SDK)\n /** Platform-specific invoke function from WASM binding */\n readonly invoke: InvokeFunction;\n /** Optional multi-resource invoke function */\n readonly invokeAny?: InvokeAnyFunction;\n /** Fetch function (defaults to globalThis.fetch) */\n readonly fetch: FetchFunction;\n /** Available TinyCloud host URLs */\n readonly hosts: string[];\n\n // Cross-service access\n /** Get another registered service by name */\n getService<T extends IService>(name: string): T | undefined;\n\n // Telemetry/Events\n /** Emit a telemetry event */\n emit(event: string, data: unknown): void;\n /** Subscribe to events */\n on(event: string, handler: EventHandler): () => void;\n\n // Lifecycle\n /** Abort signal that fires when SDK signs out */\n readonly abortSignal: AbortSignal;\n\n // Retry policy\n /** Retry policy for failed requests */\n readonly retryPolicy: RetryPolicy;\n}\n\n// =============================================================================\n// Telemetry Events\n// =============================================================================\n\n/**\n * Event emitted before a service request.\n */\nexport interface ServiceRequestEvent {\n service: string;\n action: string;\n key?: string;\n timestamp: number;\n}\n\n/**\n * Event emitted after a service response.\n */\nexport interface ServiceResponseEvent {\n service: string;\n action: string;\n ok: boolean;\n duration: number;\n status?: number;\n}\n\n/**\n * Event emitted on service error.\n */\nexport interface ServiceErrorEvent {\n service: string;\n error: ServiceError;\n}\n\n/**\n * Event emitted on retry attempt.\n */\nexport interface ServiceRetryEvent {\n service: string;\n attempt: number;\n maxAttempts: number;\n error: ServiceError;\n}\n\n/**\n * Telemetry event names.\n */\nexport const TelemetryEvents = {\n SERVICE_REQUEST: \"service.request\",\n SERVICE_RESPONSE: \"service.response\",\n SERVICE_ERROR: \"service.error\",\n SERVICE_RETRY: \"service.retry\",\n SESSION_CHANGED: \"session.changed\",\n SESSION_EXPIRED: \"session.expired\",\n} as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Create a success result.\n */\nexport function ok<T>(data: T): Result<T> {\n return { ok: true, data };\n}\n\n/**\n * Create an error result.\n */\nexport function err<E = ServiceError>(error: E): Result<never, E> {\n return { ok: false, error };\n}\n\n/**\n * Create a ServiceError.\n */\nexport function serviceError(\n code: string,\n message: string,\n service: string,\n options?: { cause?: Error; meta?: Record<string, unknown> }\n): ServiceError {\n return {\n code,\n message,\n service,\n cause: options?.cause,\n meta: options?.meta,\n };\n}\n","/**\n * Zod schemas for SDK Services API response types.\n *\n * This is the source of truth for service response types. TypeScript types\n * are derived from these schemas using z.infer<>.\n *\n * @packageDocumentation\n */\n\nimport { z } from \"zod\";\n\n// =============================================================================\n// Validation Error Type\n// =============================================================================\n\n/**\n * Validation error type for schema validation failures.\n */\nexport interface ValidationError {\n code: \"VALIDATION_ERROR\";\n message: string;\n service: string;\n meta?: {\n issues: z.ZodIssue[];\n path?: string;\n };\n}\n\n// =============================================================================\n// Service Error Schema\n// =============================================================================\n\n/**\n * Schema for service error with structured information.\n */\nexport const ServiceErrorSchema = z.object({\n /** Error code for programmatic handling (e.g., 'KV_NOT_FOUND', 'AUTH_EXPIRED') */\n code: z.string(),\n /** Human-readable error message */\n message: z.string(),\n /** Service that produced the error (e.g., 'kv', 'sql') */\n service: z.string(),\n /** Original error if this wraps another error - not validated since Error is a class */\n cause: z.unknown().optional(),\n /** Additional metadata about the error - passthrough allows any object properties */\n meta: z.object({}).passthrough().optional(),\n});\n\nexport type ServiceErrorType = z.infer<typeof ServiceErrorSchema>;\n\n// =============================================================================\n// Result Schema Factory\n// =============================================================================\n\n/**\n * Creates a Result schema for a given data type.\n * Result is a discriminated union: { ok: true, data: T } | { ok: false, error: E }\n *\n * @param dataSchema - Zod schema for the success data type\n * @param errorSchema - Zod schema for the error type (defaults to ServiceErrorSchema)\n * @returns A Zod schema for Result<T, E>\n *\n * @example\n * ```typescript\n * const KVGetResultSchema = createResultSchema(z.string());\n * type KVGetResult = z.infer<typeof KVGetResultSchema>;\n * ```\n */\nexport function createResultSchema<T extends z.ZodTypeAny, E extends z.ZodTypeAny>(\n dataSchema: T,\n errorSchema: E = ServiceErrorSchema as unknown as E\n) {\n return z.discriminatedUnion(\"ok\", [\n z.object({\n ok: z.literal(true),\n data: dataSchema,\n }),\n z.object({\n ok: z.literal(false),\n error: errorSchema,\n }),\n ]);\n}\n\n/**\n * Pre-built Result schema with unknown data and ServiceError.\n * Useful for generic validation before type narrowing.\n */\nexport const GenericResultSchema = createResultSchema(z.unknown(), ServiceErrorSchema);\n\n// =============================================================================\n// KV Response Schemas\n// =============================================================================\n\n/**\n * Schema for KV response headers metadata.\n * Note: The `get` method is a function and cannot be validated with Zod.\n * This schema validates the data properties only.\n */\nexport const KVResponseHeadersSchema = z.object({\n /** ETag for conditional requests */\n etag: z.string().optional(),\n /** Content type of the stored value */\n contentType: z.string().optional(),\n /** Last modification timestamp */\n lastModified: z.string().optional(),\n /** Content length in bytes */\n contentLength: z.number().optional(),\n});\n\nexport type KVResponseHeadersType = z.infer<typeof KVResponseHeadersSchema>;\n\n/**\n * Creates a KVResponse schema for a given data type.\n *\n * @param dataSchema - Zod schema for the data payload type\n * @returns A Zod schema for KVResponse<T>\n *\n * @example\n * ```typescript\n * const UserResponseSchema = createKVResponseSchema(UserSchema);\n * type UserResponse = z.infer<typeof UserResponseSchema>;\n * ```\n */\nexport function createKVResponseSchema<T extends z.ZodTypeAny>(dataSchema: T) {\n return z.object({\n /** The data payload */\n data: dataSchema,\n /** Response headers with metadata */\n headers: KVResponseHeadersSchema,\n });\n}\n\n/**\n * Generic KVResponse schema with unknown data.\n * Useful for generic validation before type narrowing.\n */\nexport const GenericKVResponseSchema = createKVResponseSchema(z.unknown());\n\nexport type GenericKVResponseType = z.infer<typeof GenericKVResponseSchema>;\n\n/**\n * Schema for KV list response.\n */\nexport const KVListResponseSchema = z.object({\n /** Array of keys matching the list criteria */\n keys: z.array(z.string()),\n});\n\nexport type KVListResponseType = z.infer<typeof KVListResponseSchema>;\n\n/**\n * Result schema for KV list operations.\n */\nexport const KVListResultSchema = createResultSchema(KVListResponseSchema);\n\nexport type KVListResultType = z.infer<typeof KVListResultSchema>;\n\n// =============================================================================\n// Telemetry Event Schemas\n// =============================================================================\n\n/**\n * Schema for service request event.\n */\nexport const ServiceRequestEventSchema = z.object({\n service: z.string(),\n action: z.string(),\n key: z.string().optional(),\n timestamp: z.number(),\n});\n\nexport type ServiceRequestEventType = z.infer<typeof ServiceRequestEventSchema>;\n\n/**\n * Schema for service response event.\n */\nexport const ServiceResponseEventSchema = z.object({\n service: z.string(),\n action: z.string(),\n ok: z.boolean(),\n duration: z.number(),\n status: z.number().optional(),\n});\n\nexport type ServiceResponseEventType = z.infer<typeof ServiceResponseEventSchema>;\n\n/**\n * Schema for service error event.\n */\nexport const ServiceErrorEventSchema = z.object({\n service: z.string(),\n error: ServiceErrorSchema,\n});\n\nexport type ServiceErrorEventType = z.infer<typeof ServiceErrorEventSchema>;\n\n/**\n * Schema for service retry event.\n */\nexport const ServiceRetryEventSchema = z.object({\n service: z.string(),\n attempt: z.number().int().positive(),\n maxAttempts: z.number().int().positive(),\n error: ServiceErrorSchema,\n});\n\nexport type ServiceRetryEventType = z.infer<typeof ServiceRetryEventSchema>;\n\n// =============================================================================\n// Retry Policy Schema\n// =============================================================================\n\n/**\n * Schema for retry policy configuration.\n */\nexport const RetryPolicySchema = z.object({\n /** Maximum number of attempts (including initial) */\n maxAttempts: z.number().int().positive(),\n /** Backoff strategy between retries */\n backoff: z.enum([\"none\", \"linear\", \"exponential\"]),\n /** Base delay in milliseconds for backoff calculation */\n baseDelayMs: z.number().nonnegative(),\n /** Maximum delay in milliseconds between retries */\n maxDelayMs: z.number().nonnegative(),\n /** Error codes that should trigger a retry */\n retryableErrors: z.array(z.string()),\n});\n\nexport type RetryPolicyType = z.infer<typeof RetryPolicySchema>;\n\n// =============================================================================\n// Service Session Schema\n// =============================================================================\n\n/**\n * Schema for service session data required for authenticated operations.\n */\nexport const ServiceSessionSchema = z.object({\n /** The delegation header containing the UCAN */\n delegationHeader: z.object({\n Authorization: z.string(),\n }),\n /** The delegation CID */\n delegationCid: z.string(),\n /** The space ID for this session */\n spaceId: z.string(),\n /** The verification method DID */\n verificationMethod: z.string(),\n /** The session key JWK (required for invoke) */\n jwk: z.object({}).passthrough(),\n});\n\nexport type ServiceSessionType = z.infer<typeof ServiceSessionSchema>;\n\n// =============================================================================\n// Validation Helpers\n// =============================================================================\n\n/**\n * Validate service error against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateServiceError(\n data: unknown\n): { ok: true; data: ServiceErrorType } | { ok: false; error: ValidationError } {\n const result = ServiceErrorSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"validation\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate KV list response against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateKVListResponse(\n data: unknown\n): { ok: true; data: KVListResponseType } | { ok: false; error: ValidationError } {\n const result = KVListResponseSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"kv\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate KV response headers against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateKVResponseHeaders(\n data: unknown\n): { ok: true; data: KVResponseHeadersType } | { ok: false; error: ValidationError } {\n const result = KVResponseHeadersSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"kv\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate service session against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateServiceSession(\n data: unknown\n): { ok: true; data: ServiceSessionType } | { ok: false; error: ValidationError } {\n const result = ServiceSessionSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"session\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate retry policy against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateRetryPolicy(\n data: unknown\n): { ok: true; data: RetryPolicyType } | { ok: false; error: ValidationError } {\n const result = RetryPolicySchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"config\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate service request event against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateServiceRequestEvent(\n data: unknown\n): { ok: true; data: ServiceRequestEventType } | { ok: false; error: ValidationError } {\n const result = ServiceRequestEventSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"telemetry\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n\n/**\n * Validate service response event against the schema.\n *\n * @param data - Unknown data to validate\n * @returns Result with validated data or validation error\n */\nexport function validateServiceResponseEvent(\n data: unknown\n): { ok: true; data: ServiceResponseEventType } | { ok: false; error: ValidationError } {\n const result = ServiceResponseEventSchema.safeParse(data);\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: \"VALIDATION_ERROR\",\n message: result.error.message,\n service: \"telemetry\",\n meta: { issues: result.error.issues },\n },\n };\n }\n return { ok: true, data: result.data };\n}\n","/**\n * ServiceContext implementation for TinyCloud SDK Services\n * @module @tinycloud/sdk-services\n */\n\nimport {\n IServiceContext,\n IService,\n ServiceSession,\n RetryPolicy,\n InvokeFunction,\n InvokeAnyFunction,\n FetchFunction,\n defaultRetryPolicy,\n} from \"./types\";\n\n/**\n * Event handler type for telemetry events.\n */\ntype EventHandler = (data: unknown) => void;\n\n/**\n * Configuration options for ServiceContext.\n */\nexport interface ServiceContextConfig {\n /** Function to invoke WASM operations */\n invoke: InvokeFunction;\n /** Optional function to mint a single authorization header for multiple capabilities */\n invokeAny?: InvokeAnyFunction;\n /** Function to make HTTP requests (defaults to globalThis.fetch) */\n fetch?: FetchFunction;\n /** List of TinyCloud host URLs */\n hosts: string[];\n /** Initial session (optional) */\n session?: ServiceSession | null;\n /** Retry policy configuration */\n retryPolicy?: Partial<RetryPolicy>;\n}\n\n/**\n * ServiceContext provides platform dependencies and cross-service access to services.\n * This is the primary interface services use to interact with the SDK runtime.\n *\n * @example\n * ```typescript\n * const context = new ServiceContext({\n * invoke: wasmInvoke,\n * hosts: ['https://node.tinycloud.xyz'],\n * retryPolicy: { maxAttempts: 5 },\n * });\n *\n * // Register a service\n * const kvService = new KVService({});\n * context.registerService('kv', kvService);\n * kvService.initialize(context);\n *\n * // Update session when user signs in\n * context.setSession(userSession);\n * ```\n */\nexport class ServiceContext implements IServiceContext {\n private _session: ServiceSession | null = null;\n private _services: Map<string, IService> = new Map();\n private _eventHandlers: Map<string, Set<EventHandler>> = new Map();\n private _abortController: AbortController = new AbortController();\n private readonly _invoke: InvokeFunction;\n private readonly _invokeAny?: InvokeAnyFunction;\n private readonly _fetch: FetchFunction;\n private readonly _hosts: string[];\n private readonly _retryPolicy: RetryPolicy;\n\n constructor(config: ServiceContextConfig) {\n this._invoke = config.invoke;\n this._invokeAny = config.invokeAny;\n this._fetch = config.fetch ?? globalThis.fetch.bind(globalThis);\n this._hosts = config.hosts;\n this._session = config.session ?? null;\n this._retryPolicy = {\n ...defaultRetryPolicy,\n ...config.retryPolicy,\n };\n }\n\n // ============================================================\n // Session Management\n // ============================================================\n\n /**\n * Get the current session.\n */\n get session(): ServiceSession | null {\n return this._session;\n }\n\n /**\n * Check if the context has an authenticated session.\n */\n get isAuthenticated(): boolean {\n return this._session !== null;\n }\n\n /**\n * Update the session and notify all registered services.\n *\n * @param session - New session or null to clear\n */\n setSession(session: ServiceSession | null): void {\n this._session = session;\n this.emit('session.changed', { authenticated: session !== null });\n\n // Notify all services of session change\n for (const service of this._services.values()) {\n service.onSessionChange(session);\n }\n }\n\n // ============================================================\n // Platform Dependencies\n // ============================================================\n\n /**\n * Get the invoke function for WASM operations.\n */\n get invoke(): InvokeFunction {\n return this._invoke;\n }\n\n /**\n * Get the multi-resource invoke function when available.\n */\n get invokeAny(): InvokeAnyFunction | undefined {\n return this._invokeAny;\n }\n\n /**\n * Get the fetch function for HTTP requests.\n */\n get fetch(): FetchFunction {\n return this._fetch;\n }\n\n /**\n * Get the list of TinyCloud host URLs.\n */\n get hosts(): string[] {\n return this._hosts;\n }\n\n // ============================================================\n // Service Registry\n // ============================================================\n\n /**\n * Register a service with the context.\n *\n * @param name - Service name (e.g., 'kv')\n * @param service - Service instance\n */\n registerService(name: string, service: IService): void {\n this._services.set(name, service);\n }\n\n /**\n * Unregister a service from the context.\n *\n * @param name - Service name to remove\n */\n unregisterService(name: string): void {\n this._services.delete(name);\n }\n\n /**\n * Get a registered service by name.\n *\n * @param name - Service name\n * @returns The service instance or undefined if not registered\n */\n getService<T extends IService>(name: string): T | undefined {\n return this._services.get(name) as T | undefined;\n }\n\n // ============================================================\n // Event System (Telemetry)\n // ============================================================\n\n /**\n * Emit a telemetry event.\n *\n * @param event - Event name\n * @param data - Event data\n */\n emit(event: string, data: unknown): void {\n const handlers = this._eventHandlers.get(event);\n if (handlers) {\n for (const handler of handlers) {\n try {\n handler(data);\n } catch (error) {\n // Don't let event handler errors break the flow\n console.error(`Error in event handler for \"${event}\":`, error);\n }\n }\n }\n }\n\n /**\n * Subscribe to telemetry events.\n *\n * @param event - Event name to subscribe to\n * @param handler - Handler function\n * @returns Unsubscribe function\n */\n on(event: string, handler: EventHandler): () => void {\n if (!this._eventHandlers.has(event)) {\n this._eventHandlers.set(event, new Set());\n }\n this._eventHandlers.get(event)!.add(handler);\n\n // Return unsubscribe function\n return () => {\n const handlers = this._eventHandlers.get(event);\n if (handlers) {\n handlers.delete(handler);\n if (handlers.size === 0) {\n this._eventHandlers.delete(event);\n }\n }\n };\n }\n\n /**\n * Remove all event handlers for an event.\n *\n * @param event - Event name (if omitted, clears all events)\n */\n clearEventHandlers(event?: string): void {\n if (event) {\n this._eventHandlers.delete(event);\n } else {\n this._eventHandlers.clear();\n }\n }\n\n // ============================================================\n // Lifecycle\n // ============================================================\n\n /**\n * Get the abort signal for cancelling operations.\n */\n get abortSignal(): AbortSignal {\n return this._abortController.signal;\n }\n\n /**\n * Abort all pending operations and notify services.\n * Creates a new AbortController for future operations.\n */\n abort(): void {\n this._abortController.abort();\n this._abortController = new AbortController();\n\n // Notify all services\n for (const service of this._services.values()) {\n service.onSignOut();\n }\n }\n\n /**\n * Sign out - abort operations and clear session.\n */\n signOut(): void {\n this.abort();\n this.setSession(null);\n this.emit('session.expired', {});\n }\n\n // ============================================================\n // Retry Policy\n // ============================================================\n\n /**\n * Get the retry policy configuration.\n */\n get retryPolicy(): RetryPolicy {\n return this._retryPolicy;\n }\n}\n","/**\n * SDK Services - Error Utilities\n *\n * Utilities for creating and handling service errors.\n */\n\nimport { ServiceError, ErrorCodes, err, serviceError } from \"./types\";\n\n/**\n * Create a service error for authentication required.\n */\nexport function authRequiredError(service: string): ServiceError {\n return {\n code: ErrorCodes.AUTH_REQUIRED,\n message: \"Authentication required. Please sign in first.\",\n service,\n };\n}\n\n/**\n * Create a service error for expired authentication.\n */\nexport function authExpiredError(service: string): ServiceError {\n return {\n code: ErrorCodes.AUTH_EXPIRED,\n message: \"Session has expired. Please sign in again.\",\n service,\n };\n}\n\n/**\n * Create a service error for network issues.\n */\nexport function networkError(\n service: string,\n message: string,\n cause?: Error\n): ServiceError {\n return {\n code: ErrorCodes.NETWORK_ERROR,\n message,\n service,\n cause,\n };\n}\n\n/**\n * Create a service error for timeouts.\n */\nexport function timeoutError(service: string): ServiceError {\n return {\n code: ErrorCodes.TIMEOUT,\n message: \"Request timed out.\",\n service,\n };\n}\n\n/**\n * Create a service error for aborted requests.\n */\nexport function abortedError(service: string): ServiceError {\n return {\n code: ErrorCodes.ABORTED,\n message: \"Request was aborted.\",\n service,\n };\n}\n\n/**\n * Create a service error for not found resources.\n */\nexport function notFoundError(\n service: string,\n resource: string\n): ServiceError {\n return {\n code: ErrorCodes.NOT_FOUND,\n message: `Resource not found: ${resource}`,\n service,\n };\n}\n\n/**\n * Create a service error for permission denied.\n */\nexport function permissionDeniedError(\n service: string,\n action: string\n): ServiceError {\n return {\n code: ErrorCodes.PERMISSION_DENIED,\n message: `Permission denied for action: ${action}`,\n service,\n };\n}\n\n/**\n * Parse the server's \"Unauthorized Action: {resource} / {ability}\" pattern.\n */\nexport function parseAuthError(responseText: string): { resource?: string; action?: string } {\n const match = responseText.match(/^Unauthorized Action:\\s*(.+?)\\s*\\/\\s*(tinycloud\\.\\S+)$/m);\n if (match) {\n return { resource: match[1].trim(), action: match[2].trim() };\n }\n return {};\n}\n\n/**\n * Create a service error for unauthorized action (missing capability).\n */\nexport function authUnauthorizedError(\n service: string,\n message: string,\n meta?: Record<string, unknown>\n): ServiceError {\n return serviceError(ErrorCodes.AUTH_UNAUTHORIZED, message, service, { meta });\n}\n\n/**\n * Create a service error for storage quota exceeded (402 Payment Required).\n */\nexport function storageQuotaExceededError(\n service: string,\n message: string,\n meta?: Record<string, unknown>\n): ServiceError {\n return {\n code: ErrorCodes.STORAGE_QUOTA_EXCEEDED,\n message,\n service,\n meta,\n };\n}\n\n/**\n * Create a service error for storage limit reached (413 Payload Too Large).\n */\nexport function storageLimitReachedError(\n service: string,\n message: string,\n meta?: Record<string, unknown>\n): ServiceError {\n return {\n code: ErrorCodes.STORAGE_LIMIT_REACHED,\n message,\n service,\n meta,\n };\n}\n\n/**\n * Wrap an unknown error in a ServiceError.\n */\nexport function wrapError(\n service: string,\n error: unknown,\n defaultCode: string = ErrorCodes.NETWORK_ERROR\n): ServiceError {\n if (error instanceof Error) {\n // Check for abort errors\n if (error.name === \"AbortError\") {\n return abortedError(service);\n }\n\n // Check for timeout errors (varies by platform)\n if (\n error.name === \"TimeoutError\" ||\n error.message.toLowerCase().includes(\"timeout\")\n ) {\n return timeoutError(service);\n }\n\n return {\n code: defaultCode,\n message: error.message,\n service,\n cause: error,\n };\n }\n\n return {\n code: defaultCode,\n message: String(error),\n service,\n };\n}\n\n/**\n * Create an error Result from a ServiceError.\n */\nexport function errorResult(error: ServiceError) {\n return err(error);\n}\n","/**\n * BaseService - Abstract base class for all TinyCloud services.\n *\n * Provides common functionality:\n * - Context management\n * - Session lifecycle hooks\n * - Abort signal handling\n * - Telemetry emission\n */\n\nimport {\n IService,\n IServiceContext,\n ServiceSession,\n ServiceError,\n TelemetryEvents,\n err,\n Result,\n} from \"../types\";\nimport { authRequiredError, wrapError } from \"../errors\";\n\n/**\n * Abstract base class for TinyCloud services.\n *\n * Services extend this class to get common functionality like\n * context management, session lifecycle, and abort handling.\n *\n * @example\n * ```typescript\n * class MyService extends BaseService implements IMyService {\n * static readonly serviceName = 'myservice';\n *\n * constructor(config: MyServiceConfig = {}) {\n * super();\n * this._config = config;\n * }\n *\n * async doSomething(): Promise<Result<Data>> {\n * if (!this.requireAuth()) {\n * return err(authRequiredError('myservice'));\n * }\n * // ... implementation\n * }\n * }\n * ```\n */\nexport abstract class BaseService implements IService {\n /**\n * Service identifier used for registration.\n * Must be overridden by subclasses.\n */\n static readonly serviceName: string;\n\n /**\n * Service context providing access to platform dependencies.\n * Set during initialize().\n */\n protected context!: IServiceContext;\n\n /**\n * Abort controller for this service's operations.\n * Reset on sign-out.\n */\n protected abortController: AbortController = new AbortController();\n\n /**\n * Service-specific configuration.\n */\n protected _config: Record<string, unknown> = {};\n\n /**\n * Get the service configuration.\n */\n get config(): Record<string, unknown> {\n return this._config;\n }\n\n /**\n * Initialize the service with context.\n * Called by the SDK after instantiation.\n *\n * @param context - The service context\n */\n initialize(context: IServiceContext): void {\n this.context = context;\n }\n\n /**\n * Called when session changes (sign-in, sign-out, refresh).\n * Override in subclasses to handle session changes.\n *\n * @param session - The new session, or null if signed out\n */\n onSessionChange(session: ServiceSession | null): void {\n // Override in subclass if needed\n }\n\n /**\n * Called when SDK signs out.\n * Aborts all pending operations.\n */\n onSignOut(): void {\n this.abortController.abort();\n this.abortController = new AbortController();\n }\n\n /**\n * Get the abort signal for this service.\n * Combines the service-level abort with context-level abort.\n */\n protected get abortSignal(): AbortSignal {\n return this.abortController.signal;\n }\n\n /**\n * Check if the service is authenticated.\n */\n protected get isAuthenticated(): boolean {\n return this.context?.isAuthenticated ?? false;\n }\n\n /**\n * Get the current session.\n * Throws if not authenticated.\n */\n protected get session(): ServiceSession {\n if (!this.context?.session) {\n throw new Error(\"Not authenticated\");\n }\n return this.context.session;\n }\n\n /**\n * Check authentication and return error result if not authenticated.\n * Use this at the start of methods that require authentication.\n *\n * @returns true if authenticated, false otherwise\n */\n protected requireAuth(): boolean {\n return this.isAuthenticated;\n }\n\n /**\n * Emit a telemetry event.\n *\n * @param event - Event name\n * @param data - Event data\n */\n protected emit(event: string, data: unknown): void {\n this.context?.emit(event, data);\n }\n\n /**\n * Emit a service request event.\n *\n * @param action - The action being performed\n * @param key - Optional key/path being accessed\n */\n protected emitRequest(action: string, key?: string): void {\n this.emit(TelemetryEvents.SERVICE_REQUEST, {\n service: this.getServiceName(),\n action,\n key,\n timestamp: Date.now(),\n });\n }\n\n /**\n * Emit a service response event.\n *\n * @param action - The action that was performed\n * @param ok - Whether the request was successful\n * @param startTime - Start time for duration calculation\n * @param status - Optional HTTP status code\n */\n protected emitResponse(\n action: string,\n ok: boolean,\n startTime: number,\n status?: number\n ): void {\n this.emit(TelemetryEvents.SERVICE_RESPONSE, {\n service: this.getServiceName(),\n action,\n ok,\n duration: Date.now() - startTime,\n status,\n });\n }\n\n /**\n * Emit a service error event.\n *\n * @param error - The service error\n */\n protected emitError(error: ServiceError): void {\n this.emit(TelemetryEvents.SERVICE_ERROR, {\n service: this.getServiceName(),\n error,\n });\n }\n\n /**\n * Get the service name from the static property.\n * Subclasses must define static serviceName.\n */\n protected getServiceName(): string {\n return (this.constructor as typeof BaseService).serviceName;\n }\n\n /**\n * Create a combined abort signal from multiple sources.\n *\n * @param signals - Additional abort signals to combine\n * @returns A combined abort signal\n */\n protected combineSignals(...signals: (AbortSignal | undefined)[]): AbortSignal {\n const controller = new AbortController();\n const allSignals = [this.abortSignal, ...signals.filter(Boolean)] as AbortSignal[];\n\n for (const signal of allSignals) {\n if (signal.aborted) {\n controller.abort(signal.reason);\n return controller.signal;\n }\n signal.addEventListener(\"abort\", () => controller.abort(signal.reason), {\n once: true,\n });\n }\n\n return controller.signal;\n }\n\n /**\n * Wrap an operation with error handling and telemetry.\n *\n * @param action - The action name for telemetry\n * @param key - Optional key for telemetry\n * @param operation - The operation to execute\n * @returns Result of the operation\n */\n protected async withTelemetry<T>(\n action: string,\n key: string | undefined,\n operation: () => Promise<Result<T>>\n ): Promise<Result<T>> {\n const startTime = Date.now();\n this.emitRequest(action, key);\n\n try {\n const result = await operation();\n\n if (result.ok) {\n this.emitResponse(action, true, startTime);\n } else {\n this.emitResponse(action, false, startTime);\n this.emitError(result.error);\n }\n\n return result;\n } catch (error) {\n const serviceError = wrapError(this.getServiceName(), error);\n this.emitResponse(action, false, startTime);\n this.emitError(serviceError);\n return err(serviceError);\n }\n }\n}\n","/**\n * PrefixedKVService - A prefix-scoped view of KVService.\n *\n * Provides key-value operations scoped to a specific prefix.\n * All operations automatically prefix keys, enabling app data isolation\n * within a shared space.\n *\n * @example\n * ```typescript\n * const space = sdk.space('default');\n *\n * // Create prefix-scoped views\n * const myApp = space.kv.withPrefix('/app.myapp.com');\n * const sharedPhotos = space.kv.withPrefix('/photos');\n *\n * // Operations are automatically prefixed\n * await myApp.put('settings.json', { theme: 'dark' });\n * // -> Actually writes to: /app.myapp.com/settings.json\n *\n * await myApp.get('settings.json');\n * // -> Actually reads from: /app.myapp.com/settings.json\n *\n * await sharedPhotos.list();\n * // -> Lists: /photos/*\n *\n * // Nested prefixes\n * const settings = myApp.withPrefix('/settings');\n * await settings.get('theme.json'); // -> /app.myapp.com/settings/theme.json\n * ```\n */\n\nimport { Result } from \"../types\";\nimport {\n KVGetOptions,\n KVPutOptions,\n KVListOptions,\n KVDeleteOptions,\n KVHeadOptions,\n KVResponse,\n KVListResponse,\n} from \"./types\";\n\n/**\n * Interface for prefixed KV operations.\n *\n * Provides the same operations as IKVService but scoped to a prefix.\n * Supports nested prefixes via withPrefix().\n */\nexport interface IPrefixedKVService {\n /**\n * The current prefix for this scoped view.\n */\n readonly prefix: string;\n\n /**\n * Get a value by key.\n *\n * The key is automatically prefixed with this service's prefix.\n *\n * @param key - The key to retrieve (will be prefixed)\n * @param options - Optional get configuration\n * @returns Result with the stored value and headers\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * const result = await myApp.get('settings.json');\n * // -> Reads from: /app.myapp.com/settings.json\n * ```\n */\n get<T = unknown>(\n key: string,\n options?: Omit<KVGetOptions, 'prefix'>\n ): Promise<Result<KVResponse<T>>>;\n\n /**\n * Store a value at a key.\n *\n * The key is automatically prefixed with this service's prefix.\n *\n * @param key - The key to store under (will be prefixed)\n * @param value - The value to store\n * @param options - Optional put configuration\n * @returns Result indicating success/failure\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * await myApp.put('settings.json', { theme: 'dark' });\n * // -> Stores at: /app.myapp.com/settings.json\n * ```\n */\n put(\n key: string,\n value: unknown,\n options?: Omit<KVPutOptions, 'prefix'>\n ): Promise<Result<KVResponse<void>>>;\n\n /**\n * List keys within this prefix.\n *\n * Returns keys that match the prefix, with keys returned relative\n * to the prefix when removePrefix is true (default for prefixed service).\n *\n * @param options - Optional list configuration\n * @returns Result with array of matching keys\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * const result = await myApp.list();\n * // -> Lists keys under: /app.myapp.com/*\n * // Returns: ['settings.json', 'data/user.json', ...]\n * ```\n */\n list(options?: Omit<KVListOptions, 'prefix'>): Promise<Result<KVListResponse>>;\n\n /**\n * Delete a key.\n *\n * The key is automatically prefixed with this service's prefix.\n *\n * @param key - The key to delete (will be prefixed)\n * @param options - Optional delete configuration\n * @returns Result indicating success/failure\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * await myApp.delete('old-settings.json');\n * // -> Deletes: /app.myapp.com/old-settings.json\n * ```\n */\n delete(key: string, options?: Omit<KVDeleteOptions, 'prefix'>): Promise<Result<void>>;\n\n /**\n * Get metadata for a key without retrieving the value.\n *\n * The key is automatically prefixed with this service's prefix.\n *\n * @param key - The key to check (will be prefixed)\n * @param options - Optional head configuration\n * @returns Result with headers only\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * const result = await myApp.head('large-file.bin');\n * // -> Gets metadata for: /app.myapp.com/large-file.bin\n * ```\n */\n head(key: string, options?: Omit<KVHeadOptions, 'prefix'>): Promise<Result<KVResponse<void>>>;\n\n /**\n * Create a nested prefix-scoped view.\n *\n * The subPrefix is appended to the current prefix.\n *\n * @param subPrefix - The sub-prefix to append\n * @returns A new PrefixedKVService with the combined prefix\n *\n * @example\n * ```typescript\n * const myApp = kv.withPrefix('/app.myapp.com');\n * const settings = myApp.withPrefix('/settings');\n * await settings.get('theme.json');\n * // -> Reads from: /app.myapp.com/settings/theme.json\n * ```\n */\n withPrefix(subPrefix: string): IPrefixedKVService;\n}\n\n/**\n * Interface for a KV service that supports prefix delegation.\n *\n * This is the subset of IKVService methods needed by PrefixedKVService.\n */\ninterface IKVServiceLike {\n get<T = unknown>(\n key: string,\n options?: KVGetOptions\n ): Promise<Result<KVResponse<T>>>;\n\n put(\n key: string,\n value: unknown,\n options?: KVPutOptions\n ): Promise<Result<KVResponse<void>>>;\n\n list(options?: KVListOptions): Promise<Result<KVListResponse>>;\n\n delete(key: string, options?: KVDeleteOptions): Promise<Result<void>>;\n\n head(key: string, options?: KVHeadOptions): Promise<Result<KVResponse<void>>>;\n}\n\n/**\n * PrefixedKVService - Implementation of prefix-scoped KV operations.\n *\n * This class wraps a KVService (or another PrefixedKVService) and\n * automatically prefixes all key operations with the configured prefix.\n *\n * ## Prefix Convention\n *\n * | Pattern | Use Case | Example |\n * | -- | -- | -- |\n * | `/app.{domain}/` | App-private data | `/app.photos.xyz/settings.json` |\n * | `/{type}/` | Shared data type | `/photos/vacation.jpg` |\n * | `/.{name}/` | Hidden/system data | `/.cache/thumbnails/` |\n * | `/public/` | Explicitly shareable | `/public/profile.json` |\n *\n * @example\n * ```typescript\n * // Create from KVService\n * const prefixed = new PrefixedKVService(kvService, '/app.myapp.com');\n *\n * // Or use the withPrefix factory method on KVService\n * const prefixed = kvService.withPrefix('/app.myapp.com');\n *\n * // All operations are automatically prefixed\n * await prefixed.put('settings.json', { theme: 'dark' });\n * await prefixed.get('settings.json');\n *\n * // Nested prefixes\n * const nested = prefixed.withPrefix('/settings');\n * await nested.get('theme.json'); // -> /app.myapp.com/settings/theme.json\n * ```\n */\nexport class PrefixedKVService implements IPrefixedKVService {\n /**\n * The underlying KV service.\n */\n private readonly _kv: IKVServiceLike;\n\n /**\n * The prefix for this scoped view.\n */\n private readonly _prefix: string;\n\n /**\n * Create a new PrefixedKVService.\n *\n * @param kv - The underlying KV service to delegate to\n * @param prefix - The prefix to apply to all operations\n */\n constructor(kv: IKVServiceLike, prefix: string) {\n this._kv = kv;\n // Normalize prefix: ensure it doesn't end with slash\n this._prefix = prefix.endsWith('/') ? prefix.slice(0, -1) : prefix;\n }\n\n /**\n * The current prefix for this scoped view.\n */\n get prefix(): string {\n return this._prefix;\n }\n\n /**\n * Compute the full key path by combining prefix and key.\n *\n * @param key - The key to prefix\n * @returns The full path including prefix\n */\n private getFullKey(key: string): string {\n // Handle keys that start with slash\n const normalizedKey = key.startsWith('/') ? key : `/${key}`;\n return `${this._prefix}${normalizedKey}`;\n }\n\n /**\n * Get a value by key.\n */\n async get<T = unknown>(\n key: string,\n options?: Omit<KVGetOptions, 'prefix'>\n ): Promise<Result<KVResponse<T>>> {\n const fullKey = this.getFullKey(key);\n // Use empty prefix override to use the full key as-is\n return this._kv.get<T>(fullKey, { ...options, prefix: '' });\n }\n\n /**\n * Store a value at a key.\n */\n async put(\n key: string,\n value: unknown,\n options?: Omit<KVPutOptions, 'prefix'>\n ): Promise<Result<KVResponse<void>>> {\n const fullKey = this.getFullKey(key);\n return this._kv.put(fullKey, value, { ...options, prefix: '' });\n }\n\n /**\n * List keys within this prefix.\n */\n async list(options?: Omit<KVListOptions, 'prefix'>): Promise<Result<KVListResponse>> {\n // List uses the prefix directly, and by default removes the prefix from results\n const removePrefix = options?.removePrefix ?? true;\n return this._kv.list({\n ...options,\n prefix: this._prefix,\n removePrefix,\n });\n }\n\n /**\n * Delete a key.\n */\n async delete(key: string, options?: Omit<KVDeleteOptions, 'prefix'>): Promise<Result<void>> {\n const fullKey = this.getFullKey(key);\n return this._kv.delete(fullKey, { ...options, prefix: '' });\n }\n\n /**\n * Get metadata for a key without retrieving the value.\n */\n async head(\n key: string,\n options?: Omit<KVHeadOptions, 'prefix'>\n ): Promise<Result<KVResponse<void>>> {\n const fullKey = this.getFullKey(key);\n return this._kv.head(fullKey, { ...options, prefix: '' });\n }\n\n /**\n * Create a nested prefix-scoped view.\n */\n withPrefix(subPrefix: string): IPrefixedKVService {\n // Normalize subPrefix\n const normalizedSubPrefix = subPrefix.startsWith('/')\n ? subPrefix\n : `/${subPrefix}`;\n const combinedPrefix = `${this._prefix}${normalizedSubPrefix}`;\n return new PrefixedKVService(this._kv, combinedPrefix);\n }\n}\n","/**\n * KV Service Types\n *\n * Type definitions for the KV (Key-Value) service operations.\n */\n\n/**\n * Configuration for KVService.\n */\nexport interface KVServiceConfig {\n /**\n * Default prefix for all keys.\n * Useful for namespacing data within a space.\n *\n * @example\n * ```typescript\n * const kv = new KVService({ prefix: 'myapp/settings' });\n * await kv.put('theme', 'dark'); // Stores at 'myapp/settings/theme'\n * ```\n */\n prefix?: string;\n\n /**\n * Default timeout in milliseconds for KV operations.\n * Overrides the context-level timeout if set.\n */\n timeout?: number;\n\n /** Allow additional config properties */\n [key: string]: unknown;\n}\n\n/**\n * Options for KV get operations.\n */\nexport interface KVGetOptions {\n /**\n * Override the default prefix for this operation.\n */\n prefix?: string;\n\n /**\n * Return raw response instead of parsed JSON.\n * When true, data will be the raw response text.\n */\n raw?: boolean;\n\n /**\n * Custom timeout for this operation in milliseconds.\n */\n timeout?: number;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for KV put operations.\n */\nexport interface KVPutOptions {\n /**\n * Override the default prefix for this operation.\n */\n prefix?: string;\n\n /**\n * Content type for the value.\n * Defaults to 'application/json' for objects.\n */\n contentType?: string;\n\n /**\n * Custom metadata headers to store with the value.\n */\n metadata?: Record<string, string>;\n\n /**\n * Custom timeout for this operation in milliseconds.\n */\n timeout?: number;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for KV list operations.\n */\nexport interface KVListOptions {\n /**\n * Override the default prefix for this operation.\n */\n prefix?: string;\n\n /**\n * Additional path to append to the prefix.\n */\n path?: string;\n\n /**\n * Whether to remove the prefix from returned keys.\n * When true, keys are returned relative to the prefix.\n */\n removePrefix?: boolean;\n\n /**\n * Return raw response instead of parsed JSON.\n */\n raw?: boolean;\n\n /**\n * Custom timeout for this operation in milliseconds.\n */\n timeout?: number;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for KV delete operations.\n */\nexport interface KVDeleteOptions {\n /**\n * Override the default prefix for this operation.\n */\n prefix?: string;\n\n /**\n * Custom timeout for this operation in milliseconds.\n */\n timeout?: number;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for KV head (metadata) operations.\n */\nexport interface KVHeadOptions {\n /**\n * Override the default prefix for this operation.\n */\n prefix?: string;\n\n /**\n * Custom timeout for this operation in milliseconds.\n */\n timeout?: number;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Response headers from KV operations.\n */\nexport interface KVResponseHeaders {\n /**\n * ETag for conditional requests.\n */\n etag?: string;\n\n /**\n * Content type of the stored value.\n */\n contentType?: string;\n\n /**\n * Last modification timestamp.\n */\n lastModified?: string;\n\n /**\n * Content length in bytes.\n */\n contentLength?: number;\n\n /**\n * Get a header value by name.\n * @param name - Header name (case-insensitive)\n */\n get(name: string): string | null;\n}\n\n/**\n * Response from KV get/put operations.\n *\n * @template T - Type of the data payload\n */\nexport interface KVResponse<T = unknown> {\n /**\n * The data payload.\n * For get: the stored value.\n * For put: undefined.\n */\n data: T;\n\n /**\n * Response headers with metadata.\n */\n headers: KVResponseHeaders;\n}\n\n/**\n * Response from KV list operations.\n */\nexport interface KVListResponse {\n /**\n * Array of keys matching the list criteria.\n */\n keys: string[];\n}\n\n/**\n * KV service action types.\n */\nexport const KVAction = {\n GET: \"tinycloud.kv/get\",\n PUT: \"tinycloud.kv/put\",\n LIST: \"tinycloud.kv/list\",\n DELETE: \"tinycloud.kv/del\",\n HEAD: \"tinycloud.kv/metadata\",\n} as const;\n\nexport type KVActionType = (typeof KVAction)[keyof typeof KVAction];\n","/**\n * KVService - Key-Value storage service implementation.\n *\n * Platform-agnostic KV service that works with both web-sdk and node-sdk.\n * Uses dependency injection via IServiceContext for platform dependencies.\n */\n\nimport { BaseService } from \"../base/BaseService\";\nimport {\n Result,\n ok,\n err,\n ErrorCodes,\n serviceError,\n FetchResponse,\n} from \"../types\";\nimport {\n authRequiredError,\n wrapError,\n storageQuotaExceededError,\n storageLimitReachedError,\n parseAuthError,\n authUnauthorizedError,\n} from \"../errors\";\nimport { IKVService } from \"./IKVService\";\nimport { PrefixedKVService, IPrefixedKVService } from \"./PrefixedKVService\";\nimport {\n KVServiceConfig,\n KVGetOptions,\n KVPutOptions,\n KVListOptions,\n KVDeleteOptions,\n KVHeadOptions,\n KVResponse,\n KVListResponse,\n KVResponseHeaders,\n KVAction,\n} from \"./types\";\n\n/**\n * KV service implementation.\n *\n * Provides key-value storage operations using TinyCloud's KV API.\n * Uses the Result type pattern for explicit error handling.\n *\n * @example\n * ```typescript\n * // Register with SDK\n * const sdk = new TinyCloud({\n * services: { kv: KVService },\n * serviceConfigs: { kv: { prefix: 'myapp' } },\n * });\n *\n * // Use the service\n * const result = await sdk.kv.get('settings');\n * if (result.ok) {\n * console.log(result.data.data);\n * }\n * ```\n */\nexport class KVService extends BaseService implements IKVService {\n /**\n * Service identifier for registration.\n */\n static readonly serviceName = \"kv\";\n\n /**\n * Service configuration.\n */\n declare protected _config: KVServiceConfig;\n\n /**\n * Create a new KVService instance.\n *\n * @param config - Service configuration\n */\n constructor(config: KVServiceConfig = {}) {\n super();\n this._config = config;\n }\n\n /**\n * Get the service configuration.\n */\n get config(): KVServiceConfig {\n return this._config;\n }\n\n // Parses \"Used: X bytes, Limit: Y bytes\" from tinycloud-node error responses\n private parseQuotaInfo(\n errorText: string\n ): { usedBytes: number; limitBytes: number } | undefined {\n const match = errorText.match(\n /Used:\\s*(\\d+)\\s*bytes,\\s*Limit:\\s*(\\d+)\\s*bytes/i\n );\n if (match) {\n return {\n usedBytes: parseInt(match[1], 10),\n limitBytes: parseInt(match[2], 10),\n };\n }\n return undefined;\n }\n\n private handleQuotaErrorResponse(\n response: FetchResponse,\n errorText: string,\n key: string\n ): Result<never> | undefined {\n if (response.status === 402) {\n const quotaInfo = this.parseQuotaInfo(errorText);\n return err(\n storageQuotaExceededError(\n \"kv\",\n `Storage quota exceeded for key \"${key}\": ${errorText}`,\n {\n status: response.status,\n ...(quotaInfo\n ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes }\n : {}),\n }\n )\n );\n }\n\n if (response.status === 413) {\n const quotaInfo = this.parseQuotaInfo(errorText);\n return err(\n storageLimitReachedError(\n \"kv\",\n `Storage limit reached for key \"${key}\": ${errorText}`,\n {\n status: response.status,\n ...(quotaInfo\n ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes }\n : {}),\n }\n )\n );\n }\n\n return undefined;\n }\n\n /**\n * Get the full path with optional prefix.\n *\n * @param key - The key\n * @param prefixOverride - Optional prefix override\n * @returns The full path\n */\n private getFullPath(key: string, prefixOverride?: string): string {\n const prefix = prefixOverride ?? this._config.prefix ?? \"\";\n return prefix ? `${prefix}/${key}` : key;\n }\n\n /**\n * Get the host URL.\n */\n private get host(): string {\n return this.context.hosts[0];\n }\n\n /**\n * Execute an invoke operation.\n *\n * @param path - Resource path\n * @param action - KV action\n * @param body - Optional request body\n * @param signal - Optional abort signal\n * @returns Fetch response\n */\n private async invokeOperation(\n path: string,\n action: string,\n body?: Blob | string,\n signal?: AbortSignal\n ): Promise<FetchResponse> {\n const session = this.context.session!;\n const headers = this.context.invoke(\n session,\n \"kv\",\n path,\n action\n );\n\n return this.context.fetch(`${this.host}/invoke`, {\n method: \"POST\",\n headers,\n body,\n signal: this.combineSignals(signal),\n });\n }\n\n /**\n * Create KVResponseHeaders from fetch response headers.\n *\n * @param headers - Fetch response headers\n * @returns KVResponseHeaders object\n */\n private createResponseHeaders(headers: {\n get(name: string): string | null;\n }): KVResponseHeaders {\n return {\n etag: headers.get(\"etag\") ?? undefined,\n contentType: headers.get(\"content-type\") ?? undefined,\n lastModified: headers.get(\"last-modified\") ?? undefined,\n contentLength: headers.get(\"content-length\")\n ? parseInt(headers.get(\"content-length\")!, 10)\n : undefined,\n get: (name: string) => headers.get(name),\n };\n }\n\n /**\n * Parse response body based on content type.\n *\n * @param response - Fetch response\n * @param raw - Whether to return raw text\n * @returns Parsed data\n */\n private async parseResponse<T>(\n response: FetchResponse,\n raw: boolean = false\n ): Promise<T | undefined> {\n if (!response.ok) {\n return undefined;\n }\n\n if (raw) {\n return (await response.text()) as unknown as T;\n }\n\n const contentType = response.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n return (await response.json()) as T;\n } else if (contentType?.startsWith(\"text/\")) {\n return (await response.text()) as unknown as T;\n }\n\n // No content-type header - try to parse as JSON, fall back to text\n const text = await response.text();\n if (!text) {\n return undefined;\n }\n try {\n return JSON.parse(text) as T;\n } catch {\n return text as unknown as T;\n }\n }\n\n /**\n * Get a value by key.\n */\n async get<T = unknown>(\n key: string,\n options?: KVGetOptions\n ): Promise<Result<KVResponse<T>>> {\n return this.withTelemetry(\"get\", key, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"kv\"));\n }\n\n const path = this.getFullPath(key, options?.prefix);\n\n try {\n const response = await this.invokeOperation(\n path,\n KVAction.GET,\n undefined,\n options?.signal\n );\n\n if (!response.ok) {\n if (response.status === 401) {\n const errorText = await response.text();\n const { resource, action } = parseAuthError(errorText);\n return err(authUnauthorizedError(\"kv\", errorText, {\n status: response.status,\n ...(action && { requiredAction: action }),\n ...(resource && { resource }),\n }));\n }\n\n if (response.status === 404) {\n return err(\n serviceError(\n ErrorCodes.KV_NOT_FOUND,\n `Key not found: ${key}`,\n \"kv\"\n )\n );\n }\n\n const errorText = await response.text();\n return err(\n serviceError(\n ErrorCodes.NETWORK_ERROR,\n `Failed to get key \"${key}\": ${response.status} - ${errorText}`,\n \"kv\",\n { meta: { status: response.status, statusText: response.statusText } }\n )\n );\n }\n\n const data = await this.parseResponse<T>(response, options?.raw);\n return ok({\n data: data as T,\n headers: this.createResponseHeaders(response.headers),\n });\n } catch (error) {\n return err(wrapError(\"kv\", error));\n }\n });\n }\n\n /**\n * Store a value at a key.\n */\n async put(\n key: string,\n value: unknown,\n options?: KVPutOptions\n ): Promise<Result<KVResponse<void>>> {\n return this.withTelemetry(\"put\", key, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"kv\"));\n }\n\n const path = this.getFullPath(key, options?.prefix);\n\n // Serialize value to string\n let body: string;\n if (typeof value === \"string\") {\n body = value;\n } else {\n body = JSON.stringify(value);\n }\n\n try {\n const response = await this.invokeOperation(\n path,\n KVAction.PUT,\n body,\n options?.signal\n );\n\n if (!response.ok) {\n if (response.status === 401) {\n const errorText = await response.text();\n const { resource, action } = parseAuthError(errorText);\n return err(authUnauthorizedError(\"kv\", errorText, {\n status: response.status,\n ...(action && { requiredAction: action }),\n ...(resource && { resource }),\n }));\n }\n\n const errorText = await response.text();\n\n // Check for storage quota errors (402, 413)\n const quotaError = this.handleQuotaErrorResponse(\n response,\n errorText,\n key\n );\n if (quotaError) {\n return quotaError;\n }\n\n return err(\n serviceError(\n ErrorCodes.KV_WRITE_FAILED,\n `Failed to put key \"${key}\": ${response.status} - ${errorText}`,\n \"kv\",\n { meta: { status: response.status, statusText: response.statusText } }\n )\n );\n }\n\n return ok({\n data: undefined as void,\n headers: this.createResponseHeaders(response.headers),\n });\n } catch (error) {\n return err(wrapError(\"kv\", error));\n }\n });\n }\n\n /**\n * List keys with optional prefix filtering.\n */\n async list(options?: KVListOptions): Promise<Result<KVListResponse>> {\n return this.withTelemetry(\"list\", options?.prefix, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"kv\"));\n }\n\n // Build the path from prefix and optional path\n let listPath = options?.prefix ?? this._config.prefix ?? \"\";\n if (options?.path) {\n listPath = listPath ? `${listPath}/${options.path}` : options.path;\n }\n\n try {\n const response = await this.invokeOperation(\n listPath,\n KVAction.LIST,\n undefined,\n options?.signal\n );\n\n if (!response.ok) {\n if (response.status === 401) {\n const errorText = await response.text();\n const { resource, action } = parseAuthError(errorText);\n return err(authUnauthorizedError(\"kv\", errorText, {\n status: response.status,\n ...(action && { requiredAction: action }),\n ...(resource && { resource }),\n }));\n }\n\n const errorText = await response.text();\n return err(\n serviceError(\n ErrorCodes.NETWORK_ERROR,\n `Failed to list keys: ${response.status} - ${errorText}`,\n \"kv\",\n { meta: { status: response.status, statusText: response.statusText } }\n )\n );\n }\n\n let keys = await this.parseResponse<string[]>(response, options?.raw);\n keys = keys ?? [];\n\n // Optionally remove prefix from keys\n if (options?.removePrefix && listPath) {\n const prefixWithSlash = listPath.endsWith(\"/\")\n ? listPath\n : `${listPath}/`;\n keys = keys.map((key) =>\n key.startsWith(prefixWithSlash)\n ? key.slice(prefixWithSlash.length)\n : key\n );\n }\n\n return ok({ keys });\n } catch (error) {\n return err(wrapError(\"kv\", error));\n }\n });\n }\n\n /**\n * Delete a key.\n */\n async delete(key: string, options?: KVDeleteOptions): Promise<Result<void>> {\n return this.withTelemetry(\"delete\", key, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"kv\"));\n }\n\n const path = this.getFullPath(key, options?.prefix);\n\n try {\n const response = await this.invokeOperation(\n path,\n KVAction.DELETE,\n undefined,\n options?.signal\n );\n\n if (!response.ok) {\n if (response.status === 401) {\n const errorText = await response.text();\n const { resource, action } = parseAuthError(errorText);\n return err(authUnauthorizedError(\"kv\", errorText, {\n status: response.status,\n ...(action && { requiredAction: action }),\n ...(resource && { resource }),\n }));\n }\n\n if (response.status === 404) {\n return err(\n serviceError(\n ErrorCodes.KV_NOT_FOUND,\n `Key not found: ${key}`,\n \"kv\"\n )\n );\n }\n\n const errorText = await response.text();\n return err(\n serviceError(\n ErrorCodes.NETWORK_ERROR,\n `Failed to delete key \"${key}\": ${response.status} - ${errorText}`,\n \"kv\",\n { meta: { status: response.status, statusText: response.statusText } }\n )\n );\n }\n\n return ok(undefined);\n } catch (error) {\n return err(wrapError(\"kv\", error));\n }\n });\n }\n\n /**\n * Get metadata for a key without retrieving the value.\n */\n async head(\n key: string,\n options?: KVHeadOptions\n ): Promise<Result<KVResponse<void>>> {\n return this.withTelemetry(\"head\", key, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"kv\"));\n }\n\n const path = this.getFullPath(key, options?.prefix);\n\n try {\n const response = await this.invokeOperation(\n path,\n KVAction.HEAD,\n undefined,\n options?.signal\n );\n\n if (!response.ok) {\n if (response.status === 401) {\n const errorText = await response.text();\n const { resource, action } = parseAuthError(errorText);\n return err(authUnauthorizedError(\"kv\", errorText, {\n status: response.status,\n ...(action && { requiredAction: action }),\n ...(resource && { resource }),\n }));\n }\n\n if (response.status === 404) {\n return err(\n serviceError(\n ErrorCodes.KV_NOT_FOUND,\n `Key not found: ${key}`,\n \"kv\"\n )\n );\n }\n\n const errorText = await response.text();\n return err(\n serviceError(\n ErrorCodes.NETWORK_ERROR,\n `Failed to get metadata for key \"${key}\": ${response.status} - ${errorText}`,\n \"kv\",\n { meta: { status: response.status, statusText: response.statusText } }\n )\n );\n }\n\n return ok({\n data: undefined as void,\n headers: this.createResponseHeaders(response.headers),\n });\n } catch (error) {\n return err(wrapError(\"kv\", error));\n }\n });\n }\n\n /**\n * Create a prefix-scoped view of this KV service.\n *\n * Returns a PrefixedKVService that automatically prefixes all\n * key operations with the specified prefix. This enables apps\n * to isolate their data within a shared space.\n *\n * @param prefix - The prefix to apply to all operations\n * @returns A PrefixedKVService scoped to the prefix\n *\n * ## Prefix Conventions\n *\n * | Pattern | Use Case | Example |\n * | -- | -- | -- |\n * | `/app.{domain}/` | App-private data | `/app.photos.xyz/settings.json` |\n * | `/{type}/` | Shared data type | `/photos/vacation.jpg` |\n * | `/.{name}/` | Hidden/system data | `/.cache/thumbnails/` |\n * | `/public/` | Explicitly shareable | `/public/profile.json` |\n *\n * @example\n * ```typescript\n * const space = sdk.space('default');\n *\n * // Create prefix-scoped views\n * const myApp = space.kv.withPrefix('/app.myapp.com');\n * const sharedPhotos = space.kv.withPrefix('/photos');\n *\n * // Operations are automatically prefixed\n * await myApp.put('settings.json', { theme: 'dark' });\n * // -> Actually writes to: /app.myapp.com/settings.json\n *\n * await myApp.get('settings.json');\n * // -> Actually reads from: /app.myapp.com/settings.json\n *\n * await sharedPhotos.list();\n * // -> Lists: /photos/*\n *\n * // Nested prefixes\n * const settings = myApp.withPrefix('/settings');\n * await settings.get('theme.json'); // -> /app.myapp.com/settings/theme.json\n * ```\n */\n withPrefix(prefix: string): IPrefixedKVService {\n return new PrefixedKVService(this, prefix);\n }\n}\n","/**\n * DatabaseHandle - Handle for operations on a specific named database.\n *\n * Delegates all operations to the parent SQLService with the database name.\n */\n\nimport type { Result } from \"../types\";\nimport type { IDatabaseHandle } from \"./ISQLService\";\nimport type { SQLService } from \"./SQLService\";\nimport type {\n SqlValue,\n SqlStatement,\n QueryResponse,\n ExecuteResponse,\n BatchResponse,\n QueryOptions,\n ExecuteOptions,\n BatchOptions,\n} from \"./types\";\n\nexport class DatabaseHandle implements IDatabaseHandle {\n private service: SQLService;\n public readonly name: string;\n\n constructor(service: SQLService, name: string) {\n this.service = service;\n this.name = name;\n }\n\n async query<T = Record<string, unknown>>(\n sql: string,\n params?: SqlValue[],\n options?: QueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.service.queryOnDb<T>(this.name, sql, params, options);\n }\n\n async execute(\n sql: string,\n params?: SqlValue[],\n options?: ExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.service.executeOnDb(this.name, sql, params, options);\n }\n\n async batch(\n statements: SqlStatement[],\n options?: BatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.service.batchOnDb(this.name, statements, options);\n }\n\n async executeStatement(\n name: string,\n params?: SqlValue[],\n options?: QueryOptions\n ): Promise<Result<QueryResponse | ExecuteResponse>> {\n return this.service.executeStatementOnDb(this.name, name, params, options);\n }\n\n async export(options?: QueryOptions): Promise<Result<Blob>> {\n return this.service.exportDb(this.name, options);\n }\n}\n","/**\n * SQL Service Types\n *\n * Type definitions for the SQL service operations.\n */\n\n/**\n * Configuration for SQLService.\n */\nexport interface SQLServiceConfig {\n /**\n * Default database name.\n * If not set, operations default to \"default\".\n */\n defaultDatabase?: string;\n\n /**\n * Default timeout in milliseconds for SQL operations.\n */\n timeout?: number;\n\n /** Allow additional config properties */\n [key: string]: unknown;\n}\n\n/**\n * Options for SQL query operations.\n */\nexport interface QueryOptions {\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for SQL execute operations.\n */\nexport interface ExecuteOptions {\n /**\n * Schema initialization statements (CREATE TABLE IF NOT EXISTS ...).\n * Executed before the main statement on first write.\n */\n schema?: string[];\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for SQL batch operations.\n */\nexport interface BatchOptions {\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A SQL value: null, number, string, or binary data.\n */\nexport type SqlValue = null | number | string | Uint8Array;\n\n/**\n * A SQL statement with optional parameters.\n */\nexport interface SqlStatement {\n sql: string;\n params?: SqlValue[];\n}\n\n/**\n * Response from SQL query operations.\n */\nexport interface QueryResponse<T = Record<string, unknown>> {\n columns: string[];\n rows: T[][];\n rowCount: number;\n}\n\n/**\n * Response from SQL execute operations.\n */\nexport interface ExecuteResponse {\n changes: number;\n lastInsertRowId: number;\n}\n\n/**\n * Response from SQL batch operations.\n */\nexport interface BatchResponse {\n results: ExecuteResponse[];\n}\n\n/**\n * SQL service action types.\n */\nexport const SQLAction = {\n READ: \"tinycloud.sql/read\",\n WRITE: \"tinycloud.sql/write\",\n ADMIN: \"tinycloud.sql/admin\",\n SELECT: \"tinycloud.sql/select\",\n INSERT: \"tinycloud.sql/insert\",\n UPDATE: \"tinycloud.sql/update\",\n DELETE: \"tinycloud.sql/delete\",\n EXECUTE: \"tinycloud.sql/execute\",\n EXPORT: \"tinycloud.sql/export\",\n ALL: \"tinycloud.sql/*\",\n} as const;\n\nexport type SQLActionType = (typeof SQLAction)[keyof typeof SQLAction];\n","/**\n * SQLService - SQL database service implementation.\n *\n * Platform-agnostic SQL service that works with both web-sdk and node-sdk.\n * Uses dependency injection via IServiceContext for platform dependencies.\n */\n\nimport { BaseService } from \"../base/BaseService\";\nimport {\n Result,\n ok,\n err,\n ErrorCodes,\n serviceError,\n type FetchResponse,\n} from \"../types\";\nimport { authRequiredError, wrapError, parseAuthError } from \"../errors\";\nimport type { ISQLService } from \"./ISQLService\";\nimport type { IDatabaseHandle } from \"./ISQLService\";\nimport { DatabaseHandle } from \"./DatabaseHandle\";\nimport {\n type SQLServiceConfig,\n type QueryOptions,\n type ExecuteOptions,\n type BatchOptions,\n type SqlValue,\n type SqlStatement,\n type QueryResponse,\n type ExecuteResponse,\n type BatchResponse,\n SQLAction,\n} from \"./types\";\n\nexport class SQLService extends BaseService implements ISQLService {\n static readonly serviceName = \"sql\";\n\n declare protected _config: SQLServiceConfig;\n\n constructor(config: SQLServiceConfig = {}) {\n super();\n this._config = config;\n }\n\n get config(): SQLServiceConfig {\n return this._config;\n }\n\n private get defaultDbName(): string {\n return this._config.defaultDatabase ?? \"default\";\n }\n\n private get host(): string {\n return this.context.hosts[0];\n }\n\n /**\n * Get a handle to a named database.\n */\n db(name?: string): IDatabaseHandle {\n return new DatabaseHandle(this, name ?? this.defaultDbName);\n }\n\n /**\n * Shortcut: query the default database.\n */\n async query<T = Record<string, unknown>>(\n sql: string,\n params?: SqlValue[],\n options?: QueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.queryOnDb<T>(this.defaultDbName, sql, params, options);\n }\n\n /**\n * Shortcut: execute on the default database.\n */\n async execute(\n sql: string,\n params?: SqlValue[],\n options?: ExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.executeOnDb(this.defaultDbName, sql, params, options);\n }\n\n /**\n * Shortcut: batch on the default database.\n */\n async batch(\n statements: SqlStatement[],\n options?: BatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.batchOnDb(this.defaultDbName, statements, options);\n }\n\n // === Internal methods called by DatabaseHandle ===\n\n async queryOnDb<T = Record<string, unknown>>(\n dbName: string,\n sql: string,\n params?: SqlValue[],\n options?: QueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.withTelemetry(\"query\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"sql\"));\n }\n\n try {\n const response = await this.invokeSQL(\n dbName,\n SQLAction.READ,\n { action: \"query\", sql, params: params ?? [] },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"query\");\n }\n\n const data = (await response.json()) as QueryResponse<T>;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"sql\", error));\n }\n });\n }\n\n async executeOnDb(\n dbName: string,\n sql: string,\n params?: SqlValue[],\n options?: ExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.withTelemetry(\"execute\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"sql\"));\n }\n\n try {\n const body: Record<string, unknown> = {\n action: \"execute\",\n sql,\n params: params ?? [],\n };\n if (options?.schema) {\n body.schema = options.schema;\n }\n\n const response = await this.invokeSQL(\n dbName,\n SQLAction.WRITE,\n body,\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"execute\");\n }\n\n const data = (await response.json()) as ExecuteResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"sql\", error));\n }\n });\n }\n\n async batchOnDb(\n dbName: string,\n statements: SqlStatement[],\n options?: BatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.withTelemetry(\"batch\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"sql\"));\n }\n\n try {\n const response = await this.invokeSQL(\n dbName,\n SQLAction.WRITE,\n { action: \"batch\", statements },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"batch\");\n }\n\n const data = (await response.json()) as BatchResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"sql\", error));\n }\n });\n }\n\n async executeStatementOnDb(\n dbName: string,\n name: string,\n params?: SqlValue[],\n options?: QueryOptions\n ): Promise<Result<QueryResponse | ExecuteResponse>> {\n return this.withTelemetry(\"executeStatement\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"sql\"));\n }\n\n try {\n const response = await this.invokeSQL(\n dbName,\n SQLAction.EXECUTE,\n { action: \"execute_statement\", name, params: params ?? [] },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"executeStatement\");\n }\n\n const data = (await response.json()) as\n | QueryResponse\n | ExecuteResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"sql\", error));\n }\n });\n }\n\n async exportDb(\n dbName: string,\n options?: QueryOptions\n ): Promise<Result<Blob>> {\n return this.withTelemetry(\"export\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"sql\"));\n }\n\n try {\n const response = await this.invokeSQL(\n dbName,\n SQLAction.EXPORT,\n { action: \"export\" },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"export\");\n }\n\n // FetchResponse doesn't expose blob(), so access it from the\n // underlying response which is a standard fetch Response at runtime\n const resp = response as any;\n if (typeof resp.blob === \"function\") {\n const blob = await resp.blob();\n return ok(blob as Blob);\n }\n // If blob() is not available, return the raw text as a Blob-like\n const text = await response.text();\n return ok(text as unknown as Blob);\n } catch (error) {\n return err(wrapError(\"sql\", error));\n }\n });\n }\n\n // === Private helpers ===\n\n private async invokeSQL(\n dbName: string,\n action: string,\n body: Record<string, unknown>,\n signal?: AbortSignal\n ): Promise<FetchResponse> {\n const session = this.context.session!;\n const headers = this.context.invoke(session, \"sql\", dbName, action);\n\n return this.context.fetch(`${this.host}/invoke`, {\n method: \"POST\",\n headers: {\n ...(headers as Record<string, string>),\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body) as any,\n signal: this.combineSignals(signal),\n });\n }\n\n private async handleErrorResponse(\n response: FetchResponse,\n operation: string\n ): Promise<Result<never>> {\n const errorText = await response.text();\n\n let errorBody: { error?: string; message?: string; code?: string } = {};\n try {\n errorBody = JSON.parse(errorText);\n } catch {\n // Not JSON\n }\n\n const errorCode = this.mapHttpStatusToErrorCode(\n response.status,\n errorBody.error\n );\n const message =\n errorBody.message ||\n `SQL ${operation} failed: ${response.status} - ${errorText}`;\n\n const meta: Record<string, unknown> = { status: response.status, statusText: response.statusText };\n\n if (response.status === 401) {\n const { resource, action } = parseAuthError(errorText);\n if (action) meta.requiredAction = action;\n if (resource) meta.resource = resource;\n }\n\n return err(\n serviceError(errorCode, message, \"sql\", { meta })\n );\n }\n\n private mapHttpStatusToErrorCode(\n status: number,\n serverError?: string\n ): string {\n switch (status) {\n case 400:\n return ErrorCodes.SQL_ERROR;\n case 401:\n return ErrorCodes.AUTH_UNAUTHORIZED;\n case 403:\n if (serverError === \"sql_readonly_violation\") {\n return ErrorCodes.SQL_READONLY_VIOLATION;\n }\n return ErrorCodes.SQL_PERMISSION_DENIED;\n case 404:\n return ErrorCodes.SQL_DATABASE_NOT_FOUND;\n case 413:\n return ErrorCodes.SQL_RESPONSE_TOO_LARGE;\n case 429:\n return ErrorCodes.SQL_QUOTA_EXCEEDED;\n default:\n return ErrorCodes.NETWORK_ERROR;\n }\n }\n}\n","/**\n * DuckDbDatabaseHandle - Handle for operations on a specific named database.\n *\n * Delegates all operations to the parent DuckDbService with the database name.\n */\n\nimport type { Result } from \"../types\";\nimport type { IDuckDbDatabaseHandle } from \"./IDuckDbService\";\nimport type { DuckDbService } from \"./DuckDbService\";\nimport type {\n DuckDbValue,\n DuckDbStatement,\n QueryResponse,\n ExecuteResponse,\n BatchResponse,\n SchemaInfo,\n DuckDbQueryOptions,\n DuckDbExecuteOptions,\n DuckDbBatchOptions,\n DuckDbOptions,\n} from \"./types\";\n\nexport class DuckDbDatabaseHandle implements IDuckDbDatabaseHandle {\n private service: DuckDbService;\n public readonly name: string;\n\n constructor(service: DuckDbService, name: string) {\n this.service = service;\n this.name = name;\n }\n\n async query<T = Record<string, unknown>>(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.service.queryOnDb<T>(this.name, sql, params, options);\n }\n\n async queryArrow(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<ArrayBuffer>> {\n return this.service.queryArrowOnDb(this.name, sql, params, options);\n }\n\n async execute(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.service.executeOnDb(this.name, sql, params, options);\n }\n\n async batch(\n statements: DuckDbStatement[],\n options?: DuckDbBatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.service.batchOnDb(this.name, statements, options);\n }\n\n async executeStatement(\n name: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<QueryResponse | ExecuteResponse>> {\n return this.service.executeStatementOnDb(this.name, name, params, options);\n }\n\n async describe(options?: DuckDbOptions): Promise<Result<SchemaInfo>> {\n return this.service.describeDb(this.name, options);\n }\n\n async export(options?: DuckDbOptions): Promise<Result<Blob>> {\n return this.service.exportOnDb(this.name, options);\n }\n\n async import(data: Uint8Array, options?: DuckDbOptions): Promise<Result<void>> {\n return this.service.importOnDb(this.name, data, options);\n }\n}\n","/**\n * DuckDB Service Types\n *\n * Type definitions for the DuckDB service operations.\n */\n\n/**\n * Configuration for DuckDbService.\n */\nexport interface DuckDbServiceConfig {\n /**\n * Default database name.\n * If not set, operations default to \"default\".\n */\n defaultDatabase?: string;\n\n /**\n * Default timeout in milliseconds for DuckDB operations.\n */\n timeout?: number;\n\n /** Allow additional config properties */\n [key: string]: unknown;\n}\n\n/**\n * Options for DuckDB query operations.\n */\nexport interface DuckDbQueryOptions {\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for DuckDB execute operations.\n */\nexport interface DuckDbExecuteOptions {\n /**\n * Schema initialization statements (CREATE TABLE IF NOT EXISTS ...).\n * Executed before the main statement on first write.\n */\n schema?: string[];\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for DuckDB batch operations.\n */\nexport interface DuckDbBatchOptions {\n /**\n * Whether to run statements in a transaction.\n */\n transactional?: boolean;\n\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * Options for DuckDB operations that only need an abort signal.\n */\nexport interface DuckDbOptions {\n /**\n * Custom abort signal for this operation.\n */\n signal?: AbortSignal;\n}\n\n/**\n * A DuckDB value: null, boolean, number, string, binary, array, or object.\n */\nexport type DuckDbValue =\n | null\n | boolean\n | number\n | string\n | Uint8Array\n | DuckDbValueArray\n | DuckDbValueRecord;\n\n/** Array of DuckDB values (workaround for circular type alias). */\nexport interface DuckDbValueArray extends Array<DuckDbValue> {}\n\n/** Record of DuckDB values (workaround for circular type alias). */\nexport interface DuckDbValueRecord {\n [key: string]: DuckDbValue;\n}\n\n/**\n * A DuckDB statement with optional parameters.\n */\nexport interface DuckDbStatement {\n sql: string;\n params?: DuckDbValue[];\n}\n\n/**\n * Response from DuckDB query operations.\n */\nexport interface QueryResponse<T = Record<string, unknown>> {\n columns: string[];\n rows: T[][];\n rowCount: number;\n}\n\n/**\n * Response from DuckDB execute operations.\n */\nexport interface ExecuteResponse {\n changes: number;\n}\n\n/**\n * Response from DuckDB batch operations.\n */\nexport interface BatchResponse {\n results: ExecuteResponse[];\n}\n\n/**\n * Schema information for a DuckDB database.\n */\nexport interface SchemaInfo {\n tables: TableInfo[];\n views: ViewInfo[];\n}\n\n/**\n * Information about a table.\n */\nexport interface TableInfo {\n name: string;\n columns: ColumnInfo[];\n}\n\n/**\n * Information about a column.\n */\nexport interface ColumnInfo {\n name: string;\n type: string;\n nullable: boolean;\n}\n\n/**\n * Information about a view.\n */\nexport interface ViewInfo {\n name: string;\n sql: string;\n}\n\n/**\n * DuckDB service action types.\n */\nexport const DuckDbAction = {\n READ: \"tinycloud.duckdb/read\",\n WRITE: \"tinycloud.duckdb/write\",\n ADMIN: \"tinycloud.duckdb/admin\",\n DESCRIBE: \"tinycloud.duckdb/describe\",\n EXPORT: \"tinycloud.duckdb/export\",\n IMPORT: \"tinycloud.duckdb/import\",\n EXECUTE: \"tinycloud.duckdb/execute\",\n ALL: \"tinycloud.duckdb/*\",\n} as const;\n\nexport type DuckDbActionType = (typeof DuckDbAction)[keyof typeof DuckDbAction];\n","/**\n * DuckDbService - DuckDB database service implementation.\n *\n * Platform-agnostic DuckDB service that works with both web-sdk and node-sdk.\n * Uses dependency injection via IServiceContext for platform dependencies.\n */\n\nimport { BaseService } from \"../base/BaseService\";\nimport {\n Result,\n ok,\n err,\n ErrorCodes,\n serviceError,\n type FetchResponse,\n} from \"../types\";\nimport { authRequiredError, wrapError, parseAuthError } from \"../errors\";\nimport type { IDuckDbService, IDuckDbDatabaseHandle } from \"./IDuckDbService\";\nimport { DuckDbDatabaseHandle } from \"./DuckDbDatabaseHandle\";\nimport {\n type DuckDbServiceConfig,\n type DuckDbQueryOptions,\n type DuckDbExecuteOptions,\n type DuckDbBatchOptions,\n type DuckDbOptions,\n type DuckDbValue,\n type DuckDbStatement,\n type QueryResponse,\n type ExecuteResponse,\n type BatchResponse,\n type SchemaInfo,\n DuckDbAction,\n} from \"./types\";\n\nexport class DuckDbService extends BaseService implements IDuckDbService {\n static readonly serviceName = \"duckdb\";\n\n declare protected _config: DuckDbServiceConfig;\n\n constructor(config: DuckDbServiceConfig = {}) {\n super();\n this._config = config;\n }\n\n get config(): DuckDbServiceConfig {\n return this._config;\n }\n\n private get defaultDbName(): string {\n return this._config.defaultDatabase ?? \"default\";\n }\n\n private get host(): string {\n return this.context.hosts[0];\n }\n\n /**\n * Get a handle to a named database.\n */\n db(name?: string): IDuckDbDatabaseHandle {\n return new DuckDbDatabaseHandle(this, name ?? this.defaultDbName);\n }\n\n /**\n * Shortcut: query the default database (JSON format).\n */\n async query<T = Record<string, unknown>>(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.queryOnDb<T>(this.defaultDbName, sql, params, options);\n }\n\n /**\n * Shortcut: query the default database (Arrow IPC format).\n */\n async queryArrow(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<ArrayBuffer>> {\n return this.queryArrowOnDb(this.defaultDbName, sql, params, options);\n }\n\n /**\n * Shortcut: execute on the default database.\n */\n async execute(\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.executeOnDb(this.defaultDbName, sql, params, options);\n }\n\n /**\n * Shortcut: batch on the default database.\n */\n async batch(\n statements: DuckDbStatement[],\n options?: DuckDbBatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.batchOnDb(this.defaultDbName, statements, options);\n }\n\n // === Internal methods called by DuckDbDatabaseHandle ===\n\n async queryOnDb<T = Record<string, unknown>>(\n dbName: string,\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<QueryResponse<T>>> {\n return this.withTelemetry<QueryResponse<T>>(\"query\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.READ,\n { action: \"query\", sql, params: params ?? [] },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"query\");\n }\n\n const data = (await response.json()) as QueryResponse<T>;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async queryArrowOnDb(\n dbName: string,\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<ArrayBuffer>> {\n return this.withTelemetry<ArrayBuffer>(\"queryArrow\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.READ,\n { action: \"query\", sql, params: params ?? [] },\n options?.signal,\n { Accept: \"application/vnd.apache.arrow.stream\" }\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"queryArrow\");\n }\n\n const buffer = await response.arrayBuffer();\n return ok(buffer);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async executeOnDb(\n dbName: string,\n sql: string,\n params?: DuckDbValue[],\n options?: DuckDbExecuteOptions\n ): Promise<Result<ExecuteResponse>> {\n return this.withTelemetry(\"execute\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const body: Record<string, unknown> = {\n action: \"execute\",\n sql,\n params: params ?? [],\n };\n if (options?.schema) {\n body.schema = options.schema;\n }\n\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.WRITE,\n body,\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"execute\");\n }\n\n const data = (await response.json()) as ExecuteResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async batchOnDb(\n dbName: string,\n statements: DuckDbStatement[],\n options?: DuckDbBatchOptions\n ): Promise<Result<BatchResponse>> {\n return this.withTelemetry(\"batch\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const body: Record<string, unknown> = {\n action: \"batch\",\n statements,\n };\n if (options?.transactional !== undefined) {\n body.transactional = options.transactional;\n }\n\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.WRITE,\n body,\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"batch\");\n }\n\n const data = (await response.json()) as BatchResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async executeStatementOnDb(\n dbName: string,\n name: string,\n params?: DuckDbValue[],\n options?: DuckDbQueryOptions\n ): Promise<Result<QueryResponse | ExecuteResponse>> {\n return this.withTelemetry(\"executeStatement\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.EXECUTE,\n { action: \"executeStatement\", name, params: params ?? [] },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"executeStatement\");\n }\n\n const data = (await response.json()) as\n | QueryResponse\n | ExecuteResponse;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async describeDb(\n dbName: string,\n options?: DuckDbOptions\n ): Promise<Result<SchemaInfo>> {\n return this.withTelemetry(\"describe\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.DESCRIBE,\n { action: \"describe\" },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"describe\");\n }\n\n const data = (await response.json()) as SchemaInfo;\n return ok(data);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async exportOnDb(\n dbName: string,\n options?: DuckDbOptions\n ): Promise<Result<Blob>> {\n return this.withTelemetry(\"export\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const response = await this.invokeDuckDb(\n dbName,\n DuckDbAction.EXPORT,\n { action: \"export\" },\n options?.signal\n );\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"export\");\n }\n\n const blob = await response.blob();\n return ok(blob);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n async importOnDb(\n dbName: string,\n data: Uint8Array,\n options?: DuckDbOptions\n ): Promise<Result<void>> {\n return this.withTelemetry(\"import\", dbName, async () => {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"duckdb\"));\n }\n\n try {\n const session = this.context.session!;\n const headers = this.context.invoke(\n session,\n \"duckdb\",\n dbName,\n DuckDbAction.IMPORT\n );\n\n const response = await this.context.fetch(`${this.host}/invoke`, {\n method: \"POST\",\n headers: {\n ...(headers as Record<string, string>),\n \"Content-Type\": \"application/x-duckdb\",\n },\n body: new Blob([data]),\n signal: this.combineSignals(options?.signal),\n });\n\n if (!response.ok) {\n return this.handleErrorResponse(response, \"import\");\n }\n\n return ok(undefined);\n } catch (error) {\n return err(wrapError(\"duckdb\", error));\n }\n });\n }\n\n // === Private helpers ===\n\n private async invokeDuckDb(\n dbName: string,\n action: string,\n body: Record<string, unknown>,\n signal?: AbortSignal,\n extraHeaders?: Record<string, string>\n ): Promise<FetchResponse> {\n const session = this.context.session!;\n const headers = this.context.invoke(session, \"duckdb\", dbName, action);\n\n return this.context.fetch(`${this.host}/invoke`, {\n method: \"POST\",\n headers: {\n ...(headers as Record<string, string>),\n \"Content-Type\": \"application/json\",\n ...extraHeaders,\n },\n body: JSON.stringify(body),\n signal: this.combineSignals(signal),\n });\n }\n\n private async handleErrorResponse(\n response: FetchResponse,\n operation: string\n ): Promise<Result<never>> {\n const errorText = await response.text();\n\n let errorBody: { error?: string; message?: string; code?: string } = {};\n try {\n errorBody = JSON.parse(errorText);\n } catch {\n // Not JSON\n }\n\n const errorCode = this.mapHttpStatusToErrorCode(\n response.status,\n errorBody.error\n );\n const message =\n errorBody.message ||\n `DuckDB ${operation} failed: ${response.status} - ${errorText}`;\n\n const meta: Record<string, unknown> = { status: response.status, statusText: response.statusText };\n\n if (response.status === 401) {\n const { resource, action } = parseAuthError(errorText);\n if (action) meta.requiredAction = action;\n if (resource) meta.resource = resource;\n }\n\n return err(\n serviceError(errorCode, message, \"duckdb\", { meta })\n );\n }\n\n private mapHttpStatusToErrorCode(\n status: number,\n serverError?: string\n ): string {\n switch (status) {\n case 400:\n return ErrorCodes.DUCKDB_ERROR;\n case 401:\n return ErrorCodes.AUTH_UNAUTHORIZED;\n case 403:\n if (serverError === \"duckdb_readonly_violation\") {\n return ErrorCodes.DUCKDB_READONLY_VIOLATION;\n }\n return ErrorCodes.DUCKDB_PERMISSION_DENIED;\n case 404:\n return ErrorCodes.DUCKDB_DATABASE_NOT_FOUND;\n case 413:\n return ErrorCodes.DUCKDB_RESPONSE_TOO_LARGE;\n case 429:\n return ErrorCodes.DUCKDB_QUOTA_EXCEEDED;\n default:\n return ErrorCodes.NETWORK_ERROR;\n }\n }\n}\n","import { BaseService } from \"../base/BaseService\";\nimport type {\n FetchResponse,\n InvokeAnyEntry,\n ServiceHeaders,\n Result,\n} from \"../types\";\nimport { ErrorCodes, err, ok, serviceError } from \"../types\";\nimport { authRequiredError, wrapError } from \"../errors\";\nimport type { IHooksService } from \"./IHooksService\";\nimport type {\n HookEvent,\n HookStreamEvent,\n HookSubscription,\n HooksServiceConfig,\n SubscribeOptions,\n HookWebhookListOptions,\n HookWebhookRecord,\n HookWebhookRegistration,\n HookWebhookUnregisterOptions,\n} from \"./types\";\n\ninterface HookTicketResponse {\n ticket: string;\n expiresAt: string;\n}\n\ninterface HookSubscriber {\n requested: HookSubscription[];\n ttlSeconds?: number;\n queue: AsyncQueue<HookEvent>;\n}\n\nclass AsyncQueue<T> implements AsyncIterable<T>, AsyncIterator<T> {\n private readonly values: T[] = [];\n private readonly waiters: Array<(result: IteratorResult<T>) => void> = [];\n private closed = false;\n\n [Symbol.asyncIterator](): AsyncIterator<T> {\n return this;\n }\n\n push(value: T): void {\n if (this.closed) {\n return;\n }\n\n const waiter = this.waiters.shift();\n if (waiter) {\n waiter({ value, done: false });\n return;\n }\n\n this.values.push(value);\n }\n\n close(): void {\n if (this.closed) {\n return;\n }\n\n this.closed = true;\n while (this.waiters.length > 0) {\n const waiter = this.waiters.shift();\n waiter?.({ value: undefined as never, done: true });\n }\n }\n\n next(): Promise<IteratorResult<T>> {\n if (this.values.length > 0) {\n const value = this.values.shift()!;\n return Promise.resolve({ value, done: false });\n }\n\n if (this.closed) {\n return Promise.resolve({ value: undefined as never, done: true });\n }\n\n return new Promise<IteratorResult<T>>((resolve) => {\n this.waiters.push(resolve);\n });\n }\n}\n\nexport class HooksService extends BaseService implements IHooksService {\n static readonly serviceName = \"hooks\";\n\n declare protected _config: HooksServiceConfig;\n private readonly _subscribers: Set<HookSubscriber> = new Set();\n private _sharedStreamTask?: Promise<void>;\n private _sharedStreamAbort?: AbortController;\n private _refreshChain: Promise<void> = Promise.resolve();\n private _activeSignature = \"\";\n\n constructor(config: HooksServiceConfig = {}) {\n super();\n this._config = config;\n }\n\n get config(): HooksServiceConfig {\n return this._config;\n }\n\n private get host(): string {\n return this._config.host ?? this.context.hosts[0];\n }\n\n async *subscribe(\n subscriptions: HookSubscription[],\n options: SubscribeOptions = {},\n ): AsyncIterable<HookEvent> {\n if (!this.requireAuth()) {\n throw new Error(\"Authentication required for hooks subscription\");\n }\n if (subscriptions.length === 0) {\n throw new Error(\"At least one hook subscription is required\");\n }\n\n const normalized = subscriptions.map(normalizeSubscription);\n const subscriber: HookSubscriber = {\n requested: normalized,\n ttlSeconds: options.ttlSeconds,\n queue: new AsyncQueue<HookEvent>(),\n };\n\n this._subscribers.add(subscriber);\n const abortHandler = () => {\n this._subscribers.delete(subscriber);\n subscriber.queue.close();\n void this.scheduleSharedStreamRefresh();\n };\n\n if (options.signal) {\n if (options.signal.aborted) {\n abortHandler();\n } else {\n options.signal.addEventListener(\"abort\", abortHandler, { once: true });\n }\n }\n\n void this.scheduleSharedStreamRefresh();\n\n try {\n for await (const event of subscriber.queue) {\n yield event;\n }\n } finally {\n if (options.signal) {\n options.signal.removeEventListener(\"abort\", abortHandler);\n }\n abortHandler();\n }\n }\n\n async register(\n webhook: HookWebhookRegistration,\n ): Promise<Result<HookWebhookRecord>> {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"hooks\"));\n }\n\n if (typeof webhook.secret !== \"string\" || webhook.secret.trim().length === 0) {\n return err(\n serviceError(\n ErrorCodes.INVALID_INPUT,\n \"Webhook secret is required\",\n \"hooks\",\n { meta: { field: \"secret\" } },\n ),\n );\n }\n\n try {\n const response = await this.context.fetch(`${this.host}/hooks/webhooks`, {\n method: \"POST\",\n headers: {\n ...serviceHeadersToRecord(\n this.createHookHeaders(\n \"tinycloud.hooks/register\",\n buildScopePath(webhook.service, webhook.pathPrefix),\n ),\n ),\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n space: webhook.space,\n service: webhook.service,\n pathPrefix: normalizePathPrefix(webhook.pathPrefix),\n abilities: webhook.abilities ?? [],\n callbackUrl: webhook.callbackUrl,\n secret: webhook.secret,\n }),\n });\n\n if (!response.ok) {\n return err(\n await responseError(\"hooks\", \"failed to register webhook\", response),\n );\n }\n\n const data = normalizeWebhookRecord(await response.json());\n if (!data) {\n return err(\n wrapError(\n \"hooks\",\n new Error(\"Webhook registration response did not include a record\"),\n ),\n );\n }\n\n return ok(data);\n } catch (error) {\n return err(wrapError(\"hooks\", error));\n }\n }\n\n async list(\n options: HookWebhookListOptions = {},\n ): Promise<Result<HookWebhookRecord[]>> {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"hooks\"));\n }\n\n try {\n const query = new URLSearchParams();\n if (options.space) {\n query.set(\"space\", options.space);\n }\n if (options.service) {\n query.set(\"service\", options.service);\n }\n if (options.pathPrefix) {\n const normalizedPrefix = normalizePathPrefix(options.pathPrefix);\n if (normalizedPrefix) {\n query.set(\"prefix\", normalizedPrefix);\n }\n }\n\n const response = await this.context.fetch(\n `${this.host}/hooks/webhooks${query.size > 0 ? `?${query.toString()}` : \"\"}`,\n {\n method: \"GET\",\n headers: serviceHeadersToRecord(\n this.createHookHeaders(\n \"tinycloud.hooks/list\",\n options.service\n ? buildScopePath(options.service, options.pathPrefix)\n : \"webhooks\",\n ),\n ),\n },\n );\n\n if (!response.ok) {\n return err(\n await responseError(\"hooks\", \"failed to list webhooks\", response),\n );\n }\n\n const payload = await response.json();\n const records = normalizeWebhookRecordList(payload);\n if (!records) {\n return err(\n wrapError(\n \"hooks\",\n new Error(\"Webhook list response did not include records\"),\n ),\n );\n }\n\n return ok(records);\n } catch (error) {\n return err(wrapError(\"hooks\", error));\n }\n }\n\n async unregister(\n id: string,\n options: HookWebhookUnregisterOptions = {},\n ): Promise<Result<void>> {\n if (!this.requireAuth()) {\n return err(authRequiredError(\"hooks\"));\n }\n\n try {\n const response = await this.context.fetch(\n `${this.host}/hooks/webhooks/${encodeURIComponent(id)}`,\n {\n method: \"DELETE\",\n headers: serviceHeadersToRecord(\n this.createHookHeaders(\n \"tinycloud.hooks/unregister\",\n options.target\n ? buildScopePath(\n options.target.service,\n options.target.pathPrefix,\n )\n : `webhooks/${id}`,\n ),\n ),\n },\n );\n\n if (!response.ok) {\n return err(\n await responseError(\n \"hooks\",\n \"failed to unregister webhook\",\n response,\n ),\n );\n }\n\n return ok(undefined);\n } catch (error) {\n return err(wrapError(\"hooks\", error));\n }\n }\n\n private async scheduleSharedStreamRefresh(): Promise<void> {\n this._refreshChain = this._refreshChain\n .then(() => this.refreshSharedStream())\n .catch(() => undefined);\n await this._refreshChain;\n }\n\n private async refreshSharedStream(): Promise<void> {\n if (!this.requireAuth() || this._subscribers.size === 0) {\n this.abortSharedStream();\n this._activeSignature = \"\";\n return;\n }\n\n const state = this.collectSharedStreamState();\n if (state.signature !== this._activeSignature) {\n this._activeSignature = state.signature;\n this.abortSharedStream();\n }\n\n if (!this._sharedStreamTask) {\n this._sharedStreamTask = this.runSharedStream(state)\n .catch((error: unknown) => {\n if (!isAbortError(error)) {\n throw error;\n }\n })\n .finally(() => {\n this._sharedStreamTask = undefined;\n this._sharedStreamAbort = undefined;\n if (this._subscribers.size > 0) {\n void this.scheduleSharedStreamRefresh();\n }\n });\n }\n }\n\n private collectSharedStreamState(): {\n subscriptions: HookSubscription[];\n ttlSeconds?: number;\n signature: string;\n } {\n const merged = new Map<string, HookSubscription>();\n const ttlCandidates: number[] = [];\n\n for (const subscriber of this._subscribers) {\n if (typeof subscriber.ttlSeconds === \"number\") {\n ttlCandidates.push(subscriber.ttlSeconds);\n }\n for (const subscription of subscriber.requested) {\n merged.set(subscriptionSignature(subscription), subscription);\n }\n }\n\n const subscriptions = [...merged.values()].sort((left, right) =>\n subscriptionSignature(left).localeCompare(subscriptionSignature(right)),\n );\n const ttlSeconds =\n ttlCandidates.length > 0 ? Math.min(...ttlCandidates) : undefined;\n const signature = JSON.stringify({\n subscriptions: subscriptions.map(subscriptionSignature),\n ttlSeconds,\n });\n\n return {\n subscriptions,\n ttlSeconds,\n signature,\n };\n }\n\n private async runSharedStream(state: {\n subscriptions: HookSubscription[];\n ttlSeconds?: number;\n }): Promise<void> {\n const abortController = new AbortController();\n this._sharedStreamAbort = abortController;\n\n try {\n const host = this._config.host ?? this.context.hosts[0];\n const ticketResponse = await this.mintHookTicket(\n state.subscriptions,\n state.ttlSeconds,\n abortController.signal,\n );\n const streamResponse = await this.openHookStream(\n host,\n ticketResponse.ticket,\n abortController.signal,\n );\n\n for await (const message of parseSseStream(\n streamResponse.body,\n abortController.signal,\n )) {\n if (!message.data) {\n continue;\n }\n const event = parseHookEvent(message);\n for (const subscriber of this._subscribers) {\n if (matchesAnySubscription(event, subscriber.requested)) {\n subscriber.queue.push(event);\n }\n }\n }\n } finally {\n if (this._sharedStreamAbort === abortController) {\n this._sharedStreamAbort = undefined;\n }\n }\n }\n\n private abortSharedStream(): void {\n this._sharedStreamAbort?.abort();\n }\n\n private createHookHeaders(action: string, path: string): ServiceHeaders {\n return this.context.invoke(this.session, \"hooks\", path, action);\n }\n\n private async mintHookTicket(\n subscriptions: HookSubscription[],\n ttlSeconds: number | undefined,\n signal?: AbortSignal,\n ): Promise<HookTicketResponse> {\n const host = this._config.host ?? this.context.hosts[0];\n const headers = this.createInvokeHeaders(subscriptions);\n const ticketResponse = await this.context.fetch(`${host}/hooks/tickets`, {\n method: \"POST\",\n headers: {\n ...serviceHeadersToRecord(headers),\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n subscriptions,\n ttlSeconds,\n }),\n signal,\n });\n\n if (!ticketResponse.ok) {\n throw await responseError(\n \"hooks\",\n \"failed to mint hook ticket\",\n ticketResponse,\n );\n }\n\n const ticketJson = (await ticketResponse.json()) as HookTicketResponse;\n if (!ticketJson?.ticket) {\n throw new Error(\"Hook ticket response did not include a ticket\");\n }\n\n return ticketJson;\n }\n\n private async openHookStream(\n host: string,\n ticket: string,\n signal?: AbortSignal,\n ): Promise<FetchResponse> {\n const streamResponse = await this.context.fetch(\n `${host}/hooks/events?ticket=${encodeURIComponent(ticket)}`,\n {\n method: \"GET\",\n headers: { accept: \"text/event-stream\" },\n signal,\n },\n );\n\n if (!streamResponse.ok) {\n throw await responseError(\n \"hooks\",\n \"failed to open hook stream\",\n streamResponse,\n );\n }\n\n return streamResponse;\n }\n\n private createInvokeHeaders(\n subscriptions: HookSubscription[],\n ): ServiceHeaders {\n const entries: InvokeAnyEntry[] = subscriptions.map((subscription) => ({\n spaceId: subscription.space,\n service: \"hooks\",\n path: subscription.pathPrefix\n ? `${subscription.service}/${subscription.pathPrefix}`\n : subscription.service,\n action: \"tinycloud.hooks/subscribe\",\n }));\n\n if (this.context.invokeAny) {\n return this.context.invokeAny(this.session, entries);\n }\n\n if (entries.length === 1) {\n const entry = entries[0];\n return this.context.invoke(\n this.session,\n entry.service,\n entry.path,\n entry.action,\n );\n }\n\n throw new Error(\n \"This SDK runtime does not support multi-scope hook invocations\",\n );\n }\n}\n\nfunction buildScopePath(\n service: HookSubscription[\"service\"],\n pathPrefix?: string,\n): string {\n const normalized = normalizePathPrefix(pathPrefix);\n return normalized ? `${service}/${normalized}` : service;\n}\n\nfunction normalizeSubscription(\n subscription: HookSubscription,\n): HookSubscription {\n return {\n ...subscription,\n pathPrefix: normalizePathPrefix(subscription.pathPrefix),\n abilities: subscription.abilities ?? [],\n };\n}\n\nfunction subscriptionSignature(subscription: HookSubscription): string {\n return JSON.stringify({\n space: subscription.space,\n service: subscription.service,\n pathPrefix: subscription.pathPrefix ?? \"\",\n abilities: [...(subscription.abilities ?? [])].sort(),\n });\n}\n\nfunction matchesAnySubscription(\n event: HookEvent,\n subscriptions: HookSubscription[],\n): boolean {\n return subscriptions.some((subscription) =>\n matchesSubscription(event, subscription),\n );\n}\n\nfunction matchesSubscription(\n event: HookEvent,\n subscription: HookSubscription,\n): boolean {\n if (event.space !== subscription.space) {\n return false;\n }\n if (event.service !== subscription.service) {\n return false;\n }\n if (subscription.pathPrefix) {\n const prefix = subscription.pathPrefix.endsWith(\"/\")\n ? subscription.pathPrefix\n : `${subscription.pathPrefix}/`;\n if (\n event.path &&\n event.path !== subscription.pathPrefix &&\n !event.path.startsWith(prefix)\n ) {\n return false;\n }\n }\n const abilities = subscription.abilities ?? [];\n if (abilities.length > 0 && !abilities.includes(event.ability)) {\n return false;\n }\n return true;\n}\n\nfunction normalizePathPrefix(pathPrefix?: string): string | undefined {\n if (!pathPrefix) {\n return undefined;\n }\n const trimmed = pathPrefix.replace(/^\\/+|\\/+$/g, \"\");\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction serviceHeadersToRecord(\n headers: ServiceHeaders,\n): Record<string, string> {\n if (Array.isArray(headers)) {\n return Object.fromEntries(headers);\n }\n return { ...headers };\n}\n\nasync function responseError(\n service: string,\n message: string,\n response: FetchResponse,\n): Promise<ReturnType<typeof wrapError>> {\n let detail = response.statusText;\n try {\n const text = await response.text();\n if (text) {\n detail = text;\n }\n } catch {\n // Ignore secondary body read failure.\n }\n return wrapError(\n service,\n new Error(`${message}: ${response.status} ${detail}`),\n );\n}\n\nfunction isAbortError(error: unknown): boolean {\n return error instanceof DOMException && error.name === \"AbortError\";\n}\n\nasync function* parseSseStream(\n body: unknown,\n signal?: AbortSignal,\n): AsyncIterable<HookStreamEvent> {\n if (!body) {\n throw new Error(\"Hook stream response does not expose a readable body\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n for await (const chunk of readBodyChunks(body, signal)) {\n buffer += decoder.decode(chunk, { stream: true }).replace(/\\r\\n/g, \"\\n\");\n\n let separatorIndex = buffer.indexOf(\"\\n\\n\");\n while (separatorIndex >= 0) {\n const rawEvent = buffer.slice(0, separatorIndex);\n buffer = buffer.slice(separatorIndex + 2);\n const parsed = parseSseEvent(rawEvent);\n if (parsed) {\n yield parsed;\n }\n separatorIndex = buffer.indexOf(\"\\n\\n\");\n }\n }\n\n buffer += decoder.decode();\n const trailing = parseSseEvent(buffer.trim());\n if (trailing) {\n yield trailing;\n }\n}\n\nasync function* readBodyChunks(\n body: unknown,\n signal?: AbortSignal,\n): AsyncIterable<Uint8Array> {\n const asyncIterable = body as AsyncIterable<Uint8Array>;\n if (typeof asyncIterable?.[Symbol.asyncIterator] === \"function\") {\n for await (const chunk of asyncIterable) {\n if (signal?.aborted) {\n break;\n }\n yield chunk;\n }\n return;\n }\n\n const stream = body as {\n getReader?: () => {\n read: () => Promise<{ done: boolean; value?: Uint8Array }>;\n releaseLock?: () => void;\n cancel?: () => Promise<void>;\n };\n };\n\n if (typeof stream.getReader !== \"function\") {\n throw new Error(\"Unsupported hook stream body type\");\n }\n\n const reader = stream.getReader();\n try {\n while (!signal?.aborted) {\n const { done, value } = await reader.read();\n if (done) {\n break;\n }\n if (value) {\n yield value;\n }\n }\n } finally {\n try {\n await reader.cancel?.();\n } catch {\n // Ignore cancellation failures.\n }\n reader.releaseLock?.();\n }\n}\n\nfunction parseSseEvent(rawEvent: string): HookStreamEvent | null {\n if (!rawEvent) {\n return null;\n }\n\n let event = \"message\";\n let id: string | undefined;\n const dataLines: string[] = [];\n\n for (const line of rawEvent.split(\"\\n\")) {\n if (!line || line.startsWith(\":\")) {\n continue;\n }\n const [field, ...rest] = line.split(\":\");\n const value = rest.join(\":\").replace(/^ /, \"\");\n switch (field) {\n case \"event\":\n event = value;\n break;\n case \"id\":\n id = value;\n break;\n case \"data\":\n dataLines.push(value);\n break;\n default:\n break;\n }\n }\n\n if (dataLines.length === 0) {\n return null;\n }\n\n return {\n event,\n id,\n data: dataLines.join(\"\\n\"),\n };\n}\n\nfunction parseHookEvent(message: HookStreamEvent): HookEvent {\n const parsed = JSON.parse(message.data) as Partial<HookEvent>;\n return {\n type: \"write\",\n id: parsed.id ?? message.id ?? \"\",\n space: parsed.space ?? \"\",\n service: parsed.service ?? \"\",\n ability: parsed.ability ?? \"\",\n path: parsed.path,\n actor: parsed.actor ?? \"\",\n epoch: parsed.epoch ?? \"\",\n eventIndex: parsed.eventIndex ?? 0,\n timestamp: parsed.timestamp ?? \"\",\n };\n}\n\nfunction normalizeWebhookRecord(data: unknown): HookWebhookRecord | null {\n if (!data || typeof data !== \"object\") {\n return null;\n }\n\n const record = isRecordContainer(data);\n const candidate =\n pickWebhookRecord(record) ??\n normalizeWebhookRecord(record.webhook) ??\n normalizeWebhookRecord(record.hook) ??\n normalizeWebhookRecord(record.subscription) ??\n normalizeWebhookRecord(record.data);\n return candidate ?? null;\n}\n\nfunction normalizeWebhookRecordList(data: unknown): HookWebhookRecord[] | null {\n if (Array.isArray(data)) {\n const records = data\n .map((entry) => normalizeWebhookRecord(entry))\n .filter((entry): entry is HookWebhookRecord => entry !== null);\n return records;\n }\n\n if (!data || typeof data !== \"object\") {\n return null;\n }\n\n const record = isRecordContainer(data);\n const nested =\n maybeRecordArray(record.webhooks) ??\n maybeRecordArray(record.subscriptions) ??\n maybeRecordArray(record.hooks) ??\n maybeRecordArray(record.data);\n if (nested) {\n return nested;\n }\n\n const single = pickWebhookRecord(record);\n return single ? [single] : null;\n}\n\nfunction maybeRecordArray(value: unknown): HookWebhookRecord[] | null {\n if (!Array.isArray(value)) {\n return null;\n }\n\n const records = value\n .map((entry) => normalizeWebhookRecord(entry))\n .filter((entry): entry is HookWebhookRecord => entry !== null);\n return records;\n}\n\nfunction pickWebhookRecord(\n value: Record<string, unknown>,\n): HookWebhookRecord | null {\n const id = stringField(value, \"id\");\n const space = stringField(value, \"space\") ?? stringField(value, \"spaceId\");\n const service = stringField(value, \"service\");\n const callbackUrl =\n stringField(value, \"callbackUrl\") ?? stringField(value, \"callback_url\");\n if (!id || !space || !service || !callbackUrl) {\n return null;\n }\n\n return {\n id,\n space,\n service: service as HookWebhookRecord[\"service\"],\n pathPrefix:\n optionalStringField(value, \"pathPrefix\") ??\n optionalStringField(value, \"path_prefix\"),\n abilities:\n stringArrayField(value, \"abilities\") ??\n parsedStringArrayField(value, \"abilitiesJson\") ??\n parsedStringArrayField(value, \"abilities_json\"),\n callbackUrl,\n active: booleanField(value, \"active\") ?? true,\n createdAt:\n stringField(value, \"createdAt\") ??\n stringField(value, \"created_at\") ??\n new Date().toISOString(),\n subscriberDid:\n optionalStringField(value, \"subscriberDid\") ??\n optionalStringField(value, \"subscriber_did\"),\n };\n}\n\nfunction isRecordContainer(value: object): Record<string, unknown> {\n return value as Record<string, unknown>;\n}\n\nfunction stringField(\n value: Record<string, unknown>,\n key: string,\n): string | undefined {\n const field = value[key];\n return typeof field === \"string\" ? field : undefined;\n}\n\nfunction optionalStringField(\n value: Record<string, unknown>,\n key: string,\n): string | undefined {\n return stringField(value, key);\n}\n\nfunction booleanField(\n value: Record<string, unknown>,\n key: string,\n): boolean | undefined {\n const field = value[key];\n return typeof field === \"boolean\" ? field : undefined;\n}\n\nfunction stringArrayField(\n value: Record<string, unknown>,\n key: string,\n): string[] | undefined {\n const field = value[key];\n if (!Array.isArray(field)) {\n return undefined;\n }\n const strings = field.filter(\n (item): item is string => typeof item === \"string\",\n );\n return strings.length === field.length ? strings : undefined;\n}\n\nfunction parsedStringArrayField(\n value: Record<string, unknown>,\n key: string,\n): string[] | undefined {\n const field = value[key];\n if (typeof field !== \"string\") {\n return undefined;\n }\n\n try {\n const parsed = JSON.parse(field) as unknown;\n if (!Array.isArray(parsed)) {\n return undefined;\n }\n const strings = parsed.filter(\n (item): item is string => typeof item === \"string\",\n );\n return strings.length === parsed.length ? strings : undefined;\n } catch {\n return undefined;\n }\n}\n","import type { StorageQuotaInfo } from \"../types\";\n\nexport interface QuotaConfig {\n /** Called when a storage quota error is detected (402/413) */\n onUpgradeRequired?: (info: StorageQuotaInfo) => void;\n}\n\nexport interface QuotaStatus {\n /** Storage limit in bytes for this space */\n limitBytes: number;\n /** Storage used in bytes for this space */\n usedBytes?: number;\n /** Remaining storage in bytes */\n remainingBytes?: number;\n}\n\nexport class TinyCloudQuota {\n private config: QuotaConfig;\n private quotaUrl: string | null = null;\n\n constructor(config: QuotaConfig = {}) {\n this.config = config;\n }\n\n /** Set the quota URL discovered from the /info endpoint */\n setQuotaUrl(url: string | null): void {\n this.quotaUrl = url;\n }\n\n /** Whether a quota service is available */\n get available(): boolean {\n return this.quotaUrl !== null;\n }\n\n /** Query quota status for a space from the quota URL */\n async getQuota(spaceId: string): Promise<QuotaStatus | null> {\n if (!this.quotaUrl) return null;\n\n const resp = await fetch(\n `${this.quotaUrl}/api/quota/${encodeURIComponent(spaceId)}`\n );\n if (!resp.ok) return null;\n\n const data = (await resp.json()) as { storage_limit_bytes?: number };\n return {\n limitBytes: data.storage_limit_bytes ?? 0,\n };\n }\n\n /** Trigger the upgrade callback when a quota error is encountered */\n handleQuotaError(info: StorageQuotaInfo): void {\n this.config.onUpgradeRequired?.(info);\n }\n}\n","/**\n * Data Vault Service Types\n *\n * Type definitions for the Data Vault (encrypted KV) service operations.\n */\n\n/**\n * Configuration for DataVaultService.\n */\nexport interface DataVaultConfig {\n /** Space ID for encrypted data storage */\n spaceId: string;\n /** Key rotation policy */\n keyRotation?: \"per-write\" | \"per-key\"; // default: \"per-write\"\n}\n\n/**\n * Options for vault put operations.\n */\nexport interface VaultPutOptions {\n /** Custom metadata tags appended to the envelope */\n metadata?: Record<string, string>;\n /** Content type hint for deserialization (default: auto-detect) */\n contentType?: string;\n /** Custom serializer (default: JSON.stringify for objects) */\n serialize?: (value: unknown) => Uint8Array;\n}\n\n/**\n * Options for vault get operations.\n */\nexport interface VaultGetOptions<T = unknown> {\n /** Custom deserializer (default: JSON.parse if content-type is JSON) */\n deserialize?: (data: Uint8Array) => T;\n /** Return raw decrypted bytes without deserialization */\n raw?: boolean;\n /** Delegated KV service for reading from the grantor's space (used by getShared) */\n kv?: { get<V>(key: string, options?: { raw?: boolean }): Promise<{ ok: boolean; data?: { data: V }; error?: { message: string } }> };\n}\n\n/**\n * Options for vault list operations.\n */\nexport interface VaultListOptions {\n /** Prefix filter for key names */\n prefix?: string;\n /** Remove prefix from returned keys */\n removePrefix?: boolean;\n}\n\n/**\n * Options for vault grant (sharing) operations.\n */\nexport interface VaultGrantOptions {\n /** Additional metadata on the grant */\n metadata?: Record<string, string>;\n}\n\n/**\n * A decrypted vault entry returned by get operations.\n *\n * @template T - Type of the decrypted value\n */\nexport interface VaultEntry<T> {\n /** Decrypted value */\n value: T;\n /** Envelope metadata */\n metadata: Record<string, string>;\n /** Key ID used for encryption */\n keyId: string;\n}\n\n/**\n * Structured error codes for vault operations.\n */\n/**\n * Input types for creating vault errors (service field added automatically).\n */\nexport type VaultErrorInput =\n | { code: \"DECRYPTION_FAILED\"; message?: string; cause?: Error }\n | { code: \"KEY_NOT_FOUND\"; key: string; message?: string }\n | { code: \"INTEGRITY_ERROR\"; message?: string; cause?: Error }\n | { code: \"GRANT_NOT_FOUND\"; grantor: string; key: string; message?: string }\n | { code: \"VAULT_LOCKED\"; message?: string }\n | { code: \"PUBLIC_KEY_NOT_FOUND\"; did: string; message?: string }\n | { code: \"STORAGE_ERROR\"; cause: Error; message?: string };\n\n/**\n * Vault error with service field (compatible with ServiceError).\n */\nexport type VaultError = VaultErrorInput & { service: \"vault\"; message: string };\n\n\n/** KV actions the vault needs on the public space for key publishing. */\nexport const VaultPublicSpaceKVActions = [\n \"tinycloud.kv/get\",\n \"tinycloud.kv/put\",\n \"tinycloud.kv/metadata\",\n] as const;\n\n/** Version-keyed signing message configuration for vault key derivation. */\nexport const VaultVersionConfig = {\n \"1\": {\n masterMessage: (spaceId: string) => `tinycloud-vault-master-v1:${spaceId}`,\n identityMessage: \"tinycloud-encryption-identity-v1\",\n },\n} as const;\n\nexport const CURRENT_VAULT_VERSION = \"1\" as const;\n\n/** Metadata header keys used in vault envelopes */\nexport const VaultHeaders = {\n VERSION: \"x-vault-version\",\n CIPHER: \"x-vault-cipher\",\n KEY_ID: \"x-vault-key-id\",\n CONTENT_TYPE: \"x-vault-content-type\",\n KDF: \"x-vault-kdf\",\n KEY_ROTATION: \"x-vault-key-rotation\",\n GRANT_VERSION: \"x-vault-grant-version\",\n GRANTOR: \"x-vault-grantor\",\n} as const;\n","/**\n * Caches vault signatures in IndexedDB, encrypted with a\n * non-extractable CryptoKey. Browser-only — no-ops in Node.\n */\n\n// Minimal type declarations for browser APIs used below.\n// The sdk-services tsconfig targets ES2020 without DOM lib;\n// these declarations let the file compile while the runtime\n// guards (isBrowser()) ensure we never call them in Node.\ndeclare const indexedDB: {\n open(name: string, version?: number): IDBOpenDBRequest;\n};\ninterface IDBOpenDBRequest {\n result: IDBDatabase;\n error: DOMException | null;\n onupgradeneeded: ((this: IDBOpenDBRequest) => void) | null;\n onsuccess: ((this: IDBOpenDBRequest) => void) | null;\n onerror: ((this: IDBOpenDBRequest) => void) | null;\n}\ninterface IDBDatabase {\n objectStoreNames: { contains(name: string): boolean };\n createObjectStore(name: string): void;\n transaction(storeNames: string | string[], mode?: string): IDBTransaction;\n}\ninterface IDBTransaction {\n objectStore(name: string): IDBObjectStore;\n}\ninterface IDBObjectStore {\n get(key: string): IDBRequest;\n put(value: unknown, key: string): IDBRequest;\n delete(key: string): IDBRequest;\n getAllKeys(): IDBRequest;\n}\ninterface IDBRequest<T = unknown> {\n result: T;\n error: DOMException | null;\n onsuccess: ((this: IDBRequest<T>) => void) | null;\n onerror: ((this: IDBRequest<T>) => void) | null;\n}\ntype IDBValidKey = string | number | Date | ArrayBuffer | Uint8Array | IDBValidKey[];\n\nconst DB_NAME = \"tinycloud-vault-cache\";\nconst DB_VERSION = 1;\nconst STORE_NAME = \"signatures\";\nconst WRAP_KEY_ID = \"__wrap_key__\";\n\n/** Check whether we're in a browser with IndexedDB + SubtleCrypto support. */\nfunction isBrowser(): boolean {\n try {\n return (\n typeof indexedDB !== \"undefined\" &&\n typeof crypto !== \"undefined\" &&\n typeof crypto.subtle !== \"undefined\"\n );\n } catch {\n return false;\n }\n}\n\n/** Open (or create) the IndexedDB database. */\nfunction openDB(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(DB_NAME, DB_VERSION);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(STORE_NAME)) {\n db.createObjectStore(STORE_NAME);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n\n/** Generic IDB get helper. */\nfunction idbGet<T>(db: IDBDatabase, key: string): Promise<T | undefined> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, \"readonly\");\n const store = tx.objectStore(STORE_NAME);\n const req = store.get(key);\n req.onsuccess = () => resolve(req.result as T | undefined);\n req.onerror = () => reject(req.error);\n });\n}\n\n/** Generic IDB put helper. */\nfunction idbPut(db: IDBDatabase, key: string, value: unknown): Promise<void> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, \"readwrite\");\n const store = tx.objectStore(STORE_NAME);\n const req = store.put(value, key);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n });\n}\n\n/** Generic IDB delete helper. */\nfunction idbDelete(db: IDBDatabase, key: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, \"readwrite\");\n const store = tx.objectStore(STORE_NAME);\n const req = store.delete(key);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n });\n}\n\n/** List all keys in the store. */\nfunction idbKeys(db: IDBDatabase): Promise<string[]> {\n return new Promise((resolve, reject) => {\n const tx = db.transaction(STORE_NAME, \"readonly\");\n const store = tx.objectStore(STORE_NAME);\n const req = store.getAllKeys();\n req.onsuccess = () =>\n resolve((req.result as IDBValidKey[]).filter((k) => typeof k === \"string\") as string[]);\n req.onerror = () => reject(req.error);\n });\n}\n\ninterface EncryptedEntry {\n iv: Uint8Array;\n ciphertext: Uint8Array;\n}\n\n/**\n * Get or create the non-extractable AES-GCM wrapping key.\n * The key is stored directly in IndexedDB (structured-clone preserves CryptoKey).\n */\nasync function getWrapKey(db: IDBDatabase): Promise<CryptoKey> {\n const existing = await idbGet<CryptoKey>(db, WRAP_KEY_ID);\n if (existing) return existing;\n\n const key = await crypto.subtle.generateKey(\n { name: \"AES-GCM\", length: 256 },\n false, // non-extractable\n [\"encrypt\", \"decrypt\"]\n );\n await idbPut(db, WRAP_KEY_ID, key);\n return key;\n}\n\n/** Encrypt signature bytes with the wrap key. */\nasync function encryptSig(\n wrapKey: CryptoKey,\n sigBytes: Uint8Array\n): Promise<EncryptedEntry> {\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const ciphertext = new Uint8Array(\n await crypto.subtle.encrypt({ name: \"AES-GCM\", iv }, wrapKey, sigBytes)\n );\n return { iv, ciphertext };\n}\n\n/** Decrypt an encrypted entry back to signature bytes. */\nasync function decryptSig(\n wrapKey: CryptoKey,\n entry: EncryptedEntry\n): Promise<Uint8Array> {\n const plaintext = await crypto.subtle.decrypt(\n { name: \"AES-GCM\", iv: entry.iv },\n wrapKey,\n entry.ciphertext\n );\n return new Uint8Array(plaintext);\n}\n\n/** Cache key for a given spaceId. */\nfunction cacheKey(spaceId: string): string {\n return `sig:${spaceId}`;\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Load a cached signature for the given spaceId.\n * Returns null on cache miss or in non-browser environments.\n */\nexport async function loadCachedSignature(\n spaceId: string\n): Promise<Uint8Array | null> {\n if (!isBrowser()) return null;\n try {\n const db = await openDB();\n const entry = await idbGet<EncryptedEntry>(db, cacheKey(spaceId));\n if (!entry) return null;\n const wrapKey = await getWrapKey(db);\n return await decryptSig(wrapKey, entry);\n } catch {\n return null;\n }\n}\n\n/**\n * Cache a signature for the given spaceId.\n * No-ops in non-browser environments.\n */\nexport async function cacheSignature(\n spaceId: string,\n sigBytes: Uint8Array\n): Promise<void> {\n if (!isBrowser()) return;\n try {\n const db = await openDB();\n const wrapKey = await getWrapKey(db);\n const encrypted = await encryptSig(wrapKey, sigBytes);\n await idbPut(db, cacheKey(spaceId), encrypted);\n } catch {\n // Best-effort — swallow errors\n }\n}\n\n/**\n * Clear cached signature(s).\n * If spaceId is provided, clears only that entry; otherwise clears all.\n */\nexport async function clearSignatureCache(\n spaceId?: string\n): Promise<void> {\n if (!isBrowser()) return;\n try {\n const db = await openDB();\n if (spaceId) {\n await idbDelete(db, cacheKey(spaceId));\n } else {\n // Clear all sig entries but keep the wrap key\n const keys = await idbKeys(db);\n for (const k of keys) {\n if (k.startsWith(\"sig:\")) {\n await idbDelete(db, k);\n }\n }\n }\n } catch {\n // Best-effort\n }\n}\n","/**\n * DataVaultService - Encrypted key-value storage service implementation.\n *\n * Platform-agnostic encrypted KV service that wraps KVService internally.\n * Uses dependency injection via VaultCrypto for WASM crypto operations\n * and DataVaultServiceConfig for platform dependencies.\n *\n * Architecture:\n * - Extends BaseService (not KVService)\n * - Wraps two KV instances: dataKV (prefix \"vault/\") and keyKV (prefix \"keys/\")\n * - Master key and encryption identity live in memory only (cleared on lock)\n */\n\nimport { BaseService } from \"../base/BaseService\";\nimport {\n Result,\n ok,\n err,\n serviceError,\n IServiceContext,\n ServiceSession,\n} from \"../types\";\nimport { wrapError } from \"../errors\";\nimport type { IKVService } from \"../kv/IKVService\";\nimport type { KVService } from \"../kv/KVService\";\nimport type { IDataVaultService } from \"./IDataVaultService\";\nimport {\n DataVaultConfig,\n VaultPutOptions,\n VaultGetOptions,\n VaultListOptions,\n VaultGrantOptions,\n VaultEntry,\n VaultError,\n VaultErrorInput,\n VaultHeaders,\n VaultVersionConfig,\n CURRENT_VAULT_VERSION,\n} from \"./types\";\nimport {\n loadCachedSignature,\n cacheSignature,\n clearSignatureCache,\n} from \"./SignatureCache\";\n\n// =============================================================================\n// Crypto Interface\n// =============================================================================\n\n/**\n * Crypto operations interface - implementations provided by WASM bindings.\n * Passed via DataVaultServiceConfig to keep the service platform-agnostic.\n */\nexport interface VaultCrypto {\n encrypt(key: Uint8Array, plaintext: Uint8Array): Uint8Array;\n decrypt(key: Uint8Array, blob: Uint8Array): Uint8Array;\n deriveKey(\n signature: Uint8Array,\n salt: Uint8Array,\n info: Uint8Array\n ): Uint8Array;\n x25519FromSeed(\n seed: Uint8Array\n ): { publicKey: Uint8Array; privateKey: Uint8Array };\n x25519Dh(privateKey: Uint8Array, publicKey: Uint8Array): Uint8Array;\n randomBytes(length: number): Uint8Array;\n sha256(data: Uint8Array): Uint8Array;\n}\n\n// =============================================================================\n// Extended Config\n// =============================================================================\n\n/**\n * Extended config used internally by DataVaultService.\n * Includes crypto operations and TinyCloud instance references.\n */\ninterface DataVaultServiceConfig extends DataVaultConfig {\n [key: string]: unknown;\n /** Crypto operations (WASM bindings) */\n crypto: VaultCrypto;\n /** TinyCloud instance for space/kv/delegation operations */\n tc: {\n kv: IKVService;\n ensurePublicSpace(): Promise<Result<void>>;\n publicKV: IKVService;\n readPublicSpace<T>(\n host: string,\n spaceId: string,\n key: string\n ): Promise<Result<T>>;\n makePublicSpaceId(address: string, chainId: number): string;\n did: string;\n address: string;\n chainId: number;\n hosts: string[];\n };\n}\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/** Convert a caught value to an Error. WASM throws plain objects, not Error instances. */\nfunction toError(error: unknown): Error {\n if (error instanceof Error) return error;\n if (typeof error === \"object\" && error !== null) {\n return new Error(JSON.stringify(error));\n }\n return new Error(String(error));\n}\n\nfunction toBytes(str: string): Uint8Array {\n return new TextEncoder().encode(str);\n}\n\nfunction fromBytes(bytes: Uint8Array): string {\n return new TextDecoder().decode(bytes);\n}\n\nfunction hexEncode(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nfunction concatBytes(...arrays: Uint8Array[]): Uint8Array {\n const total = arrays.reduce((acc, arr) => acc + arr.length, 0);\n const result = new Uint8Array(total);\n let offset = 0;\n for (const arr of arrays) {\n result.set(arr, offset);\n offset += arr.length;\n }\n return result;\n}\n\nfunction base64Encode(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\nfunction base64Decode(str: string): Uint8Array {\n const binary = atob(str);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n\nfunction defaultVaultMessage(input: VaultErrorInput): string {\n switch (input.code) {\n case \"DECRYPTION_FAILED\": return input.message ?? \"Decryption failed\";\n case \"KEY_NOT_FOUND\": return input.message ?? `Key not found: ${input.key}`;\n case \"INTEGRITY_ERROR\": return input.message ?? \"Integrity check failed\";\n case \"GRANT_NOT_FOUND\": return input.message ?? `Grant not found: ${input.grantor} / ${input.key}`;\n case \"VAULT_LOCKED\": return input.message ?? \"Vault is locked\";\n case \"PUBLIC_KEY_NOT_FOUND\": return input.message ?? `Public key not found for ${input.did}`;\n case \"STORAGE_ERROR\": return input.message ?? input.cause.message;\n }\n}\n\nfunction vaultError(input: VaultErrorInput): Result<never, VaultError> {\n const error: VaultError = {\n ...input,\n service: \"vault\",\n message: defaultVaultMessage(input),\n };\n return { ok: false, error };\n}\n\n// =============================================================================\n// DataVaultService\n// =============================================================================\n\n/**\n * Data Vault service implementation.\n *\n * Provides encrypted key-value storage with client-side encryption,\n * key management, and sharing via X25519 grants.\n *\n * @example\n * ```typescript\n * // Unlock the vault\n * await vault.unlock(signer);\n *\n * // Store encrypted data\n * await vault.put('secret/notes', { content: 'Hello' });\n *\n * // Retrieve and decrypt\n * const entry = await vault.get<{ content: string }>('secret/notes');\n * if (entry.ok) {\n * console.log(entry.data.value.content); // 'Hello'\n * }\n *\n * // Share with another user\n * await vault.grant('secret/notes', recipientDID);\n * ```\n */\nexport class DataVaultService extends BaseService implements IDataVaultService {\n /**\n * Service identifier for registration.\n */\n static readonly serviceName = \"vault\";\n\n /**\n * Service configuration.\n */\n declare protected _config: DataVaultServiceConfig;\n\n private masterKey: Uint8Array | null = null;\n private encryptionIdentity: {\n publicKey: Uint8Array;\n privateKey: Uint8Array;\n } | null = null;\n private _isUnlocked = false;\n private vaultConfig: DataVaultServiceConfig;\n\n /**\n * Create a new DataVaultService instance.\n *\n * @param config - Service configuration including crypto and tc references\n */\n constructor(config: DataVaultServiceConfig) {\n super();\n this.vaultConfig = config;\n this._config = config;\n }\n\n /**\n * Get the service configuration.\n */\n get config(): DataVaultServiceConfig {\n return this._config;\n }\n\n /**\n * Whether the vault is currently unlocked.\n */\n get isUnlocked(): boolean {\n return this._isUnlocked;\n }\n\n /**\n * The vault's public encryption key (X25519).\n * Throws if vault is locked.\n */\n get publicKey(): Uint8Array {\n if (!this.encryptionIdentity) {\n throw new Error(\"Vault is locked\");\n }\n return this.encryptionIdentity.publicKey;\n }\n\n /**\n * Convenience accessor for crypto operations.\n */\n private get crypto(): VaultCrypto {\n return this.vaultConfig.crypto;\n }\n\n /**\n * Convenience accessor for TinyCloud instance.\n */\n private get tc() {\n return this.vaultConfig.tc;\n }\n\n /**\n * Get the host URL.\n */\n private get host(): string {\n return this.tc.hosts[0];\n }\n\n // =========================================================================\n // Phase 1: Core Operations\n // =========================================================================\n\n /**\n * Unlock the vault. Derives keys from two wallet signatures:\n * 1. Master signature (per-space) — used to derive the master encryption key\n * 2. Identity signature (per-address) — used to derive X25519 encryption identity\n *\n * If the identity public key already exists in the public space, the identity\n * signature is skipped entirely (no wallet popup). The identity private key is\n * only needed for sharing operations.\n *\n * @param signer - Object with signMessage method. Optional when cached\n * signatures exist (browser only).\n */\n async unlock(\n signer?: { signMessage(message: string): Promise<string> } | unknown\n ): Promise<Result<void, VaultError>> {\n return this.withTelemetry(\"unlock\", undefined, async () => {\n const spaceId = this.vaultConfig.spaceId;\n const versionConfig = VaultVersionConfig[CURRENT_VAULT_VERSION];\n const masterCacheKey = `vault-master:${spaceId}`;\n const identityCacheKey = `vault-identity:${this.tc.address}`;\n\n try {\n // -----------------------------------------------------------------\n // Step 1: Master signature → master key\n // -----------------------------------------------------------------\n let masterSigBytes = await loadCachedSignature(masterCacheKey);\n\n if (!masterSigBytes) {\n if (!signer) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Signer is required when no cached master signature exists\",\n });\n }\n const s = signer as { signMessage(message: string): Promise<string> };\n const sig = await s.signMessage(versionConfig.masterMessage(spaceId));\n masterSigBytes = toBytes(sig);\n await cacheSignature(masterCacheKey, masterSigBytes);\n }\n\n // Derive master key: deriveKey(sigBytes, sha256(spaceId), \"vault-master\")\n this.masterKey = this.crypto.deriveKey(\n masterSigBytes,\n this.crypto.sha256(toBytes(spaceId)),\n toBytes(\"vault-master\")\n );\n\n // -----------------------------------------------------------------\n // Step 2: Identity — check public space first, then sign if needed\n // -----------------------------------------------------------------\n const publicSpaceId = this.tc.makePublicSpaceId(this.tc.address, this.tc.chainId);\n\n // Check public space for existing vault pubkey\n let existingPubKey: string | null = null;\n try {\n const existing = await this.tc.readPublicSpace<string>(\n this.host, publicSpaceId, \".well-known/vault-pubkey\"\n );\n if (existing.ok && existing.data) {\n existingPubKey = existing.data as string;\n }\n } catch {\n // Read failed — treat as missing\n }\n\n if (existingPubKey) {\n // Public key exists — trust it, skip identity signing entirely\n this.encryptionIdentity = {\n publicKey: base64Decode(existingPubKey),\n privateKey: new Uint8Array(0), // private key not available without signing\n };\n } else {\n // Public key missing — need identity signature to derive keypair\n let identitySigBytes = await loadCachedSignature(identityCacheKey);\n\n if (!identitySigBytes) {\n if (!signer) {\n // No signer available — skip identity derivation.\n // Vault still works for get/put (only needs master key).\n this.encryptionIdentity = null;\n this._isUnlocked = true;\n return ok(undefined);\n }\n const s = signer as { signMessage(message: string): Promise<string> };\n const sig = await s.signMessage(versionConfig.identityMessage);\n identitySigBytes = toBytes(sig);\n await cacheSignature(identityCacheKey, identitySigBytes);\n }\n\n // Derive X25519 keypair from identity signature\n const seed = this.crypto.deriveKey(\n identitySigBytes,\n toBytes(\"tinycloud-x25519\"),\n toBytes(\"encryption-identity\")\n );\n this.encryptionIdentity = this.crypto.x25519FromSeed(seed);\n\n // Publish public key to public space\n try {\n const pubKeyB64 = base64Encode(this.encryptionIdentity.publicKey);\n await this.tc.ensurePublicSpace();\n await this.tc.publicKV.put(\".well-known/vault-pubkey\", pubKeyB64);\n await this.tc.publicKV.put(\".well-known/vault-version\", CURRENT_VAULT_VERSION);\n await this.tc.publicKV.put(\".well-known/vault-space\", this.vaultConfig.spaceId);\n } catch {\n // Publishing failed — vault still usable\n }\n }\n\n this._isUnlocked = true;\n return ok(undefined);\n } catch (error) {\n // Clear key material on failure\n this.masterKey = null;\n this.encryptionIdentity = null;\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<void, VaultError>>;\n }\n\n /**\n * Clear the cached vault signatures.\n *\n * @param spaceId - Clear only this space's master cache. If omitted, clears all.\n */\n async clearCache(spaceId?: string): Promise<void> {\n if (spaceId) {\n await clearSignatureCache(`vault-master:${spaceId}`);\n } else {\n await clearSignatureCache();\n }\n }\n\n /**\n * Lock the vault, clearing all key material from memory.\n */\n lock(): void {\n this.masterKey = null;\n this.encryptionIdentity = null;\n this._isUnlocked = false;\n }\n\n /**\n * Called when SDK signs out. Locks the vault and aborts operations.\n */\n onSignOut(): void {\n this.lock();\n super.onSignOut();\n }\n\n /**\n * Encrypt and store a value at the given key.\n *\n * @param key - The key to store under\n * @param value - The value to encrypt and store\n * @param options - Optional put configuration\n */\n async put(\n key: string,\n value: unknown,\n options?: VaultPutOptions\n ): Promise<Result<void, VaultError>> {\n return this.withTelemetry(\"put\", key, async () => {\n if (!this._isUnlocked || !this.masterKey) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before storing data\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Serialize value\n let plaintext: Uint8Array;\n if (value instanceof Uint8Array) {\n plaintext = value;\n } else if (options?.serialize) {\n plaintext = options.serialize(value);\n } else if (typeof value === \"string\") {\n plaintext = toBytes(value);\n } else {\n plaintext = toBytes(JSON.stringify(value));\n }\n\n const contentType =\n options?.contentType ??\n (value instanceof Uint8Array\n ? \"application/octet-stream\"\n : \"application/json\");\n\n // Generate per-entry key\n const entryKey = this.crypto.randomBytes(32);\n const keyId = hexEncode(this.crypto.sha256(entryKey)).slice(0, 16);\n\n // Encrypt value with entry key\n const encrypted = this.crypto.encrypt(entryKey, plaintext);\n\n // Encrypt entry key with master key\n const keyBlob = this.crypto.encrypt(this.masterKey, entryKey);\n\n // Build metadata\n const metadata: Record<string, string> = {\n [VaultHeaders.VERSION]: \"1\",\n [VaultHeaders.CIPHER]: \"aes-256-gcm\",\n [VaultHeaders.KEY_ID]: keyId,\n [VaultHeaders.CONTENT_TYPE]: contentType,\n [VaultHeaders.KDF]: \"hkdf-sha256\",\n [VaultHeaders.KEY_ROTATION]:\n this.vaultConfig.keyRotation ?? \"per-write\",\n ...(options?.metadata ?? {}),\n };\n\n // Store encrypted entry key in key space\n const keyMetadata = JSON.stringify({\n keyId,\n contentType,\n ...metadata,\n });\n const keyPayload = JSON.stringify({\n key: base64Encode(keyBlob),\n metadata: keyMetadata,\n });\n const keyPutResult = await this.tc.kv.put(\n `keys/${key}`,\n keyPayload\n );\n if (!keyPutResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to store key blob: ${keyPutResult.error.message}`\n ),\n });\n }\n\n // Store encrypted value in data space\n const valuePayload = JSON.stringify({\n data: base64Encode(encrypted),\n metadata,\n });\n const valuePutResult = await this.tc.kv.put(\n `vault/${key}`,\n valuePayload\n );\n if (!valuePutResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to store encrypted value: ${valuePutResult.error.message}`\n ),\n });\n }\n\n return ok(undefined);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<void, VaultError>>;\n }\n\n /**\n * Retrieve and decrypt a value by key.\n *\n * @param key - The key to retrieve\n * @param options - Optional get configuration\n * @returns Result with the decrypted entry\n */\n async get<T = unknown>(\n key: string,\n options?: VaultGetOptions<T>\n ): Promise<Result<VaultEntry<T>, VaultError>> {\n return this.withTelemetry(\"get\", key, async () => {\n if (!this._isUnlocked || !this.masterKey) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before reading data\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Fetch encrypted entry key from key space\n const keyResult = await this.tc.kv.get<string>(`keys/${key}`, {\n raw: true,\n });\n if (!keyResult.ok) {\n return vaultError({ code: \"KEY_NOT_FOUND\", key });\n }\n\n const keyEnvelope = JSON.parse(keyResult.data.data as string);\n const keyBlobBytes = base64Decode(keyEnvelope.key);\n const entryKey = this.crypto.decrypt(this.masterKey, keyBlobBytes);\n\n // Fetch encrypted value from data space\n const valueResult = await this.tc.kv.get<string>(`vault/${key}`, {\n raw: true,\n });\n if (!valueResult.ok) {\n return vaultError({ code: \"KEY_NOT_FOUND\", key });\n }\n\n const valueEnvelope = JSON.parse(valueResult.data.data as string);\n const encryptedBytes = base64Decode(valueEnvelope.data);\n const plaintext = this.crypto.decrypt(entryKey, encryptedBytes);\n\n // Read metadata\n const metadata: Record<string, string> = valueEnvelope.metadata ?? {};\n const contentType =\n metadata[VaultHeaders.CONTENT_TYPE] ?? \"application/json\";\n const keyId = metadata[VaultHeaders.KEY_ID] ?? \"\";\n\n // Deserialize\n let value: T;\n if (options?.raw) {\n value = plaintext as unknown as T;\n } else if (options?.deserialize) {\n value = options.deserialize(plaintext);\n } else if (contentType === \"application/json\") {\n value = JSON.parse(fromBytes(plaintext)) as T;\n } else {\n value = plaintext as unknown as T;\n }\n\n return ok({ value, metadata, keyId });\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes(\"decryption\")\n ) {\n return vaultError({\n code: \"DECRYPTION_FAILED\",\n message: error.message,\n });\n }\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<VaultEntry<T>, VaultError>>;\n }\n\n /**\n * Delete an encrypted key.\n * Removes both the encrypted value and the key blob.\n *\n * @param key - The key to delete\n */\n async delete(key: string): Promise<Result<void, VaultError>> {\n return this.withTelemetry(\"delete\", key, async () => {\n if (!this._isUnlocked) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before deleting data\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Delete from both key space and data space\n const [keyDelResult, valueDelResult] = await Promise.all([\n this.tc.kv.delete(`keys/${key}`),\n this.tc.kv.delete(`vault/${key}`),\n ]);\n\n if (!keyDelResult.ok && !valueDelResult.ok) {\n return vaultError({ code: \"KEY_NOT_FOUND\", key });\n }\n\n return ok(undefined);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<void, VaultError>>;\n }\n\n /**\n * List vault keys with optional prefix filtering.\n *\n * @param options - Optional list configuration\n * @returns Result with array of key names (vault/ prefix stripped)\n */\n async list(\n options?: VaultListOptions\n ): Promise<Result<string[], VaultError>> {\n return this.withTelemetry(\"list\", options?.prefix, async () => {\n if (!this._isUnlocked) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before listing data\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n const listPrefix = options?.prefix\n ? `vault/${options.prefix}`\n : \"vault/\";\n\n const listResult = await this.tc.kv.list({\n prefix: listPrefix,\n removePrefix: true,\n });\n\n if (!listResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to list vault keys: ${listResult.error.message}`\n ),\n });\n }\n\n // Keys are already stripped of the \"vault/\" prefix by removePrefix\n let keys = listResult.data.keys;\n\n // If a user prefix was provided, strip it too if requested\n if (options?.removePrefix && options.prefix) {\n const userPrefix = options.prefix.endsWith(\"/\")\n ? options.prefix\n : `${options.prefix}/`;\n keys = keys.map((k) =>\n k.startsWith(userPrefix) ? k.slice(userPrefix.length) : k\n );\n }\n\n return ok(keys);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<string[], VaultError>>;\n }\n\n /**\n * Get envelope metadata for a key without decrypting the value.\n *\n * @param key - The key to inspect\n * @returns Result with metadata headers\n */\n async head(\n key: string\n ): Promise<Result<Record<string, string>, VaultError>> {\n return this.withTelemetry(\"head\", key, async () => {\n if (!this._isUnlocked) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before reading metadata\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Fetch envelope without decrypting\n const valueResult = await this.tc.kv.get<string>(`vault/${key}`, {\n raw: true,\n });\n if (!valueResult.ok) {\n return vaultError({ code: \"KEY_NOT_FOUND\", key });\n }\n\n const valueEnvelope = JSON.parse(valueResult.data.data as string);\n const metadata: Record<string, string> = valueEnvelope.metadata ?? {};\n return ok(metadata);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<Record<string, string>, VaultError>>;\n }\n\n // =========================================================================\n // Batch Operations\n // =========================================================================\n\n /**\n * Encrypt and store multiple entries.\n *\n * @param entries - Array of key/value pairs with optional per-entry options\n * @returns Array of results, one per entry\n */\n async putMany(\n entries: Array<{ key: string; value: unknown; options?: VaultPutOptions }>\n ): Promise<Result<void, VaultError>[]> {\n return Promise.all(\n entries.map((entry) => this.put(entry.key, entry.value, entry.options))\n );\n }\n\n /**\n * Retrieve and decrypt multiple keys.\n *\n * @param keys - Array of keys to retrieve\n * @param options - Optional get configuration applied to all entries\n * @returns Array of results, one per key\n */\n async getMany<T = unknown>(\n keys: string[],\n options?: VaultGetOptions<T>\n ): Promise<Result<VaultEntry<T>, VaultError>[]> {\n return Promise.all(keys.map((key) => this.get<T>(key, options)));\n }\n\n // =========================================================================\n // Phase 2: Sharing\n // =========================================================================\n\n /**\n * Re-encrypt a vault key for another user (renamed from grant).\n * Re-encrypts the data key to the recipient's public key via X25519 DH.\n *\n * @param key - The key to share\n * @param recipientDID - The recipient's primary DID (did:pkh:...)\n * @param options - Optional grant configuration\n */\n async reencrypt(\n key: string,\n recipientDID: string,\n options?: VaultGrantOptions\n ): Promise<Result<void, VaultError>> {\n return this.withTelemetry(\"reencrypt\", key, async () => {\n if (!this._isUnlocked || !this.masterKey) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before granting access\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Step 1: Resolve recipient's public key\n const pubKeyResult = await this.resolvePublicKey(recipientDID);\n if (!pubKeyResult.ok) {\n return pubKeyResult;\n }\n const bobPubKey = pubKeyResult.data;\n\n // Step 2: Fetch and decrypt entry key from key space\n const keyResult = await this.tc.kv.get<string>(`keys/${key}`, {\n raw: true,\n });\n if (!keyResult.ok) {\n return vaultError({ code: \"KEY_NOT_FOUND\", key });\n }\n\n const keyEnvelope = JSON.parse(keyResult.data.data as string);\n const keyBlobBytes = base64Decode(keyEnvelope.key);\n const entryKey = this.crypto.decrypt(this.masterKey, keyBlobBytes);\n\n // Step 3: Create ephemeral X25519 key pair\n const ephemeralSeed = this.crypto.randomBytes(32);\n const ephemeralKeyPair = this.crypto.x25519FromSeed(ephemeralSeed);\n\n // Step 4: Compute shared secret via DH\n const sharedSecret = this.crypto.x25519Dh(\n ephemeralKeyPair.privateKey,\n bobPubKey\n );\n\n // Step 5: Derive encryption key from shared secret\n const encryptionKey = this.crypto.deriveKey(\n sharedSecret,\n toBytes(\"tinycloud-x25519\"),\n toBytes(\"vault-grant\")\n );\n\n // Step 6: Encrypt entry key with derived key\n const encryptedGrant = this.crypto.encrypt(encryptionKey, entryKey);\n\n // Step 7: Concatenate ephemeral public key + encrypted grant\n const grantBlob = concatBytes(\n ephemeralKeyPair.publicKey,\n encryptedGrant\n );\n\n // Step 8: Store grant in key space\n const grantPayload = JSON.stringify({\n grant: base64Encode(grantBlob),\n spaceId: this.vaultConfig.spaceId,\n metadata: {\n [VaultHeaders.GRANT_VERSION]: \"1\",\n [VaultHeaders.GRANTOR]: this.tc.did,\n ...(options?.metadata ?? {}),\n },\n });\n // Store grant in the vault's space (main space)\n const grantPutResult = await this.tc.kv.put(\n `grants/${recipientDID}/${key}`,\n grantPayload\n );\n if (!grantPutResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to store grant: ${grantPutResult.error.message}`\n ),\n });\n }\n\n return ok(undefined);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<void, VaultError>>;\n }\n\n /**\n * @deprecated Use reencrypt() instead.\n */\n async grant(\n key: string,\n recipientDID: string,\n options?: VaultGrantOptions\n ): Promise<Result<void, VaultError>> {\n return this.reencrypt(key, recipientDID, options);\n }\n\n /**\n * Retrieve and decrypt a value shared by another user.\n *\n * @param grantorDID - The DID of the user who shared the data\n * @param key - The key that was shared\n * @param options - Optional get configuration\n * @returns Result with the decrypted entry\n */\n async getShared<T = unknown>(\n grantorDID: string,\n key: string,\n options?: VaultGetOptions<T>\n ): Promise<Result<VaultEntry<T>, VaultError>> {\n return this.withTelemetry(\"getShared\", key, async () => {\n if (\n !this._isUnlocked ||\n !this.masterKey ||\n !this.encryptionIdentity\n ) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before reading shared data\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n const myDID = this.tc.did;\n const grantorKV = options?.kv;\n\n if (!grantorKV) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n \"getShared requires a delegated KV service via options.kv. \" +\n \"Use useDelegation() to get delegated access, then pass { kv: access.kv }.\"\n ),\n });\n }\n\n // Step 1: Fetch grant from grantor's space via delegated KV\n const grantResult = await grantorKV.get<string>(`grants/${myDID}/${key}`, {\n raw: true,\n });\n if (!grantResult.ok) {\n return vaultError({\n code: \"GRANT_NOT_FOUND\",\n grantor: grantorDID,\n key,\n });\n }\n\n const grantEnvelope = typeof grantResult.data?.data === \"string\"\n ? JSON.parse(grantResult.data.data as string)\n : grantResult.data?.data;\n const grantBlobBytes = base64Decode((grantEnvelope as any).grant);\n\n // Step 2: Extract ephemeral public key and encrypted grant\n const ephemeralPubKey = grantBlobBytes.slice(0, 32);\n const encryptedGrant = grantBlobBytes.slice(32);\n\n // Step 3: Compute shared secret using our private key\n const sharedSecret = this.crypto.x25519Dh(\n this.encryptionIdentity.privateKey,\n ephemeralPubKey\n );\n\n // Step 4: Derive decryption key\n const encryptionKey = this.crypto.deriveKey(\n sharedSecret,\n toBytes(\"tinycloud-x25519\"),\n toBytes(\"vault-grant\")\n );\n\n // Step 5: Decrypt entry key\n const entryKey = this.crypto.decrypt(encryptionKey, encryptedGrant);\n\n // Step 6: Fetch encrypted value from grantor's space via delegated KV\n const valueResult = await grantorKV.get<string>(`vault/${key}`, {\n raw: true,\n });\n if (!valueResult.ok) {\n return vaultError({\n code: \"KEY_NOT_FOUND\",\n key,\n });\n }\n\n const valueEnvelope = typeof valueResult.data?.data === \"string\"\n ? JSON.parse(valueResult.data.data as string)\n : valueResult.data?.data;\n const encryptedBytes = base64Decode((valueEnvelope as any).data);\n const plaintext = this.crypto.decrypt(entryKey, encryptedBytes);\n\n // Read metadata\n const metadata: Record<string, string> = (valueEnvelope as any).metadata ?? {};\n const contentType =\n metadata[VaultHeaders.CONTENT_TYPE] ?? \"application/json\";\n const keyId = metadata[VaultHeaders.KEY_ID] ?? \"\";\n\n // Deserialize\n let value: T;\n if (options?.raw) {\n value = plaintext as unknown as T;\n } else if (options?.deserialize) {\n value = options.deserialize(plaintext);\n } else if (contentType === \"application/json\") {\n value = JSON.parse(fromBytes(plaintext)) as T;\n } else {\n value = plaintext as unknown as T;\n }\n\n return ok({ value, metadata, keyId });\n } catch (error) {\n if (\n error instanceof Error &&\n error.message.includes(\"decryption\")\n ) {\n return vaultError({\n code: \"DECRYPTION_FAILED\",\n message: error.message,\n });\n }\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<VaultEntry<T>, VaultError>>;\n }\n\n /**\n * Resolve another user's public encryption key from their DID.\n *\n * @param did - The DID to resolve (did:pkh:eip155:{chainId}:{address})\n * @returns Result with the public key bytes\n */\n async resolvePublicKey(\n did: string\n ): Promise<Result<Uint8Array, VaultError>> {\n try {\n const parts = this.parseDID(did);\n if (!parts) {\n return vaultError({ code: \"PUBLIC_KEY_NOT_FOUND\", did });\n }\n\n const spaceId = this.tc.makePublicSpaceId(\n parts.address,\n parts.chainId\n );\n\n const result = await this.tc.readPublicSpace<string>(\n this.host,\n spaceId,\n \".well-known/vault-pubkey\"\n );\n\n if (!result.ok) {\n return vaultError({ code: \"PUBLIC_KEY_NOT_FOUND\", did });\n }\n\n const pubKeyBytes = base64Decode(result.data as string);\n return { ok: true, data: pubKeyBytes } as Result<Uint8Array, VaultError>;\n } catch (error) {\n return vaultError({ code: \"PUBLIC_KEY_NOT_FOUND\", did });\n }\n }\n\n /**\n * List DIDs that have been granted access to a key.\n *\n * @param key - The key to list grants for\n * @returns Result with array of recipient DIDs\n */\n async listGrants(\n key: string\n ): Promise<Result<string[], VaultError>> {\n return this.withTelemetry(\"listGrants\", key, async () => {\n if (!this._isUnlocked) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before listing grants\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n const listResult = await this.tc.kv.list({\n prefix: \"grants/\",\n removePrefix: true,\n });\n\n if (!listResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to list grants: ${listResult.error.message}`\n ),\n });\n }\n\n // Grant paths are: {recipientDID}/{key}\n // Filter for the specific key and extract DIDs\n const dids: string[] = [];\n for (const grantPath of listResult.data.keys) {\n // Path format: {recipientDID}/{key}\n // The key may contain slashes, so we need to match the suffix\n if (grantPath.endsWith(`/${key}`)) {\n const did = grantPath.slice(\n 0,\n grantPath.length - key.length - 1\n );\n if (did) {\n dids.push(did);\n }\n }\n }\n\n return ok(dids);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<string[], VaultError>>;\n }\n\n // =========================================================================\n // Phase 3: Key Rotation / Revocation\n // =========================================================================\n\n /**\n * Revoke a previously issued grant.\n *\n * This performs a full key rotation:\n * 1. Lists current grantees\n * 2. Removes the revoked recipient\n * 3. Re-encrypts the value with a new entry key\n * 4. Re-issues grants to remaining recipients\n *\n * @param key - The key to revoke access to\n * @param recipientDID - The recipient whose access to revoke\n */\n async revoke(\n key: string,\n recipientDID: string\n ): Promise<Result<void, VaultError>> {\n return this.withTelemetry(\"revoke\", key, async () => {\n if (!this._isUnlocked || !this.masterKey) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Vault must be unlocked before revoking access\",\n });\n }\n\n if (!this.requireAuth()) {\n return vaultError({\n code: \"VAULT_LOCKED\",\n message: \"Authentication required\",\n });\n }\n\n try {\n // Step 1: List all current grantees\n const granteesResult = await this.listGrants(key);\n if (!granteesResult.ok) {\n return granteesResult;\n }\n\n const remainingGrantees = granteesResult.data.filter(\n (did) => did !== recipientDID\n );\n\n // Step 2: Delete the grant for the revoked recipient\n const deleteGrantResult = await this.tc.kv.delete(\n `grants/${recipientDID}/${key}`\n );\n // Grant may already be deleted, that's fine\n\n // Step 3: Fetch and decrypt current value\n const getResult = await this.get(key);\n if (!getResult.ok) {\n return getResult as Result<never, VaultError>;\n }\n\n const currentEntry = getResult.data;\n\n // Step 4: Generate new entry key\n const newEntryKey = this.crypto.randomBytes(32);\n const newKeyId = hexEncode(this.crypto.sha256(newEntryKey)).slice(\n 0,\n 16\n );\n\n // Step 5: Re-serialize and re-encrypt value with new key\n let plaintext: Uint8Array;\n if (currentEntry.value instanceof Uint8Array) {\n plaintext = currentEntry.value;\n } else {\n plaintext = toBytes(JSON.stringify(currentEntry.value));\n }\n\n const encrypted = this.crypto.encrypt(newEntryKey, plaintext);\n\n // Step 6: Encrypt new entry key with master key\n const newKeyBlob = this.crypto.encrypt(this.masterKey, newEntryKey);\n\n // Step 7: Update metadata with new key ID\n const metadata: Record<string, string> = {\n ...currentEntry.metadata,\n [VaultHeaders.KEY_ID]: newKeyId,\n };\n\n // Step 8: Store updated key blob\n const keyPayload = JSON.stringify({\n key: base64Encode(newKeyBlob),\n metadata: JSON.stringify({\n keyId: newKeyId,\n ...metadata,\n }),\n });\n const keyPutResult = await this.tc.kv.put(\n `keys/${key}`,\n keyPayload\n );\n if (!keyPutResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to store rotated key blob: ${keyPutResult.error.message}`\n ),\n });\n }\n\n // Step 9: Store re-encrypted value\n const valuePayload = JSON.stringify({\n data: base64Encode(encrypted),\n metadata,\n });\n const valuePutResult = await this.tc.kv.put(\n `vault/${key}`,\n valuePayload\n );\n if (!valuePutResult.ok) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause: new Error(\n `Failed to store re-encrypted value: ${valuePutResult.error.message}`\n ),\n });\n }\n\n // Step 10: Re-issue grants to remaining recipients\n for (const did of remainingGrantees) {\n const grantResult = await this.reencrypt(key, did);\n if (!grantResult.ok) {\n // Continue re-issuing to other recipients even if one fails\n // The failed grant can be re-issued manually\n }\n }\n\n return ok(undefined);\n } catch (error) {\n return vaultError({\n code: \"STORAGE_ERROR\",\n cause:\n toError(error),\n });\n }\n }) as Promise<Result<void, VaultError>>;\n }\n\n // =========================================================================\n // Internal Helpers\n // =========================================================================\n\n /**\n * Parse a DID string to extract address and chainId.\n * Expected format: did:pkh:eip155:{chainId}:{address}\n *\n * @param did - The DID to parse\n * @returns Parsed address and chainId, or null if invalid\n */\n private parseDID(\n did: string\n ): { address: string; chainId: number } | null {\n // did:pkh:eip155:{chainId}:{address}\n const parts = did.split(\":\");\n if (\n parts.length !== 5 ||\n parts[0] !== \"did\" ||\n parts[1] !== \"pkh\" ||\n parts[2] !== \"eip155\"\n ) {\n return null;\n }\n\n const chainId = parseInt(parts[3], 10);\n const address = parts[4];\n if (isNaN(chainId) || !address) {\n return null;\n }\n\n return { address, chainId };\n }\n}\n","import type { VaultCrypto } from \"./DataVaultService\";\n\nexport interface WasmVaultFunctions {\n vault_encrypt(key: Uint8Array, plaintext: Uint8Array): Uint8Array;\n vault_decrypt(key: Uint8Array, blob: Uint8Array): Uint8Array;\n /** WASM order: (salt, signature, info) — NOT (signature, salt, info) */\n vault_derive_key(salt: Uint8Array, signature: Uint8Array, info: Uint8Array): Uint8Array;\n vault_x25519_from_seed(seed: Uint8Array): { publicKey: Uint8Array; privateKey: Uint8Array };\n vault_x25519_dh(privateKey: Uint8Array, publicKey: Uint8Array): Uint8Array;\n vault_random_bytes(length: number): Uint8Array;\n vault_sha256(data: Uint8Array): Uint8Array;\n}\n\nexport function createVaultCrypto(wasm: WasmVaultFunctions): VaultCrypto {\n return {\n encrypt: (key, plaintext) => wasm.vault_encrypt(key, plaintext),\n decrypt: (key, blob) => wasm.vault_decrypt(key, blob),\n deriveKey: (signature, salt, info) => wasm.vault_derive_key(salt, signature, info),\n x25519FromSeed: (seed) => wasm.vault_x25519_from_seed(seed),\n x25519Dh: (privateKey, publicKey) => wasm.vault_x25519_dh(privateKey, publicKey),\n randomBytes: (length) => wasm.vault_random_bytes(length),\n sha256: (data) => wasm.vault_sha256(data),\n };\n}\n","import {\n ErrorCodes,\n err,\n type Result,\n type ServiceError,\n} from \"../types\";\nimport type { IDataVaultService } from \"../vault/IDataVaultService\";\nimport type { VaultError } from \"../vault/types\";\nimport type {\n ISecretsService,\n SecretPayload,\n SecretsError,\n} from \"./ISecretsService\";\n\nconst SECRET_NAME_RE = /^[A-Z][A-Z0-9_]*$/;\nconst SECRET_PREFIX = \"secrets/\";\n\nfunction invalidSecretName(name: string): Result<never, ServiceError> {\n return err({\n code: ErrorCodes.INVALID_INPUT,\n service: \"secrets\",\n message:\n `Invalid secret name ${JSON.stringify(name)}. Secret names must match ${SECRET_NAME_RE.source}.`,\n });\n}\n\nfunction secretKey(name: string): string {\n return `${SECRET_PREFIX}${name}`;\n}\n\nexport class SecretsService implements ISecretsService {\n private readonly getVault: () => IDataVaultService;\n\n constructor(vault: IDataVaultService | (() => IDataVaultService)) {\n this.getVault = typeof vault === \"function\" ? vault : () => vault;\n }\n\n get vault(): IDataVaultService {\n return this.getVault();\n }\n\n get isUnlocked(): boolean {\n return this.vault.isUnlocked;\n }\n\n unlock(signer?: unknown): Promise<Result<void, VaultError>> {\n return this.vault.unlock(signer);\n }\n\n lock(): void {\n this.vault.lock();\n }\n\n async get(name: string): Promise<Result<string, SecretsError>> {\n if (!SECRET_NAME_RE.test(name)) {\n return invalidSecretName(name);\n }\n\n const result = await this.vault.get<SecretPayload>(secretKey(name));\n if (!result.ok) {\n return result;\n }\n return { ok: true, data: result.data.value.value };\n }\n\n async put(name: string, value: string): Promise<Result<void, SecretsError>> {\n if (!SECRET_NAME_RE.test(name)) {\n return invalidSecretName(name);\n }\n\n const now = new Date().toISOString();\n return this.vault.put(secretKey(name), {\n value,\n createdAt: now,\n updatedAt: now,\n } satisfies SecretPayload);\n }\n\n async delete(name: string): Promise<Result<void, SecretsError>> {\n if (!SECRET_NAME_RE.test(name)) {\n return invalidSecretName(name);\n }\n\n return this.vault.delete(secretKey(name));\n }\n\n async list(): Promise<Result<string[], SecretsError>> {\n const result = await this.vault.list({\n prefix: SECRET_PREFIX,\n removePrefix: true,\n });\n if (!result.ok) {\n return result;\n }\n return {\n ok: true,\n data: result.data.filter((name) => SECRET_NAME_RE.test(name)),\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC4DO,IAAM,aAAa;AAAA;AAAA,EAExB,WAAW;AAAA,EACX,cAAc;AAAA,EACd,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,eAAe;AAAA,EACf,SAAS;AAAA,EACT,SAAS;AAAA,EACT,eAAe;AAAA,EACf,mBAAmB;AAAA;AAAA,EAGnB,cAAc;AAAA,EACd,iBAAiB;AAAA;AAAA,EAGjB,WAAW;AAAA,EACX,uBAAuB;AAAA,EACvB,wBAAwB;AAAA,EACxB,wBAAwB;AAAA,EACxB,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,EACvB,kBAAkB;AAAA,EAClB,wBAAwB;AAAA;AAAA,EAGxB,wBAAwB;AAAA,EACxB,uBAAuB;AAAA;AAAA,EAGvB,cAAc;AAAA,EACd,0BAA0B;AAAA,EAC1B,2BAA2B;AAAA,EAC3B,2BAA2B;AAAA,EAC3B,uBAAuB;AAAA,EACvB,0BAA0B;AAAA,EAC1B,qBAAqB;AAAA,EACrB,2BAA2B;AAC7B;AAmJO,IAAM,qBAAkC;AAAA,EAC7C,aAAa;AAAA,EACb,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,iBAAiB,CAAC,WAAW,eAAe,WAAW,OAAO;AAChE;AAkHO,IAAM,kBAAkB;AAAA,EAC7B,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,iBAAiB;AACnB;AASO,SAAS,GAAM,MAAoB;AACxC,SAAO,EAAE,IAAI,MAAM,KAAK;AAC1B;AAKO,SAAS,IAAsB,OAA4B;AAChE,SAAO,EAAE,IAAI,OAAO,MAAM;AAC5B;AAKO,SAAS,aACd,MACA,SACA,SACA,SACc;AACd,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,SAAS;AAAA,IAChB,MAAM,SAAS;AAAA,EACjB;AACF;;;AChZA,iBAAkB;AA0BX,IAAM,qBAAqB,aAAE,OAAO;AAAA;AAAA,EAEzC,MAAM,aAAE,OAAO;AAAA;AAAA,EAEf,SAAS,aAAE,OAAO;AAAA;AAAA,EAElB,SAAS,aAAE,OAAO;AAAA;AAAA,EAElB,OAAO,aAAE,QAAQ,EAAE,SAAS;AAAA;AAAA,EAE5B,MAAM,aAAE,OAAO,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS;AAC5C,CAAC;AAsBM,SAAS,mBACd,YACA,cAAiB,oBACjB;AACA,SAAO,aAAE,mBAAmB,MAAM;AAAA,IAChC,aAAE,OAAO;AAAA,MACP,IAAI,aAAE,QAAQ,IAAI;AAAA,MAClB,MAAM;AAAA,IACR,CAAC;AAAA,IACD,aAAE,OAAO;AAAA,MACP,IAAI,aAAE,QAAQ,KAAK;AAAA,MACnB,OAAO;AAAA,IACT,CAAC;AAAA,EACH,CAAC;AACH;AAMO,IAAM,sBAAsB,mBAAmB,aAAE,QAAQ,GAAG,kBAAkB;AAW9E,IAAM,0BAA0B,aAAE,OAAO;AAAA;AAAA,EAE9C,MAAM,aAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE1B,aAAa,aAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAEjC,cAAc,aAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAElC,eAAe,aAAE,OAAO,EAAE,SAAS;AACrC,CAAC;AAgBM,SAAS,uBAA+C,YAAe;AAC5E,SAAO,aAAE,OAAO;AAAA;AAAA,IAEd,MAAM;AAAA;AAAA,IAEN,SAAS;AAAA,EACX,CAAC;AACH;AAMO,IAAM,0BAA0B,uBAAuB,aAAE,QAAQ,CAAC;AAOlE,IAAM,uBAAuB,aAAE,OAAO;AAAA;AAAA,EAE3C,MAAM,aAAE,MAAM,aAAE,OAAO,CAAC;AAC1B,CAAC;AAOM,IAAM,qBAAqB,mBAAmB,oBAAoB;AAWlE,IAAM,4BAA4B,aAAE,OAAO;AAAA,EAChD,SAAS,aAAE,OAAO;AAAA,EAClB,QAAQ,aAAE,OAAO;AAAA,EACjB,KAAK,aAAE,OAAO,EAAE,SAAS;AAAA,EACzB,WAAW,aAAE,OAAO;AACtB,CAAC;AAOM,IAAM,6BAA6B,aAAE,OAAO;AAAA,EACjD,SAAS,aAAE,OAAO;AAAA,EAClB,QAAQ,aAAE,OAAO;AAAA,EACjB,IAAI,aAAE,QAAQ;AAAA,EACd,UAAU,aAAE,OAAO;AAAA,EACnB,QAAQ,aAAE,OAAO,EAAE,SAAS;AAC9B,CAAC;AAOM,IAAM,0BAA0B,aAAE,OAAO;AAAA,EAC9C,SAAS,aAAE,OAAO;AAAA,EAClB,OAAO;AACT,CAAC;AAOM,IAAM,0BAA0B,aAAE,OAAO;AAAA,EAC9C,SAAS,aAAE,OAAO;AAAA,EAClB,SAAS,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACnC,aAAa,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACvC,OAAO;AACT,CAAC;AAWM,IAAM,oBAAoB,aAAE,OAAO;AAAA;AAAA,EAExC,aAAa,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA;AAAA,EAEvC,SAAS,aAAE,KAAK,CAAC,QAAQ,UAAU,aAAa,CAAC;AAAA;AAAA,EAEjD,aAAa,aAAE,OAAO,EAAE,YAAY;AAAA;AAAA,EAEpC,YAAY,aAAE,OAAO,EAAE,YAAY;AAAA;AAAA,EAEnC,iBAAiB,aAAE,MAAM,aAAE,OAAO,CAAC;AACrC,CAAC;AAWM,IAAM,uBAAuB,aAAE,OAAO;AAAA;AAAA,EAE3C,kBAAkB,aAAE,OAAO;AAAA,IACzB,eAAe,aAAE,OAAO;AAAA,EAC1B,CAAC;AAAA;AAAA,EAED,eAAe,aAAE,OAAO;AAAA;AAAA,EAExB,SAAS,aAAE,OAAO;AAAA;AAAA,EAElB,oBAAoB,aAAE,OAAO;AAAA;AAAA,EAE7B,KAAK,aAAE,OAAO,CAAC,CAAC,EAAE,YAAY;AAChC,CAAC;AAcM,SAAS,qBACd,MAC8E;AAC9E,QAAM,SAAS,mBAAmB,UAAU,IAAI;AAChD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,OAAO,MAAM;AAAA,QACtB,SAAS;AAAA,QACT,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAO;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK;AACvC;AAQO,SAAS,uBACd,MACgF;AAChF,QAAM,SAAS,qBAAqB,UAAU,IAAI;AAClD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,OAAO,MAAM;AAAA,QACtB,SAAS;AAAA,QACT,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAO;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK;AACvC;AAQO,SAAS,0BACd,MACmF;AACnF,QAAM,SAAS,wBAAwB,UAAU,IAAI;AACrD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,OAAO,MAAM;AAAA,QACtB,SAAS;AAAA,QACT,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAO;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK;AACvC;AAQO,SAAS,uBACd,MACgF;AAChF,QAAM,SAAS,qBAAqB,UAAU,IAAI;AAClD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,OAAO,MAAM;AAAA,QACtB,SAAS;AAAA,QACT,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAO;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK;AACvC;AAQO,SAAS,oBACd,MAC6E;AAC7E,QAAM,SAAS,kBAAkB,UAAU,IAAI;AAC/C,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,OAAO,MAAM;AAAA,QACtB,SAAS;AAAA,QACT,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAO;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK;AACvC;AAQO,SAAS,4BACd,MACqF;AACrF,QAAM,SAAS,0BAA0B,UAAU,IAAI;AACvD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,OAAO,MAAM;AAAA,QACtB,SAAS;AAAA,QACT,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAO;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK;AACvC;AAQO,SAAS,6BACd,MACsF;AACtF,QAAM,SAAS,2BAA2B,UAAU,IAAI;AACxD,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,OAAO,MAAM;AAAA,QACtB,SAAS;AAAA,QACT,MAAM,EAAE,QAAQ,OAAO,MAAM,OAAO;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK;AACvC;;;AC7WO,IAAM,iBAAN,MAAgD;AAAA,EAWrD,YAAY,QAA8B;AAV1C,SAAQ,WAAkC;AAC1C,SAAQ,YAAmC,oBAAI,IAAI;AACnD,SAAQ,iBAAiD,oBAAI,IAAI;AACjE,SAAQ,mBAAoC,IAAI,gBAAgB;AAQ9D,SAAK,UAAU,OAAO;AACtB,SAAK,aAAa,OAAO;AACzB,SAAK,SAAS,OAAO,SAAS,WAAW,MAAM,KAAK,UAAU;AAC9D,SAAK,SAAS,OAAO;AACrB,SAAK,WAAW,OAAO,WAAW;AAClC,SAAK,eAAe;AAAA,MAClB,GAAG;AAAA,MACH,GAAG,OAAO;AAAA,IACZ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,UAAiC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,kBAA2B;AAC7B,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,SAAsC;AAC/C,SAAK,WAAW;AAChB,SAAK,KAAK,mBAAmB,EAAE,eAAe,YAAY,KAAK,CAAC;AAGhE,eAAW,WAAW,KAAK,UAAU,OAAO,GAAG;AAC7C,cAAQ,gBAAgB,OAAO;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,SAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAA2C;AAC7C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAAuB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,gBAAgB,MAAc,SAAyB;AACrD,SAAK,UAAU,IAAI,MAAM,OAAO;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kBAAkB,MAAoB;AACpC,SAAK,UAAU,OAAO,IAAI;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAA+B,MAA6B;AAC1D,WAAO,KAAK,UAAU,IAAI,IAAI;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,KAAK,OAAe,MAAqB;AACvC,UAAM,WAAW,KAAK,eAAe,IAAI,KAAK;AAC9C,QAAI,UAAU;AACZ,iBAAW,WAAW,UAAU;AAC9B,YAAI;AACF,kBAAQ,IAAI;AAAA,QACd,SAAS,OAAO;AAEd,kBAAQ,MAAM,+BAA+B,KAAK,MAAM,KAAK;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,GAAG,OAAe,SAAmC;AACnD,QAAI,CAAC,KAAK,eAAe,IAAI,KAAK,GAAG;AACnC,WAAK,eAAe,IAAI,OAAO,oBAAI,IAAI,CAAC;AAAA,IAC1C;AACA,SAAK,eAAe,IAAI,KAAK,EAAG,IAAI,OAAO;AAG3C,WAAO,MAAM;AACX,YAAM,WAAW,KAAK,eAAe,IAAI,KAAK;AAC9C,UAAI,UAAU;AACZ,iBAAS,OAAO,OAAO;AACvB,YAAI,SAAS,SAAS,GAAG;AACvB,eAAK,eAAe,OAAO,KAAK;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,mBAAmB,OAAsB;AACvC,QAAI,OAAO;AACT,WAAK,eAAe,OAAO,KAAK;AAAA,IAClC,OAAO;AACL,WAAK,eAAe,MAAM;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,cAA2B;AAC7B,WAAO,KAAK,iBAAiB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAc;AACZ,SAAK,iBAAiB,MAAM;AAC5B,SAAK,mBAAmB,IAAI,gBAAgB;AAG5C,eAAW,WAAW,KAAK,UAAU,OAAO,GAAG;AAC7C,cAAQ,UAAU;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,SAAK,MAAM;AACX,SAAK,WAAW,IAAI;AACpB,SAAK,KAAK,mBAAmB,CAAC,CAAC;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,cAA2B;AAC7B,WAAO,KAAK;AAAA,EACd;AACF;;;ACpRO,SAAS,kBAAkB,SAA+B;AAC/D,SAAO;AAAA,IACL,MAAM,WAAW;AAAA,IACjB,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAKO,SAAS,iBAAiB,SAA+B;AAC9D,SAAO;AAAA,IACL,MAAM,WAAW;AAAA,IACjB,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAKO,SAAS,aACd,SACA,SACA,OACc;AACd,SAAO;AAAA,IACL,MAAM,WAAW;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,aAAa,SAA+B;AAC1D,SAAO;AAAA,IACL,MAAM,WAAW;AAAA,IACjB,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAKO,SAAS,aAAa,SAA+B;AAC1D,SAAO;AAAA,IACL,MAAM,WAAW;AAAA,IACjB,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAKO,SAAS,cACd,SACA,UACc;AACd,SAAO;AAAA,IACL,MAAM,WAAW;AAAA,IACjB,SAAS,uBAAuB,QAAQ;AAAA,IACxC;AAAA,EACF;AACF;AAKO,SAAS,sBACd,SACA,QACc;AACd,SAAO;AAAA,IACL,MAAM,WAAW;AAAA,IACjB,SAAS,iCAAiC,MAAM;AAAA,IAChD;AAAA,EACF;AACF;AAKO,SAAS,eAAe,cAA8D;AAC3F,QAAM,QAAQ,aAAa,MAAM,yDAAyD;AAC1F,MAAI,OAAO;AACT,WAAO,EAAE,UAAU,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,MAAM,CAAC,EAAE,KAAK,EAAE;AAAA,EAC9D;AACA,SAAO,CAAC;AACV;AAKO,SAAS,sBACd,SACA,SACA,MACc;AACd,SAAO,aAAa,WAAW,mBAAmB,SAAS,SAAS,EAAE,KAAK,CAAC;AAC9E;AAKO,SAAS,0BACd,SACA,SACA,MACc;AACd,SAAO;AAAA,IACL,MAAM,WAAW;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,yBACd,SACA,SACA,MACc;AACd,SAAO;AAAA,IACL,MAAM,WAAW;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKO,SAAS,UACd,SACA,OACA,cAAsB,WAAW,eACnB;AACd,MAAI,iBAAiB,OAAO;AAE1B,QAAI,MAAM,SAAS,cAAc;AAC/B,aAAO,aAAa,OAAO;AAAA,IAC7B;AAGA,QACE,MAAM,SAAS,kBACf,MAAM,QAAQ,YAAY,EAAE,SAAS,SAAS,GAC9C;AACA,aAAO,aAAa,OAAO;AAAA,IAC7B;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS,MAAM;AAAA,MACf;AAAA,MACA,OAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,OAAO,KAAK;AAAA,IACrB;AAAA,EACF;AACF;AAKO,SAAS,YAAY,OAAqB;AAC/C,SAAO,IAAI,KAAK;AAClB;;;AClJO,IAAe,cAAf,MAA+C;AAAA,EAA/C;AAiBL;AAAA;AAAA;AAAA;AAAA,SAAU,kBAAmC,IAAI,gBAAgB;AAKjE;AAAA;AAAA;AAAA,SAAU,UAAmC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9C,IAAI,SAAkC;AACpC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,SAAgC;AACzC,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,SAAsC;AAAA,EAEtD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAkB;AAChB,SAAK,gBAAgB,MAAM;AAC3B,SAAK,kBAAkB,IAAI,gBAAgB;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAc,cAA2B;AACvC,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAc,kBAA2B;AACvC,WAAO,KAAK,SAAS,mBAAmB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAc,UAA0B;AACtC,QAAI,CAAC,KAAK,SAAS,SAAS;AAC1B,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACrC;AACA,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,cAAuB;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,KAAK,OAAe,MAAqB;AACjD,SAAK,SAAS,KAAK,OAAO,IAAI;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,YAAY,QAAgB,KAAoB;AACxD,SAAK,KAAK,gBAAgB,iBAAiB;AAAA,MACzC,SAAS,KAAK,eAAe;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUU,aACR,QACAA,KACA,WACA,QACM;AACN,SAAK,KAAK,gBAAgB,kBAAkB;AAAA,MAC1C,SAAS,KAAK,eAAe;AAAA,MAC7B;AAAA,MACA,IAAAA;AAAA,MACA,UAAU,KAAK,IAAI,IAAI;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOU,UAAU,OAA2B;AAC7C,SAAK,KAAK,gBAAgB,eAAe;AAAA,MACvC,SAAS,KAAK,eAAe;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMU,iBAAyB;AACjC,WAAQ,KAAK,YAAmC;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQU,kBAAkB,SAAmD;AAC7E,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,aAAa,CAAC,KAAK,aAAa,GAAG,QAAQ,OAAO,OAAO,CAAC;AAEhE,eAAW,UAAU,YAAY;AAC/B,UAAI,OAAO,SAAS;AAClB,mBAAW,MAAM,OAAO,MAAM;AAC9B,eAAO,WAAW;AAAA,MACpB;AACA,aAAO,iBAAiB,SAAS,MAAM,WAAW,MAAM,OAAO,MAAM,GAAG;AAAA,QACtE,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAEA,WAAO,WAAW;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAgB,cACd,QACA,KACA,WACoB;AACpB,UAAM,YAAY,KAAK,IAAI;AAC3B,SAAK,YAAY,QAAQ,GAAG;AAE5B,QAAI;AACF,YAAM,SAAS,MAAM,UAAU;AAE/B,UAAI,OAAO,IAAI;AACb,aAAK,aAAa,QAAQ,MAAM,SAAS;AAAA,MAC3C,OAAO;AACL,aAAK,aAAa,QAAQ,OAAO,SAAS;AAC1C,aAAK,UAAU,OAAO,KAAK;AAAA,MAC7B;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAMC,gBAAe,UAAU,KAAK,eAAe,GAAG,KAAK;AAC3D,WAAK,aAAa,QAAQ,OAAO,SAAS;AAC1C,WAAK,UAAUA,aAAY;AAC3B,aAAO,IAAIA,aAAY;AAAA,IACzB;AAAA,EACF;AACF;;;ACvCO,IAAM,oBAAN,MAAM,mBAAgD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiB3D,YAAY,IAAoB,QAAgB;AAC9C,SAAK,MAAM;AAEX,SAAK,UAAU,OAAO,SAAS,GAAG,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAiB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,WAAW,KAAqB;AAEtC,UAAM,gBAAgB,IAAI,WAAW,GAAG,IAAI,MAAM,IAAI,GAAG;AACzD,WAAO,GAAG,KAAK,OAAO,GAAG,aAAa;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IACJ,KACA,SACgC;AAChC,UAAM,UAAU,KAAK,WAAW,GAAG;AAEnC,WAAO,KAAK,IAAI,IAAO,SAAS,EAAE,GAAG,SAAS,QAAQ,GAAG,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IACJ,KACA,OACA,SACmC;AACnC,UAAM,UAAU,KAAK,WAAW,GAAG;AACnC,WAAO,KAAK,IAAI,IAAI,SAAS,OAAO,EAAE,GAAG,SAAS,QAAQ,GAAG,CAAC;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,SAA0E;AAEnF,UAAM,eAAe,SAAS,gBAAgB;AAC9C,WAAO,KAAK,IAAI,KAAK;AAAA,MACnB,GAAG;AAAA,MACH,QAAQ,KAAK;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,KAAa,SAAkE;AAC1F,UAAM,UAAU,KAAK,WAAW,GAAG;AACnC,WAAO,KAAK,IAAI,OAAO,SAAS,EAAE,GAAG,SAAS,QAAQ,GAAG,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KACJ,KACA,SACmC;AACnC,UAAM,UAAU,KAAK,WAAW,GAAG;AACnC,WAAO,KAAK,IAAI,KAAK,SAAS,EAAE,GAAG,SAAS,QAAQ,GAAG,CAAC;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,WAAuC;AAEhD,UAAM,sBAAsB,UAAU,WAAW,GAAG,IAChD,YACA,IAAI,SAAS;AACjB,UAAM,iBAAiB,GAAG,KAAK,OAAO,GAAG,mBAAmB;AAC5D,WAAO,IAAI,mBAAkB,KAAK,KAAK,cAAc;AAAA,EACvD;AACF;;;AC7GO,IAAM,WAAW;AAAA,EACtB,KAAK;AAAA,EACL,KAAK;AAAA,EACL,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,MAAM;AACR;;;AC9KO,IAAM,YAAN,cAAwB,YAAkC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgB/D,YAAY,SAA0B,CAAC,GAAG;AACxC,UAAM;AACN,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAA0B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGQ,eACN,WACuD;AACvD,UAAM,QAAQ,UAAU;AAAA,MACtB;AAAA,IACF;AACA,QAAI,OAAO;AACT,aAAO;AAAA,QACL,WAAW,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,QAChC,YAAY,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,MACnC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,yBACN,UACA,WACA,KAC2B;AAC3B,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,YAAY,KAAK,eAAe,SAAS;AAC/C,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA,mCAAmC,GAAG,MAAM,SAAS;AAAA,UACrD;AAAA,YACE,QAAQ,SAAS;AAAA,YACjB,GAAI,YACA,EAAE,WAAW,UAAU,WAAW,YAAY,UAAU,WAAW,IACnE,CAAC;AAAA,UACP;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,YAAY,KAAK,eAAe,SAAS;AAC/C,aAAO;AAAA,QACL;AAAA,UACE;AAAA,UACA,kCAAkC,GAAG,MAAM,SAAS;AAAA,UACpD;AAAA,YACE,QAAQ,SAAS;AAAA,YACjB,GAAI,YACA,EAAE,WAAW,UAAU,WAAW,YAAY,UAAU,WAAW,IACnE,CAAC;AAAA,UACP;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,YAAY,KAAa,gBAAiC;AAChE,UAAM,SAAS,kBAAkB,KAAK,QAAQ,UAAU;AACxD,WAAO,SAAS,GAAG,MAAM,IAAI,GAAG,KAAK;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,OAAe;AACzB,WAAO,KAAK,QAAQ,MAAM,CAAC;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAc,gBACZ,MACA,QACA,MACA,QACwB;AACxB,UAAM,UAAU,KAAK,QAAQ;AAC7B,UAAM,UAAU,KAAK,QAAQ;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,WAAO,KAAK,QAAQ,MAAM,GAAG,KAAK,IAAI,WAAW;AAAA,MAC/C,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,QAAQ,KAAK,eAAe,MAAM;AAAA,IACpC,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,sBAAsB,SAER;AACpB,WAAO;AAAA,MACL,MAAM,QAAQ,IAAI,MAAM,KAAK;AAAA,MAC7B,aAAa,QAAQ,IAAI,cAAc,KAAK;AAAA,MAC5C,cAAc,QAAQ,IAAI,eAAe,KAAK;AAAA,MAC9C,eAAe,QAAQ,IAAI,gBAAgB,IACvC,SAAS,QAAQ,IAAI,gBAAgB,GAAI,EAAE,IAC3C;AAAA,MACJ,KAAK,CAAC,SAAiB,QAAQ,IAAI,IAAI;AAAA,IACzC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,cACZ,UACA,MAAe,OACS;AACxB,QAAI,CAAC,SAAS,IAAI;AAChB,aAAO;AAAA,IACT;AAEA,QAAI,KAAK;AACP,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAEA,UAAM,cAAc,SAAS,QAAQ,IAAI,cAAc;AACvD,QAAI,aAAa,SAAS,kBAAkB,GAAG;AAC7C,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B,WAAW,aAAa,WAAW,OAAO,GAAG;AAC3C,aAAQ,MAAM,SAAS,KAAK;AAAA,IAC9B;AAGA,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI,CAAC,MAAM;AACT,aAAO;AAAA,IACT;AACA,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IACJ,KACA,SACgC;AAChC,WAAO,KAAK,cAAc,OAAO,KAAK,YAAY;AAChD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,IAAI,CAAC;AAAA,MACpC;AAEA,YAAM,OAAO,KAAK,YAAY,KAAK,SAAS,MAAM;AAElD,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,cAAI,SAAS,WAAW,KAAK;AAC3B,kBAAMC,aAAY,MAAM,SAAS,KAAK;AACtC,kBAAM,EAAE,UAAU,OAAO,IAAI,eAAeA,UAAS;AACrD,mBAAO,IAAI,sBAAsB,MAAMA,YAAW;AAAA,cAChD,QAAQ,SAAS;AAAA,cACjB,GAAI,UAAU,EAAE,gBAAgB,OAAO;AAAA,cACvC,GAAI,YAAY,EAAE,SAAS;AAAA,YAC7B,CAAC,CAAC;AAAA,UACJ;AAEA,cAAI,SAAS,WAAW,KAAK;AAC3B,mBAAO;AAAA,cACL;AAAA,gBACE,WAAW;AAAA,gBACX,kBAAkB,GAAG;AAAA,gBACrB;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,YAAY,MAAM,SAAS,KAAK;AACtC,iBAAO;AAAA,YACL;AAAA,cACE,WAAW;AAAA,cACX,sBAAsB,GAAG,MAAM,SAAS,MAAM,MAAM,SAAS;AAAA,cAC7D;AAAA,cACA,EAAE,MAAM,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,WAAW,EAAE;AAAA,YACvE;AAAA,UACF;AAAA,QACF;AAEA,cAAM,OAAO,MAAM,KAAK,cAAiB,UAAU,SAAS,GAAG;AAC/D,eAAO,GAAG;AAAA,UACR;AAAA,UACA,SAAS,KAAK,sBAAsB,SAAS,OAAO;AAAA,QACtD,CAAC;AAAA,MACH,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,MAAM,KAAK,CAAC;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IACJ,KACA,OACA,SACmC;AACnC,WAAO,KAAK,cAAc,OAAO,KAAK,YAAY;AAChD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,IAAI,CAAC;AAAA,MACpC;AAEA,YAAM,OAAO,KAAK,YAAY,KAAK,SAAS,MAAM;AAGlD,UAAI;AACJ,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO;AAAA,MACT,OAAO;AACL,eAAO,KAAK,UAAU,KAAK;AAAA,MAC7B;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,cAAI,SAAS,WAAW,KAAK;AAC3B,kBAAMA,aAAY,MAAM,SAAS,KAAK;AACtC,kBAAM,EAAE,UAAU,OAAO,IAAI,eAAeA,UAAS;AACrD,mBAAO,IAAI,sBAAsB,MAAMA,YAAW;AAAA,cAChD,QAAQ,SAAS;AAAA,cACjB,GAAI,UAAU,EAAE,gBAAgB,OAAO;AAAA,cACvC,GAAI,YAAY,EAAE,SAAS;AAAA,YAC7B,CAAC,CAAC;AAAA,UACJ;AAEA,gBAAM,YAAY,MAAM,SAAS,KAAK;AAGtC,gBAAM,aAAa,KAAK;AAAA,YACtB;AAAA,YACA;AAAA,YACA;AAAA,UACF;AACA,cAAI,YAAY;AACd,mBAAO;AAAA,UACT;AAEA,iBAAO;AAAA,YACL;AAAA,cACE,WAAW;AAAA,cACX,sBAAsB,GAAG,MAAM,SAAS,MAAM,MAAM,SAAS;AAAA,cAC7D;AAAA,cACA,EAAE,MAAM,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,WAAW,EAAE;AAAA,YACvE;AAAA,UACF;AAAA,QACF;AAEA,eAAO,GAAG;AAAA,UACR,MAAM;AAAA,UACN,SAAS,KAAK,sBAAsB,SAAS,OAAO;AAAA,QACtD,CAAC;AAAA,MACH,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,MAAM,KAAK,CAAC;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,SAA0D;AACnE,WAAO,KAAK,cAAc,QAAQ,SAAS,QAAQ,YAAY;AAC7D,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,IAAI,CAAC;AAAA,MACpC;AAGA,UAAI,WAAW,SAAS,UAAU,KAAK,QAAQ,UAAU;AACzD,UAAI,SAAS,MAAM;AACjB,mBAAW,WAAW,GAAG,QAAQ,IAAI,QAAQ,IAAI,KAAK,QAAQ;AAAA,MAChE;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,cAAI,SAAS,WAAW,KAAK;AAC3B,kBAAMA,aAAY,MAAM,SAAS,KAAK;AACtC,kBAAM,EAAE,UAAU,OAAO,IAAI,eAAeA,UAAS;AACrD,mBAAO,IAAI,sBAAsB,MAAMA,YAAW;AAAA,cAChD,QAAQ,SAAS;AAAA,cACjB,GAAI,UAAU,EAAE,gBAAgB,OAAO;AAAA,cACvC,GAAI,YAAY,EAAE,SAAS;AAAA,YAC7B,CAAC,CAAC;AAAA,UACJ;AAEA,gBAAM,YAAY,MAAM,SAAS,KAAK;AACtC,iBAAO;AAAA,YACL;AAAA,cACE,WAAW;AAAA,cACX,wBAAwB,SAAS,MAAM,MAAM,SAAS;AAAA,cACtD;AAAA,cACA,EAAE,MAAM,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,WAAW,EAAE;AAAA,YACvE;AAAA,UACF;AAAA,QACF;AAEA,YAAI,OAAO,MAAM,KAAK,cAAwB,UAAU,SAAS,GAAG;AACpE,eAAO,QAAQ,CAAC;AAGhB,YAAI,SAAS,gBAAgB,UAAU;AACrC,gBAAM,kBAAkB,SAAS,SAAS,GAAG,IACzC,WACA,GAAG,QAAQ;AACf,iBAAO,KAAK;AAAA,YAAI,CAAC,QACf,IAAI,WAAW,eAAe,IAC1B,IAAI,MAAM,gBAAgB,MAAM,IAChC;AAAA,UACN;AAAA,QACF;AAEA,eAAO,GAAG,EAAE,KAAK,CAAC;AAAA,MACpB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,MAAM,KAAK,CAAC;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,KAAa,SAAkD;AAC1E,WAAO,KAAK,cAAc,UAAU,KAAK,YAAY;AACnD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,IAAI,CAAC;AAAA,MACpC;AAEA,YAAM,OAAO,KAAK,YAAY,KAAK,SAAS,MAAM;AAElD,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,cAAI,SAAS,WAAW,KAAK;AAC3B,kBAAMA,aAAY,MAAM,SAAS,KAAK;AACtC,kBAAM,EAAE,UAAU,OAAO,IAAI,eAAeA,UAAS;AACrD,mBAAO,IAAI,sBAAsB,MAAMA,YAAW;AAAA,cAChD,QAAQ,SAAS;AAAA,cACjB,GAAI,UAAU,EAAE,gBAAgB,OAAO;AAAA,cACvC,GAAI,YAAY,EAAE,SAAS;AAAA,YAC7B,CAAC,CAAC;AAAA,UACJ;AAEA,cAAI,SAAS,WAAW,KAAK;AAC3B,mBAAO;AAAA,cACL;AAAA,gBACE,WAAW;AAAA,gBACX,kBAAkB,GAAG;AAAA,gBACrB;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,YAAY,MAAM,SAAS,KAAK;AACtC,iBAAO;AAAA,YACL;AAAA,cACE,WAAW;AAAA,cACX,yBAAyB,GAAG,MAAM,SAAS,MAAM,MAAM,SAAS;AAAA,cAChE;AAAA,cACA,EAAE,MAAM,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,WAAW,EAAE;AAAA,YACvE;AAAA,UACF;AAAA,QACF;AAEA,eAAO,GAAG,MAAS;AAAA,MACrB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,MAAM,KAAK,CAAC;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KACJ,KACA,SACmC;AACnC,WAAO,KAAK,cAAc,QAAQ,KAAK,YAAY;AACjD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,IAAI,CAAC;AAAA,MACpC;AAEA,YAAM,OAAO,KAAK,YAAY,KAAK,SAAS,MAAM;AAElD,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,cAAI,SAAS,WAAW,KAAK;AAC3B,kBAAMA,aAAY,MAAM,SAAS,KAAK;AACtC,kBAAM,EAAE,UAAU,OAAO,IAAI,eAAeA,UAAS;AACrD,mBAAO,IAAI,sBAAsB,MAAMA,YAAW;AAAA,cAChD,QAAQ,SAAS;AAAA,cACjB,GAAI,UAAU,EAAE,gBAAgB,OAAO;AAAA,cACvC,GAAI,YAAY,EAAE,SAAS;AAAA,YAC7B,CAAC,CAAC;AAAA,UACJ;AAEA,cAAI,SAAS,WAAW,KAAK;AAC3B,mBAAO;AAAA,cACL;AAAA,gBACE,WAAW;AAAA,gBACX,kBAAkB,GAAG;AAAA,gBACrB;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,YAAY,MAAM,SAAS,KAAK;AACtC,iBAAO;AAAA,YACL;AAAA,cACE,WAAW;AAAA,cACX,mCAAmC,GAAG,MAAM,SAAS,MAAM,MAAM,SAAS;AAAA,cAC1E;AAAA,cACA,EAAE,MAAM,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,WAAW,EAAE;AAAA,YACvE;AAAA,UACF;AAAA,QACF;AAEA,eAAO,GAAG;AAAA,UACR,MAAM;AAAA,UACN,SAAS,KAAK,sBAAsB,SAAS,OAAO;AAAA,QACtD,CAAC;AAAA,MACH,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,MAAM,KAAK,CAAC;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4CA,WAAW,QAAoC;AAC7C,WAAO,IAAI,kBAAkB,MAAM,MAAM;AAAA,EAC3C;AACF;AAAA;AAAA;AAAA;AArjBa,UAIK,cAAc;;;AC5CzB,IAAM,iBAAN,MAAgD;AAAA,EAIrD,YAAY,SAAqB,MAAc;AAC7C,SAAK,UAAU;AACf,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,MAAM,MACJ,KACA,QACA,SACmC;AACnC,WAAO,KAAK,QAAQ,UAAa,KAAK,MAAM,KAAK,QAAQ,OAAO;AAAA,EAClE;AAAA,EAEA,MAAM,QACJ,KACA,QACA,SACkC;AAClC,WAAO,KAAK,QAAQ,YAAY,KAAK,MAAM,KAAK,QAAQ,OAAO;AAAA,EACjE;AAAA,EAEA,MAAM,MACJ,YACA,SACgC;AAChC,WAAO,KAAK,QAAQ,UAAU,KAAK,MAAM,YAAY,OAAO;AAAA,EAC9D;AAAA,EAEA,MAAM,iBACJ,MACA,QACA,SACkD;AAClD,WAAO,KAAK,QAAQ,qBAAqB,KAAK,MAAM,MAAM,QAAQ,OAAO;AAAA,EAC3E;AAAA,EAEA,MAAM,OAAO,SAA+C;AAC1D,WAAO,KAAK,QAAQ,SAAS,KAAK,MAAM,OAAO;AAAA,EACjD;AACF;;;ACsCO,IAAM,YAAY;AAAA,EACvB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,KAAK;AACP;;;AC/EO,IAAM,aAAN,cAAyB,YAAmC;AAAA,EAKjE,YAAY,SAA2B,CAAC,GAAG;AACzC,UAAM;AACN,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAI,SAA2B;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAY,gBAAwB;AAClC,WAAO,KAAK,QAAQ,mBAAmB;AAAA,EACzC;AAAA,EAEA,IAAY,OAAe;AACzB,WAAO,KAAK,QAAQ,MAAM,CAAC;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,GAAG,MAAgC;AACjC,WAAO,IAAI,eAAe,MAAM,QAAQ,KAAK,aAAa;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MACJ,KACA,QACA,SACmC;AACnC,WAAO,KAAK,UAAa,KAAK,eAAe,KAAK,QAAQ,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QACJ,KACA,QACA,SACkC;AAClC,WAAO,KAAK,YAAY,KAAK,eAAe,KAAK,QAAQ,OAAO;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MACJ,YACA,SACgC;AAChC,WAAO,KAAK,UAAU,KAAK,eAAe,YAAY,OAAO;AAAA,EAC/D;AAAA;AAAA,EAIA,MAAM,UACJ,QACA,KACA,QACA,SACmC;AACnC,WAAO,KAAK,cAAc,SAAS,QAAQ,YAAY;AACrD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,KAAK,CAAC;AAAA,MACrC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,UAAU;AAAA,UACV,EAAE,QAAQ,SAAS,KAAK,QAAQ,UAAU,CAAC,EAAE;AAAA,UAC7C,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,OAAO;AAAA,QACnD;AAEA,cAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YACJ,QACA,KACA,QACA,SACkC;AAClC,WAAO,KAAK,cAAc,WAAW,QAAQ,YAAY;AACvD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,KAAK,CAAC;AAAA,MACrC;AAEA,UAAI;AACF,cAAM,OAAgC;AAAA,UACpC,QAAQ;AAAA,UACR;AAAA,UACA,QAAQ,UAAU,CAAC;AAAA,QACrB;AACA,YAAI,SAAS,QAAQ;AACnB,eAAK,SAAS,QAAQ;AAAA,QACxB;AAEA,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,UAAU;AAAA,UACV;AAAA,UACA,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,SAAS;AAAA,QACrD;AAEA,cAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,UACJ,QACA,YACA,SACgC;AAChC,WAAO,KAAK,cAAc,SAAS,QAAQ,YAAY;AACrD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,KAAK,CAAC;AAAA,MACrC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,UAAU;AAAA,UACV,EAAE,QAAQ,SAAS,WAAW;AAAA,UAC9B,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,OAAO;AAAA,QACnD;AAEA,cAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,qBACJ,QACA,MACA,QACA,SACkD;AAClD,WAAO,KAAK,cAAc,oBAAoB,QAAQ,YAAY;AAChE,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,KAAK,CAAC;AAAA,MACrC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,UAAU;AAAA,UACV,EAAE,QAAQ,qBAAqB,MAAM,QAAQ,UAAU,CAAC,EAAE;AAAA,UAC1D,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,kBAAkB;AAAA,QAC9D;AAEA,cAAM,OAAQ,MAAM,SAAS,KAAK;AAGlC,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,SACJ,QACA,SACuB;AACvB,WAAO,KAAK,cAAc,UAAU,QAAQ,YAAY;AACtD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,KAAK,CAAC;AAAA,MACrC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,UAAU;AAAA,UACV,EAAE,QAAQ,SAAS;AAAA,UACnB,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,QAAQ;AAAA,QACpD;AAIA,cAAM,OAAO;AACb,YAAI,OAAO,KAAK,SAAS,YAAY;AACnC,gBAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,iBAAO,GAAG,IAAY;AAAA,QACxB;AAEA,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,eAAO,GAAG,IAAuB;AAAA,MACnC,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,OAAO,KAAK,CAAC;AAAA,MACpC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAIA,MAAc,UACZ,QACA,QACA,MACA,QACwB;AACxB,UAAM,UAAU,KAAK,QAAQ;AAC7B,UAAM,UAAU,KAAK,QAAQ,OAAO,SAAS,OAAO,QAAQ,MAAM;AAElE,WAAO,KAAK,QAAQ,MAAM,GAAG,KAAK,IAAI,WAAW;AAAA,MAC/C,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,GAAI;AAAA,QACJ,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ,KAAK,eAAe,MAAM;AAAA,IACpC,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,oBACZ,UACA,WACwB;AACxB,UAAM,YAAY,MAAM,SAAS,KAAK;AAEtC,QAAI,YAAiE,CAAC;AACtE,QAAI;AACF,kBAAY,KAAK,MAAM,SAAS;AAAA,IAClC,QAAQ;AAAA,IAER;AAEA,UAAM,YAAY,KAAK;AAAA,MACrB,SAAS;AAAA,MACT,UAAU;AAAA,IACZ;AACA,UAAM,UACJ,UAAU,WACV,OAAO,SAAS,YAAY,SAAS,MAAM,MAAM,SAAS;AAE5D,UAAM,OAAgC,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,WAAW;AAEjG,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,EAAE,UAAU,OAAO,IAAI,eAAe,SAAS;AACrD,UAAI,OAAQ,MAAK,iBAAiB;AAClC,UAAI,SAAU,MAAK,WAAW;AAAA,IAChC;AAEA,WAAO;AAAA,MACL,aAAa,WAAW,SAAS,OAAO,EAAE,KAAK,CAAC;AAAA,IAClD;AAAA,EACF;AAAA,EAEQ,yBACN,QACA,aACQ;AACR,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO,WAAW;AAAA,MACpB,KAAK;AACH,eAAO,WAAW;AAAA,MACpB,KAAK;AACH,YAAI,gBAAgB,0BAA0B;AAC5C,iBAAO,WAAW;AAAA,QACpB;AACA,eAAO,WAAW;AAAA,MACpB,KAAK;AACH,eAAO,WAAW;AAAA,MACpB,KAAK;AACH,eAAO,WAAW;AAAA,MACpB,KAAK;AACH,eAAO,WAAW;AAAA,MACpB;AACE,eAAO,WAAW;AAAA,IACtB;AAAA,EACF;AACF;AA1Ta,WACK,cAAc;;;ACZzB,IAAM,uBAAN,MAA4D;AAAA,EAIjE,YAAY,SAAwB,MAAc;AAChD,SAAK,UAAU;AACf,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,MAAM,MACJ,KACA,QACA,SACmC;AACnC,WAAO,KAAK,QAAQ,UAAa,KAAK,MAAM,KAAK,QAAQ,OAAO;AAAA,EAClE;AAAA,EAEA,MAAM,WACJ,KACA,QACA,SAC8B;AAC9B,WAAO,KAAK,QAAQ,eAAe,KAAK,MAAM,KAAK,QAAQ,OAAO;AAAA,EACpE;AAAA,EAEA,MAAM,QACJ,KACA,QACA,SACkC;AAClC,WAAO,KAAK,QAAQ,YAAY,KAAK,MAAM,KAAK,QAAQ,OAAO;AAAA,EACjE;AAAA,EAEA,MAAM,MACJ,YACA,SACgC;AAChC,WAAO,KAAK,QAAQ,UAAU,KAAK,MAAM,YAAY,OAAO;AAAA,EAC9D;AAAA,EAEA,MAAM,iBACJ,MACA,QACA,SACkD;AAClD,WAAO,KAAK,QAAQ,qBAAqB,KAAK,MAAM,MAAM,QAAQ,OAAO;AAAA,EAC3E;AAAA,EAEA,MAAM,SAAS,SAAsD;AACnE,WAAO,KAAK,QAAQ,WAAW,KAAK,MAAM,OAAO;AAAA,EACnD;AAAA,EAEA,MAAM,OAAO,SAAgD;AAC3D,WAAO,KAAK,QAAQ,WAAW,KAAK,MAAM,OAAO;AAAA,EACnD;AAAA,EAEA,MAAM,OAAO,MAAkB,SAAgD;AAC7E,WAAO,KAAK,QAAQ,WAAW,KAAK,MAAM,MAAM,OAAO;AAAA,EACzD;AACF;;;ACkFO,IAAM,eAAe;AAAA,EAC1B,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,KAAK;AACP;;;AC1IO,IAAM,gBAAN,cAA4B,YAAsC;AAAA,EAKvE,YAAY,SAA8B,CAAC,GAAG;AAC5C,UAAM;AACN,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAI,SAA8B;AAChC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAY,gBAAwB;AAClC,WAAO,KAAK,QAAQ,mBAAmB;AAAA,EACzC;AAAA,EAEA,IAAY,OAAe;AACzB,WAAO,KAAK,QAAQ,MAAM,CAAC;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,GAAG,MAAsC;AACvC,WAAO,IAAI,qBAAqB,MAAM,QAAQ,KAAK,aAAa;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MACJ,KACA,QACA,SACmC;AACnC,WAAO,KAAK,UAAa,KAAK,eAAe,KAAK,QAAQ,OAAO;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WACJ,KACA,QACA,SAC8B;AAC9B,WAAO,KAAK,eAAe,KAAK,eAAe,KAAK,QAAQ,OAAO;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QACJ,KACA,QACA,SACkC;AAClC,WAAO,KAAK,YAAY,KAAK,eAAe,KAAK,QAAQ,OAAO;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MACJ,YACA,SACgC;AAChC,WAAO,KAAK,UAAU,KAAK,eAAe,YAAY,OAAO;AAAA,EAC/D;AAAA;AAAA,EAIA,MAAM,UACJ,QACA,KACA,QACA,SACmC;AACnC,WAAO,KAAK,cAAgC,SAAS,QAAQ,YAAY;AACvE,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,QAAQ,CAAC;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,aAAa;AAAA,UACb,EAAE,QAAQ,SAAS,KAAK,QAAQ,UAAU,CAAC,EAAE;AAAA,UAC7C,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,OAAO;AAAA,QACnD;AAEA,cAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,UAAU,KAAK,CAAC;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,eACJ,QACA,KACA,QACA,SAC8B;AAC9B,WAAO,KAAK,cAA2B,cAAc,QAAQ,YAAY;AACvE,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,QAAQ,CAAC;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,aAAa;AAAA,UACb,EAAE,QAAQ,SAAS,KAAK,QAAQ,UAAU,CAAC,EAAE;AAAA,UAC7C,SAAS;AAAA,UACT,EAAE,QAAQ,sCAAsC;AAAA,QAClD;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,YAAY;AAAA,QACxD;AAEA,cAAM,SAAS,MAAM,SAAS,YAAY;AAC1C,eAAO,GAAG,MAAM;AAAA,MAClB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,UAAU,KAAK,CAAC;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YACJ,QACA,KACA,QACA,SACkC;AAClC,WAAO,KAAK,cAAc,WAAW,QAAQ,YAAY;AACvD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,QAAQ,CAAC;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,OAAgC;AAAA,UACpC,QAAQ;AAAA,UACR;AAAA,UACA,QAAQ,UAAU,CAAC;AAAA,QACrB;AACA,YAAI,SAAS,QAAQ;AACnB,eAAK,SAAS,QAAQ;AAAA,QACxB;AAEA,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,aAAa;AAAA,UACb;AAAA,UACA,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,SAAS;AAAA,QACrD;AAEA,cAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,UAAU,KAAK,CAAC;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,UACJ,QACA,YACA,SACgC;AAChC,WAAO,KAAK,cAAc,SAAS,QAAQ,YAAY;AACrD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,QAAQ,CAAC;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,OAAgC;AAAA,UACpC,QAAQ;AAAA,UACR;AAAA,QACF;AACA,YAAI,SAAS,kBAAkB,QAAW;AACxC,eAAK,gBAAgB,QAAQ;AAAA,QAC/B;AAEA,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,aAAa;AAAA,UACb;AAAA,UACA,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,OAAO;AAAA,QACnD;AAEA,cAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,UAAU,KAAK,CAAC;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,qBACJ,QACA,MACA,QACA,SACkD;AAClD,WAAO,KAAK,cAAc,oBAAoB,QAAQ,YAAY;AAChE,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,QAAQ,CAAC;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,aAAa;AAAA,UACb,EAAE,QAAQ,oBAAoB,MAAM,QAAQ,UAAU,CAAC,EAAE;AAAA,UACzD,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,kBAAkB;AAAA,QAC9D;AAEA,cAAM,OAAQ,MAAM,SAAS,KAAK;AAGlC,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,UAAU,KAAK,CAAC;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,WACJ,QACA,SAC6B;AAC7B,WAAO,KAAK,cAAc,YAAY,QAAQ,YAAY;AACxD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,QAAQ,CAAC;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,aAAa;AAAA,UACb,EAAE,QAAQ,WAAW;AAAA,UACrB,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,UAAU;AAAA,QACtD;AAEA,cAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,UAAU,KAAK,CAAC;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,WACJ,QACA,SACuB;AACvB,WAAO,KAAK,cAAc,UAAU,QAAQ,YAAY;AACtD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,QAAQ,CAAC;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,KAAK;AAAA,UAC1B;AAAA,UACA,aAAa;AAAA,UACb,EAAE,QAAQ,SAAS;AAAA,UACnB,SAAS;AAAA,QACX;AAEA,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,QAAQ;AAAA,QACpD;AAEA,cAAM,OAAO,MAAM,SAAS,KAAK;AACjC,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,UAAU,KAAK,CAAC;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,WACJ,QACA,MACA,SACuB;AACvB,WAAO,KAAK,cAAc,UAAU,QAAQ,YAAY;AACtD,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,IAAI,kBAAkB,QAAQ,CAAC;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,UAAU,KAAK,QAAQ;AAC7B,cAAM,UAAU,KAAK,QAAQ;AAAA,UAC3B;AAAA,UACA;AAAA,UACA;AAAA,UACA,aAAa;AAAA,QACf;AAEA,cAAM,WAAW,MAAM,KAAK,QAAQ,MAAM,GAAG,KAAK,IAAI,WAAW;AAAA,UAC/D,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,GAAI;AAAA,YACJ,gBAAgB;AAAA,UAClB;AAAA,UACA,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC;AAAA,UACrB,QAAQ,KAAK,eAAe,SAAS,MAAM;AAAA,QAC7C,CAAC;AAED,YAAI,CAAC,SAAS,IAAI;AAChB,iBAAO,KAAK,oBAAoB,UAAU,QAAQ;AAAA,QACpD;AAEA,eAAO,GAAG,MAAS;AAAA,MACrB,SAAS,OAAO;AACd,eAAO,IAAI,UAAU,UAAU,KAAK,CAAC;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAIA,MAAc,aACZ,QACA,QACA,MACA,QACA,cACwB;AACxB,UAAM,UAAU,KAAK,QAAQ;AAC7B,UAAM,UAAU,KAAK,QAAQ,OAAO,SAAS,UAAU,QAAQ,MAAM;AAErE,WAAO,KAAK,QAAQ,MAAM,GAAG,KAAK,IAAI,WAAW;AAAA,MAC/C,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,GAAI;AAAA,QACJ,gBAAgB;AAAA,QAChB,GAAG;AAAA,MACL;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ,KAAK,eAAe,MAAM;AAAA,IACpC,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,oBACZ,UACA,WACwB;AACxB,UAAM,YAAY,MAAM,SAAS,KAAK;AAEtC,QAAI,YAAiE,CAAC;AACtE,QAAI;AACF,kBAAY,KAAK,MAAM,SAAS;AAAA,IAClC,QAAQ;AAAA,IAER;AAEA,UAAM,YAAY,KAAK;AAAA,MACrB,SAAS;AAAA,MACT,UAAU;AAAA,IACZ;AACA,UAAM,UACJ,UAAU,WACV,UAAU,SAAS,YAAY,SAAS,MAAM,MAAM,SAAS;AAE/D,UAAM,OAAgC,EAAE,QAAQ,SAAS,QAAQ,YAAY,SAAS,WAAW;AAEjG,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAM,EAAE,UAAU,OAAO,IAAI,eAAe,SAAS;AACrD,UAAI,OAAQ,MAAK,iBAAiB;AAClC,UAAI,SAAU,MAAK,WAAW;AAAA,IAChC;AAEA,WAAO;AAAA,MACL,aAAa,WAAW,SAAS,UAAU,EAAE,KAAK,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEQ,yBACN,QACA,aACQ;AACR,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO,WAAW;AAAA,MACpB,KAAK;AACH,eAAO,WAAW;AAAA,MACpB,KAAK;AACH,YAAI,gBAAgB,6BAA6B;AAC/C,iBAAO,WAAW;AAAA,QACpB;AACA,eAAO,WAAW;AAAA,MACpB,KAAK;AACH,eAAO,WAAW;AAAA,MACpB,KAAK;AACH,eAAO,WAAW;AAAA,MACpB,KAAK;AACH,eAAO,WAAW;AAAA,MACpB;AACE,eAAO,WAAW;AAAA,IACtB;AAAA,EACF;AACF;AA5aa,cACK,cAAc;;;ACFhC,IAAM,aAAN,MAAkE;AAAA,EAAlE;AACE,SAAiB,SAAc,CAAC;AAChC,SAAiB,UAAsD,CAAC;AACxE,SAAQ,SAAS;AAAA;AAAA,EAEjB,CAAC,OAAO,aAAa,IAAsB;AACzC,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,OAAgB;AACnB,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,QAAQ,MAAM;AAClC,QAAI,QAAQ;AACV,aAAO,EAAE,OAAO,MAAM,MAAM,CAAC;AAC7B;AAAA,IACF;AAEA,SAAK,OAAO,KAAK,KAAK;AAAA,EACxB;AAAA,EAEA,QAAc;AACZ,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AAEA,SAAK,SAAS;AACd,WAAO,KAAK,QAAQ,SAAS,GAAG;AAC9B,YAAM,SAAS,KAAK,QAAQ,MAAM;AAClC,eAAS,EAAE,OAAO,QAAoB,MAAM,KAAK,CAAC;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,OAAmC;AACjC,QAAI,KAAK,OAAO,SAAS,GAAG;AAC1B,YAAM,QAAQ,KAAK,OAAO,MAAM;AAChC,aAAO,QAAQ,QAAQ,EAAE,OAAO,MAAM,MAAM,CAAC;AAAA,IAC/C;AAEA,QAAI,KAAK,QAAQ;AACf,aAAO,QAAQ,QAAQ,EAAE,OAAO,QAAoB,MAAM,KAAK,CAAC;AAAA,IAClE;AAEA,WAAO,IAAI,QAA2B,CAAC,YAAY;AACjD,WAAK,QAAQ,KAAK,OAAO;AAAA,IAC3B,CAAC;AAAA,EACH;AACF;AAEO,IAAM,eAAN,cAA2B,YAAqC;AAAA,EAUrE,YAAY,SAA6B,CAAC,GAAG;AAC3C,UAAM;AAPR,SAAiB,eAAoC,oBAAI,IAAI;AAG7D,SAAQ,gBAA+B,QAAQ,QAAQ;AACvD,SAAQ,mBAAmB;AAIzB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAI,SAA6B;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAY,OAAe;AACzB,WAAO,KAAK,QAAQ,QAAQ,KAAK,QAAQ,MAAM,CAAC;AAAA,EAClD;AAAA,EAEA,OAAO,UACL,eACA,UAA4B,CAAC,GACH;AAC1B,QAAI,CAAC,KAAK,YAAY,GAAG;AACvB,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AACA,QAAI,cAAc,WAAW,GAAG;AAC9B,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAEA,UAAM,aAAa,cAAc,IAAI,qBAAqB;AAC1D,UAAM,aAA6B;AAAA,MACjC,WAAW;AAAA,MACX,YAAY,QAAQ;AAAA,MACpB,OAAO,IAAI,WAAsB;AAAA,IACnC;AAEA,SAAK,aAAa,IAAI,UAAU;AAChC,UAAM,eAAe,MAAM;AACzB,WAAK,aAAa,OAAO,UAAU;AACnC,iBAAW,MAAM,MAAM;AACvB,WAAK,KAAK,4BAA4B;AAAA,IACxC;AAEA,QAAI,QAAQ,QAAQ;AAClB,UAAI,QAAQ,OAAO,SAAS;AAC1B,qBAAa;AAAA,MACf,OAAO;AACL,gBAAQ,OAAO,iBAAiB,SAAS,cAAc,EAAE,MAAM,KAAK,CAAC;AAAA,MACvE;AAAA,IACF;AAEA,SAAK,KAAK,4BAA4B;AAEtC,QAAI;AACF,uBAAiB,SAAS,WAAW,OAAO;AAC1C,cAAM;AAAA,MACR;AAAA,IACF,UAAE;AACA,UAAI,QAAQ,QAAQ;AAClB,gBAAQ,OAAO,oBAAoB,SAAS,YAAY;AAAA,MAC1D;AACA,mBAAa;AAAA,IACf;AAAA,EACF;AAAA,EAEA,MAAM,SACJ,SACoC;AACpC,QAAI,CAAC,KAAK,YAAY,GAAG;AACvB,aAAO,IAAI,kBAAkB,OAAO,CAAC;AAAA,IACvC;AAEA,QAAI,OAAO,QAAQ,WAAW,YAAY,QAAQ,OAAO,KAAK,EAAE,WAAW,GAAG;AAC5E,aAAO;AAAA,QACL;AAAA,UACE,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,EAAE,MAAM,EAAE,OAAO,SAAS,EAAE;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ,MAAM,GAAG,KAAK,IAAI,mBAAmB;AAAA,QACvE,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,GAAG;AAAA,YACD,KAAK;AAAA,cACH;AAAA,cACA,eAAe,QAAQ,SAAS,QAAQ,UAAU;AAAA,YACpD;AAAA,UACF;AAAA,UACA,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU;AAAA,UACnB,OAAO,QAAQ;AAAA,UACf,SAAS,QAAQ;AAAA,UACjB,YAAY,oBAAoB,QAAQ,UAAU;AAAA,UAClD,WAAW,QAAQ,aAAa,CAAC;AAAA,UACjC,aAAa,QAAQ;AAAA,UACrB,QAAQ,QAAQ;AAAA,QAClB,CAAC;AAAA,MACH,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,eAAO;AAAA,UACL,MAAM,cAAc,SAAS,8BAA8B,QAAQ;AAAA,QACrE;AAAA,MACF;AAEA,YAAM,OAAO,uBAAuB,MAAM,SAAS,KAAK,CAAC;AACzD,UAAI,CAAC,MAAM;AACT,eAAO;AAAA,UACL;AAAA,YACE;AAAA,YACA,IAAI,MAAM,wDAAwD;AAAA,UACpE;AAAA,QACF;AAAA,MACF;AAEA,aAAO,GAAG,IAAI;AAAA,IAChB,SAAS,OAAO;AACd,aAAO,IAAI,UAAU,SAAS,KAAK,CAAC;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAM,KACJ,UAAkC,CAAC,GACG;AACtC,QAAI,CAAC,KAAK,YAAY,GAAG;AACvB,aAAO,IAAI,kBAAkB,OAAO,CAAC;AAAA,IACvC;AAEA,QAAI;AACF,YAAM,QAAQ,IAAI,gBAAgB;AAClC,UAAI,QAAQ,OAAO;AACjB,cAAM,IAAI,SAAS,QAAQ,KAAK;AAAA,MAClC;AACA,UAAI,QAAQ,SAAS;AACnB,cAAM,IAAI,WAAW,QAAQ,OAAO;AAAA,MACtC;AACA,UAAI,QAAQ,YAAY;AACtB,cAAM,mBAAmB,oBAAoB,QAAQ,UAAU;AAC/D,YAAI,kBAAkB;AACpB,gBAAM,IAAI,UAAU,gBAAgB;AAAA,QACtC;AAAA,MACF;AAEA,YAAM,WAAW,MAAM,KAAK,QAAQ;AAAA,QAClC,GAAG,KAAK,IAAI,kBAAkB,MAAM,OAAO,IAAI,IAAI,MAAM,SAAS,CAAC,KAAK,EAAE;AAAA,QAC1E;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,KAAK;AAAA,cACH;AAAA,cACA,QAAQ,UACJ,eAAe,QAAQ,SAAS,QAAQ,UAAU,IAClD;AAAA,YACN;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,SAAS,IAAI;AAChB,eAAO;AAAA,UACL,MAAM,cAAc,SAAS,2BAA2B,QAAQ;AAAA,QAClE;AAAA,MACF;AAEA,YAAM,UAAU,MAAM,SAAS,KAAK;AACpC,YAAM,UAAU,2BAA2B,OAAO;AAClD,UAAI,CAAC,SAAS;AACZ,eAAO;AAAA,UACL;AAAA,YACE;AAAA,YACA,IAAI,MAAM,+CAA+C;AAAA,UAC3D;AAAA,QACF;AAAA,MACF;AAEA,aAAO,GAAG,OAAO;AAAA,IACnB,SAAS,OAAO;AACd,aAAO,IAAI,UAAU,SAAS,KAAK,CAAC;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAM,WACJ,IACA,UAAwC,CAAC,GAClB;AACvB,QAAI,CAAC,KAAK,YAAY,GAAG;AACvB,aAAO,IAAI,kBAAkB,OAAO,CAAC;AAAA,IACvC;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,QAAQ;AAAA,QAClC,GAAG,KAAK,IAAI,mBAAmB,mBAAmB,EAAE,CAAC;AAAA,QACrD;AAAA,UACE,QAAQ;AAAA,UACR,SAAS;AAAA,YACP,KAAK;AAAA,cACH;AAAA,cACA,QAAQ,SACJ;AAAA,gBACE,QAAQ,OAAO;AAAA,gBACf,QAAQ,OAAO;AAAA,cACjB,IACA,YAAY,EAAE;AAAA,YACpB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,SAAS,IAAI;AAChB,eAAO;AAAA,UACL,MAAM;AAAA,YACJ;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO,GAAG,MAAS;AAAA,IACrB,SAAS,OAAO;AACd,aAAO,IAAI,UAAU,SAAS,KAAK,CAAC;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAc,8BAA6C;AACzD,SAAK,gBAAgB,KAAK,cACvB,KAAK,MAAM,KAAK,oBAAoB,CAAC,EACrC,MAAM,MAAM,MAAS;AACxB,UAAM,KAAK;AAAA,EACb;AAAA,EAEA,MAAc,sBAAqC;AACjD,QAAI,CAAC,KAAK,YAAY,KAAK,KAAK,aAAa,SAAS,GAAG;AACvD,WAAK,kBAAkB;AACvB,WAAK,mBAAmB;AACxB;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK,yBAAyB;AAC5C,QAAI,MAAM,cAAc,KAAK,kBAAkB;AAC7C,WAAK,mBAAmB,MAAM;AAC9B,WAAK,kBAAkB;AAAA,IACzB;AAEA,QAAI,CAAC,KAAK,mBAAmB;AAC3B,WAAK,oBAAoB,KAAK,gBAAgB,KAAK,EAChD,MAAM,CAAC,UAAmB;AACzB,YAAI,CAAC,aAAa,KAAK,GAAG;AACxB,gBAAM;AAAA,QACR;AAAA,MACF,CAAC,EACA,QAAQ,MAAM;AACb,aAAK,oBAAoB;AACzB,aAAK,qBAAqB;AAC1B,YAAI,KAAK,aAAa,OAAO,GAAG;AAC9B,eAAK,KAAK,4BAA4B;AAAA,QACxC;AAAA,MACF,CAAC;AAAA,IACL;AAAA,EACF;AAAA,EAEQ,2BAIN;AACA,UAAM,SAAS,oBAAI,IAA8B;AACjD,UAAM,gBAA0B,CAAC;AAEjC,eAAW,cAAc,KAAK,cAAc;AAC1C,UAAI,OAAO,WAAW,eAAe,UAAU;AAC7C,sBAAc,KAAK,WAAW,UAAU;AAAA,MAC1C;AACA,iBAAW,gBAAgB,WAAW,WAAW;AAC/C,eAAO,IAAI,sBAAsB,YAAY,GAAG,YAAY;AAAA,MAC9D;AAAA,IACF;AAEA,UAAM,gBAAgB,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE;AAAA,MAAK,CAAC,MAAM,UACrD,sBAAsB,IAAI,EAAE,cAAc,sBAAsB,KAAK,CAAC;AAAA,IACxE;AACA,UAAM,aACJ,cAAc,SAAS,IAAI,KAAK,IAAI,GAAG,aAAa,IAAI;AAC1D,UAAM,YAAY,KAAK,UAAU;AAAA,MAC/B,eAAe,cAAc,IAAI,qBAAqB;AAAA,MACtD;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,gBAAgB,OAGZ;AAChB,UAAM,kBAAkB,IAAI,gBAAgB;AAC5C,SAAK,qBAAqB;AAE1B,QAAI;AACF,YAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,QAAQ,MAAM,CAAC;AACtD,YAAM,iBAAiB,MAAM,KAAK;AAAA,QAChC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,gBAAgB;AAAA,MAClB;AACA,YAAM,iBAAiB,MAAM,KAAK;AAAA,QAChC;AAAA,QACA,eAAe;AAAA,QACf,gBAAgB;AAAA,MAClB;AAEA,uBAAiB,WAAW;AAAA,QAC1B,eAAe;AAAA,QACf,gBAAgB;AAAA,MAClB,GAAG;AACD,YAAI,CAAC,QAAQ,MAAM;AACjB;AAAA,QACF;AACA,cAAM,QAAQ,eAAe,OAAO;AACpC,mBAAW,cAAc,KAAK,cAAc;AAC1C,cAAI,uBAAuB,OAAO,WAAW,SAAS,GAAG;AACvD,uBAAW,MAAM,KAAK,KAAK;AAAA,UAC7B;AAAA,QACF;AAAA,MACF;AAAA,IACF,UAAE;AACA,UAAI,KAAK,uBAAuB,iBAAiB;AAC/C,aAAK,qBAAqB;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,oBAA0B;AAChC,SAAK,oBAAoB,MAAM;AAAA,EACjC;AAAA,EAEQ,kBAAkB,QAAgB,MAA8B;AACtE,WAAO,KAAK,QAAQ,OAAO,KAAK,SAAS,SAAS,MAAM,MAAM;AAAA,EAChE;AAAA,EAEA,MAAc,eACZ,eACA,YACA,QAC6B;AAC7B,UAAM,OAAO,KAAK,QAAQ,QAAQ,KAAK,QAAQ,MAAM,CAAC;AACtD,UAAM,UAAU,KAAK,oBAAoB,aAAa;AACtD,UAAM,iBAAiB,MAAM,KAAK,QAAQ,MAAM,GAAG,IAAI,kBAAkB;AAAA,MACvE,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,GAAG,uBAAuB,OAAO;AAAA,QACjC,gBAAgB;AAAA,MAClB;AAAA,MACA,MAAM,KAAK,UAAU;AAAA,QACnB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,MACD;AAAA,IACF,CAAC;AAED,QAAI,CAAC,eAAe,IAAI;AACtB,YAAM,MAAM;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAc,MAAM,eAAe,KAAK;AAC9C,QAAI,CAAC,YAAY,QAAQ;AACvB,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,eACZ,MACA,QACA,QACwB;AACxB,UAAM,iBAAiB,MAAM,KAAK,QAAQ;AAAA,MACxC,GAAG,IAAI,wBAAwB,mBAAmB,MAAM,CAAC;AAAA,MACzD;AAAA,QACE,QAAQ;AAAA,QACR,SAAS,EAAE,QAAQ,oBAAoB;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,eAAe,IAAI;AACtB,YAAM,MAAM;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,oBACN,eACgB;AAChB,UAAM,UAA4B,cAAc,IAAI,CAAC,kBAAkB;AAAA,MACrE,SAAS,aAAa;AAAA,MACtB,SAAS;AAAA,MACT,MAAM,aAAa,aACf,GAAG,aAAa,OAAO,IAAI,aAAa,UAAU,KAClD,aAAa;AAAA,MACjB,QAAQ;AAAA,IACV,EAAE;AAEF,QAAI,KAAK,QAAQ,WAAW;AAC1B,aAAO,KAAK,QAAQ,UAAU,KAAK,SAAS,OAAO;AAAA,IACrD;AAEA,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,QAAQ,QAAQ,CAAC;AACvB,aAAO,KAAK,QAAQ;AAAA,QAClB,KAAK;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AA9ba,aACK,cAAc;AA+bhC,SAAS,eACP,SACA,YACQ;AACR,QAAM,aAAa,oBAAoB,UAAU;AACjD,SAAO,aAAa,GAAG,OAAO,IAAI,UAAU,KAAK;AACnD;AAEA,SAAS,sBACP,cACkB;AAClB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,YAAY,oBAAoB,aAAa,UAAU;AAAA,IACvD,WAAW,aAAa,aAAa,CAAC;AAAA,EACxC;AACF;AAEA,SAAS,sBAAsB,cAAwC;AACrE,SAAO,KAAK,UAAU;AAAA,IACpB,OAAO,aAAa;AAAA,IACpB,SAAS,aAAa;AAAA,IACtB,YAAY,aAAa,cAAc;AAAA,IACvC,WAAW,CAAC,GAAI,aAAa,aAAa,CAAC,CAAE,EAAE,KAAK;AAAA,EACtD,CAAC;AACH;AAEA,SAAS,uBACP,OACA,eACS;AACT,SAAO,cAAc;AAAA,IAAK,CAAC,iBACzB,oBAAoB,OAAO,YAAY;AAAA,EACzC;AACF;AAEA,SAAS,oBACP,OACA,cACS;AACT,MAAI,MAAM,UAAU,aAAa,OAAO;AACtC,WAAO;AAAA,EACT;AACA,MAAI,MAAM,YAAY,aAAa,SAAS;AAC1C,WAAO;AAAA,EACT;AACA,MAAI,aAAa,YAAY;AAC3B,UAAM,SAAS,aAAa,WAAW,SAAS,GAAG,IAC/C,aAAa,aACb,GAAG,aAAa,UAAU;AAC9B,QACE,MAAM,QACN,MAAM,SAAS,aAAa,cAC5B,CAAC,MAAM,KAAK,WAAW,MAAM,GAC7B;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,YAAY,aAAa,aAAa,CAAC;AAC7C,MAAI,UAAU,SAAS,KAAK,CAAC,UAAU,SAAS,MAAM,OAAO,GAAG;AAC9D,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,YAAyC;AACpE,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AACA,QAAM,UAAU,WAAW,QAAQ,cAAc,EAAE;AACnD,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,uBACP,SACwB;AACxB,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,WAAO,OAAO,YAAY,OAAO;AAAA,EACnC;AACA,SAAO,EAAE,GAAG,QAAQ;AACtB;AAEA,eAAe,cACb,SACA,SACA,UACuC;AACvC,MAAI,SAAS,SAAS;AACtB,MAAI;AACF,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI,MAAM;AACR,eAAS;AAAA,IACX;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AAAA,IACL;AAAA,IACA,IAAI,MAAM,GAAG,OAAO,KAAK,SAAS,MAAM,IAAI,MAAM,EAAE;AAAA,EACtD;AACF;AAEA,SAAS,aAAa,OAAyB;AAC7C,SAAO,iBAAiB,gBAAgB,MAAM,SAAS;AACzD;AAEA,gBAAgB,eACd,MACA,QACgC;AAChC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AAEA,QAAM,UAAU,IAAI,YAAY;AAChC,MAAI,SAAS;AAEb,mBAAiB,SAAS,eAAe,MAAM,MAAM,GAAG;AACtD,cAAU,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,EAAE,QAAQ,SAAS,IAAI;AAEvE,QAAI,iBAAiB,OAAO,QAAQ,MAAM;AAC1C,WAAO,kBAAkB,GAAG;AAC1B,YAAM,WAAW,OAAO,MAAM,GAAG,cAAc;AAC/C,eAAS,OAAO,MAAM,iBAAiB,CAAC;AACxC,YAAM,SAAS,cAAc,QAAQ;AACrC,UAAI,QAAQ;AACV,cAAM;AAAA,MACR;AACA,uBAAiB,OAAO,QAAQ,MAAM;AAAA,IACxC;AAAA,EACF;AAEA,YAAU,QAAQ,OAAO;AACzB,QAAM,WAAW,cAAc,OAAO,KAAK,CAAC;AAC5C,MAAI,UAAU;AACZ,UAAM;AAAA,EACR;AACF;AAEA,gBAAgB,eACd,MACA,QAC2B;AAC3B,QAAM,gBAAgB;AACtB,MAAI,OAAO,gBAAgB,OAAO,aAAa,MAAM,YAAY;AAC/D,qBAAiB,SAAS,eAAe;AACvC,UAAI,QAAQ,SAAS;AACnB;AAAA,MACF;AACA,YAAM;AAAA,IACR;AACA;AAAA,EACF;AAEA,QAAM,SAAS;AAQf,MAAI,OAAO,OAAO,cAAc,YAAY;AAC1C,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,QAAM,SAAS,OAAO,UAAU;AAChC,MAAI;AACF,WAAO,CAAC,QAAQ,SAAS;AACvB,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,MAAM;AACR;AAAA,MACF;AACA,UAAI,OAAO;AACT,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,UAAE;AACA,QAAI;AACF,YAAM,OAAO,SAAS;AAAA,IACxB,QAAQ;AAAA,IAER;AACA,WAAO,cAAc;AAAA,EACvB;AACF;AAEA,SAAS,cAAc,UAA0C;AAC/D,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ;AACZ,MAAI;AACJ,QAAM,YAAsB,CAAC;AAE7B,aAAW,QAAQ,SAAS,MAAM,IAAI,GAAG;AACvC,QAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,GAAG;AACjC;AAAA,IACF;AACA,UAAM,CAAC,OAAO,GAAG,IAAI,IAAI,KAAK,MAAM,GAAG;AACvC,UAAM,QAAQ,KAAK,KAAK,GAAG,EAAE,QAAQ,MAAM,EAAE;AAC7C,YAAQ,OAAO;AAAA,MACb,KAAK;AACH,gBAAQ;AACR;AAAA,MACF,KAAK;AACH,aAAK;AACL;AAAA,MACF,KAAK;AACH,kBAAU,KAAK,KAAK;AACpB;AAAA,MACF;AACE;AAAA,IACJ;AAAA,EACF;AAEA,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM,UAAU,KAAK,IAAI;AAAA,EAC3B;AACF;AAEA,SAAS,eAAe,SAAqC;AAC3D,QAAM,SAAS,KAAK,MAAM,QAAQ,IAAI;AACtC,SAAO;AAAA,IACL,MAAM;AAAA,IACN,IAAI,OAAO,MAAM,QAAQ,MAAM;AAAA,IAC/B,OAAO,OAAO,SAAS;AAAA,IACvB,SAAS,OAAO,WAAW;AAAA,IAC3B,SAAS,OAAO,WAAW;AAAA,IAC3B,MAAM,OAAO;AAAA,IACb,OAAO,OAAO,SAAS;AAAA,IACvB,OAAO,OAAO,SAAS;AAAA,IACvB,YAAY,OAAO,cAAc;AAAA,IACjC,WAAW,OAAO,aAAa;AAAA,EACjC;AACF;AAEA,SAAS,uBAAuB,MAAyC;AACvE,MAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,kBAAkB,IAAI;AACrC,QAAM,YACJ,kBAAkB,MAAM,KACxB,uBAAuB,OAAO,OAAO,KACrC,uBAAuB,OAAO,IAAI,KAClC,uBAAuB,OAAO,YAAY,KAC1C,uBAAuB,OAAO,IAAI;AACpC,SAAO,aAAa;AACtB;AAEA,SAAS,2BAA2B,MAA2C;AAC7E,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,UAAM,UAAU,KACb,IAAI,CAAC,UAAU,uBAAuB,KAAK,CAAC,EAC5C,OAAO,CAAC,UAAsC,UAAU,IAAI;AAC/D,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,kBAAkB,IAAI;AACrC,QAAM,SACJ,iBAAiB,OAAO,QAAQ,KAChC,iBAAiB,OAAO,aAAa,KACrC,iBAAiB,OAAO,KAAK,KAC7B,iBAAiB,OAAO,IAAI;AAC9B,MAAI,QAAQ;AACV,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,kBAAkB,MAAM;AACvC,SAAO,SAAS,CAAC,MAAM,IAAI;AAC7B;AAEA,SAAS,iBAAiB,OAA4C;AACpE,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,MACb,IAAI,CAAC,UAAU,uBAAuB,KAAK,CAAC,EAC5C,OAAO,CAAC,UAAsC,UAAU,IAAI;AAC/D,SAAO;AACT;AAEA,SAAS,kBACP,OAC0B;AAC1B,QAAM,KAAK,YAAY,OAAO,IAAI;AAClC,QAAM,QAAQ,YAAY,OAAO,OAAO,KAAK,YAAY,OAAO,SAAS;AACzE,QAAM,UAAU,YAAY,OAAO,SAAS;AAC5C,QAAM,cACJ,YAAY,OAAO,aAAa,KAAK,YAAY,OAAO,cAAc;AACxE,MAAI,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,aAAa;AAC7C,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,YACE,oBAAoB,OAAO,YAAY,KACvC,oBAAoB,OAAO,aAAa;AAAA,IAC1C,WACE,iBAAiB,OAAO,WAAW,KACnC,uBAAuB,OAAO,eAAe,KAC7C,uBAAuB,OAAO,gBAAgB;AAAA,IAChD;AAAA,IACA,QAAQ,aAAa,OAAO,QAAQ,KAAK;AAAA,IACzC,WACE,YAAY,OAAO,WAAW,KAC9B,YAAY,OAAO,YAAY,MAC/B,oBAAI,KAAK,GAAE,YAAY;AAAA,IACzB,eACE,oBAAoB,OAAO,eAAe,KAC1C,oBAAoB,OAAO,gBAAgB;AAAA,EAC/C;AACF;AAEA,SAAS,kBAAkB,OAAwC;AACjE,SAAO;AACT;AAEA,SAAS,YACP,OACA,KACoB;AACpB,QAAM,QAAQ,MAAM,GAAG;AACvB,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAEA,SAAS,oBACP,OACA,KACoB;AACpB,SAAO,YAAY,OAAO,GAAG;AAC/B;AAEA,SAAS,aACP,OACA,KACqB;AACrB,QAAM,QAAQ,MAAM,GAAG;AACvB,SAAO,OAAO,UAAU,YAAY,QAAQ;AAC9C;AAEA,SAAS,iBACP,OACA,KACsB;AACtB,QAAM,QAAQ,MAAM,GAAG;AACvB,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM;AAAA,IACpB,CAAC,SAAyB,OAAO,SAAS;AAAA,EAC5C;AACA,SAAO,QAAQ,WAAW,MAAM,SAAS,UAAU;AACrD;AAEA,SAAS,uBACP,OACA,KACsB;AACtB,QAAM,QAAQ,MAAM,GAAG;AACvB,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,QAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,aAAO;AAAA,IACT;AACA,UAAM,UAAU,OAAO;AAAA,MACrB,CAAC,SAAyB,OAAO,SAAS;AAAA,IAC5C;AACA,WAAO,QAAQ,WAAW,OAAO,SAAS,UAAU;AAAA,EACtD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AC74BO,IAAM,iBAAN,MAAqB;AAAA,EAI1B,YAAY,SAAsB,CAAC,GAAG;AAFtC,SAAQ,WAA0B;AAGhC,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA,EAGA,YAAY,KAA0B;AACpC,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA,EAGA,IAAI,YAAqB;AACvB,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA;AAAA,EAGA,MAAM,SAAS,SAA8C;AAC3D,QAAI,CAAC,KAAK,SAAU,QAAO;AAE3B,UAAM,OAAO,MAAM;AAAA,MACjB,GAAG,KAAK,QAAQ,cAAc,mBAAmB,OAAO,CAAC;AAAA,IAC3D;AACA,QAAI,CAAC,KAAK,GAAI,QAAO;AAErB,UAAM,OAAQ,MAAM,KAAK,KAAK;AAC9B,WAAO;AAAA,MACL,YAAY,KAAK,uBAAuB;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA,EAGA,iBAAiB,MAA8B;AAC7C,SAAK,OAAO,oBAAoB,IAAI;AAAA,EACtC;AACF;;;ACyCO,IAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,qBAAqB;AAAA,EAChC,KAAK;AAAA,IACH,eAAe,CAAC,YAAoB,6BAA6B,OAAO;AAAA,IACxE,iBAAiB;AAAA,EACnB;AACF;AAEO,IAAM,wBAAwB;AAG9B,IAAM,eAAe;AAAA,EAC1B,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,KAAK;AAAA,EACL,cAAc;AAAA,EACd,eAAe;AAAA,EACf,SAAS;AACX;;;AC/EA,IAAM,UAAU;AAChB,IAAM,aAAa;AACnB,IAAM,aAAa;AACnB,IAAM,cAAc;AAGpB,SAAS,YAAqB;AAC5B,MAAI;AACF,WACE,OAAO,cAAc,eACrB,OAAO,WAAW,eAClB,OAAO,OAAO,WAAW;AAAA,EAE7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGA,SAAS,SAA+B;AACtC,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,UAAU,UAAU,KAAK,SAAS,UAAU;AAClD,YAAQ,kBAAkB,MAAM;AAC9B,YAAM,KAAK,QAAQ;AACnB,UAAI,CAAC,GAAG,iBAAiB,SAAS,UAAU,GAAG;AAC7C,WAAG,kBAAkB,UAAU;AAAA,MACjC;AAAA,IACF;AACA,YAAQ,YAAY,MAAM,QAAQ,QAAQ,MAAM;AAChD,YAAQ,UAAU,MAAM,OAAO,QAAQ,KAAK;AAAA,EAC9C,CAAC;AACH;AAGA,SAAS,OAAU,IAAiB,KAAqC;AACvE,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,KAAK,GAAG,YAAY,YAAY,UAAU;AAChD,UAAM,QAAQ,GAAG,YAAY,UAAU;AACvC,UAAM,MAAM,MAAM,IAAI,GAAG;AACzB,QAAI,YAAY,MAAM,QAAQ,IAAI,MAAuB;AACzD,QAAI,UAAU,MAAM,OAAO,IAAI,KAAK;AAAA,EACtC,CAAC;AACH;AAGA,SAAS,OAAO,IAAiB,KAAa,OAA+B;AAC3E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,KAAK,GAAG,YAAY,YAAY,WAAW;AACjD,UAAM,QAAQ,GAAG,YAAY,UAAU;AACvC,UAAM,MAAM,MAAM,IAAI,OAAO,GAAG;AAChC,QAAI,YAAY,MAAM,QAAQ;AAC9B,QAAI,UAAU,MAAM,OAAO,IAAI,KAAK;AAAA,EACtC,CAAC;AACH;AAGA,SAAS,UAAU,IAAiB,KAA4B;AAC9D,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,KAAK,GAAG,YAAY,YAAY,WAAW;AACjD,UAAM,QAAQ,GAAG,YAAY,UAAU;AACvC,UAAM,MAAM,MAAM,OAAO,GAAG;AAC5B,QAAI,YAAY,MAAM,QAAQ;AAC9B,QAAI,UAAU,MAAM,OAAO,IAAI,KAAK;AAAA,EACtC,CAAC;AACH;AAGA,SAAS,QAAQ,IAAoC;AACnD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,KAAK,GAAG,YAAY,YAAY,UAAU;AAChD,UAAM,QAAQ,GAAG,YAAY,UAAU;AACvC,UAAM,MAAM,MAAM,WAAW;AAC7B,QAAI,YAAY,MACd,QAAS,IAAI,OAAyB,OAAO,CAAC,MAAM,OAAO,MAAM,QAAQ,CAAa;AACxF,QAAI,UAAU,MAAM,OAAO,IAAI,KAAK;AAAA,EACtC,CAAC;AACH;AAWA,eAAe,WAAW,IAAqC;AAC7D,QAAM,WAAW,MAAM,OAAkB,IAAI,WAAW;AACxD,MAAI,SAAU,QAAO;AAErB,QAAM,MAAM,MAAM,OAAO,OAAO;AAAA,IAC9B,EAAE,MAAM,WAAW,QAAQ,IAAI;AAAA,IAC/B;AAAA;AAAA,IACA,CAAC,WAAW,SAAS;AAAA,EACvB;AACA,QAAM,OAAO,IAAI,aAAa,GAAG;AACjC,SAAO;AACT;AAGA,eAAe,WACb,SACA,UACyB;AACzB,QAAM,KAAK,OAAO,gBAAgB,IAAI,WAAW,EAAE,CAAC;AACpD,QAAM,aAAa,IAAI;AAAA,IACrB,MAAM,OAAO,OAAO,QAAQ,EAAE,MAAM,WAAW,GAAG,GAAG,SAAS,QAAQ;AAAA,EACxE;AACA,SAAO,EAAE,IAAI,WAAW;AAC1B;AAGA,eAAe,WACb,SACA,OACqB;AACrB,QAAM,YAAY,MAAM,OAAO,OAAO;AAAA,IACpC,EAAE,MAAM,WAAW,IAAI,MAAM,GAAG;AAAA,IAChC;AAAA,IACA,MAAM;AAAA,EACR;AACA,SAAO,IAAI,WAAW,SAAS;AACjC;AAGA,SAAS,SAAS,SAAyB;AACzC,SAAO,OAAO,OAAO;AACvB;AAUA,eAAsB,oBACpB,SAC4B;AAC5B,MAAI,CAAC,UAAU,EAAG,QAAO;AACzB,MAAI;AACF,UAAM,KAAK,MAAM,OAAO;AACxB,UAAM,QAAQ,MAAM,OAAuB,IAAI,SAAS,OAAO,CAAC;AAChE,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,UAAU,MAAM,WAAW,EAAE;AACnC,WAAO,MAAM,WAAW,SAAS,KAAK;AAAA,EACxC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,eAAsB,eACpB,SACA,UACe;AACf,MAAI,CAAC,UAAU,EAAG;AAClB,MAAI;AACF,UAAM,KAAK,MAAM,OAAO;AACxB,UAAM,UAAU,MAAM,WAAW,EAAE;AACnC,UAAM,YAAY,MAAM,WAAW,SAAS,QAAQ;AACpD,UAAM,OAAO,IAAI,SAAS,OAAO,GAAG,SAAS;AAAA,EAC/C,QAAQ;AAAA,EAER;AACF;AAMA,eAAsB,oBACpB,SACe;AACf,MAAI,CAAC,UAAU,EAAG;AAClB,MAAI;AACF,UAAM,KAAK,MAAM,OAAO;AACxB,QAAI,SAAS;AACX,YAAM,UAAU,IAAI,SAAS,OAAO,CAAC;AAAA,IACvC,OAAO;AAEL,YAAM,OAAO,MAAM,QAAQ,EAAE;AAC7B,iBAAW,KAAK,MAAM;AACpB,YAAI,EAAE,WAAW,MAAM,GAAG;AACxB,gBAAM,UAAU,IAAI,CAAC;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACF;;;ACrIA,SAAS,QAAQ,OAAuB;AACtC,MAAI,iBAAiB,MAAO,QAAO;AACnC,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO,IAAI,MAAM,KAAK,UAAU,KAAK,CAAC;AAAA,EACxC;AACA,SAAO,IAAI,MAAM,OAAO,KAAK,CAAC;AAChC;AAEA,SAAS,QAAQ,KAAyB;AACxC,SAAO,IAAI,YAAY,EAAE,OAAO,GAAG;AACrC;AAEA,SAAS,UAAU,OAA2B;AAC5C,SAAO,IAAI,YAAY,EAAE,OAAO,KAAK;AACvC;AAEA,SAAS,UAAU,OAA2B;AAC5C,SAAO,MAAM,KAAK,KAAK,EACpB,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAC1C,KAAK,EAAE;AACZ;AAEA,SAAS,eAAe,QAAkC;AACxD,QAAM,QAAQ,OAAO,OAAO,CAAC,KAAK,QAAQ,MAAM,IAAI,QAAQ,CAAC;AAC7D,QAAM,SAAS,IAAI,WAAW,KAAK;AACnC,MAAI,SAAS;AACb,aAAW,OAAO,QAAQ;AACxB,WAAO,IAAI,KAAK,MAAM;AACtB,cAAU,IAAI;AAAA,EAChB;AACA,SAAO;AACT;AAEA,SAAS,aAAa,OAA2B;AAC/C,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,cAAU,OAAO,aAAa,MAAM,CAAC,CAAC;AAAA,EACxC;AACA,SAAO,KAAK,MAAM;AACpB;AAEA,SAAS,aAAa,KAAyB;AAC7C,QAAM,SAAS,KAAK,GAAG;AACvB,QAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;AAC1C,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,EAChC;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,OAAgC;AAC3D,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AAAqB,aAAO,MAAM,WAAW;AAAA,IAClD,KAAK;AAAiB,aAAO,MAAM,WAAW,kBAAkB,MAAM,GAAG;AAAA,IACzE,KAAK;AAAmB,aAAO,MAAM,WAAW;AAAA,IAChD,KAAK;AAAmB,aAAO,MAAM,WAAW,oBAAoB,MAAM,OAAO,MAAM,MAAM,GAAG;AAAA,IAChG,KAAK;AAAgB,aAAO,MAAM,WAAW;AAAA,IAC7C,KAAK;AAAwB,aAAO,MAAM,WAAW,4BAA4B,MAAM,GAAG;AAAA,IAC1F,KAAK;AAAiB,aAAO,MAAM,WAAW,MAAM,MAAM;AAAA,EAC5D;AACF;AAEA,SAAS,WAAW,OAAmD;AACrE,QAAM,QAAoB;AAAA,IACxB,GAAG;AAAA,IACH,SAAS;AAAA,IACT,SAAS,oBAAoB,KAAK;AAAA,EACpC;AACA,SAAO,EAAE,IAAI,OAAO,MAAM;AAC5B;AA8BO,IAAM,mBAAN,cAA+B,YAAyC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwB7E,YAAY,QAAgC;AAC1C,UAAM;AAdR,SAAQ,YAA+B;AACvC,SAAQ,qBAGG;AACX,SAAQ,cAAc;AAUpB,SAAK,cAAc;AACnB,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAiC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,aAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,YAAwB;AAC1B,QAAI,CAAC,KAAK,oBAAoB;AAC5B,YAAM,IAAI,MAAM,iBAAiB;AAAA,IACnC;AACA,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,SAAsB;AAChC,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,KAAK;AACf,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAY,OAAe;AACzB,WAAO,KAAK,GAAG,MAAM,CAAC;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,OACJ,QACmC;AACnC,WAAO,KAAK,cAAc,UAAU,QAAW,YAAY;AACzD,YAAM,UAAU,KAAK,YAAY;AACjC,YAAM,gBAAgB,mBAAmB,qBAAqB;AAC9D,YAAM,iBAAiB,gBAAgB,OAAO;AAC9C,YAAM,mBAAmB,kBAAkB,KAAK,GAAG,OAAO;AAE1D,UAAI;AAIF,YAAI,iBAAiB,MAAM,oBAAoB,cAAc;AAE7D,YAAI,CAAC,gBAAgB;AACnB,cAAI,CAAC,QAAQ;AACX,mBAAO,WAAW;AAAA,cAChB,MAAM;AAAA,cACN,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AACA,gBAAM,IAAI;AACV,gBAAM,MAAM,MAAM,EAAE,YAAY,cAAc,cAAc,OAAO,CAAC;AACpE,2BAAiB,QAAQ,GAAG;AAC5B,gBAAM,eAAe,gBAAgB,cAAc;AAAA,QACrD;AAGA,aAAK,YAAY,KAAK,OAAO;AAAA,UAC3B;AAAA,UACA,KAAK,OAAO,OAAO,QAAQ,OAAO,CAAC;AAAA,UACnC,QAAQ,cAAc;AAAA,QACxB;AAKA,cAAM,gBAAgB,KAAK,GAAG,kBAAkB,KAAK,GAAG,SAAS,KAAK,GAAG,OAAO;AAGhF,YAAI,iBAAgC;AACpC,YAAI;AACF,gBAAM,WAAW,MAAM,KAAK,GAAG;AAAA,YAC7B,KAAK;AAAA,YAAM;AAAA,YAAe;AAAA,UAC5B;AACA,cAAI,SAAS,MAAM,SAAS,MAAM;AAChC,6BAAiB,SAAS;AAAA,UAC5B;AAAA,QACF,QAAQ;AAAA,QAER;AAEA,YAAI,gBAAgB;AAElB,eAAK,qBAAqB;AAAA,YACxB,WAAW,aAAa,cAAc;AAAA,YACtC,YAAY,IAAI,WAAW,CAAC;AAAA;AAAA,UAC9B;AAAA,QACF,OAAO;AAEL,cAAI,mBAAmB,MAAM,oBAAoB,gBAAgB;AAEjE,cAAI,CAAC,kBAAkB;AACrB,gBAAI,CAAC,QAAQ;AAGX,mBAAK,qBAAqB;AAC1B,mBAAK,cAAc;AACnB,qBAAO,GAAG,MAAS;AAAA,YACrB;AACA,kBAAM,IAAI;AACV,kBAAM,MAAM,MAAM,EAAE,YAAY,cAAc,eAAe;AAC7D,+BAAmB,QAAQ,GAAG;AAC9B,kBAAM,eAAe,kBAAkB,gBAAgB;AAAA,UACzD;AAGA,gBAAM,OAAO,KAAK,OAAO;AAAA,YACvB;AAAA,YACA,QAAQ,kBAAkB;AAAA,YAC1B,QAAQ,qBAAqB;AAAA,UAC/B;AACA,eAAK,qBAAqB,KAAK,OAAO,eAAe,IAAI;AAGzD,cAAI;AACF,kBAAM,YAAY,aAAa,KAAK,mBAAmB,SAAS;AAChE,kBAAM,KAAK,GAAG,kBAAkB;AAChC,kBAAM,KAAK,GAAG,SAAS,IAAI,4BAA4B,SAAS;AAChE,kBAAM,KAAK,GAAG,SAAS,IAAI,6BAA6B,qBAAqB;AAC7E,kBAAM,KAAK,GAAG,SAAS,IAAI,2BAA2B,KAAK,YAAY,OAAO;AAAA,UAChF,QAAQ;AAAA,UAER;AAAA,QACF;AAEA,aAAK,cAAc;AACnB,eAAO,GAAG,MAAS;AAAA,MACrB,SAAS,OAAO;AAEd,aAAK,YAAY;AACjB,aAAK,qBAAqB;AAC1B,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,OACE,QAAQ,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAW,SAAiC;AAChD,QAAI,SAAS;AACX,YAAM,oBAAoB,gBAAgB,OAAO,EAAE;AAAA,IACrD,OAAO;AACL,YAAM,oBAAoB;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AACX,SAAK,YAAY;AACjB,SAAK,qBAAqB;AAC1B,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAkB;AAChB,SAAK,KAAK;AACV,UAAM,UAAU;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IACJ,KACA,OACA,SACmC;AACnC,WAAO,KAAK,cAAc,OAAO,KAAK,YAAY;AAChD,UAAI,CAAC,KAAK,eAAe,CAAC,KAAK,WAAW;AACxC,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI;AAEF,YAAI;AACJ,YAAI,iBAAiB,YAAY;AAC/B,sBAAY;AAAA,QACd,WAAW,SAAS,WAAW;AAC7B,sBAAY,QAAQ,UAAU,KAAK;AAAA,QACrC,WAAW,OAAO,UAAU,UAAU;AACpC,sBAAY,QAAQ,KAAK;AAAA,QAC3B,OAAO;AACL,sBAAY,QAAQ,KAAK,UAAU,KAAK,CAAC;AAAA,QAC3C;AAEA,cAAM,cACJ,SAAS,gBACR,iBAAiB,aACd,6BACA;AAGN,cAAM,WAAW,KAAK,OAAO,YAAY,EAAE;AAC3C,cAAM,QAAQ,UAAU,KAAK,OAAO,OAAO,QAAQ,CAAC,EAAE,MAAM,GAAG,EAAE;AAGjE,cAAM,YAAY,KAAK,OAAO,QAAQ,UAAU,SAAS;AAGzD,cAAM,UAAU,KAAK,OAAO,QAAQ,KAAK,WAAW,QAAQ;AAG5D,cAAM,WAAmC;AAAA,UACvC,CAAC,aAAa,OAAO,GAAG;AAAA,UACxB,CAAC,aAAa,MAAM,GAAG;AAAA,UACvB,CAAC,aAAa,MAAM,GAAG;AAAA,UACvB,CAAC,aAAa,YAAY,GAAG;AAAA,UAC7B,CAAC,aAAa,GAAG,GAAG;AAAA,UACpB,CAAC,aAAa,YAAY,GACxB,KAAK,YAAY,eAAe;AAAA,UAClC,GAAI,SAAS,YAAY,CAAC;AAAA,QAC5B;AAGA,cAAM,cAAc,KAAK,UAAU;AAAA,UACjC;AAAA,UACA;AAAA,UACA,GAAG;AAAA,QACL,CAAC;AACD,cAAM,aAAa,KAAK,UAAU;AAAA,UAChC,KAAK,aAAa,OAAO;AAAA,UACzB,UAAU;AAAA,QACZ,CAAC;AACD,cAAM,eAAe,MAAM,KAAK,GAAG,GAAG;AAAA,UACpC,QAAQ,GAAG;AAAA,UACX;AAAA,QACF;AACA,YAAI,CAAC,aAAa,IAAI;AACpB,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,IAAI;AAAA,cACT,6BAA6B,aAAa,MAAM,OAAO;AAAA,YACzD;AAAA,UACF,CAAC;AAAA,QACH;AAGA,cAAM,eAAe,KAAK,UAAU;AAAA,UAClC,MAAM,aAAa,SAAS;AAAA,UAC5B;AAAA,QACF,CAAC;AACD,cAAM,iBAAiB,MAAM,KAAK,GAAG,GAAG;AAAA,UACtC,SAAS,GAAG;AAAA,UACZ;AAAA,QACF;AACA,YAAI,CAAC,eAAe,IAAI;AACtB,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,IAAI;AAAA,cACT,oCAAoC,eAAe,MAAM,OAAO;AAAA,YAClE;AAAA,UACF,CAAC;AAAA,QACH;AAEA,eAAO,GAAG,MAAS;AAAA,MACrB,SAAS,OAAO;AACd,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,OACE,QAAQ,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,IACJ,KACA,SAC4C;AAC5C,WAAO,KAAK,cAAc,OAAO,KAAK,YAAY;AAChD,UAAI,CAAC,KAAK,eAAe,CAAC,KAAK,WAAW;AACxC,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI;AAEF,cAAM,YAAY,MAAM,KAAK,GAAG,GAAG,IAAY,QAAQ,GAAG,IAAI;AAAA,UAC5D,KAAK;AAAA,QACP,CAAC;AACD,YAAI,CAAC,UAAU,IAAI;AACjB,iBAAO,WAAW,EAAE,MAAM,iBAAiB,IAAI,CAAC;AAAA,QAClD;AAEA,cAAM,cAAc,KAAK,MAAM,UAAU,KAAK,IAAc;AAC5D,cAAM,eAAe,aAAa,YAAY,GAAG;AACjD,cAAM,WAAW,KAAK,OAAO,QAAQ,KAAK,WAAW,YAAY;AAGjE,cAAM,cAAc,MAAM,KAAK,GAAG,GAAG,IAAY,SAAS,GAAG,IAAI;AAAA,UAC/D,KAAK;AAAA,QACP,CAAC;AACD,YAAI,CAAC,YAAY,IAAI;AACnB,iBAAO,WAAW,EAAE,MAAM,iBAAiB,IAAI,CAAC;AAAA,QAClD;AAEA,cAAM,gBAAgB,KAAK,MAAM,YAAY,KAAK,IAAc;AAChE,cAAM,iBAAiB,aAAa,cAAc,IAAI;AACtD,cAAM,YAAY,KAAK,OAAO,QAAQ,UAAU,cAAc;AAG9D,cAAM,WAAmC,cAAc,YAAY,CAAC;AACpE,cAAM,cACJ,SAAS,aAAa,YAAY,KAAK;AACzC,cAAM,QAAQ,SAAS,aAAa,MAAM,KAAK;AAG/C,YAAI;AACJ,YAAI,SAAS,KAAK;AAChB,kBAAQ;AAAA,QACV,WAAW,SAAS,aAAa;AAC/B,kBAAQ,QAAQ,YAAY,SAAS;AAAA,QACvC,WAAW,gBAAgB,oBAAoB;AAC7C,kBAAQ,KAAK,MAAM,UAAU,SAAS,CAAC;AAAA,QACzC,OAAO;AACL,kBAAQ;AAAA,QACV;AAEA,eAAO,GAAG,EAAE,OAAO,UAAU,MAAM,CAAC;AAAA,MACtC,SAAS,OAAO;AACd,YACE,iBAAiB,SACjB,MAAM,QAAQ,SAAS,YAAY,GACnC;AACA,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,SAAS,MAAM;AAAA,UACjB,CAAC;AAAA,QACH;AACA,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,OACE,QAAQ,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAO,KAAgD;AAC3D,WAAO,KAAK,cAAc,UAAU,KAAK,YAAY;AACnD,UAAI,CAAC,KAAK,aAAa;AACrB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI;AAEF,cAAM,CAAC,cAAc,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA,UACvD,KAAK,GAAG,GAAG,OAAO,QAAQ,GAAG,EAAE;AAAA,UAC/B,KAAK,GAAG,GAAG,OAAO,SAAS,GAAG,EAAE;AAAA,QAClC,CAAC;AAED,YAAI,CAAC,aAAa,MAAM,CAAC,eAAe,IAAI;AAC1C,iBAAO,WAAW,EAAE,MAAM,iBAAiB,IAAI,CAAC;AAAA,QAClD;AAEA,eAAO,GAAG,MAAS;AAAA,MACrB,SAAS,OAAO;AACd,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,OACE,QAAQ,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KACJ,SACuC;AACvC,WAAO,KAAK,cAAc,QAAQ,SAAS,QAAQ,YAAY;AAC7D,UAAI,CAAC,KAAK,aAAa;AACrB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI;AACF,cAAM,aAAa,SAAS,SACxB,SAAS,QAAQ,MAAM,KACvB;AAEJ,cAAM,aAAa,MAAM,KAAK,GAAG,GAAG,KAAK;AAAA,UACvC,QAAQ;AAAA,UACR,cAAc;AAAA,QAChB,CAAC;AAED,YAAI,CAAC,WAAW,IAAI;AAClB,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,IAAI;AAAA,cACT,8BAA8B,WAAW,MAAM,OAAO;AAAA,YACxD;AAAA,UACF,CAAC;AAAA,QACH;AAGA,YAAI,OAAO,WAAW,KAAK;AAG3B,YAAI,SAAS,gBAAgB,QAAQ,QAAQ;AAC3C,gBAAM,aAAa,QAAQ,OAAO,SAAS,GAAG,IAC1C,QAAQ,SACR,GAAG,QAAQ,MAAM;AACrB,iBAAO,KAAK;AAAA,YAAI,CAAC,MACf,EAAE,WAAW,UAAU,IAAI,EAAE,MAAM,WAAW,MAAM,IAAI;AAAA,UAC1D;AAAA,QACF;AAEA,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,OACE,QAAQ,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,KACJ,KACqD;AACrD,WAAO,KAAK,cAAc,QAAQ,KAAK,YAAY;AACjD,UAAI,CAAC,KAAK,aAAa;AACrB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI;AAEF,cAAM,cAAc,MAAM,KAAK,GAAG,GAAG,IAAY,SAAS,GAAG,IAAI;AAAA,UAC/D,KAAK;AAAA,QACP,CAAC;AACD,YAAI,CAAC,YAAY,IAAI;AACnB,iBAAO,WAAW,EAAE,MAAM,iBAAiB,IAAI,CAAC;AAAA,QAClD;AAEA,cAAM,gBAAgB,KAAK,MAAM,YAAY,KAAK,IAAc;AAChE,cAAM,WAAmC,cAAc,YAAY,CAAC;AACpE,eAAO,GAAG,QAAQ;AAAA,MACpB,SAAS,OAAO;AACd,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,OACE,QAAQ,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,QACJ,SACqC;AACrC,WAAO,QAAQ;AAAA,MACb,QAAQ,IAAI,CAAC,UAAU,KAAK,IAAI,MAAM,KAAK,MAAM,OAAO,MAAM,OAAO,CAAC;AAAA,IACxE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QACJ,MACA,SAC8C;AAC9C,WAAO,QAAQ,IAAI,KAAK,IAAI,CAAC,QAAQ,KAAK,IAAO,KAAK,OAAO,CAAC,CAAC;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,UACJ,KACA,cACA,SACmC;AACnC,WAAO,KAAK,cAAc,aAAa,KAAK,YAAY;AACtD,UAAI,CAAC,KAAK,eAAe,CAAC,KAAK,WAAW;AACxC,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI;AAEF,cAAM,eAAe,MAAM,KAAK,iBAAiB,YAAY;AAC7D,YAAI,CAAC,aAAa,IAAI;AACpB,iBAAO;AAAA,QACT;AACA,cAAM,YAAY,aAAa;AAG/B,cAAM,YAAY,MAAM,KAAK,GAAG,GAAG,IAAY,QAAQ,GAAG,IAAI;AAAA,UAC5D,KAAK;AAAA,QACP,CAAC;AACD,YAAI,CAAC,UAAU,IAAI;AACjB,iBAAO,WAAW,EAAE,MAAM,iBAAiB,IAAI,CAAC;AAAA,QAClD;AAEA,cAAM,cAAc,KAAK,MAAM,UAAU,KAAK,IAAc;AAC5D,cAAM,eAAe,aAAa,YAAY,GAAG;AACjD,cAAM,WAAW,KAAK,OAAO,QAAQ,KAAK,WAAW,YAAY;AAGjE,cAAM,gBAAgB,KAAK,OAAO,YAAY,EAAE;AAChD,cAAM,mBAAmB,KAAK,OAAO,eAAe,aAAa;AAGjE,cAAM,eAAe,KAAK,OAAO;AAAA,UAC/B,iBAAiB;AAAA,UACjB;AAAA,QACF;AAGA,cAAM,gBAAgB,KAAK,OAAO;AAAA,UAChC;AAAA,UACA,QAAQ,kBAAkB;AAAA,UAC1B,QAAQ,aAAa;AAAA,QACvB;AAGA,cAAM,iBAAiB,KAAK,OAAO,QAAQ,eAAe,QAAQ;AAGlE,cAAM,YAAY;AAAA,UAChB,iBAAiB;AAAA,UACjB;AAAA,QACF;AAGA,cAAM,eAAe,KAAK,UAAU;AAAA,UAClC,OAAO,aAAa,SAAS;AAAA,UAC7B,SAAS,KAAK,YAAY;AAAA,UAC1B,UAAU;AAAA,YACR,CAAC,aAAa,aAAa,GAAG;AAAA,YAC9B,CAAC,aAAa,OAAO,GAAG,KAAK,GAAG;AAAA,YAChC,GAAI,SAAS,YAAY,CAAC;AAAA,UAC5B;AAAA,QACF,CAAC;AAED,cAAM,iBAAiB,MAAM,KAAK,GAAG,GAAG;AAAA,UACtC,UAAU,YAAY,IAAI,GAAG;AAAA,UAC7B;AAAA,QACF;AACA,YAAI,CAAC,eAAe,IAAI;AACtB,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,IAAI;AAAA,cACT,0BAA0B,eAAe,MAAM,OAAO;AAAA,YACxD;AAAA,UACF,CAAC;AAAA,QACH;AAEA,eAAO,GAAG,MAAS;AAAA,MACrB,SAAS,OAAO;AACd,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,OACE,QAAQ,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MACJ,KACA,cACA,SACmC;AACnC,WAAO,KAAK,UAAU,KAAK,cAAc,OAAO;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,UACJ,YACA,KACA,SAC4C;AAC5C,WAAO,KAAK,cAAc,aAAa,KAAK,YAAY;AACtD,UACE,CAAC,KAAK,eACN,CAAC,KAAK,aACN,CAAC,KAAK,oBACN;AACA,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI;AACF,cAAM,QAAQ,KAAK,GAAG;AACtB,cAAM,YAAY,SAAS;AAE3B,YAAI,CAAC,WAAW;AACd,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,IAAI;AAAA,cACT;AAAA,YAEF;AAAA,UACF,CAAC;AAAA,QACH;AAGA,cAAM,cAAc,MAAM,UAAU,IAAY,UAAU,KAAK,IAAI,GAAG,IAAI;AAAA,UACxE,KAAK;AAAA,QACP,CAAC;AACD,YAAI,CAAC,YAAY,IAAI;AACnB,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,SAAS;AAAA,YACT;AAAA,UACF,CAAC;AAAA,QACH;AAEA,cAAM,gBAAgB,OAAO,YAAY,MAAM,SAAS,WACpD,KAAK,MAAM,YAAY,KAAK,IAAc,IAC1C,YAAY,MAAM;AACtB,cAAM,iBAAiB,aAAc,cAAsB,KAAK;AAGhE,cAAM,kBAAkB,eAAe,MAAM,GAAG,EAAE;AAClD,cAAM,iBAAiB,eAAe,MAAM,EAAE;AAG9C,cAAM,eAAe,KAAK,OAAO;AAAA,UAC/B,KAAK,mBAAmB;AAAA,UACxB;AAAA,QACF;AAGA,cAAM,gBAAgB,KAAK,OAAO;AAAA,UAChC;AAAA,UACA,QAAQ,kBAAkB;AAAA,UAC1B,QAAQ,aAAa;AAAA,QACvB;AAGA,cAAM,WAAW,KAAK,OAAO,QAAQ,eAAe,cAAc;AAGlE,cAAM,cAAc,MAAM,UAAU,IAAY,SAAS,GAAG,IAAI;AAAA,UAC9D,KAAK;AAAA,QACP,CAAC;AACD,YAAI,CAAC,YAAY,IAAI;AACnB,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN;AAAA,UACF,CAAC;AAAA,QACH;AAEA,cAAM,gBAAgB,OAAO,YAAY,MAAM,SAAS,WACpD,KAAK,MAAM,YAAY,KAAK,IAAc,IAC1C,YAAY,MAAM;AACtB,cAAM,iBAAiB,aAAc,cAAsB,IAAI;AAC/D,cAAM,YAAY,KAAK,OAAO,QAAQ,UAAU,cAAc;AAG9D,cAAM,WAAoC,cAAsB,YAAY,CAAC;AAC7E,cAAM,cACJ,SAAS,aAAa,YAAY,KAAK;AACzC,cAAM,QAAQ,SAAS,aAAa,MAAM,KAAK;AAG/C,YAAI;AACJ,YAAI,SAAS,KAAK;AAChB,kBAAQ;AAAA,QACV,WAAW,SAAS,aAAa;AAC/B,kBAAQ,QAAQ,YAAY,SAAS;AAAA,QACvC,WAAW,gBAAgB,oBAAoB;AAC7C,kBAAQ,KAAK,MAAM,UAAU,SAAS,CAAC;AAAA,QACzC,OAAO;AACL,kBAAQ;AAAA,QACV;AAEA,eAAO,GAAG,EAAE,OAAO,UAAU,MAAM,CAAC;AAAA,MACtC,SAAS,OAAO;AACd,YACE,iBAAiB,SACjB,MAAM,QAAQ,SAAS,YAAY,GACnC;AACA,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,SAAS,MAAM;AAAA,UACjB,CAAC;AAAA,QACH;AACA,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,OACE,QAAQ,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBACJ,KACyC;AACzC,QAAI;AACF,YAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,UAAI,CAAC,OAAO;AACV,eAAO,WAAW,EAAE,MAAM,wBAAwB,IAAI,CAAC;AAAA,MACzD;AAEA,YAAM,UAAU,KAAK,GAAG;AAAA,QACtB,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAEA,YAAM,SAAS,MAAM,KAAK,GAAG;AAAA,QAC3B,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAEA,UAAI,CAAC,OAAO,IAAI;AACd,eAAO,WAAW,EAAE,MAAM,wBAAwB,IAAI,CAAC;AAAA,MACzD;AAEA,YAAM,cAAc,aAAa,OAAO,IAAc;AACtD,aAAO,EAAE,IAAI,MAAM,MAAM,YAAY;AAAA,IACvC,SAAS,OAAO;AACd,aAAO,WAAW,EAAE,MAAM,wBAAwB,IAAI,CAAC;AAAA,IACzD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WACJ,KACuC;AACvC,WAAO,KAAK,cAAc,cAAc,KAAK,YAAY;AACvD,UAAI,CAAC,KAAK,aAAa;AACrB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI;AACF,cAAM,aAAa,MAAM,KAAK,GAAG,GAAG,KAAK;AAAA,UACvC,QAAQ;AAAA,UACR,cAAc;AAAA,QAChB,CAAC;AAED,YAAI,CAAC,WAAW,IAAI;AAClB,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,IAAI;AAAA,cACT,0BAA0B,WAAW,MAAM,OAAO;AAAA,YACpD;AAAA,UACF,CAAC;AAAA,QACH;AAIA,cAAM,OAAiB,CAAC;AACxB,mBAAW,aAAa,WAAW,KAAK,MAAM;AAG5C,cAAI,UAAU,SAAS,IAAI,GAAG,EAAE,GAAG;AACjC,kBAAM,MAAM,UAAU;AAAA,cACpB;AAAA,cACA,UAAU,SAAS,IAAI,SAAS;AAAA,YAClC;AACA,gBAAI,KAAK;AACP,mBAAK,KAAK,GAAG;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAEA,eAAO,GAAG,IAAI;AAAA,MAChB,SAAS,OAAO;AACd,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,OACE,QAAQ,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,OACJ,KACA,cACmC;AACnC,WAAO,KAAK,cAAc,UAAU,KAAK,YAAY;AACnD,UAAI,CAAC,KAAK,eAAe,CAAC,KAAK,WAAW;AACxC,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI,CAAC,KAAK,YAAY,GAAG;AACvB,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAEA,UAAI;AAEF,cAAM,iBAAiB,MAAM,KAAK,WAAW,GAAG;AAChD,YAAI,CAAC,eAAe,IAAI;AACtB,iBAAO;AAAA,QACT;AAEA,cAAM,oBAAoB,eAAe,KAAK;AAAA,UAC5C,CAAC,QAAQ,QAAQ;AAAA,QACnB;AAGA,cAAM,oBAAoB,MAAM,KAAK,GAAG,GAAG;AAAA,UACzC,UAAU,YAAY,IAAI,GAAG;AAAA,QAC/B;AAIA,cAAM,YAAY,MAAM,KAAK,IAAI,GAAG;AACpC,YAAI,CAAC,UAAU,IAAI;AACjB,iBAAO;AAAA,QACT;AAEA,cAAM,eAAe,UAAU;AAG/B,cAAM,cAAc,KAAK,OAAO,YAAY,EAAE;AAC9C,cAAM,WAAW,UAAU,KAAK,OAAO,OAAO,WAAW,CAAC,EAAE;AAAA,UAC1D;AAAA,UACA;AAAA,QACF;AAGA,YAAI;AACJ,YAAI,aAAa,iBAAiB,YAAY;AAC5C,sBAAY,aAAa;AAAA,QAC3B,OAAO;AACL,sBAAY,QAAQ,KAAK,UAAU,aAAa,KAAK,CAAC;AAAA,QACxD;AAEA,cAAM,YAAY,KAAK,OAAO,QAAQ,aAAa,SAAS;AAG5D,cAAM,aAAa,KAAK,OAAO,QAAQ,KAAK,WAAW,WAAW;AAGlE,cAAM,WAAmC;AAAA,UACvC,GAAG,aAAa;AAAA,UAChB,CAAC,aAAa,MAAM,GAAG;AAAA,QACzB;AAGA,cAAM,aAAa,KAAK,UAAU;AAAA,UAChC,KAAK,aAAa,UAAU;AAAA,UAC5B,UAAU,KAAK,UAAU;AAAA,YACvB,OAAO;AAAA,YACP,GAAG;AAAA,UACL,CAAC;AAAA,QACH,CAAC;AACD,cAAM,eAAe,MAAM,KAAK,GAAG,GAAG;AAAA,UACpC,QAAQ,GAAG;AAAA,UACX;AAAA,QACF;AACA,YAAI,CAAC,aAAa,IAAI;AACpB,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,IAAI;AAAA,cACT,qCAAqC,aAAa,MAAM,OAAO;AAAA,YACjE;AAAA,UACF,CAAC;AAAA,QACH;AAGA,cAAM,eAAe,KAAK,UAAU;AAAA,UAClC,MAAM,aAAa,SAAS;AAAA,UAC5B;AAAA,QACF,CAAC;AACD,cAAM,iBAAiB,MAAM,KAAK,GAAG,GAAG;AAAA,UACtC,SAAS,GAAG;AAAA,UACZ;AAAA,QACF;AACA,YAAI,CAAC,eAAe,IAAI;AACtB,iBAAO,WAAW;AAAA,YAChB,MAAM;AAAA,YACN,OAAO,IAAI;AAAA,cACT,uCAAuC,eAAe,MAAM,OAAO;AAAA,YACrE;AAAA,UACF,CAAC;AAAA,QACH;AAGA,mBAAW,OAAO,mBAAmB;AACnC,gBAAM,cAAc,MAAM,KAAK,UAAU,KAAK,GAAG;AACjD,cAAI,CAAC,YAAY,IAAI;AAAA,UAGrB;AAAA,QACF;AAEA,eAAO,GAAG,MAAS;AAAA,MACrB,SAAS,OAAO;AACd,eAAO,WAAW;AAAA,UAChB,MAAM;AAAA,UACN,OACE,QAAQ,KAAK;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaQ,SACN,KAC6C;AAE7C,UAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,QACE,MAAM,WAAW,KACjB,MAAM,CAAC,MAAM,SACb,MAAM,CAAC,MAAM,SACb,MAAM,CAAC,MAAM,UACb;AACA,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,SAAS,MAAM,CAAC,GAAG,EAAE;AACrC,UAAM,UAAU,MAAM,CAAC;AACvB,QAAI,MAAM,OAAO,KAAK,CAAC,SAAS;AAC9B,aAAO;AAAA,IACT;AAEA,WAAO,EAAE,SAAS,QAAQ;AAAA,EAC5B;AACF;AAAA;AAAA;AAAA;AAxpCa,iBAIK,cAAc;;;AClMzB,SAAS,kBAAkB,MAAuC;AACvE,SAAO;AAAA,IACL,SAAS,CAAC,KAAK,cAAc,KAAK,cAAc,KAAK,SAAS;AAAA,IAC9D,SAAS,CAAC,KAAK,SAAS,KAAK,cAAc,KAAK,IAAI;AAAA,IACpD,WAAW,CAAC,WAAW,MAAM,SAAS,KAAK,iBAAiB,MAAM,WAAW,IAAI;AAAA,IACjF,gBAAgB,CAAC,SAAS,KAAK,uBAAuB,IAAI;AAAA,IAC1D,UAAU,CAAC,YAAY,cAAc,KAAK,gBAAgB,YAAY,SAAS;AAAA,IAC/E,aAAa,CAAC,WAAW,KAAK,mBAAmB,MAAM;AAAA,IACvD,QAAQ,CAAC,SAAS,KAAK,aAAa,IAAI;AAAA,EAC1C;AACF;;;ACTA,IAAM,iBAAiB;AACvB,IAAM,gBAAgB;AAEtB,SAAS,kBAAkB,MAA2C;AACpE,SAAO,IAAI;AAAA,IACT,MAAM,WAAW;AAAA,IACjB,SAAS;AAAA,IACT,SACE,uBAAuB,KAAK,UAAU,IAAI,CAAC,6BAA6B,eAAe,MAAM;AAAA,EACjG,CAAC;AACH;AAEA,SAAS,UAAU,MAAsB;AACvC,SAAO,GAAG,aAAa,GAAG,IAAI;AAChC;AAEO,IAAM,iBAAN,MAAgD;AAAA,EAGrD,YAAY,OAAsD;AAChE,SAAK,WAAW,OAAO,UAAU,aAAa,QAAQ,MAAM;AAAA,EAC9D;AAAA,EAEA,IAAI,QAA2B;AAC7B,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA,EAEA,IAAI,aAAsB;AACxB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEA,OAAO,QAAqD;AAC1D,WAAO,KAAK,MAAM,OAAO,MAAM;AAAA,EACjC;AAAA,EAEA,OAAa;AACX,SAAK,MAAM,KAAK;AAAA,EAClB;AAAA,EAEA,MAAM,IAAI,MAAqD;AAC7D,QAAI,CAAC,eAAe,KAAK,IAAI,GAAG;AAC9B,aAAO,kBAAkB,IAAI;AAAA,IAC/B;AAEA,UAAM,SAAS,MAAM,KAAK,MAAM,IAAmB,UAAU,IAAI,CAAC;AAClE,QAAI,CAAC,OAAO,IAAI;AACd,aAAO;AAAA,IACT;AACA,WAAO,EAAE,IAAI,MAAM,MAAM,OAAO,KAAK,MAAM,MAAM;AAAA,EACnD;AAAA,EAEA,MAAM,IAAI,MAAc,OAAoD;AAC1E,QAAI,CAAC,eAAe,KAAK,IAAI,GAAG;AAC9B,aAAO,kBAAkB,IAAI;AAAA,IAC/B;AAEA,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,WAAO,KAAK,MAAM,IAAI,UAAU,IAAI,GAAG;AAAA,MACrC;AAAA,MACA,WAAW;AAAA,MACX,WAAW;AAAA,IACb,CAAyB;AAAA,EAC3B;AAAA,EAEA,MAAM,OAAO,MAAmD;AAC9D,QAAI,CAAC,eAAe,KAAK,IAAI,GAAG;AAC9B,aAAO,kBAAkB,IAAI;AAAA,IAC/B;AAEA,WAAO,KAAK,MAAM,OAAO,UAAU,IAAI,CAAC;AAAA,EAC1C;AAAA,EAEA,MAAM,OAAgD;AACpD,UAAM,SAAS,MAAM,KAAK,MAAM,KAAK;AAAA,MACnC,QAAQ;AAAA,MACR,cAAc;AAAA,IAChB,CAAC;AACD,QAAI,CAAC,OAAO,IAAI;AACd,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM,OAAO,KAAK,OAAO,CAAC,SAAS,eAAe,KAAK,IAAI,CAAC;AAAA,IAC9D;AAAA,EACF;AACF;","names":["ok","serviceError","errorText"]}
|