@vskin/sdk 0.1.0 → 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/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
 
@@ -163,6 +171,7 @@ var buildViewerHandle = ({
163
171
  pause: () => command("pause" /* PAUSE */),
164
172
  playAnimation: (args) => command("playAnimation" /* PLAY_ANIMATION */, args),
165
173
  stopAnimation: () => command("stopAnimation" /* STOP_ANIMATION */),
174
+ setSilentReload: (args) => command("setSilentReload" /* SET_SILENT_RELOAD */, args),
166
175
  startFire: () => command("startFire" /* START_FIRE */),
167
176
  stopFire: () => command("stopFire" /* STOP_FIRE */),
168
177
  armPlacement: (args) => command("armPlacement" /* ARM_PLACEMENT */, args),
@@ -345,13 +354,15 @@ var performHandshake = ({
345
354
  transport,
346
355
  iframe,
347
356
  mirror,
348
- onGiveUp
357
+ onGiveUp,
358
+ subscribeRefusal
349
359
  }) => new Promise((resolve, reject) => {
350
360
  let settled = false;
351
361
  const beginAt = Date.now();
352
362
  const settle = () => {
353
363
  settled = true;
354
364
  iframe.removeEventListener("load", attempt);
365
+ unsubscribeRefusal();
355
366
  };
356
367
  const attempt = () => {
357
368
  if (settled) return;
@@ -360,7 +371,7 @@ var performHandshake = ({
360
371
  onGiveUp();
361
372
  return reject({
362
373
  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"
374
+ message: "the viewer never answered: the render service is unreachable, or the frame was blocked before the page could boot"
364
375
  });
365
376
  }
366
377
  transport.send({
@@ -376,6 +387,15 @@ var performHandshake = ({
376
387
  resolve();
377
388
  }).catch(() => setTimeout(attempt, HELLO_RETRY_MS));
378
389
  };
390
+ const unsubscribeRefusal = subscribeRefusal(({ family }) => {
391
+ if (settled) return;
392
+ settle();
393
+ reject({
394
+ code: "refused" /* REFUSED */,
395
+ family,
396
+ message: "the embed server refused this viewer; its family says whose problem it is"
397
+ });
398
+ });
379
399
  iframe.addEventListener("load", attempt);
380
400
  setTimeout(attempt, HELLO_RETRY_MS);
381
401
  });
@@ -410,6 +430,10 @@ var createViewer = ({
410
430
  let destroyed = false;
411
431
  let greeted = false;
412
432
  let greetingAgain = false;
433
+ const subscribeRefusal = (handler) => hub.on(
434
+ "refused" /* REFUSED */,
435
+ (payload) => handler(payload)
436
+ );
413
437
  const greetAgain = () => {
414
438
  if (!greeted || greetingAgain || destroyed) return;
415
439
  greetingAgain = true;
@@ -420,7 +444,8 @@ var createViewer = ({
420
444
  mirror,
421
445
  // A reload that never answers leaves the viewer as it is: the frame is the
422
446
  // integrator's to keep or drop, and an error says so.
423
- onGiveUp: () => void 0
447
+ onGiveUp: () => void 0,
448
+ subscribeRefusal
424
449
  }).then(
425
450
  () => hub.dispatch({
426
451
  name: "reconnect" /* RECONNECT */,
@@ -461,7 +486,8 @@ var createViewer = ({
461
486
  transport,
462
487
  iframe,
463
488
  mirror,
464
- onGiveUp: destroy
489
+ onGiveUp: destroy,
490
+ subscribeRefusal
465
491
  }).then(() => {
466
492
  greeted = true;
467
493
  return viewer;
@@ -476,6 +502,7 @@ exports.EErrorCode = EErrorCode;
476
502
  exports.EFacing = EFacing;
477
503
  exports.EFeature = EFeature;
478
504
  exports.EHandedness = EHandedness;
505
+ exports.ERefusalFamily = ERefusalFamily;
479
506
  exports.ESubject = ESubject;
480
507
  exports.EView = EView;
481
508
  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 SET_SILENT_RELOAD = 'setSilentReload',\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 setSilentReload: (args) =>\n command(EProtocolCommand.SET_SILENT_RELOAD, args),\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-DD3qQ0dB.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-DD3qQ0dB.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-DD3qQ0dB.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-DD3qQ0dB.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-G3MXT3N5.js';
2
+ export { EBackgroundType, EErrorCode, EFacing, EFeature, EHandedness, ERefusalFamily, ESubject, EView, EViewerEvent, PROTOCOL_VERSION, createViewer } from './chunk-G3MXT3N5.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 = {
@@ -244,6 +252,9 @@ type Viewer = {
244
252
  name: string;
245
253
  }) => Promise<void>;
246
254
  stopAnimation: () => Promise<void>;
255
+ setSilentReload: (args: {
256
+ held: boolean;
257
+ }) => Promise<void>;
247
258
  startFire: () => Promise<void>;
248
259
  stopFire: () => Promise<void>;
249
260
  armPlacement: (args: {
@@ -278,4 +289,4 @@ type CreateViewerOptions = {
278
289
  locale?: string;
279
290
  };
280
291
 
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 };
292
+ 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 = {
@@ -244,6 +252,9 @@ type Viewer = {
244
252
  name: string;
245
253
  }) => Promise<void>;
246
254
  stopAnimation: () => Promise<void>;
255
+ setSilentReload: (args: {
256
+ held: boolean;
257
+ }) => Promise<void>;
247
258
  startFire: () => Promise<void>;
248
259
  stopFire: () => Promise<void>;
249
260
  armPlacement: (args: {
@@ -278,4 +289,4 @@ type CreateViewerOptions = {
278
289
  locale?: string;
279
290
  };
280
291
 
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 };
292
+ 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
@@ -84,6 +84,7 @@ var buildViewerHandle = ({
84
84
  pause: () => command("pause" /* PAUSE */),
85
85
  playAnimation: (args) => command("playAnimation" /* PLAY_ANIMATION */, args),
86
86
  stopAnimation: () => command("stopAnimation" /* STOP_ANIMATION */),
87
+ setSilentReload: (args) => command("setSilentReload" /* SET_SILENT_RELOAD */, args),
87
88
  startFire: () => command("startFire" /* START_FIRE */),
88
89
  stopFire: () => command("stopFire" /* STOP_FIRE */),
89
90
  armPlacement: (args) => command("armPlacement" /* ARM_PLACEMENT */, args),
@@ -266,13 +267,15 @@ var performHandshake = ({
266
267
  transport,
267
268
  iframe,
268
269
  mirror,
269
- onGiveUp
270
+ onGiveUp,
271
+ subscribeRefusal
270
272
  }) => new Promise((resolve, reject) => {
271
273
  let settled = false;
272
274
  const beginAt = Date.now();
273
275
  const settle = () => {
274
276
  settled = true;
275
277
  iframe.removeEventListener("load", attempt);
278
+ unsubscribeRefusal();
276
279
  };
277
280
  const attempt = () => {
278
281
  if (settled) return;
@@ -281,7 +284,7 @@ var performHandshake = ({
281
284
  onGiveUp();
282
285
  return reject({
283
286
  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"
287
+ message: "the viewer never answered: the render service is unreachable, or the frame was blocked before the page could boot"
285
288
  });
286
289
  }
287
290
  transport.send({
@@ -297,6 +300,15 @@ var performHandshake = ({
297
300
  resolve();
298
301
  }).catch(() => setTimeout(attempt, HELLO_RETRY_MS));
299
302
  };
303
+ const unsubscribeRefusal = subscribeRefusal(({ family }) => {
304
+ if (settled) return;
305
+ settle();
306
+ reject({
307
+ code: "refused" /* REFUSED */,
308
+ family,
309
+ message: "the embed server refused this viewer; its family says whose problem it is"
310
+ });
311
+ });
300
312
  iframe.addEventListener("load", attempt);
301
313
  setTimeout(attempt, HELLO_RETRY_MS);
302
314
  });
@@ -331,6 +343,10 @@ var createViewer = ({
331
343
  let destroyed = false;
332
344
  let greeted = false;
333
345
  let greetingAgain = false;
346
+ const subscribeRefusal = (handler) => hub.on(
347
+ "refused" /* REFUSED */,
348
+ (payload) => handler(payload)
349
+ );
334
350
  const greetAgain = () => {
335
351
  if (!greeted || greetingAgain || destroyed) return;
336
352
  greetingAgain = true;
@@ -341,7 +357,8 @@ var createViewer = ({
341
357
  mirror,
342
358
  // A reload that never answers leaves the viewer as it is: the frame is the
343
359
  // integrator's to keep or drop, and an error says so.
344
- onGiveUp: () => void 0
360
+ onGiveUp: () => void 0,
361
+ subscribeRefusal
345
362
  }).then(
346
363
  () => hub.dispatch({
347
364
  name: "reconnect" /* RECONNECT */,
@@ -382,7 +399,8 @@ var createViewer = ({
382
399
  transport,
383
400
  iframe,
384
401
  mirror,
385
- onGiveUp: destroy
402
+ onGiveUp: destroy,
403
+ subscribeRefusal
386
404
  }).then(() => {
387
405
  greeted = true;
388
406
  return viewer;