@vskin/sdk 0.1.0 → 0.2.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/index.cjs CHANGED
@@ -105,8 +105,15 @@ var EErrorCode = /* @__PURE__ */ ((EErrorCode2) => {
105
105
  EErrorCode2["NOT_READY"] = "not_ready";
106
106
  EErrorCode2["RATE_LIMITED"] = "rate_limited";
107
107
  EErrorCode2["INTERNAL"] = "internal";
108
+ EErrorCode2["REFUSED"] = "refused";
108
109
  return EErrorCode2;
109
110
  })(EErrorCode || {});
111
+ var ERefusalFamily = /* @__PURE__ */ ((ERefusalFamily2) => {
112
+ ERefusalFamily2["SETUP"] = "setup";
113
+ ERefusalFamily2["CUT_OFF"] = "cut_off";
114
+ ERefusalFamily2["OUTAGE"] = "outage";
115
+ return ERefusalFamily2;
116
+ })(ERefusalFamily || {});
110
117
  var EViewerEvent = /* @__PURE__ */ ((EViewerEvent2) => {
111
118
  EViewerEvent2["READY"] = "ready";
112
119
  EViewerEvent2["ERROR"] = "error";
@@ -123,6 +130,7 @@ var EViewerEvent = /* @__PURE__ */ ((EViewerEvent2) => {
123
130
  EViewerEvent2["PLACEMENT_START"] = "placementstart";
124
131
  EViewerEvent2["PLACEMENT_MOVE"] = "placementmove";
125
132
  EViewerEvent2["PLACEMENT_END"] = "placementend";
133
+ EViewerEvent2["REFUSED"] = "refused";
126
134
  return EViewerEvent2;
127
135
  })(EViewerEvent || {});
128
136
 
@@ -345,13 +353,15 @@ var performHandshake = ({
345
353
  transport,
346
354
  iframe,
347
355
  mirror,
348
- onGiveUp
356
+ onGiveUp,
357
+ subscribeRefusal
349
358
  }) => new Promise((resolve, reject) => {
350
359
  let settled = false;
351
360
  const beginAt = Date.now();
352
361
  const settle = () => {
353
362
  settled = true;
354
363
  iframe.removeEventListener("load", attempt);
364
+ unsubscribeRefusal();
355
365
  };
356
366
  const attempt = () => {
357
367
  if (settled) return;
@@ -360,7 +370,7 @@ var performHandshake = ({
360
370
  onGiveUp();
361
371
  return reject({
362
372
  code: "invalid_key" /* INVALID_KEY */,
363
- message: "the viewer never answered: the key was refused, this domain is not declared for it, or the render service is unreachable"
373
+ message: "the viewer never answered: the render service is unreachable, or the frame was blocked before the page could boot"
364
374
  });
365
375
  }
366
376
  transport.send({
@@ -376,6 +386,15 @@ var performHandshake = ({
376
386
  resolve();
377
387
  }).catch(() => setTimeout(attempt, HELLO_RETRY_MS));
378
388
  };
389
+ const unsubscribeRefusal = subscribeRefusal(({ family }) => {
390
+ if (settled) return;
391
+ settle();
392
+ reject({
393
+ code: "refused" /* REFUSED */,
394
+ family,
395
+ message: "the embed server refused this viewer; its family says whose problem it is"
396
+ });
397
+ });
379
398
  iframe.addEventListener("load", attempt);
380
399
  setTimeout(attempt, HELLO_RETRY_MS);
381
400
  });
@@ -410,6 +429,10 @@ var createViewer = ({
410
429
  let destroyed = false;
411
430
  let greeted = false;
412
431
  let greetingAgain = false;
432
+ const subscribeRefusal = (handler) => hub.on(
433
+ "refused" /* REFUSED */,
434
+ (payload) => handler(payload)
435
+ );
413
436
  const greetAgain = () => {
414
437
  if (!greeted || greetingAgain || destroyed) return;
415
438
  greetingAgain = true;
@@ -420,7 +443,8 @@ var createViewer = ({
420
443
  mirror,
421
444
  // A reload that never answers leaves the viewer as it is: the frame is the
422
445
  // integrator's to keep or drop, and an error says so.
423
- onGiveUp: () => void 0
446
+ onGiveUp: () => void 0,
447
+ subscribeRefusal
424
448
  }).then(
425
449
  () => hub.dispatch({
426
450
  name: "reconnect" /* RECONNECT */,
@@ -461,7 +485,8 @@ var createViewer = ({
461
485
  transport,
462
486
  iframe,
463
487
  mirror,
464
- onGiveUp: destroy
488
+ onGiveUp: destroy,
489
+ subscribeRefusal
465
490
  }).then(() => {
466
491
  greeted = true;
467
492
  return viewer;
@@ -476,6 +501,7 @@ exports.EErrorCode = EErrorCode;
476
501
  exports.EFacing = EFacing;
477
502
  exports.EFeature = EFeature;
478
503
  exports.EHandedness = EHandedness;
504
+ exports.ERefusalFamily = ERefusalFamily;
479
505
  exports.ESubject = ESubject;
480
506
  exports.EView = EView;
481
507
  exports.EViewerEvent = EViewerEvent;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/constants.ts","../src/contract/interfaces.ts","../src/lib/helpers/buildEmbedUrl.ts","../src/protocol/interfaces.ts","../src/lib/helpers/buildViewerHandle.ts","../src/lib/helpers/createEmbedIframe.ts","../src/lib/helpers/createViewerEventHub.ts","../src/lib/helpers/createCommandId.ts","../src/protocol/constants.ts","../src/lib/helpers/createViewerTransport.ts","../src/lib/helpers/performHandshake.ts","../src/lib/createViewer.ts","../src/lib/buildInspectLink.ts"],"names":["EView","EBackgroundType","EFacing","EHandedness","ESubject","EFeature","EErrorCode","EViewerEvent"],"mappings":"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","file":"index.cjs","sourcesContent":["// Where the viewer lives when the integration does not say otherwise.\nexport const DEFAULT_BASE_URL = 'https://render.vskin.gg';\n\n// The embed page answers the handshake as soon as its bridge is up — retried because the page\n// boots asynchronously behind the iframe's load event.\nexport const HELLO_RETRY_MS = 300;\nexport const HELLO_TIMEOUT_MS = 15000;\n\n// A command that never comes back (the page died, the network broke) must not hang a client's\n// await forever.\nexport const COMMAND_TIMEOUT_MS = 30000;\n\n// The command Steam itself serves in its inventory and market payloads. The space is\n// percent-encoded on purpose: a literal space truncates the steam:// command.\nexport const CS2_INSPECT_LINK_PREFIX =\n 'steam://run/730//+csgo_econ_action_preview%20';\n","// The viewer's public vocabulary: domain words only, no abbreviation, one options object per\n// method, enums whose values ARE the strings a plain-JavaScript consumer writes.\n\nexport enum EView {\n FREE = 'free',\n FIRST_PERSON = 'firstPerson',\n THIRD_PERSON = 'thirdPerson',\n}\n\n// The background is a VALUE, not a boolean: `none` composites the canvas straight onto your\n// page (put your own background behind the viewer), `environment` shows the map's own decor.\nexport enum EBackgroundType {\n NONE = 'none',\n ENVIRONMENT = 'environment',\n}\n\nexport type Background = {\n type: EBackgroundType;\n};\n\nexport enum EFacing {\n FRONT = 'front',\n BACK = 'back',\n}\n\nexport enum EHandedness {\n RIGHT = 'right',\n LEFT = 'left',\n}\n\n// Which of the two picked items the free view presents when a weapon and a pair of gloves are\n// both on stage.\nexport enum ESubject {\n WEAPON = 'weapon',\n GLOVES = 'gloves',\n}\n\n// The weapon as you describe it — identity, roll, marks — in the market's own words (`seed`\n// and `float`). The viewer owns the road to it: a seed or float alone re-rolls in place, a\n// name alone re-engraves the plate, a new identity re-mounts.\nexport type Weapon = {\n // The inspect certificate (hex), the market door: it carries identity, roll and cosmetics.\n cert?: string;\n // The manual door: the item's definition and finish indices.\n defIndex?: number;\n paintIndex?: number;\n seed?: number;\n float?: number;\n stattrak?: boolean;\n kills?: number;\n name?: string;\n};\n\nexport type Gloves = {\n cert?: string;\n defIndex?: number;\n paintIndex?: number;\n seed?: number;\n float?: number;\n};\n\nexport type Agent = {\n // The inspect certificate (hex): a character travels by cert too, patches included.\n cert?: string;\n defIndex?: number;\n};\n\nexport type Sticker = {\n id: number;\n slot: number;\n wear?: number;\n rotation?: number;\n offsetX?: number;\n offsetY?: number;\n};\n\nexport type Charm = {\n id: number;\n pattern?: number;\n // The display-case family: the sticker sealed inside the slab, by its id.\n wrappedSticker?: number;\n // The charm's placement, as a DELTA from the weapon's default hook in the weapon's model\n // space (Source inches) — the same numbers a free-placement drag settles on. Absent = the\n // authored hook. The state mirror's `charmAnchor` publishes the composed ABSOLUTE.\n offsetX?: number;\n offsetY?: number;\n offsetZ?: number;\n};\n\nexport type Patch = {\n id: number;\n slot: number;\n};\n\n// First-person dials in the GAME's units: `fov` is viewmodel_fov degrees, offsets are\n// viewmodel_offset inches. A new dial is a new FIELD here, never a new method.\nexport type FirstPersonSettings = {\n fov?: number;\n offsetX?: number;\n offsetY?: number;\n offsetZ?: number;\n handedness?: EHandedness;\n};\n\n// The camera's flight target. A sticker is named by its STABLE uid (a certificate may repeat a\n// slot, so a slot is not an identity); the state mirror publishes each sticker's uid.\nexport type FocusTarget =\n | { kind: 'sticker'; uid: string }\n | { kind: 'charm' }\n | { kind: 'patch'; slot: number }\n | null;\n\n// What the free-placement mode is armed on: while armed, pressing that cosmetic in the canvas\n// MOVES it instead of orbiting the item. Null disarms.\nexport type PlacementTarget =\n { kind: 'sticker'; slot: number } | { kind: 'charm' } | null;\n\n// One capability, two layers already intersected for you: `entitled` is what the plan bought\n// (stable for the session), `available` folds in what the current scene can serve (moving;\n// `capabilitieschange` fires when it does).\nexport type Capability = {\n entitled: boolean;\n available: boolean;\n};\n\nexport enum EFeature {\n SELECT_WEAPON = 'selectWeapon',\n SELECT_GLOVES = 'selectGloves',\n SELECT_AGENT = 'selectAgent',\n SELECT_ENVIRONMENT = 'selectEnvironment',\n EDIT_SEED = 'editSeed',\n EDIT_FLOAT = 'editFloat',\n EDIT_STATTRAK = 'editStattrak',\n EDIT_NAMETAG = 'editNametag',\n SELECT_STICKER = 'selectSticker',\n SELECT_CHARM = 'selectCharm',\n SELECT_PATCH = 'selectPatch',\n EDIT_STICKERS = 'editStickers',\n EDIT_CHARMS = 'editCharms',\n PLACE_STICKERS = 'placeStickers',\n PLACE_CHARM = 'placeCharm',\n SCREENSHOT = 'screenshot',\n INSPECT_LINK = 'inspectLink',\n SUBJECT_CONTROLS = 'subjectControls',\n WEAPON_ANIMATIONS = 'weaponAnimations',\n AGENT_ANIMATIONS = 'agentAnimations',\n}\n\nexport type ViewerCapabilities = {\n views: Record<EView, Capability>;\n features: Record<EFeature, Capability>;\n};\n\n// One animation the scene can play, with the one fact you need to offer it honestly: a\n// looping clip is a toggle, a one-shot replays.\nexport type AnimationEntry = {\n name: string;\n loop: boolean;\n};\n\n// The synchronous mirror: the last known truth, re-published whole on every `change` event.\n// Read it without ever awaiting.\nexport type ViewerState = {\n weapon: Weapon | null;\n gloves: Gloves | null;\n agent: Agent | null;\n subject: ESubject | null;\n view: { view: EView; active: boolean };\n environment: string | null;\n background: Background;\n stickers: Array<Sticker & { uid?: string }>;\n charm: Charm | null;\n // Where the charm actually sits, in the form a cert names it: the composed ABSOLUTE\n // position in the weapon's model space, read off the manifest the render is using.\n charmAnchor: [number, number, number] | null;\n patches: Array<Patch>;\n // How many patch slots the mounted character authors — the render's own answer, read off\n // its landed manifest. null while no character manifest has answered (none asked, or still\n // composing): 0 is a real answer, \"this body authors none\".\n patchSlots: number | null;\n playing: boolean;\n animation: string | null;\n animations: Array<AnimationEntry>;\n // The character's celebrations: what the mounted body can play beyond its resting posture,\n // and the one running right now (null at rest). Driven through the same playAnimation /\n // stopAnimation door as the weapon clips.\n agentAnimation: string | null;\n agentAnimations: Array<string>;\n sound: { muted: boolean };\n firstPerson: FirstPersonSettings;\n facing: EFacing;\n placement: PlacementTarget;\n};\n","import type { Background, Weapon } from '@/contract/interfaces';\nimport { EBackgroundType } from '@/contract/interfaces';\n\n// The embed page's URL grammar, written once: the boot seed rides the URL, everything after\n// boot rides the protocol.\nexport const buildEmbedUrl = ({\n baseUrl,\n key,\n weapon,\n environment,\n background,\n interactive,\n autoplay,\n locale,\n}: {\n baseUrl: string;\n key?: string;\n weapon?: Weapon;\n environment?: string;\n background?: Background;\n interactive?: boolean;\n autoplay?: boolean;\n locale?: string;\n}): string => {\n const query = new URLSearchParams();\n if (key) query.set('key', key);\n if (weapon?.cert) {\n query.set('cert', weapon.cert);\n } else if (\n weapon &&\n typeof weapon.defIndex === 'number' &&\n typeof weapon.paintIndex === 'number'\n ) {\n query.set('def', String(weapon.defIndex));\n query.set('paint', String(weapon.paintIndex));\n if (weapon.seed !== undefined) query.set('seed', String(weapon.seed));\n if (weapon.float !== undefined)\n query.set('float', String(weapon.float));\n if (weapon.stattrak) query.set('stattrak', '1');\n if (weapon.kills !== undefined)\n query.set('kills', String(weapon.kills));\n if (weapon.name !== undefined) query.set('name', weapon.name);\n }\n if (environment) query.set('env', environment);\n if (background?.type === EBackgroundType.NONE)\n query.set('backdrop', 'false');\n if (interactive === false) query.set('interactive', 'false');\n if (autoplay) query.set('autoplay', '1');\n if (locale) query.set('lang', locale);\n const suffix = query.toString();\n return `${baseUrl}/v1/sdk${suffix ? `?${suffix}` : ''}`;\n};\n","// The wire format of the embed protocol, client side. Every name here is contract: a change is\n// an addition, never a redefinition.\n\nexport enum EProtocolMessageKind {\n COMMAND = 'command',\n RESPONSE = 'response',\n EVENT = 'event',\n // The viewer page saying \"I just started, greet me\". It carries no data, and the SDK answers\n // it with the handshake — which is what makes a reloaded viewer pick itself back up.\n ANNOUNCE = 'announce',\n}\n\n// The CLOSED error vocabulary. A code's meaning never changes; branch behavior on the code,\n// never on the message text.\nexport enum EErrorCode {\n INVALID_KEY = 'invalid_key',\n ORIGIN_NOT_ALLOWED = 'origin_not_allowed',\n NOT_ENTITLED = 'not_entitled',\n UNSUPPORTED_VIEW = 'unsupported_view',\n UNAVAILABLE_ITEM = 'unavailable_item',\n INVALID_ARGUMENT = 'invalid_argument',\n NOT_READY = 'not_ready',\n RATE_LIMITED = 'rate_limited',\n INTERNAL = 'internal',\n}\n\nexport enum EProtocolCommand {\n HELLO = 'hello',\n SET_WEAPON = 'setWeapon',\n SET_GLOVES = 'setGloves',\n SET_AGENT = 'setAgent',\n SET_SUBJECT = 'setSubject',\n SET_STICKERS = 'setStickers',\n SET_CHARM = 'setCharm',\n SET_PATCHES = 'setPatches',\n SET_VIEW = 'setView',\n SET_FIRST_PERSON_SETTINGS = 'setFirstPersonSettings',\n SET_FACING = 'setFacing',\n SET_ENVIRONMENT = 'setEnvironment',\n SET_BACKGROUND = 'setBackground',\n FOCUS = 'focus',\n RESET_CAMERA = 'resetCamera',\n PLAY = 'play',\n PAUSE = 'pause',\n PLAY_ANIMATION = 'playAnimation',\n STOP_ANIMATION = 'stopAnimation',\n START_FIRE = 'startFire',\n STOP_FIRE = 'stopFire',\n SET_SOUND = 'setSound',\n SET_LOCALE = 'setLocale',\n ARM_PLACEMENT = 'armPlacement',\n FORWARD_POINTER = 'forwardPointer',\n CAPTURE = 'capture',\n CATALOG_WEAPONS = 'catalogWeapons',\n CATALOG_STICKERS = 'catalogStickers',\n CATALOG_CHARMS = 'catalogCharms',\n CATALOG_PATCHES = 'catalogPatches',\n CATALOG_AGENTS = 'catalogAgents',\n CATALOG_WEAPON_MODELS = 'catalogWeaponModels',\n CATALOG_ENVIRONMENTS = 'catalogEnvironments',\n DESTROY = 'destroy',\n}\n\n// Every event the viewer emits, in glued lowercase: `<thing>change` for a state change (always\n// carrying what changed), a `start`/`move`/`end` triplet for a continuous gesture, a bare noun\n// for an isolated fact.\nexport enum EViewerEvent {\n READY = 'ready',\n ERROR = 'error',\n // The viewer reloaded and was greeted again: everything you had set is gone with the page\n // it lived in, and the scene is blank. Re-apply what you want on screen when you get this.\n RECONNECT = 'reconnect',\n PROGRESS = 'progress',\n UNAVAILABLE = 'unavailable',\n CHANGE = 'change',\n VIEW_CHANGE = 'viewchange',\n SUBJECT_CHANGE = 'subjectchange',\n COSMETICS_CHANGE = 'cosmeticschange',\n ANIMATION_CHANGE = 'animationchange',\n PLAYBACK_CHANGE = 'playbackchange',\n CAPABILITIES_CHANGE = 'capabilitieschange',\n PLACEMENT_START = 'placementstart',\n PLACEMENT_MOVE = 'placementmove',\n PLACEMENT_END = 'placementend',\n}\n\nexport type ViewerError = {\n code: EErrorCode;\n message?: string;\n};\n\nexport type ProtocolResponseMessage = {\n source: string;\n version: number;\n kind: EProtocolMessageKind.RESPONSE;\n id: string;\n} & ({ ok: true; value?: unknown } | { ok: false; error: ViewerError });\n\nexport type ProtocolEventMessage = {\n source: string;\n version: number;\n kind: EProtocolMessageKind.EVENT;\n name: EViewerEvent;\n payload?: unknown;\n};\n","import type { ViewerCapabilities, ViewerState } from '@/contract/interfaces';\nimport type { Viewer, ViewerMirror } from '@/lib/interfaces';\nimport type { ViewerEventHub } from '@/lib/helpers/createViewerEventHub';\nimport type { ViewerTransport } from '@/lib/helpers/createViewerTransport';\nimport { EProtocolCommand } from '@/protocol/interfaces';\n\n// The typed handle the integrator holds: every method one options object, one command, one\n// promise. The state and capability getters read the mirror synchronously — never an await.\nexport const buildViewerHandle = ({\n transport,\n hub,\n mirror,\n iframe,\n destroy,\n}: {\n transport: ViewerTransport;\n hub: ViewerEventHub;\n mirror: ViewerMirror;\n iframe: HTMLIFrameElement;\n destroy: () => void;\n}): Viewer => {\n const command = (\n name: EProtocolCommand,\n payload?: unknown,\n ): Promise<void> => transport.send({ name, payload }).then(() => undefined);\n\n return {\n get state() {\n return mirror.state as ViewerState;\n },\n get capabilities() {\n return mirror.capabilities as ViewerCapabilities;\n },\n on: (event, handler) => hub.on(event, handler),\n setWeapon: (args) => command(EProtocolCommand.SET_WEAPON, args),\n setGloves: (args) => command(EProtocolCommand.SET_GLOVES, args),\n setAgent: (args) => command(EProtocolCommand.SET_AGENT, args),\n setSubject: (args) => command(EProtocolCommand.SET_SUBJECT, args),\n setStickers: (args) => command(EProtocolCommand.SET_STICKERS, args),\n setCharm: (args) => command(EProtocolCommand.SET_CHARM, args),\n setPatches: (args) => command(EProtocolCommand.SET_PATCHES, args),\n setView: (args) => command(EProtocolCommand.SET_VIEW, args),\n setFirstPersonSettings: (args) =>\n command(EProtocolCommand.SET_FIRST_PERSON_SETTINGS, args),\n setFacing: (args) => command(EProtocolCommand.SET_FACING, args),\n setEnvironment: (args) =>\n command(EProtocolCommand.SET_ENVIRONMENT, args),\n setBackground: (args) => command(EProtocolCommand.SET_BACKGROUND, args),\n setSound: (args) => command(EProtocolCommand.SET_SOUND, args),\n setLocale: (args) => command(EProtocolCommand.SET_LOCALE, args),\n focus: (args) => command(EProtocolCommand.FOCUS, args),\n resetCamera: () => command(EProtocolCommand.RESET_CAMERA),\n play: () => command(EProtocolCommand.PLAY),\n pause: () => command(EProtocolCommand.PAUSE),\n playAnimation: (args) => command(EProtocolCommand.PLAY_ANIMATION, args),\n stopAnimation: () => command(EProtocolCommand.STOP_ANIMATION),\n startFire: () => command(EProtocolCommand.START_FIRE),\n stopFire: () => command(EProtocolCommand.STOP_FIRE),\n armPlacement: (args) => command(EProtocolCommand.ARM_PLACEMENT, args),\n forwardPointer: ({ x, y, phase }) => {\n const rect = iframe.getBoundingClientRect();\n return command(EProtocolCommand.FORWARD_POINTER, {\n x: x - rect.left,\n y: y - rect.top,\n phase,\n });\n },\n capture: () =>\n transport\n .send({ name: EProtocolCommand.CAPTURE })\n .then((value) => (value as { image: string }).image),\n catalog: {\n weapons: (query) =>\n transport.send({\n name: EProtocolCommand.CATALOG_WEAPONS,\n payload: query,\n }),\n stickers: (query) =>\n transport.send({\n name: EProtocolCommand.CATALOG_STICKERS,\n payload: query,\n }),\n charms: (query) =>\n transport.send({\n name: EProtocolCommand.CATALOG_CHARMS,\n payload: query,\n }),\n patches: (query) =>\n transport.send({\n name: EProtocolCommand.CATALOG_PATCHES,\n payload: query,\n }),\n agents: (query) =>\n transport.send({\n name: EProtocolCommand.CATALOG_AGENTS,\n payload: query,\n }),\n weaponModels: () =>\n transport.send({\n name: EProtocolCommand.CATALOG_WEAPON_MODELS,\n }),\n environments: () =>\n transport.send({\n name: EProtocolCommand.CATALOG_ENVIRONMENTS,\n }),\n },\n destroy,\n };\n};\n","// The viewer's frame: an implementation detail the integrator never touches, filling the\n// container it is handed.\nexport const createEmbedIframe = ({\n src,\n}: {\n src: string;\n}): HTMLIFrameElement => {\n const iframe = document.createElement('iframe');\n iframe.src = src;\n iframe.style.width = '100%';\n iframe.style.height = '100%';\n iframe.style.display = 'block';\n iframe.style.border = '0';\n // Browsers composite a dark-scheme iframe on a light host as OPAQUE: pinning the scheme is\n // what keeps the transparent background actually transparent. You never have to know this.\n iframe.style.colorScheme = 'normal';\n iframe.allow = 'fullscreen';\n return iframe;\n};\n","import type { ViewerCapabilities, ViewerState } from '@/contract/interfaces';\nimport type { ViewerEventHandler, ViewerMirror } from '@/lib/interfaces';\nimport { EViewerEvent } from '@/protocol/interfaces';\n\nexport type ViewerEventHub = {\n on: (event: string, handler: ViewerEventHandler) => () => void;\n dispatch: ({ name, payload }: { name: string; payload: unknown }) => void;\n clear: () => void;\n};\n\n// The subscription side of the viewer, and the mirror's one writer: a `change` carries the\n// whole state, `capabilitieschange` the whole capability map — absorbed before the handlers\n// run, so a handler reading `viewer.state` already sees the truth it was told about.\nexport const createViewerEventHub = ({\n mirror,\n}: {\n mirror: ViewerMirror;\n}): ViewerEventHub => {\n const handlers = new Map<string, Set<ViewerEventHandler>>();\n\n return {\n on: (event, handler) => {\n const set = handlers.get(event) ?? new Set();\n set.add(handler);\n handlers.set(event, set);\n return () => {\n set.delete(handler);\n };\n },\n dispatch: ({ name, payload }) => {\n if (name === EViewerEvent.CHANGE) {\n const change = payload as { state?: ViewerState } | undefined;\n if (change?.state) mirror.state = change.state;\n }\n if (name === EViewerEvent.CAPABILITIES_CHANGE) {\n const change = payload as\n { capabilities?: ViewerCapabilities } | undefined;\n if (change?.capabilities)\n mirror.capabilities = change.capabilities;\n }\n for (const handler of handlers.get(name) ?? []) handler(payload);\n },\n clear: () => handlers.clear(),\n };\n};\n","let sequence = 0;\n\n// Correlation ids only need to be unique within one page's lifetime; the random prefix keeps\n// two viewers on the same page from ever colliding.\nconst prefix = Math.random().toString(36).slice(2, 8);\n\nexport const createCommandId = (): string => `${prefix}-${++sequence}`;\n","// The wire identity of every message crossing the iframe boundary. This file is the PUBLIC\n// twin of the render service's own declaration: the package cannot depend on private code, so\n// the wire format is declared on both sides and a conformity bench proves they never drift.\nexport const PROTOCOL_SOURCE = 'vskin-render';\n\n// One dial only: the protocol version this package ships is the version it speaks — never\n// overridden at run time. The service supports the current version and the previous one.\nexport const PROTOCOL_VERSION = 1;\n","import { COMMAND_TIMEOUT_MS } from '@/lib/constants';\nimport { createCommandId } from '@/lib/helpers/createCommandId';\nimport { PROTOCOL_SOURCE, PROTOCOL_VERSION } from '@/protocol/constants';\nimport { EErrorCode, EProtocolMessageKind } from '@/protocol/interfaces';\nimport type { ViewerError } from '@/protocol/interfaces';\n\nexport type ViewerTransport = {\n send: (args: {\n name: string;\n payload?: unknown;\n timeoutMs?: number;\n }) => Promise<unknown>;\n start: () => void;\n stop: () => void;\n // Settles every pending command with the given refusal — the teardown's last word.\n rejectAll: (args: { message: string }) => void;\n};\n\n// The wire side of the viewer: posts commands to the iframe at its precise origin, correlates\n// the one response each command gets, forwards events up. Everything else on the shared\n// `window` is ignored — responses are accepted only from OUR iframe's window AND origin.\nexport const createViewerTransport = ({\n iframe,\n embedOrigin,\n isDestroyed,\n onEvent,\n onAnnounce,\n}: {\n iframe: HTMLIFrameElement;\n embedOrigin: string;\n isDestroyed: () => boolean;\n onEvent: ({ name, payload }: { name: string; payload: unknown }) => void;\n // The page saying it just started. Fires on its first boot and again on every reload.\n onAnnounce: () => void;\n}): ViewerTransport => {\n const pending = new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: ViewerError) => void;\n timer: ReturnType<typeof setTimeout>;\n }\n >();\n\n const handleMessage = (event: MessageEvent) => {\n if (event.source !== iframe.contentWindow) return;\n if (event.origin !== embedOrigin) return;\n const data = event.data as\n { source?: unknown; kind?: unknown } | null | undefined;\n if (!data || data.source !== PROTOCOL_SOURCE) return;\n if (data.kind === EProtocolMessageKind.RESPONSE) {\n const response = event.data as {\n id: string;\n ok: boolean;\n value?: unknown;\n error?: ViewerError;\n };\n const waiter = pending.get(response.id);\n if (!waiter) return;\n pending.delete(response.id);\n clearTimeout(waiter.timer);\n if (response.ok) waiter.resolve(response.value);\n else waiter.reject(response.error ?? { code: EErrorCode.INTERNAL });\n return;\n }\n if (data.kind === EProtocolMessageKind.EVENT) {\n const message = event.data as { name: string; payload?: unknown };\n onEvent({ name: message.name, payload: message.payload });\n return;\n }\n if (data.kind === EProtocolMessageKind.ANNOUNCE) onAnnounce();\n };\n\n const send = ({\n name,\n payload,\n timeoutMs = COMMAND_TIMEOUT_MS,\n }: {\n name: string;\n payload?: unknown;\n timeoutMs?: number;\n }): Promise<unknown> => {\n if (isDestroyed()) {\n return Promise.reject({\n code: EErrorCode.NOT_READY,\n message: 'this viewer was destroyed',\n } satisfies ViewerError);\n }\n const id = createCommandId();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pending.delete(id);\n reject({\n code: EErrorCode.INTERNAL,\n message: 'the viewer did not answer',\n } satisfies ViewerError);\n }, timeoutMs);\n pending.set(id, { resolve, reject, timer });\n iframe.contentWindow?.postMessage(\n {\n source: PROTOCOL_SOURCE,\n version: PROTOCOL_VERSION,\n kind: EProtocolMessageKind.COMMAND,\n id,\n name,\n payload,\n },\n embedOrigin,\n );\n });\n };\n\n return {\n send,\n start: () => window.addEventListener('message', handleMessage),\n stop: () => window.removeEventListener('message', handleMessage),\n rejectAll: ({ message }) => {\n for (const [, waiter] of pending) {\n clearTimeout(waiter.timer);\n waiter.reject({ code: EErrorCode.NOT_READY, message });\n }\n pending.clear();\n },\n };\n};\n","import { HELLO_RETRY_MS, HELLO_TIMEOUT_MS } from '@/lib/constants';\nimport type { ViewerMirror } from '@/lib/interfaces';\nimport type { ViewerTransport } from '@/lib/helpers/createViewerTransport';\nimport { PROTOCOL_VERSION } from '@/protocol/constants';\nimport { EErrorCode, EProtocolCommand } from '@/protocol/interfaces';\nimport type { ViewerError } from '@/protocol/interfaces';\nimport type { ViewerCapabilities, ViewerState } from '@/contract/interfaces';\n\n// The handshake: retried until the page's bridge is up, refused whole after the timeout. Its\n// answer seeds the mirror — whatever happened before the client was listening is in it.\nexport const performHandshake = ({\n transport,\n iframe,\n mirror,\n onGiveUp,\n}: {\n transport: ViewerTransport;\n iframe: HTMLIFrameElement;\n mirror: ViewerMirror;\n // Called once when the handshake is abandoned, before the rejection reaches the caller.\n onGiveUp: () => void;\n}): Promise<void> =>\n new Promise<void>((resolve, reject) => {\n let settled = false;\n const beginAt = Date.now();\n // The listener outlives nothing: a handshake is run again on every reload, and one\n // left behind per run would pile up on the frame.\n const settle = () => {\n settled = true;\n iframe.removeEventListener('load', attempt);\n };\n const attempt = () => {\n if (settled) return;\n if (Date.now() - beginAt > HELLO_TIMEOUT_MS) {\n settle();\n onGiveUp();\n return reject({\n code: EErrorCode.INVALID_KEY,\n message:\n 'the viewer never answered: the key was refused, this domain is not declared for it, or the render service is unreachable',\n } satisfies ViewerError);\n }\n transport\n .send({\n name: EProtocolCommand.HELLO,\n payload: { version: PROTOCOL_VERSION },\n timeoutMs: HELLO_RETRY_MS,\n })\n .then((value) => {\n if (settled) return;\n settle();\n const hello = value as {\n state?: ViewerState;\n capabilities?: ViewerCapabilities;\n };\n mirror.state = hello.state ?? mirror.state;\n mirror.capabilities =\n hello.capabilities ?? mirror.capabilities;\n resolve();\n })\n .catch(() => setTimeout(attempt, HELLO_RETRY_MS));\n };\n iframe.addEventListener('load', attempt);\n // A cached iframe can be complete before the listener lands.\n setTimeout(attempt, HELLO_RETRY_MS);\n });\n","// The viewer factory: creates the render iframe on the VSkin origin, drives it by messages,\n// and hands back a typed handle plus a catalog client. This file only assembles — the frame,\n// the transport, the event hub, the handle and the handshake are each their own helper.\n\nimport { DEFAULT_BASE_URL } from '@/lib/constants';\nimport { buildEmbedUrl } from '@/lib/helpers/buildEmbedUrl';\nimport { buildViewerHandle } from '@/lib/helpers/buildViewerHandle';\nimport { createEmbedIframe } from '@/lib/helpers/createEmbedIframe';\nimport { createViewerEventHub } from '@/lib/helpers/createViewerEventHub';\nimport { createViewerTransport } from '@/lib/helpers/createViewerTransport';\nimport { performHandshake } from '@/lib/helpers/performHandshake';\nimport type {\n CreateViewerOptions,\n Viewer,\n ViewerMirror,\n} from '@/lib/interfaces';\nimport { EProtocolCommand, EViewerEvent } from '@/protocol/interfaces';\nimport type { ViewerError } from '@/protocol/interfaces';\n\nexport type {\n CatalogQuery,\n CreateViewerOptions,\n Viewer,\n ViewerEventHandler,\n} from '@/lib/interfaces';\n\nexport const createViewer = ({\n container,\n key,\n baseUrl = DEFAULT_BASE_URL,\n weapon,\n environment,\n background,\n interactive,\n autoplay,\n locale,\n}: CreateViewerOptions): Promise<Viewer> => {\n const embedOrigin = new URL(baseUrl).origin;\n const iframe = createEmbedIframe({\n src: buildEmbedUrl({\n baseUrl,\n key,\n weapon,\n environment,\n background,\n interactive,\n autoplay,\n locale,\n }),\n });\n const mirror: ViewerMirror = { state: null, capabilities: null };\n const hub = createViewerEventHub({ mirror });\n let destroyed = false;\n // Whether a bridge has been greeted. What it guards: the FIRST announce is the page's\n // ordinary boot, which the handshake below is already answering; every later one means the\n // frame reloaded under us and the greeting has to be done again.\n let greeted = false;\n let greetingAgain = false;\n\n const greetAgain = () => {\n if (!greeted || greetingAgain || destroyed) return;\n greetingAgain = true;\n // Whatever was in flight died with the page that owed it an answer.\n transport.rejectAll({ message: 'the viewer reloaded' });\n void performHandshake({\n transport,\n iframe,\n mirror,\n // A reload that never answers leaves the viewer as it is: the frame is the\n // integrator's to keep or drop, and an error says so.\n onGiveUp: () => undefined,\n })\n .then(() =>\n hub.dispatch({\n name: EViewerEvent.RECONNECT,\n payload: undefined,\n }),\n )\n .catch((error: ViewerError) =>\n hub.dispatch({ name: EViewerEvent.ERROR, payload: error }),\n )\n .finally(() => {\n greetingAgain = false;\n });\n };\n\n const transport = createViewerTransport({\n iframe,\n embedOrigin,\n isDestroyed: () => destroyed,\n onEvent: hub.dispatch,\n onAnnounce: greetAgain,\n });\n\n const destroy = () => {\n if (destroyed) return;\n // The goodbye posts BEFORE the flag flips — a destroyed transport refuses to send.\n void transport\n .send({ name: EProtocolCommand.DESTROY })\n .catch(() => undefined);\n destroyed = true;\n transport.stop();\n iframe.remove();\n transport.rejectAll({ message: 'this viewer was destroyed' });\n hub.clear();\n };\n\n const viewer = buildViewerHandle({\n transport,\n hub,\n mirror,\n iframe,\n destroy,\n });\n\n transport.start();\n container.appendChild(iframe);\n\n return performHandshake({\n transport,\n iframe,\n mirror,\n onGiveUp: destroy,\n }).then(() => {\n greeted = true;\n return viewer;\n });\n};\n","import { CS2_INSPECT_LINK_PREFIX } from '@/lib/constants';\n\n// The steam:// inspect link for an item certificate. Pure and instant — the certificate IS the\n// link's payload, so this never talks to the viewer and works with no viewer mounted at all.\nexport const buildInspectLink = ({ cert }: { cert: string }): string =>\n `${CS2_INSPECT_LINK_PREFIX}${cert}`;\n"]}
1
+ {"version":3,"sources":["../src/lib/constants.ts","../src/contract/interfaces.ts","../src/lib/helpers/buildEmbedUrl.ts","../src/protocol/interfaces.ts","../src/lib/helpers/buildViewerHandle.ts","../src/lib/helpers/createEmbedIframe.ts","../src/lib/helpers/createViewerEventHub.ts","../src/lib/helpers/createCommandId.ts","../src/protocol/constants.ts","../src/lib/helpers/createViewerTransport.ts","../src/lib/helpers/performHandshake.ts","../src/lib/createViewer.ts","../src/lib/buildInspectLink.ts"],"names":["EView","EBackgroundType","EFacing","EHandedness","ESubject","EFeature","EErrorCode","ERefusalFamily","EViewerEvent"],"mappings":"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","file":"index.cjs","sourcesContent":["// Where the viewer lives when the integration does not say otherwise.\nexport const DEFAULT_BASE_URL = 'https://render.vskin.gg';\n\n// The embed page answers the handshake as soon as its bridge is up — retried because the page\n// boots asynchronously behind the iframe's load event.\nexport const HELLO_RETRY_MS = 300;\nexport const HELLO_TIMEOUT_MS = 15000;\n\n// A command that never comes back (the page died, the network broke) must not hang a client's\n// await forever.\nexport const COMMAND_TIMEOUT_MS = 30000;\n\n// The command Steam itself serves in its inventory and market payloads. The space is\n// percent-encoded on purpose: a literal space truncates the steam:// command.\nexport const CS2_INSPECT_LINK_PREFIX =\n 'steam://run/730//+csgo_econ_action_preview%20';\n","// The viewer's public vocabulary: domain words only, no abbreviation, one options object per\n// method, enums whose values ARE the strings a plain-JavaScript consumer writes.\n\nexport enum EView {\n FREE = 'free',\n FIRST_PERSON = 'firstPerson',\n THIRD_PERSON = 'thirdPerson',\n}\n\n// The background is a VALUE, not a boolean: `none` composites the canvas straight onto your\n// page (put your own background behind the viewer), `environment` shows the map's own decor.\nexport enum EBackgroundType {\n NONE = 'none',\n ENVIRONMENT = 'environment',\n}\n\nexport type Background = {\n type: EBackgroundType;\n};\n\nexport enum EFacing {\n FRONT = 'front',\n BACK = 'back',\n}\n\nexport enum EHandedness {\n RIGHT = 'right',\n LEFT = 'left',\n}\n\n// Which of the two picked items the free view presents when a weapon and a pair of gloves are\n// both on stage.\nexport enum ESubject {\n WEAPON = 'weapon',\n GLOVES = 'gloves',\n}\n\n// The weapon as you describe it — identity, roll, marks — in the market's own words (`seed`\n// and `float`). The viewer owns the road to it: a seed or float alone re-rolls in place, a\n// name alone re-engraves the plate, a new identity re-mounts.\nexport type Weapon = {\n // The inspect certificate (hex), the market door: it carries identity, roll and cosmetics.\n cert?: string;\n // The manual door: the item's definition and finish indices.\n defIndex?: number;\n paintIndex?: number;\n seed?: number;\n float?: number;\n stattrak?: boolean;\n kills?: number;\n name?: string;\n};\n\nexport type Gloves = {\n cert?: string;\n defIndex?: number;\n paintIndex?: number;\n seed?: number;\n float?: number;\n};\n\nexport type Agent = {\n // The inspect certificate (hex): a character travels by cert too, patches included.\n cert?: string;\n defIndex?: number;\n};\n\nexport type Sticker = {\n id: number;\n slot: number;\n wear?: number;\n rotation?: number;\n offsetX?: number;\n offsetY?: number;\n};\n\nexport type Charm = {\n id: number;\n pattern?: number;\n // The display-case family: the sticker sealed inside the slab, by its id.\n wrappedSticker?: number;\n // The charm's placement, as a DELTA from the weapon's default hook in the weapon's model\n // space (Source inches) — the same numbers a free-placement drag settles on. Absent = the\n // authored hook. The state mirror's `charmAnchor` publishes the composed ABSOLUTE.\n offsetX?: number;\n offsetY?: number;\n offsetZ?: number;\n};\n\nexport type Patch = {\n id: number;\n slot: number;\n};\n\n// First-person dials in the GAME's units: `fov` is viewmodel_fov degrees, offsets are\n// viewmodel_offset inches. A new dial is a new FIELD here, never a new method.\nexport type FirstPersonSettings = {\n fov?: number;\n offsetX?: number;\n offsetY?: number;\n offsetZ?: number;\n handedness?: EHandedness;\n};\n\n// The camera's flight target. A sticker is named by its STABLE uid (a certificate may repeat a\n// slot, so a slot is not an identity); the state mirror publishes each sticker's uid.\nexport type FocusTarget =\n | { kind: 'sticker'; uid: string }\n | { kind: 'charm' }\n | { kind: 'patch'; slot: number }\n | null;\n\n// What the free-placement mode is armed on: while armed, pressing that cosmetic in the canvas\n// MOVES it instead of orbiting the item. Null disarms.\nexport type PlacementTarget =\n { kind: 'sticker'; slot: number } | { kind: 'charm' } | null;\n\n// One capability, two layers already intersected for you: `entitled` is what the plan bought\n// (stable for the session), `available` folds in what the current scene can serve (moving;\n// `capabilitieschange` fires when it does).\nexport type Capability = {\n entitled: boolean;\n available: boolean;\n};\n\nexport enum EFeature {\n SELECT_WEAPON = 'selectWeapon',\n SELECT_GLOVES = 'selectGloves',\n SELECT_AGENT = 'selectAgent',\n SELECT_ENVIRONMENT = 'selectEnvironment',\n EDIT_SEED = 'editSeed',\n EDIT_FLOAT = 'editFloat',\n EDIT_STATTRAK = 'editStattrak',\n EDIT_NAMETAG = 'editNametag',\n SELECT_STICKER = 'selectSticker',\n SELECT_CHARM = 'selectCharm',\n SELECT_PATCH = 'selectPatch',\n EDIT_STICKERS = 'editStickers',\n EDIT_CHARMS = 'editCharms',\n PLACE_STICKERS = 'placeStickers',\n PLACE_CHARM = 'placeCharm',\n SCREENSHOT = 'screenshot',\n INSPECT_LINK = 'inspectLink',\n SUBJECT_CONTROLS = 'subjectControls',\n WEAPON_ANIMATIONS = 'weaponAnimations',\n AGENT_ANIMATIONS = 'agentAnimations',\n}\n\nexport type ViewerCapabilities = {\n views: Record<EView, Capability>;\n features: Record<EFeature, Capability>;\n};\n\n// One animation the scene can play, with the one fact you need to offer it honestly: a\n// looping clip is a toggle, a one-shot replays.\nexport type AnimationEntry = {\n name: string;\n loop: boolean;\n};\n\n// The synchronous mirror: the last known truth, re-published whole on every `change` event.\n// Read it without ever awaiting.\nexport type ViewerState = {\n weapon: Weapon | null;\n gloves: Gloves | null;\n agent: Agent | null;\n subject: ESubject | null;\n view: { view: EView; active: boolean };\n environment: string | null;\n background: Background;\n stickers: Array<Sticker & { uid?: string }>;\n charm: Charm | null;\n // Where the charm actually sits, in the form a cert names it: the composed ABSOLUTE\n // position in the weapon's model space, read off the manifest the render is using.\n charmAnchor: [number, number, number] | null;\n patches: Array<Patch>;\n // How many patch slots the mounted character authors — the render's own answer, read off\n // its landed manifest. null while no character manifest has answered (none asked, or still\n // composing): 0 is a real answer, \"this body authors none\".\n patchSlots: number | null;\n playing: boolean;\n animation: string | null;\n animations: Array<AnimationEntry>;\n // The character's celebrations: what the mounted body can play beyond its resting posture,\n // and the one running right now (null at rest). Driven through the same playAnimation /\n // stopAnimation door as the weapon clips.\n agentAnimation: string | null;\n agentAnimations: Array<string>;\n sound: { muted: boolean };\n firstPerson: FirstPersonSettings;\n facing: EFacing;\n placement: PlacementTarget;\n};\n","import type { Background, Weapon } from '@/contract/interfaces';\nimport { EBackgroundType } from '@/contract/interfaces';\n\n// The embed page's URL grammar, written once: the boot seed rides the URL, everything after\n// boot rides the protocol.\nexport const buildEmbedUrl = ({\n baseUrl,\n key,\n weapon,\n environment,\n background,\n interactive,\n autoplay,\n locale,\n}: {\n baseUrl: string;\n key?: string;\n weapon?: Weapon;\n environment?: string;\n background?: Background;\n interactive?: boolean;\n autoplay?: boolean;\n locale?: string;\n}): string => {\n const query = new URLSearchParams();\n if (key) query.set('key', key);\n if (weapon?.cert) {\n query.set('cert', weapon.cert);\n } else if (\n weapon &&\n typeof weapon.defIndex === 'number' &&\n typeof weapon.paintIndex === 'number'\n ) {\n query.set('def', String(weapon.defIndex));\n query.set('paint', String(weapon.paintIndex));\n if (weapon.seed !== undefined) query.set('seed', String(weapon.seed));\n if (weapon.float !== undefined)\n query.set('float', String(weapon.float));\n if (weapon.stattrak) query.set('stattrak', '1');\n if (weapon.kills !== undefined)\n query.set('kills', String(weapon.kills));\n if (weapon.name !== undefined) query.set('name', weapon.name);\n }\n if (environment) query.set('env', environment);\n if (background?.type === EBackgroundType.NONE)\n query.set('backdrop', 'false');\n if (interactive === false) query.set('interactive', 'false');\n if (autoplay) query.set('autoplay', '1');\n if (locale) query.set('lang', locale);\n const suffix = query.toString();\n return `${baseUrl}/v1/sdk${suffix ? `?${suffix}` : ''}`;\n};\n","// The wire format of the embed protocol, client side. Every name here is contract: a change is\n// an addition, never a redefinition.\n\nexport enum EProtocolMessageKind {\n COMMAND = 'command',\n RESPONSE = 'response',\n EVENT = 'event',\n // The viewer page saying \"I just started, greet me\". It carries no data, and the SDK answers\n // it with the handshake — which is what makes a reloaded viewer pick itself back up.\n ANNOUNCE = 'announce',\n}\n\n// The CLOSED error vocabulary. A code's meaning never changes; branch behavior on the code,\n// never on the message text.\nexport enum EErrorCode {\n INVALID_KEY = 'invalid_key',\n ORIGIN_NOT_ALLOWED = 'origin_not_allowed',\n NOT_ENTITLED = 'not_entitled',\n UNSUPPORTED_VIEW = 'unsupported_view',\n UNAVAILABLE_ITEM = 'unavailable_item',\n INVALID_ARGUMENT = 'invalid_argument',\n NOT_READY = 'not_ready',\n RATE_LIMITED = 'rate_limited',\n INTERNAL = 'internal',\n // The embed server refused to serve the viewer at all. `family` on the error says whose\n // problem it is; the frame is left in place, showing the explanation.\n REFUSED = 'refused',\n}\n\n// Whose problem a refusal is, and all you learn of it: your integration mid-setup (a missing\n// key, a page opened outside an iframe), your account no longer opening the door (a revoked or\n// expired key, an undeclared domain, a plan without this surface), or an outage on our side.\nexport enum ERefusalFamily {\n SETUP = 'setup',\n CUT_OFF = 'cut_off',\n OUTAGE = 'outage',\n}\n\nexport enum EProtocolCommand {\n HELLO = 'hello',\n SET_WEAPON = 'setWeapon',\n SET_GLOVES = 'setGloves',\n SET_AGENT = 'setAgent',\n SET_SUBJECT = 'setSubject',\n SET_STICKERS = 'setStickers',\n SET_CHARM = 'setCharm',\n SET_PATCHES = 'setPatches',\n SET_VIEW = 'setView',\n SET_FIRST_PERSON_SETTINGS = 'setFirstPersonSettings',\n SET_FACING = 'setFacing',\n SET_ENVIRONMENT = 'setEnvironment',\n SET_BACKGROUND = 'setBackground',\n FOCUS = 'focus',\n RESET_CAMERA = 'resetCamera',\n PLAY = 'play',\n PAUSE = 'pause',\n PLAY_ANIMATION = 'playAnimation',\n STOP_ANIMATION = 'stopAnimation',\n START_FIRE = 'startFire',\n STOP_FIRE = 'stopFire',\n SET_SOUND = 'setSound',\n SET_LOCALE = 'setLocale',\n ARM_PLACEMENT = 'armPlacement',\n FORWARD_POINTER = 'forwardPointer',\n CAPTURE = 'capture',\n CATALOG_WEAPONS = 'catalogWeapons',\n CATALOG_STICKERS = 'catalogStickers',\n CATALOG_CHARMS = 'catalogCharms',\n CATALOG_PATCHES = 'catalogPatches',\n CATALOG_AGENTS = 'catalogAgents',\n CATALOG_WEAPON_MODELS = 'catalogWeaponModels',\n CATALOG_ENVIRONMENTS = 'catalogEnvironments',\n DESTROY = 'destroy',\n}\n\n// Every event the viewer emits, in glued lowercase: `<thing>change` for a state change (always\n// carrying what changed), a `start`/`move`/`end` triplet for a continuous gesture, a bare noun\n// for an isolated fact.\nexport enum EViewerEvent {\n READY = 'ready',\n ERROR = 'error',\n // The viewer reloaded and was greeted again: everything you had set is gone with the page\n // it lived in, and the scene is blank. Re-apply what you want on screen when you get this.\n RECONNECT = 'reconnect',\n PROGRESS = 'progress',\n UNAVAILABLE = 'unavailable',\n CHANGE = 'change',\n VIEW_CHANGE = 'viewchange',\n SUBJECT_CHANGE = 'subjectchange',\n COSMETICS_CHANGE = 'cosmeticschange',\n ANIMATION_CHANGE = 'animationchange',\n PLAYBACK_CHANGE = 'playbackchange',\n CAPABILITIES_CHANGE = 'capabilitieschange',\n PLACEMENT_START = 'placementstart',\n PLACEMENT_MOVE = 'placementmove',\n PLACEMENT_END = 'placementend',\n // Posted by the embed server's refusal page, never by a booted viewer: the frame is showing\n // a refusal screen. Never reaches `on`: it settles `createViewer` with a `refused` error.\n REFUSED = 'refused',\n}\n\nexport type ViewerError = {\n code: EErrorCode;\n message?: string;\n // With `refused` only: whose problem it is.\n family?: ERefusalFamily;\n};\n\nexport type ProtocolResponseMessage = {\n source: string;\n version: number;\n kind: EProtocolMessageKind.RESPONSE;\n id: string;\n} & ({ ok: true; value?: unknown } | { ok: false; error: ViewerError });\n\nexport type ProtocolEventMessage = {\n source: string;\n version: number;\n kind: EProtocolMessageKind.EVENT;\n name: EViewerEvent;\n payload?: unknown;\n};\n","import type { ViewerCapabilities, ViewerState } from '@/contract/interfaces';\nimport type { Viewer, ViewerMirror } from '@/lib/interfaces';\nimport type { ViewerEventHub } from '@/lib/helpers/createViewerEventHub';\nimport type { ViewerTransport } from '@/lib/helpers/createViewerTransport';\nimport { EProtocolCommand } from '@/protocol/interfaces';\n\n// The typed handle the integrator holds: every method one options object, one command, one\n// promise. The state and capability getters read the mirror synchronously — never an await.\nexport const buildViewerHandle = ({\n transport,\n hub,\n mirror,\n iframe,\n destroy,\n}: {\n transport: ViewerTransport;\n hub: ViewerEventHub;\n mirror: ViewerMirror;\n iframe: HTMLIFrameElement;\n destroy: () => void;\n}): Viewer => {\n const command = (\n name: EProtocolCommand,\n payload?: unknown,\n ): Promise<void> => transport.send({ name, payload }).then(() => undefined);\n\n return {\n get state() {\n return mirror.state as ViewerState;\n },\n get capabilities() {\n return mirror.capabilities as ViewerCapabilities;\n },\n on: (event, handler) => hub.on(event, handler),\n setWeapon: (args) => command(EProtocolCommand.SET_WEAPON, args),\n setGloves: (args) => command(EProtocolCommand.SET_GLOVES, args),\n setAgent: (args) => command(EProtocolCommand.SET_AGENT, args),\n setSubject: (args) => command(EProtocolCommand.SET_SUBJECT, args),\n setStickers: (args) => command(EProtocolCommand.SET_STICKERS, args),\n setCharm: (args) => command(EProtocolCommand.SET_CHARM, args),\n setPatches: (args) => command(EProtocolCommand.SET_PATCHES, args),\n setView: (args) => command(EProtocolCommand.SET_VIEW, args),\n setFirstPersonSettings: (args) =>\n command(EProtocolCommand.SET_FIRST_PERSON_SETTINGS, args),\n setFacing: (args) => command(EProtocolCommand.SET_FACING, args),\n setEnvironment: (args) =>\n command(EProtocolCommand.SET_ENVIRONMENT, args),\n setBackground: (args) => command(EProtocolCommand.SET_BACKGROUND, args),\n setSound: (args) => command(EProtocolCommand.SET_SOUND, args),\n setLocale: (args) => command(EProtocolCommand.SET_LOCALE, args),\n focus: (args) => command(EProtocolCommand.FOCUS, args),\n resetCamera: () => command(EProtocolCommand.RESET_CAMERA),\n play: () => command(EProtocolCommand.PLAY),\n pause: () => command(EProtocolCommand.PAUSE),\n playAnimation: (args) => command(EProtocolCommand.PLAY_ANIMATION, args),\n stopAnimation: () => command(EProtocolCommand.STOP_ANIMATION),\n startFire: () => command(EProtocolCommand.START_FIRE),\n stopFire: () => command(EProtocolCommand.STOP_FIRE),\n armPlacement: (args) => command(EProtocolCommand.ARM_PLACEMENT, args),\n forwardPointer: ({ x, y, phase }) => {\n const rect = iframe.getBoundingClientRect();\n return command(EProtocolCommand.FORWARD_POINTER, {\n x: x - rect.left,\n y: y - rect.top,\n phase,\n });\n },\n capture: () =>\n transport\n .send({ name: EProtocolCommand.CAPTURE })\n .then((value) => (value as { image: string }).image),\n catalog: {\n weapons: (query) =>\n transport.send({\n name: EProtocolCommand.CATALOG_WEAPONS,\n payload: query,\n }),\n stickers: (query) =>\n transport.send({\n name: EProtocolCommand.CATALOG_STICKERS,\n payload: query,\n }),\n charms: (query) =>\n transport.send({\n name: EProtocolCommand.CATALOG_CHARMS,\n payload: query,\n }),\n patches: (query) =>\n transport.send({\n name: EProtocolCommand.CATALOG_PATCHES,\n payload: query,\n }),\n agents: (query) =>\n transport.send({\n name: EProtocolCommand.CATALOG_AGENTS,\n payload: query,\n }),\n weaponModels: () =>\n transport.send({\n name: EProtocolCommand.CATALOG_WEAPON_MODELS,\n }),\n environments: () =>\n transport.send({\n name: EProtocolCommand.CATALOG_ENVIRONMENTS,\n }),\n },\n destroy,\n };\n};\n","// The viewer's frame: an implementation detail the integrator never touches, filling the\n// container it is handed.\nexport const createEmbedIframe = ({\n src,\n}: {\n src: string;\n}): HTMLIFrameElement => {\n const iframe = document.createElement('iframe');\n iframe.src = src;\n iframe.style.width = '100%';\n iframe.style.height = '100%';\n iframe.style.display = 'block';\n iframe.style.border = '0';\n // Browsers composite a dark-scheme iframe on a light host as OPAQUE: pinning the scheme is\n // what keeps the transparent background actually transparent. You never have to know this.\n iframe.style.colorScheme = 'normal';\n iframe.allow = 'fullscreen';\n return iframe;\n};\n","import type { ViewerCapabilities, ViewerState } from '@/contract/interfaces';\nimport type { ViewerEventHandler, ViewerMirror } from '@/lib/interfaces';\nimport { EViewerEvent } from '@/protocol/interfaces';\n\nexport type ViewerEventHub = {\n on: (event: string, handler: ViewerEventHandler) => () => void;\n dispatch: ({ name, payload }: { name: string; payload: unknown }) => void;\n clear: () => void;\n};\n\n// The subscription side of the viewer, and the mirror's one writer: a `change` carries the\n// whole state, `capabilitieschange` the whole capability map — absorbed before the handlers\n// run, so a handler reading `viewer.state` already sees the truth it was told about.\nexport const createViewerEventHub = ({\n mirror,\n}: {\n mirror: ViewerMirror;\n}): ViewerEventHub => {\n const handlers = new Map<string, Set<ViewerEventHandler>>();\n\n return {\n on: (event, handler) => {\n const set = handlers.get(event) ?? new Set();\n set.add(handler);\n handlers.set(event, set);\n return () => {\n set.delete(handler);\n };\n },\n dispatch: ({ name, payload }) => {\n if (name === EViewerEvent.CHANGE) {\n const change = payload as { state?: ViewerState } | undefined;\n if (change?.state) mirror.state = change.state;\n }\n if (name === EViewerEvent.CAPABILITIES_CHANGE) {\n const change = payload as\n { capabilities?: ViewerCapabilities } | undefined;\n if (change?.capabilities)\n mirror.capabilities = change.capabilities;\n }\n for (const handler of handlers.get(name) ?? []) handler(payload);\n },\n clear: () => handlers.clear(),\n };\n};\n","let sequence = 0;\n\n// Correlation ids only need to be unique within one page's lifetime; the random prefix keeps\n// two viewers on the same page from ever colliding.\nconst prefix = Math.random().toString(36).slice(2, 8);\n\nexport const createCommandId = (): string => `${prefix}-${++sequence}`;\n","// The wire identity of every message crossing the iframe boundary. This file is the PUBLIC\n// twin of the render service's own declaration: the package cannot depend on private code, so\n// the wire format is declared on both sides and a conformity bench proves they never drift.\nexport const PROTOCOL_SOURCE = 'vskin-render';\n\n// One dial only: the protocol version this package ships is the version it speaks — never\n// overridden at run time. The service supports the current version and the previous one.\nexport const PROTOCOL_VERSION = 1;\n","import { COMMAND_TIMEOUT_MS } from '@/lib/constants';\nimport { createCommandId } from '@/lib/helpers/createCommandId';\nimport { PROTOCOL_SOURCE, PROTOCOL_VERSION } from '@/protocol/constants';\nimport { EErrorCode, EProtocolMessageKind } from '@/protocol/interfaces';\nimport type { ViewerError } from '@/protocol/interfaces';\n\nexport type ViewerTransport = {\n send: (args: {\n name: string;\n payload?: unknown;\n timeoutMs?: number;\n }) => Promise<unknown>;\n start: () => void;\n stop: () => void;\n // Settles every pending command with the given refusal — the teardown's last word.\n rejectAll: (args: { message: string }) => void;\n};\n\n// The wire side of the viewer: posts commands to the iframe at its precise origin, correlates\n// the one response each command gets, forwards events up. Everything else on the shared\n// `window` is ignored — responses are accepted only from OUR iframe's window AND origin.\nexport const createViewerTransport = ({\n iframe,\n embedOrigin,\n isDestroyed,\n onEvent,\n onAnnounce,\n}: {\n iframe: HTMLIFrameElement;\n embedOrigin: string;\n isDestroyed: () => boolean;\n onEvent: ({ name, payload }: { name: string; payload: unknown }) => void;\n // The page saying it just started. Fires on its first boot and again on every reload.\n onAnnounce: () => void;\n}): ViewerTransport => {\n const pending = new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: ViewerError) => void;\n timer: ReturnType<typeof setTimeout>;\n }\n >();\n\n const handleMessage = (event: MessageEvent) => {\n if (event.source !== iframe.contentWindow) return;\n if (event.origin !== embedOrigin) return;\n const data = event.data as\n { source?: unknown; kind?: unknown } | null | undefined;\n if (!data || data.source !== PROTOCOL_SOURCE) return;\n if (data.kind === EProtocolMessageKind.RESPONSE) {\n const response = event.data as {\n id: string;\n ok: boolean;\n value?: unknown;\n error?: ViewerError;\n };\n const waiter = pending.get(response.id);\n if (!waiter) return;\n pending.delete(response.id);\n clearTimeout(waiter.timer);\n if (response.ok) waiter.resolve(response.value);\n else waiter.reject(response.error ?? { code: EErrorCode.INTERNAL });\n return;\n }\n if (data.kind === EProtocolMessageKind.EVENT) {\n const message = event.data as { name: string; payload?: unknown };\n onEvent({ name: message.name, payload: message.payload });\n return;\n }\n if (data.kind === EProtocolMessageKind.ANNOUNCE) onAnnounce();\n };\n\n const send = ({\n name,\n payload,\n timeoutMs = COMMAND_TIMEOUT_MS,\n }: {\n name: string;\n payload?: unknown;\n timeoutMs?: number;\n }): Promise<unknown> => {\n if (isDestroyed()) {\n return Promise.reject({\n code: EErrorCode.NOT_READY,\n message: 'this viewer was destroyed',\n } satisfies ViewerError);\n }\n const id = createCommandId();\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n pending.delete(id);\n reject({\n code: EErrorCode.INTERNAL,\n message: 'the viewer did not answer',\n } satisfies ViewerError);\n }, timeoutMs);\n pending.set(id, { resolve, reject, timer });\n iframe.contentWindow?.postMessage(\n {\n source: PROTOCOL_SOURCE,\n version: PROTOCOL_VERSION,\n kind: EProtocolMessageKind.COMMAND,\n id,\n name,\n payload,\n },\n embedOrigin,\n );\n });\n };\n\n return {\n send,\n start: () => window.addEventListener('message', handleMessage),\n stop: () => window.removeEventListener('message', handleMessage),\n rejectAll: ({ message }) => {\n for (const [, waiter] of pending) {\n clearTimeout(waiter.timer);\n waiter.reject({ code: EErrorCode.NOT_READY, message });\n }\n pending.clear();\n },\n };\n};\n","import { HELLO_RETRY_MS, HELLO_TIMEOUT_MS } from '@/lib/constants';\nimport type { ViewerMirror } from '@/lib/interfaces';\nimport type { ViewerTransport } from '@/lib/helpers/createViewerTransport';\nimport { PROTOCOL_VERSION } from '@/protocol/constants';\nimport { EErrorCode, EProtocolCommand } from '@/protocol/interfaces';\nimport type { ERefusalFamily, ViewerError } from '@/protocol/interfaces';\nimport type { ViewerCapabilities, ViewerState } from '@/contract/interfaces';\n\n// The handshake: retried until the page's bridge is up, refused whole after the timeout. Its\n// answer seeds the mirror — whatever happened before the client was listening is in it. A page\n// the embed server refused says so itself, and the handshake settles on that word at once.\nexport const performHandshake = ({\n transport,\n iframe,\n mirror,\n onGiveUp,\n subscribeRefusal,\n}: {\n transport: ViewerTransport;\n iframe: HTMLIFrameElement;\n mirror: ViewerMirror;\n // Called once when the handshake is abandoned for want of an answer, before the rejection\n // reaches the caller. NOT called on a refusal: the frame then shows the explanation.\n onGiveUp: () => void;\n // Hands the refusal page's word to the handshake; the returned function unsubscribes.\n subscribeRefusal: (\n handler: (args: { family: ERefusalFamily }) => void,\n ) => () => void;\n}): Promise<void> =>\n new Promise<void>((resolve, reject) => {\n let settled = false;\n const beginAt = Date.now();\n // The listeners outlive nothing: a handshake is run again on every reload, and one\n // left behind per run would pile up on the frame.\n const settle = () => {\n settled = true;\n iframe.removeEventListener('load', attempt);\n unsubscribeRefusal();\n };\n const attempt = () => {\n if (settled) return;\n if (Date.now() - beginAt > HELLO_TIMEOUT_MS) {\n settle();\n onGiveUp();\n return reject({\n code: EErrorCode.INVALID_KEY,\n message:\n 'the viewer never answered: the render service is unreachable, or the frame was blocked before the page could boot',\n } satisfies ViewerError);\n }\n transport\n .send({\n name: EProtocolCommand.HELLO,\n payload: { version: PROTOCOL_VERSION },\n timeoutMs: HELLO_RETRY_MS,\n })\n .then((value) => {\n if (settled) return;\n settle();\n const hello = value as {\n state?: ViewerState;\n capabilities?: ViewerCapabilities;\n };\n mirror.state = hello.state ?? mirror.state;\n mirror.capabilities =\n hello.capabilities ?? mirror.capabilities;\n resolve();\n })\n .catch(() => setTimeout(attempt, HELLO_RETRY_MS));\n };\n const unsubscribeRefusal = subscribeRefusal(({ family }) => {\n if (settled) return;\n settle();\n reject({\n code: EErrorCode.REFUSED,\n family,\n message:\n 'the embed server refused this viewer; its family says whose problem it is',\n } satisfies ViewerError);\n });\n iframe.addEventListener('load', attempt);\n // A cached iframe can be complete before the listener lands.\n setTimeout(attempt, HELLO_RETRY_MS);\n });\n","// The viewer factory: creates the render iframe on the VSkin origin, drives it by messages,\n// and hands back a typed handle plus a catalog client. This file only assembles — the frame,\n// the transport, the event hub, the handle and the handshake are each their own helper.\n\nimport { DEFAULT_BASE_URL } from '@/lib/constants';\nimport { buildEmbedUrl } from '@/lib/helpers/buildEmbedUrl';\nimport { buildViewerHandle } from '@/lib/helpers/buildViewerHandle';\nimport { createEmbedIframe } from '@/lib/helpers/createEmbedIframe';\nimport { createViewerEventHub } from '@/lib/helpers/createViewerEventHub';\nimport { createViewerTransport } from '@/lib/helpers/createViewerTransport';\nimport { performHandshake } from '@/lib/helpers/performHandshake';\nimport type {\n CreateViewerOptions,\n Viewer,\n ViewerMirror,\n} from '@/lib/interfaces';\nimport { EProtocolCommand, EViewerEvent } from '@/protocol/interfaces';\nimport type { ERefusalFamily, ViewerError } from '@/protocol/interfaces';\n\nexport type {\n CatalogQuery,\n CreateViewerOptions,\n Viewer,\n ViewerEventHandler,\n} from '@/lib/interfaces';\n\nexport const createViewer = ({\n container,\n key,\n baseUrl = DEFAULT_BASE_URL,\n weapon,\n environment,\n background,\n interactive,\n autoplay,\n locale,\n}: CreateViewerOptions): Promise<Viewer> => {\n const embedOrigin = new URL(baseUrl).origin;\n const iframe = createEmbedIframe({\n src: buildEmbedUrl({\n baseUrl,\n key,\n weapon,\n environment,\n background,\n interactive,\n autoplay,\n locale,\n }),\n });\n const mirror: ViewerMirror = { state: null, capabilities: null };\n const hub = createViewerEventHub({ mirror });\n let destroyed = false;\n // Whether a bridge has been greeted. What it guards: the FIRST announce is the page's\n // ordinary boot, which the handshake below is already answering; every later one means the\n // frame reloaded under us and the greeting has to be done again.\n let greeted = false;\n let greetingAgain = false;\n\n // The refusal page's word, routed to whichever handshake is waiting for it.\n const subscribeRefusal = (\n handler: (args: { family: ERefusalFamily }) => void,\n ) =>\n hub.on(EViewerEvent.REFUSED, (payload) =>\n handler(payload as { family: ERefusalFamily }),\n );\n\n const greetAgain = () => {\n if (!greeted || greetingAgain || destroyed) return;\n greetingAgain = true;\n // Whatever was in flight died with the page that owed it an answer.\n transport.rejectAll({ message: 'the viewer reloaded' });\n void performHandshake({\n transport,\n iframe,\n mirror,\n // A reload that never answers leaves the viewer as it is: the frame is the\n // integrator's to keep or drop, and an error says so.\n onGiveUp: () => undefined,\n subscribeRefusal,\n })\n .then(() =>\n hub.dispatch({\n name: EViewerEvent.RECONNECT,\n payload: undefined,\n }),\n )\n .catch((error: ViewerError) =>\n hub.dispatch({ name: EViewerEvent.ERROR, payload: error }),\n )\n .finally(() => {\n greetingAgain = false;\n });\n };\n\n const transport = createViewerTransport({\n iframe,\n embedOrigin,\n isDestroyed: () => destroyed,\n onEvent: hub.dispatch,\n onAnnounce: greetAgain,\n });\n\n const destroy = () => {\n if (destroyed) return;\n // The goodbye posts BEFORE the flag flips — a destroyed transport refuses to send.\n void transport\n .send({ name: EProtocolCommand.DESTROY })\n .catch(() => undefined);\n destroyed = true;\n transport.stop();\n iframe.remove();\n transport.rejectAll({ message: 'this viewer was destroyed' });\n hub.clear();\n };\n\n const viewer = buildViewerHandle({\n transport,\n hub,\n mirror,\n iframe,\n destroy,\n });\n\n transport.start();\n container.appendChild(iframe);\n\n // Given up on = destroyed; refused = kept, the frame is showing the visitor why.\n return performHandshake({\n transport,\n iframe,\n mirror,\n onGiveUp: destroy,\n subscribeRefusal,\n }).then(() => {\n greeted = true;\n return viewer;\n });\n};\n","import { CS2_INSPECT_LINK_PREFIX } from '@/lib/constants';\n\n// The steam:// inspect link for an item certificate. Pure and instant — the certificate IS the\n// link's payload, so this never talks to the viewer and works with no viewer mounted at all.\nexport const buildInspectLink = ({ cert }: { cert: string }): string =>\n `${CS2_INSPECT_LINK_PREFIX}${cert}`;\n"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CreateViewerOptions, V as Viewer } from './interfaces-OatKvSe8.cjs';
2
- export { A as Agent, a as AnimationEntry, B as Background, b as Capability, c as CatalogQuery, d as Charm, E as EBackgroundType, e as EErrorCode, f as EFacing, g as EFeature, h as EHandedness, i as ESubject, j as EView, k as EViewerEvent, F as FirstPersonSettings, l as FocusTarget, G as Gloves, P as Patch, m as PlacementTarget, S as Sticker, n as ViewerCapabilities, o as ViewerError, p as ViewerEventHandler, q as ViewerState, W as Weapon } from './interfaces-OatKvSe8.cjs';
1
+ import { C as CreateViewerOptions, V as Viewer } from './interfaces-iOmXANSI.cjs';
2
+ export { A as Agent, a as AnimationEntry, B as Background, b as Capability, c as CatalogQuery, d as Charm, E as EBackgroundType, e as EErrorCode, f as EFacing, g as EFeature, h as EHandedness, i as ERefusalFamily, j as ESubject, k as EView, l as EViewerEvent, F as FirstPersonSettings, m as FocusTarget, G as Gloves, P as Patch, n as PlacementTarget, S as Sticker, o as ViewerCapabilities, p as ViewerError, q as ViewerEventHandler, r as ViewerState, W as Weapon } from './interfaces-iOmXANSI.cjs';
3
3
 
4
4
  declare const createViewer: ({ container, key, baseUrl, weapon, environment, background, interactive, autoplay, locale, }: CreateViewerOptions) => Promise<Viewer>;
5
5
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CreateViewerOptions, V as Viewer } from './interfaces-OatKvSe8.js';
2
- export { A as Agent, a as AnimationEntry, B as Background, b as Capability, c as CatalogQuery, d as Charm, E as EBackgroundType, e as EErrorCode, f as EFacing, g as EFeature, h as EHandedness, i as ESubject, j as EView, k as EViewerEvent, F as FirstPersonSettings, l as FocusTarget, G as Gloves, P as Patch, m as PlacementTarget, S as Sticker, n as ViewerCapabilities, o as ViewerError, p as ViewerEventHandler, q as ViewerState, W as Weapon } from './interfaces-OatKvSe8.js';
1
+ import { C as CreateViewerOptions, V as Viewer } from './interfaces-iOmXANSI.js';
2
+ export { A as Agent, a as AnimationEntry, B as Background, b as Capability, c as CatalogQuery, d as Charm, E as EBackgroundType, e as EErrorCode, f as EFacing, g as EFeature, h as EHandedness, i as ERefusalFamily, j as ESubject, k as EView, l as EViewerEvent, F as FirstPersonSettings, m as FocusTarget, G as Gloves, P as Patch, n as PlacementTarget, S as Sticker, o as ViewerCapabilities, p as ViewerError, q as ViewerEventHandler, r as ViewerState, W as Weapon } from './interfaces-iOmXANSI.js';
3
3
 
4
4
  declare const createViewer: ({ container, key, baseUrl, weapon, environment, background, interactive, autoplay, locale, }: CreateViewerOptions) => Promise<Viewer>;
5
5
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { CS2_INSPECT_LINK_PREFIX } from './chunk-KADQENVR.js';
2
- export { EBackgroundType, EErrorCode, EFacing, EFeature, EHandedness, ESubject, EView, EViewerEvent, PROTOCOL_VERSION, createViewer } from './chunk-KADQENVR.js';
1
+ import { CS2_INSPECT_LINK_PREFIX } from './chunk-Y4CYVADH.js';
2
+ export { EBackgroundType, EErrorCode, EFacing, EFeature, EHandedness, ERefusalFamily, ESubject, EView, EViewerEvent, PROTOCOL_VERSION, createViewer } from './chunk-Y4CYVADH.js';
3
3
 
4
4
  // src/lib/buildInspectLink.ts
5
5
  var buildInspectLink = ({ cert }) => `${CS2_INSPECT_LINK_PREFIX}${cert}`;
@@ -159,7 +159,13 @@ declare enum EErrorCode {
159
159
  INVALID_ARGUMENT = "invalid_argument",
160
160
  NOT_READY = "not_ready",
161
161
  RATE_LIMITED = "rate_limited",
162
- INTERNAL = "internal"
162
+ INTERNAL = "internal",
163
+ REFUSED = "refused"
164
+ }
165
+ declare enum ERefusalFamily {
166
+ SETUP = "setup",
167
+ CUT_OFF = "cut_off",
168
+ OUTAGE = "outage"
163
169
  }
164
170
  declare enum EViewerEvent {
165
171
  READY = "ready",
@@ -176,11 +182,13 @@ declare enum EViewerEvent {
176
182
  CAPABILITIES_CHANGE = "capabilitieschange",
177
183
  PLACEMENT_START = "placementstart",
178
184
  PLACEMENT_MOVE = "placementmove",
179
- PLACEMENT_END = "placementend"
185
+ PLACEMENT_END = "placementend",
186
+ REFUSED = "refused"
180
187
  }
181
188
  type ViewerError = {
182
189
  code: EErrorCode;
183
190
  message?: string;
191
+ family?: ERefusalFamily;
184
192
  };
185
193
 
186
194
  type CatalogQuery = {
@@ -278,4 +286,4 @@ type CreateViewerOptions = {
278
286
  locale?: string;
279
287
  };
280
288
 
281
- export { type Agent as A, type Background as B, type CreateViewerOptions as C, EBackgroundType as E, type FirstPersonSettings as F, type Gloves as G, type Patch as P, type Sticker as S, type Viewer as V, type Weapon as W, type AnimationEntry as a, type Capability as b, type CatalogQuery as c, type Charm as d, EErrorCode as e, EFacing as f, EFeature as g, EHandedness as h, ESubject as i, EView as j, EViewerEvent as k, type FocusTarget as l, type PlacementTarget as m, type ViewerCapabilities as n, type ViewerError as o, type ViewerEventHandler as p, type ViewerState as q };
289
+ export { type Agent as A, type Background as B, type CreateViewerOptions as C, EBackgroundType as E, type FirstPersonSettings as F, type Gloves as G, type Patch as P, type Sticker as S, type Viewer as V, type Weapon as W, type AnimationEntry as a, type Capability as b, type CatalogQuery as c, type Charm as d, EErrorCode as e, EFacing as f, EFeature as g, EHandedness as h, ERefusalFamily as i, ESubject as j, EView as k, EViewerEvent as l, type FocusTarget as m, type PlacementTarget as n, type ViewerCapabilities as o, type ViewerError as p, type ViewerEventHandler as q, type ViewerState as r };
@@ -159,7 +159,13 @@ declare enum EErrorCode {
159
159
  INVALID_ARGUMENT = "invalid_argument",
160
160
  NOT_READY = "not_ready",
161
161
  RATE_LIMITED = "rate_limited",
162
- INTERNAL = "internal"
162
+ INTERNAL = "internal",
163
+ REFUSED = "refused"
164
+ }
165
+ declare enum ERefusalFamily {
166
+ SETUP = "setup",
167
+ CUT_OFF = "cut_off",
168
+ OUTAGE = "outage"
163
169
  }
164
170
  declare enum EViewerEvent {
165
171
  READY = "ready",
@@ -176,11 +182,13 @@ declare enum EViewerEvent {
176
182
  CAPABILITIES_CHANGE = "capabilitieschange",
177
183
  PLACEMENT_START = "placementstart",
178
184
  PLACEMENT_MOVE = "placementmove",
179
- PLACEMENT_END = "placementend"
185
+ PLACEMENT_END = "placementend",
186
+ REFUSED = "refused"
180
187
  }
181
188
  type ViewerError = {
182
189
  code: EErrorCode;
183
190
  message?: string;
191
+ family?: ERefusalFamily;
184
192
  };
185
193
 
186
194
  type CatalogQuery = {
@@ -278,4 +286,4 @@ type CreateViewerOptions = {
278
286
  locale?: string;
279
287
  };
280
288
 
281
- export { type Agent as A, type Background as B, type CreateViewerOptions as C, EBackgroundType as E, type FirstPersonSettings as F, type Gloves as G, type Patch as P, type Sticker as S, type Viewer as V, type Weapon as W, type AnimationEntry as a, type Capability as b, type CatalogQuery as c, type Charm as d, EErrorCode as e, EFacing as f, EFeature as g, EHandedness as h, ESubject as i, EView as j, EViewerEvent as k, type FocusTarget as l, type PlacementTarget as m, type ViewerCapabilities as n, type ViewerError as o, type ViewerEventHandler as p, type ViewerState as q };
289
+ export { type Agent as A, type Background as B, type CreateViewerOptions as C, EBackgroundType as E, type FirstPersonSettings as F, type Gloves as G, type Patch as P, type Sticker as S, type Viewer as V, type Weapon as W, type AnimationEntry as a, type Capability as b, type CatalogQuery as c, type Charm as d, EErrorCode as e, EFacing as f, EFeature as g, EHandedness as h, ERefusalFamily as i, ESubject as j, EView as k, EViewerEvent as l, type FocusTarget as m, type PlacementTarget as n, type ViewerCapabilities as o, type ViewerError as p, type ViewerEventHandler as q, type ViewerState as r };
package/dist/react.cjs CHANGED
@@ -266,13 +266,15 @@ var performHandshake = ({
266
266
  transport,
267
267
  iframe,
268
268
  mirror,
269
- onGiveUp
269
+ onGiveUp,
270
+ subscribeRefusal
270
271
  }) => new Promise((resolve, reject) => {
271
272
  let settled = false;
272
273
  const beginAt = Date.now();
273
274
  const settle = () => {
274
275
  settled = true;
275
276
  iframe.removeEventListener("load", attempt);
277
+ unsubscribeRefusal();
276
278
  };
277
279
  const attempt = () => {
278
280
  if (settled) return;
@@ -281,7 +283,7 @@ var performHandshake = ({
281
283
  onGiveUp();
282
284
  return reject({
283
285
  code: "invalid_key" /* INVALID_KEY */,
284
- message: "the viewer never answered: the key was refused, this domain is not declared for it, or the render service is unreachable"
286
+ message: "the viewer never answered: the render service is unreachable, or the frame was blocked before the page could boot"
285
287
  });
286
288
  }
287
289
  transport.send({
@@ -297,6 +299,15 @@ var performHandshake = ({
297
299
  resolve();
298
300
  }).catch(() => setTimeout(attempt, HELLO_RETRY_MS));
299
301
  };
302
+ const unsubscribeRefusal = subscribeRefusal(({ family }) => {
303
+ if (settled) return;
304
+ settle();
305
+ reject({
306
+ code: "refused" /* REFUSED */,
307
+ family,
308
+ message: "the embed server refused this viewer; its family says whose problem it is"
309
+ });
310
+ });
300
311
  iframe.addEventListener("load", attempt);
301
312
  setTimeout(attempt, HELLO_RETRY_MS);
302
313
  });
@@ -331,6 +342,10 @@ var createViewer = ({
331
342
  let destroyed = false;
332
343
  let greeted = false;
333
344
  let greetingAgain = false;
345
+ const subscribeRefusal = (handler) => hub.on(
346
+ "refused" /* REFUSED */,
347
+ (payload) => handler(payload)
348
+ );
334
349
  const greetAgain = () => {
335
350
  if (!greeted || greetingAgain || destroyed) return;
336
351
  greetingAgain = true;
@@ -341,7 +356,8 @@ var createViewer = ({
341
356
  mirror,
342
357
  // A reload that never answers leaves the viewer as it is: the frame is the
343
358
  // integrator's to keep or drop, and an error says so.
344
- onGiveUp: () => void 0
359
+ onGiveUp: () => void 0,
360
+ subscribeRefusal
345
361
  }).then(
346
362
  () => hub.dispatch({
347
363
  name: "reconnect" /* RECONNECT */,
@@ -382,7 +398,8 @@ var createViewer = ({
382
398
  transport,
383
399
  iframe,
384
400
  mirror,
385
- onGiveUp: destroy
401
+ onGiveUp: destroy,
402
+ subscribeRefusal
386
403
  }).then(() => {
387
404
  greeted = true;
388
405
  return viewer;