{
  "version": 3,
  "sources": ["twenty-sdk-define-stub:__twenty-sdk-define-stub__", "../../../src/constants/universal-identifiers.ts", "../../../src/config.ts", "../../../src/rateLimiter.ts", "../../../src/relayClient.ts", "../../../src/twentyRepository.ts", "../../../src/routeRuntime.ts", "../../../src/taskEventRuntime.ts", "../../../src/crypto.ts", "../../../src/eventId.ts", "../../../src/triggers/taskAssigned.ts", "../../../src/task-created.logic-function.ts"],
  "sourcesContent": ["\n// Auto-generated stub for twenty-sdk/define injected by the SDK CLI build.\n// Real implementations would pull in zod, twenty-shared and ~1MB of code; at\n// runtime only `default.config.handler` is consumed, so tiny no-ops suffice.\nconst __defineFactoryStub = (config) => ({\n  success: true,\n  config,\n  errors: [],\n});\n\nconst __anyHandler = {\n  get(_target, prop) {\n    if (prop === '__esModule') return true;\n    if (prop === Symbol.toPrimitive) return () => '';\n    if (typeof prop === 'symbol') return undefined;\n    return new Proxy(() => undefined, __anyHandler);\n  },\n  apply() {\n    return new Proxy(() => undefined, __anyHandler);\n  },\n};\nconst __anyStub = new Proxy(() => undefined, __anyHandler);\n\nexport const createValidationResult = __defineFactoryStub;\nexport const defineAgent = __defineFactoryStub;\nexport const defineApplication = __defineFactoryStub;\nexport const defineApplicationRole = __defineFactoryStub;\nexport const defineCommandMenuItem = __defineFactoryStub;\nexport const defineConnectionProvider = __defineFactoryStub;\nexport const defineField = __defineFactoryStub;\nexport const defineFrontComponent = __defineFactoryStub;\nexport const defineIndex = __defineFactoryStub;\nexport const defineLogicFunction = __defineFactoryStub;\nexport const defineNavigationMenuItem = __defineFactoryStub;\nexport const defineObject = __defineFactoryStub;\nexport const definePageLayout = __defineFactoryStub;\nexport const definePageLayoutTab = __defineFactoryStub;\nexport const definePermissionFlag = __defineFactoryStub;\nexport const definePostInstallLogicFunction = __defineFactoryStub;\nexport const definePreInstallLogicFunction = __defineFactoryStub;\nexport const defineRole = __defineFactoryStub;\nexport const defineSkill = __defineFactoryStub;\nexport const defineView = __defineFactoryStub;\nexport const defineViewField = __defineFactoryStub;\nexport const AggregateOperations = __anyStub;\nexport const DateDisplayFormat = __anyStub;\nexport const FieldMetadataSettingsOnClickAction = __anyStub;\nexport const FieldType = __anyStub;\nexport const HTTPMethod = __anyStub;\nexport const NavigationMenuItemType = __anyStub;\nexport const NumberDataType = __anyStub;\nexport const ObjectRecordGroupByDateGranularity = __anyStub;\nexport const OnDeleteAction = __anyStub;\nexport const PageLayoutTabLayoutMode = __anyStub;\nexport const RelationType = __anyStub;\nexport const STANDARD_OBJECT = __anyStub;\nexport const STANDARD_OBJECT_UNIVERSAL_IDENTIFIERS = __anyStub;\nexport const STANDARD_PAGE_LAYOUT = __anyStub;\nexport const STANDARD_PAGE_LAYOUT_UNIVERSAL_IDENTIFIERS = __anyStub;\nexport const SystemPermissionFlag = __anyStub;\nexport const ViewCalendarLayout = __anyStub;\nexport const ViewFilterGroupLogicalOperator = __anyStub;\nexport const ViewFilterOperand = __anyStub;\nexport const ViewKey = __anyStub;\nexport const ViewOpenRecordIn = __anyStub;\nexport const ViewSortDirection = __anyStub;\nexport const ViewType = __anyStub;\nexport const ViewVisibility = __anyStub;\nexport const canAccessFullAdminPanel = __anyStub;\nexport const canImpersonate = __anyStub;\nexport const every = __anyStub;\nexport const everyDefined = __anyStub;\nexport const everyEquals = __anyStub;\nexport const favoriteRecordIds = __anyStub;\nexport const featureFlags = __anyStub;\nexport const generateDefaultFieldUniversalIdentifier = __anyStub;\nexport const hasAnySoftDeleteFilterOnView = __anyStub;\nexport const includes = __anyStub;\nexport const includesEvery = __anyStub;\nexport const isDashboardPageLayoutInEditMode = __anyStub;\nexport const isDefined = __anyStub;\nexport const isInSidePanel = __anyStub;\nexport const isLayoutCustomizationModeEnabled = __anyStub;\nexport const isNonEmptyString = __anyStub;\nexport const isSelectAll = __anyStub;\nexport const none = __anyStub;\nexport const noneDefined = __anyStub;\nexport const noneEquals = __anyStub;\nexport const numberOfSelectedRecords = __anyStub;\nexport const objectMetadataItem = __anyStub;\nexport const objectMetadataLabel = __anyStub;\nexport const objectPermissions = __anyStub;\nexport const pageType = __anyStub;\nexport const selectedRecords = __anyStub;\nexport const some = __anyStub;\nexport const someDefined = __anyStub;\nexport const someEquals = __anyStub;\nexport const someNonEmptyString = __anyStub;\nexport const targetObjectReadPermissions = __anyStub;\nexport const targetObjectWritePermissions = __anyStub;\nexport const validateFields = __anyStub;\n", "export const APP_DISPLAY_NAME = \"Viginti Mobile Push\";\nexport const APP_DESCRIPTION =\n  \"Registers iOS and iPadOS devices for Viginti remote push notifications and relays task assignment events through a Cloudflare Worker to Firebase Cloud Messaging.\";\n\nexport const APPLICATION_UNIVERSAL_IDENTIFIER = \"05ce64a4-c1ee-4f4e-885c-bc1f7123a25b\";\nexport const DEFAULT_ROLE_UNIVERSAL_IDENTIFIER = \"4c8246e5-0a05-4155-816c-9ec4cb79c04b\";\nexport const RELAY_BASE_URL_VARIABLE_UNIVERSAL_IDENTIFIER =\n  \"06000b38-8fe0-413c-9b19-22afb1974ff5\";\nexport const POST_INSTALL_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER =\n  \"f9791ee7-af73-41e2-81aa-08bd9e29c876\";\nexport const STATUS_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER =\n  \"c80d22cf-ce36-485b-8bd3-07d9caf0ba33\";\nexport const REGISTER_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER =\n  \"806f4f64-9676-4af1-825c-bef656ab0fab\";\nexport const UNREGISTER_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER =\n  \"b768f8c5-e660-49ba-a302-e7b7cb7bb2c1\";\nexport const PREFERENCES_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER =\n  \"5b32dcbd-86dc-4f3b-adb6-e98eea298b69\";\nexport const TEST_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER =\n  \"ce6343cd-24f0-4faf-8c34-6ea5f5af4bda\";\nexport const TASK_CREATED_PUSH_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER =\n  \"b845b39b-aaad-42eb-82aa-97ac6742b8b4\";\nexport const TASK_UPDATED_PUSH_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER =\n  \"f7fda668-8229-427f-92f0-fb1521d2a067\";\n\nexport const PUSH_DEVICE_OBJECT_UNIVERSAL_IDENTIFIER =\n  \"9b8388f0-36f5-4cfc-8d4f-aaac5f358c05\";\nexport const PUSH_DEVICE_INDEX_UNIVERSAL_IDENTIFIER =\n  \"995bdfe7-9d9b-4e81-a8e3-f738e2ab5ded\";\nexport const PUSH_DEVICE_FIELD_UNIVERSAL_IDENTIFIERS = {\n  installationId: \"11672460-4bc9-4adc-9815-3a1e4580e4f7\",\n  workspaceMemberId: \"ea864f90-59e2-4f09-8be5-b431416731d5\",\n  fcmToken: \"91d5f03f-5fcc-417c-a97e-5d0ebf689564\",\n  tokenHash: \"7fa4054d-dd2e-4c10-b8fd-91318d1833c9\",\n  platform: \"35fde69d-4fcd-4b6d-b560-00f9bebd0d9d\",\n  environment: \"07e09c4a-d328-42fc-a0ef-d7f74c70262b\",\n  bundleIdentifier: \"4c8c1a24-36d8-4ec5-a983-8468be33f7e6\",\n  appVersion: \"ef80c428-1a95-4532-94be-bdbedea30fcc\",\n  buildNumber: \"220a51d3-a7aa-4ead-822b-7eaa0a8f0e39\",\n  deviceLocale: \"88e14f0c-511e-4671-bfb3-bd938965f893\",\n  timeZone: \"33469cde-22f6-47ca-818c-b4a4485c90d0\",\n  notificationsEnabled: \"081b6f77-1083-4d73-aff5-f210bf8e001a\",\n  taskAssignedEnabled: \"0996e12d-a6c1-4eef-a797-0d0646033736\",\n  taskDueDateChangedEnabled: \"30c399a9-2fd4-4c17-a98a-e1368f614c7e\",\n  taskCompletedEnabled: \"e0689b0a-95fd-4117-9c48-326e02830772\",\n  taskUnassignedEnabled: \"4a91a20a-199f-4f31-8e84-7f00b29e92fc\",\n  lastSeenAt: \"1f29217a-9bf6-4694-bed6-9f318941ead0\",\n  disabledAt: \"d9970b6e-ce54-4e4a-a66d-28b9ec8351d5\",\n  lastDeliveryError: \"cebc6621-f35a-4694-8f11-f04155d3081c\",\n} as const;\n", "/**\n * App configuration resolved from Twenty's injected runtime environment.\n */\nexport interface AppConfig {\n  /** Base URL of the Cloudflare relay, e.g. https://relay.example.workers.dev */\n  relayBaseUrl: string;\n  /** Twenty's application installation id, sent as X-Twenty-Push-Installation. */\n  installationId: string;\n  /** Twenty app access token injected into logic functions/install hooks. */\n  relayAuthToken: string;\n  /** Twenty API URL used by the relay to verify the app access token on install. */\n  twentyApiUrl: string;\n}\n\nexport class AppConfigError extends Error {}\n\nfunction normalizeHttpsUrl(value: string | undefined): string | null {\n  const trimmed = (value ?? \"\").trim().replace(/\\/+$/, \"\");\n  return /^https:\\/\\//.test(trimmed) ? trimmed : null;\n}\n\nfunction resolveTwentyApiUrl(env: Record<string, string | undefined>): string {\n  return (\n    normalizeHttpsUrl(env.API_URL) ??\n    normalizeHttpsUrl(env.TWENTY_API_URL) ??\n    normalizeHttpsUrl(env.SERVER_URL) ??\n    normalizeHttpsUrl(env.TWENTY_SERVER_URL) ??\n    \"https://api.twenty.com\"\n  );\n}\n\nexport function loadAppConfig(env: Record<string, string | undefined>): AppConfig {\n  const relayBaseUrl = normalizeHttpsUrl(env.RELAY_BASE_URL) ?? \"\";\n  const installationId = (env.APPLICATION_ID ?? env.RELAY_INSTALLATION_ID ?? \"\").trim();\n  const relayAuthToken = (env.APP_ACCESS_TOKEN ?? env.TWENTY_APP_ACCESS_TOKEN ?? \"\").trim();\n  const twentyApiUrl = resolveTwentyApiUrl(env);\n\n  if (!relayBaseUrl) {\n    throw new AppConfigError(\"RELAY_BASE_URL must be an https URL\");\n  }\n  if (!installationId) {\n    throw new AppConfigError(\"APPLICATION_ID is missing\");\n  }\n  if (!relayAuthToken) {\n    throw new AppConfigError(\"APP_ACCESS_TOKEN is missing\");\n  }\n  return { relayBaseUrl, installationId, relayAuthToken, twentyApiUrl };\n}\n\n/** True when the relay env is present and valid. Never throws. */\nexport function isRelayConfigured(env: Record<string, string | undefined>): boolean {\n  try {\n    loadAppConfig(env);\n    return true;\n  } catch {\n    return false;\n  }\n}\n", "/**\n * Minimal fixed-window rate limiter. In-memory by default (per app instance);\n * swap for a shared store if stronger guarantees are needed.\n */\nexport interface RateLimiter {\n  /** Returns true if the action is allowed and consumes one unit. */\n  tryConsume(key: string): boolean;\n}\n\nexport class InMemoryRateLimiter implements RateLimiter {\n  private readonly hits = new Map<string, { count: number; windowStart: number }>();\n\n  constructor(\n    private readonly limit: number,\n    private readonly windowMs: number,\n    private readonly now: () => number = () => Date.now(),\n  ) {}\n\n  tryConsume(key: string): boolean {\n    const current = this.now();\n    const entry = this.hits.get(key);\n    if (!entry || current - entry.windowStart >= this.windowMs) {\n      this.hits.set(key, { count: 1, windowStart: current });\n      return true;\n    }\n    if (entry.count >= this.limit) {\n      return false;\n    }\n    entry.count++;\n    return true;\n  }\n}\n\nexport const inMemoryRateLimiter = new InMemoryRateLimiter(3, 60_000);\n", "/**\n * Client for the Cloudflare push relay. Authenticates with Twenty's injected\n * app access token and parses the aggregated result. The app never sends\n * notification text \u2014 only opaque IDs; the relay owns the copy.\n *\n * The relay is reached via this single interface; the app does not know (or\n * care) whether the worker dispatches directly to FCM or, later, via a queue.\n */\n\nimport type { AppConfig } from \"./config\";\nimport type { RemotePushEventType } from \"./types\";\n\nexport interface RelayMessage {\n  deviceId: string;\n  token: string;\n  data: {\n    version: \"1\";\n    type: RemotePushEventType;\n    workspaceId: string;\n    recordId: string;\n    eventId: string;\n  };\n}\n\nexport interface RelayJob {\n  eventId: string;\n  type: RemotePushEventType;\n  messages: RelayMessage[];\n}\n\nexport interface RelayResult {\n  success: boolean;\n  eventId: string;\n  delivered: number;\n  invalidDeviceIds: string[];\n  temporaryFailures: number;\n  permanentFailures: number;\n}\n\nexport type FetchLike = typeof fetch;\n\n/** Interface over the relay so callers don't depend on the concrete client. */\nexport interface RelayDispatcher {\n  dispatch(job: RelayJob): Promise<RelayResult>;\n}\n\nexport class RelayClient implements RelayDispatcher {\n  constructor(\n    private readonly config: AppConfig,\n    private readonly fetchImpl: FetchLike = fetch,\n    private readonly now: () => number = () => Math.floor(Date.now() / 1000),\n  ) {}\n\n  async dispatch(job: RelayJob): Promise<RelayResult> {\n    const timestamp = this.now();\n    const body = JSON.stringify({\n      version: 1,\n      eventId: job.eventId,\n      installationId: this.config.installationId,\n      timestamp,\n      type: job.type,\n      messages: job.messages,\n    });\n\n    const response = await this.fetchImpl(`${this.config.relayBaseUrl}/v1/push`, {\n      method: \"POST\",\n      headers: {\n        \"content-type\": \"application/json\",\n        \"authorization\": `Bearer ${this.config.relayAuthToken}`,\n        \"x-twenty-push-installation\": this.config.installationId,\n      },\n      body,\n    });\n\n    if (!response.ok) {\n      throw new RelayError(`Relay returned HTTP ${response.status}`, response.status);\n    }\n\n    const parsed = (await response.json()) as {\n      success?: boolean;\n      eventId?: string;\n      results?: {\n        delivered?: number;\n        invalidDeviceIds?: string[];\n        temporaryFailures?: number;\n        permanentFailures?: number;\n      };\n    };\n\n    const results = parsed.results ?? {};\n    return {\n      success: parsed.success === true,\n      eventId: parsed.eventId ?? job.eventId,\n      delivered: results.delivered ?? 0,\n      invalidDeviceIds: Array.isArray(results.invalidDeviceIds) ? results.invalidDeviceIds : [],\n      temporaryFailures: results.temporaryFailures ?? 0,\n      permanentFailures: results.permanentFailures ?? 0,\n    };\n  }\n}\n\nexport class RelayError extends Error {\n  constructor(\n    message: string,\n    readonly httpStatus: number,\n  ) {\n    super(message);\n  }\n}\n", "import type { AppConfig } from \"./config\";\nimport type { CreatePushDeviceInput, PushDeviceRepository } from \"./repository\";\nimport type { PushDeviceRecord } from \"./types\";\n\nconst PUSH_DEVICE_FIELDS = `\n  id\n  installationId\n  workspaceMemberId\n  fcmToken\n  tokenHash\n  platform\n  environment\n  bundleIdentifier\n  appVersion\n  buildNumber\n  deviceLocale\n  timeZone\n  notificationsEnabled\n  taskAssignedEnabled\n  taskDueDateChangedEnabled\n  taskCompletedEnabled\n  taskUnassignedEnabled\n  lastSeenAt\n  disabledAt\n  lastDeliveryError\n  createdAt\n  updatedAt\n`;\n\ninterface GraphQLResponse<T> {\n  data?: T;\n  errors?: { message: string }[];\n}\n\ntype PushDeviceConnection = {\n  pushDevices: {\n    edges: { node: PushDeviceRecord }[];\n  };\n};\n\nexport class TwentyGraphQLPushDeviceRepository implements PushDeviceRepository {\n  constructor(\n    private readonly config: AppConfig,\n    private readonly fetchImpl: typeof fetch = fetch,\n  ) {}\n\n  async findByMemberAndInstallation(\n    workspaceMemberId: string,\n    installationId: string,\n  ): Promise<PushDeviceRecord | null> {\n    const data = await this.graphql<PushDeviceConnection>(\n      `query PushDeviceByMemberAndInstallation($workspaceMemberId: String!, $installationId: String!) {\n        pushDevices(\n          first: 1\n          filter: {\n            workspaceMemberId: { eq: $workspaceMemberId }\n            installationId: { eq: $installationId }\n          }\n        ) {\n          edges { node { ${PUSH_DEVICE_FIELDS} } }\n        }\n      }`,\n      { workspaceMemberId, installationId },\n    );\n\n    return data.pushDevices.edges[0]?.node ?? null;\n  }\n\n  async create(input: CreatePushDeviceInput): Promise<PushDeviceRecord> {\n    const data = await this.graphql<{ createPushDevice: PushDeviceRecord }>(\n      `mutation CreatePushDevice($data: PushDeviceCreateInput!) {\n        createPushDevice(data: $data) { ${PUSH_DEVICE_FIELDS} }\n      }`,\n      {\n        data: {\n          ...input,\n          taskAssignedEnabled: true,\n          taskDueDateChangedEnabled: false,\n          taskCompletedEnabled: false,\n          taskUnassignedEnabled: false,\n          disabledAt: null,\n          lastDeliveryError: null,\n        },\n      },\n    );\n\n    return data.createPushDevice;\n  }\n\n  async update(id: string, patch: Partial<PushDeviceRecord>): Promise<PushDeviceRecord> {\n    const data = await this.graphql<{ updatePushDevice: PushDeviceRecord }>(\n      `mutation UpdatePushDevice($id: UUID!, $data: PushDeviceUpdateInput!) {\n        updatePushDevice(id: $id, data: $data) { ${PUSH_DEVICE_FIELDS} }\n      }`,\n      { id, data: sanitizePatch(patch) },\n    );\n\n    return data.updatePushDevice;\n  }\n\n  async findActiveByMember(workspaceMemberId: string): Promise<PushDeviceRecord[]> {\n    const data = await this.graphql<PushDeviceConnection>(\n      `query ActivePushDevices($workspaceMemberId: String!) {\n        pushDevices(\n          first: 100\n          filter: {\n            workspaceMemberId: { eq: $workspaceMemberId }\n            notificationsEnabled: { eq: true }\n            disabledAt: { is: NULL }\n          }\n        ) {\n          edges { node { ${PUSH_DEVICE_FIELDS} } }\n        }\n      }`,\n      { workspaceMemberId },\n    );\n\n    return data.pushDevices.edges.map((edge) => edge.node);\n  }\n\n  async findById(id: string): Promise<PushDeviceRecord | null> {\n    const data = await this.graphql<{ pushDevice: PushDeviceRecord | null }>(\n      `query PushDeviceById($id: UUID!) {\n        pushDevice(filter: { id: { eq: $id } }) { ${PUSH_DEVICE_FIELDS} }\n      }`,\n      { id },\n    );\n\n    return data.pushDevice;\n  }\n\n  private async graphql<T>(query: string, variables: Record<string, unknown>): Promise<T> {\n    const response = await this.fetchImpl(`${this.config.twentyApiUrl}/graphql`, {\n      method: \"POST\",\n      headers: {\n        \"content-type\": \"application/json\",\n        \"authorization\": `Bearer ${this.config.relayAuthToken}`,\n      },\n      body: JSON.stringify({ query, variables }),\n    });\n\n    const body = (await response.json()) as GraphQLResponse<T>;\n    if (!response.ok || body.errors?.length) {\n      const message = body.errors?.map((error) => error.message).join(\"; \") || response.statusText;\n      throw new Error(`Twenty GraphQL request failed: ${message}`);\n    }\n    if (!body.data) {\n      throw new Error(\"Twenty GraphQL request returned no data\");\n    }\n    return body.data;\n  }\n}\n\nfunction sanitizePatch(patch: Partial<PushDeviceRecord>): Partial<PushDeviceRecord> {\n  const { id: _id, createdAt: _createdAt, updatedAt: _updatedAt, ...data } = patch;\n  return data;\n}\n", "import { Response, type RoutePayload } from \"twenty-sdk/logic-function\";\n\nimport { loadAppConfig } from \"./config\";\nimport { inMemoryRateLimiter } from \"./rateLimiter\";\nimport { RelayClient } from \"./relayClient\";\nimport { TwentyGraphQLPushDeviceRepository } from \"./twentyRepository\";\nimport { HandlerError, type AuthContext, type HandlerResult } from \"./types\";\n\nexport interface RuntimeDeps {\n  repository: TwentyGraphQLPushDeviceRepository;\n  relay: RelayClient;\n  rateLimiter: typeof inMemoryRateLimiter;\n  now: () => Date;\n}\n\nexport function routeBody(event: RoutePayload): unknown {\n  if (event.body !== null) {\n    return event.body;\n  }\n  if (event.rawBody && event.rawBody.length > 0) {\n    return JSON.parse(event.rawBody) as unknown;\n  }\n  return {};\n}\n\n/**\n * Resolves the identity of the workspace member behind a Twenty bearer token.\n * Extracted as a seam so the auth check can be unit-tested without network and\n * so the member is resolved from Twenty itself rather than guessed from JWT\n * claims (which OAuth/PKCE access tokens do not carry).\n */\nexport interface IdentityResolver {\n  resolveWorkspaceMemberId(bearerToken: string): Promise<string | null>;\n}\n\nexport async function authContext(\n  event: RoutePayload,\n  identity?: IdentityResolver,\n): Promise<AuthContext> {\n  if (!event.userWorkspaceId) {\n    throw new HandlerError(401, \"unauthenticated\", \"Authentication is required\");\n  }\n\n  const token = bearerToken(event);\n  if (!token) {\n    throw new HandlerError(\n      401,\n      \"personal_session_required\",\n      \"A personal Twenty session is required\",\n    );\n  }\n\n  // The runtime has already accepted the token (userWorkspaceId is set). Ask\n  // Twenty who the member is, using the caller's own token \u2014 this works for\n  // both personal-session JWTs and workspace-agnostic OAuth access tokens.\n  const resolver = identity ?? defaultIdentityResolver();\n  const workspaceMemberId = await resolver.resolveWorkspaceMemberId(token);\n  if (!workspaceMemberId) {\n    throw new HandlerError(\n      401,\n      \"personal_session_required\",\n      \"A personal Twenty session is required\",\n    );\n  }\n\n  return {\n    workspaceId: resolveWorkspaceId(process.env),\n    workspaceMemberId,\n    isAdmin: false,\n  };\n}\n\nfunction bearerToken(event: RoutePayload): string | null {\n  const authorization = Object.entries(event.headers).find(\n    ([name]) => name.toLowerCase() === \"authorization\",\n  )?.[1];\n  return authorization?.match(/^Bearer\\s+(.+)$/i)?.[1] ?? null;\n}\n\nfunction defaultIdentityResolver(): IdentityResolver {\n  const config = loadAppConfig(process.env);\n  return new TwentyIdentityResolver(config.twentyApiUrl);\n}\n\n/**\n * Resolves the current workspace member via Twenty's metadata GraphQL endpoint\n * using the caller's bearer token. `currentUser.workspaceMember.id` is the same\n * field the mobile client already reads after login.\n */\nexport class TwentyIdentityResolver implements IdentityResolver {\n  constructor(\n    private readonly twentyApiUrl: string,\n    private readonly fetchImpl: typeof fetch = fetch,\n  ) {}\n\n  async resolveWorkspaceMemberId(bearerToken: string): Promise<string | null> {\n    let response: Awaited<ReturnType<typeof fetch>>;\n    try {\n      response = await this.fetchImpl(`${this.twentyApiUrl}/metadata`, {\n        method: \"POST\",\n        headers: {\n          \"content-type\": \"application/json\",\n          authorization: `Bearer ${bearerToken}`,\n        },\n        body: JSON.stringify({\n          query:\n            \"query PushAuthContext { currentUser { workspaceMember { id } } }\",\n        }),\n      });\n    } catch {\n      return null;\n    }\n\n    if (!response.ok) {\n      return null;\n    }\n\n    const body = (await response.json()) as {\n      data?: { currentUser?: { workspaceMember?: { id?: string } | null } | null };\n    };\n    return body.data?.currentUser?.workspaceMember?.id ?? null;\n  }\n}\n\nexport function runtimeDeps(): RuntimeDeps {\n  const config = loadAppConfig(process.env);\n  return {\n    repository: new TwentyGraphQLPushDeviceRepository(config),\n    relay: new RelayClient(config),\n    rateLimiter: inMemoryRateLimiter,\n    now: () => new Date(),\n  };\n}\n\nexport function httpResponse(result: HandlerResult): Response {\n  return new Response(result.body, { status: result.status });\n}\n\nexport function errorResponse(error: unknown): Response {\n  if (error instanceof HandlerError) {\n    return new Response(\n      { success: false, code: error.code, error: error.message },\n      { status: error.status },\n    );\n  }\n\n  return new Response(\n    {\n      success: false,\n      code: \"internal_error\",\n      error: error instanceof Error ? error.message : \"Unexpected error\",\n    },\n    { status: 500 },\n  );\n}\n\nfunction resolveWorkspaceId(env: Record<string, string | undefined>): string {\n  const explicit = env.WORKSPACE_ID?.trim();\n  if (explicit) {\n    return explicit;\n  }\n\n  const token = (env.APP_ACCESS_TOKEN ?? env.TWENTY_APP_ACCESS_TOKEN ?? \"\").trim();\n  const parts = token.split(\".\");\n  if (parts.length < 2) {\n    return \"unknown\";\n  }\n\n  try {\n    const payload = JSON.parse(base64UrlDecode(parts[1])) as { workspaceId?: string };\n    return payload.workspaceId ?? \"unknown\";\n  } catch {\n    return \"unknown\";\n  }\n}\n\nfunction base64UrlDecode(value: string): string {\n  const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n  const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, \"=\");\n  return Buffer.from(padded, \"base64\").toString(\"utf8\");\n}\n", "import type { DatabaseEventPayload } from \"twenty-sdk/logic-function\";\n\nimport { runtimeDeps } from \"./routeRuntime\";\nimport type { TaskAssignedDeps, TaskAssignedEvent, TaskSnapshot } from \"./triggers/taskAssigned\";\n\nexport function taskEventFromPayload(\n  payload: DatabaseEventPayload,\n  operation: \"created\" | \"updated\",\n): TaskAssignedEvent {\n  const properties = payload.properties as {\n    before?: Record<string, unknown> | null;\n    after?: Record<string, unknown> | null;\n  };\n  const after = snapshotFromRecord(properties.after, payload.recordId);\n  if (!after) {\n    throw new Error(\"Task event payload is missing properties.after\");\n  }\n\n  return {\n    operation,\n    workspaceId: payload.workspaceId,\n    actorWorkspaceMemberId: payload.workspaceMemberId ?? payload.userWorkspaceId ?? null,\n    before: snapshotFromRecord(properties.before, payload.recordId),\n    after,\n  };\n}\n\nexport function taskTriggerDeps(): TaskAssignedDeps {\n  const deps = runtimeDeps();\n  return {\n    repository: deps.repository,\n    relay: deps.relay,\n    now: deps.now,\n    log: (fields) => console.info(JSON.stringify(fields)),\n  };\n}\n\nfunction snapshotFromRecord(\n  record: Record<string, unknown> | null | undefined,\n  fallbackId: string,\n): TaskSnapshot | null {\n  if (!record) {\n    return null;\n  }\n\n  return {\n    id: stringValue(record.id) ?? fallbackId,\n    assigneeWorkspaceMemberId: stringValue(record.assigneeWorkspaceMemberId),\n    assigneeId: stringValue(record.assigneeId),\n    assignee: relationValue(record.assignee),\n    dueAt: stringValue(record.dueAt),\n    status: stringValue(record.status),\n    updatedAt: stringValue(record.updatedAt) ?? new Date().toISOString(),\n  };\n}\n\nfunction relationValue(value: unknown): { id?: string | null } | null {\n  if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n    return null;\n  }\n  const id = stringValue((value as Record<string, unknown>).id);\n  return id ? { id } : null;\n}\n\nfunction stringValue(value: unknown): string | null {\n  return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : null;\n}\n", "/** Web Crypto helpers (Node 18+ / Twenty runtime both expose globalThis.crypto). */\n\nconst encoder = new TextEncoder();\n\nfunction toHex(buffer: ArrayBuffer): string {\n  const bytes = new Uint8Array(buffer);\n  let out = \"\";\n  for (const b of bytes) out += b.toString(16).padStart(2, \"0\");\n  return out;\n}\n\nexport async function sha256Hex(input: string): Promise<string> {\n  const digest = await crypto.subtle.digest(\"SHA-256\", encoder.encode(input));\n  return toHex(digest);\n}\n\n/** Short non-reversible fingerprint of a token for safe storage/search. */\nexport async function tokenFingerprint(token: string, length = 16): Promise<string> {\n  return (await sha256Hex(token)).slice(0, length);\n}\n\n/** HMAC-SHA256 over `timestamp + \".\" + rawBody`, returns lowercase hex. */\nexport async function hmacSignatureHex(\n  secret: string,\n  timestamp: string,\n  rawBody: string,\n): Promise<string> {\n  const key = await crypto.subtle.importKey(\n    \"raw\",\n    encoder.encode(secret),\n    { name: \"HMAC\", hash: \"SHA-256\" },\n    false,\n    [\"sign\"],\n  );\n  const signed = await crypto.subtle.sign(\"HMAC\", key, encoder.encode(`${timestamp}.${rawBody}`));\n  return toHex(signed);\n}\n", "/**\n * Stable event id for a push job. Prefer the native Twenty event id when the\n * database event provides one; otherwise derive a deterministic id so retries /\n * replays of the same logical change collapse to one id. This is forwarded to\n * the relay and is the seed for a future D1-backed deduplication store.\n */\n\nimport { sha256Hex } from \"./crypto\";\nimport type { RemotePushEventType } from \"./types\";\n\nexport interface DeterministicEventInput {\n  workspaceId: string;\n  type: RemotePushEventType;\n  recordId: string;\n  recipientWorkspaceMemberId: string;\n  relevantUpdatedAt: string;\n}\n\nexport async function deterministicEventId(input: DeterministicEventInput): Promise<string> {\n  const seed = [\n    input.workspaceId,\n    input.type,\n    input.recordId,\n    input.recipientWorkspaceMemberId,\n    input.relevantUpdatedAt,\n  ].join(\"|\");\n  return sha256Hex(seed);\n}\n\nexport async function resolveEventId(\n  nativeEventId: string | null | undefined,\n  fallback: DeterministicEventInput,\n): Promise<string> {\n  if (nativeEventId && nativeEventId.length > 0) {\n    return nativeEventId;\n  }\n  return deterministicEventId(fallback);\n}\n", "/**\n * Task push trigger logic.\n *\n * Pushes are supplementary to CRM writes: relay failures are logged and returned\n * as skipped outcomes, never thrown to the Twenty database transaction.\n */\n\nimport { resolveEventId } from \"../eventId\";\nimport type { RelayDispatcher, RelayMessage } from \"../relayClient\";\nimport type { PushDeviceRepository } from \"../repository\";\nimport type { PushDeviceRecord, RemotePushEventType } from \"../types\";\n\nexport interface TaskSnapshot {\n  id: string;\n  assigneeWorkspaceMemberId?: string | null;\n  assigneeId?: string | null;\n  assignee?: { id?: string | null } | null;\n  dueAt?: string | null;\n  status?: string | null;\n  updatedAt: string;\n}\n\nexport interface TaskAssignedEvent {\n  operation: \"created\" | \"updated\";\n  workspaceId: string;\n  nativeEventId?: string | null;\n  actorWorkspaceMemberId?: string | null;\n  before?: TaskSnapshot | null;\n  after: TaskSnapshot;\n}\n\nexport type SkipReason =\n  | \"no_recipient\"\n  | \"no_assignment_change\"\n  | \"no_due_date_change\"\n  | \"no_completion_change\"\n  | \"no_unassignment_change\"\n  | \"self_assignment\"\n  | \"preference_disabled_or_no_active_devices\"\n  | \"relay_error\";\n\nexport interface TriggerOutcome {\n  sent: boolean;\n  type?: RemotePushEventType;\n  skipReason?: SkipReason;\n  delivered?: number;\n  invalidDeviceIds?: string[];\n  temporaryFailures?: number;\n}\n\nexport interface TaskAssignedDeps {\n  repository: PushDeviceRepository;\n  relay: RelayDispatcher;\n  now: () => Date;\n  log?: (fields: Record<string, unknown>) => void;\n}\n\ntype PreferenceKey =\n  | \"taskAssignedEnabled\"\n  | \"taskDueDateChangedEnabled\"\n  | \"taskCompletedEnabled\"\n  | \"taskUnassignedEnabled\";\n\ninterface DetectedTaskPush {\n  type: RemotePushEventType;\n  recipient: string | null;\n  preferenceKey: PreferenceKey;\n  skipWhenMissing: SkipReason;\n}\n\nexport async function handleTaskAssigned(\n  event: TaskAssignedEvent,\n  deps: TaskAssignedDeps,\n): Promise<TriggerOutcome> {\n  return handleDetectedPush(event, deps, detectTaskAssigned(event));\n}\n\nexport async function handleTaskDueDateChanged(\n  event: TaskAssignedEvent,\n  deps: TaskAssignedDeps,\n): Promise<TriggerOutcome> {\n  return handleDetectedPush(event, deps, detectTaskDueDateChanged(event));\n}\n\nexport async function handleTaskCompleted(\n  event: TaskAssignedEvent,\n  deps: TaskAssignedDeps,\n): Promise<TriggerOutcome> {\n  return handleDetectedPush(event, deps, detectTaskCompleted(event));\n}\n\nexport async function handleTaskUnassigned(\n  event: TaskAssignedEvent,\n  deps: TaskAssignedDeps,\n): Promise<TriggerOutcome> {\n  return handleDetectedPush(event, deps, detectTaskUnassigned(event));\n}\n\nexport async function handleTaskUpdatedPushes(\n  event: TaskAssignedEvent,\n  deps: TaskAssignedDeps,\n): Promise<TriggerOutcome[]> {\n  return Promise.all([\n    handleTaskAssigned(event, deps),\n    handleTaskDueDateChanged(event, deps),\n    handleTaskCompleted(event, deps),\n    handleTaskUnassigned(event, deps),\n  ]);\n}\n\nasync function handleDetectedPush(\n  event: TaskAssignedEvent,\n  deps: TaskAssignedDeps,\n  detected: DetectedTaskPush | null,\n): Promise<TriggerOutcome> {\n  if (!detected) {\n    return { sent: false, skipReason: skipReasonForNoChange(event) };\n  }\n  if (!detected.recipient) {\n    return { sent: false, type: detected.type, skipReason: detected.skipWhenMissing };\n  }\n  if (event.actorWorkspaceMemberId && event.actorWorkspaceMemberId === detected.recipient) {\n    return { sent: false, type: detected.type, skipReason: \"self_assignment\" };\n  }\n\n  const devices = (await deps.repository.findActiveByMember(detected.recipient)).filter(\n    (device) =>\n      device[detected.preferenceKey] &&\n      device.notificationsEnabled &&\n      !device.disabledAt,\n  );\n  if (devices.length === 0) {\n    return {\n      sent: false,\n      type: detected.type,\n      skipReason: \"preference_disabled_or_no_active_devices\",\n    };\n  }\n\n  return sendPush(event, deps, detected.type, detected.recipient, devices);\n}\n\nfunction detectTaskAssigned(event: TaskAssignedEvent): DetectedTaskPush | null {\n  const recipient = assigneeId(event.after);\n  if (!recipient) {\n    return {\n      type: \"task_assigned\",\n      recipient: null,\n      preferenceKey: \"taskAssignedEnabled\",\n      skipWhenMissing: \"no_recipient\",\n    };\n  }\n\n  if (event.operation === \"updated\" && assigneeId(event.before) === recipient) {\n    return null;\n  }\n\n  return {\n    type: \"task_assigned\",\n    recipient,\n    preferenceKey: \"taskAssignedEnabled\",\n    skipWhenMissing: \"no_recipient\",\n  };\n}\n\nfunction detectTaskDueDateChanged(event: TaskAssignedEvent): DetectedTaskPush | null {\n  if (event.operation !== \"updated\" || normalizeDate(event.before?.dueAt) === normalizeDate(event.after.dueAt)) {\n    return null;\n  }\n  return {\n    type: \"task_due_date_changed\",\n    recipient: assigneeId(event.after),\n    preferenceKey: \"taskDueDateChangedEnabled\",\n    skipWhenMissing: \"no_recipient\",\n  };\n}\n\nfunction detectTaskCompleted(event: TaskAssignedEvent): DetectedTaskPush | null {\n  if (event.operation !== \"updated\") {\n    return null;\n  }\n  const beforeDone = isCompletedStatus(event.before?.status);\n  const afterDone = isCompletedStatus(event.after.status);\n  if (beforeDone || !afterDone) {\n    return null;\n  }\n  return {\n    type: \"task_completed\",\n    recipient: assigneeId(event.after),\n    preferenceKey: \"taskCompletedEnabled\",\n    skipWhenMissing: \"no_recipient\",\n  };\n}\n\nfunction detectTaskUnassigned(event: TaskAssignedEvent): DetectedTaskPush | null {\n  if (event.operation !== \"updated\") {\n    return null;\n  }\n  const previous = assigneeId(event.before);\n  const next = assigneeId(event.after);\n  if (!previous || previous === next) {\n    return null;\n  }\n  return {\n    type: \"task_unassigned\",\n    recipient: previous,\n    preferenceKey: \"taskUnassignedEnabled\",\n    skipWhenMissing: \"no_unassignment_change\",\n  };\n}\n\nasync function sendPush(\n  event: TaskAssignedEvent,\n  deps: TaskAssignedDeps,\n  type: RemotePushEventType,\n  recipient: string,\n  devices: PushDeviceRecord[],\n): Promise<TriggerOutcome> {\n  const eventId = await resolveEventId(event.nativeEventId, {\n    workspaceId: event.workspaceId,\n    type,\n    recordId: event.after.id,\n    recipientWorkspaceMemberId: recipient,\n    relevantUpdatedAt: event.after.updatedAt,\n  });\n\n  const messages: RelayMessage[] = devices.map((device) => ({\n    deviceId: device.id,\n    token: device.fcmToken,\n    data: {\n      version: \"1\",\n      type,\n      workspaceId: event.workspaceId,\n      recordId: event.after.id,\n      eventId,\n    },\n  }));\n\n  try {\n    const result = await deps.relay.dispatch({ eventId, type, messages });\n\n    for (const deviceId of result.invalidDeviceIds) {\n      await deps.repository.update(deviceId, {\n        notificationsEnabled: false,\n        disabledAt: deps.now().toISOString(),\n        lastDeliveryError: \"invalid_token\",\n      });\n    }\n\n    deps.log?.({\n      event: `${type}_push`,\n      eventId,\n      recordId: event.after.id,\n      recipientWorkspaceMemberId: recipient,\n      delivered: result.delivered,\n      invalid: result.invalidDeviceIds.length,\n      temporaryFailures: result.temporaryFailures,\n    });\n\n    return {\n      sent: true,\n      type,\n      delivered: result.delivered,\n      invalidDeviceIds: result.invalidDeviceIds,\n      temporaryFailures: result.temporaryFailures,\n    };\n  } catch (error) {\n    deps.log?.({\n      event: `${type}_push_failed`,\n      eventId,\n      reason: error instanceof Error ? error.name : \"unknown\",\n    });\n    return { sent: false, type, skipReason: \"relay_error\" };\n  }\n}\n\nfunction assigneeId(snapshot: TaskSnapshot | null | undefined): string | null {\n  return (\n    nonEmptyString(snapshot?.assigneeWorkspaceMemberId) ??\n    nonEmptyString(snapshot?.assigneeId) ??\n    nonEmptyString(snapshot?.assignee?.id) ??\n    null\n  );\n}\n\nfunction nonEmptyString(value: unknown): string | null {\n  return typeof value === \"string\" && value.trim().length > 0 ? value.trim() : null;\n}\n\nfunction normalizeDate(value: string | null | undefined): string | null {\n  return value && value.trim().length > 0 ? value.trim() : null;\n}\n\nfunction isCompletedStatus(value: string | null | undefined): boolean {\n  return value === \"DONE\" || value === \"done\" || value === \"COMPLETED\" || value === \"completed\";\n}\n\nfunction skipReasonForNoChange(event: TaskAssignedEvent): SkipReason {\n  if (event.operation === \"updated\") {\n    return \"no_assignment_change\";\n  }\n  return \"no_recipient\";\n}\n", "import { defineLogicFunction } from \"twenty-sdk/define\";\nimport type { DatabaseEventPayload } from \"twenty-sdk/logic-function\";\n\nimport { TASK_CREATED_PUSH_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER } from \"src/constants/universal-identifiers\";\nimport { taskEventFromPayload, taskTriggerDeps } from \"src/taskEventRuntime\";\nimport { handleTaskAssigned } from \"src/triggers/taskAssigned\";\n\nconst handler = async (payload: DatabaseEventPayload) => {\n  return handleTaskAssigned(taskEventFromPayload(payload, \"created\"), taskTriggerDeps());\n};\n\nexport default defineLogicFunction({\n  universalIdentifier: TASK_CREATED_PUSH_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER,\n  name: \"task-created-push\",\n  description: \"Sends a push notification when a newly created task is assigned.\",\n  timeoutSeconds: 20,\n  handler,\n  databaseEventTriggerSettings: {\n    eventName: \"task.created\",\n  },\n});\n"],
  "mappings": ";;;;AAIA,IAAM,sBAAsB,CAAC,YAAY;AAAA,EACvC,SAAS;AAAA,EACT;AAAA,EACA,QAAQ,CAAC;AACX;AAEA,IAAM,eAAe;AAAA,EACnB,IAAI,SAAS,MAAM;AACjB,QAAI,SAAS,aAAc,QAAO;AAClC,QAAI,SAAS,OAAO,YAAa,QAAO,MAAM;AAC9C,QAAI,OAAO,SAAS,SAAU,QAAO;AACrC,WAAO,IAAI,MAAM,MAAM,QAAW,YAAY;AAAA,EAChD;AAAA,EACA,QAAQ;AACN,WAAO,IAAI,MAAM,MAAM,QAAW,YAAY;AAAA,EAChD;AACF;AACA,IAAM,YAAY,IAAI,MAAM,MAAM,QAAW,YAAY;AAWlD,IAAM,sBAAsB;;;ACZ5B,IAAM,wDACX;;;ACPK,IAAM,iBAAN,cAA6B,MAAM;AAAC;AAE3C,SAAS,kBAAkB,OAA0C;AACnE,QAAM,WAAW,SAAS,IAAI,KAAK,EAAE,QAAQ,QAAQ,EAAE;AACvD,SAAO,cAAc,KAAK,OAAO,IAAI,UAAU;AACjD;AAEA,SAAS,oBAAoB,KAAiD;AAC5E,SACE,kBAAkB,IAAI,OAAO,KAC7B,kBAAkB,IAAI,cAAc,KACpC,kBAAkB,IAAI,UAAU,KAChC,kBAAkB,IAAI,iBAAiB,KACvC;AAEJ;AAEO,SAAS,cAAc,KAAoD;AAChF,QAAM,eAAe,kBAAkB,IAAI,cAAc,KAAK;AAC9D,QAAM,kBAAkB,IAAI,kBAAkB,IAAI,yBAAyB,IAAI,KAAK;AACpF,QAAM,kBAAkB,IAAI,oBAAoB,IAAI,2BAA2B,IAAI,KAAK;AACxF,QAAM,eAAe,oBAAoB,GAAG;AAE5C,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,eAAe,qCAAqC;AAAA,EAChE;AACA,MAAI,CAAC,gBAAgB;AACnB,UAAM,IAAI,eAAe,2BAA2B;AAAA,EACtD;AACA,MAAI,CAAC,gBAAgB;AACnB,UAAM,IAAI,eAAe,6BAA6B;AAAA,EACxD;AACA,SAAO,EAAE,cAAc,gBAAgB,gBAAgB,aAAa;AACtE;;;ACtCO,IAAM,sBAAN,MAAiD;AAAA,EAGtD,YACmB,OACA,UACA,MAAoB,MAAM,KAAK,IAAI,GACpD;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EALF,OAAO,oBAAI,IAAoD;AAAA,EAQhF,WAAW,KAAsB;AAC/B,UAAM,UAAU,KAAK,IAAI;AACzB,UAAM,QAAQ,KAAK,KAAK,IAAI,GAAG;AAC/B,QAAI,CAAC,SAAS,UAAU,MAAM,eAAe,KAAK,UAAU;AAC1D,WAAK,KAAK,IAAI,KAAK,EAAE,OAAO,GAAG,aAAa,QAAQ,CAAC;AACrD,aAAO;AAAA,IACT;AACA,QAAI,MAAM,SAAS,KAAK,OAAO;AAC7B,aAAO;AAAA,IACT;AACA,UAAM;AACN,WAAO;AAAA,EACT;AACF;AAEO,IAAM,sBAAsB,IAAI,oBAAoB,GAAG,GAAM;;;ACa7D,IAAM,cAAN,MAA6C;AAAA,EAClD,YACmB,QACA,YAAuB,OACvB,MAAoB,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,GACvE;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EAGnB,MAAM,SAAS,KAAqC;AAClD,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,OAAO,KAAK,UAAU;AAAA,MAC1B,SAAS;AAAA,MACT,SAAS,IAAI;AAAA,MACb,gBAAgB,KAAK,OAAO;AAAA,MAC5B;AAAA,MACA,MAAM,IAAI;AAAA,MACV,UAAU,IAAI;AAAA,IAChB,CAAC;AAED,UAAM,WAAW,MAAM,KAAK,UAAU,GAAG,KAAK,OAAO,YAAY,YAAY;AAAA,MAC3E,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB,UAAU,KAAK,OAAO,cAAc;AAAA,QACrD,8BAA8B,KAAK,OAAO;AAAA,MAC5C;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI,WAAW,uBAAuB,SAAS,MAAM,IAAI,SAAS,MAAM;AAAA,IAChF;AAEA,UAAM,SAAU,MAAM,SAAS,KAAK;AAWpC,UAAM,UAAU,OAAO,WAAW,CAAC;AACnC,WAAO;AAAA,MACL,SAAS,OAAO,YAAY;AAAA,MAC5B,SAAS,OAAO,WAAW,IAAI;AAAA,MAC/B,WAAW,QAAQ,aAAa;AAAA,MAChC,kBAAkB,MAAM,QAAQ,QAAQ,gBAAgB,IAAI,QAAQ,mBAAmB,CAAC;AAAA,MACxF,mBAAmB,QAAQ,qBAAqB;AAAA,MAChD,mBAAmB,QAAQ,qBAAqB;AAAA,IAClD;AAAA,EACF;AACF;AAEO,IAAM,aAAN,cAAyB,MAAM;AAAA,EACpC,YACE,SACS,YACT;AACA,UAAM,OAAO;AAFJ;AAAA,EAGX;AAAA,EAHW;AAIb;;;ACxGA,IAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAoCpB,IAAM,oCAAN,MAAwE;AAAA,EAC7E,YACmB,QACA,YAA0B,OAC3C;AAFiB;AACA;AAAA,EAChB;AAAA,EAFgB;AAAA,EACA;AAAA,EAGnB,MAAM,4BACJ,mBACA,gBACkC;AAClC,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAQqB,kBAAkB;AAAA;AAAA;AAAA,MAGvC,EAAE,mBAAmB,eAAe;AAAA,IACtC;AAEA,WAAO,KAAK,YAAY,MAAM,CAAC,GAAG,QAAQ;AAAA,EAC5C;AAAA,EAEA,MAAM,OAAO,OAAyD;AACpE,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,0CACoC,kBAAkB;AAAA;AAAA,MAEtD;AAAA,QACE,MAAM;AAAA,UACJ,GAAG;AAAA,UACH,qBAAqB;AAAA,UACrB,2BAA2B;AAAA,UAC3B,sBAAsB;AAAA,UACtB,uBAAuB;AAAA,UACvB,YAAY;AAAA,UACZ,mBAAmB;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,OAAO,IAAY,OAA6D;AACpF,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,mDAC6C,kBAAkB;AAAA;AAAA,MAE/D,EAAE,IAAI,MAAM,cAAc,KAAK,EAAE;AAAA,IACnC;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,mBAAmB,mBAAwD;AAC/E,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BASqB,kBAAkB;AAAA;AAAA;AAAA,MAGvC,EAAE,kBAAkB;AAAA,IACtB;AAEA,WAAO,KAAK,YAAY,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,EACvD;AAAA,EAEA,MAAM,SAAS,IAA8C;AAC3D,UAAM,OAAO,MAAM,KAAK;AAAA,MACtB;AAAA,oDAC8C,kBAAkB;AAAA;AAAA,MAEhE,EAAE,GAAG;AAAA,IACP;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,QAAW,OAAe,WAAgD;AACtF,UAAM,WAAW,MAAM,KAAK,UAAU,GAAG,KAAK,OAAO,YAAY,YAAY;AAAA,MAC3E,QAAQ;AAAA,MACR,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,iBAAiB,UAAU,KAAK,OAAO,cAAc;AAAA,MACvD;AAAA,MACA,MAAM,KAAK,UAAU,EAAE,OAAO,UAAU,CAAC;AAAA,IAC3C,CAAC;AAED,UAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,QAAI,CAAC,SAAS,MAAM,KAAK,QAAQ,QAAQ;AACvC,YAAM,UAAU,KAAK,QAAQ,IAAI,CAAC,UAAU,MAAM,OAAO,EAAE,KAAK,IAAI,KAAK,SAAS;AAClF,YAAM,IAAI,MAAM,kCAAkC,OAAO,EAAE;AAAA,IAC7D;AACA,QAAI,CAAC,KAAK,MAAM;AACd,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AACA,WAAO,KAAK;AAAA,EACd;AACF;AAEA,SAAS,cAAc,OAA6D;AAClF,QAAM,EAAE,IAAI,KAAK,WAAW,YAAY,WAAW,YAAY,GAAG,KAAK,IAAI;AAC3E,SAAO;AACT;;;AChCO,SAAS,cAA2B;AACzC,QAAM,SAAS,cAAc,QAAQ,GAAG;AACxC,SAAO;AAAA,IACL,YAAY,IAAI,kCAAkC,MAAM;AAAA,IACxD,OAAO,IAAI,YAAY,MAAM;AAAA,IAC7B,aAAa;AAAA,IACb,KAAK,MAAM,oBAAI,KAAK;AAAA,EACtB;AACF;;;AC/HO,SAAS,qBACd,SACA,WACmB;AACnB,QAAM,aAAa,QAAQ;AAI3B,QAAM,QAAQ,mBAAmB,WAAW,OAAO,QAAQ,QAAQ;AACnE,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,SAAO;AAAA,IACL;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB,wBAAwB,QAAQ,qBAAqB,QAAQ,mBAAmB;AAAA,IAChF,QAAQ,mBAAmB,WAAW,QAAQ,QAAQ,QAAQ;AAAA,IAC9D;AAAA,EACF;AACF;AAEO,SAAS,kBAAoC;AAClD,QAAM,OAAO,YAAY;AACzB,SAAO;AAAA,IACL,YAAY,KAAK;AAAA,IACjB,OAAO,KAAK;AAAA,IACZ,KAAK,KAAK;AAAA,IACV,KAAK,CAAC,WAAW,QAAQ,KAAK,KAAK,UAAU,MAAM,CAAC;AAAA,EACtD;AACF;AAEA,SAAS,mBACP,QACA,YACqB;AACrB,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,IAAI,YAAY,OAAO,EAAE,KAAK;AAAA,IAC9B,2BAA2B,YAAY,OAAO,yBAAyB;AAAA,IACvE,YAAY,YAAY,OAAO,UAAU;AAAA,IACzC,UAAU,cAAc,OAAO,QAAQ;AAAA,IACvC,OAAO,YAAY,OAAO,KAAK;AAAA,IAC/B,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,WAAW,YAAY,OAAO,SAAS,MAAK,oBAAI,KAAK,GAAE,YAAY;AAAA,EACrE;AACF;AAEA,SAAS,cAAc,OAA+C;AACpE,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,WAAO;AAAA,EACT;AACA,QAAM,KAAK,YAAa,MAAkC,EAAE;AAC5D,SAAO,KAAK,EAAE,GAAG,IAAI;AACvB;AAEA,SAAS,YAAY,OAA+B;AAClD,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,IAAI,MAAM,KAAK,IAAI;AAC/E;;;AChEA,IAAM,UAAU,IAAI,YAAY;AAEhC,SAAS,MAAM,QAA6B;AAC1C,QAAM,QAAQ,IAAI,WAAW,MAAM;AACnC,MAAI,MAAM;AACV,aAAW,KAAK,MAAO,QAAO,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC5D,SAAO;AACT;AAEA,eAAsB,UAAU,OAAgC;AAC9D,QAAM,SAAS,MAAM,OAAO,OAAO,OAAO,WAAW,QAAQ,OAAO,KAAK,CAAC;AAC1E,SAAO,MAAM,MAAM;AACrB;;;ACIA,eAAsB,qBAAqB,OAAiD;AAC1F,QAAM,OAAO;AAAA,IACX,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,EACR,EAAE,KAAK,GAAG;AACV,SAAO,UAAU,IAAI;AACvB;AAEA,eAAsB,eACpB,eACA,UACiB;AACjB,MAAI,iBAAiB,cAAc,SAAS,GAAG;AAC7C,WAAO;AAAA,EACT;AACA,SAAO,qBAAqB,QAAQ;AACtC;;;ACiCA,eAAsB,mBACpB,OACA,MACyB;AACzB,SAAO,mBAAmB,OAAO,MAAM,mBAAmB,KAAK,CAAC;AAClE;AAmCA,eAAe,mBACb,OACA,MACA,UACyB;AACzB,MAAI,CAAC,UAAU;AACb,WAAO,EAAE,MAAM,OAAO,YAAY,sBAAsB,KAAK,EAAE;AAAA,EACjE;AACA,MAAI,CAAC,SAAS,WAAW;AACvB,WAAO,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,YAAY,SAAS,gBAAgB;AAAA,EAClF;AACA,MAAI,MAAM,0BAA0B,MAAM,2BAA2B,SAAS,WAAW;AACvF,WAAO,EAAE,MAAM,OAAO,MAAM,SAAS,MAAM,YAAY,kBAAkB;AAAA,EAC3E;AAEA,QAAM,WAAW,MAAM,KAAK,WAAW,mBAAmB,SAAS,SAAS,GAAG;AAAA,IAC7E,CAAC,WACC,OAAO,SAAS,aAAa,KAC7B,OAAO,wBACP,CAAC,OAAO;AAAA,EACZ;AACA,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM,SAAS;AAAA,MACf,YAAY;AAAA,IACd;AAAA,EACF;AAEA,SAAO,SAAS,OAAO,MAAM,SAAS,MAAM,SAAS,WAAW,OAAO;AACzE;AAEA,SAAS,mBAAmB,OAAmD;AAC7E,QAAM,YAAY,WAAW,MAAM,KAAK;AACxC,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX,eAAe;AAAA,MACf,iBAAiB;AAAA,IACnB;AAAA,EACF;AAEA,MAAI,MAAM,cAAc,aAAa,WAAW,MAAM,MAAM,MAAM,WAAW;AAC3E,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,eAAe;AAAA,IACf,iBAAiB;AAAA,EACnB;AACF;AAgDA,eAAe,SACb,OACA,MACA,MACA,WACA,SACyB;AACzB,QAAM,UAAU,MAAM,eAAe,MAAM,eAAe;AAAA,IACxD,aAAa,MAAM;AAAA,IACnB;AAAA,IACA,UAAU,MAAM,MAAM;AAAA,IACtB,4BAA4B;AAAA,IAC5B,mBAAmB,MAAM,MAAM;AAAA,EACjC,CAAC;AAED,QAAM,WAA2B,QAAQ,IAAI,CAAC,YAAY;AAAA,IACxD,UAAU,OAAO;AAAA,IACjB,OAAO,OAAO;AAAA,IACd,MAAM;AAAA,MACJ,SAAS;AAAA,MACT;AAAA,MACA,aAAa,MAAM;AAAA,MACnB,UAAU,MAAM,MAAM;AAAA,MACtB;AAAA,IACF;AAAA,EACF,EAAE;AAEF,MAAI;AACF,UAAM,SAAS,MAAM,KAAK,MAAM,SAAS,EAAE,SAAS,MAAM,SAAS,CAAC;AAEpE,eAAW,YAAY,OAAO,kBAAkB;AAC9C,YAAM,KAAK,WAAW,OAAO,UAAU;AAAA,QACrC,sBAAsB;AAAA,QACtB,YAAY,KAAK,IAAI,EAAE,YAAY;AAAA,QACnC,mBAAmB;AAAA,MACrB,CAAC;AAAA,IACH;AAEA,SAAK,MAAM;AAAA,MACT,OAAO,GAAG,IAAI;AAAA,MACd;AAAA,MACA,UAAU,MAAM,MAAM;AAAA,MACtB,4BAA4B;AAAA,MAC5B,WAAW,OAAO;AAAA,MAClB,SAAS,OAAO,iBAAiB;AAAA,MACjC,mBAAmB,OAAO;AAAA,IAC5B,CAAC;AAED,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,WAAW,OAAO;AAAA,MAClB,kBAAkB,OAAO;AAAA,MACzB,mBAAmB,OAAO;AAAA,IAC5B;AAAA,EACF,SAAS,OAAO;AACd,SAAK,MAAM;AAAA,MACT,OAAO,GAAG,IAAI;AAAA,MACd;AAAA,MACA,QAAQ,iBAAiB,QAAQ,MAAM,OAAO;AAAA,IAChD,CAAC;AACD,WAAO,EAAE,MAAM,OAAO,MAAM,YAAY,cAAc;AAAA,EACxD;AACF;AAEA,SAAS,WAAW,UAA0D;AAC5E,SACE,eAAe,UAAU,yBAAyB,KAClD,eAAe,UAAU,UAAU,KACnC,eAAe,UAAU,UAAU,EAAE,KACrC;AAEJ;AAEA,SAAS,eAAe,OAA+B;AACrD,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS,IAAI,MAAM,KAAK,IAAI;AAC/E;AAUA,SAAS,sBAAsB,OAAsC;AACnE,MAAI,MAAM,cAAc,WAAW;AACjC,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ACvSA,IAAM,UAAU,OAAO,YAAkC;AACvD,SAAO,mBAAmB,qBAAqB,SAAS,SAAS,GAAG,gBAAgB,CAAC;AACvF;AAEA,IAAO,sCAAQ,oBAAoB;AAAA,EACjC,qBAAqB;AAAA,EACrB,MAAM;AAAA,EACN,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB;AAAA,EACA,8BAA8B;AAAA,IAC5B,WAAW;AAAA,EACb;AACF,CAAC;",
  "names": []
}
