@runlane/realtime 0.0.0-stage → 0.5.0
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/LICENSE +202 -0
- package/dist/client.cjs +542 -0
- package/dist/client.cjs.map +1 -0
- package/dist/client.d.cts +29 -0
- package/dist/client.d.cts.map +1 -0
- package/dist/client.d.mts +29 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +516 -0
- package/dist/client.mjs.map +1 -0
- package/dist/index.cjs +683 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +62 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +62 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +664 -0
- package/dist/index.mjs.map +1 -0
- package/dist/time-BhORZuav.cjs +87 -0
- package/dist/time-BhORZuav.cjs.map +1 -0
- package/dist/time-sHQYGDPD.mjs +37 -0
- package/dist/time-sHQYGDPD.mjs.map +1 -0
- package/package.json +83 -3
- package/README.md +0 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["RunReadPermission","RunSubscriptionEventType","runRealtimeSnapshotSchema","z","encoder","verifiedRunTokenSchema","runAccessGrantSchema","createDurationSchema","realtimeClock","RunReadPermission","CompactSign","RunlaneError","ErrorCode","realtimeTiming","compactVerify","RunlaneMetricName","RunlaneMetricAttribute","RunlaneLogEventType","RunlaneLogLevel","RunlaneLogAttribute","base64url","createRunlaneIdSchema","createDurationSchema","contractDefaults","z","objectSurfaceSchema","createFunctionSchema","invalidOptions","RunlaneError","ErrorCode","RunlaneMetricName","RunlaneMetricAttribute","RunlaneLogEventType","RunlaneLogLevel","RunlaneLogAttribute","runAccessGrantSchema","runStreamNameSchema","runCursorSchema","realtimeClock","realtimeTiming","runWithRunlaneTelemetrySpan","RunlaneSpanName","waitForAbortableTimeout","encode","realtimeDefaults","RunReadPermission","runStatusValues","runRealtimeErrorCodeSchema"],"sources":["../src/access.ts","../src/tokens.ts","../src/handler.ts"],"sourcesContent":["import {\n RunReadPermission,\n runRealtimeSnapshotSchema,\n RunSubscriptionEventType,\n type RunAccessGrant,\n type RunSubscriptionEvent,\n type RuntimeRunSubscriptionEvent,\n} from '@runlane/contracts/realtime'\n\nexport function intersectGrants(app: RunAccessGrant, token?: RunAccessGrant): RunAccessGrant {\n if (token === undefined) return app\n const permissions = app.permissions.filter((permission) => token.permissions.includes(permission))\n let streams = app.streams ?? token.streams\n if (app.streams !== undefined && token.streams !== undefined)\n streams = app.streams.filter((name) => token.streams?.includes(name))\n return { permissions, ...(streams === undefined ? {} : { streams }) }\n}\n\nexport function permitsStream(grant: RunAccessGrant, name: string): boolean {\n return (\n grant.permissions.includes(RunReadPermission.Streams) &&\n (grant.streams === undefined || grant.streams.includes(name))\n )\n}\n\nexport function projectEvent(\n event: RuntimeRunSubscriptionEvent,\n grant: RunAccessGrant,\n): RunSubscriptionEvent | undefined {\n if (event.type === RunSubscriptionEventType.Stream) return permitsStream(grant, event.record.name) ? event : undefined\n if (event.type === RunSubscriptionEventType.Meta)\n return grant.permissions.includes(RunReadPermission.Meta) ? event : undefined\n if (!grant.permissions.includes(RunReadPermission.Status)) return undefined\n if (event.type === RunSubscriptionEventType.Status) {\n const status = { ...event }\n if (!grant.permissions.includes(RunReadPermission.Output)) {\n delete status.output\n delete status.failure\n }\n if (status.failure !== undefined) {\n status.failure = runRealtimeSnapshotSchema.shape.failure.parse(status.failure)\n }\n return status\n }\n return { ...event, run: projectSnapshot(event.run, grant) }\n}\n\nfunction projectSnapshot(\n source: Extract<RunSubscriptionEvent, { type: RunSubscriptionEventType.Snapshot }>['run'],\n grant: RunAccessGrant,\n) {\n const { meta, output, failure, ...status } = runRealtimeSnapshotSchema.parse(source)\n return {\n ...status,\n ...(grant.permissions.includes(RunReadPermission.Meta) && meta !== undefined ? { meta } : {}),\n ...(grant.permissions.includes(RunReadPermission.Output)\n ? {\n ...(output === undefined ? {} : { output }),\n ...(failure === undefined ? {} : { failure }),\n }\n : {}),\n }\n}\n","import {\n createDurationSchema,\n ErrorCode,\n recordRunlaneTelemetryLog,\n recordRunlaneTelemetryMetric,\n runAccessGrantSchema,\n RunlaneError,\n RunlaneLogAttribute,\n RunlaneLogEventType,\n RunlaneLogLevel,\n RunlaneMetricAttribute,\n RunlaneMetricName,\n RunReadPermission,\n verifiedRunTokenSchema,\n type DurationString,\n type Environment,\n type RunlaneTelemetryRecordingContext,\n type VerifiedRunToken,\n} from '@runlane/contracts/realtime'\nimport { base64url, CompactSign, compactVerify } from 'jose'\nimport { z } from 'zod'\n\nimport { realtimeClock, realtimeTiming } from './time.js'\n\nconst tokenPartsSchema = z.tuple([z.string(), z.string(), z.string()])\nconst headerSchema = z.strictObject({ alg: z.literal('HS256'), typ: z.literal('JWT'), kid: z.string().min(1).max(128) })\nconst algorithmSchema = z.object({\n name: z.literal('HMAC'),\n hash: z.object({ name: z.literal('SHA-256') }),\n length: z.number().int().min(256),\n})\nconst encoder = new TextEncoder()\nconst decoder = new TextDecoder('utf-8', { fatal: true })\nconst maximumTokenLength = 16_384\n\n/** Strict construction schema; claim and header constraints remain the canonical owners. */\nexport const realtimeTokenOptionsSchema = z\n .strictObject({\n audience: verifiedRunTokenSchema.shape.audience,\n keyId: headerSchema.shape.kid,\n key: z.instanceof(CryptoKey),\n verifyKeys: z.record(headerSchema.shape.kid, z.instanceof(CryptoKey)).readonly().optional(),\n })\n .refine(\n (tokens) => !Object.hasOwn(tokens.verifyKeys ?? {}, tokens.keyId),\n 'tokens.keyId must not also appear in verifyKeys.',\n )\n\n/** Active signing/verification key and previous verify-only keys. Keep all keys server-side. */\nexport type RunlaneRealtimeTokenOptions = Readonly<z.output<typeof realtimeTokenOptionsSchema>>\n\nconst createTokenOptionsSchema = z.strictObject({\n // The complete claims schema validates and brands this identifier before signing.\n runId: z.string(),\n grant: runAccessGrantSchema.optional(),\n expiresIn: createDurationSchema('expiresIn must be whole seconds between 1s and realtime.maxTokenTTL.').optional(),\n})\n/** Minting inputs for one run. The app must check access before calling createToken. */\nexport type CreateRealtimeTokenOptions = Readonly<z.input<typeof createTokenOptionsSchema>> & {\n readonly expiresIn?: DurationString\n}\n\n/** Signs one run/environment/audience grant using an HMAC-SHA256 key of at least 256 bits. */\nexport async function signRunToken(\n environment: Environment,\n tokens: RunlaneRealtimeTokenOptions,\n input: CreateRealtimeTokenOptions,\n): Promise<string> {\n try {\n const options = createTokenOptionsSchema.parse(input)\n const header = headerSchema.parse({ alg: 'HS256', typ: 'JWT', kid: tokens.keyId })\n requireHmacKey(tokens.key, 'sign')\n const ttl = tokenLifetime(options.expiresIn?.milliseconds)\n const issuedAt = Math.floor(realtimeClock.now() / 1000)\n const claims = verifiedRunTokenSchema.parse({\n environment,\n runId: options.runId,\n grant: options.grant ?? { permissions: Object.values(RunReadPermission) },\n audience: tokens.audience,\n issuedAt,\n expiresAt: issuedAt + ttl / 1000,\n version: 1,\n })\n const token = await new CompactSign(encoder.encode(JSON.stringify(claims)))\n .setProtectedHeader(header)\n .sign(tokens.key)\n if (token.length > maximumTokenLength) throw invalidToken()\n return token\n } catch (cause) {\n if (cause instanceof RunlaneError) throw cause\n const message =\n cause instanceof z.ZodError\n ? `Token ${cause.issues[0]?.path.join('.') ?? 'expiresIn'} is invalid: ${cause.issues[0]?.message ?? 'Check the token options.'}`\n : 'Token signing failed; check key and claims.'\n const field = cause instanceof z.ZodError ? cause.issues[0]?.path[0] : undefined\n let code = ErrorCode.InternalError\n if (cause instanceof z.ZodError) {\n code =\n field === 'environment' || field === 'runId' || field === 'grant'\n ? ErrorCode.ValidationFailed\n : ErrorCode.ConfigurationInvalid\n }\n throw new RunlaneError({ code, message, retryable: false, cause })\n }\n}\n\nfunction tokenLifetime(ttl = realtimeTiming.tokenTTL): number {\n if (ttl < 1000 || ttl > realtimeTiming.maxTokenTTL || ttl % 1000 !== 0)\n throw new RunlaneError({\n code: ErrorCode.ConfigurationInvalid,\n message: 'expiresIn must be whole seconds between 1s and realtime.maxTokenTTL.',\n retryable: false,\n })\n return ttl\n}\n\n/** Verifies a scoped token and records only bounded rejection reasons through the supplied telemetry. */\nexport async function verifyRunToken(\n token: string,\n options: { readonly audience: string; readonly keys: Readonly<Record<string, CryptoKey>> },\n diagnostics: RunlaneTelemetryRecordingContext = {},\n operation = 'verify',\n): Promise<VerifiedRunToken> {\n let reason: TokenRejectionReason = TokenRejectionReason.Malformed\n try {\n if (token.length > maximumTokenLength) throw invalidToken()\n const [head, body, signature] = tokenPartsSchema.parse(token.split('.'))\n reason = TokenRejectionReason.Header\n const header = headerSchema.parse(JSON.parse(decoder.decode(decodeBase64(head))))\n reason = TokenRejectionReason.UnknownKey\n const key = Object.hasOwn(options.keys, header.kid) ? options.keys[header.kid] : undefined\n if (key === undefined) throw invalidToken()\n reason = TokenRejectionReason.Key\n requireHmacKey(key, 'verify')\n reason = TokenRejectionReason.Signature\n decodeBase64(signature)\n const verified = await compactVerify(token, key, { algorithms: ['HS256'] })\n reason = TokenRejectionReason.Claims\n decodeBase64(body)\n const claims = verifiedRunTokenSchema.parse(JSON.parse(decoder.decode(verified.payload)))\n const now = Math.floor(realtimeClock.now() / 1000)\n const rejection = tokenClaimRejection(claims, options.audience, now)\n if (rejection !== undefined) {\n reason = rejection\n throw invalidToken()\n }\n return claims\n } catch (cause) {\n recordRunlaneTelemetryMetric(diagnostics, {\n name: RunlaneMetricName.RealtimeTokenRejectedCount,\n value: 1,\n attributes: { [RunlaneMetricAttribute.Operation]: operation, [RunlaneMetricAttribute.Reason]: reason },\n })\n recordRunlaneTelemetryLog(diagnostics, {\n type: RunlaneLogEventType.RealtimeTokenRejected,\n level: RunlaneLogLevel.Warn,\n attributes: { [RunlaneLogAttribute.Operation]: operation, [RunlaneLogAttribute.Reason]: reason },\n })\n throw invalidToken(cause)\n }\n}\n\nfunction tokenClaimRejection(\n claims: VerifiedRunToken,\n audience: string,\n now: number,\n): TokenRejectionReason | undefined {\n if (claims.audience !== audience) return TokenRejectionReason.Audience\n if (claims.issuedAt > now + realtimeTiming.issuedAtLeeway / 1000) return TokenRejectionReason.IssuedAt\n if (claims.expiresAt <= now) return TokenRejectionReason.Expired\n if (claims.expiresAt <= claims.issuedAt || (claims.expiresAt - claims.issuedAt) * 1000 > realtimeTiming.maxTokenTTL)\n return TokenRejectionReason.Lifetime\n return undefined\n}\n\n/** Shared key policy for signing, verification, and handler startup checks. */\nexport function requireHmacKey(key: CryptoKey, usage: KeyUsage): void {\n if (\n !(key instanceof CryptoKey) ||\n key.type !== 'secret' ||\n !algorithmSchema.safeParse(key.algorithm).success ||\n !key.usages.includes(usage)\n )\n throw new RunlaneError({\n code: ErrorCode.ConfigurationInvalid,\n message: `key must be an HMAC-SHA256 key of at least 256 bits with ${usage} usage.`,\n retryable: false,\n })\n}\n\nfunction decodeBase64(value: string): Uint8Array {\n if (!/^[A-Za-z0-9_-]+$/.test(value)) throw invalidToken()\n const bytes = base64url.decode(value)\n if (base64url.encode(bytes) !== value) throw invalidToken()\n return bytes\n}\n\nfunction invalidToken(cause?: unknown): RunlaneError {\n return new RunlaneError({\n code: ErrorCode.AccessDenied,\n message: 'Run access denied.',\n retryable: false,\n cause,\n })\n}\n\nenum TokenRejectionReason {\n Malformed = 'malformed',\n Header = 'header',\n UnknownKey = 'unknown_key',\n Key = 'key',\n Signature = 'signature',\n Claims = 'claims',\n Audience = 'audience',\n IssuedAt = 'issued_at',\n Expired = 'expired',\n Lifetime = 'lifetime',\n}\n","import {\n contractDefaults,\n createDurationSchema,\n createRunlaneIdSchema,\n ErrorCode,\n realtimeDefaults,\n recordRunlaneTelemetryLog,\n recordRunlaneTelemetryMetric,\n runAccessGrantSchema,\n runCursorSchema,\n RunlaneError,\n RunlaneLogAttribute,\n RunlaneLogEventType,\n RunlaneLogLevel,\n RunlaneMetricAttribute,\n RunlaneMetricName,\n RunlaneSpanName,\n RunReadPermission,\n runRealtimeErrorCodeSchema,\n runStatusValues,\n runStreamNameSchema,\n runWithRunlaneTelemetrySpan,\n type RealtimeErrorData,\n type RunAccessGrant,\n type RunCursor,\n type RunId,\n type RunlaneTelemetryRecordingContext,\n type RunReadPage,\n type RunStreamRecord,\n type VerifiedRunToken,\n} from '@runlane/contracts/realtime'\nimport {\n createFunctionSchema,\n objectSurfaceSchema,\n waitForAbortableTimeout,\n type Awaitable,\n} from '@runlane/utilities/browser'\nimport { encode } from 'eventsource-encoder'\nimport * as z from 'zod'\n\nimport { intersectGrants, permitsStream, projectEvent } from './access.js'\nimport { invalidOptions } from './errors.js'\nimport { type RunlaneRealtimeSource } from './source.js'\nimport { realtimeClock, realtimeTiming } from './time.js'\nimport {\n realtimeTokenOptionsSchema,\n requireHmacKey,\n signRunToken,\n verifyRunToken,\n type CreateRealtimeTokenOptions,\n type RunlaneRealtimeTokenOptions,\n} from './tokens.js'\n\n/** Server options require authorize, tokens, or both. Configured authorization limits every valid connection. */\nexport interface RunlaneRealtimeOptions extends RunlaneTelemetryRecordingContext {\n readonly runlane: RunlaneRealtimeSource\n readonly authorize?: (input: {\n readonly request: Request\n readonly runId: RunId\n readonly token?: VerifiedRunToken\n }) => Awaitable<RunAccessGrant | undefined>\n readonly tokens?: RunlaneRealtimeTokenOptions\n}\n/** Authorization callback for a separately defined policy; undefined denies access to the run. */\nexport type RunlaneRealtimeAuthorize = NonNullable<RunlaneRealtimeOptions['authorize']>\n\n/** Server entry for authorized reads and request-independent token minting. */\nexport interface RunlaneRealtime {\n /** Serves SSE reads; authorize, when configured, limits every valid connection. */\n readonly handle: (request: Request) => Promise<Response>\n /** Mint after the app checks access. Does not call authorize or check run existence. */\n readonly createToken: (options: CreateRealtimeTokenOptions) => Promise<string>\n}\ninterface Route {\n readonly runId: RunId\n readonly name?: string\n readonly after?: RunCursor\n}\ninterface Frame {\n readonly event: string\n readonly cursor?: RunCursor\n readonly data: object\n}\nconst encoder = new TextEncoder()\nconst runIdSchema = createRunlaneIdSchema<'run'>('Run id')\nconst pollInterval = createDurationSchema().parse(contractDefaults.streams.pollInterval).milliseconds\n\nconst handlerOptionsSchema = z\n .strictObject({\n runlane: objectSurfaceSchema,\n authorize: createFunctionSchema<RunlaneRealtimeAuthorize>('authorize must be a function.').optional(),\n tokens: realtimeTokenOptionsSchema.optional(),\n telemetry: objectSurfaceSchema.optional(),\n onTelemetryError: createFunctionSchema<NonNullable<RunlaneRealtimeOptions['onTelemetryError']>>(\n 'onTelemetryError must be a function.',\n ).optional(),\n })\n .refine(\n (options) => options.authorize !== undefined || options.tokens !== undefined,\n 'Configure authorize for session access, tokens for bearer access, or both.',\n )\n\n/** Mounts authorized, bounded SSE reads without starting workers or adding runtime storage work. */\nexport function createRunlaneRealtime(options: RunlaneRealtimeOptions): RunlaneRealtime {\n const checked = handlerOptionsSchema.safeParse(options)\n if (!checked.success) throw invalidOptions(checked.error, 'handler')\n const tokens = checked.data.tokens\n if (tokens !== undefined) {\n requireHmacKey(tokens.key, 'sign')\n requireHmacKey(tokens.key, 'verify')\n for (const key of Object.values(tokens.verifyKeys ?? {})) requireHmacKey(key, 'verify')\n }\n const verification =\n tokens === undefined\n ? undefined\n : {\n audience: tokens.audience,\n keys: { ...tokens.verifyKeys, [tokens.keyId]: tokens.key },\n }\n return {\n async createToken(input) {\n if (tokens === undefined)\n throw new RunlaneError({\n code: ErrorCode.ConfigurationInvalid,\n message: 'Configure tokens before calling createToken.',\n })\n return signRunToken(options.runlane.environment, tokens, input)\n },\n async handle(request) {\n let operation = 'subscribe'\n try {\n const route = parseRoute(request)\n operation = route.name === undefined ? 'subscribe' : 'read'\n const token = await requestToken(request, route.runId, options, verification)\n const grant = await authorizeGrant(options, request, route, token, operation)\n return await openConnection(options, request, route, grant, token)\n } catch (cause) {\n const error = publicError(cause)\n if (error.code === ErrorCode.AccessDenied) recordDenial(options, cause, operation)\n return Response.json(\n { error },\n {\n status: request.method === 'GET' ? httpStatus(error.code) : 405,\n headers: { 'cache-control': 'no-store', ...(request.method === 'GET' ? {} : { allow: 'GET' }) },\n },\n )\n }\n },\n }\n}\n\nasync function authorizeGrant(\n options: RunlaneRealtimeOptions,\n request: Request,\n route: Route,\n token: VerifiedRunToken | undefined,\n operation: string,\n): Promise<RunAccessGrant> {\n let app: RunAccessGrant | undefined\n try {\n app =\n options.authorize === undefined\n ? token?.grant\n : await options.authorize({ request, runId: route.runId, ...(token === undefined ? {} : { token }) })\n } catch (cause) {\n recordRunlaneTelemetryMetric(options, {\n name: RunlaneMetricName.RealtimeAuthorizationErrorCount,\n value: 1,\n attributes: {\n [RunlaneMetricAttribute.Operation]: operation,\n [RunlaneMetricAttribute.Reason]: 'authorize_exception',\n },\n })\n recordRunlaneTelemetryLog(options, {\n type: RunlaneLogEventType.RealtimeAuthorizationFailed,\n level: RunlaneLogLevel.Error,\n attributes: {\n [RunlaneLogAttribute.Operation]: operation,\n [RunlaneLogAttribute.Reason]: 'authorize_exception',\n },\n })\n throw new RunlaneError({ code: ErrorCode.InternalError, message: 'Realtime authorization failed.', cause })\n }\n if (app === undefined) throw accessDenied()\n const parsed = runAccessGrantSchema.safeParse(app)\n if (!parsed.success) throw invalidRequest('Realtime grant is invalid.', parsed.error)\n const grant = intersectGrants(parsed.data, token?.grant)\n if (grant.permissions.length === 0 || (route.name !== undefined && !permitsStream(grant, route.name)))\n throw accessDenied()\n return grant\n}\n\nfunction recordDenial(options: RunlaneRealtimeOptions, cause: unknown, operation: string): void {\n const reason =\n accessDenialReasonSchema.safeParse(cause instanceof RunlaneError ? cause.meta?.reason : undefined).data ??\n 'token_rejected'\n if (reason !== 'token_rejected')\n recordRunlaneTelemetryLog(options, {\n type: RunlaneLogEventType.RealtimeAuthorizationDenied,\n level: RunlaneLogLevel.Warn,\n attributes: { [RunlaneLogAttribute.Operation]: operation, [RunlaneLogAttribute.Reason]: reason },\n })\n recordRunlaneTelemetryMetric(options, {\n name: RunlaneMetricName.RealtimeAuthorizationDeniedCount,\n value: 1,\n attributes: { [RunlaneMetricAttribute.Operation]: operation, [RunlaneMetricAttribute.Reason]: reason },\n })\n}\n\nfunction parseRoute(request: Request): Route {\n if (request.method !== 'GET')\n throw new RunlaneError({\n code: ErrorCode.ValidationFailed,\n message: 'Realtime routes require GET.',\n retryable: false,\n })\n const url = new URL(request.url)\n if (Array.from(url.searchParams.keys()).some((key) => key !== 'after') || url.searchParams.getAll('after').length > 1)\n throw invalidRequest('Only one after query parameter is accepted; use Authorization for credentials.')\n const match = /\\/runs\\/([^/]+)\\/(events|streams\\/([^/]+))$/.exec(url.pathname)\n if (match?.[1] === undefined)\n throw new RunlaneError({\n code: ErrorCode.RunNotFound,\n message: 'Realtime route was not found.',\n retryable: false,\n })\n let runId: RunId\n let name: string | undefined\n try {\n runId = runIdSchema.parse(decodeURIComponent(match[1]))\n name = match[3] === undefined ? undefined : runStreamNameSchema.parse(decodeURIComponent(match[3]))\n } catch (cause) {\n throw invalidRequest('Run id or stream name is invalid.', cause)\n }\n return { runId, ...(name === undefined ? {} : { name }), ...parseResumeCursor(request, url) }\n}\n\nfunction parseResumeCursor(request: Request, url: URL): Pick<Route, 'after'> {\n const header = request.headers.get('last-event-id')\n const query = url.searchParams.get('after')\n if (header !== null && query !== null && header !== query) throw invalidCursor()\n const raw = header ?? query\n const parsed = raw === null ? undefined : runCursorSchema.safeParse(raw)\n if (parsed !== undefined && !parsed.success) throw invalidCursor()\n return parsed?.success ? { after: parsed.data } : {}\n}\n\nasync function openConnection(\n options: RunlaneRealtimeOptions,\n request: Request,\n route: Route,\n grant: RunAccessGrant,\n token?: VerifiedRunToken,\n): Promise<Response> {\n const started = realtimeClock.now()\n const operation = route.name === undefined ? 'subscribe' : 'read'\n const control = new AbortController()\n const expires = Math.min(\n started + realtimeTiming.connectionDuration,\n token === undefined ? Infinity : token.expiresAt * 1000,\n )\n const stop = () => control.abort()\n request.signal.addEventListener('abort', stop, { once: true })\n if (request.signal.aborted) stop()\n const expiry = setTimeout(stop, Math.max(0, expires - realtimeClock.now()))\n const frames = sourceFrames(options.runlane, route, grant, control.signal)\n let pending: Promise<IteratorResult<Frame, void>> | undefined\n let cursor = route.after\n let closed = false\n const finish = () => {\n if (closed) return\n closed = true\n clearTimeout(expiry)\n request.signal.removeEventListener('abort', stop)\n control.abort()\n void frames.return().catch(() => undefined)\n recordRunlaneTelemetryMetric(options, {\n name: RunlaneMetricName.RealtimeConnectionDurationMs,\n value: Math.max(0, realtimeClock.now() - started),\n attributes: { [RunlaneMetricAttribute.Operation]: operation },\n })\n }\n const next = async (): Promise<Uint8Array | undefined> => {\n if (control.signal.aborted || realtimeClock.now() >= expires) return undefined\n pending ??= runWithRunlaneTelemetrySpan(\n options,\n { name: route.name === undefined ? RunlaneSpanName.RealtimeSubscribe : RunlaneSpanName.RealtimeRead },\n () => frames.next(),\n ).catch((cause: unknown) => {\n // Record the source failure before converting it to the public transport contract.\n const { cursor, ...error } = publicSourceError(cause)\n throw new RunlaneError({ ...error, cause, ...(cursor === undefined ? {} : { meta: { cursor } }) })\n })\n const timer = new AbortController()\n const abortTimer = () => timer.abort()\n control.signal.addEventListener('abort', abortTimer, { once: true })\n try {\n const result = await Promise.race([\n pending,\n waitForAbortableTimeout(realtimeTiming.heartbeatInterval, timer.signal).then(() => undefined),\n ])\n if (realtimeClock.now() >= expires) return undefined\n if (result === undefined) return encoder.encode(encode({ comment: 'heartbeat' }))\n pending = undefined\n if (result.done) return undefined\n const frame = result.value\n const bytes = encodeFrame(frame, cursor)\n cursor = frame.cursor ?? cursor\n return bytes\n } finally {\n timer.abort()\n control.signal.removeEventListener('abort', abortTimer)\n }\n }\n let first: Uint8Array | undefined\n try {\n first = await next()\n } catch (cause) {\n finish()\n throw cause\n }\n // No automatic prefetch: only a reader pull advances the core iterator.\n const body = new ReadableStream<Uint8Array>(\n {\n start(controller) {\n const end = () => {\n if (closed) return\n controller.close()\n finish()\n }\n control.signal.addEventListener('abort', end, { once: true })\n if (control.signal.aborted) end()\n },\n async pull(controller) {\n try {\n const bytes = control.signal.aborted || realtimeClock.now() >= expires ? undefined : (first ?? (await next()))\n if (closed) return\n first = undefined\n if (bytes === undefined) {\n controller.close()\n finish()\n return\n }\n controller.enqueue(bytes)\n } catch (cause) {\n if (closed) return\n controller.enqueue(\n encoder.encode(encode({ event: 'error', data: JSON.stringify(publicError(cause, cursor)) })),\n )\n controller.close()\n finish()\n }\n },\n cancel() {\n finish()\n },\n },\n { highWaterMark: 0 },\n )\n return new Response(body, {\n headers: {\n 'content-type': 'text/event-stream; charset=utf-8',\n 'cache-control': 'no-store',\n 'x-accel-buffering': 'no',\n },\n })\n}\n\nfunction encodeFrame(frame: Frame, cursor?: RunCursor): Uint8Array {\n const data = JSON.stringify(frame.data)\n const bytes = encoder.encode(\n encode({ event: frame.event, data, ...(frame.cursor === undefined ? {} : { id: frame.cursor }) }),\n )\n if (bytes.byteLength > realtimeDefaults.maxEventBytes)\n throw new RunlaneError({\n code: ErrorCode.EventTooLarge,\n message: 'Realtime event exceeds the serialized UTF-8 byte limit.',\n retryable: false,\n ...(cursor === undefined ? {} : { meta: { cursor } }),\n })\n return bytes\n}\n\nasync function* sourceFrames(\n source: RunlaneRealtimeSource,\n route: Route,\n grant: RunAccessGrant,\n signal: AbortSignal,\n): AsyncGenerator<Frame, void> {\n if (route.name === undefined) {\n for await (const event of source.runs.subscribe(route.runId, {\n after: route.after,\n signal,\n streams: grant.permissions.includes(RunReadPermission.Streams) ? grant.streams : false,\n })) {\n if (signal.aborted) return\n const projected = projectEvent(event, grant)\n yield projected === undefined\n ? { event: 'checkpoint', cursor: event.cursor, data: {} }\n : { event: projected.type, cursor: projected.cursor, data: projected }\n }\n if (!signal.aborted) yield { event: 'end', data: {} }\n return\n }\n yield* namedFrames(source, route.runId, route.name, route.after, signal)\n}\n\nasync function* namedFrames(\n source: RunlaneRealtimeSource,\n runId: RunId,\n name: string,\n initial: RunCursor | undefined,\n signal: AbortSignal,\n): AsyncGenerator<Frame, void> {\n let after = initial\n let terminal = false\n while (!signal.aborted) {\n const controller = new AbortController()\n const waiting = source.lane?.runSignal\n ?.wait({\n environment: source.environment,\n runId,\n signal: AbortSignal.any([signal, controller.signal]),\n timeoutMs: pollInterval,\n })\n .catch((cause: unknown) => {\n throw new RunlaneError({\n code: ErrorCode.AdapterContractViolation,\n message: 'Lane run signal wait must not reject.',\n cause,\n })\n })\n // A provider may reject before the page read finishes or while the consumer pauses.\n void waiting?.catch(() => undefined)\n try {\n const page = await source.runs.readStream(runId, name, { after, limit: contractDefaults.pagination.defaultLimit })\n yield* namedPageFrames(page, after)\n after = page.cursor\n if (page.hasMore) continue\n if (terminal && page.records.length === 0) {\n yield { event: 'end', data: {} }\n return\n }\n terminal = await readNamedRunTerminal(source, runId)\n if (terminal) continue\n if (page.records.length === 0) await (waiting ?? waitForAbortableTimeout(pollInterval, signal))\n } finally {\n controller.abort()\n await waiting\n }\n }\n}\n\nasync function readNamedRunTerminal(source: RunlaneRealtimeSource, runId: RunId): Promise<boolean> {\n const run = await source.runs.get(runId)\n if (run === undefined)\n throw new RunlaneError({\n code: ErrorCode.RunNotFound,\n message: 'Run was not found.',\n retryable: false,\n })\n return runStatusValues.isTerminal(run.status)\n}\n\nfunction* namedPageFrames(page: RunReadPage<RunStreamRecord>, after?: RunCursor): Generator<Frame, void> {\n for (const [index, record] of page.records.entries()) {\n const last = index === page.records.length - 1\n yield {\n event: 'stream',\n ...(last ? { cursor: page.cursor } : {}),\n data: { ...(last ? { cursor: page.cursor } : {}), record },\n }\n }\n if (page.records.length === 0 && page.cursor !== after) yield { event: 'checkpoint', cursor: page.cursor, data: {} }\n}\n\nfunction publicError(cause: unknown, cursor?: RunCursor): RealtimeErrorData {\n const checkpoint =\n cursor ?? (cause instanceof RunlaneError ? runCursorSchema.safeParse(cause.meta?.cursor).data : undefined)\n const resume = checkpoint === undefined ? {} : { cursor: checkpoint }\n if (cause instanceof RunlaneError) {\n const code = runRealtimeErrorCodeSchema.safeParse(cause.code)\n if (code.success && code.data !== ErrorCode.InternalError) {\n return { code: code.data, message: cause.message, retryable: cause.retryable, ...resume }\n }\n }\n return {\n code: ErrorCode.InternalError,\n message: 'Realtime request failed.',\n retryable: true,\n ...resume,\n }\n}\nfunction publicSourceError(cause: unknown): RealtimeErrorData {\n const error = publicError(cause)\n if (cause instanceof RunlaneError) {\n switch (cause.code) {\n case ErrorCode.ConfigurationInvalid:\n case ErrorCode.ValidationFailed:\n return { ...error, code: ErrorCode.ValidationFailed, message: 'Realtime request is invalid.', retryable: false }\n case ErrorCode.RunCursorInvalid:\n return { ...error, code: ErrorCode.RunCursorInvalid, message: 'Run cursor is invalid.', retryable: false }\n case ErrorCode.RunNotFound:\n return { ...error, code: ErrorCode.RunNotFound, message: 'Run was not found.', retryable: false }\n case ErrorCode.OperationCancelled:\n return {\n ...error,\n code: ErrorCode.Disconnected,\n message: 'Realtime runtime is closing; reconnect to resume.',\n retryable: true,\n }\n }\n }\n return error\n}\nfunction httpStatus(code: ErrorCode): number {\n if (code === ErrorCode.AccessDenied) return 403\n if (code === ErrorCode.RunNotFound) return 404\n if (code === ErrorCode.ValidationFailed || code === ErrorCode.RunCursorInvalid) return 400\n return 500\n}\nenum AccessDenialReason {\n ApplicationDenied = 'application_denied',\n AuthorizationHeader = 'authorization_header',\n VerificationUnconfigured = 'verification_unconfigured',\n TokenScope = 'token_scope',\n}\nconst accessDenialReasonSchema = z.enum(AccessDenialReason)\n\nfunction accessDenied(reason: AccessDenialReason = AccessDenialReason.ApplicationDenied): RunlaneError {\n return new RunlaneError({ code: ErrorCode.AccessDenied, message: 'Run access denied.', meta: { reason } })\n}\nfunction invalidRequest(message: string, cause?: unknown): RunlaneError {\n return new RunlaneError({ code: ErrorCode.ValidationFailed, message, retryable: false, cause })\n}\nfunction invalidCursor(): RunlaneError {\n return new RunlaneError({\n code: ErrorCode.RunCursorInvalid,\n message: 'Run cursor is invalid or conflicts with after.',\n retryable: false,\n })\n}\n\nasync function requestToken(\n request: Request,\n runId: RunId,\n options: RunlaneRealtimeOptions,\n verification: Parameters<typeof verifyRunToken>[1] | undefined,\n): Promise<VerifiedRunToken | undefined> {\n const supplied = request.headers.get('authorization')\n if (supplied === null) return undefined\n const match = /^Bearer ([a-z0-9_.-]+)$/i.exec(supplied)\n if (match?.[1] === undefined) throw accessDenied(AccessDenialReason.AuthorizationHeader)\n if (verification === undefined) throw accessDenied(AccessDenialReason.VerificationUnconfigured)\n const token = await verifyRunToken(\n match[1],\n verification,\n options,\n new URL(request.url).pathname.endsWith('/events') ? 'subscribe' : 'read',\n )\n if (token.runId !== runId || token.environment.name !== options.runlane.environment.name)\n throw accessDenied(AccessDenialReason.TokenScope)\n return token\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { DurationString, Environment, ErrorCode, RunAccessGrant, RunAccessGrant as RunAccessGrant$1, RunId, RunReadOptions, RunReadPage, RunReadPermission, RunReadPermission as RunReadPermission$1, RunRecord, RunStreamRecord, RunSubscribeOptions, RunlaneError, RunlaneTelemetryRecordingContext, RuntimeRunSubscriptionEvent, VerifiedRunToken, VerifiedRunToken as VerifiedRunToken$1 } from "@runlane/contracts/realtime";
|
|
2
|
+
import { Awaitable } from "@runlane/utilities/browser";
|
|
3
|
+
import { Lane } from "@runlane/contracts";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
/** Structural read-only boundary. A core runtime satisfies it without importing HTTP code. */
|
|
6
|
+
interface RunlaneRealtimeSource {
|
|
7
|
+
readonly environment: Environment;
|
|
8
|
+
/** Optional committed-source hints; absent hints retain the polling fallback. */
|
|
9
|
+
readonly lane?: Pick<Lane, 'runSignal'>;
|
|
10
|
+
readonly runs: {
|
|
11
|
+
get(runId: RunId): Promise<RunRecord | undefined>;
|
|
12
|
+
subscribe(runId: RunId, options?: RunSubscribeOptions): AsyncGenerator<RuntimeRunSubscriptionEvent, void>;
|
|
13
|
+
readStream(runId: RunId, name: string, options?: RunReadOptions): Promise<RunReadPage<RunStreamRecord>>;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Strict construction schema; claim and header constraints remain the canonical owners. */
|
|
17
|
+
declare const realtimeTokenOptionsSchema: z.ZodObject<{
|
|
18
|
+
audience: import("zod").ZodString;
|
|
19
|
+
keyId: z.ZodString;
|
|
20
|
+
key: z.ZodInstanceOf<CryptoKey>;
|
|
21
|
+
verifyKeys: z.ZodOptional<z.ZodReadonly<z.ZodRecord<z.ZodString, z.ZodInstanceOf<CryptoKey>>>>;
|
|
22
|
+
}, z.core.$strict>;
|
|
23
|
+
/** Active signing/verification key and previous verify-only keys. Keep all keys server-side. */
|
|
24
|
+
type RunlaneRealtimeTokenOptions = Readonly<z.output<typeof realtimeTokenOptionsSchema>>;
|
|
25
|
+
declare const createTokenOptionsSchema: z.ZodObject<{
|
|
26
|
+
runId: z.ZodString;
|
|
27
|
+
grant: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
28
|
+
permissions: import("zod").ZodReadonly<import("zod").ZodArray<import("zod").ZodEnum<typeof RunReadPermission$1>>>;
|
|
29
|
+
streams: import("zod").ZodOptional<import("zod").ZodReadonly<import("zod").ZodArray<import("zod").ZodString>>>;
|
|
30
|
+
}, import("zod/v4/core").$strict>>;
|
|
31
|
+
expiresIn: import("zod").ZodOptional<import("zod").ZodPipe<import("zod").ZodCodec<import("zod").ZodString, import("zod").ZodCustom<`${number}d` | `${number}h` | `${number}ms` | `${number}m` | `${number}s`, `${number}d` | `${number}h` | `${number}ms` | `${number}m` | `${number}s`>>, import("zod").ZodTransform<{
|
|
32
|
+
duration: `${number}d` | `${number}h` | `${number}ms` | `${number}m` | `${number}s`;
|
|
33
|
+
milliseconds: number;
|
|
34
|
+
}, `${number}d` | `${number}h` | `${number}ms` | `${number}m` | `${number}s`>>>;
|
|
35
|
+
}, z.core.$strict>;
|
|
36
|
+
/** Minting inputs for one run. The app must check access before calling createToken. */
|
|
37
|
+
type CreateRealtimeTokenOptions = Readonly<z.input<typeof createTokenOptionsSchema>> & {
|
|
38
|
+
readonly expiresIn?: DurationString;
|
|
39
|
+
};
|
|
40
|
+
/** Server options require authorize, tokens, or both. Configured authorization limits every valid connection. */
|
|
41
|
+
interface RunlaneRealtimeOptions extends RunlaneTelemetryRecordingContext {
|
|
42
|
+
readonly runlane: RunlaneRealtimeSource;
|
|
43
|
+
readonly authorize?: (input: {
|
|
44
|
+
readonly request: Request;
|
|
45
|
+
readonly runId: RunId;
|
|
46
|
+
readonly token?: VerifiedRunToken$1;
|
|
47
|
+
}) => Awaitable<RunAccessGrant$1 | undefined>;
|
|
48
|
+
readonly tokens?: RunlaneRealtimeTokenOptions;
|
|
49
|
+
}
|
|
50
|
+
/** Authorization callback for a separately defined policy; undefined denies access to the run. */
|
|
51
|
+
type RunlaneRealtimeAuthorize = NonNullable<RunlaneRealtimeOptions['authorize']>;
|
|
52
|
+
/** Server entry for authorized reads and request-independent token minting. */
|
|
53
|
+
interface RunlaneRealtime {
|
|
54
|
+
/** Serves SSE reads; authorize, when configured, limits every valid connection. */
|
|
55
|
+
readonly handle: (request: Request) => Promise<Response>;
|
|
56
|
+
/** Mint after the app checks access. Does not call authorize or check run existence. */
|
|
57
|
+
readonly createToken: (options: CreateRealtimeTokenOptions) => Promise<string>;
|
|
58
|
+
}
|
|
59
|
+
/** Mounts authorized, bounded SSE reads without starting workers or adding runtime storage work. */
|
|
60
|
+
export declare function createRunlaneRealtime(options: RunlaneRealtimeOptions): RunlaneRealtime;
|
|
61
|
+
export { type CreateRealtimeTokenOptions, ErrorCode, type RunAccessGrant, RunReadPermission, RunlaneError, type RunlaneRealtime, type RunlaneRealtimeAuthorize, type RunlaneRealtimeOptions, type RunlaneRealtimeSource, type RunlaneRealtimeTokenOptions, type VerifiedRunToken };
|
|
62
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":["RunReadPermission","VerifiedRunToken","RunAccessGrant"],"sources":["../src/source.ts","../src/tokens.ts","../src/handler.ts"],"mappings":";;;;;UAaiB;WACN,aAAa;;WAEb,OAAO,KAAK;WACZ;IACP,IAAI,OAAO,QAAQ,QAAQ;IAC3B,UAAU,OAAO,OAAO,UAAU,sBAAsB,eAAe;IACvE,WAAW,OAAO,OAAO,cAAc,UAAU,iBAAiB,QAAQ,YAAY;;;;cCgB7E,4BAA0B,EAAA;;;;;GAUpC,EAAA,KAAA;;KAGS,8BAA8B,SAAS,EAAE,cAAc;cAE7D,0BAAwB,EAAA;;;;;;;;;;GAK5B,EAAA,KAAA;;KAEU,6BAA6B,SAAS,EAAE,aAAa;WACtD,YAAY;;;UCLN,+BAA+B;WACrC,SAAS;WACT,aAAa;aACX,SAAS;aACT,OAAO;aACP,QAAQC;QACb,UAAUC;WACP,SAAS;;;KAGR,2BAA2B,YAAY;;UAGlC;;WAEN,SAAS,SAAS,YAAY,QAAQ;;WAEtC,cAAc,SAAS,+BAA+B;;;wBAgCjD,sBAAsB,SAAS,yBAAyB"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { DurationString, Environment, ErrorCode, RunAccessGrant, RunAccessGrant as RunAccessGrant$1, RunId, RunReadOptions, RunReadPage, RunReadPermission, RunReadPermission as RunReadPermission$1, RunRecord, RunStreamRecord, RunSubscribeOptions, RunlaneError, RunlaneTelemetryRecordingContext, RuntimeRunSubscriptionEvent, VerifiedRunToken, VerifiedRunToken as VerifiedRunToken$1 } from "@runlane/contracts/realtime";
|
|
2
|
+
import { Awaitable } from "@runlane/utilities/browser";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { Lane } from "@runlane/contracts";
|
|
5
|
+
/** Structural read-only boundary. A core runtime satisfies it without importing HTTP code. */
|
|
6
|
+
interface RunlaneRealtimeSource {
|
|
7
|
+
readonly environment: Environment;
|
|
8
|
+
/** Optional committed-source hints; absent hints retain the polling fallback. */
|
|
9
|
+
readonly lane?: Pick<Lane, 'runSignal'>;
|
|
10
|
+
readonly runs: {
|
|
11
|
+
get(runId: RunId): Promise<RunRecord | undefined>;
|
|
12
|
+
subscribe(runId: RunId, options?: RunSubscribeOptions): AsyncGenerator<RuntimeRunSubscriptionEvent, void>;
|
|
13
|
+
readStream(runId: RunId, name: string, options?: RunReadOptions): Promise<RunReadPage<RunStreamRecord>>;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** Strict construction schema; claim and header constraints remain the canonical owners. */
|
|
17
|
+
declare const realtimeTokenOptionsSchema: z.ZodObject<{
|
|
18
|
+
audience: import("zod").ZodString;
|
|
19
|
+
keyId: z.ZodString;
|
|
20
|
+
key: z.ZodInstanceOf<CryptoKey>;
|
|
21
|
+
verifyKeys: z.ZodOptional<z.ZodReadonly<z.ZodRecord<z.ZodString, z.ZodInstanceOf<CryptoKey>>>>;
|
|
22
|
+
}, z.core.$strict>;
|
|
23
|
+
/** Active signing/verification key and previous verify-only keys. Keep all keys server-side. */
|
|
24
|
+
type RunlaneRealtimeTokenOptions = Readonly<z.output<typeof realtimeTokenOptionsSchema>>;
|
|
25
|
+
declare const createTokenOptionsSchema: z.ZodObject<{
|
|
26
|
+
runId: z.ZodString;
|
|
27
|
+
grant: import("zod").ZodOptional<import("zod").ZodObject<{
|
|
28
|
+
permissions: import("zod").ZodReadonly<import("zod").ZodArray<import("zod").ZodEnum<typeof RunReadPermission$1>>>;
|
|
29
|
+
streams: import("zod").ZodOptional<import("zod").ZodReadonly<import("zod").ZodArray<import("zod").ZodString>>>;
|
|
30
|
+
}, import("zod/v4/core").$strict>>;
|
|
31
|
+
expiresIn: import("zod").ZodOptional<import("zod").ZodPipe<import("zod").ZodCodec<import("zod").ZodString, import("zod").ZodCustom<`${number}d` | `${number}h` | `${number}ms` | `${number}m` | `${number}s`, `${number}d` | `${number}h` | `${number}ms` | `${number}m` | `${number}s`>>, import("zod").ZodTransform<{
|
|
32
|
+
duration: `${number}d` | `${number}h` | `${number}ms` | `${number}m` | `${number}s`;
|
|
33
|
+
milliseconds: number;
|
|
34
|
+
}, `${number}d` | `${number}h` | `${number}ms` | `${number}m` | `${number}s`>>>;
|
|
35
|
+
}, z.core.$strict>;
|
|
36
|
+
/** Minting inputs for one run. The app must check access before calling createToken. */
|
|
37
|
+
type CreateRealtimeTokenOptions = Readonly<z.input<typeof createTokenOptionsSchema>> & {
|
|
38
|
+
readonly expiresIn?: DurationString;
|
|
39
|
+
};
|
|
40
|
+
/** Server options require authorize, tokens, or both. Configured authorization limits every valid connection. */
|
|
41
|
+
interface RunlaneRealtimeOptions extends RunlaneTelemetryRecordingContext {
|
|
42
|
+
readonly runlane: RunlaneRealtimeSource;
|
|
43
|
+
readonly authorize?: (input: {
|
|
44
|
+
readonly request: Request;
|
|
45
|
+
readonly runId: RunId;
|
|
46
|
+
readonly token?: VerifiedRunToken$1;
|
|
47
|
+
}) => Awaitable<RunAccessGrant$1 | undefined>;
|
|
48
|
+
readonly tokens?: RunlaneRealtimeTokenOptions;
|
|
49
|
+
}
|
|
50
|
+
/** Authorization callback for a separately defined policy; undefined denies access to the run. */
|
|
51
|
+
type RunlaneRealtimeAuthorize = NonNullable<RunlaneRealtimeOptions['authorize']>;
|
|
52
|
+
/** Server entry for authorized reads and request-independent token minting. */
|
|
53
|
+
interface RunlaneRealtime {
|
|
54
|
+
/** Serves SSE reads; authorize, when configured, limits every valid connection. */
|
|
55
|
+
readonly handle: (request: Request) => Promise<Response>;
|
|
56
|
+
/** Mint after the app checks access. Does not call authorize or check run existence. */
|
|
57
|
+
readonly createToken: (options: CreateRealtimeTokenOptions) => Promise<string>;
|
|
58
|
+
}
|
|
59
|
+
/** Mounts authorized, bounded SSE reads without starting workers or adding runtime storage work. */
|
|
60
|
+
export declare function createRunlaneRealtime(options: RunlaneRealtimeOptions): RunlaneRealtime;
|
|
61
|
+
export { type CreateRealtimeTokenOptions, ErrorCode, type RunAccessGrant, RunReadPermission, RunlaneError, type RunlaneRealtime, type RunlaneRealtimeAuthorize, type RunlaneRealtimeOptions, type RunlaneRealtimeSource, type RunlaneRealtimeTokenOptions, type VerifiedRunToken };
|
|
62
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":["RunReadPermission","VerifiedRunToken","RunAccessGrant"],"sources":["../src/source.ts","../src/tokens.ts","../src/handler.ts"],"mappings":";;;;;UAaiB;WACN,aAAa;;WAEb,OAAO,KAAK;WACZ;IACP,IAAI,OAAO,QAAQ,QAAQ;IAC3B,UAAU,OAAO,OAAO,UAAU,sBAAsB,eAAe;IACvE,WAAW,OAAO,OAAO,cAAc,UAAU,iBAAiB,QAAQ,YAAY;;;;cCgB7E,4BAA0B,EAAA;;;;;GAUpC,EAAA,KAAA;;KAGS,8BAA8B,SAAS,EAAE,cAAc;cAE7D,0BAAwB,EAAA;;;;;;;;;;GAK5B,EAAA,KAAA;;KAEU,6BAA6B,SAAS,EAAE,aAAa;WACtD,YAAY;;;UCLN,+BAA+B;WACrC,SAAS;WACT,aAAa;aACX,SAAS;aACT,OAAO;aACP,QAAQC;QACb,UAAUC;WACP,SAAS;;;KAGR,2BAA2B,YAAY;;UAGlC;;WAEN,SAAS,SAAS,YAAY,QAAQ;;WAEtC,cAAc,SAAS,+BAA+B;;;wBAgCjD,sBAAsB,SAAS,yBAAyB"}
|