@lootlog/sdk 0.1.1 → 0.3.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/dist/activity.d.ts +8 -2
- package/dist/activity.d.ts.map +1 -1
- package/dist/activity.js +2 -2
- package/dist/activity.js.map +1 -1
- package/dist/battlelog.d.ts +280 -5
- package/dist/battlelog.d.ts.map +1 -1
- package/dist/battlelog.js +11 -6
- package/dist/battlelog.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/main.d.ts +1457 -918
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +400 -284
- package/dist/main.js.map +1 -1
- package/dist/{mutators-Da_vMUva.d.ts → mutators-BaZDDfwh.d.ts} +2 -2
- package/dist/{mutators-Da_vMUva.d.ts.map → mutators-BaZDDfwh.d.ts.map} +1 -1
- package/dist/{mutators-CaBTxpi-.js → mutators-Dj5qBH3y.js} +2 -2
- package/dist/{mutators-CaBTxpi-.js.map → mutators-Dj5qBH3y.js.map} +1 -1
- package/dist/realtime.d.ts +430 -21
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +799 -587
- package/dist/realtime.js.map +1 -1
- package/dist/search.d.ts +247 -5
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +115 -2
- package/dist/search.js.map +1 -1
- package/dist/{transport-CIfewyM7.js → transport-Cn1V6y-o.js} +46 -8
- package/dist/transport-Cn1V6y-o.js.map +1 -0
- package/dist/{transport-BHbtsYo_.d.ts → transport-CoTymLxF.d.ts} +3 -1
- package/dist/transport-CoTymLxF.d.ts.map +1 -0
- package/openapi/activity.json +15 -1
- package/openapi/battlelog.json +807 -40
- package/openapi/main.json +5752 -4060
- package/openapi/search.json +721 -53
- package/package.json +5 -6
- package/dist/transport-BHbtsYo_.d.ts.map +0 -1
- package/dist/transport-CIfewyM7.js.map +0 -1
package/dist/realtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"realtime.js","names":["Schema","NonEmptyString","TaggedErrorClass"],"sources":["../../schema/src/npc-type.ts","../../schema/src/permissions.ts","../../protocol/src/realtime/access-policy.ts","../../schema/src/item-rarity.ts","../../schema/src/loot.ts","../../schema/src/http-scalars.ts","../../protocol/src/loot-summary.ts","../../protocol/src/feed.ts","../../schema/src/primitives.ts","../../schema/src/air-tag.ts","../../schema/src/map-ping.ts","../../schema/src/discord.ts","../../protocol/src/rabbit/topology.ts","../../protocol/src/rabbit/events.ts","../../protocol/src/realtime/protocol.ts","../../protocol/src/realtime/codec.ts","../../client/src/realtime/realtime-client.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nexport const NpcTypeEnum = {\n COMMON: \"COMMON\",\n ELITE: \"ELITE\",\n ELITE2: \"ELITE2\",\n ELITE3: \"ELITE3\",\n HERO: \"HERO\",\n EVENT_HERO: \"EVENT_HERO\",\n COLOSSUS: \"COLOSSUS\",\n TITAN: \"TITAN\",\n NPC: \"NPC\",\n} as const;\n\nexport type NpcTypeEnum = (typeof NpcTypeEnum)[keyof typeof NpcTypeEnum];\n\nexport const NpcTypeSchema = Schema.Literals([\n NpcTypeEnum.COMMON,\n NpcTypeEnum.ELITE,\n NpcTypeEnum.ELITE2,\n NpcTypeEnum.ELITE3,\n NpcTypeEnum.HERO,\n NpcTypeEnum.EVENT_HERO,\n NpcTypeEnum.COLOSSUS,\n NpcTypeEnum.TITAN,\n NpcTypeEnum.NPC,\n]);\n","import { Schema } from \"effect\";\n\nexport const Capability = {\n OWNER: \"OWNER\",\n ADMIN: \"ADMIN\",\n LOOTLOG_MANAGE: \"LOOTLOG_MANAGE\",\n LOOTLOG_ACCESS: \"LOOTLOG_ACCESS\",\n LOOTLOG_LOOTS_READ: \"LOOTLOG_LOOTS_READ\",\n LOOTLOG_LOOTS_WRITE: \"LOOTLOG_LOOTS_WRITE\",\n LOOTLOG_LOOTS_ARCHIVE: \"LOOTLOG_LOOTS_ARCHIVE\",\n LOOTLOG_LOOTS_TITANS_READ: \"LOOTLOG_LOOTS_TITANS_READ\",\n LOOTLOG_LOOTS_HEROES_READ: \"LOOTLOG_LOOTS_HEROES_READ\",\n LOOTLOG_TIMERS_READ: \"LOOTLOG_TIMERS_READ\",\n LOOTLOG_TIMERS_WRITE: \"LOOTLOG_TIMERS_WRITE\",\n LOOTLOG_TIMERS_RESET: \"LOOTLOG_TIMERS_RESET\",\n LOOTLOG_TIMERS_DELETE: \"LOOTLOG_TIMERS_DELETE\",\n LOOTLOG_TIMERS_TITANS_READ: \"LOOTLOG_TIMERS_TITANS_READ\",\n LOOTLOG_TIMERS_HEROES_READ: \"LOOTLOG_TIMERS_HEROES_READ\",\n LOOTLOG_RESERVATIONS_READ: \"LOOTLOG_RESERVATIONS_READ\",\n LOOTLOG_RESERVATIONS_WRITE: \"LOOTLOG_RESERVATIONS_WRITE\",\n LOOTLOG_MEMBERS_READ: \"LOOTLOG_MEMBERS_READ\",\n LOOTLOG_ONLINE_PLAYERS_READ: \"LOOTLOG_ONLINE_PLAYERS_READ\",\n LOOTLOG_PRESENCE_LOCATION_READ: \"LOOTLOG_PRESENCE_LOCATION_READ\",\n LOOTLOG_CHAT_READ: \"LOOTLOG_CHAT_READ\",\n LOOTLOG_CHAT_WRITE: \"LOOTLOG_CHAT_WRITE\",\n LOOTLOG_CHAT_TITANS_READ: \"LOOTLOG_CHAT_TITANS_READ\",\n LOOTLOG_CHAT_HEROES_READ: \"LOOTLOG_CHAT_HEROES_READ\",\n LOOTLOG_NOTIFICATIONS_READ: \"LOOTLOG_NOTIFICATIONS_READ\",\n LOOTLOG_NOTIFICATIONS_SEND: \"LOOTLOG_NOTIFICATIONS_SEND\",\n LOOTLOG_NOTIFICATIONS_TITANS_READ: \"LOOTLOG_NOTIFICATIONS_TITANS_READ\",\n LOOTLOG_NOTIFICATIONS_HEROES_READ: \"LOOTLOG_NOTIFICATIONS_HEROES_READ\",\n LOOTLOG_EVENTS_MANAGE: \"LOOTLOG_EVENTS_MANAGE\",\n LOOTLOG_EVENTS_READ: \"LOOTLOG_EVENTS_READ\",\n LOOTLOG_EVENTS_WRITE: \"LOOTLOG_EVENTS_WRITE\",\n LOOTLOG_DOCS_READ: \"LOOTLOG_DOCS_READ\",\n LOOTLOG_DOCS_WRITE: \"LOOTLOG_DOCS_WRITE\",\n} as const;\n\nexport type Capability = (typeof Capability)[keyof typeof Capability];\n\nexport const Permission = Capability;\n\nexport type Permission = Capability;\n\nexport interface UserGuildPermissionsRole {\n id: string;\n lvlRangeFrom: number;\n lvlRangeTo: number;\n permissions: Permission[];\n}\n\nexport interface UserGuildPermissionsGuild {\n id: string;\n ownerId: string;\n}\n\nexport interface UserGuildPermissionsDto {\n guild: UserGuildPermissionsGuild;\n roles: UserGuildPermissionsRole[];\n}\n\nexport const CapabilitySchema = Schema.Literals(Object.values(Capability));\n\nexport const PermissionSchema = CapabilitySchema;\n\nexport const UserGuildPermissionsRoleSchema = Schema.Struct({\n id: Schema.NonEmptyString,\n lvlRangeFrom: Schema.Int,\n lvlRangeTo: Schema.Int,\n permissions: Schema.Array(PermissionSchema),\n});\n\nexport const UserGuildPermissionsGuildSchema = Schema.Struct({\n id: Schema.NonEmptyString,\n ownerId: Schema.NonEmptyString,\n});\n\nexport const UserGuildPermissionsDtoSchema = Schema.Struct({\n guild: UserGuildPermissionsGuildSchema,\n roles: Schema.Array(UserGuildPermissionsRoleSchema),\n});\n","import { NpcTypeEnum } from \"@lootlog/schema/npc-type\";\nimport { Permission, PermissionSchema } from \"@lootlog/schema/permissions\";\nimport { Schema } from \"effect\";\n\nconst LevelRange = Schema.Struct({ from: Schema.Int, to: Schema.Int });\n\nconst AREAS = [\n \"timers\",\n \"chat\",\n \"notifications\",\n \"presence\",\n \"reservations\",\n \"loots\",\n \"events\",\n \"organization\",\n] as const;\n\nexport const AccessPolicyArea = Schema.Literals(AREAS);\n\nexport type AccessPolicyArea = typeof AccessPolicyArea.Type;\n\nexport const OrganizationAccessPolicy = Schema.Struct({\n organizationId: Schema.NonEmptyString,\n owner: Schema.Boolean,\n permissions: Schema.Array(PermissionSchema),\n grants: Schema.Array(\n Schema.Struct({\n permission: PermissionSchema,\n ranges: Schema.Array(LevelRange),\n }),\n ),\n});\n\nexport type OrganizationAccessPolicy = typeof OrganizationAccessPolicy.Type;\n\nexport const AccessPolicySnapshot = Schema.Struct({\n version: Schema.NonEmptyString,\n organizations: Schema.Array(OrganizationAccessPolicy),\n});\n\nexport type AccessPolicySnapshot = typeof AccessPolicySnapshot.Type;\n\nexport const isAccessPolicySnapshot = Schema.is(AccessPolicySnapshot);\n\nexport const AccessPolicyChange = Schema.Struct({\n organizationId: Schema.NonEmptyString,\n areas: Schema.Array(AccessPolicyArea),\n restricted: Schema.Boolean,\n expanded: Schema.Boolean,\n});\n\nexport type AccessPolicyChange = typeof AccessPolicyChange.Type;\n\ntype Range = typeof LevelRange.Type;\n\ntype GuildPolicy = {\n readonly guild: { readonly id: string; readonly ownerId: string };\n readonly roles: readonly {\n readonly permissions: readonly Permission[];\n readonly lvlRangeFrom: number;\n readonly lvlRangeTo: number;\n }[];\n};\n\nconst NPC_PERMISSIONS = {\n timers: [\n Permission.LOOTLOG_TIMERS_READ,\n Permission.LOOTLOG_TIMERS_HEROES_READ,\n Permission.LOOTLOG_TIMERS_TITANS_READ,\n ],\n chat: [\n Permission.LOOTLOG_CHAT_READ,\n Permission.LOOTLOG_CHAT_HEROES_READ,\n Permission.LOOTLOG_CHAT_TITANS_READ,\n ],\n notifications: [\n Permission.LOOTLOG_NOTIFICATIONS_READ,\n Permission.LOOTLOG_NOTIFICATIONS_HEROES_READ,\n Permission.LOOTLOG_NOTIFICATIONS_TITANS_READ,\n ],\n loots: [\n Permission.LOOTLOG_LOOTS_READ,\n Permission.LOOTLOG_LOOTS_HEROES_READ,\n Permission.LOOTLOG_LOOTS_TITANS_READ,\n ],\n} as const;\n\nconst RANGE_PERMISSIONS = Object.values(NPC_PERMISSIONS).flat();\n\nconst LOOT_RANGE_PERMISSIONS = new Set<Permission>(NPC_PERMISSIONS.loots);\n\nconst ALL_PERMISSIONS = Object.values(Permission).sort();\n\nconst NPC_TYPES = new Set<string>(Object.values(NpcTypeEnum));\n\nconst mergeRanges = (ranges: Range[]): Range[] => {\n const merged: Array<{ from: number; to: number }> = [];\n\n for (const range of ranges.sort((a, b) => a.from - b.from || a.to - b.to)) {\n if (range.from > range.to) continue;\n const last = merged[merged.length - 1];\n\n // NPC event levels accept finite numbers, so integer-adjacent ranges retain a fractional gap.\n if (last && range.from <= last.to) last.to = Math.max(last.to, range.to);\n else merged.push({ ...range });\n }\n\n return merged;\n};\n\n/** Canonical effective grants: role identifiers, role ordering, and overlapping grants do not change the version. */\nexport const createAccessPolicySnapshot = (\n guilds: readonly GuildPolicy[],\n discordId: string,\n): AccessPolicySnapshot => {\n const organizations = guilds\n .map(({ guild, roles }): OrganizationAccessPolicy => {\n const owner = guild.ownerId === discordId;\n const explicit = new Set(roles.flatMap((role) => role.permissions));\n const administrator = owner || explicit.has(Permission.ADMIN);\n\n const permissions = administrator\n ? ALL_PERMISSIONS.filter(\n (permission) => owner || permission !== Permission.OWNER,\n )\n : [...explicit].sort();\n\n const grants = RANGE_PERMISSIONS.map((permission) => {\n const bypass =\n owner || (administrator && !LOOT_RANGE_PERMISSIONS.has(permission));\n\n const ranges = bypass\n ? [{ from: 0, to: Number.MAX_SAFE_INTEGER }]\n : mergeRanges(\n roles\n .filter(\n (role) =>\n role.permissions.includes(permission) &&\n (!LOOT_RANGE_PERMISSIONS.has(permission) ||\n role.permissions.includes(Permission.LOOTLOG_LOOTS_READ)),\n )\n .map((role) => ({\n from: role.lvlRangeFrom,\n to: role.lvlRangeTo,\n })),\n );\n\n return { permission, ranges };\n })\n .filter(({ ranges }) => ranges.length > 0)\n .sort((a, b) => a.permission.localeCompare(b.permission));\n\n return { organizationId: guild.id, owner, permissions, grants };\n })\n .sort((a, b) => a.organizationId.localeCompare(b.organizationId));\n\n return { version: JSON.stringify(organizations), organizations };\n};\n\nconst permissionArea = (permission: Permission): AccessPolicyArea => {\n if (permission.startsWith(\"LOOTLOG_TIMERS_\")) return \"timers\";\n\n if (permission.startsWith(\"LOOTLOG_CHAT_\")) return \"chat\";\n\n if (permission.startsWith(\"LOOTLOG_NOTIFICATIONS_\")) return \"notifications\";\n\n if (permission.startsWith(\"LOOTLOG_LOOTS_\")) return \"loots\";\n\n if (permission.startsWith(\"LOOTLOG_RESERVATIONS_\")) return \"reservations\";\n\n if (permission.startsWith(\"LOOTLOG_EVENTS_\")) return \"events\";\n\n if (\n permission === Permission.LOOTLOG_ONLINE_PLAYERS_READ ||\n permission === Permission.LOOTLOG_PRESENCE_LOCATION_READ\n )\n return \"presence\";\n\n return \"organization\";\n};\n\nconst includesArea = (\n target: OrganizationAccessPolicy,\n source: OrganizationAccessPolicy,\n area: AccessPolicyArea,\n): boolean =>\n source.permissions\n .filter((permission) => permissionArea(permission) === area)\n .every((permission) => target.permissions.includes(permission)) &&\n source.grants\n .filter(({ permission }) => permissionArea(permission) === area)\n .every(({ permission, ranges }) => {\n const targetRanges =\n target.grants.find((grant) => grant.permission === permission)\n ?.ranges ?? [];\n\n return ranges.every((range) =>\n targetRanges.some(\n (candidate) =>\n candidate.from <= range.from && candidate.to >= range.to,\n ),\n );\n });\n\n/** Compare the local snapshot, including after reconnect; the event's delta may refer to a newer server baseline. */\nexport const diffAccessPolicies = (\n previous: AccessPolicySnapshot,\n next: AccessPolicySnapshot,\n): AccessPolicyChange[] => {\n if (previous.version === next.version) return [];\n\n const before = new Map(\n previous.organizations.map((organization) => [\n organization.organizationId,\n organization,\n ]),\n );\n\n const after = new Map(\n next.organizations.map((organization) => [\n organization.organizationId,\n organization,\n ]),\n );\n\n const changes: AccessPolicyChange[] = [];\n\n for (const organizationId of new Set([...before.keys(), ...after.keys()])) {\n const oldPolicy = before.get(organizationId);\n const newPolicy = after.get(organizationId);\n\n if (!oldPolicy || !newPolicy) {\n changes.push({\n organizationId,\n areas: [...AREAS],\n restricted: !newPolicy,\n expanded: !oldPolicy,\n });\n continue;\n }\n\n for (const area of AREAS) {\n const restricted = !includesArea(newPolicy, oldPolicy, area);\n const expanded = !includesArea(oldPolicy, newPolicy, area);\n\n if (restricted || expanded)\n changes.push({ organizationId, areas: [area], restricted, expanded });\n }\n }\n\n return changes;\n};\n\nexport const canReadPolicyNpc = (\n organization: OrganizationAccessPolicy,\n area: \"timers\" | \"chat\" | \"notifications\",\n npc: { readonly type: string; readonly lvl: number } | null,\n): boolean => {\n if (area === \"timers\" && npc === null) return false;\n\n if (\n npc &&\n (!Number.isFinite(npc.lvl) || npc.lvl < 0 || !NPC_TYPES.has(npc.type))\n )\n return false;\n\n if (organization.owner || organization.permissions.includes(Permission.ADMIN))\n return true;\n const [base, heroes, titans] = NPC_PERMISSIONS[area];\n\n if (!organization.permissions.includes(base)) return false;\n\n if (npc === null) return true;\n let permission: Permission = base;\n\n if (npc.type === \"TITAN\") permission = titans;\n\n if (npc.type === \"HERO\" || npc.type === \"EVENT_HERO\") permission = heroes;\n\n return (\n organization.grants\n .find((grant) => grant.permission === permission)\n ?.ranges.some(({ from, to }) => from <= npc.lvl && to >= npc.lvl) ?? false\n );\n};\n","import { Schema } from \"effect\";\n\nexport const ItemRarityEnum = {\n UNIQUE: \"UNIQUE\",\n HEROIC: \"HEROIC\",\n LEGENDARY: \"LEGENDARY\",\n UPGRADED: \"UPGRADED\",\n} as const;\n\nexport type ItemRarityEnum =\n (typeof ItemRarityEnum)[keyof typeof ItemRarityEnum];\n\nexport const ItemRaritySchema = Schema.Literals([\n ItemRarityEnum.UNIQUE,\n ItemRarityEnum.HEROIC,\n ItemRarityEnum.LEGENDARY,\n ItemRarityEnum.UPGRADED,\n]);\n","import { Schema } from \"effect\";\n\nexport const LootSourceEnum = {\n LOOTBOX: \"LOOTBOX\",\n DIALOG: \"DIALOG\",\n FIGHT: \"FIGHT\",\n} as const;\n\nexport type LootSourceEnum =\n (typeof LootSourceEnum)[keyof typeof LootSourceEnum];\n\nexport const LootSourceSchema = Schema.Literals([\n LootSourceEnum.LOOTBOX,\n LootSourceEnum.DIALOG,\n LootSourceEnum.FIGHT,\n]);\n\nexport const LootShareSourceEnum = {\n NONE: \"NONE\",\n ITEM_OWNER: \"ITEM_OWNER\",\n CHAT_MESSAGE: \"CHAT_MESSAGE\",\n} as const;\n\nexport type LootShareSourceEnum =\n (typeof LootShareSourceEnum)[keyof typeof LootShareSourceEnum];\n\nexport const LootShareSourceSchema = Schema.Literals([\n LootShareSourceEnum.NONE,\n LootShareSourceEnum.ITEM_OWNER,\n LootShareSourceEnum.CHAT_MESSAGE,\n]);\n\nexport const ProfessionEnum = {\n WARRIOR: \"WARRIOR\",\n PALADIN: \"PALADIN\",\n HUNTER: \"HUNTER\",\n MAGE: \"MAGE\",\n BLADE_DANCER: \"BLADE_DANCER\",\n TRACKER: \"TRACKER\",\n} as const;\n\nexport type ProfessionEnum =\n (typeof ProfessionEnum)[keyof typeof ProfessionEnum];\n\nexport const ProfessionSchema = Schema.Literals([\n ProfessionEnum.WARRIOR,\n ProfessionEnum.PALADIN,\n ProfessionEnum.HUNTER,\n ProfessionEnum.MAGE,\n ProfessionEnum.BLADE_DANCER,\n ProfessionEnum.TRACKER,\n]);\n\nexport const ItemTypeEnum = {\n ONE_HAND_WEAPON: \"ONE_HAND_WEAPON\",\n TWO_HAND_WEAPON: \"TWO_HAND_WEAPON\",\n ONE_AND_HALF_HAND_WEAPON: \"ONE_AND_HALF_HAND_WEAPON\",\n DISTANCE_WEAPON: \"DISTANCE_WEAPON\",\n HELP_WEAPON: \"HELP_WEAPON\",\n WAND_WEAPON: \"WAND_WEAPON\",\n ORB_WEAPON: \"ORB_WEAPON\",\n ARMOR: \"ARMOR\",\n HELMET: \"HELMET\",\n BOOTS: \"BOOTS\",\n GLOVES: \"GLOVES\",\n RING: \"RING\",\n NECKLACE: \"NECKLACE\",\n SHIELD: \"SHIELD\",\n NEUTRAL: \"NEUTRAL\",\n CONSUME: \"CONSUME\",\n GOLD: \"GOLD\",\n KEYS: \"KEYS\",\n QUEST: \"QUEST\",\n RENEWABLE: \"RENEWABLE\",\n ARROWS: \"ARROWS\",\n TALISMAN: \"TALISMAN\",\n BOOK: \"BOOK\",\n BAG: \"BAG\",\n BLESS: \"BLESS\",\n UPGRADE: \"UPGRADE\",\n RECIPE: \"RECIPE\",\n COINAGE: \"COINAGE\",\n QUIVER: \"QUIVER\",\n OUTFITS: \"OUTFITS\",\n PETS: \"PETS\",\n TELEPORTS: \"TELEPORTS\",\n} as const;\n\nexport type ItemTypeEnum = (typeof ItemTypeEnum)[keyof typeof ItemTypeEnum];\n\nexport const ItemTypeSchema = Schema.Literals([\n ItemTypeEnum.ONE_HAND_WEAPON,\n ItemTypeEnum.TWO_HAND_WEAPON,\n ItemTypeEnum.ONE_AND_HALF_HAND_WEAPON,\n ItemTypeEnum.DISTANCE_WEAPON,\n ItemTypeEnum.HELP_WEAPON,\n ItemTypeEnum.WAND_WEAPON,\n ItemTypeEnum.ORB_WEAPON,\n ItemTypeEnum.ARMOR,\n ItemTypeEnum.HELMET,\n ItemTypeEnum.BOOTS,\n ItemTypeEnum.GLOVES,\n ItemTypeEnum.RING,\n ItemTypeEnum.NECKLACE,\n ItemTypeEnum.SHIELD,\n ItemTypeEnum.NEUTRAL,\n ItemTypeEnum.CONSUME,\n ItemTypeEnum.GOLD,\n ItemTypeEnum.KEYS,\n ItemTypeEnum.QUEST,\n ItemTypeEnum.RENEWABLE,\n ItemTypeEnum.ARROWS,\n ItemTypeEnum.TALISMAN,\n ItemTypeEnum.BOOK,\n ItemTypeEnum.BAG,\n ItemTypeEnum.BLESS,\n ItemTypeEnum.UPGRADE,\n ItemTypeEnum.RECIPE,\n ItemTypeEnum.COINAGE,\n ItemTypeEnum.QUIVER,\n ItemTypeEnum.OUTFITS,\n ItemTypeEnum.PETS,\n ItemTypeEnum.TELEPORTS,\n]);\n","import * as Schema from \"effect/Schema\";\n\nexport const FiniteNumber = Schema.Number.check(\n Schema.isFinite().annotate({ expected: \"a finite number\" }),\n);\n\nconst dateTimeString = (pattern: string) =>\n Schema.String.annotate({ format: \"date-time\" }).check(\n Schema.isPattern(new RegExp(pattern)).annotate({\n expected: `a string matching the RegExp ${pattern}`,\n }),\n );\n\nexport const DateTimeString = dateTimeString(\n \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z))$\",\n);\n\nexport const DateTimeWithOffsetString = dateTimeString(\n \"^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:Z|([+-](?:[01]\\\\d|2[0-3]):[0-5]\\\\d)))$\",\n);\n\nexport const NonEmptyString = Schema.String.check(\n Schema.isMinLength(1).annotate({\n expected: \"a value with a length of at least 1\",\n }),\n);\n\nexport const JsonValue = Schema.Json.annotate({ expected: \"JSON value\" });\n\nexport const SafeInteger = Schema.Number.check(\n Schema.isInt().annotate({ expected: \"an integer\" }),\n)\n .check(\n Schema.isGreaterThanOrEqualTo(-9007199254740991).annotate({\n expected: \"a value greater than or equal to -9007199254740991\",\n }),\n )\n .check(\n Schema.isLessThanOrEqualTo(9007199254740991).annotate({\n expected: \"a value less than or equal to 9007199254740991\",\n }),\n );\n\nexport const PositiveSafeInteger = Schema.Number.check(\n Schema.isInt().annotate({ expected: \"an integer\" }),\n)\n .check(\n Schema.isGreaterThanOrEqualTo(1).annotate({\n expected: \"a value greater than or equal to 1\",\n }),\n )\n .check(\n Schema.isLessThanOrEqualTo(9007199254740991).annotate({\n expected: \"a value less than or equal to 9007199254740991\",\n }),\n );\n\nexport const NonNegativeSafeInteger = Schema.Number.check(\n Schema.isInt().annotate({ expected: \"an integer\" }),\n)\n .check(\n Schema.isGreaterThanOrEqualTo(0).annotate({\n expected: \"a value greater than or equal to 0\",\n }),\n )\n .check(\n Schema.isLessThanOrEqualTo(9007199254740991).annotate({\n expected: \"a value less than or equal to 9007199254740991\",\n }),\n );\n\nexport const LevelFilter = Schema.Number.check(\n Schema.isInt().annotate({ expected: \"an integer\" }),\n)\n .check(\n Schema.isGreaterThanOrEqualTo(0).annotate({\n expected: \"a value greater than or equal to 0\",\n }),\n )\n .check(\n Schema.isLessThanOrEqualTo(500).annotate({\n expected: \"a value less than or equal to 500\",\n }),\n );\n\nexport const PageSize = Schema.Number.check(\n Schema.isInt().annotate({ expected: \"an integer\" }),\n)\n .check(\n Schema.isGreaterThanOrEqualTo(1).annotate({\n expected: \"a value greater than or equal to 1\",\n }),\n )\n .check(\n Schema.isLessThanOrEqualTo(100).annotate({\n expected: \"a value less than or equal to 100\",\n }),\n );\n","import { ItemRaritySchema } from \"@lootlog/schema/item-rarity\";\nimport { ProfessionSchema } from \"@lootlog/schema/loot\";\nimport { NpcTypeSchema } from \"@lootlog/schema/npc-type\";\nimport { Schema } from \"effect\";\nimport { FiniteNumber } from \"@lootlog/schema/http-scalars\";\n\nexport const LootItemResponse = Schema.Struct({\n id: FiniteNumber,\n hid: Schema.String,\n name: Schema.String,\n icon: Schema.String,\n stat: Schema.String,\n type: Schema.NullOr(Schema.String),\n rarity: Schema.NullOr(ItemRaritySchema),\n lvl: FiniteNumber,\n prof: Schema.Array(ProfessionSchema),\n});\n\nexport const LootPlayerResponse = Schema.Struct({\n id: Schema.Union([Schema.String, FiniteNumber]),\n name: Schema.String,\n lvl: Schema.NullOr(FiniteNumber),\n prof: Schema.NullOr(ProfessionSchema),\n icon: Schema.NullOr(Schema.String),\n characterId: Schema.NullOr(FiniteNumber),\n accountId: Schema.NullOr(FiniteNumber),\n hpp: Schema.NullOr(FiniteNumber),\n});\n\nexport const LootNpcResponse = Schema.Struct({\n id: FiniteNumber,\n name: Schema.String,\n wt: Schema.NullOr(FiniteNumber),\n lvl: Schema.NullOr(FiniteNumber),\n prof: Schema.NullOr(ProfessionSchema),\n icon: Schema.NullOr(Schema.String),\n type: Schema.NullOr(NpcTypeSchema),\n margonemType: Schema.NullOr(FiniteNumber),\n});\n\nexport const LootShareResponse = Schema.Record(\n Schema.String,\n Schema.Array(Schema.String),\n);\n\nexport const LootSummary = Schema.Struct({\n items: Schema.Array(LootItemResponse),\n players: Schema.Array(LootPlayerResponse),\n npcs: Schema.Array(LootNpcResponse),\n lootShare: LootShareResponse,\n location: Schema.String,\n});\n\nexport type LootSummary = typeof LootSummary.Type;\n","import { LootSummary } from \"./loot-summary.js\";\nimport {\n FiniteNumber,\n PositiveSafeInteger,\n} from \"@lootlog/schema/http-scalars\";\nimport { Schema } from \"effect\";\n\nconst FeedNpc = Schema.Struct({\n id: FiniteNumber,\n name: Schema.String,\n type: Schema.NullOr(Schema.String),\n lvl: Schema.NullOr(FiniteNumber),\n icon: Schema.NullOr(Schema.String),\n prof: Schema.optionalKey(Schema.NullOr(Schema.String)),\n});\n\nconst common = {\n id: Schema.String,\n version: PositiveSafeInteger,\n groupKey: Schema.optionalKey(Schema.String),\n occurredAt: Schema.String,\n world: Schema.String,\n guild: Schema.Struct({\n id: Schema.String,\n name: Schema.String,\n vanityUrl: Schema.NullOr(Schema.String),\n }),\n npc: Schema.NullOr(FeedNpc),\n};\n\nexport const UserFeedItem = Schema.Union([\n Schema.Struct({\n ...common,\n type: Schema.Literal(\"kill\"),\n npc: FeedNpc,\n count: PositiveSafeInteger,\n }),\n Schema.Struct({\n ...common,\n type: Schema.Literal(\"loot\"),\n lootId: PositiveSafeInteger,\n summary: Schema.optionalKey(LootSummary),\n additionalItemsCount: FiniteNumber,\n items: Schema.Array(\n Schema.Struct({\n id: FiniteNumber,\n name: Schema.String,\n icon: Schema.String,\n rarity: Schema.NullOr(Schema.String),\n stat: Schema.optionalKey(Schema.String),\n type: Schema.optionalKey(Schema.NullOr(Schema.String)),\n lvl: Schema.optionalKey(Schema.NullOr(FiniteNumber)),\n }),\n ),\n }),\n]);\n\nexport type UserFeedItem = typeof UserFeedItem.Type;\n","import { Schema, SchemaTransformation } from \"effect\";\n\nexport const NonEmptyString = Schema.NonEmptyString;\n\nexport const NonNegativeInt = Schema.Int.check(\n Schema.isGreaterThanOrEqualTo(0),\n);\n\nconst isoDateTimePattern =\n /^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/;\n\n/** A JavaScript Date encoded as the existing HTTP ISO-8601 string format. */\nexport const IsoDateTime = Schema.String.annotate({\n format: \"date-time\",\n}).pipe(\n Schema.check(Schema.isPattern(isoDateTimePattern)),\n Schema.decodeTo(Schema.Date, SchemaTransformation.dateFromString),\n);\n\nexport type IsoDateTime = typeof IsoDateTime.Type;\n\nexport type EncodedIsoDateTime = typeof IsoDateTime.Encoded;\n","import { Schema } from \"effect\";\n\nexport const AIR_TAG_RELATIONS = [1, 2, 3, 4, 5, 6, 7, 8] as const;\n\nexport const AIR_TAG_ENEMY_RELATION = 3;\n\nexport const AIR_TAG_CLAN_ENEMY_RELATION = 6;\n\nexport const AIR_TAG_MAX_BATCH_SIZE = 50;\n\nexport const AIR_TAG_MAX_COORDINATE = 65_535;\n\nexport type AirTagRelation = (typeof AIR_TAG_RELATIONS)[number];\n\nexport interface AirTagClan {\n id: number;\n name: string;\n}\n\nexport interface AirTagObservation {\n targetId: string;\n nickname: string;\n clan?: AirTagClan;\n relation: AirTagRelation;\n x: number;\n y: number;\n}\n\nexport interface AirTagObservationBatch {\n expectedMapId: number;\n observations: AirTagObservation[];\n}\n\nexport interface AirTagSubscriptionPayload {\n requestId: string;\n enabled: boolean;\n expectedMapId?: number;\n}\n\nexport interface AirTagTarget extends AirTagObservation {\n observedAt: number;\n enemyObservedAt?: number;\n clanEnemyObservedAt?: number;\n}\n\nexport interface AirTagScopeSnapshot {\n guildId: string;\n world: string;\n mapId: number;\n epochId: string;\n epochStartedAt: number;\n revision: number;\n targets: AirTagTarget[];\n}\n\nexport interface AirTagUpdateEvent {\n guildId: string;\n world: string;\n mapId: number;\n epochId: string;\n epochStartedAt: number;\n revision: number;\n target: AirTagTarget;\n}\n\nexport type AirTagRejectCode =\n | \"forbidden\"\n | \"invalid-context\"\n | \"invalid-payload\"\n | \"rate-limited\"\n | \"temporarily-unavailable\";\n\nexport type AirTagSubscriptionAck =\n | {\n status: \"accepted\";\n requestId: string;\n scopes: AirTagScopeSnapshot[];\n }\n | {\n status: \"rejected\";\n requestId: string;\n code: AirTagRejectCode;\n };\n\nexport type AirTagObservationAck =\n | {\n status: \"accepted\";\n acceptedScopes: number;\n acceptedTargets: number;\n }\n | {\n status: \"rejected\";\n code: AirTagRejectCode;\n retryAfterMs?: number;\n };\n\nconst ShortString = Schema.NonEmptyString.check(Schema.isMaxLength(64));\n\nconst GuildId = Schema.NonEmptyString.check(Schema.isMaxLength(128));\n\nconst SafeNatural = Schema.Int.check(\n Schema.isBetween({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER }),\n);\n\nconst Coordinate = Schema.Int.check(\n Schema.isBetween({ minimum: 0, maximum: AIR_TAG_MAX_COORDINATE }),\n);\n\nexport const AirTagRelationSchema = Schema.Literals(AIR_TAG_RELATIONS);\n\nexport const AirTagClanSchema = Schema.Struct({\n id: SafeNatural,\n name: ShortString,\n});\n\nexport const AirTagObservationSchema = Schema.Struct({\n targetId: ShortString,\n nickname: ShortString,\n clan: Schema.optionalKey(AirTagClanSchema),\n relation: AirTagRelationSchema,\n x: Coordinate,\n y: Coordinate,\n});\n\nexport const AirTagObservationBatchSchema = Schema.Struct({\n expectedMapId: Coordinate,\n observations: Schema.Array(AirTagObservationSchema),\n});\n\nexport const AirTagSubscriptionPayloadSchema = Schema.Struct({\n requestId: ShortString,\n enabled: Schema.Boolean,\n expectedMapId: Schema.optionalKey(Coordinate),\n});\n\nexport const AirTagTargetSchema = Schema.Struct({\n targetId: ShortString,\n nickname: ShortString,\n clan: Schema.optionalKey(AirTagClanSchema),\n relation: AirTagRelationSchema,\n x: Coordinate,\n y: Coordinate,\n observedAt: SafeNatural,\n enemyObservedAt: Schema.optionalKey(SafeNatural),\n clanEnemyObservedAt: Schema.optionalKey(SafeNatural),\n});\n\nconst AirTagScopeIdentityFields = {\n guildId: GuildId,\n world: ShortString,\n mapId: Coordinate,\n epochId: ShortString,\n epochStartedAt: SafeNatural,\n revision: SafeNatural,\n} as const;\n\nexport const AirTagScopeSnapshotSchema = Schema.Struct({\n ...AirTagScopeIdentityFields,\n targets: Schema.Array(AirTagTargetSchema),\n});\n\nexport const AirTagUpdateEventSchema = Schema.Struct({\n ...AirTagScopeIdentityFields,\n target: AirTagTargetSchema,\n});\n\nexport const isAirTagRelation = Schema.is(AirTagRelationSchema);\n\nexport const isAirTagObservation = Schema.is(AirTagObservationSchema);\n\nexport const isAirTagTarget = Schema.is(AirTagTargetSchema);\n\nexport const isAirTagScopeSnapshot = Schema.is(AirTagScopeSnapshotSchema);\n\nexport const isAirTagUpdateEvent = Schema.is(AirTagUpdateEventSchema);\n","import { Schema } from \"effect\";\nimport { NonNegativeInt } from \"./primitives.js\";\n\nexport const MAP_PING_TYPES = [\n \"attention\",\n \"enemy\",\n \"regroup\",\n \"avoid\",\n] as const;\n\nexport type MapPingType = (typeof MAP_PING_TYPES)[number];\n\nexport const MapPingTypeSchema = Schema.Literals(MAP_PING_TYPES);\n\nexport const MapPingRejectCodeSchema = Schema.Literals([\n \"forbidden\",\n \"invalid-context\",\n \"invalid-payload\",\n \"rate-limited\",\n \"temporarily-unavailable\",\n]);\n\nexport const isMapPingType = Schema.is(MapPingTypeSchema);\n\nexport interface MapPingSendPayload {\n expectedMapId: number;\n type: MapPingType;\n x: number;\n y: number;\n}\n\nexport type MapPingRejectCode =\n | \"forbidden\"\n | \"invalid-context\"\n | \"invalid-payload\"\n | \"rate-limited\"\n | \"temporarily-unavailable\";\n\nexport type MapPingAck =\n | {\n status: \"accepted\";\n pingId: string;\n }\n | {\n status: \"rejected\";\n code: MapPingRejectCode;\n retryAfterMs?: number;\n };\n\nexport interface MapPingEvent {\n pingId: string;\n world: string;\n mapId: number;\n type: MapPingType;\n x: number;\n y: number;\n sender: {\n characterId: string;\n name: string;\n };\n createdAt: number;\n}\n\nexport const MapPingSendPayloadSchema = Schema.Struct({\n expectedMapId: NonNegativeInt,\n type: MapPingTypeSchema,\n x: NonNegativeInt,\n y: NonNegativeInt,\n});\n\nexport const MapPingAckSchema = Schema.Union([\n Schema.Struct({\n status: Schema.Literal(\"accepted\"),\n pingId: Schema.NonEmptyString,\n }),\n Schema.Struct({\n status: Schema.Literal(\"rejected\"),\n code: MapPingRejectCodeSchema,\n retryAfterMs: Schema.optionalKey(NonNegativeInt),\n }),\n]);\n\nexport const MapPingEventSchema = Schema.Struct({\n pingId: Schema.NonEmptyString,\n world: Schema.NonEmptyString,\n mapId: NonNegativeInt,\n type: MapPingTypeSchema,\n x: NonNegativeInt,\n y: NonNegativeInt,\n sender: Schema.Struct({\n characterId: Schema.NonEmptyString,\n name: Schema.NonEmptyString,\n }),\n createdAt: NonNegativeInt,\n});\n","import { Schema } from \"effect\";\n\nexport const DISCORD_AUTH_SCOPES = [\n \"guilds.members.read\",\n \"guilds\",\n \"identify\",\n \"email\",\n];\n\nexport const DISCORD_ADMINISTRATOR_PERMISSION = 0x8n;\n\nexport const discordPermissionFields = {\n hasRequiredPermissions: Schema.Boolean,\n requiredPermissions: Schema.Array(Schema.String),\n grantedPermissions: Schema.Array(Schema.String),\n missingPermissions: Schema.Array(Schema.String),\n};\n\nexport const DiscordGuildSyncStatus = Schema.Literals([\n \"SYNCED\",\n \"SYNCING\",\n \"FAILED\",\n \"STALE\",\n \"NOT_FOUND\",\n]);\n","import { Schema } from \"effect\";\n\nexport const RabbitExchange = {\n DEFAULT: \"default\",\n DEAD_LETTER: \"dlx\",\n RETRY: \"retry\",\n} as const;\n\nexport const RabbitExchangeName = Schema.Literals([\n RabbitExchange.DEFAULT,\n RabbitExchange.DEAD_LETTER,\n RabbitExchange.RETRY,\n]);\n\nexport type RabbitExchangeName = typeof RabbitExchangeName.Type;\n\nexport const RabbitRoutingKey = {\n USERS_ONLINE_CHECKPOINT_V1: \"users.online.checkpoint.v1\",\n USERS_ONLINE_CHECKPOINT_V1_RETRY: \"users.online.checkpoint.v1.retry\",\n USERS_ONLINE_CHECKPOINT_V1_DLQ: \"users.online.checkpoint.v1.dlq\",\n ACTIVITY_LOG_CREATE: \"activity.log.create\",\n ACTIVITY_LOG_CREATE_DLQ: \"activity.log.create.dlq\",\n ACTIVITY_LOG_CREATE_RETRY: \"activity.log.create.retry\",\n DISCORD_GUILD_CHANNEL_DELETED: \"discord.guild.channel.deleted\",\n DISCORD_GUILD_CHANNEL_UPSERTED: \"discord.guild.channel.upserted\",\n DISCORD_GUILD_CHANNELS_SYNC_FAILED: \"discord.guild.channels.sync.failed\",\n DISCORD_GUILD_CHANNELS_SYNCED: \"discord.guild.channels.synced\",\n DISCORD_GUILD_SYNC_STATE_UPDATED: \"discord.guild.sync-state.updated\",\n EVENT_HERO_KILLED: \"event.hero.killed\",\n EVENT_MAP_STATUS_UPDATE: \"event.map-status.update\",\n EVENT_RANKING_UPDATE: \"event.ranking.update\",\n EVENT_RESPAWN_WINDOW_CLOSED: \"event.respawn-window.closed\",\n EVENT_RESPAWN_WINDOW_OPENED: \"event.respawn-window.opened\",\n GUILDS_CLEAR_MESSAGES: \"guilds.clear.messages\",\n GUILDS_CREATE: \"guilds.create\",\n GUILDS_CREATE_DLQ: \"guilds.create.dlq\",\n GUILDS_CREATE_RETRY: \"guilds.create.retry\",\n GUILDS_CREATE_ROLE: \"guilds.create.role\",\n GUILDS_CREATE_ROLE_DLQ: \"guilds.create.role.dlq\",\n GUILDS_CREATE_ROLE_RETRY: \"guilds.create.role.retry\",\n GUILDS_DELETE: \"guilds.delete\",\n GUILDS_DELETE_DLQ: \"guilds.delete.dlq\",\n GUILDS_DELETE_MESSAGE: \"guilds.delete.message\",\n GUILDS_DELETE_RETRY: \"guilds.delete.retry\",\n GUILDS_DELETE_ROLE: \"guilds.delete.role\",\n GUILDS_DELETE_ROLE_DLQ: \"guilds.delete.role.dlq\",\n GUILDS_DELETE_ROLE_RETRY: \"guilds.delete.role.retry\",\n GUILDS_INITIALIZE: \"guilds.initialize\",\n GUILDS_INITIALIZE_BOT: \"guilds.initialize-bot\",\n GUILDS_INITIALIZE_DLQ: \"guilds.initialize.dlq\",\n GUILDS_INITIALIZE_RETRY: \"guilds.initialize.retry\",\n GUILDS_KILLS_ACCEPTED_V1: \"guilds.kills.accepted.v1\",\n GUILDS_KILLS_ACCEPTED_V1_RETRY: \"guilds.kills.accepted.v1.retry\",\n GUILDS_KILLS_ACCEPTED_V1_DLQ: \"guilds.kills.accepted.v1.dlq\",\n GUILDS_LOOTS_CREATE: \"guilds.loots.create\",\n GUILDS_LOOTS_CREATE_DLQ: \"guilds.loots.create.dlq\",\n GUILDS_LOOTS_CREATE_RETRY: \"guilds.loots.create.retry\",\n GUILDS_LOOTS_DELETE: \"guilds.loots.delete\",\n GUILDS_LOOTS_SHARE_UPDATE: \"guilds.loots.share.update\",\n GUILDS_LOOTS_SHARE_UPDATE_DLQ: \"guilds.loots.share.update.dlq\",\n GUILDS_LOOTS_SHARE_UPDATE_RETRY: \"guilds.loots.share.update.retry\",\n GUILDS_LOOTS_UPDATE: \"guilds.loots.update\",\n GUILDS_MEMBERS_ADD: \"guilds.members.add\",\n GUILDS_MEMBERS_ADD_DLQ: \"guilds.members.add.dlq\",\n GUILDS_MEMBERS_ADD_RETRY: \"guilds.members.add.retry\",\n GUILDS_MEMBERS_ADD_ROLE: \"guilds.members.add.role\",\n GUILDS_MEMBERS_ADD_ROLE_DLQ: \"guilds.members.add.role.dlq\",\n GUILDS_MEMBERS_ADD_ROLE_RETRY: \"guilds.members.add.role.retry\",\n GUILDS_MEMBERS_REFRESH_JOB_UPDATE: \"guilds.members.refresh.job.update\",\n GUILDS_MEMBERS_REMOVE: \"guilds.members.remove\",\n GUILDS_MEMBERS_REMOVE_DLQ: \"guilds.members.remove.dlq\",\n GUILDS_MEMBERS_REMOVE_RETRY: \"guilds.members.remove.retry\",\n GUILDS_MEMBERS_REMOVE_ROLE: \"guilds.members.remove.role\",\n GUILDS_MEMBERS_REMOVE_ROLE_DLQ: \"guilds.members.remove.role.dlq\",\n GUILDS_MEMBERS_REMOVE_ROLE_RETRY: \"guilds.members.remove.role.retry\",\n GUILDS_MEMBERS_UPDATE: \"guilds.members.update\",\n GUILDS_MEMBERS_UPDATE_DLQ: \"guilds.members.update.dlq\",\n GUILDS_MEMBERS_UPDATE_RETRY: \"guilds.members.update.retry\",\n GUILDS_NOTIFICATIONS_SEND: \"guilds.notifications.send\",\n GUILDS_NOTIFICATIONS_SEND_DLQ: \"guilds.notifications.send.dlq\",\n GUILDS_NOTIFICATIONS_SEND_RETRY: \"guilds.notifications.send.retry\",\n GUILDS_NOTIFICATIONS_VOLUNTEER: \"guilds.notifications.volunteer\",\n GUILDS_NOTIFICATIONS_VOLUNTEER_DLQ: \"guilds.notifications.volunteer.dlq\",\n GUILDS_NOTIFICATIONS_VOLUNTEER_RETRY: \"guilds.notifications.volunteer.retry\",\n GUILDS_PARTY_GATHERING: \"guilds.party-gathering\",\n GUILDS_PARTY_GATHERING_CANCEL: \"guilds.party-gathering.cancel\",\n GUILDS_PARTY_GATHERING_DLQ: \"guilds.party-gathering.dlq\",\n GUILDS_PARTY_GATHERING_RETRY: \"guilds.party-gathering.retry\",\n GUILDS_RESERVATIONS_CHANGED_V2: \"guilds.reservations.v2.changed\",\n GUILDS_RESERVATIONS_CHANGED_V2_DLQ: \"guilds.reservations.v2.changed.dlq\",\n GUILDS_RESERVATIONS_CHANGED_V2_RETRY: \"guilds.reservations.v2.changed.retry\",\n GUILDS_RESERVATIONS_CREATE: \"guilds.reservations.create\",\n GUILDS_RESERVATIONS_CREATE_DLQ: \"guilds.reservations.create.dlq\",\n GUILDS_RESERVATIONS_CREATE_RETRY: \"guilds.reservations.create.retry\",\n GUILDS_RESERVATIONS_DELETE: \"guilds.reservations.delete\",\n GUILDS_RESERVATIONS_DELETE_DLQ: \"guilds.reservations.delete.dlq\",\n GUILDS_RESERVATIONS_DELETE_RETRY: \"guilds.reservations.delete.retry\",\n GUILDS_SEND_MESSAGE: \"guilds.send.message\",\n GUILDS_SEND_MESSAGE_DLQ: \"guilds.send.message.dlq\",\n GUILDS_SEND_MESSAGE_RETRY: \"guilds.send.message.retry\",\n GUILDS_SYNC: \"guilds.sync\",\n GUILDS_SYNC_TRIGGER: \"guilds.sync.trigger\",\n GUILDS_TIMERS_DELETE: \"guilds.timers.delete\",\n GUILDS_TIMERS_DELETE_DLQ: \"guilds.timers.delete.dlq\",\n GUILDS_TIMERS_DELETE_RETRY: \"guilds.timers.delete.retry\",\n GUILDS_TIMERS_UPDATE: \"guilds.timers.update\",\n GUILDS_TIMERS_UPDATE_DLQ: \"guilds.timers.update.dlq\",\n GUILDS_TIMERS_UPDATE_RETRY: \"guilds.timers.update.retry\",\n GUILDS_UPDATE: \"guilds.update\",\n GUILDS_UPDATE_DLQ: \"guilds.update.dlq\",\n GUILDS_UPDATE_MESSAGE: \"guilds.update.message\",\n GUILDS_UPDATE_RETRY: \"guilds.update.retry\",\n GUILDS_UPDATE_ROLE: \"guilds.update.role\",\n GUILDS_UPDATE_ROLE_DLQ: \"guilds.update.role.dlq\",\n GUILDS_UPDATE_ROLE_RETRY: \"guilds.update.role.retry\",\n NOTIFICATIONS_DELIVERY_RESULT: \"notifications.delivery.result\",\n NOTIFICATIONS_DISCORD_SEND: \"notifications.discord.send\",\n NOTIFICATIONS_LOOT_CREATED: \"notifications.loot.created\",\n NOTIFICATIONS_TIMER_DELETED: \"notifications.timer.deleted\",\n NOTIFICATIONS_TIMER_UPDATED: \"notifications.timer.updated\",\n GAME_CHARACTER_OFFLINE: \"game.character.offline\",\n PRESENCE_CHECK_REQUEST: \"presence.check.request\",\n PRESENCE_COVERAGE_CHECK: \"presence.coverage.check\",\n SEARCH_ITEMS_INDEX: \"search.items.index\",\n SEARCH_NPCS_INDEX: \"search.npcs.index\",\n SEARCH_PLAYERS_INDEX: \"search.players.index\",\n USERS_PARTY_READY_ROOM_UPDATED: \"users.party-ready-room.updated\",\n USERS_PARTY_READY_ROOM_UPDATED_DLQ: \"users.party-ready-room.updated.dlq\",\n USERS_PARTY_READY_ROOM_UPDATED_RETRY: \"users.party-ready-room.updated.retry\",\n} as const;\n\nexport const RabbitRoutingKeyName = Schema.Literals(\n Object.values(RabbitRoutingKey),\n);\n\nexport type RabbitRoutingKeyName = typeof RabbitRoutingKeyName.Type;\n\nexport const DEFAULT_RETRY_TTL_MS = 30_000;\n\nexport const RabbitExchangeDefinition = Schema.Struct({\n name: RabbitExchangeName,\n type: Schema.Literal(\"topic\"),\n durable: Schema.Boolean,\n});\n\nexport type RabbitExchangeDefinition = typeof RabbitExchangeDefinition.Type;\n\nexport const RabbitQueueDefinition = Schema.Struct({\n name: Schema.String,\n exchange: RabbitExchangeName,\n routingKey: RabbitRoutingKeyName,\n durable: Schema.Boolean,\n messageTtl: Schema.optional(Schema.Int),\n singleActiveConsumer: Schema.optional(Schema.Boolean),\n deadLetterExchange: Schema.optional(RabbitExchangeName),\n deadLetterRoutingKey: Schema.optional(RabbitRoutingKeyName),\n});\n\nexport type RabbitQueueDefinition = typeof RabbitQueueDefinition.Type;\n\nexport const canonicalExchanges = [\n { name: RabbitExchange.DEFAULT, type: \"topic\", durable: true },\n { name: RabbitExchange.RETRY, type: \"topic\", durable: true },\n { name: RabbitExchange.DEAD_LETTER, type: \"topic\", durable: true },\n] as const satisfies ReadonlyArray<RabbitExchangeDefinition>;\n\nexport const makeRetryQueue = (options: {\n name: string;\n retryRoutingKey: RabbitRoutingKeyName;\n destinationRoutingKey: RabbitRoutingKeyName;\n messageTtl?: number;\n}): RabbitQueueDefinition => ({\n name: options.name,\n exchange: RabbitExchange.RETRY,\n routingKey: options.retryRoutingKey,\n durable: true,\n messageTtl: options.messageTtl ?? DEFAULT_RETRY_TTL_MS,\n deadLetterExchange: RabbitExchange.DEFAULT,\n deadLetterRoutingKey: options.destinationRoutingKey,\n});\n\nexport const makeDeadLetterQueue = (options: {\n name: string;\n routingKey: RabbitRoutingKeyName;\n}): RabbitQueueDefinition => ({\n name: options.name,\n exchange: RabbitExchange.DEAD_LETTER,\n routingKey: options.routingKey,\n durable: true,\n});\n\nexport const makeQueue = (\n name: string,\n routingKey: RabbitQueueDefinition[\"routingKey\"],\n options: Partial<RabbitQueueDefinition> = {},\n): RabbitQueueDefinition => ({\n name,\n exchange: RabbitExchange.DEFAULT,\n routingKey,\n durable: true,\n ...options,\n});\n","import { UserFeedItem } from \"../feed.js\";\nimport { NpcTypeSchema } from \"@lootlog/schema/npc-type\";\nimport { DateTimeWithOffsetString } from \"@lootlog/schema/http-scalars\";\nimport {\n discordPermissionFields,\n DiscordGuildSyncStatus,\n} from \"@lootlog/schema/discord\";\nimport { NonEmptyString, NonNegativeInt } from \"@lootlog/schema/primitives\";\nimport { Schema } from \"effect\";\nimport { RabbitRoutingKey } from \"./topology.js\";\n\nexport const GameCharacterOffline = Schema.Struct({\n userId: NonEmptyString,\n discordId: NonEmptyString,\n world: NonEmptyString,\n characterId: NonEmptyString,\n organizationIds: Schema.Array(NonEmptyString),\n disconnectedAt: NonNegativeInt,\n});\n\nexport type GameCharacterOffline = typeof GameCharacterOffline.Type;\n\nconst NullableString = Schema.NullOr(Schema.String);\n\nconst NullableNumber = Schema.NullOr(Schema.Number);\n\nconst GuildRole = Schema.Struct({\n id: NonEmptyString,\n name: NonEmptyString,\n color: Schema.Number,\n admin: Schema.Boolean,\n position: Schema.Number,\n});\n\nexport const GuildCreated = Schema.Struct({\n guildId: NonEmptyString,\n name: NonEmptyString,\n icon: NullableString,\n ownerId: NonEmptyString,\n roles: Schema.Array(GuildRole),\n});\n\nexport const GuildUpdated = Schema.Struct({\n guildId: NonEmptyString,\n name: NonEmptyString,\n icon: NullableString,\n ownerId: NonEmptyString,\n});\n\nexport const GuildDeleted = Schema.Struct({ guildId: NonEmptyString });\n\nexport type GuildCreated = typeof GuildCreated.Type;\n\nexport type GuildUpdated = typeof GuildUpdated.Type;\n\nexport type GuildDeleted = typeof GuildDeleted.Type;\n\nexport const GuildRoleChanged = Schema.Struct({\n guildId: NonEmptyString,\n ...GuildRole.fields,\n});\n\nexport const GuildRoleDeleted = Schema.Struct({\n guildId: NonEmptyString,\n id: NonEmptyString,\n});\n\nexport type GuildRoleChanged = typeof GuildRoleChanged.Type;\n\nexport type GuildRoleDeleted = typeof GuildRoleDeleted.Type;\n\nexport const GuildMemberChanged = Schema.Struct({\n guildId: NonEmptyString,\n discordId: NonEmptyString,\n userId: NonEmptyString,\n});\n\nexport const PresenceCheckRequested = Schema.Struct({\n guildId: NonEmptyString,\n mapName: NonEmptyString,\n});\n\nexport const PresenceCoverageChecked = Schema.Struct({\n guildId: NonEmptyString,\n mapName: NonEmptyString,\n discordId: NonEmptyString,\n hasPlayer: Schema.Boolean,\n isAfk: Schema.optional(Schema.Boolean),\n});\n\nconst DiscordGuildChannel = Schema.Struct({\n guildId: NonEmptyString,\n channelId: NonEmptyString,\n name: NonEmptyString,\n channelType: NonEmptyString,\n parentId: NullableString,\n position: Schema.Number,\n active: Schema.Boolean,\n canView: Schema.Boolean,\n canSend: Schema.Boolean,\n ...discordPermissionFields,\n lastSyncedAt: NonEmptyString,\n});\n\nconst DiscordGuildSyncState = Schema.Struct({\n guildId: NonEmptyString,\n status: DiscordGuildSyncStatus,\n ...discordPermissionFields,\n channelCount: NonNegativeInt,\n selectableChannelCount: NonNegativeInt,\n lastAttemptAt: NullableString,\n lastSuccessAt: NullableString,\n lastError: NullableString,\n updatedAt: NonEmptyString,\n});\n\nexport const DiscordGuildChannelsSynced = Schema.Struct({\n guildId: NonEmptyString,\n channels: Schema.Array(DiscordGuildChannel),\n syncState: DiscordGuildSyncState,\n});\n\nexport const DiscordGuildChannelUpserted = Schema.Struct({\n guildId: NonEmptyString,\n channel: DiscordGuildChannel,\n syncState: DiscordGuildSyncState,\n});\n\nexport const DiscordGuildChannelsSyncFailed = Schema.Struct({\n guildId: NonEmptyString,\n status: DiscordGuildSyncStatus,\n lastAttemptAt: NonEmptyString,\n lastError: NonEmptyString,\n});\n\nexport const DiscordGuildSyncStateUpdated = Schema.Struct({\n guildId: NonEmptyString,\n syncState: DiscordGuildSyncState,\n});\n\nexport const OrganizationScopedEvent = Schema.Union([\n Schema.Struct({ guildId: NonEmptyString }),\n Schema.Struct({ organizationId: NonEmptyString }),\n]);\n\nexport const PartyReadyRoomUpdated = Schema.Struct({\n recipientDiscordId: NonEmptyString,\n eligibleGuildIds: Schema.Array(NonEmptyString),\n update: Schema.Unknown,\n});\n\nexport const NotificationVolunteer = Schema.Struct({\n notificationId: NonEmptyString,\n targetDiscordId: NonEmptyString,\n volunteerDiscordId: NonEmptyString,\n world: NonEmptyString,\n character: Schema.Unknown,\n});\n\nexport const GuildLootEventNpc = Schema.Struct({\n lvl: Schema.optional(NullableNumber),\n prof: Schema.optional(NullableString),\n type: Schema.optional(\n Schema.NullOr(Schema.Union([Schema.Number, Schema.String])),\n ),\n wt: Schema.optional(\n Schema.NullOr(Schema.Union([Schema.Number, Schema.String])),\n ),\n});\n\nexport const GuildKillsAcceptedV1 = Schema.Struct({\n sourceNpcs: Schema.optional(\n Schema.Array(Schema.Struct({ level: NonNegativeInt, type: NpcTypeSchema })),\n ),\n feedEntry: Schema.optional(UserFeedItem),\n version: Schema.Literal(1),\n guildId: NonEmptyString,\n world: NonEmptyString,\n npc: Schema.Struct({ type: NpcTypeSchema, lvl: NonNegativeInt }),\n});\n\nexport type GuildKillsAcceptedV1 = typeof GuildKillsAcceptedV1.Type;\n\nexport const GuildLootCreatedEventV2 = Schema.Struct({\n feedEntry: Schema.optional(UserFeedItem),\n version: Schema.Literal(2),\n guildId: NonEmptyString,\n lootId: NonNegativeInt,\n npcs: Schema.Array(GuildLootEventNpc),\n});\n\nexport type GuildLootCreatedEventV2 = typeof GuildLootCreatedEventV2.Type;\n\nexport const GuildLootShareUpdatedEventV2 = Schema.Struct({\n ...GuildLootCreatedEventV2.fields,\n lootShare: Schema.Record(Schema.String, Schema.Array(Schema.String)),\n});\n\nexport type GuildLootShareUpdatedEventV2 =\n typeof GuildLootShareUpdatedEventV2.Type;\n\nexport const ReservationChangedEventV2 = Schema.Struct({\n version: Schema.Literal(2),\n action: Schema.Literals([\"created\", \"updated\", \"deleted\", \"sharing-changed\"]),\n sourceGuildId: NonEmptyString,\n audienceGuildIds: Schema.Array(NonEmptyString),\n reservationId: Schema.NullOr(NonNegativeInt),\n spotId: Schema.NullOr(Schema.String),\n});\n\nexport type ReservationChangedEventV2 = typeof ReservationChangedEventV2.Type;\n\nexport const EventScope = Schema.Struct({\n guildId: NonEmptyString,\n eventId: NonEmptyString,\n});\n\nexport const EventMapStatusUpdated = Schema.Struct({\n ...EventScope.fields,\n heroNpcLvl: Schema.optional(Schema.NullOr(NonNegativeInt)),\n mapId: NonEmptyString,\n reason: Schema.optional(Schema.String),\n});\n\nexport const EventHeroKilled = Schema.Struct({\n ...EventScope.fields,\n heroNpcLvl: Schema.optional(Schema.NullOr(NonNegativeInt)),\n heroId: Schema.optional(NonEmptyString),\n});\n\nexport const EventRespawnWindowChanged = Schema.Struct({\n ...EventScope.fields,\n heroNpcLvl: Schema.optional(Schema.NullOr(NonNegativeInt)),\n heroId: NonEmptyString,\n});\n\nexport const ActivityLogCreated = Schema.Struct({\n userId: NonEmptyString,\n guildId: Schema.optional(NonEmptyString),\n action: NonEmptyString,\n entityType: Schema.optional(NonEmptyString),\n entityId: Schema.optional(Schema.Union([Schema.String, Schema.Number])),\n metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n});\n\nexport const NotificationTimerUpdated = Schema.Struct({\n guildId: NonEmptyString,\n world: NonEmptyString,\n npcId: NonNegativeInt,\n timerKey: NonEmptyString,\n minSpawnTime: NonEmptyString,\n maxSpawnTime: NonEmptyString,\n npc: Schema.optional(\n Schema.NullOr(Schema.Struct({ name: Schema.optional(Schema.String) })),\n ),\n});\n\nexport const NotificationTimerDeleted = Schema.Struct({\n guildId: NonEmptyString,\n world: NonEmptyString,\n timerKey: NonEmptyString,\n npcId: Schema.optional(NonNegativeInt),\n});\n\nexport const LootCreatedNotificationEventV2 = Schema.Struct({\n version: Schema.Literal(2),\n lootId: NonNegativeInt,\n world: NonEmptyString,\n guildIds: Schema.Array(NonEmptyString),\n itemIds: Schema.Array(NonNegativeInt),\n itemNames: Schema.Array(Schema.String),\n npcs: Schema.Array(\n Schema.Struct({\n type: NullableString,\n lvl: NullableNumber,\n }),\n ),\n});\n\nexport const DiscordNotificationDeliveryResult = Schema.Struct({\n notificationJobId: NonEmptyString,\n success: Schema.Boolean,\n retryable: Schema.Boolean,\n providerMessageId: Schema.optional(NullableString),\n errorCode: Schema.optional(NullableString),\n errorMessage: Schema.optional(NullableString),\n deliveredAt: NonEmptyString,\n});\n\nexport const DiscordGuildChannelDeleted = Schema.Struct({\n guildId: NonEmptyString,\n channelId: NonEmptyString,\n syncState: DiscordGuildSyncState,\n});\n\n/** Cumulative confirmed game presence. A gap starts a new segment; retries never extend it. */\nexport const UserOnlineCheckpointV1 = Schema.Struct({\n version: Schema.Literal(1),\n type: Schema.Literal(\"checkpoint\"),\n userId: NonEmptyString,\n sessionId: NonEmptyString,\n segmentId: NonEmptyString,\n world: Schema.optional(NonEmptyString),\n startedAt: DateTimeWithOffsetString,\n endedAt: DateTimeWithOffsetString,\n observedAt: DateTimeWithOffsetString,\n}).check(\n Schema.makeFilter(\n (event) =>\n Date.parse(event.startedAt) <= Date.parse(event.endedAt) &&\n Date.parse(event.endedAt) <= Date.parse(event.observedAt),\n { expected: \"ordered confirmed interval timestamps\" },\n ),\n);\n\nexport type UserOnlineCheckpointV1 = typeof UserOnlineCheckpointV1.Type;\n\n/** Published only after the durable publisher has drained its pending checkpoints. */\nexport const UserOnlineHealthV1 = Schema.Struct({\n version: Schema.Literal(1),\n type: Schema.Literal(\"collector\"),\n observedAt: DateTimeWithOffsetString,\n status: Schema.Literals([\"healthy\", \"degraded\"]),\n});\n\nexport type UserOnlineHealthV1 = typeof UserOnlineHealthV1.Type;\n\nexport const UserOnlineEventV1 = Schema.Union([\n UserOnlineCheckpointV1,\n UserOnlineHealthV1,\n]);\n\nexport type UserOnlineEventV1 = typeof UserOnlineEventV1.Type;\n\nexport const canonicalRabbitEventSchemas = {\n [RabbitRoutingKey.GAME_CHARACTER_OFFLINE]: GameCharacterOffline,\n [RabbitRoutingKey.GUILDS_KILLS_ACCEPTED_V1]: GuildKillsAcceptedV1,\n [RabbitRoutingKey.USERS_ONLINE_CHECKPOINT_V1]: UserOnlineEventV1,\n [RabbitRoutingKey.ACTIVITY_LOG_CREATE]: ActivityLogCreated,\n [RabbitRoutingKey.DISCORD_GUILD_CHANNEL_DELETED]: DiscordGuildChannelDeleted,\n [RabbitRoutingKey.DISCORD_GUILD_CHANNEL_UPSERTED]:\n DiscordGuildChannelUpserted,\n [RabbitRoutingKey.DISCORD_GUILD_CHANNELS_SYNC_FAILED]:\n DiscordGuildChannelsSyncFailed,\n [RabbitRoutingKey.DISCORD_GUILD_CHANNELS_SYNCED]: DiscordGuildChannelsSynced,\n [RabbitRoutingKey.DISCORD_GUILD_SYNC_STATE_UPDATED]:\n DiscordGuildSyncStateUpdated,\n [RabbitRoutingKey.EVENT_HERO_KILLED]: EventHeroKilled,\n [RabbitRoutingKey.EVENT_MAP_STATUS_UPDATE]: EventMapStatusUpdated,\n [RabbitRoutingKey.EVENT_RANKING_UPDATE]: EventScope,\n [RabbitRoutingKey.EVENT_RESPAWN_WINDOW_CLOSED]: EventRespawnWindowChanged,\n [RabbitRoutingKey.EVENT_RESPAWN_WINDOW_OPENED]: EventRespawnWindowChanged,\n [RabbitRoutingKey.GUILDS_LOOTS_CREATE]: GuildLootCreatedEventV2,\n [RabbitRoutingKey.GUILDS_LOOTS_SHARE_UPDATE]: GuildLootShareUpdatedEventV2,\n [RabbitRoutingKey.GUILDS_CREATE]: GuildCreated,\n [RabbitRoutingKey.GUILDS_DELETE]: GuildDeleted,\n [RabbitRoutingKey.GUILDS_UPDATE]: GuildUpdated,\n [RabbitRoutingKey.GUILDS_CREATE_ROLE]: GuildRoleChanged,\n [RabbitRoutingKey.GUILDS_DELETE_ROLE]: GuildRoleDeleted,\n [RabbitRoutingKey.GUILDS_UPDATE_ROLE]: GuildRoleChanged,\n [RabbitRoutingKey.GUILDS_MEMBERS_ADD]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_MEMBERS_ADD_ROLE]: GuildMemberChanged,\n [RabbitRoutingKey.GUILDS_MEMBERS_REMOVE]: GuildMemberChanged,\n [RabbitRoutingKey.GUILDS_MEMBERS_REMOVE_ROLE]: GuildMemberChanged,\n [RabbitRoutingKey.GUILDS_MEMBERS_UPDATE]: GuildMemberChanged,\n [RabbitRoutingKey.GUILDS_TIMERS_UPDATE]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_TIMERS_DELETE]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_RESERVATIONS_CREATE]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_RESERVATIONS_DELETE]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_SEND_MESSAGE]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_UPDATE_MESSAGE]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_DELETE_MESSAGE]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_CLEAR_MESSAGES]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_NOTIFICATIONS_SEND]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_NOTIFICATIONS_VOLUNTEER]: NotificationVolunteer,\n [RabbitRoutingKey.GUILDS_PARTY_GATHERING]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_PARTY_GATHERING_CANCEL]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_MEMBERS_REFRESH_JOB_UPDATE]: OrganizationScopedEvent,\n [RabbitRoutingKey.GUILDS_RESERVATIONS_CHANGED_V2]: ReservationChangedEventV2,\n [RabbitRoutingKey.NOTIFICATIONS_DELIVERY_RESULT]:\n DiscordNotificationDeliveryResult,\n [RabbitRoutingKey.NOTIFICATIONS_LOOT_CREATED]: LootCreatedNotificationEventV2,\n [RabbitRoutingKey.NOTIFICATIONS_TIMER_DELETED]: NotificationTimerDeleted,\n [RabbitRoutingKey.NOTIFICATIONS_TIMER_UPDATED]: NotificationTimerUpdated,\n [RabbitRoutingKey.PRESENCE_CHECK_REQUEST]: PresenceCheckRequested,\n [RabbitRoutingKey.PRESENCE_COVERAGE_CHECK]: PresenceCoverageChecked,\n [RabbitRoutingKey.USERS_PARTY_READY_ROOM_UPDATED]: PartyReadyRoomUpdated,\n} as const;\n\nexport type CanonicalRabbitEventRoutingKey =\n keyof typeof canonicalRabbitEventSchemas;\n\nexport type CanonicalRabbitEvent<\n RoutingKey extends CanonicalRabbitEventRoutingKey,\n> = (typeof canonicalRabbitEventSchemas)[RoutingKey][\"Encoded\"];\n\nexport const decodeRabbitEvent = <\n RoutingKey extends CanonicalRabbitEventRoutingKey,\n>(\n routingKey: RoutingKey,\n input: unknown,\n): CanonicalRabbitEvent<RoutingKey> => {\n const eventSchema = canonicalRabbitEventSchemas[routingKey];\n\n if (eventSchema === undefined) {\n throw new Error(`No RabbitMQ event schema for routing key: ${routingKey}`);\n }\n\n Schema.decodeUnknownSync(eventSchema)(input);\n\n // SAFETY: the routing key's schema just validated its encoded input. Return\n // that original input to preserve wire extension fields and object identity.\n return input as CanonicalRabbitEvent<RoutingKey>;\n};\n\nexport const decodeRabbitEventJson = <\n RoutingKey extends CanonicalRabbitEventRoutingKey,\n>(\n routingKey: RoutingKey,\n input: string,\n): CanonicalRabbitEvent<RoutingKey> =>\n decodeRabbitEvent(\n routingKey,\n Schema.decodeUnknownSync(Schema.fromJsonString(Schema.Unknown))(input),\n );\n","import { AccessPolicySnapshot, AccessPolicyChange } from \"./access-policy.js\";\nimport { UserFeedItem } from \"../feed.js\";\nimport { NonEmptyString, NonNegativeInt } from \"@lootlog/schema/primitives\";\nimport {\n AirTagObservationBatchSchema,\n AirTagScopeSnapshotSchema,\n AirTagUpdateEventSchema,\n} from \"@lootlog/schema/air-tag\";\nimport {\n MapPingAckSchema,\n MapPingEventSchema,\n MapPingSendPayloadSchema,\n} from \"@lootlog/schema/map-ping\";\nimport { Schema } from \"effect\";\nimport {\n GuildLootCreatedEventV2,\n GuildLootShareUpdatedEventV2,\n ReservationChangedEventV2,\n} from \"../rabbit/events.js\";\n\nexport const REALTIME_PROTOCOL_VERSION = 1;\n\n// Offered alongside v1 by clients that understand feed events; never selected as the wire protocol.\nexport const REALTIME_FEED_CAPABILITY = \"lootlog.feed.v1\";\n\nexport const REALTIME_NOTIFICATION_VOLUNTEER_CAPABILITY =\n \"lootlog.notification-volunteer.v1\";\n\nexport const REALTIME_SUBPROTOCOL = \"lootlog.realtime.v1\";\n\nexport const REALTIME_JSON_SUBPROTOCOL = \"lootlog.realtime.json.v1\";\n\nexport const PRESENCE_HEARTBEAT_INTERVAL_MS = 25_000;\n\nexport const PRESENCE_EXPIRY_MS = 60_000;\n\nconst RequestId = NonEmptyString;\n\nconst Revision = NonNegativeInt;\n\nconst Timestamp = NonNegativeInt;\n\nexport const RealtimeLogicalTopic = Schema.Literals([\n \"organization.activity\",\n \"organization.chat\",\n \"organization.loots\",\n \"organization.members\",\n \"organization.notifications\",\n \"organization.presence\",\n \"organization.reservations\",\n \"organization.timers\",\n \"event.coordination\",\n \"map.air-tags\",\n \"map.pings\",\n \"party.ready-room\",\n]);\n\nexport type RealtimeLogicalTopic = typeof RealtimeLogicalTopic.Type;\n\nexport const SubscriptionScope = Schema.Struct({\n topic: RealtimeLogicalTopic,\n organizationId: Schema.optional(NonEmptyString),\n eventId: Schema.optional(NonEmptyString),\n world: Schema.optional(NonEmptyString),\n mapId: Schema.optional(NonNegativeInt),\n});\n\nexport type SubscriptionScope = typeof SubscriptionScope.Type;\n\nexport const PresencePlatform = Schema.Literals([\"game\", \"web-app\"]);\n\nexport const PresenceStatus = Schema.Literals([\"online\", \"offline\"]);\n\nexport const PresenceConfidence = Schema.Literals([\"verified\", \"reported\"]);\n\nexport const PresenceClan = Schema.Struct({\n id: Schema.optional(NonNegativeInt),\n name: Schema.optional(Schema.String),\n rank: Schema.optional(Schema.Int),\n});\n\nexport const PresenceCharacter = Schema.Struct({\n world: NonEmptyString,\n name: NonEmptyString,\n lvl: NonNegativeInt,\n icon: Schema.String,\n characterId: NonEmptyString,\n accountId: NonEmptyString,\n prof: Schema.String,\n clan: Schema.optional(PresenceClan),\n});\n\nexport const PrecisePresenceLocation = Schema.Struct({\n mapId: Schema.optional(NonNegativeInt),\n map: NonEmptyString,\n x: Schema.optional(NonNegativeInt),\n y: Schema.optional(NonNegativeInt),\n});\n\nexport const BasicPresence = Schema.Struct({\n userId: NonEmptyString,\n discordId: Schema.optional(NonEmptyString),\n sessionId: NonEmptyString,\n organizationIds: Schema.Array(NonEmptyString),\n platform: PresencePlatform,\n status: PresenceStatus,\n confidence: PresenceConfidence,\n isAfk: Schema.Boolean,\n lastSeen: Timestamp,\n character: Schema.optional(PresenceCharacter),\n});\n\nexport type BasicPresence = typeof BasicPresence.Type;\n\nexport const PresenceWithLocation = Schema.Struct({\n ...BasicPresence.fields,\n location: PrecisePresenceLocation,\n});\n\nexport type PresenceWithLocation = typeof PresenceWithLocation.Type;\n\nexport const PublishedPresence = Schema.Struct({\n organizationIds: Schema.Array(NonEmptyString),\n isAfk: Schema.optional(Schema.Boolean),\n character: Schema.optional(PresenceCharacter),\n location: Schema.optional(PrecisePresenceLocation),\n clientObservedAt: Schema.optional(Timestamp),\n});\n\nexport const PresenceSnapshot = Schema.Struct({\n organizationId: NonEmptyString,\n world: Schema.optional(NonEmptyString),\n revision: Revision,\n // Match the richer shape first so the basic schema does not strip location.\n presences: Schema.Array(Schema.Union([PresenceWithLocation, BasicPresence])),\n});\n\nexport const PresenceDelta = Schema.Struct({\n organizationId: NonEmptyString,\n revision: Revision,\n changes: Schema.Array(\n Schema.Union([\n Schema.Struct({\n action: Schema.Literal(\"upsert\"),\n presence: Schema.Union([PresenceWithLocation, BasicPresence]),\n }),\n Schema.Struct({\n action: Schema.Literal(\"remove\"),\n userId: NonEmptyString,\n discordId: Schema.optional(NonEmptyString),\n sessionId: NonEmptyString,\n }),\n ]),\n ),\n});\n\nconst command = <\n Type extends string,\n Data extends Schema.Codec<unknown, unknown>,\n>(\n type: Type,\n data: Data,\n) =>\n Schema.Struct({\n v: Schema.Literal(REALTIME_PROTOCOL_VERSION),\n type: Schema.Literal(type),\n requestId: Schema.optional(RequestId),\n data,\n });\n\nexport const SessionJoinCommand = command(\n \"session.join\",\n Schema.Struct({\n world: Schema.optional(NonEmptyString),\n character: Schema.optional(PresenceCharacter),\n margonemAccountProof: Schema.optional(Schema.Unknown),\n }),\n);\n\nexport const HeartbeatCommand = command(\n \"presence.heartbeat\",\n Schema.Struct({ sessionId: NonEmptyString }),\n);\n\nexport const PresencePublishCommand = command(\n \"presence.publish\",\n PublishedPresence,\n);\n\nexport const PresenceFetchCommand = command(\n \"presence.fetch\",\n Schema.Struct({\n organizationId: NonEmptyString,\n world: Schema.optional(NonEmptyString),\n }),\n);\n\nexport const SubscribeCommand = command(\n \"subscription.subscribe\",\n SubscriptionScope,\n);\n\nexport const UnsubscribeCommand = command(\n \"subscription.unsubscribe\",\n SubscriptionScope,\n);\n\nexport const MapPingCommand = command(\n \"map-ping.send\",\n MapPingSendPayloadSchema,\n);\n\nexport const AirTagSubscriptionCommand = command(\n \"air-tag.subscription\",\n Schema.Struct({\n requestId: RequestId,\n enabled: Schema.Boolean,\n expectedMapId: Schema.optional(NonNegativeInt),\n }),\n);\n\nexport const AirTagObservationCommand = command(\n \"air-tag.observation\",\n AirTagObservationBatchSchema,\n);\n\nexport const AirTagRejectCode = Schema.Literals([\n \"forbidden\",\n \"invalid-context\",\n \"invalid-payload\",\n \"rate-limited\",\n \"temporarily-unavailable\",\n]);\n\nexport const AirTagSubscriptionAck = Schema.Union([\n Schema.Struct({\n status: Schema.Literal(\"accepted\"),\n requestId: RequestId,\n scopes: Schema.Array(AirTagScopeSnapshotSchema),\n }),\n Schema.Struct({\n status: Schema.Literal(\"rejected\"),\n requestId: RequestId,\n code: AirTagRejectCode,\n }),\n]);\n\nexport const AirTagObservationAck = Schema.Union([\n Schema.Struct({\n status: Schema.Literal(\"accepted\"),\n acceptedScopes: NonNegativeInt,\n acceptedTargets: NonNegativeInt,\n }),\n Schema.Struct({\n status: Schema.Literal(\"rejected\"),\n code: AirTagRejectCode,\n retryAfterMs: Schema.optional(NonNegativeInt),\n }),\n]);\n\nexport { MapPingAckSchema };\n\nexport const ClientCommand = Schema.Union([\n SessionJoinCommand,\n HeartbeatCommand,\n PresencePublishCommand,\n PresenceFetchCommand,\n SubscribeCommand,\n UnsubscribeCommand,\n MapPingCommand,\n AirTagSubscriptionCommand,\n AirTagObservationCommand,\n]);\n\nexport type ClientCommand = typeof ClientCommand.Type;\n\nexport const RealtimeError = Schema.Struct({\n code: NonEmptyString,\n message: NonEmptyString,\n retryable: Schema.Boolean,\n retryAfterMs: Schema.optional(NonNegativeInt),\n details: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n});\n\nexport type RealtimeError = typeof RealtimeError.Type;\n\nexport const Response = Schema.Union([\n Schema.Struct({\n v: Schema.Literal(REALTIME_PROTOCOL_VERSION),\n requestId: RequestId,\n status: Schema.Literal(\"success\"),\n data: Schema.optional(Schema.Unknown),\n }),\n Schema.Struct({\n v: Schema.Literal(REALTIME_PROTOCOL_VERSION),\n requestId: RequestId,\n status: Schema.Literal(\"error\"),\n error: RealtimeError,\n }),\n]);\n\nexport type Response = typeof Response.Type;\n\nconst serverEvent = <\n Type extends string,\n Data extends Schema.Codec<unknown, unknown>,\n>(\n type: Type,\n data: Data,\n) =>\n Schema.Struct({\n v: Schema.Literal(REALTIME_PROTOCOL_VERSION),\n type: Schema.Literal(type),\n sequence: Schema.optional(Revision),\n data,\n });\n\nconst OrganizationEvent = Schema.Struct({\n organizationId: NonEmptyString,\n payload: Schema.Unknown,\n});\n\nexport const ServerEvent = Schema.Union([\n serverEvent(\n \"session.joined\",\n Schema.Struct({\n connectionId: NonEmptyString,\n organizationIds: Schema.Array(NonEmptyString),\n subscriptionScopes: Schema.Array(SubscriptionScope),\n accessPolicy: Schema.optional(AccessPolicySnapshot),\n }),\n ),\n serverEvent(\n \"permissions.updated\",\n Schema.Struct({\n changes: Schema.optional(Schema.Array(AccessPolicyChange)),\n organizationIds: Schema.Array(NonEmptyString),\n subscriptionScopes: Schema.Array(SubscriptionScope),\n accessPolicy: Schema.optional(AccessPolicySnapshot),\n }),\n ),\n serverEvent(\"presence.snapshot\", PresenceSnapshot),\n serverEvent(\"presence.delta\", PresenceDelta),\n serverEvent(\"chat.created\", OrganizationEvent),\n serverEvent(\"chat.updated\", OrganizationEvent),\n serverEvent(\"chat.deleted\", OrganizationEvent),\n serverEvent(\"chat.cleared\", OrganizationEvent),\n serverEvent(\"feed.entry\", UserFeedItem),\n serverEvent(\"kills.changed\", Schema.Struct({ guildId: NonEmptyString })),\n serverEvent(\"loot.created\", GuildLootCreatedEventV2),\n serverEvent(\"loot.share-updated\", GuildLootShareUpdatedEventV2),\n serverEvent(\"timer.created\", OrganizationEvent),\n serverEvent(\"timer.deleted\", OrganizationEvent),\n serverEvent(\"reservation.created\", OrganizationEvent),\n serverEvent(\"reservation.deleted\", OrganizationEvent),\n serverEvent(\"reservation.changed\", ReservationChangedEventV2),\n serverEvent(\"notification.sent\", OrganizationEvent),\n serverEvent(\"member-refresh.updated\", OrganizationEvent),\n serverEvent(\"party-gathering.updated\", OrganizationEvent),\n serverEvent(\"party-gathering.cancelled\", OrganizationEvent),\n serverEvent(\"party-ready-room.updated\", OrganizationEvent),\n serverEvent(\"map-ping.received\", MapPingEventSchema),\n serverEvent(\"air-tag.updated\", AirTagUpdateEventSchema),\n serverEvent(\"event.map-status-updated\", OrganizationEvent),\n serverEvent(\"event.hero-killed\", OrganizationEvent),\n serverEvent(\"event.ranking-updated\", OrganizationEvent),\n serverEvent(\"event.respawn-window-opened\", OrganizationEvent),\n serverEvent(\"event.respawn-window-closed\", OrganizationEvent),\n serverEvent(\n \"notification.volunteer\",\n Schema.Struct({\n notificationId: NonEmptyString,\n volunteer: Schema.StructWithRest(\n Schema.Struct({ discordId: NonEmptyString, world: NonEmptyString }),\n [Schema.Record(Schema.String, Schema.Unknown)],\n ),\n }),\n ),\n]);\n\nexport type ServerEvent = typeof ServerEvent.Type;\n\nexport const RealtimeFrame = Schema.Union([\n ClientCommand,\n Response,\n ServerEvent,\n]);\n\nexport type RealtimeFrame = typeof RealtimeFrame.Type;\n\nexport const decodeClientCommand = Schema.decodeUnknownSync(ClientCommand);\n\nexport const decodeResponse = Schema.decodeUnknownSync(Response);\n\nexport const decodeServerEvent = Schema.decodeUnknownSync(ServerEvent);\n\nexport const decodeRealtimeFrame = Schema.decodeUnknownSync(RealtimeFrame);\n\n// Discriminate an already decoded frame without parsing its payload a second time.\nconst serverEventTypes = new Set<string>(\n ServerEvent.members.map((member) => member.fields.type.literal),\n);\n\nexport const isServerEventFrame = (\n frame: RealtimeFrame,\n): frame is ServerEvent => \"type\" in frame && serverEventTypes.has(frame.type);\n","import { TaggedError as TaggedErrorClass } from \"effect/Schema\";\nimport { decode, encode } from \"@msgpack/msgpack\";\nimport { Predicate, Result, Schema } from \"effect\";\nimport {\n PresenceSnapshot,\n MapPingAckSchema,\n AirTagSubscriptionAck,\n AirTagObservationAck,\n RealtimeFrame,\n type RealtimeFrame as RealtimeFrameType,\n} from \"./protocol.js\";\n\nexport class RealtimeCodecError extends TaggedErrorClass<RealtimeCodecError>()(\n \"RealtimeCodecError\",\n {\n operation: Schema.Literals([\"decode\", \"encode\"]),\n message: Schema.String,\n cause: Schema.Defect(),\n },\n) {}\n\nconst getErrorMessage = (cause: unknown): string =>\n cause instanceof Error ? cause.message : String(cause);\n\nconst tryEncodeFrame = (frame: RealtimeFrameType) =>\n Result.try({\n try: () => {\n const validated = Schema.encodeUnknownSync(RealtimeFrame)(frame);\n\n return {\n frame: validated,\n bytes: encode(validated, { ignoreUndefined: true }),\n };\n },\n catch: (error) =>\n new RealtimeCodecError({\n operation: \"encode\",\n message: getErrorMessage(error),\n cause: error,\n }),\n });\n\nexport const tryEncodeRealtimeFrame = (frame: RealtimeFrameType) =>\n Result.map(tryEncodeFrame(frame), ({ bytes }) => bytes);\n\n// Only reuse values that MessagePack would leave unchanged. In particular,\n// open payloads may contain accessors, binary views, undefined or custom objects.\n// Keep the decoder as the authority for normalization and rejected map keys.\n// oxlint-disable-next-line anti-slop/no-unknown-parameters -- The codec must inspect schema-validated open payloads for MessagePack normalization.\nconst isMessagePackStable = (value: unknown): boolean => {\n if (Predicate.isNumber(value)) return !Object.is(value, -0);\n\n if (Predicate.isString(value)) return !/[\\uD800-\\uDFFF]/u.test(value);\n\n if (!Predicate.isObjectOrArray(value))\n return value === null || Predicate.isBoolean(value);\n\n const prototype: unknown = Object.getPrototypeOf(value);\n const array = Array.isArray(value);\n\n if (\n prototype !== (array ? Array.prototype : Object.prototype) &&\n prototype !== null\n )\n return false;\n\n const keys = Reflect.ownKeys(value);\n\n if (array && keys.length !== value.length + 1) return false;\n\n for (const key of keys) {\n if (!Predicate.isString(key)) return false;\n\n if (array && key === \"length\") continue;\n const property = Object.getOwnPropertyDescriptor(value, key);\n\n if (!property?.enumerable || !(\"value\" in property)) return false;\n\n if (key === \"__proto__\" || /[\\uD800-\\uDFFF]/u.test(key)) return false;\n\n if (!isMessagePackStable(property.value)) return false;\n }\n\n return true;\n};\n\n/** Encode once and retain the validated value when no wire normalization is needed. */\nexport const prepareRealtimeFrame = (frame: RealtimeFrameType) => {\n const encoded = Result.getOrThrow(tryEncodeFrame(frame));\n\n return {\n bytes: encoded.bytes,\n // An absent value requests the normal decoder path, never the original input.\n frame: isMessagePackStable(encoded.frame) ? encoded.frame : undefined,\n };\n};\n\nexport const encodeRealtimeFrame = (\n frame: RealtimeFrameType,\n): Uint8Array<ArrayBuffer> => Result.getOrThrow(tryEncodeRealtimeFrame(frame));\n\nexport const tryDecodeRealtimeFrame = (bytes: Uint8Array | ArrayBuffer) =>\n Result.try({\n try: () => {\n const input = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);\n\n return Schema.decodeUnknownSync(RealtimeFrame)(decode(input));\n },\n catch: (error) =>\n new RealtimeCodecError({\n operation: \"decode\",\n message: getErrorMessage(error),\n cause: error,\n }),\n });\n\nexport const decodeRealtimeFrame = (\n bytes: Uint8Array | ArrayBuffer,\n): RealtimeFrameType => Result.getOrThrow(tryDecodeRealtimeFrame(bytes));\n\nexport const decodePresenceSnapshot =\n Schema.decodeUnknownSync(PresenceSnapshot);\n\nexport const isMapPingAcknowledgement = Schema.is(MapPingAckSchema);\n\nexport const isAirTagSubscriptionAcknowledgement = Schema.is(\n AirTagSubscriptionAck,\n);\n\nexport const isAirTagObservationAcknowledgement =\n Schema.is(AirTagObservationAck);\n\nexport const isPresenceFetchResult = Schema.is(\n Schema.Struct({\n presences: Schema.optional(PresenceSnapshot.fields.presences),\n }),\n);\n","import {\n decodeRealtimeFrame,\n isServerEventFrame,\n PRESENCE_HEARTBEAT_INTERVAL_MS,\n REALTIME_PROTOCOL_VERSION,\n type ClientCommand,\n type ServerEvent,\n type SubscriptionScope,\n} from \"@lootlog/protocol/realtime\";\nimport {\n encodeRealtimeFrame,\n tryDecodeRealtimeFrame,\n} from \"@lootlog/protocol/realtime/codec\";\nimport { Result } from \"effect\";\n\ntype CommandType = ClientCommand[\"type\"];\n\ntype CommandData<Type extends CommandType> = Extract<\n ClientCommand,\n { type: Type }\n>[\"data\"];\n\nexport type RealtimeConnectionState =\n | \"disconnected\"\n | \"connecting\"\n | \"connected\"\n | \"joining\"\n | \"ready\"\n | \"reconnecting\";\n\nexport interface RealtimeWebSocket {\n binaryType: BinaryType;\n readonly readyState: number;\n addEventListener(\n type: \"open\" | \"close\" | \"error\" | \"message\",\n listener: (event: { readonly data?: unknown }) => void,\n ): void;\n send(data: string | Uint8Array<ArrayBuffer>): void;\n close(code?: number, reason?: string): void;\n}\n\nexport type RealtimeWebSocketFactory = (\n url: string,\n protocols?: string[],\n) => RealtimeWebSocket;\n\nexport interface RealtimeClientOptions {\n readonly url: string;\n readonly path?: string;\n readonly protocols?: ReadonlyArray<string>;\n readonly frameEncoding?: \"json\" | \"messagepack\";\n readonly requestTimeoutMs?: number;\n readonly reconnectBaseDelayMs?: number;\n readonly reconnectMaxDelayMs?: number;\n readonly random?: () => number;\n readonly webSocketFactory?: RealtimeWebSocketFactory;\n}\n\ninterface PendingRequest {\n readonly type: CommandType;\n readonly resolve: (data: unknown) => void;\n readonly reject: (error: Error) => void;\n readonly timeout: ReturnType<typeof setTimeout>;\n}\n\nexport class RealtimeRequestError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly retryable: boolean,\n readonly retryAfterMs?: number,\n ) {\n super(message);\n this.name = \"RealtimeRequestError\";\n }\n}\n\nconst normalizeUrl = (baseUrl: string, path: string): string => {\n const fallbackBase =\n typeof globalThis.location === \"undefined\"\n ? \"http://localhost\"\n : globalThis.location.href;\n\n const url = new URL(baseUrl, fallbackBase);\n\n if (url.protocol === \"http:\") url.protocol = \"ws:\";\n\n if (url.protocol === \"https:\") url.protocol = \"wss:\";\n url.pathname = path.startsWith(\"/\") ? path : `/${path}`;\n url.search = \"\";\n url.hash = \"\";\n\n return url.toString();\n};\n\nconst nativeWebSocketFactory: RealtimeWebSocketFactory = (url, protocols) =>\n new WebSocket(url, protocols);\n\nconst WEBSOCKET_OPEN = 1;\n\nconst scopeKey = (scope: SubscriptionScope): string =>\n JSON.stringify([\n scope.topic,\n scope.organizationId ?? null,\n scope.eventId ?? null,\n scope.world ?? null,\n scope.mapId ?? null,\n ]);\n\nconst toBytes = async (data: unknown): Promise<Uint8Array> => {\n if (data instanceof Uint8Array) return data;\n\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n\n if (data instanceof Blob) return new Uint8Array(await data.arrayBuffer());\n throw new Error(\"Gateway returned a non-binary realtime frame\");\n};\n\nconst getPresenceSessionId = (data: unknown): string | null => {\n if (!data || typeof data !== \"object\" || !(\"sessionId\" in data)) return null;\n\n return typeof data.sessionId === \"string\" ? data.sessionId : null;\n};\n\nexport class RealtimeClient {\n private readonly url: string;\n private readonly protocols?: string[];\n private readonly requestTimeoutMs: number;\n private readonly reconnectBaseDelayMs: number;\n private readonly reconnectMaxDelayMs: number;\n private readonly random: () => number;\n private readonly webSocketFactory: RealtimeWebSocketFactory;\n private readonly frameEncoding: \"json\" | \"messagepack\";\n private readonly eventListeners = new Set<(event: ServerEvent) => void>();\n private readonly stateListeners = new Set<\n (state: RealtimeConnectionState) => void\n >();\n private readonly pending = new Map<string, PendingRequest>();\n private readonly subscriptions = new Map<string, SubscriptionScope>();\n private socket: RealtimeWebSocket | null = null;\n private stateValue: RealtimeConnectionState = \"disconnected\";\n private joinData: CommandData<\"session.join\"> | null = null;\n private reconnectAttempt = 0;\n private reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\n private heartbeatTimeout: ReturnType<typeof setTimeout> | null = null;\n private presenceSessionId: string | null = null;\n private manuallyClosed = false;\n private messageChain = Promise.resolve();\n private rejoinHandler: (() => Promise<void>) | null = null;\n\n constructor(options: RealtimeClientOptions) {\n this.url = normalizeUrl(options.url, options.path ?? \"/ws\");\n this.protocols = options.protocols ? [...options.protocols] : undefined;\n this.requestTimeoutMs = options.requestTimeoutMs ?? 20_000;\n this.reconnectBaseDelayMs = options.reconnectBaseDelayMs ?? 1_000;\n this.reconnectMaxDelayMs = options.reconnectMaxDelayMs ?? 30_000;\n this.random = options.random ?? Math.random;\n this.webSocketFactory = options.webSocketFactory ?? nativeWebSocketFactory;\n this.frameEncoding = options.frameEncoding ?? \"messagepack\";\n }\n\n get state(): RealtimeConnectionState {\n return this.stateValue;\n }\n\n get connected(): boolean {\n return this.socket?.readyState === WEBSOCKET_OPEN;\n }\n\n connect(): void {\n if (this.socket && this.socket.readyState <= WEBSOCKET_OPEN) return;\n this.manuallyClosed = false;\n this.clearReconnect();\n this.open(this.reconnectAttempt > 0 ? \"reconnecting\" : \"connecting\");\n }\n\n disconnect(): void {\n this.manuallyClosed = true;\n this.clearReconnect();\n this.clearHeartbeat();\n this.rejectPending(new Error(\"Realtime client disconnected\"));\n const activeSocket = this.socket;\n this.socket = null;\n activeSocket?.close(1000, \"client disconnect\");\n this.setState(\"disconnected\");\n }\n\n subscribe(listener: (event: ServerEvent) => void): () => void {\n this.eventListeners.add(listener);\n\n return () => this.eventListeners.delete(listener);\n }\n\n subscribeState(\n listener: (state: RealtimeConnectionState) => void,\n ): () => void {\n this.stateListeners.add(listener);\n listener(this.stateValue);\n\n return () => this.stateListeners.delete(listener);\n }\n\n setReconnectHandler(handler: (() => Promise<void>) | null): void {\n this.rejoinHandler = handler;\n }\n\n join(data: CommandData<\"session.join\">): Promise<unknown> {\n this.joinData = data;\n\n return this.performJoin();\n }\n\n subscribeScope(scope: SubscriptionScope): Promise<unknown> {\n this.subscriptions.set(scopeKey(scope), scope);\n\n if (!this.connected || this.stateValue !== \"ready\") {\n return Promise.resolve(undefined);\n }\n\n return this.request(\"subscription.subscribe\", scope);\n }\n\n unsubscribeScope(scope: SubscriptionScope): Promise<unknown> {\n this.subscriptions.delete(scopeKey(scope));\n\n if (!this.connected || this.stateValue !== \"ready\") {\n return Promise.resolve(undefined);\n }\n\n return this.request(\"subscription.unsubscribe\", scope);\n }\n\n request<Type extends CommandType>(\n type: Type,\n data: CommandData<Type>,\n ): Promise<unknown> {\n const activeSocket = this.socket;\n\n if (!activeSocket || activeSocket.readyState !== WEBSOCKET_OPEN) {\n return Promise.reject(new Error(\"Realtime connection is not open\"));\n }\n\n const requestId = crypto.randomUUID();\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(requestId);\n reject(new Error(`Realtime request timed out: ${type}`));\n }, this.requestTimeoutMs);\n\n this.pending.set(requestId, { type, resolve, reject, timeout });\n\n try {\n // SAFETY: the command discriminator and payload are coupled by CommandData<Type>.\n activeSocket.send(\n this.encodeFrame({\n v: REALTIME_PROTOCOL_VERSION,\n type,\n requestId,\n data,\n } as ClientCommand),\n );\n } catch (error) {\n clearTimeout(timeout);\n this.pending.delete(requestId);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n });\n }\n\n send<Type extends CommandType>(type: Type, data: CommandData<Type>): void {\n const activeSocket = this.socket;\n\n if (!activeSocket || activeSocket.readyState !== WEBSOCKET_OPEN) return;\n // SAFETY: the command discriminator and payload are coupled by CommandData<Type>.\n activeSocket.send(\n this.encodeFrame({\n v: REALTIME_PROTOCOL_VERSION,\n type,\n data,\n } as ClientCommand),\n );\n }\n\n private open(state: \"connecting\" | \"reconnecting\"): void {\n this.setState(state);\n\n if (this.manuallyClosed) return;\n const socket = this.webSocketFactory(this.url, this.protocols);\n socket.binaryType = \"arraybuffer\";\n this.socket = socket;\n socket.addEventListener(\"open\", () => {\n if (this.socket !== socket) return;\n this.setState(\"connected\");\n\n if (this.joinData) {\n const rejoin =\n this.rejoinHandler ??\n (() => this.performJoin().then(() => undefined));\n\n void rejoin().catch(() => socket.close(4008, \"session rejoin failed\"));\n }\n });\n socket.addEventListener(\"message\", (event) => {\n this.messageChain = this.messageChain\n .then(() => this.handleMessage(event.data))\n .catch(() => socket.close(4007, \"malformed realtime frame\"));\n });\n socket.addEventListener(\"error\", () => {\n if (this.socket === socket) socket.close();\n });\n socket.addEventListener(\"close\", () => {\n if (this.socket !== socket) return;\n this.socket = null;\n this.clearHeartbeat();\n this.rejectPending(new Error(\"Realtime connection closed\"));\n this.setState(\"disconnected\");\n\n if (!this.manuallyClosed) this.scheduleReconnect();\n });\n }\n\n private async performJoin(): Promise<unknown> {\n if (!this.joinData || !this.connected) return undefined;\n this.setState(\"joining\");\n\n try {\n const result = await this.request(\"session.join\", this.joinData);\n await Promise.all(\n [...this.subscriptions.values()].map((scope) =>\n this.request(\"subscription.subscribe\", scope),\n ),\n );\n this.reconnectAttempt = 0;\n this.setState(\"ready\");\n\n return result;\n } catch (error) {\n if (this.connected) this.socket?.close(4008, \"session join failed\");\n throw error;\n }\n }\n\n private async handleMessage(data: unknown): Promise<void> {\n const frame = await this.decodeFrame(data);\n\n if (\"status\" in frame) {\n const pending = this.pending.get(frame.requestId);\n\n if (!pending) return;\n clearTimeout(pending.timeout);\n this.pending.delete(frame.requestId);\n\n if (frame.status === \"success\") {\n if (pending.type === \"presence.publish\") {\n this.presenceSessionId = getPresenceSessionId(frame.data);\n this.scheduleHeartbeat();\n }\n\n pending.resolve(frame.data);\n } else {\n pending.reject(\n new RealtimeRequestError(\n frame.error.code,\n frame.error.message,\n frame.error.retryable,\n frame.error.retryAfterMs,\n ),\n );\n }\n\n return;\n }\n\n if (!isServerEventFrame(frame)) return;\n\n for (const listener of this.eventListeners) listener(frame);\n }\n\n private encodeFrame(frame: ClientCommand): string | Uint8Array<ArrayBuffer> {\n return this.frameEncoding === \"json\"\n ? JSON.stringify(frame)\n : encodeRealtimeFrame(frame);\n }\n\n private async decodeFrame(data: unknown) {\n if (this.frameEncoding === \"json\") {\n if (typeof data !== \"string\")\n throw new Error(\"Gateway returned a non-text realtime frame\");\n\n return decodeRealtimeFrame(JSON.parse(data));\n }\n\n const decoded = tryDecodeRealtimeFrame(await toBytes(data));\n\n if (Result.isFailure(decoded)) throw decoded.failure;\n\n return decoded.success;\n }\n\n private scheduleReconnect(): void {\n this.reconnectAttempt += 1;\n\n const exponential = Math.min(\n this.reconnectMaxDelayMs,\n this.reconnectBaseDelayMs * 2 ** (this.reconnectAttempt - 1),\n );\n\n const jittered = Math.round(exponential * (0.5 + this.random()));\n this.setState(\"reconnecting\");\n this.reconnectTimeout = setTimeout(\n () => this.open(\"reconnecting\"),\n jittered,\n );\n }\n\n private scheduleHeartbeat(): void {\n this.clearHeartbeat();\n\n if (!this.presenceSessionId || !this.connected) return;\n this.heartbeatTimeout = setTimeout(() => {\n const sessionId = this.presenceSessionId;\n\n if (!sessionId) return;\n void this.request(\"presence.heartbeat\", { sessionId })\n .then(() => this.scheduleHeartbeat())\n .catch(() => this.socket?.close());\n }, PRESENCE_HEARTBEAT_INTERVAL_MS);\n }\n\n private rejectPending(error: Error): void {\n for (const pending of this.pending.values()) {\n clearTimeout(pending.timeout);\n pending.reject(error);\n }\n\n this.pending.clear();\n }\n\n private setState(state: RealtimeConnectionState): void {\n if (this.stateValue === state) return;\n this.stateValue = state;\n\n for (const listener of this.stateListeners) listener(state);\n }\n\n private clearReconnect(): void {\n if (this.reconnectTimeout) clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n private clearHeartbeat(): void {\n if (this.heartbeatTimeout) clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"realtime.js","names":["Schema","SchemaTransformation","CharacterIdSchema","decodeRealtimeFrame","TaggedErrorClass"],"sources":["../../schema/src/npc-type.ts","../../schema/src/permissions.ts","../../protocol/src/realtime/access-policy.ts","../../schema/src/item-rarity.ts","../../schema/src/loot.ts","../../schema/src/http-scalars.ts","../../protocol/src/loot-summary.ts","../../protocol/src/feed.ts","../../schema/src/primitives.ts","../../schema/src/party-ready-room.ts","../../schema/src/chat.ts","../../schema/src/air-tag.ts","../../schema/src/battle-ping.ts","../../schema/src/loot-split.ts","../../schema/src/npc-presence.ts","../../schema/src/map-ping.ts","../../protocol/src/loot-events.ts","../../protocol/src/realtime/protocol.ts","../../protocol/src/realtime/codec.ts","../../client/src/realtime/notify-listeners.ts","../../client/src/realtime/realtime-client.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\nexport const NpcTypeEnum = {\n COMMON: \"COMMON\",\n ELITE: \"ELITE\",\n ELITE2: \"ELITE2\",\n ELITE3: \"ELITE3\",\n HERO: \"HERO\",\n EVENT_HERO: \"EVENT_HERO\",\n COLOSSUS: \"COLOSSUS\",\n TITAN: \"TITAN\",\n HERO_TRACKER: \"HERO_TRACKER\",\n NPC: \"NPC\",\n} as const;\n\nexport type NpcTypeEnum = (typeof NpcTypeEnum)[keyof typeof NpcTypeEnum];\n\nexport const NpcTypeSchema = Schema.Literals([\n NpcTypeEnum.COMMON,\n NpcTypeEnum.ELITE,\n NpcTypeEnum.ELITE2,\n NpcTypeEnum.ELITE3,\n NpcTypeEnum.HERO,\n NpcTypeEnum.EVENT_HERO,\n NpcTypeEnum.COLOSSUS,\n NpcTypeEnum.TITAN,\n NpcTypeEnum.HERO_TRACKER,\n NpcTypeEnum.NPC,\n]);\n","import { Schema } from \"effect\";\n\nexport const Capability = {\n OWNER: \"OWNER\",\n ADMIN: \"ADMIN\",\n LOOTLOG_MANAGE: \"LOOTLOG_MANAGE\",\n LOOTLOG_ACCESS: \"LOOTLOG_ACCESS\",\n LOOTLOG_LOOTS_READ: \"LOOTLOG_LOOTS_READ\",\n LOOTLOG_LOOTS_WRITE: \"LOOTLOG_LOOTS_WRITE\",\n LOOTLOG_LOOTS_ARCHIVE: \"LOOTLOG_LOOTS_ARCHIVE\",\n LOOTLOG_LOOTS_TITANS_READ: \"LOOTLOG_LOOTS_TITANS_READ\",\n LOOTLOG_LOOTS_HEROES_READ: \"LOOTLOG_LOOTS_HEROES_READ\",\n LOOTLOG_TIMERS_READ: \"LOOTLOG_TIMERS_READ\",\n LOOTLOG_TIMERS_WRITE: \"LOOTLOG_TIMERS_WRITE\",\n LOOTLOG_TIMERS_RESET: \"LOOTLOG_TIMERS_RESET\",\n LOOTLOG_TIMERS_DELETE: \"LOOTLOG_TIMERS_DELETE\",\n LOOTLOG_TIMERS_TITANS_READ: \"LOOTLOG_TIMERS_TITANS_READ\",\n LOOTLOG_TIMERS_HEROES_READ: \"LOOTLOG_TIMERS_HEROES_READ\",\n LOOTLOG_RESERVATIONS_READ: \"LOOTLOG_RESERVATIONS_READ\",\n LOOTLOG_RESERVATIONS_WRITE: \"LOOTLOG_RESERVATIONS_WRITE\",\n LOOTLOG_MEMBERS_READ: \"LOOTLOG_MEMBERS_READ\",\n LOOTLOG_ONLINE_PLAYERS_READ: \"LOOTLOG_ONLINE_PLAYERS_READ\",\n LOOTLOG_PRESENCE_LOCATION_READ: \"LOOTLOG_PRESENCE_LOCATION_READ\",\n LOOTLOG_CHAT_READ: \"LOOTLOG_CHAT_READ\",\n LOOTLOG_CHAT_WRITE: \"LOOTLOG_CHAT_WRITE\",\n LOOTLOG_CHAT_TITANS_READ: \"LOOTLOG_CHAT_TITANS_READ\",\n LOOTLOG_CHAT_HEROES_READ: \"LOOTLOG_CHAT_HEROES_READ\",\n LOOTLOG_NOTIFICATIONS_READ: \"LOOTLOG_NOTIFICATIONS_READ\",\n LOOTLOG_NOTIFICATIONS_SEND: \"LOOTLOG_NOTIFICATIONS_SEND\",\n LOOTLOG_NOTIFICATIONS_TITANS_READ: \"LOOTLOG_NOTIFICATIONS_TITANS_READ\",\n LOOTLOG_NOTIFICATIONS_HEROES_READ: \"LOOTLOG_NOTIFICATIONS_HEROES_READ\",\n LOOTLOG_EVENTS_MANAGE: \"LOOTLOG_EVENTS_MANAGE\",\n LOOTLOG_EVENTS_READ: \"LOOTLOG_EVENTS_READ\",\n LOOTLOG_EVENTS_WRITE: \"LOOTLOG_EVENTS_WRITE\",\n LOOTLOG_DOCS_READ: \"LOOTLOG_DOCS_READ\",\n LOOTLOG_DOCS_WRITE: \"LOOTLOG_DOCS_WRITE\",\n} as const;\n\nexport type Capability = (typeof Capability)[keyof typeof Capability];\n\nexport const Permission = Capability;\n\nexport type Permission = Capability;\n\nexport const CapabilitySchema = Schema.Literals(Object.values(Capability));\n\nexport const PermissionSchema = CapabilitySchema;\n\nconst UserGuildPermissionsRoleSchema = Schema.Struct({\n id: Schema.NonEmptyString,\n lvlRangeFrom: Schema.Int,\n lvlRangeTo: Schema.Int,\n permissions: Schema.Array(PermissionSchema),\n});\n\nconst UserGuildPermissionsGuildSchema = Schema.Struct({\n id: Schema.NonEmptyString,\n ownerId: Schema.NonEmptyString,\n});\n\nexport const UserGuildPermissionsDtoSchema = Schema.Struct({\n guild: UserGuildPermissionsGuildSchema,\n roles: Schema.Array(UserGuildPermissionsRoleSchema),\n});\n","import { getNpcTypeRoutingTier } from \"@lootlog/schema/npc-routing\";\nimport { NpcTypeSchema } from \"@lootlog/schema/npc-type\";\nimport { Permission, PermissionSchema } from \"@lootlog/schema/permissions\";\nimport { Schema } from \"effect\";\n\nconst LevelRange = Schema.Struct({ from: Schema.Int, to: Schema.Int });\n\nconst AREAS = [\n \"timers\",\n \"chat\",\n \"notifications\",\n \"presence\",\n \"reservations\",\n \"loots\",\n \"events\",\n \"organization\",\n] as const;\n\nconst AccessPolicyArea = Schema.Literals(AREAS);\n\ntype AccessPolicyArea = typeof AccessPolicyArea.Type;\n\nexport const OrganizationAccessPolicy = Schema.Struct({\n organizationId: Schema.NonEmptyString,\n owner: Schema.Boolean,\n permissions: Schema.Array(PermissionSchema),\n grants: Schema.Array(\n Schema.Struct({\n permission: PermissionSchema,\n ranges: Schema.Array(LevelRange),\n }),\n ),\n});\n\nexport type OrganizationAccessPolicy = typeof OrganizationAccessPolicy.Type;\n\nexport const AccessPolicySnapshot = Schema.Struct({\n version: Schema.NonEmptyString,\n organizations: Schema.Array(OrganizationAccessPolicy),\n});\n\nexport type AccessPolicySnapshot = typeof AccessPolicySnapshot.Type;\n\nexport const isAccessPolicySnapshot = Schema.is(AccessPolicySnapshot);\n\nexport const AccessPolicyChange = Schema.Struct({\n organizationId: Schema.NonEmptyString,\n areas: Schema.Array(AccessPolicyArea),\n restricted: Schema.Boolean,\n expanded: Schema.Boolean,\n});\n\nexport type AccessPolicyChange = typeof AccessPolicyChange.Type;\n\ntype Range = typeof LevelRange.Type;\n\ntype GuildPolicy = {\n readonly guild: { readonly id: string; readonly ownerId: string };\n readonly roles: readonly {\n readonly permissions: readonly Permission[];\n readonly lvlRangeFrom: number;\n readonly lvlRangeTo: number;\n }[];\n};\n\nconst NPC_PERMISSIONS = {\n timers: [\n Permission.LOOTLOG_TIMERS_READ,\n Permission.LOOTLOG_TIMERS_HEROES_READ,\n Permission.LOOTLOG_TIMERS_TITANS_READ,\n ],\n chat: [\n Permission.LOOTLOG_CHAT_READ,\n Permission.LOOTLOG_CHAT_HEROES_READ,\n Permission.LOOTLOG_CHAT_TITANS_READ,\n ],\n notifications: [\n Permission.LOOTLOG_NOTIFICATIONS_READ,\n Permission.LOOTLOG_NOTIFICATIONS_HEROES_READ,\n Permission.LOOTLOG_NOTIFICATIONS_TITANS_READ,\n ],\n loots: [\n Permission.LOOTLOG_LOOTS_READ,\n Permission.LOOTLOG_LOOTS_HEROES_READ,\n Permission.LOOTLOG_LOOTS_TITANS_READ,\n ],\n} as const;\n\nconst RANGE_PERMISSIONS = Object.values(NPC_PERMISSIONS).flat();\n\nconst LOOT_RANGE_PERMISSIONS = new Set<Permission>(NPC_PERMISSIONS.loots);\n\nconst ALL_PERMISSIONS = Object.values(Permission).sort();\n\nconst isNpcType = Schema.is(NpcTypeSchema);\n\nconst mergeRanges = (ranges: Range[]): Range[] => {\n const merged: Array<{ from: number; to: number }> = [];\n\n for (const range of ranges.sort((a, b) => a.from - b.from || a.to - b.to)) {\n if (range.from > range.to) continue;\n const last = merged[merged.length - 1];\n\n // NPC event levels accept finite numbers, so integer-adjacent ranges retain a fractional gap.\n if (last && range.from <= last.to) last.to = Math.max(last.to, range.to);\n else merged.push({ ...range });\n }\n\n return merged;\n};\n\n/** Canonical effective grants: role identifiers, role ordering, and overlapping grants do not change the version. */\nexport const createAccessPolicySnapshot = (\n guilds: readonly GuildPolicy[],\n discordId: string,\n): AccessPolicySnapshot => {\n const organizations = guilds\n .map(({ guild, roles }): OrganizationAccessPolicy => {\n const owner = guild.ownerId === discordId;\n const explicit = new Set(roles.flatMap((role) => role.permissions));\n const administrator = owner || explicit.has(Permission.ADMIN);\n\n const permissions = administrator\n ? ALL_PERMISSIONS.filter(\n (permission) => owner || permission !== Permission.OWNER,\n )\n : [...explicit].sort();\n\n const grants = RANGE_PERMISSIONS.map((permission) => {\n const bypass =\n owner || (administrator && !LOOT_RANGE_PERMISSIONS.has(permission));\n\n const ranges = bypass\n ? [{ from: 0, to: Number.MAX_SAFE_INTEGER }]\n : mergeRanges(\n roles\n .filter(\n (role) =>\n role.permissions.includes(permission) &&\n (!LOOT_RANGE_PERMISSIONS.has(permission) ||\n role.permissions.includes(Permission.LOOTLOG_LOOTS_READ)),\n )\n .map((role) => ({\n from: role.lvlRangeFrom,\n to: role.lvlRangeTo,\n })),\n );\n\n return { permission, ranges };\n })\n .filter(({ ranges }) => ranges.length > 0)\n .sort((a, b) => a.permission.localeCompare(b.permission));\n\n return { organizationId: guild.id, owner, permissions, grants };\n })\n .sort((a, b) => a.organizationId.localeCompare(b.organizationId));\n\n return { version: JSON.stringify(organizations), organizations };\n};\n\nconst permissionArea = (permission: Permission): AccessPolicyArea => {\n if (permission.startsWith(\"LOOTLOG_TIMERS_\")) return \"timers\";\n\n if (permission.startsWith(\"LOOTLOG_CHAT_\")) return \"chat\";\n\n if (permission.startsWith(\"LOOTLOG_NOTIFICATIONS_\")) return \"notifications\";\n\n if (permission.startsWith(\"LOOTLOG_LOOTS_\")) return \"loots\";\n\n if (permission.startsWith(\"LOOTLOG_RESERVATIONS_\")) return \"reservations\";\n\n if (permission.startsWith(\"LOOTLOG_EVENTS_\")) return \"events\";\n\n if (\n permission === Permission.LOOTLOG_ONLINE_PLAYERS_READ ||\n permission === Permission.LOOTLOG_PRESENCE_LOCATION_READ\n )\n return \"presence\";\n\n return \"organization\";\n};\n\nconst includesArea = (\n target: OrganizationAccessPolicy,\n source: OrganizationAccessPolicy,\n area: AccessPolicyArea,\n): boolean =>\n source.permissions\n .filter((permission) => permissionArea(permission) === area)\n .every((permission) => target.permissions.includes(permission)) &&\n source.grants\n .filter(({ permission }) => permissionArea(permission) === area)\n .every(({ permission, ranges }) => {\n const targetRanges =\n target.grants.find((grant) => grant.permission === permission)\n ?.ranges ?? [];\n\n return ranges.every((range) =>\n targetRanges.some(\n (candidate) =>\n candidate.from <= range.from && candidate.to >= range.to,\n ),\n );\n });\n\n/** Compare the local snapshot, including after reconnect; the event's delta may refer to a newer server baseline. */\nexport const diffAccessPolicies = (\n previous: AccessPolicySnapshot,\n next: AccessPolicySnapshot,\n): AccessPolicyChange[] => {\n if (previous.version === next.version) return [];\n\n const before = new Map(\n previous.organizations.map((organization) => [\n organization.organizationId,\n organization,\n ]),\n );\n\n const after = new Map(\n next.organizations.map((organization) => [\n organization.organizationId,\n organization,\n ]),\n );\n\n const changes: AccessPolicyChange[] = [];\n\n for (const organizationId of new Set([...before.keys(), ...after.keys()])) {\n const oldPolicy = before.get(organizationId);\n const newPolicy = after.get(organizationId);\n\n if (!oldPolicy || !newPolicy) {\n changes.push({\n organizationId,\n areas: [...AREAS],\n restricted: !newPolicy,\n expanded: !oldPolicy,\n });\n continue;\n }\n\n for (const area of AREAS) {\n const restricted = !includesArea(newPolicy, oldPolicy, area);\n const expanded = !includesArea(oldPolicy, newPolicy, area);\n\n if (restricted || expanded)\n changes.push({ organizationId, areas: [area], restricted, expanded });\n }\n }\n\n return changes;\n};\n\nexport const canReadPolicyNpc = (\n organization: OrganizationAccessPolicy,\n area: \"timers\" | \"chat\" | \"notifications\",\n npc: { readonly type: string; readonly lvl: number } | null,\n): boolean => {\n if (area === \"timers\" && npc === null) return false;\n\n if (npc && (!Number.isFinite(npc.lvl) || npc.lvl < 0 || !isNpcType(npc.type)))\n return false;\n\n if (organization.owner || organization.permissions.includes(Permission.ADMIN))\n return true;\n const [base, heroes, titans] = NPC_PERMISSIONS[area];\n\n if (!organization.permissions.includes(base)) return false;\n\n if (npc === null) return true;\n\n if (!isNpcType(npc.type)) return false;\n const permission = { base, heroes, titans }[getNpcTypeRoutingTier(npc.type)];\n\n return (\n organization.grants\n .find((grant) => grant.permission === permission)\n ?.ranges.some(({ from, to }) => from <= npc.lvl && to >= npc.lvl) ?? false\n );\n};\n","import { Schema } from \"effect\";\n\nexport const ItemRarityEnum = {\n UNIQUE: \"UNIQUE\",\n HEROIC: \"HEROIC\",\n LEGENDARY: \"LEGENDARY\",\n UPGRADED: \"UPGRADED\",\n} as const;\n\nexport type ItemRarityEnum =\n (typeof ItemRarityEnum)[keyof typeof ItemRarityEnum];\n\nexport const ItemRaritySchema = Schema.Literals([\n ItemRarityEnum.UNIQUE,\n ItemRarityEnum.HEROIC,\n ItemRarityEnum.LEGENDARY,\n ItemRarityEnum.UPGRADED,\n]);\n","import { Schema } from \"effect\";\n\nexport const LootSourceEnum = {\n LOOTBOX: \"LOOTBOX\",\n DIALOG: \"DIALOG\",\n FIGHT: \"FIGHT\",\n} as const;\n\nexport type LootSourceEnum =\n (typeof LootSourceEnum)[keyof typeof LootSourceEnum];\n\nexport const LootSourceSchema = Schema.Literals([\n LootSourceEnum.LOOTBOX,\n LootSourceEnum.DIALOG,\n LootSourceEnum.FIGHT,\n]);\n\nexport const LootShareSourceEnum = {\n NONE: \"NONE\",\n ITEM_OWNER: \"ITEM_OWNER\",\n CHAT_MESSAGE: \"CHAT_MESSAGE\",\n} as const;\n\nexport type LootShareSourceEnum =\n (typeof LootShareSourceEnum)[keyof typeof LootShareSourceEnum];\n\nexport const ProfessionEnum = {\n WARRIOR: \"WARRIOR\",\n PALADIN: \"PALADIN\",\n HUNTER: \"HUNTER\",\n MAGE: \"MAGE\",\n BLADE_DANCER: \"BLADE_DANCER\",\n TRACKER: \"TRACKER\",\n} as const;\n\nexport type ProfessionEnum =\n (typeof ProfessionEnum)[keyof typeof ProfessionEnum];\n\nexport const ProfessionSchema = Schema.Literals([\n ProfessionEnum.WARRIOR,\n ProfessionEnum.PALADIN,\n ProfessionEnum.HUNTER,\n ProfessionEnum.MAGE,\n ProfessionEnum.BLADE_DANCER,\n ProfessionEnum.TRACKER,\n]);\n\nexport const ItemTypeEnum = {\n ONE_HAND_WEAPON: \"ONE_HAND_WEAPON\",\n TWO_HAND_WEAPON: \"TWO_HAND_WEAPON\",\n ONE_AND_HALF_HAND_WEAPON: \"ONE_AND_HALF_HAND_WEAPON\",\n DISTANCE_WEAPON: \"DISTANCE_WEAPON\",\n HELP_WEAPON: \"HELP_WEAPON\",\n WAND_WEAPON: \"WAND_WEAPON\",\n ORB_WEAPON: \"ORB_WEAPON\",\n ARMOR: \"ARMOR\",\n HELMET: \"HELMET\",\n BOOTS: \"BOOTS\",\n GLOVES: \"GLOVES\",\n RING: \"RING\",\n NECKLACE: \"NECKLACE\",\n SHIELD: \"SHIELD\",\n NEUTRAL: \"NEUTRAL\",\n CONSUME: \"CONSUME\",\n GOLD: \"GOLD\",\n KEYS: \"KEYS\",\n QUEST: \"QUEST\",\n RENEWABLE: \"RENEWABLE\",\n ARROWS: \"ARROWS\",\n TALISMAN: \"TALISMAN\",\n BOOK: \"BOOK\",\n BAG: \"BAG\",\n BLESS: \"BLESS\",\n UPGRADE: \"UPGRADE\",\n RECIPE: \"RECIPE\",\n COINAGE: \"COINAGE\",\n QUIVER: \"QUIVER\",\n OUTFITS: \"OUTFITS\",\n PETS: \"PETS\",\n TELEPORTS: \"TELEPORTS\",\n} as const;\n\nexport type ItemTypeEnum = (typeof ItemTypeEnum)[keyof typeof ItemTypeEnum];\n","import * as Schema from \"effect/Schema\";\nimport * as SchemaTransformation from \"effect/SchemaTransformation\";\nimport { NpcTypeSchema } from \"./npc-type.js\";\n\nexport const FiniteNumber = Schema.Number.check(\n Schema.isFinite().annotate({ expected: \"a finite number\" }),\n);\n\nconst dateTimeString = (pattern: string) =>\n Schema.String.annotate({ format: \"date-time\" }).check(\n Schema.isPattern(new RegExp(pattern, \"u\")).annotate({\n expected: `a string matching the RegExp ${pattern}`,\n }),\n );\n\nconst dateTimePattern = (timeZonePattern: string) =>\n `^(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))T(?:(?:[01]\\\\d|2[0-3]):[0-5]\\\\d(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?(?:${timeZonePattern}))$`;\n\n/** Strict ISO-8601 UTC date-time pattern shared by HTTP and domain schemas. */\nexport const DATE_TIME_STRING_PATTERN = dateTimePattern(\"Z\");\n\nexport const DateTimeString = dateTimeString(DATE_TIME_STRING_PATTERN);\n\nexport const DateTimeWithOffsetString = dateTimeString(\n dateTimePattern(\"Z|([+-](?:[01]\\\\d|2[0-3]):[0-5]\\\\d)\"),\n);\n\nexport const NonEmptyString = Schema.String.check(\n Schema.isMinLength(1).annotate({\n expected: \"a value with a length of at least 1\",\n }),\n);\n\nexport const JsonValue = Schema.Json.annotate({ expected: \"JSON value\" });\n\nconst boundedInteger = (minimum: number, maximum: number) =>\n Schema.Number.check(Schema.isInt().annotate({ expected: \"an integer\" }))\n .check(\n Schema.isGreaterThanOrEqualTo(minimum).annotate({\n expected: `a value greater than or equal to ${minimum}`,\n }),\n )\n .check(\n Schema.isLessThanOrEqualTo(maximum).annotate({\n expected: `a value less than or equal to ${maximum}`,\n }),\n );\n\nexport const SafeInteger = boundedInteger(-9007199254740991, 9007199254740991);\n\nexport const PositiveSafeInteger = boundedInteger(1, 9007199254740991);\n\nexport const NonNegativeSafeInteger = boundedInteger(0, 9007199254740991);\n\nexport const LevelFilter = boundedInteger(0, 500);\n\nexport const PageSize = boundedInteger(1, 100);\n\n/** Rejects a level filter whose lower bound exceeds its upper bound. */\nexport const levelRangeCheck = <Min extends string, Max extends string>(\n minKey: Min,\n maxKey: Max,\n) =>\n Schema.makeFilter<{ readonly [K in Min | Max]?: number }>((data) => {\n const min = data[minKey];\n const max = data[maxKey];\n\n return min === undefined || max === undefined || min <= max\n ? undefined\n : { path: [minKey], issue: `${minKey} must be <= ${maxKey}` };\n });\n\n/** Every filter by NPC level uses `npcLevelMin`/`npcLevelMax`. */\nexport const NpcLevelRange = {\n fields: {\n npcLevelMin: Schema.optionalKey(LevelFilter),\n npcLevelMax: Schema.optionalKey(LevelFilter),\n },\n check: levelRangeCheck(\"npcLevelMin\", \"npcLevelMax\"),\n};\n\n/** Repeated `npcTypes` query values; an unknown type is a 400. */\nexport const NpcTypes = Schema.Array(NpcTypeSchema);\n\n/** Time window of a statistics read, counted back from now. */\nexport const Period = Schema.Literals([\n \"24h\",\n \"3d\",\n \"7d\",\n \"14d\",\n \"30d\",\n \"90d\",\n \"180d\",\n \"all\",\n]).annotate({ default: \"7d\" });\n\nexport type Period = typeof Period.Type;\n\nexport const DEFAULT_PERIOD: Period = \"7d\";\n\n/** `true`/`false` query flag. */\nexport const BooleanQuery = Schema.Boolean;\n\nexport const WORLD_MAX_LENGTH = 64;\n\n/**\n * Margonem world in a path or filter, trimmed and lower-cased like stored\n * worlds. Length limits sit on the encoded string so OpenAPI documents them.\n */\nexport const WorldParam = Schema.String.check(\n Schema.isMinLength(1),\n Schema.isMaxLength(WORLD_MAX_LENGTH),\n)\n .pipe(\n Schema.decode(SchemaTransformation.trim()),\n Schema.decode(SchemaTransformation.toLowerCase()),\n )\n .check(Schema.isMinLength(1).annotate({ expected: \"a non-empty world\" }));\n\nexport const SEARCH_TEXT_MAX_LENGTH = 100;\n\n/**\n * Free-text search, trimmed. Match it with a LIKE pattern built by the API's\n * `containsPattern`, which escapes `%`, `_` and `\\`.\n */\nexport const SearchText = Schema.String.check(\n Schema.isMaxLength(SEARCH_TEXT_MAX_LENGTH),\n).pipe(Schema.decode(SchemaTransformation.trim()));\n\n/** Opaque continuation token returned as `nextCursor` by a paginated list. */\nexport const PageCursor = Schema.String.check(\n Schema.isMinLength(1),\n Schema.isMaxLength(512),\n);\n\n/** One page of a list: `nextCursor` is null on the last page. */\nexport const Page = <Item extends Schema.Top>(item: Item) =>\n Schema.Struct({\n items: Schema.Array(item),\n nextCursor: Schema.NullOr(Schema.String),\n });\n","import { ItemRaritySchema } from \"@lootlog/schema/item-rarity\";\nimport { LootSourceSchema, ProfessionSchema } from \"@lootlog/schema/loot\";\nimport { NpcTypeSchema } from \"@lootlog/schema/npc-type\";\nimport { Schema } from \"effect\";\nimport {\n FiniteNumber,\n NonEmptyString,\n PositiveSafeInteger,\n} from \"@lootlog/schema/http-scalars\";\n\nexport const MapPlayersSnapshot = Schema.Array(\n Schema.Struct({\n accountId: PositiveSafeInteger,\n characterId: PositiveSafeInteger,\n name: NonEmptyString,\n prof: Schema.NullOr(ProfessionSchema),\n icon: Schema.NullOr(Schema.String),\n }),\n).check(Schema.isMinLength(1));\n\nexport type MapPlayersSnapshot = typeof MapPlayersSnapshot.Type;\n\nexport const LootItemResponse = Schema.Struct({\n id: FiniteNumber,\n hid: Schema.String,\n name: Schema.String,\n icon: Schema.String,\n stat: Schema.String,\n type: Schema.NullOr(Schema.String),\n rarity: Schema.NullOr(ItemRaritySchema),\n lvl: FiniteNumber,\n prof: Schema.Array(ProfessionSchema),\n});\n\nexport const LootPlayerResponse = Schema.Struct({\n id: Schema.Union([Schema.String, FiniteNumber]),\n name: Schema.String,\n lvl: Schema.NullOr(FiniteNumber),\n prof: Schema.NullOr(ProfessionSchema),\n icon: Schema.NullOr(Schema.String),\n characterId: Schema.NullOr(FiniteNumber),\n accountId: Schema.NullOr(FiniteNumber),\n hpp: Schema.NullOr(FiniteNumber),\n});\n\nexport const LootNpcResponse = Schema.Struct({\n id: FiniteNumber,\n name: Schema.String,\n wt: Schema.NullOr(FiniteNumber),\n lvl: Schema.NullOr(FiniteNumber),\n prof: Schema.NullOr(ProfessionSchema),\n icon: Schema.NullOr(Schema.String),\n type: Schema.NullOr(NpcTypeSchema),\n margonemType: Schema.NullOr(FiniteNumber),\n});\n\nexport const LootShareResponse = Schema.Record(\n Schema.String,\n Schema.Array(Schema.String),\n);\n\nexport const LootSummary = Schema.Struct({\n items: Schema.Array(LootItemResponse),\n players: Schema.Array(LootPlayerResponse),\n npcs: Schema.Array(LootNpcResponse),\n lootShare: LootShareResponse,\n location: Schema.String,\n});\n\nexport type LootSummary = typeof LootSummary.Type;\n\n/** Same shape as the HTTP `MemberSummary`. */\nconst LootMember = Schema.Struct({\n id: Schema.Number,\n name: Schema.String,\n avatar: Schema.NullOr(Schema.String),\n userId: Schema.String,\n});\n\nconst LootSubmission = Schema.Struct({\n guildId: Schema.String,\n memberId: Schema.Number,\n lootId: Schema.Number,\n member: LootMember,\n});\n\n/** One Organization's view of a loot, as its HTTP list and detail responses encode it. */\nexport const LootSnapshot = Schema.Struct({\n id: Schema.Number,\n uniqueId: Schema.String,\n world: Schema.String,\n source: LootSourceSchema,\n location: Schema.String,\n items: Schema.Array(LootItemResponse),\n players: Schema.Array(LootPlayerResponse),\n mapPlayersSnapshot: Schema.NullOr(MapPlayersSnapshot),\n npcs: Schema.Array(LootNpcResponse),\n lootShare: LootShareResponse,\n createdAt: Schema.String,\n updatedAt: Schema.String,\n submissions: Schema.optionalKey(Schema.Array(LootSubmission)),\n commentsCount: Schema.Number,\n // Publishers before likes omit them.\n likes: Schema.optionalKey(Schema.Array(LootMember)),\n});\n\nexport type LootSnapshot = typeof LootSnapshot.Type;\n","import { LootSummary } from \"./loot-summary.js\";\nimport {\n FiniteNumber,\n PositiveSafeInteger,\n} from \"@lootlog/schema/http-scalars\";\nimport { Schema } from \"effect\";\n\nconst FeedNpc = Schema.Struct({\n id: FiniteNumber,\n name: Schema.String,\n type: Schema.NullOr(Schema.String),\n lvl: Schema.NullOr(FiniteNumber),\n icon: Schema.NullOr(Schema.String),\n prof: Schema.optionalKey(Schema.NullOr(Schema.String)),\n});\n\nconst common = {\n id: Schema.String,\n version: PositiveSafeInteger,\n groupKey: Schema.optionalKey(Schema.String),\n occurredAt: Schema.String,\n world: Schema.String,\n guild: Schema.Struct({\n id: Schema.String,\n name: Schema.String,\n vanityUrl: Schema.NullOr(Schema.String),\n }),\n npc: Schema.NullOr(FeedNpc),\n};\n\nexport const UserFeedItem = Schema.Union([\n Schema.Struct({\n ...common,\n type: Schema.Literal(\"kill\"),\n npc: FeedNpc,\n count: PositiveSafeInteger,\n }),\n Schema.Struct({\n ...common,\n type: Schema.Literal(\"loot\"),\n lootId: PositiveSafeInteger,\n summary: Schema.optionalKey(LootSummary),\n additionalItemsCount: FiniteNumber,\n items: Schema.Array(\n Schema.Struct({\n id: FiniteNumber,\n name: Schema.String,\n icon: Schema.String,\n rarity: Schema.NullOr(Schema.String),\n stat: Schema.optionalKey(Schema.String),\n type: Schema.optionalKey(Schema.NullOr(Schema.String)),\n lvl: Schema.optionalKey(Schema.NullOr(FiniteNumber)),\n }),\n ),\n }),\n]);\n\nexport type UserFeedItem = typeof UserFeedItem.Type;\n","import { Schema, SchemaTransformation } from \"effect\";\n\nimport { DATE_TIME_STRING_PATTERN } from \"./http-scalars.js\";\n\nexport const NonNegativeInt = Schema.Int.check(\n Schema.isGreaterThanOrEqualTo(0),\n);\n\nconst isoDateTimePattern = new RegExp(DATE_TIME_STRING_PATTERN, \"u\");\n\n/** A JavaScript Date encoded as the existing HTTP ISO-8601 string format. */\nexport const IsoDateTime = Schema.String.annotate({\n format: \"date-time\",\n}).pipe(\n Schema.check(Schema.isPattern(isoDateTimePattern)),\n Schema.decodeTo(Schema.Date, SchemaTransformation.dateFromString),\n);\n\nexport type IsoDateTime = typeof IsoDateTime.Type;\n","import { Schema } from \"effect\";\nimport {\n DateTimeString,\n FiniteNumber,\n NonEmptyString,\n NonNegativeSafeInteger,\n PositiveSafeInteger,\n} from \"./http-scalars.js\";\n\nconst PARTY_READY_ROOM_STATUSES = [\"ACTIVE\", \"CANCELLED\"] as const;\n\nexport const PARTY_READY_ROOM_PARTY_PRESENCE_STATES = [\n \"OUTSIDE\",\n \"IN_PARTY\",\n] as const;\n\nexport type PartyReadyRoomStatus = (typeof PARTY_READY_ROOM_STATUSES)[number];\n\ntype PartyReadyRoomPartyPresenceState =\n (typeof PARTY_READY_ROOM_PARTY_PRESENCE_STATES)[number];\n\ninterface PartyReadyRoomClan {\n id?: number;\n name?: string;\n}\n\nexport interface PartyReadyRoomCharacter {\n accountId: string;\n characterId: string;\n icon: string;\n lvl: number;\n nick: string;\n prof: string;\n clan?: PartyReadyRoomClan;\n}\n\nexport interface PartyReadyRoomParticipant {\n participantId: string;\n discordId: string;\n character: PartyReadyRoomCharacter;\n partyPresence: PartyReadyRoomPartyPresenceState;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface PartyReadyRoomProjectionBase {\n npc?: PartyGatheringNpc;\n schemaVersion: 3;\n notificationId: string;\n organizerDiscordId: string;\n organizerCharacter: PartyReadyRoomCharacter;\n guildIds: string[];\n world: string;\n description?: string;\n minLvl?: number;\n maxLvl?: number;\n partyMemberCount?: number;\n partyState?: PartyGatheringPartyState;\n volunteers?: ReadonlyArray<PartyGatheringVolunteer>;\n status: \"ACTIVE\";\n revision: number;\n createdAt: string;\n updatedAt: string;\n expiresAt: string;\n}\n\nexport type PartyReadyRoomOrganizerProjection =\n typeof PartyReadyRoomOrganizerProjectionSchema.Type;\n\nexport type PartyReadyRoomParticipantProjection =\n typeof PartyReadyRoomParticipantProjectionSchema.Type;\n\nexport type PartyReadyRoomProjection =\n typeof PartyReadyRoomProjectionSchema.Type;\n\nexport type PartyReadyRoomClientUpdate =\n typeof PartyReadyRoomClientUpdateSchema.Type;\n\nexport interface PartyReadyRoomUpdateEnvelope {\n recipientDiscordId: string;\n eligibleGuildIds: string[];\n update: PartyReadyRoomClientUpdate;\n}\n\nexport interface PartyReadyRoomInvitationTarget {\n participantId: string;\n characterId: string;\n}\n\nconst PartyReadyRoomClanSchema = Schema.Struct({\n id: Schema.optionalKey(Schema.Number),\n name: Schema.optionalKey(Schema.String),\n});\n\nconst PartyReadyRoomCharacterSchema = Schema.Struct({\n accountId: Schema.String,\n characterId: Schema.String,\n icon: Schema.String,\n lvl: Schema.Number,\n nick: Schema.String,\n prof: Schema.String,\n clan: Schema.optionalKey(PartyReadyRoomClanSchema),\n});\n\nconst PartyReadyRoomParticipantSchema = Schema.Struct({\n participantId: Schema.String,\n discordId: Schema.String,\n character: PartyReadyRoomCharacterSchema,\n partyPresence: Schema.Literals(PARTY_READY_ROOM_PARTY_PRESENCE_STATES),\n createdAt: Schema.String,\n updatedAt: Schema.String,\n});\n\nexport const PartyGatheringNpcSchema = Schema.Struct({\n prof: Schema.optionalKey(Schema.String),\n icon: Schema.optionalKey(Schema.String),\n name: Schema.String,\n location: Schema.String,\n lvl: Schema.Number,\n type: Schema.String,\n x: Schema.optionalKey(Schema.Number),\n y: Schema.optionalKey(Schema.Number),\n});\n\nexport type PartyGatheringNpc = typeof PartyGatheringNpcSchema.Type;\n\nexport const PartyGatheringCharacterSchema = Schema.Struct({\n characterId: NonEmptyString.check(Schema.isMaxLength(255)),\n nick: Schema.String.check(Schema.isMaxLength(255)),\n icon: Schema.String.check(Schema.isMaxLength(2048)),\n lvl: FiniteNumber,\n prof: Schema.String.check(Schema.isMaxLength(100)),\n});\n\nexport type PartyGatheringCharacter = typeof PartyGatheringCharacterSchema.Type;\n\nexport const PartyGatheringPartyMemberSchema = Schema.Struct({\n characterId: PartyGatheringCharacterSchema.fields.characterId,\n nick: Schema.optionalKey(PartyGatheringCharacterSchema.fields.nick),\n icon: Schema.optionalKey(PartyGatheringCharacterSchema.fields.icon),\n lvl: Schema.optionalKey(PartyGatheringCharacterSchema.fields.lvl),\n prof: Schema.optionalKey(PartyGatheringCharacterSchema.fields.prof),\n});\n\nexport type PartyGatheringPartyMember =\n typeof PartyGatheringPartyMemberSchema.Type;\n\nexport const PartyGatheringPartyStateSchema = Schema.Union([\n Schema.Struct({ status: Schema.Literal(\"UNKNOWN\") }),\n Schema.Struct({\n status: Schema.Literal(\"OBSERVED\"),\n observedAt: DateTimeString,\n members: Schema.Array(PartyGatheringPartyMemberSchema).check(\n Schema.isMaxLength(20),\n ),\n }),\n]);\n\nexport type PartyGatheringPartyState =\n typeof PartyGatheringPartyStateSchema.Type;\n\n// Viewers show an observed party as stale once `observedAt` is this old.\nexport const PARTY_OBSERVATION_FRESHNESS_MS = 2 * 60_000;\n\n// The organizer's client re-reports an unchanged party this often so that\n// viewers keep receiving a fresh `observedAt` well before it goes stale.\nexport const PARTY_OBSERVATION_HEARTBEAT_MS = 60_000;\n\n// The API commits an unchanged observation only once it is at least this old.\n// It stays below the heartbeat interval so every heartbeat refreshes viewers,\n// while repeated reports (reconnects, remounts) do not publish a new revision.\nexport const PARTY_OBSERVATION_REFRESH_MS = 45_000;\n\nexport const PartyGatheringVolunteerSchema = Schema.Struct({\n ...PartyGatheringCharacterSchema.fields,\n partyPresence: Schema.Literals(PARTY_READY_ROOM_PARTY_PRESENCE_STATES),\n});\n\nexport type PartyGatheringVolunteer = typeof PartyGatheringVolunteerSchema.Type;\n\nexport const PartyGatheringSummarySchema = Schema.Struct({\n notificationId: Schema.String,\n organizerName: Schema.String,\n organizerDiscordId: Schema.optionalKey(Schema.String),\n organizerLvl: Schema.optionalKey(FiniteNumber),\n organizerProf: Schema.optionalKey(Schema.String),\n applicantCount: NonNegativeSafeInteger,\n inPartyCount: NonNegativeSafeInteger,\n partyMemberCount: Schema.optionalKey(NonNegativeSafeInteger),\n revision: Schema.optionalKey(PositiveSafeInteger),\n volunteers: Schema.optionalKey(Schema.Array(PartyGatheringVolunteerSchema)),\n partyState: Schema.optionalKey(PartyGatheringPartyStateSchema),\n guildIds: Schema.Array(Schema.String),\n world: Schema.String,\n description: Schema.optionalKey(Schema.String),\n minLvl: Schema.optionalKey(FiniteNumber),\n maxLvl: Schema.optionalKey(FiniteNumber),\n npc: Schema.optionalKey(\n Schema.Struct({\n ...PartyGatheringNpcSchema.fields,\n type: Schema.optionalKey(Schema.String),\n }),\n ),\n createdAt: DateTimeString,\n expiresAt: DateTimeString,\n});\n\nexport type PartyGatheringSummary = typeof PartyGatheringSummarySchema.Type;\n\nexport const PartyGatheringClientUpdateSchema = Schema.Union([\n Schema.Struct({\n type: Schema.Literal(\"UPSERT\"),\n gathering: PartyGatheringSummarySchema,\n }),\n Schema.Struct({\n type: Schema.Literal(\"REMOVE\"),\n notificationId: Schema.String,\n revision: PositiveSafeInteger,\n }),\n]);\n\nexport type PartyGatheringClientUpdate =\n typeof PartyGatheringClientUpdateSchema.Type;\n\nexport const PartyGatheringUpdateEnvelopeSchema = Schema.Struct({\n guildId: Schema.String,\n guildIds: Schema.Array(Schema.String),\n organizerDiscordId: Schema.String,\n npc: Schema.optionalKey(PartyGatheringNpcSchema),\n world: Schema.String,\n notificationId: Schema.String,\n revision: PositiveSafeInteger,\n update: PartyGatheringClientUpdateSchema,\n});\n\nexport type PartyGatheringUpdateEnvelope =\n typeof PartyGatheringUpdateEnvelopeSchema.Type;\n\nexport const PartyReadyRoomAggregateSchema = Schema.Struct({\n schemaVersion: Schema.Literal(3),\n npc: Schema.optionalKey(PartyGatheringNpcSchema),\n notificationId: Schema.String,\n organizerDiscordId: Schema.String,\n organizerCharacter: PartyReadyRoomCharacterSchema,\n guildIds: Schema.mutable(Schema.Array(Schema.String)),\n world: Schema.String,\n description: Schema.optionalKey(Schema.String),\n minLvl: Schema.optionalKey(Schema.Number),\n maxLvl: Schema.optionalKey(Schema.Number),\n partyMemberCount: Schema.optionalKey(NonNegativeSafeInteger),\n partyState: Schema.optionalKey(PartyGatheringPartyStateSchema),\n status: Schema.Literals(PARTY_READY_ROOM_STATUSES),\n revision: Schema.Number,\n createdAt: Schema.String,\n updatedAt: Schema.String,\n expiresAt: Schema.String,\n participants: Schema.Record(Schema.String, PartyReadyRoomParticipantSchema),\n});\n\nconst activeProjectionFields = {\n volunteers: Schema.optionalKey(Schema.Array(PartyGatheringVolunteerSchema)),\n ...PartyReadyRoomAggregateSchema.fields,\n participants: Schema.Record(\n Schema.String,\n Schema.mutableKey(PartyReadyRoomParticipantSchema),\n ),\n status: Schema.Literal(\"ACTIVE\"),\n};\n\nconst PartyReadyRoomOrganizerProjectionSchema = Schema.Struct({\n ...activeProjectionFields,\n viewer: Schema.Literal(\"ORGANIZER\"),\n ownedParticipantIds: Schema.mutable(Schema.Array(Schema.String)),\n});\n\nconst PartyReadyRoomParticipantProjectionSchema = Schema.Struct({\n ...activeProjectionFields,\n viewer: Schema.Literal(\"PARTICIPANT\"),\n});\n\nconst PartyReadyRoomProjectionSchema = Schema.Union([\n PartyReadyRoomOrganizerProjectionSchema,\n PartyReadyRoomParticipantProjectionSchema,\n]);\n\nexport const decodePartyReadyRoomProjection = Schema.decodeUnknownSync(\n PartyReadyRoomProjectionSchema,\n);\n\nconst PartyReadyRoomUpsertUpdateSchema = Schema.Struct({\n schemaVersion: Schema.Literal(3),\n type: Schema.Literal(\"UPSERT\"),\n projection: PartyReadyRoomProjectionSchema,\n});\n\nconst PartyReadyRoomRemoveUpdateSchema = Schema.Struct({\n schemaVersion: Schema.Literal(3),\n type: Schema.Literal(\"REMOVE\"),\n notificationId: Schema.String,\n revision: Schema.Number,\n});\n\nconst PartyReadyRoomClientUpdateSchema = Schema.Union([\n PartyReadyRoomUpsertUpdateSchema,\n PartyReadyRoomRemoveUpdateSchema,\n]);\n\nexport const decodePartyReadyRoomClientUpdate = Schema.decodeUnknownSync(\n PartyReadyRoomClientUpdateSchema,\n);\n","import { Schema } from \"effect\";\nimport { DateTimeString } from \"./http-scalars.js\";\nimport { NonNegativeInt } from \"./primitives.js\";\n\nexport const CHAT_MESSAGE_LIMIT = 300;\n\n/** Messages each global chat channel keeps; every send trims older ones. */\nexport const GLOBAL_CHAT_MESSAGE_LIMIT = 2000;\n\nexport const GLOBAL_CHAT_PAGE_SIZE = 100;\n\nexport const GLOBAL_CHAT_MESSAGE_MAX_LENGTH = 128;\n\n/** One User sends at most one global chat message in this window, across channels. */\nexport const GLOBAL_CHAT_SEND_COOLDOWN_SECONDS = 3;\n\n/** How long an admin may mute a sender; `null` mutes until an admin lifts it. */\nexport const GLOBAL_CHAT_MUTE_DURATIONS_MINUTES = [\n 5, 15, 30, 60, 180, 360, 720, 1440, 4320, 10080, 43200,\n] as const;\n\nexport const GlobalChatMessageText = Schema.String.check(\n Schema.isTrimmed(),\n Schema.isMinLength(1),\n Schema.isMaxLength(GLOBAL_CHAT_MESSAGE_MAX_LENGTH),\n);\n\n/**\n * A Margonem world with its own global chat channel. Wherever a channel is\n * named, an absent world means the channel every world shares.\n */\nexport const GlobalChatWorld = Schema.NonEmptyString.check(\n Schema.isMaxLength(64),\n);\n\n/**\n * A global chat message as every Member sees it. It crosses Organization\n * boundaries, so it names the sender only by their Discord display name and\n * never carries a User, Discord, Organization or character identifier.\n *\n * `isAdmin` and the worlds are optional only for messages published before\n * channels existed; the API sets `isAdmin` on every message it stores.\n */\nexport const GlobalChatMessageSchema = Schema.Struct({\n id: Schema.NonEmptyString,\n displayName: Schema.NonEmptyString,\n message: GlobalChatMessageText,\n timestamp: DateTimeString,\n /** The channel's world; absent in the channel every world shares. */\n world: Schema.optionalKey(GlobalChatWorld),\n /** In the shared channel only: the world the sender wrote from. */\n originWorld: Schema.optionalKey(GlobalChatWorld),\n isAdmin: Schema.optionalKey(Schema.Boolean),\n});\n\nexport type GlobalChatMessage = typeof GlobalChatMessageSchema.Type;\n\n/** An admin removed a message, or pinned or unpinned one, in a channel. */\nexport const GlobalChatChannelUpdateSchema = Schema.Union([\n Schema.Struct({\n type: Schema.Literal(\"deleted\"),\n world: Schema.optionalKey(GlobalChatWorld),\n id: Schema.NonEmptyString,\n }),\n Schema.Struct({\n type: Schema.Literal(\"pinned\"),\n world: Schema.optionalKey(GlobalChatWorld),\n message: Schema.NullOr(GlobalChatMessageSchema),\n }),\n]);\n\nexport type GlobalChatChannelUpdate = typeof GlobalChatChannelUpdateSchema.Type;\n\n/** Live counts the gateway sends to a channel's subscribers. */\nexport const GlobalChatStatsSchema = Schema.Struct({\n world: Schema.optionalKey(GlobalChatWorld),\n /**\n * Unique Users with a live Game client across every Organization: on the\n * channel's world, or on any world in the shared channel.\n */\n online: NonNegativeInt,\n /** Unique Users following this channel. */\n listeners: NonNegativeInt,\n});\n\nexport type GlobalChatStats = typeof GlobalChatStatsSchema.Type;\n","import { Schema } from \"effect\";\n\nconst AIR_TAG_RELATIONS = [1, 2, 3, 4, 5, 6, 7, 8] as const;\n\nexport const AIR_TAG_ENEMY_RELATION = 3;\n\nexport const AIR_TAG_CLAN_ENEMY_RELATION = 6;\n\nexport const AIR_TAG_MAX_BATCH_SIZE = 50;\n\nconst AIR_TAG_MAX_COORDINATE = 65_535;\n\nexport const AIR_TAG_MAX_MAP_NAME_LENGTH = 128;\n\n/** A map threat is current this long after its last clan-enemy sighting. */\nexport const AIR_TAG_MAP_THREAT_FRESH_MS = 10_000;\n\n/** After this long without a sighting, a map threat is dropped. */\nexport const AIR_TAG_MAP_THREAT_TTL_MS = 30_000;\n\nexport type AirTagRelation = (typeof AIR_TAG_RELATIONS)[number];\n\ninterface AirTagClan {\n id: number;\n name: string;\n}\n\nexport interface AirTagObservation {\n targetId: string;\n nickname: string;\n clan?: AirTagClan;\n relation: AirTagRelation;\n x: number;\n y: number;\n lvl?: number;\n /** Margonem profession letter, such as `w` or `m`. */\n prof?: string;\n /** Margonem stasis: the player is away from the keyboard. */\n stasis?: boolean;\n}\n\n/**\n * `left-map`: the observer is certain the target left the map (logout, teleport,\n * gateway). `out-of-sight`: the target may still be on the map, beyond the\n * observer's war shadow range.\n */\nexport type AirTagDepartureReason = \"left-map\" | \"out-of-sight\";\n\nexport interface AirTagDeparture {\n targetId: string;\n reason: AirTagDepartureReason;\n}\n\nexport interface AirTagObservationBatch {\n expectedMapId: number;\n observations: AirTagObservation[];\n /** Sent only to gateways listing `lootlog.air-tag-scope-update.v1`. */\n departures?: AirTagDeparture[];\n}\n\nexport interface AirTagSubscriptionPayload {\n requestId: string;\n enabled: boolean;\n expectedMapId?: number;\n}\n\nexport interface AirTagTarget extends AirTagObservation {\n observedAt: number;\n enemyObservedAt?: number;\n clanEnemyObservedAt?: number;\n}\n\nexport interface AirTagScopeSnapshot {\n guildId: string;\n world: string;\n mapId: number;\n epochId: string;\n epochStartedAt: number;\n revision: number;\n targets: AirTagTarget[];\n /** Redis time of the snapshot; relates `observedAt` values to the local clock. */\n serverTime?: number;\n}\n\nexport interface AirTagUpdateEvent {\n guildId: string;\n world: string;\n mapId: number;\n epochId: string;\n epochStartedAt: number;\n revision: number;\n target: AirTagTarget;\n}\n\n/**\n * Every change of one scope from one merged batch. Removals precede updates:\n * `targets[i]` carries revision `revision - (targets.length - 1 - i)`.\n */\nexport interface AirTagScopeUpdateEvent {\n guildId: string;\n world: string;\n mapId: number;\n epochId: string;\n epochStartedAt: number;\n revision: number;\n targets: readonly AirTagTarget[];\n /** Targets every observer lost sight of after one saw them leave the map. */\n removedTargetIds: readonly string[];\n}\n\nexport interface AirTagMapThreatEnemy {\n targetId: string;\n nickname: string;\n clan?: AirTagClan;\n lvl?: number;\n prof?: string;\n stasis?: boolean;\n /** Time since the last clan-enemy sighting when the gateway sent the event; immune to client clock skew. */\n ageMs: number;\n}\n\n/** Every clan enemy an Organization member saw on one map within `AIR_TAG_MAP_THREAT_TTL_MS`. */\nexport interface AirTagMapThreatEvent {\n guildId: string;\n world: string;\n mapId: number;\n mapName: string;\n /** Redis time of the aggregation; a later list of the same map replaces an earlier one. */\n revision: number;\n enemies: readonly AirTagMapThreatEnemy[];\n}\n\nexport type AirTagRejectCode =\n | \"forbidden\"\n | \"invalid-context\"\n | \"invalid-payload\"\n | \"rate-limited\"\n | \"temporarily-unavailable\";\n\nexport type AirTagSubscriptionAck =\n | {\n status: \"accepted\";\n requestId: string;\n scopes: AirTagScopeSnapshot[];\n }\n | {\n status: \"rejected\";\n requestId: string;\n code: AirTagRejectCode;\n };\n\nexport type AirTagObservationAck =\n | {\n status: \"accepted\";\n acceptedScopes: number;\n acceptedTargets: number;\n }\n | {\n status: \"rejected\";\n code: AirTagRejectCode;\n retryAfterMs?: number;\n };\n\nconst ShortString = Schema.NonEmptyString.check(Schema.isMaxLength(64));\n\nconst GuildId = Schema.NonEmptyString.check(Schema.isMaxLength(128));\n\nconst SafeNatural = Schema.Int.check(\n Schema.isBetween({ minimum: 0, maximum: Number.MAX_SAFE_INTEGER }),\n);\n\nconst Coordinate = Schema.Int.check(\n Schema.isBetween({ minimum: 0, maximum: AIR_TAG_MAX_COORDINATE }),\n);\n\nconst Level = Schema.Int.check(\n Schema.isBetween({ minimum: 0, maximum: 10_000 }),\n);\n\nconst Profession = Schema.NonEmptyString.check(Schema.isMaxLength(1));\n\nconst AirTagRelationSchema = Schema.Literals(AIR_TAG_RELATIONS);\n\nconst AirTagClanSchema = Schema.Struct({\n id: SafeNatural,\n name: ShortString,\n});\n\nexport const AirTagObservationSchema = Schema.Struct({\n targetId: ShortString,\n nickname: ShortString,\n clan: Schema.optionalKey(AirTagClanSchema),\n relation: AirTagRelationSchema,\n x: Coordinate,\n y: Coordinate,\n lvl: Schema.optionalKey(Level),\n prof: Schema.optionalKey(Profession),\n stasis: Schema.optionalKey(Schema.Boolean),\n});\n\nexport const AirTagDepartureSchema = Schema.Struct({\n targetId: ShortString,\n reason: Schema.Literals([\"left-map\", \"out-of-sight\"]),\n});\n\nexport const AirTagObservationBatchSchema = Schema.Struct({\n expectedMapId: Coordinate,\n observations: Schema.Array(AirTagObservationSchema),\n departures: Schema.optionalKey(Schema.Array(AirTagDepartureSchema)),\n});\n\nexport const AirTagTargetSchema = Schema.Struct({\n ...AirTagObservationSchema.fields,\n observedAt: SafeNatural,\n enemyObservedAt: Schema.optionalKey(SafeNatural),\n clanEnemyObservedAt: Schema.optionalKey(SafeNatural),\n});\n\nconst AirTagScopeIdentityFields = {\n guildId: GuildId,\n world: ShortString,\n mapId: Coordinate,\n epochId: ShortString,\n epochStartedAt: SafeNatural,\n revision: SafeNatural,\n} as const;\n\nexport const AirTagScopeSnapshotSchema = Schema.Struct({\n ...AirTagScopeIdentityFields,\n targets: Schema.Array(AirTagTargetSchema),\n serverTime: Schema.optionalKey(SafeNatural),\n});\n\nexport const AirTagUpdateEventSchema = Schema.Struct({\n ...AirTagScopeIdentityFields,\n target: AirTagTargetSchema,\n});\n\nexport const AirTagScopeUpdateEventSchema = Schema.Struct({\n ...AirTagScopeIdentityFields,\n targets: Schema.Array(AirTagTargetSchema),\n removedTargetIds: Schema.Array(ShortString),\n});\n\nexport const AirTagMapThreatEventSchema = Schema.Struct({\n guildId: GuildId,\n world: ShortString,\n mapId: Coordinate,\n mapName: Schema.NonEmptyString.check(\n Schema.isMaxLength(AIR_TAG_MAX_MAP_NAME_LENGTH),\n ),\n revision: SafeNatural,\n enemies: Schema.Array(\n Schema.Struct({\n targetId: AirTagObservationSchema.fields.targetId,\n nickname: AirTagObservationSchema.fields.nickname,\n clan: AirTagObservationSchema.fields.clan,\n lvl: AirTagObservationSchema.fields.lvl,\n prof: AirTagObservationSchema.fields.prof,\n stasis: AirTagObservationSchema.fields.stasis,\n ageMs: SafeNatural,\n }),\n ),\n});\n\nexport const isAirTagObservation = Schema.is(AirTagObservationSchema);\n\nexport const isAirTagRelation = Schema.is(AirTagRelationSchema);\n\nexport const isAirTagScopeSnapshot = Schema.is(AirTagScopeSnapshotSchema);\n\nexport const isAirTagUpdateEvent = Schema.is(AirTagUpdateEventSchema);\n\nexport const isAirTagScopeUpdateEvent = Schema.is(AirTagScopeUpdateEventSchema);\n\nexport const isAirTagDeparture = Schema.is(AirTagDepartureSchema);\n","import { Schema } from \"effect\";\nimport { NonNegativeInt } from \"./primitives.js\";\n\n/** Pings placed on an enemy warrior. `attack` is the team's shared target. */\nconst BATTLE_ENEMY_PING_TYPES = [\"attack\", \"caution\", \"spare\"] as const;\n\n/** Requests placed on an allied warrior (or on the sender's own warrior). */\nconst BATTLE_REQUEST_PING_TYPES = [\n \"attack-speed-aura\",\n \"atmo\",\n \"cleanse\",\n \"emanating-arrow\",\n \"fury\",\n \"heal\",\n \"healing-wave\",\n \"need-heal\",\n \"poison\",\n \"protection-aura\",\n \"rime\",\n \"stigma\",\n \"taunt\",\n] as const;\n\n/**\n * Calls to the whole battle team, sent from the sender's own warrior. Only\n * sockets that negotiated `lootlog.battle-ping.team.v1` send or receive them.\n */\nconst BATTLE_TEAM_PING_TYPES = [\"quick-fight\"] as const;\n\nconst BATTLE_PING_TYPES = [\n ...BATTLE_ENEMY_PING_TYPES,\n ...BATTLE_REQUEST_PING_TYPES,\n ...BATTLE_TEAM_PING_TYPES,\n] as const;\n\nexport type BattlePingType = (typeof BATTLE_PING_TYPES)[number];\n\n/** A Margonem party holds at most ten characters, so nine other recipients. */\nconst MAX_BATTLE_PING_RECIPIENTS = 9;\n\n/** Margonem battle warrior ids: positive for characters, negative for NPCs. */\nconst MAX_BATTLE_WARRIOR_ID = 2_147_483_647;\n\nconst BattlePingTypeSchema = Schema.Literals(BATTLE_PING_TYPES);\n\nconst BattleWarriorIdSchema = Schema.Int.check(\n Schema.isBetween({\n minimum: -MAX_BATTLE_WARRIOR_ID,\n maximum: MAX_BATTLE_WARRIOR_ID,\n }),\n Schema.makeFilter((id: number) => id !== 0 || \"warrior id must not be 0\"),\n);\n\nconst CharacterIdSchema = Schema.String.check(\n Schema.isPattern(/^[1-9]\\d{0,9}$/u),\n);\n\nexport const isBattlePingType = Schema.is(BattlePingTypeSchema);\n\nexport const isBattleEnemyPingType = Schema.is(\n Schema.Literals(BATTLE_ENEMY_PING_TYPES),\n);\n\nexport const isBattleTeamPingType = Schema.is(\n Schema.Literals(BATTLE_TEAM_PING_TYPES),\n);\n\nexport interface BattlePingSendPayload {\n expectedMapId: number;\n type: BattlePingType;\n warriorId: number;\n /** Character ids of the other players on the sender's battle team. */\n recipientCharacterIds: readonly string[];\n}\n\nexport interface BattlePingEvent {\n pingId: string;\n world: string;\n mapId: number;\n type: BattlePingType;\n warriorId: number;\n sender: {\n characterId: string;\n name: string;\n };\n createdAt: number;\n}\n\nexport const BattlePingSendPayloadSchema = Schema.Struct({\n expectedMapId: NonNegativeInt,\n type: BattlePingTypeSchema,\n warriorId: BattleWarriorIdSchema,\n recipientCharacterIds: Schema.Array(CharacterIdSchema).check(\n Schema.isMinLength(1),\n Schema.isMaxLength(MAX_BATTLE_PING_RECIPIENTS),\n ),\n});\n\nexport const BattlePingEventSchema = Schema.Struct({\n pingId: Schema.NonEmptyString,\n world: Schema.NonEmptyString,\n mapId: NonNegativeInt,\n type: BattlePingTypeSchema,\n warriorId: BattleWarriorIdSchema,\n sender: Schema.Struct({\n characterId: Schema.NonEmptyString,\n name: Schema.NonEmptyString,\n }),\n createdAt: NonNegativeInt,\n});\n","import { Schema } from \"effect\";\nimport { NonNegativeInt } from \"./primitives.js\";\n\n/**\n * A participant's choice for one item of a group loot split, as Margonem's\n * `loot.states` reports it: 0 \"nie chcę\", 1 \"chcę\", 2 \"bardzo chcę\".\n */\nconst LOOT_SPLIT_CHOICES = [0, 1, 2] as const;\n\nexport type LootSplitChoice = (typeof LOOT_SPLIT_CHOICES)[number];\n\n/** A Margonem party holds at most ten characters, so nine other recipients. */\nconst MAX_LOOT_SPLIT_RECIPIENTS = 9;\n\n/** Bounds a frame; one group loot holds far fewer items. */\nconst MAX_LOOT_SPLIT_ITEMS = 64;\n\nconst ITEM_ID_PATTERN = /^[1-9]\\d{0,17}$/u;\n\nconst ItemIdSchema = Schema.String.check(Schema.isPattern(ITEM_ID_PATTERN));\n\nconst CharacterIdSchema = Schema.String.check(\n Schema.isPattern(/^[1-9]\\d{0,9}$/u),\n);\n\nconst RecipientCharacterIdsSchema = Schema.Array(CharacterIdSchema).check(\n Schema.isMinLength(1),\n Schema.isMaxLength(MAX_LOOT_SPLIT_RECIPIENTS),\n);\n\nconst SenderSchema = Schema.Struct({\n characterId: Schema.NonEmptyString,\n name: Schema.NonEmptyString,\n});\n\nconst LootSplitChoicesSchema = Schema.Record(\n Schema.String,\n Schema.Literals(LOOT_SPLIT_CHOICES),\n).check(\n Schema.makeFilter((choices: Readonly<Record<string, LootSplitChoice>>) => {\n const ids = Object.keys(choices);\n\n return (\n (ids.length <= MAX_LOOT_SPLIT_ITEMS &&\n ids.every((id) => ITEM_ID_PATTERN.test(id))) ||\n \"choices must map at most 64 item ids\"\n );\n }),\n);\n\nexport interface LootSplitSendPayload {\n /** The smallest item id of the split: item ids are unique server-wide. */\n splitId: string;\n choices: Readonly<Record<string, LootSplitChoice>>;\n accepted: boolean;\n /** Character ids of the split's other participants, fixed when it opened. */\n recipientCharacterIds: readonly string[];\n}\n\nexport interface LootSplitEvent {\n splitId: string;\n world: string;\n sender: {\n characterId: string;\n name: string;\n };\n choices: Readonly<Record<string, LootSplitChoice>>;\n accepted: boolean;\n sentAt: number;\n}\n\n/**\n * Sent by a participant whose Margonem loot filter accepted the split for\n * them: the game then opens no loot window and tells that client neither the\n * items nor the choices, so the split has no id it could name.\n */\nexport interface LootSplitAutoAcceptPayload {\n /** Character ids of the fight's other players. */\n recipientCharacterIds: readonly string[];\n}\n\nexport interface LootSplitAutoAcceptedEvent {\n world: string;\n sender: {\n characterId: string;\n name: string;\n };\n sentAt: number;\n}\n\nexport type LootSplitAck =\n | { status: \"accepted\" }\n | {\n status: \"rejected\";\n code:\n | \"forbidden\"\n | \"invalid-context\"\n | \"invalid-payload\"\n | \"rate-limited\"\n | \"temporarily-unavailable\";\n retryAfterMs?: number;\n };\n\nexport const LootSplitSendPayloadSchema = Schema.Struct({\n splitId: ItemIdSchema,\n choices: LootSplitChoicesSchema,\n accepted: Schema.Boolean,\n recipientCharacterIds: RecipientCharacterIdsSchema,\n});\n\nexport const LootSplitEventSchema = Schema.Struct({\n splitId: ItemIdSchema,\n world: Schema.NonEmptyString,\n sender: SenderSchema,\n choices: LootSplitChoicesSchema,\n accepted: Schema.Boolean,\n sentAt: NonNegativeInt,\n});\n\nexport const LootSplitAutoAcceptPayloadSchema = Schema.Struct({\n recipientCharacterIds: RecipientCharacterIdsSchema,\n});\n\nexport const LootSplitAutoAcceptedEventSchema = Schema.Struct({\n world: Schema.NonEmptyString,\n sender: SenderSchema,\n sentAt: NonNegativeInt,\n});\n\nexport const LootSplitAckSchema = Schema.Union([\n Schema.Struct({ status: Schema.Literal(\"accepted\") }),\n Schema.Struct({\n status: Schema.Literal(\"rejected\"),\n code: Schema.Literals([\n \"forbidden\",\n \"invalid-context\",\n \"invalid-payload\",\n \"rate-limited\",\n \"temporarily-unavailable\",\n ]),\n retryAfterMs: Schema.optionalKey(NonNegativeInt),\n }),\n]);\n","import { Schema } from \"effect\";\nimport { NonNegativeInt } from \"./primitives.js\";\n\n/** An NPC this light can have a timer, so only these are reported as standing. */\nexport const NPC_PRESENCE_MIN_WT = 20;\n\nexport const NPC_PRESENCE_MAX_NPCS = 50;\n\nexport const NPC_PRESENCE_MAX_ORGANIZATIONS = 20;\n\n/**\n * A reported NPC stops standing this long after its reporter's last heartbeat.\n * Only a reporter that vanished without closing its socket reaches it.\n */\nexport const NPC_PRESENCE_TTL_MS = 60_000;\n\n/** The fields organization NPC visibility needs, keyed by the NPC's runtime id. */\nexport const NpcPresenceNpcSchema = Schema.Struct({\n id: NonNegativeInt,\n lvl: NonNegativeInt,\n wt: NonNegativeInt,\n prof: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(8))),\n type: Schema.optionalKey(NonNegativeInt),\n});\n\nexport type NpcPresenceNpc = typeof NpcPresenceNpcSchema.Type;\n\n/** Every NPC a character currently sees on its map; each report replaces the previous one. */\nexport const NpcPresenceReportSchema = Schema.Struct({\n world: Schema.NonEmptyString.check(Schema.isMaxLength(64)),\n organizationIds: Schema.Array(Schema.NonEmptyString).check(\n Schema.isMaxLength(NPC_PRESENCE_MAX_ORGANIZATIONS),\n ),\n npcs: Schema.Array(NpcPresenceNpcSchema).check(\n Schema.isMaxLength(NPC_PRESENCE_MAX_NPCS),\n ),\n});\n\nexport type NpcPresenceReport = typeof NpcPresenceReportSchema.Type;\n\n/** Sent only when an NPC gains its first reporter or loses its last one. */\nexport const NpcPresenceEventSchema = Schema.Struct({\n organizationId: Schema.NonEmptyString,\n world: Schema.NonEmptyString,\n /** Orders the updates of one Organization and world across gateway replicas. */\n revision: NonNegativeInt,\n npc: NpcPresenceNpcSchema,\n standing: Schema.Boolean,\n /** Gateway time the NPC was first reported. */\n since: NonNegativeInt,\n});\n\nexport type NpcPresenceEvent = typeof NpcPresenceEventSchema.Type;\n\nexport const NpcPresenceSnapshotSchema = Schema.Struct({\n revision: NonNegativeInt,\n npcs: Schema.Array(\n Schema.Struct({ npc: NpcPresenceNpcSchema, since: NonNegativeInt }),\n ),\n});\n\nexport type NpcPresenceSnapshot = typeof NpcPresenceSnapshotSchema.Type;\n\nexport const NpcPresenceRejectCode = Schema.Literals([\n \"forbidden\",\n \"invalid-context\",\n \"invalid-payload\",\n \"rate-limited\",\n \"temporarily-unavailable\",\n]);\n\nexport const NpcPresenceReportAckSchema = Schema.Union([\n Schema.Struct({ status: Schema.Literal(\"accepted\") }),\n Schema.Struct({\n status: Schema.Literal(\"rejected\"),\n code: NpcPresenceRejectCode,\n retryAfterMs: Schema.optional(NonNegativeInt),\n }),\n]);\n\nexport type NpcPresenceReportAck = typeof NpcPresenceReportAckSchema.Type;\n","import { Schema } from \"effect\";\nimport { NonNegativeInt } from \"./primitives.js\";\n\nconst MAP_PING_TYPES = [\"attention\", \"enemy\", \"regroup\", \"avoid\"] as const;\n\nexport type MapPingType = (typeof MAP_PING_TYPES)[number];\n\nconst MapPingTypeSchema = Schema.Literals(MAP_PING_TYPES);\n\n/** Margonem NPC and character ids are positive 32-bit integers. */\nconst MapPingCharacterIdSchema = Schema.Int.check(\n Schema.isBetween({ minimum: 1, maximum: 2_147_483_647 }),\n);\n\nconst MapPingRejectCodeSchema = Schema.Literals([\n \"forbidden\",\n \"invalid-context\",\n \"invalid-payload\",\n \"rate-limited\",\n \"temporarily-unavailable\",\n]);\n\nexport const isMapPingType = Schema.is(MapPingTypeSchema);\n\nexport interface MapPingSendPayload {\n expectedMapId: number;\n type: MapPingType;\n x: number;\n y: number;\n /** The NPC the ping targets. Older gateways and clients ignore it. */\n npcId?: number;\n /** The player the ping targets. Older gateways and clients ignore it. */\n playerId?: number;\n}\n\ntype MapPingRejectCode =\n | \"forbidden\"\n | \"invalid-context\"\n | \"invalid-payload\"\n | \"rate-limited\"\n | \"temporarily-unavailable\";\n\nexport type MapPingAck =\n | {\n status: \"accepted\";\n pingId: string;\n }\n | {\n status: \"rejected\";\n code: MapPingRejectCode;\n retryAfterMs?: number;\n };\n\nexport interface MapPingEvent {\n pingId: string;\n world: string;\n mapId: number;\n type: MapPingType;\n x: number;\n y: number;\n npcId?: number;\n playerId?: number;\n sender: {\n characterId: string;\n name: string;\n };\n createdAt: number;\n}\n\nconst mapPingFields = {\n type: MapPingTypeSchema,\n x: NonNegativeInt,\n y: NonNegativeInt,\n npcId: Schema.optionalKey(MapPingCharacterIdSchema),\n playerId: Schema.optionalKey(MapPingCharacterIdSchema),\n};\n\nexport const MapPingSendPayloadSchema = Schema.Struct({\n expectedMapId: NonNegativeInt,\n ...mapPingFields,\n});\n\nexport const MapPingAckSchema = Schema.Union([\n Schema.Struct({\n status: Schema.Literal(\"accepted\"),\n pingId: Schema.NonEmptyString,\n }),\n Schema.Struct({\n status: Schema.Literal(\"rejected\"),\n code: MapPingRejectCodeSchema,\n retryAfterMs: Schema.optionalKey(NonNegativeInt),\n }),\n]);\n\nexport const MapPingEventSchema = Schema.Struct({\n pingId: Schema.NonEmptyString,\n world: Schema.NonEmptyString,\n mapId: NonNegativeInt,\n ...mapPingFields,\n sender: Schema.Struct({\n characterId: Schema.NonEmptyString,\n name: Schema.NonEmptyString,\n }),\n createdAt: NonNegativeInt,\n});\n","import { UserFeedItem } from \"./feed.js\";\nimport { LootSnapshot } from \"./loot-summary.js\";\nimport { NonNegativeInt } from \"@lootlog/schema/primitives\";\nimport { Schema } from \"effect\";\n\n/*\n * Loot and reservation events that RabbitMQ carries and the realtime gateway\n * forwards to browsers. They live apart from the RabbitMQ catalogue so the\n * realtime protocol does not bundle every server-only event schema.\n */\n\nexport const GuildLootEventNpc = Schema.Struct({\n lvl: Schema.optional(Schema.NullOr(Schema.Number)),\n prof: Schema.optional(Schema.NullOr(Schema.String)),\n type: Schema.optional(\n Schema.NullOr(Schema.Union([Schema.Number, Schema.String])),\n ),\n wt: Schema.optional(\n Schema.NullOr(Schema.Union([Schema.Number, Schema.String])),\n ),\n});\n\nexport const GuildLootCreatedEventV2 = Schema.Struct({\n feedEntry: Schema.optional(UserFeedItem),\n version: Schema.Literal(2),\n guildId: Schema.NonEmptyString,\n lootId: NonNegativeInt,\n npcs: Schema.Array(GuildLootEventNpc),\n});\n\nexport type GuildLootCreatedEventV2 = typeof GuildLootCreatedEventV2.Type;\n\n// Publishers before the snapshot omit `loot`; web clients then read the loot back.\nexport const GuildLootCreatedMessageV2 = Schema.Struct({\n ...GuildLootCreatedEventV2.fields,\n loot: Schema.optional(LootSnapshot),\n});\n\nexport type GuildLootCreatedMessageV2 = typeof GuildLootCreatedMessageV2.Type;\n\nexport const GuildLootShareUpdatedEventV2 = Schema.Struct({\n ...GuildLootCreatedEventV2.fields,\n lootShare: Schema.Record(Schema.String, Schema.Array(Schema.String)),\n});\n\nexport type GuildLootShareUpdatedEventV2 =\n typeof GuildLootShareUpdatedEventV2.Type;\n\nexport const ReservationChangedEventV2 = Schema.Struct({\n version: Schema.Literal(2),\n action: Schema.Literals([\"created\", \"updated\", \"deleted\", \"sharing-changed\"]),\n sourceGuildId: Schema.NonEmptyString,\n audienceGuildIds: Schema.Array(Schema.NonEmptyString),\n reservationId: Schema.NullOr(NonNegativeInt),\n spotId: Schema.NullOr(Schema.String),\n});\n\nexport type ReservationChangedEventV2 = typeof ReservationChangedEventV2.Type;\n","import { AccessPolicySnapshot, AccessPolicyChange } from \"./access-policy.js\";\nimport { UserFeedItem } from \"../feed.js\";\nimport { NonNegativeInt } from \"@lootlog/schema/primitives\";\nimport { PartyGatheringClientUpdateSchema } from \"@lootlog/schema/party-ready-room\";\nimport {\n GlobalChatMessageSchema,\n GlobalChatStatsSchema,\n GlobalChatWorld,\n} from \"@lootlog/schema/chat\";\nimport {\n AirTagMapThreatEventSchema,\n AirTagObservationBatchSchema,\n AirTagScopeSnapshotSchema,\n AirTagScopeUpdateEventSchema,\n AirTagUpdateEventSchema,\n} from \"@lootlog/schema/air-tag\";\nimport {\n BattlePingEventSchema,\n BattlePingSendPayloadSchema,\n} from \"@lootlog/schema/battle-ping\";\nimport {\n LootSplitAutoAcceptedEventSchema,\n LootSplitAutoAcceptPayloadSchema,\n LootSplitEventSchema,\n LootSplitSendPayloadSchema,\n} from \"@lootlog/schema/loot-split\";\nimport {\n NpcPresenceEventSchema,\n NpcPresenceReportSchema,\n} from \"@lootlog/schema/npc-presence\";\nimport {\n MapPingAckSchema,\n MapPingEventSchema,\n MapPingSendPayloadSchema,\n} from \"@lootlog/schema/map-ping\";\nimport { Schema } from \"effect\";\nimport {\n GuildLootCreatedEventV2,\n GuildLootCreatedMessageV2,\n GuildLootShareUpdatedEventV2,\n ReservationChangedEventV2,\n} from \"../loot-events.js\";\n\nexport const REALTIME_PROTOCOL_VERSION = 1;\n\nconst { feedEntry: _feedEntry, ...lootCreatedFields } =\n GuildLootCreatedMessageV2.fields;\n\n// `loot` is absent when the publisher predates snapshots.\nexport const LootSnapshotEvent = Schema.Struct(lootCreatedFields);\n\nexport type LootSnapshotEvent = typeof LootSnapshotEvent.Type;\n\n// Offered alongside v1 by clients that understand feed events; never selected as the wire protocol.\nexport const REALTIME_FEED_CAPABILITY = \"lootlog.feed.v1\";\n\nexport const REALTIME_NOTIFICATION_VOLUNTEER_CAPABILITY =\n \"lootlog.notification-volunteer.v1\";\n\nexport const REALTIME_PARTY_GATHERING_STATE_CAPABILITY =\n \"lootlog.party-gathering-state.v1\";\n\n// Listed in `session.joined` capabilities. Older gateways close the socket on an\n// unknown command, so clients send `connection.ping` only when it is listed.\nexport const REALTIME_PING_CAPABILITY = \"connection.ping\";\n\n// Offered as a subprotocol by clients that decode `battle-ping.received`, and\n// listed in `session.joined` capabilities by gateways that accept\n// `battle-ping.send`. Older clients close the socket on an unknown event, and\n// older gateways close it on an unknown command.\nexport const REALTIME_BATTLE_PING_CAPABILITY = \"lootlog.battle-ping.v1\";\n\n// Negotiated like `lootlog.battle-ping.v1`, for the battle ping types that\n// address the whole team (`quick-fight`), which v1 clients and gateways cannot\n// decode.\nexport const REALTIME_TEAM_BATTLE_PING_CAPABILITY =\n \"lootlog.battle-ping.team.v1\";\n\n// Offered as a subprotocol by clients that decode `loot-split.received`, and\n// listed in `session.joined` capabilities by gateways that accept\n// `loot-split.send`. Older clients close the socket on an unknown event, and\n// older gateways close it on an unknown command.\nexport const REALTIME_LOOT_SPLIT_CAPABILITY = \"lootlog.loot-split.v1\";\n\n// Negotiated like `lootlog.loot-split.v1`, for `loot-split.auto-accept` and\n// `loot-split.auto-accepted`: a participant whose loot filter accepted the\n// split for them.\nexport const REALTIME_LOOT_SPLIT_AUTO_ACCEPT_CAPABILITY =\n \"lootlog.loot-split.auto-accept.v1\";\n\n// Offered as a subprotocol by clients that decode `air-tag.map-threat-updated`,\n// and listed in `session.joined` capabilities by gateways that accept\n// `air-tag.map-threats.fetch`. Older clients close the socket on an unknown\n// event, and older gateways close it on an unknown command.\nexport const REALTIME_AIR_TAG_MAP_THREAT_CAPABILITY =\n \"lootlog.air-tag-map-threat.v1\";\n\n// Offered as a subprotocol by clients that decode `air-tag.scope-updated`, and\n// listed in `session.joined` capabilities by gateways that accept `departures`\n// in `air-tag.observation`. Clients without it receive one `air-tag.updated`\n// per target and no removals.\nexport const REALTIME_AIR_TAG_SCOPE_UPDATE_CAPABILITY =\n \"lootlog.air-tag-scope-update.v1\";\n\n// Offered as a subprotocol by clients that decode `npc-presence.updated`, and\n// listed in `session.joined` capabilities by gateways that accept\n// `npc-presence.report` and `npc-presence.fetch`. Older clients close the socket\n// on an unknown event, and older gateways close it on an unknown command.\nexport const REALTIME_NPC_PRESENCE_CAPABILITY = \"lootlog.npc-presence.v1\";\n\n// Offered as a subprotocol by clients that decode `global-chat.created`, and\n// listed in `session.joined` capabilities by gateways that accept a\n// `subscription.subscribe` to `global.chat`. Older clients close the socket on\n// an unknown event, and older gateways close it on an unknown topic.\nexport const REALTIME_GLOBAL_CHAT_CAPABILITY = \"lootlog.global-chat.v1\";\n\n// Offered as a subprotocol by clients that decode `global-chat.deleted`,\n// `global-chat.pinned` and `global-chat.stats`, and listed in `session.joined`\n// capabilities by gateways that route per-world `global.chat` scopes and send\n// those events. Clients without it follow only the channel every world shares.\nexport const REALTIME_GLOBAL_CHAT_CHANNELS_CAPABILITY =\n \"lootlog.global-chat.v2\";\n\n// Offered as a subprotocol by web clients that decode `loot.snapshot`. Such a\n// session receives `loot.snapshot` instead of `loot.created`, so a new loot\n// reaches its lists without an HTTP read.\nexport const REALTIME_LOOT_SNAPSHOT_CAPABILITY = \"lootlog.loot-snapshot.v1\";\n\nexport const REALTIME_SESSION_HELLO_CAPABILITY = \"lootlog.session-hello.v1\";\n\nexport const REALTIME_JSON_SUBPROTOCOL = \"lootlog.realtime.json.v1\";\n\n// Browser-permitted application codes; reasons are deliberately static and contain no identity.\nexport const REALTIME_CLIENT_CLOSE_CODES = {\n heartbeatTimeout: 4001,\n heartbeatRejected: 4002,\n heartbeatUnavailable: 4003,\n malformedFrame: 4007,\n sessionJoinFailed: 4008,\n} as const;\n\n// Sent by a gateway that sheds sessions: a draining replica restarts (1012),\n// and an overloaded or degraded one asks clients to try again later (1013).\nexport const REALTIME_SERVER_CLOSE_CODES = {\n restarting: 1012,\n tryAgainLater: 1013,\n} as const;\n\n// Clients closed by REALTIME_SERVER_CLOSE_CODES reconnect after a uniformly\n// random delay up to this window, so a deploy spreads rejoins and their HTTP\n// resyncs across it instead of hitting the API at once.\nexport const REALTIME_SERVER_CLOSE_RECONNECT_WINDOW_MS = 30_000;\n\nexport const PRESENCE_HEARTBEAT_INTERVAL_MS = 25_000;\n\nexport const PRESENCE_EXPIRY_MS = 60_000;\n\nconst RequestId = Schema.NonEmptyString;\n\nconst Revision = NonNegativeInt;\n\nconst Timestamp = NonNegativeInt;\n\nexport const RealtimeLogicalTopic = Schema.Literals([\n \"organization.activity\",\n \"organization.chat\",\n \"organization.loots\",\n \"organization.members\",\n \"organization.notifications\",\n \"organization.presence\",\n \"organization.reservations\",\n \"organization.timers\",\n \"event.coordination\",\n \"map.air-tags\",\n \"map.pings\",\n \"party.ready-room\",\n \"global.chat\",\n // A world's own global chat channel. A scope without a world matches every\n // world, so world channels cannot share the shared channel's topic.\n \"global.chat.world\",\n]);\n\nexport type RealtimeLogicalTopic = typeof RealtimeLogicalTopic.Type;\n\nexport const SubscriptionScope = Schema.Struct({\n topic: RealtimeLogicalTopic,\n organizationId: Schema.optional(Schema.NonEmptyString),\n eventId: Schema.optional(Schema.NonEmptyString),\n world: Schema.optional(Schema.NonEmptyString),\n mapId: Schema.optional(NonNegativeInt),\n});\n\nexport type SubscriptionScope = typeof SubscriptionScope.Type;\n\nexport const PresencePlatform = Schema.Literals([\"game\", \"web-app\"]);\n\nconst PresenceStatus = Schema.Literals([\"online\", \"offline\"]);\n\nexport const PresenceConfidence = Schema.Literals([\"verified\", \"reported\"]);\n\nconst PresenceClan = Schema.Struct({\n id: Schema.optional(NonNegativeInt),\n name: Schema.optional(Schema.String),\n rank: Schema.optional(Schema.Int),\n});\n\nexport const PresenceCharacter = Schema.Struct({\n world: Schema.NonEmptyString,\n name: Schema.NonEmptyString,\n lvl: NonNegativeInt,\n icon: Schema.String,\n characterId: Schema.NonEmptyString,\n accountId: Schema.NonEmptyString,\n prof: Schema.String,\n clan: Schema.optional(PresenceClan),\n});\n\nconst PrecisePresenceLocation = Schema.Struct({\n mapId: Schema.optional(NonNegativeInt),\n map: Schema.NonEmptyString,\n x: Schema.optional(NonNegativeInt),\n y: Schema.optional(NonNegativeInt),\n});\n\nexport const BasicPresence = Schema.Struct({\n userId: Schema.NonEmptyString,\n discordId: Schema.optional(Schema.NonEmptyString),\n sessionId: Schema.NonEmptyString,\n organizationIds: Schema.Array(Schema.NonEmptyString),\n platform: PresencePlatform,\n status: PresenceStatus,\n confidence: PresenceConfidence,\n isAfk: Schema.Boolean,\n lastSeen: Timestamp,\n character: Schema.optional(PresenceCharacter),\n});\n\nexport type BasicPresence = typeof BasicPresence.Type;\n\nexport const PresenceWithLocation = Schema.Struct({\n ...BasicPresence.fields,\n location: PrecisePresenceLocation,\n});\n\nexport type PresenceWithLocation = typeof PresenceWithLocation.Type;\n\nexport const PublishedPresence = Schema.Struct({\n organizationIds: Schema.Array(Schema.NonEmptyString),\n isAfk: Schema.optional(Schema.Boolean),\n character: Schema.optional(PresenceCharacter),\n location: Schema.optional(PrecisePresenceLocation),\n clientObservedAt: Schema.optional(Timestamp),\n});\n\nexport const PresenceSnapshot = Schema.Struct({\n organizationId: Schema.NonEmptyString,\n world: Schema.optional(Schema.NonEmptyString),\n revision: Revision,\n // Match the richer shape first so the basic schema does not strip location.\n presences: Schema.Array(Schema.Union([PresenceWithLocation, BasicPresence])),\n});\n\nconst PresenceDelta = Schema.Struct({\n organizationId: Schema.NonEmptyString,\n revision: Revision,\n changes: Schema.Array(\n Schema.Union([\n Schema.Struct({\n action: Schema.Literal(\"upsert\"),\n presence: Schema.Union([PresenceWithLocation, BasicPresence]),\n }),\n Schema.Struct({\n action: Schema.Literal(\"remove\"),\n userId: Schema.NonEmptyString,\n discordId: Schema.optional(Schema.NonEmptyString),\n sessionId: Schema.NonEmptyString,\n }),\n ]),\n ),\n});\n\nconst command = <\n Type extends string,\n Data extends Schema.Codec<unknown, unknown>,\n>(\n type: Type,\n data: Data,\n) =>\n Schema.Struct({\n v: Schema.Literal(REALTIME_PROTOCOL_VERSION),\n type: Schema.Literal(type),\n requestId: Schema.optional(RequestId),\n data,\n });\n\nconst SessionJoinCommand = command(\n \"session.join\",\n Schema.Struct({\n world: Schema.optional(Schema.NonEmptyString),\n character: Schema.optional(PresenceCharacter),\n margonemAccountProof: Schema.optional(Schema.Unknown),\n }),\n);\n\nconst HeartbeatCommand = command(\n \"presence.heartbeat\",\n Schema.Struct({ sessionId: Schema.NonEmptyString }),\n);\n\nconst PresencePublishCommand = command(\"presence.publish\", PublishedPresence);\n\n// Answered without I/O, so the round trip measures only the connection.\nconst PingCommand = command(\"connection.ping\", Schema.Struct({}));\n\nconst PresenceFetchCommand = command(\n \"presence.fetch\",\n Schema.Struct({\n organizationId: Schema.NonEmptyString,\n world: Schema.optional(Schema.NonEmptyString),\n delivery: Schema.optional(Schema.Literal(\"response\")),\n }),\n);\n\nconst SubscribeCommand = command(\"subscription.subscribe\", SubscriptionScope);\n\nconst UnsubscribeCommand = command(\n \"subscription.unsubscribe\",\n SubscriptionScope,\n);\n\nexport const MapPingCommand = command(\n \"map-ping.send\",\n MapPingSendPayloadSchema,\n);\n\n// Acknowledged with `MapPingAckSchema`: both pings share one reject vocabulary.\nexport const BattlePingCommand = command(\n \"battle-ping.send\",\n BattlePingSendPayloadSchema,\n);\n\n// Acknowledged with `LootSplitAckSchema`.\nexport const LootSplitCommand = command(\n \"loot-split.send\",\n LootSplitSendPayloadSchema,\n);\n\n// Acknowledged with `LootSplitAckSchema`.\nexport const LootSplitAutoAcceptCommand = command(\n \"loot-split.auto-accept\",\n LootSplitAutoAcceptPayloadSchema,\n);\n\nexport const AirTagSubscriptionCommand = command(\n \"air-tag.subscription\",\n Schema.Struct({\n requestId: RequestId,\n enabled: Schema.Boolean,\n expectedMapId: Schema.optional(NonNegativeInt),\n }),\n);\n\nexport const AirTagObservationCommand = command(\n \"air-tag.observation\",\n AirTagObservationBatchSchema,\n);\n\nexport const AirTagMapThreatsFetchCommand = command(\n \"air-tag.map-threats.fetch\",\n Schema.Struct({\n organizationId: Schema.NonEmptyString,\n world: Schema.NonEmptyString,\n }),\n);\n\nexport const AirTagMapThreatsFetchResponse = Schema.Struct({\n threats: Schema.Array(AirTagMapThreatEventSchema),\n});\n\nexport const NpcPresenceReportCommand = command(\n \"npc-presence.report\",\n NpcPresenceReportSchema,\n);\n\nexport const NpcPresenceFetchCommand = command(\n \"npc-presence.fetch\",\n Schema.Struct({\n organizationId: Schema.NonEmptyString,\n world: Schema.NonEmptyString,\n }),\n);\n\nexport const AirTagRejectCode = Schema.Literals([\n \"forbidden\",\n \"invalid-context\",\n \"invalid-payload\",\n \"rate-limited\",\n \"temporarily-unavailable\",\n]);\n\nexport const AirTagSubscriptionAck = Schema.Union([\n Schema.Struct({\n status: Schema.Literal(\"accepted\"),\n requestId: RequestId,\n scopes: Schema.Array(AirTagScopeSnapshotSchema),\n }),\n Schema.Struct({\n status: Schema.Literal(\"rejected\"),\n requestId: RequestId,\n code: AirTagRejectCode,\n }),\n]);\n\nexport const AirTagObservationAck = Schema.Union([\n Schema.Struct({\n status: Schema.Literal(\"accepted\"),\n acceptedScopes: NonNegativeInt,\n acceptedTargets: NonNegativeInt,\n }),\n Schema.Struct({\n status: Schema.Literal(\"rejected\"),\n code: AirTagRejectCode,\n retryAfterMs: Schema.optional(NonNegativeInt),\n }),\n]);\n\nexport { MapPingAckSchema };\n\nexport const ClientCommand = Schema.Union([\n SessionJoinCommand,\n HeartbeatCommand,\n PingCommand,\n PresencePublishCommand,\n PresenceFetchCommand,\n SubscribeCommand,\n UnsubscribeCommand,\n MapPingCommand,\n BattlePingCommand,\n LootSplitCommand,\n LootSplitAutoAcceptCommand,\n AirTagSubscriptionCommand,\n AirTagObservationCommand,\n AirTagMapThreatsFetchCommand,\n NpcPresenceReportCommand,\n NpcPresenceFetchCommand,\n]);\n\nexport type ClientCommand = typeof ClientCommand.Type;\n\nconst RealtimeError = Schema.Struct({\n code: Schema.NonEmptyString,\n message: Schema.NonEmptyString,\n retryable: Schema.Boolean,\n retryAfterMs: Schema.optional(NonNegativeInt),\n details: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),\n});\n\ntype RealtimeError = typeof RealtimeError.Type;\n\nexport const Response = Schema.Union([\n Schema.Struct({\n v: Schema.Literal(REALTIME_PROTOCOL_VERSION),\n requestId: RequestId,\n status: Schema.Literal(\"success\"),\n data: Schema.optional(Schema.Unknown),\n }),\n Schema.Struct({\n v: Schema.Literal(REALTIME_PROTOCOL_VERSION),\n requestId: RequestId,\n status: Schema.Literal(\"error\"),\n error: RealtimeError,\n }),\n]);\n\nexport type Response = typeof Response.Type;\n\nconst serverEvent = <\n Type extends string,\n Data extends Schema.Codec<unknown, unknown>,\n>(\n type: Type,\n data: Data,\n) =>\n Schema.Struct({\n v: Schema.Literal(REALTIME_PROTOCOL_VERSION),\n type: Schema.Literal(type),\n sequence: Schema.optional(Revision),\n data,\n });\n\nconst OrganizationEvent = Schema.Struct({\n organizationId: Schema.NonEmptyString,\n payload: Schema.Unknown,\n});\n\nexport const ServerEvent = Schema.Union([\n serverEvent(\n \"session.hello\",\n Schema.Struct({ connectionId: Schema.NonEmptyString }),\n ),\n serverEvent(\n \"session.joined\",\n Schema.Struct({\n connectionId: Schema.NonEmptyString,\n organizationIds: Schema.Array(Schema.NonEmptyString),\n subscriptionScopes: Schema.Array(SubscriptionScope),\n accessPolicy: Schema.optional(AccessPolicySnapshot),\n capabilities: Schema.optional(Schema.Array(Schema.NonEmptyString)),\n }),\n ),\n serverEvent(\n \"permissions.updated\",\n Schema.Struct({\n changes: Schema.optional(Schema.Array(AccessPolicyChange)),\n organizationIds: Schema.Array(Schema.NonEmptyString),\n subscriptionScopes: Schema.Array(SubscriptionScope),\n accessPolicy: Schema.optional(AccessPolicySnapshot),\n }),\n ),\n serverEvent(\"presence.snapshot\", PresenceSnapshot),\n serverEvent(\"presence.delta\", PresenceDelta),\n serverEvent(\"chat.created\", OrganizationEvent),\n serverEvent(\"chat.updated\", OrganizationEvent),\n serverEvent(\"chat.deleted\", OrganizationEvent),\n serverEvent(\"chat.cleared\", OrganizationEvent),\n serverEvent(\"global-chat.created\", GlobalChatMessageSchema),\n serverEvent(\n \"global-chat.deleted\",\n Schema.Struct({\n world: Schema.optionalKey(GlobalChatWorld),\n id: Schema.NonEmptyString,\n }),\n ),\n serverEvent(\n \"global-chat.pinned\",\n Schema.Struct({\n world: Schema.optionalKey(GlobalChatWorld),\n message: Schema.NullOr(GlobalChatMessageSchema),\n }),\n ),\n serverEvent(\"global-chat.stats\", GlobalChatStatsSchema),\n serverEvent(\"feed.entry\", UserFeedItem),\n serverEvent(\n \"kills.changed\",\n Schema.Struct({ guildId: Schema.NonEmptyString }),\n ),\n serverEvent(\"loot.created\", GuildLootCreatedEventV2),\n serverEvent(\"loot.share-updated\", GuildLootShareUpdatedEventV2),\n serverEvent(\"loot.snapshot\", LootSnapshotEvent),\n serverEvent(\"timer.created\", OrganizationEvent),\n serverEvent(\"timer.deleted\", OrganizationEvent),\n serverEvent(\"hero-sighting.updated\", OrganizationEvent),\n serverEvent(\"reservation.created\", OrganizationEvent),\n serverEvent(\"reservation.deleted\", OrganizationEvent),\n serverEvent(\"reservation.changed\", ReservationChangedEventV2),\n serverEvent(\"notification.sent\", OrganizationEvent),\n serverEvent(\"member-refresh.updated\", OrganizationEvent),\n serverEvent(\"party-gathering.updated\", OrganizationEvent),\n serverEvent(\"party-gathering.cancelled\", OrganizationEvent),\n serverEvent(\n \"party-gathering.state-updated\",\n Schema.Struct({\n organizationId: Schema.NonEmptyString,\n payload: PartyGatheringClientUpdateSchema,\n }),\n ),\n serverEvent(\"party-ready-room.updated\", OrganizationEvent),\n serverEvent(\"map-ping.received\", MapPingEventSchema),\n serverEvent(\"battle-ping.received\", BattlePingEventSchema),\n serverEvent(\"loot-split.received\", LootSplitEventSchema),\n serverEvent(\"loot-split.auto-accepted\", LootSplitAutoAcceptedEventSchema),\n serverEvent(\"air-tag.updated\", AirTagUpdateEventSchema),\n serverEvent(\"air-tag.scope-updated\", AirTagScopeUpdateEventSchema),\n serverEvent(\"air-tag.map-threat-updated\", AirTagMapThreatEventSchema),\n serverEvent(\"npc-presence.updated\", NpcPresenceEventSchema),\n serverEvent(\"event.map-status-updated\", OrganizationEvent),\n serverEvent(\"event.hero-killed\", OrganizationEvent),\n serverEvent(\"event.ranking-updated\", OrganizationEvent),\n serverEvent(\"event.respawn-window-opened\", OrganizationEvent),\n serverEvent(\"event.respawn-window-closed\", OrganizationEvent),\n serverEvent(\n \"notification.volunteer\",\n Schema.Struct({\n notificationId: Schema.NonEmptyString,\n volunteer: Schema.StructWithRest(\n Schema.Struct({\n discordId: Schema.NonEmptyString,\n world: Schema.NonEmptyString,\n }),\n [Schema.Record(Schema.String, Schema.Unknown)],\n ),\n }),\n ),\n]);\n\nexport type ServerEvent = typeof ServerEvent.Type;\n\nexport const RealtimeFrame = Schema.Union([\n ClientCommand,\n Response,\n ServerEvent,\n]);\n\nexport type RealtimeFrame = typeof RealtimeFrame.Type;\n\nexport const decodeClientCommand = Schema.decodeUnknownSync(ClientCommand);\n\nexport const decodeServerEvent = Schema.decodeUnknownSync(ServerEvent);\n\nexport const decodeRealtimeFrame = Schema.decodeUnknownSync(RealtimeFrame);\n\n// Discriminate an already decoded frame without parsing its payload a second time.\nconst serverEventTypes = new Set<string>(\n ServerEvent.members.map((member) => member.fields.type.literal),\n);\n\nexport const isServerEventFrame = (\n frame: RealtimeFrame,\n): frame is ServerEvent => \"type\" in frame && serverEventTypes.has(frame.type);\n","import { TaggedError as TaggedErrorClass } from \"effect/Schema\";\nimport { LootSplitAckSchema } from \"@lootlog/schema/loot-split\";\nimport { Predicate, Result, Schema } from \"effect\";\nimport {\n PresenceSnapshot,\n MapPingAckSchema,\n AirTagSubscriptionAck,\n AirTagObservationAck,\n AirTagMapThreatsFetchResponse,\n RealtimeFrame,\n type RealtimeFrame as RealtimeFrameType,\n} from \"./protocol.js\";\nimport {\n NpcPresenceReportAckSchema,\n NpcPresenceSnapshotSchema,\n} from \"@lootlog/schema/npc-presence\";\n\nexport class RealtimeCodecError extends TaggedErrorClass<RealtimeCodecError>()(\n \"RealtimeCodecError\",\n {\n operation: Schema.Literals([\"decode\", \"encode\"]),\n message: Schema.String,\n cause: Schema.Defect(),\n },\n) {}\n\nconst getErrorMessage = (cause: unknown): string =>\n cause instanceof Error ? cause.message : String(cause);\n\nconst tryEncodeFrame = (frame: RealtimeFrameType) =>\n Result.try({\n try: () => {\n const validated = Schema.encodeUnknownSync(RealtimeFrame)(frame);\n\n return { frame: validated, text: JSON.stringify(validated) };\n },\n catch: (error) =>\n new RealtimeCodecError({\n operation: \"encode\",\n message: getErrorMessage(error),\n cause: error,\n }),\n });\n\nexport const tryEncodeRealtimeFrame = (frame: RealtimeFrameType) =>\n Result.map(tryEncodeFrame(frame), ({ text }) => text);\n\n// Only reuse values that a JSON round trip would leave unchanged. In particular,\n// open payloads may contain accessors, binary views, undefined or custom objects.\n// Keep the decoder as the authority for normalization and rejected keys.\nconst isJsonStable = (value: unknown): value is Schema.Json => {\n if (Predicate.isNumber(value))\n return Number.isFinite(value) && !Object.is(value, -0);\n\n if (!Predicate.isObjectOrArray(value))\n return (\n value === null || Predicate.isBoolean(value) || Predicate.isString(value)\n );\n\n const prototype: unknown = Object.getPrototypeOf(value);\n const array = Array.isArray(value);\n\n if (\n prototype !== (array ? Array.prototype : Object.prototype) &&\n prototype !== null\n )\n return false;\n\n const keys = Reflect.ownKeys(value);\n\n if (array && keys.length !== value.length + 1) return false;\n\n for (const key of keys) {\n if (!Predicate.isString(key)) return false;\n\n if (array && key === \"length\") continue;\n const property = Object.getOwnPropertyDescriptor(value, key);\n\n if (!property?.enumerable || !(\"value\" in property)) return false;\n\n if (key === \"__proto__\") return false;\n\n if (!isJsonStable(property.value)) return false;\n }\n\n return true;\n};\n\n/** Encode once and retain the validated value when no wire normalization is needed. */\nexport const prepareRealtimeFrame = (frame: RealtimeFrameType) => {\n const encoded = Result.getOrThrow(tryEncodeFrame(frame));\n\n return {\n text: encoded.text,\n // An absent value requests the normal decoder path, never the original input.\n frame: isJsonStable(encoded.frame) ? encoded.frame : undefined,\n };\n};\n\nexport const encodeRealtimeFrame = (frame: RealtimeFrameType): string =>\n Result.getOrThrow(tryEncodeRealtimeFrame(frame));\n\n// Receivers that copy keys by assignment would turn this key into a prototype.\nconst rejectProtoKey = (key: string, value: Schema.Json) => {\n if (key === \"__proto__\") throw new Error(\"The key __proto__ is not allowed\");\n\n return value;\n};\n\n/**\n * Whether a JSON text cannot have a `__proto__` key. A key can spell it only\n * literally or through a `\\u` escape.\n */\nconst isWithoutProtoKey = (text: string): boolean =>\n !text.includes(\"__proto__\") && !text.includes(\"\\\\u\");\n\n/**\n * JSON-parse a realtime text, rejecting any `__proto__` key. The reviver makes\n * parsing several times slower, so it runs only when the text may need it.\n */\nexport const parseRealtimeJson = (text: string): Schema.Json =>\n isWithoutProtoKey(text) ? JSON.parse(text) : JSON.parse(text, rejectProtoKey);\n\n/**\n * Parse a frame that a peer encoded through this schema, without validating it\n * again. Use `tryDecodeRealtimeFrame` for any other input.\n */\nexport const tryParseEncodedRealtimeFrame = (text: string) =>\n Result.try({\n try: () => {\n const value = parseRealtimeJson(text);\n\n if (!Predicate.isObject(value))\n throw new Error(\"Realtime frame is not an object\");\n\n // SAFETY: the caller vouches that this schema encoded the text.\n return value as RealtimeFrameType;\n },\n catch: (error) =>\n new RealtimeCodecError({\n operation: \"decode\",\n message: getErrorMessage(error),\n cause: error,\n }),\n });\n\nconst tryDecode = (input: () => Schema.Json) =>\n Result.try({\n try: () => Schema.decodeUnknownSync(RealtimeFrame)(input()),\n catch: (error) =>\n new RealtimeCodecError({\n operation: \"decode\",\n message: getErrorMessage(error),\n cause: error,\n }),\n });\n\n/** Validate a frame that arrived already parsed by `parseRealtimeJson`. */\nexport const tryDecodeRealtimeFrameValue = (value: Schema.Json) =>\n tryDecode(() => value);\n\nexport const tryDecodeRealtimeFrame = (text: string) =>\n tryDecode(() => parseRealtimeJson(text));\n\nexport const decodeRealtimeFrame = (text: string): RealtimeFrameType =>\n Result.getOrThrow(tryDecodeRealtimeFrame(text));\n\nexport const decodePresenceSnapshot =\n Schema.decodeUnknownSync(PresenceSnapshot);\n\nexport const isMapPingAcknowledgement = Schema.is(MapPingAckSchema);\n\nexport const isLootSplitAcknowledgement = Schema.is(LootSplitAckSchema);\n\nexport const isAirTagSubscriptionAcknowledgement = Schema.is(\n AirTagSubscriptionAck,\n);\n\nexport const isAirTagObservationAcknowledgement =\n Schema.is(AirTagObservationAck);\n\nexport const isAirTagMapThreatsFetchResponse = Schema.is(\n AirTagMapThreatsFetchResponse,\n);\n\nexport const isNpcPresenceReportAcknowledgement = Schema.is(\n NpcPresenceReportAckSchema,\n);\n\nexport const isNpcPresenceSnapshot = Schema.is(NpcPresenceSnapshotSchema);\n\nexport const hasRealtimeCapabilities = Schema.is(\n Schema.Struct({ capabilities: Schema.Array(Schema.NonEmptyString) }),\n);\n\nexport const isPresenceFetchResult = Schema.is(\n Schema.Struct({\n presences: Schema.optional(PresenceSnapshot.fields.presences),\n }),\n);\n","type ListenerFailure = {\n source: string;\n error: unknown;\n};\n\nconst reportListenerError = ({ source, error }: ListenerFailure): void => {\n try {\n console.warn(`[Realtime] ${source} listener failed:`, error);\n } catch {\n // Diagnostics must not interrupt the transport or the remaining observers.\n }\n};\n\nexport const notifyListeners = <Listener>(\n listeners: Iterable<Listener>,\n notify: (listener: Listener) => void,\n source: string,\n): void => {\n for (const listener of listeners) {\n try {\n notify(listener);\n } catch (error) {\n reportListenerError({ source, error });\n }\n }\n};\n","import {\n isServerEventFrame,\n REALTIME_JSON_SUBPROTOCOL,\n PRESENCE_HEARTBEAT_INTERVAL_MS,\n PRESENCE_EXPIRY_MS,\n REALTIME_PING_CAPABILITY,\n REALTIME_PROTOCOL_VERSION,\n REALTIME_CLIENT_CLOSE_CODES,\n REALTIME_SERVER_CLOSE_CODES,\n REALTIME_SERVER_CLOSE_RECONNECT_WINDOW_MS,\n type ClientCommand,\n type ServerEvent,\n type SubscriptionScope,\n} from \"@lootlog/protocol/realtime\";\nimport {\n decodeRealtimeFrame,\n encodeRealtimeFrame,\n hasRealtimeCapabilities,\n} from \"@lootlog/protocol/realtime/codec\";\nimport { Predicate } from \"effect\";\nimport { notifyListeners } from \"./notify-listeners.js\";\n\ntype CommandType = ClientCommand[\"type\"];\n\ntype CommandData<Type extends CommandType> = Extract<\n ClientCommand,\n { type: Type }\n>[\"data\"];\n\nexport type RealtimeConnectionState =\n | \"disconnected\"\n | \"connecting\"\n | \"connected\"\n | \"joining\"\n | \"ready\"\n | \"reconnecting\";\n\nexport interface RealtimeWebSocket {\n readonly readyState: number;\n addEventListener(\n type: \"open\" | \"close\" | \"error\" | \"message\",\n listener: (event: {\n readonly data?: unknown;\n readonly code?: number;\n }) => void,\n ): void;\n send(data: string): void;\n close(code?: number, reason?: string): void;\n}\n\nexport type RealtimeWebSocketFactory = (\n url: string,\n protocols?: string[],\n) => RealtimeWebSocket;\n\nexport interface RealtimeClientOptions {\n readonly url: string;\n readonly path?: string;\n /** Capability subprotocols to offer next to `REALTIME_JSON_SUBPROTOCOL`. */\n readonly protocols?: ReadonlyArray<string>;\n readonly requestTimeoutMs?: number;\n readonly reconnectBaseDelayMs?: number;\n readonly reconnectMaxDelayMs?: number;\n readonly random?: () => number;\n readonly webSocketFactory?: RealtimeWebSocketFactory;\n}\n\ninterface PendingRequest {\n readonly type: CommandType;\n readonly startedAt: number;\n readonly resolve: (data: unknown) => void;\n readonly reject: (error: Error) => void;\n readonly timeout: ReturnType<typeof setTimeout>;\n}\n\nclass RealtimeRequestTimeout extends Error {}\n\nexport class RealtimeRequestError extends Error {\n constructor(\n readonly code: string,\n message: string,\n readonly retryable: boolean,\n readonly retryAfterMs?: number,\n ) {\n super(message);\n this.name = \"RealtimeRequestError\";\n }\n}\n\nconst normalizeUrl = (baseUrl: string, path: string): string => {\n const fallbackBase =\n typeof globalThis.location === \"undefined\"\n ? \"http://localhost\"\n : globalThis.location.href;\n\n const url = new URL(baseUrl, fallbackBase);\n\n if (url.protocol === \"http:\") url.protocol = \"ws:\";\n\n if (url.protocol === \"https:\") url.protocol = \"wss:\";\n url.pathname = path.startsWith(\"/\") ? path : `/${path}`;\n url.search = \"\";\n url.hash = \"\";\n\n return url.toString();\n};\n\nconst nativeWebSocketFactory: RealtimeWebSocketFactory = (url, protocols) =>\n new WebSocket(url, protocols);\n\nconst WEBSOCKET_OPEN = 1;\n\nconst MIN_HEARTBEAT_RETRY_BUDGET_MS = 2_000;\n\nconst scopeKey = (scope: SubscriptionScope): string =>\n JSON.stringify([\n scope.topic,\n scope.organizationId ?? null,\n scope.eventId ?? null,\n scope.world ?? null,\n scope.mapId ?? null,\n ]);\n\nconst SERVER_CLOSE_CODES: ReadonlySet<number> = new Set(\n Object.values(REALTIME_SERVER_CLOSE_CODES),\n);\n\nconst getPresenceSessionId = (data: unknown): string | null => {\n if (!data || typeof data !== \"object\" || !(\"sessionId\" in data)) return null;\n\n return typeof data.sessionId === \"string\" ? data.sessionId : null;\n};\n\nexport class RealtimeClient {\n private readonly url: string;\n private readonly protocols: string[];\n private readonly requestTimeoutMs: number;\n private readonly reconnectBaseDelayMs: number;\n private readonly reconnectMaxDelayMs: number;\n private readonly random: () => number;\n private readonly webSocketFactory: RealtimeWebSocketFactory;\n private readonly eventListeners = new Set<(event: ServerEvent) => void>();\n private readonly stateListeners = new Set<\n (state: RealtimeConnectionState) => void\n >();\n private heartbeatLatencyMs: number | null = null;\n private readonly heartbeatLatencyListeners = new Set<\n (latencyMs: number | null) => void\n >();\n private readonly pending = new Map<string, PendingRequest>();\n private readonly subscriptions = new Map<string, SubscriptionScope>();\n private socket: RealtimeWebSocket | null = null;\n private stateValue: RealtimeConnectionState = \"disconnected\";\n private joinData: CommandData<\"session.join\"> | null = null;\n private joinAttempt: {\n readonly socket: RealtimeWebSocket;\n readonly key: string;\n readonly promise: Promise<unknown>;\n } | null = null;\n private reconnectAttempt = 0;\n private reconnectNotBeforeMs = 0;\n private reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\n private heartbeatTimeout: ReturnType<typeof setTimeout> | null = null;\n private presenceSessionId: string | null = null;\n private presenceRefreshedAt = 0;\n private pingSupported = false;\n private latencyProbeInFlight = false;\n private manuallyClosed = false;\n private rejoinHandler: (() => Promise<void>) | null = null;\n\n constructor(options: RealtimeClientOptions) {\n this.url = normalizeUrl(options.url, options.path ?? \"/ws\");\n this.protocols = [\n ...new Set([REALTIME_JSON_SUBPROTOCOL, ...(options.protocols ?? [])]),\n ];\n this.requestTimeoutMs = options.requestTimeoutMs ?? 20_000;\n this.reconnectBaseDelayMs = options.reconnectBaseDelayMs ?? 1_000;\n this.reconnectMaxDelayMs = options.reconnectMaxDelayMs ?? 30_000;\n this.random = options.random ?? Math.random;\n this.webSocketFactory = options.webSocketFactory ?? nativeWebSocketFactory;\n }\n\n get state(): RealtimeConnectionState {\n return this.stateValue;\n }\n\n get connected(): boolean {\n return this.socket?.readyState === WEBSOCKET_OPEN;\n }\n\n connect(): void {\n if (this.socket && this.socket.readyState <= WEBSOCKET_OPEN) return;\n this.manuallyClosed = false;\n this.clearReconnect();\n this.open(this.reconnectAttempt > 0 ? \"reconnecting\" : \"connecting\");\n }\n\n disconnect(): void {\n this.manuallyClosed = true;\n this.clearReconnect();\n this.clearHeartbeat();\n this.pingSupported = false;\n this.rejectPending(new Error(\"Realtime client disconnected\"));\n const activeSocket = this.socket;\n this.socket = null;\n activeSocket?.close(1000, \"client disconnect\");\n this.setState(\"disconnected\");\n }\n\n subscribe(listener: (event: ServerEvent) => void): () => void {\n this.eventListeners.add(listener);\n\n return () => this.eventListeners.delete(listener);\n }\n\n subscribeState(\n listener: (state: RealtimeConnectionState) => void,\n ): () => void {\n this.stateListeners.add(listener);\n listener(this.stateValue);\n\n return () => this.stateListeners.delete(listener);\n }\n\n subscribeHeartbeatLatency(\n listener: (latencyMs: number | null) => void,\n ): () => void {\n this.heartbeatLatencyListeners.add(listener);\n listener(this.heartbeatLatencyMs);\n\n return () => this.heartbeatLatencyListeners.delete(listener);\n }\n\n /**\n * Measures the round trip now instead of at the next heartbeat. A gateway\n * that does not advertise `connection.ping` keeps the heartbeat measurement.\n */\n probeLatency(): void {\n if (\n !this.pingSupported ||\n this.stateValue !== \"ready\" ||\n this.latencyProbeInFlight\n )\n return;\n const socket = this.socket;\n const startedAt = performance.now();\n this.latencyProbeInFlight = true;\n void this.request(\"connection.ping\", {})\n .then(() => {\n if (this.socket === socket)\n this.setHeartbeatLatency(Math.round(performance.now() - startedAt));\n })\n // Heartbeats own liveness; a lost probe leaves the last measurement.\n .catch(() => {})\n .finally(() => {\n this.latencyProbeInFlight = false;\n });\n }\n\n private setHeartbeatLatency(latencyMs: number | null): void {\n this.heartbeatLatencyMs = latencyMs;\n\n notifyListeners(\n this.heartbeatLatencyListeners,\n (listener) => listener(latencyMs),\n \"heartbeat latency\",\n );\n }\n\n setReconnectHandler(handler: (() => Promise<void>) | null): void {\n this.rejoinHandler = handler;\n }\n\n join(data: CommandData<\"session.join\">): Promise<unknown> {\n this.joinData = data;\n\n return this.performJoin();\n }\n\n subscribeScope(scope: SubscriptionScope): Promise<unknown> {\n this.subscriptions.set(scopeKey(scope), scope);\n\n if (!this.connected || this.stateValue !== \"ready\") {\n return Promise.resolve(undefined);\n }\n\n return this.request(\"subscription.subscribe\", scope);\n }\n\n unsubscribeScope(scope: SubscriptionScope): Promise<unknown> {\n this.subscriptions.delete(scopeKey(scope));\n\n if (!this.connected || this.stateValue !== \"ready\") {\n return Promise.resolve(undefined);\n }\n\n return this.request(\"subscription.unsubscribe\", scope);\n }\n\n request<Type extends CommandType>(\n type: Type,\n data: CommandData<Type>,\n ): Promise<unknown> {\n return this.requestWithTimeout(type, data, this.requestTimeoutMs);\n }\n\n private requestWithTimeout<Type extends CommandType>(\n type: Type,\n data: CommandData<Type>,\n timeoutMs: number,\n ): ReturnType<RealtimeClient[\"request\"]> {\n const activeSocket = this.socket;\n\n if (!activeSocket || activeSocket.readyState !== WEBSOCKET_OPEN) {\n return Promise.reject(new Error(\"Realtime connection is not open\"));\n }\n\n const requestId = crypto.randomUUID();\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n this.pending.delete(requestId);\n reject(\n new RealtimeRequestTimeout(`Realtime request timed out: ${type}`),\n );\n }, timeoutMs);\n\n this.pending.set(requestId, {\n type,\n startedAt: performance.now(),\n resolve,\n reject,\n timeout,\n });\n\n try {\n // SAFETY: the command discriminator and payload are coupled by CommandData<Type>.\n activeSocket.send(\n encodeRealtimeFrame({\n v: REALTIME_PROTOCOL_VERSION,\n type,\n requestId,\n data,\n } as ClientCommand),\n );\n } catch (error) {\n clearTimeout(timeout);\n this.pending.delete(requestId);\n reject(error instanceof Error ? error : new Error(String(error)));\n }\n });\n }\n\n send<Type extends CommandType>(type: Type, data: CommandData<Type>): void {\n const activeSocket = this.socket;\n\n if (!activeSocket || activeSocket.readyState !== WEBSOCKET_OPEN) return;\n // SAFETY: the command discriminator and payload are coupled by CommandData<Type>.\n activeSocket.send(\n encodeRealtimeFrame({\n v: REALTIME_PROTOCOL_VERSION,\n type,\n data,\n } as ClientCommand),\n );\n }\n\n private open(state: \"connecting\" | \"reconnecting\"): void {\n this.setState(state);\n\n if (this.manuallyClosed) return;\n const socket = this.webSocketFactory(this.url, this.protocols);\n this.socket = socket;\n socket.addEventListener(\"open\", () => {\n if (this.socket !== socket) return;\n this.setState(\"connected\");\n\n // A synchronous observer suppresses only the default join. Explicit restore\n // handlers can also refresh HTTP data or publish presence and must still run.\n if (\n this.joinData &&\n (this.rejoinHandler || this.stateValue === \"connected\")\n ) {\n const rejoin =\n this.rejoinHandler ??\n (() => this.performJoin().then(() => undefined));\n\n void rejoin().catch(() =>\n socket.close(\n REALTIME_CLIENT_CLOSE_CODES.sessionJoinFailed,\n \"session rejoin failed\",\n ),\n );\n }\n });\n socket.addEventListener(\"message\", (event) => {\n try {\n this.handleMessage(event.data, socket);\n } catch {\n socket.close(\n REALTIME_CLIENT_CLOSE_CODES.malformedFrame,\n \"malformed realtime frame\",\n );\n }\n });\n socket.addEventListener(\"close\", (event) => {\n if (this.socket !== socket) return;\n this.socket = null;\n\n // Every session of a restarting replica closes within seconds; spread\n // their rejoins and the HTTP resyncs that follow them.\n if (event.code !== undefined && SERVER_CLOSE_CODES.has(event.code))\n this.reconnectNotBeforeMs = Math.round(\n this.random() * REALTIME_SERVER_CLOSE_RECONNECT_WINDOW_MS,\n );\n\n this.clearHeartbeat();\n this.pingSupported = false;\n this.rejectPending(new Error(\"Realtime connection closed\"));\n this.setState(\"disconnected\");\n\n if (!this.manuallyClosed) this.scheduleReconnect();\n });\n }\n\n private performJoin(data = this.joinData): Promise<unknown> {\n const socket = this.socket;\n\n if (!data || !socket || !this.connected) return Promise.resolve(undefined);\n const key = JSON.stringify(data);\n const pending = this.joinAttempt;\n\n if (pending?.socket === socket) {\n if (pending.key === key) return pending.promise;\n\n // The game client can replace an unverified session with a proof-bearing\n // join. Serialize that update instead of discarding its new credentials.\n return pending.promise.then(() => {\n if (this.socket !== socket || !this.connected)\n throw new Error(\"Realtime connection changed before queued join\");\n\n return this.performJoin(data);\n });\n }\n\n const promise = this.restoreSession(\n socket,\n this.request(\"session.join\", data),\n );\n\n this.joinAttempt = { socket, key, promise };\n this.setState(\"joining\");\n\n return promise;\n }\n\n private async restoreSession(\n socket: RealtimeWebSocket,\n joined: Promise<unknown>,\n ): ReturnType<RealtimeClient[\"join\"]> {\n try {\n const result = await joined;\n\n if (this.socket !== socket) return result;\n this.pingSupported =\n hasRealtimeCapabilities(result) &&\n result.capabilities.includes(REALTIME_PING_CAPABILITY);\n await Promise.all(\n [...this.subscriptions.values()].map((scope) =>\n this.request(\"subscription.subscribe\", scope),\n ),\n );\n\n if (this.socket !== socket) return result;\n this.reconnectAttempt = 0;\n this.setState(\"ready\");\n\n return result;\n } catch (error) {\n if (this.socket === socket) {\n if (error instanceof RealtimeRequestError && !error.retryable) {\n this.manuallyClosed = true;\n this.clearReconnect();\n }\n\n // A busy gateway spreads rejoins with the delay it asked for.\n if (error instanceof RealtimeRequestError && error.retryable)\n this.reconnectNotBeforeMs = error.retryAfterMs ?? 0;\n\n socket.close(\n REALTIME_CLIENT_CLOSE_CODES.sessionJoinFailed,\n \"session join failed\",\n );\n }\n\n throw error;\n } finally {\n if (this.joinAttempt?.socket === socket) this.joinAttempt = null;\n }\n }\n\n private handleMessage(data: unknown, socket: RealtimeWebSocket): void {\n if (this.socket !== socket) return;\n\n if (!Predicate.isString(data))\n throw new Error(\"Gateway returned a non-text realtime frame\");\n const frame = decodeRealtimeFrame(data);\n\n if (\"status\" in frame) {\n const pending = this.pending.get(frame.requestId);\n\n if (!pending) return;\n clearTimeout(pending.timeout);\n this.pending.delete(frame.requestId);\n\n if (frame.status === \"success\") {\n if (pending.type === \"presence.publish\") {\n this.presenceSessionId = getPresenceSessionId(frame.data);\n this.presenceRefreshedAt = pending.startedAt;\n this.scheduleHeartbeat();\n }\n\n pending.resolve(frame.data);\n } else {\n pending.reject(\n new RealtimeRequestError(\n frame.error.code,\n frame.error.message,\n frame.error.retryable,\n frame.error.retryAfterMs,\n ),\n );\n }\n\n return;\n }\n\n if (!isServerEventFrame(frame)) return;\n\n notifyListeners(\n this.eventListeners,\n (listener) => listener(frame),\n `server event ${frame.type}`,\n );\n }\n\n private scheduleReconnect(): void {\n this.reconnectAttempt += 1;\n\n const exponential = Math.min(\n this.reconnectMaxDelayMs,\n this.reconnectBaseDelayMs * 2 ** (this.reconnectAttempt - 1),\n );\n\n const jittered = Math.max(\n Math.round(exponential * (0.5 + this.random())),\n this.reconnectNotBeforeMs,\n );\n\n this.reconnectNotBeforeMs = 0;\n this.setState(\"reconnecting\");\n this.reconnectTimeout = setTimeout(\n () => this.open(\"reconnecting\"),\n jittered,\n );\n }\n\n private scheduleHeartbeat(\n delayMs = PRESENCE_HEARTBEAT_INTERVAL_MS,\n retryAttempt = 0,\n ): void {\n this.clearHeartbeat();\n\n if (!this.presenceSessionId || !this.connected) {\n this.setHeartbeatLatency(null);\n\n return;\n }\n\n this.heartbeatTimeout = setTimeout(() => {\n const sessionId = this.presenceSessionId;\n\n if (!sessionId) return;\n const startedAt = performance.now();\n const socket = this.socket;\n const refreshedAt = this.presenceRefreshedAt;\n const expiry = refreshedAt + PRESENCE_EXPIRY_MS;\n const remaining = expiry - startedAt;\n\n if (\n remaining <= 0 ||\n (retryAttempt > 0 && remaining < MIN_HEARTBEAT_RETRY_BUDGET_MS)\n ) {\n this.setHeartbeatLatency(null);\n socket?.close(\n REALTIME_CLIENT_CLOSE_CODES.heartbeatUnavailable,\n \"heartbeat unavailable\",\n );\n\n return;\n }\n\n // A publication can refresh this same session while its heartbeat is\n // in flight. Keep the publication's heartbeat schedule and lifetime.\n const isStaleHeartbeat = () =>\n this.socket !== socket ||\n this.presenceSessionId !== sessionId ||\n this.presenceRefreshedAt !== refreshedAt;\n\n void this.requestWithTimeout(\n \"presence.heartbeat\",\n { sessionId },\n Math.min(this.requestTimeoutMs, remaining),\n )\n .then(() => {\n if (isStaleHeartbeat()) return;\n this.presenceRefreshedAt = startedAt;\n this.setHeartbeatLatency(Math.round(performance.now() - startedAt));\n this.scheduleHeartbeat();\n })\n .catch((error: Error) => {\n if (isStaleHeartbeat()) return;\n this.setHeartbeatLatency(null);\n\n // Correlated retryable responses prove the transport is alive. Back off\n // on the same session while its last successful refresh is still valid.\n if (error instanceof RealtimeRequestError && error.retryable) {\n const retryDelay = Math.max(\n Math.round(\n Math.min(5_000, 1_000 * 2 ** retryAttempt) *\n (0.5 + this.random()),\n ),\n error.retryAfterMs ?? 0,\n );\n\n if (\n expiry - performance.now() - retryDelay >=\n MIN_HEARTBEAT_RETRY_BUDGET_MS\n ) {\n this.scheduleHeartbeat(retryDelay, retryAttempt + 1);\n\n return;\n }\n\n socket?.close(\n REALTIME_CLIENT_CLOSE_CODES.heartbeatUnavailable,\n \"heartbeat unavailable\",\n );\n\n return;\n }\n\n if (error instanceof RealtimeRequestTimeout) {\n socket?.close(\n REALTIME_CLIENT_CLOSE_CODES.heartbeatTimeout,\n \"heartbeat timeout\",\n );\n\n return;\n }\n\n if (error instanceof RealtimeRequestError) {\n socket?.close(\n REALTIME_CLIENT_CLOSE_CODES.heartbeatRejected,\n \"heartbeat rejected\",\n );\n\n return;\n }\n\n socket?.close();\n });\n }, delayMs);\n }\n\n private rejectPending(error: Error): void {\n for (const pending of this.pending.values()) {\n clearTimeout(pending.timeout);\n pending.reject(error);\n }\n\n this.pending.clear();\n }\n\n private setState(state: RealtimeConnectionState): void {\n if (this.stateValue === state) return;\n this.stateValue = state;\n\n if (state === \"disconnected\") this.setHeartbeatLatency(null);\n\n notifyListeners(\n this.stateListeners,\n (listener) => listener(state),\n `connection state ${state}`,\n );\n }\n\n private clearReconnect(): void {\n if (this.reconnectTimeout) clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n private clearHeartbeat(): void {\n if (this.heartbeatTimeout) clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n}\n"],"mappings":"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"}
|