@eyepop.ai/eyepop 0.9.2 → 0.11.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.js CHANGED
@@ -8657,10 +8657,23 @@ var require_mime_types = __commonJS({
8657
8657
  // src/index.ts
8658
8658
  var src_exports = {};
8659
8659
  __export(src_exports, {
8660
- EyePopSdk: () => EyePopSdk
8660
+ EndpointState: () => EndpointState,
8661
+ EyePopSdk: () => EyePopSdk,
8662
+ default: () => src_default
8661
8663
  });
8662
8664
  module.exports = __toCommonJS(src_exports);
8663
8665
 
8666
+ // src/types.ts
8667
+ var EndpointState = /* @__PURE__ */ ((EndpointState2) => {
8668
+ EndpointState2["Idle"] = "Idle";
8669
+ EndpointState2["Busy"] = "Busy";
8670
+ EndpointState2["Authenticating"] = "Authenticating";
8671
+ EndpointState2["FetchConfig"] = "FetchConfig";
8672
+ EndpointState2["StartingPop"] = "StartingPop";
8673
+ EndpointState2["Error"] = "Error";
8674
+ return EndpointState2;
8675
+ })(EndpointState || {});
8676
+
8664
8677
  // src/streaming.ts
8665
8678
  var Stream = class _Stream {
8666
8679
  constructor(iterator, controller) {
@@ -8913,16 +8926,13 @@ function readableStreamAsyncIterable(stream) {
8913
8926
  }
8914
8927
 
8915
8928
  // src/jobs.ts
8916
- var _AbstractJob = class _AbstractJob {
8917
- constructor(baseUrl, pipelineId, authorizationHeader, client, requestLogger) {
8929
+ var AbstractJob = class {
8930
+ constructor(getSession, client, requestLogger) {
8918
8931
  this._responseStream = null;
8919
8932
  this._controller = new AbortController();
8920
- this._baseUrl = baseUrl.replace(/\/+$/, "");
8921
- this._pipelineId = pipelineId;
8922
- this._authorizationHeader = authorizationHeader;
8933
+ this._getSession = getSession;
8923
8934
  this._client = client;
8924
8935
  this._requestLogger = requestLogger;
8925
- this.i = _AbstractJob.n++;
8926
8936
  }
8927
8937
  [Symbol.asyncIterator]() {
8928
8938
  if (!this._responseStream) {
@@ -8933,22 +8943,55 @@ var _AbstractJob = class _AbstractJob {
8933
8943
  async startJob() {
8934
8944
  return Promise.reject("abstract class");
8935
8945
  }
8936
- start(done) {
8937
- this._responseStream = new Promise((resolve2, reject) => {
8938
- const request = this.startJob();
8939
- request.then((response) => {
8940
- if (response.status != 200) {
8941
- reject(`upload error ${response.status}: ${response.text()}`);
8942
- } else if (!response.body) {
8943
- reject(`response body is empty`);
8944
- } else {
8945
- resolve2(response.body);
8946
+ start(done, status) {
8947
+ this._responseStream = new Promise(async (resolve2, reject) => {
8948
+ try {
8949
+ let retries = 1;
8950
+ while (true) {
8951
+ try {
8952
+ const response = await this.startJob();
8953
+ if (response.status == 401) {
8954
+ status(response.status);
8955
+ if (retries--) {
8956
+ this._requestLogger.info("received 401 response, attempt to reauthorize once");
8957
+ } else {
8958
+ reject(`response ${response.status}: ${response.statusText}`);
8959
+ break;
8960
+ }
8961
+ } else if (response.status == 404) {
8962
+ status(response.status);
8963
+ if (retries--) {
8964
+ this._requestLogger.info("received 404 response, attempt to restart pop");
8965
+ } else {
8966
+ reject(`response ${response.status}: ${response.statusText}`);
8967
+ break;
8968
+ }
8969
+ } else if (response.status != 200) {
8970
+ reject(`upload error ${response.status}: ${await response.text()}`);
8971
+ break;
8972
+ } else if (!response.body) {
8973
+ reject(`response body is empty`);
8974
+ break;
8975
+ } else {
8976
+ resolve2(response.body);
8977
+ break;
8978
+ }
8979
+ } catch (error) {
8980
+ if (retries--) {
8981
+ this._requestLogger.info("unknown, attempt to restart pop (as if we received 404)", error);
8982
+ status(404);
8983
+ } else {
8984
+ status(500);
8985
+ reject(error);
8986
+ break;
8987
+ }
8988
+ }
8946
8989
  }
8947
- }).catch((reason) => {
8990
+ } catch (reason) {
8948
8991
  reject(reason);
8949
- }).finally(() => {
8992
+ } finally {
8950
8993
  done();
8951
- });
8994
+ }
8952
8995
  });
8953
8996
  return this;
8954
8997
  }
@@ -8956,24 +8999,24 @@ var _AbstractJob = class _AbstractJob {
8956
8999
  this._controller.abort("cancelled");
8957
9000
  }
8958
9001
  };
8959
- _AbstractJob.n = 0;
8960
- var AbstractJob = _AbstractJob;
9002
+ AbstractJob.n = 0;
8961
9003
  var UploadJob = class extends AbstractJob {
8962
9004
  get [Symbol.toStringTag]() {
8963
9005
  return "uploadJob";
8964
9006
  }
8965
- constructor(stream, mimeType, baseUrl, pipelineId, authorizationHeader, client, requestLogger) {
8966
- super(baseUrl, pipelineId, authorizationHeader, client, requestLogger);
9007
+ constructor(stream, mimeType, getSession, client, requestLogger) {
9008
+ super(getSession, client, requestLogger);
8967
9009
  this._uploadStream = stream;
8968
9010
  this._mimeType = mimeType;
8969
9011
  }
8970
9012
  async startJob() {
9013
+ const session = await this._getSession();
8971
9014
  const headers = {
8972
- "Authorization": this._authorizationHeader,
9015
+ "Authorization": `Bearer ${session.accessToken}`,
8973
9016
  "Accept": "application/jsonl",
8974
9017
  "Content-Type": this._mimeType
8975
9018
  };
8976
- const postUrl = `${this._baseUrl}/pipelines/${this._pipelineId}/source?mode=queue&processing=sync`;
9019
+ const postUrl = `${session.baseUrl.replace(/\/+$/, "")}/pipelines/${session.pipelineId}/source?mode=queue&processing=sync`;
8977
9020
  this._requestLogger.debug("before POST %s with stream as body");
8978
9021
  const response = await this._client.fetch(postUrl, {
8979
9022
  headers,
@@ -8989,26 +9032,60 @@ var UploadJob = class extends AbstractJob {
8989
9032
  }
8990
9033
  };
8991
9034
  var LoadFromJob = class extends AbstractJob {
8992
- constructor(location, baseUrl, pipelineId, authorizationHeader, client, requestLogger) {
8993
- super(baseUrl, pipelineId, authorizationHeader, client, requestLogger);
9035
+ constructor(location, getSession, client, requestLogger) {
9036
+ super(getSession, client, requestLogger);
8994
9037
  this._location = location;
8995
9038
  }
8996
9039
  get [Symbol.toStringTag]() {
8997
9040
  return "loadFromJob";
8998
9041
  }
8999
9042
  async startJob() {
9043
+ const body = {
9044
+ "sourceType": "URL",
9045
+ "url": this._location
9046
+ };
9047
+ const session = await this._getSession();
9000
9048
  const headers = {
9001
- "Authorization": this._authorizationHeader,
9049
+ "Authorization": `Bearer ${session.accessToken}`,
9002
9050
  "Accept": "application/jsonl",
9003
9051
  "Content-Type": "application/json"
9004
9052
  };
9053
+ const patchUrl = `${session.baseUrl.replace(/\/+$/, "")}/pipelines/${session.pipelineId}/source?mode=queue&processing=sync`;
9054
+ this._requestLogger.debug("before PATCH %s with url %s as source", patchUrl, this._location);
9055
+ const response = await this._client.fetch(patchUrl, {
9056
+ headers,
9057
+ method: "PATCH",
9058
+ body: JSON.stringify(body),
9059
+ signal: this._controller.signal,
9060
+ // @ts-ignore
9061
+ dispatcher: this._dispatcher
9062
+ });
9063
+ this._requestLogger.debug("after PATCH %s with url %s as source", patchUrl, this._location);
9064
+ return response;
9065
+ }
9066
+ };
9067
+ var LoadLiveIngressJob = class extends AbstractJob {
9068
+ constructor(ingressId, getSession, client, requestLogger) {
9069
+ super(getSession, client, requestLogger);
9070
+ this._ingressId = ingressId;
9071
+ }
9072
+ get [Symbol.toStringTag]() {
9073
+ return "loadLiveIngressJob";
9074
+ }
9075
+ async startJob() {
9005
9076
  const body = {
9006
- "sourceType": "URL",
9007
- "url": this._location
9077
+ "sourceType": "LIVE_INGRESS",
9078
+ "liveIngressId": this._ingressId
9008
9079
  };
9009
- const postUrl = `${this._baseUrl}/pipelines/${this._pipelineId}/source?mode=queue&processing=sync`;
9010
- this._requestLogger.debug("before PATCH %s with url %s as source", postUrl, this._location);
9011
- const response = await this._client.fetch(postUrl, {
9080
+ const session = await this._getSession();
9081
+ const headers = {
9082
+ "Authorization": `Bearer ${session.accessToken}`,
9083
+ "Accept": "application/jsonl",
9084
+ "Content-Type": "application/json"
9085
+ };
9086
+ const patchUrl = `${session.baseUrl.replace(/\/+$/, "")}/pipelines/${session.pipelineId}/source?mode=queue&processing=sync`;
9087
+ this._requestLogger.debug("before PATCH %s with url %s as source", patchUrl, this._ingressId);
9088
+ const response = await this._client.fetch(patchUrl, {
9012
9089
  headers,
9013
9090
  method: "PATCH",
9014
9091
  body: JSON.stringify(body),
@@ -9016,7 +9093,7 @@ var LoadFromJob = class extends AbstractJob {
9016
9093
  // @ts-ignore
9017
9094
  dispatcher: this._dispatcher
9018
9095
  });
9019
- this._requestLogger.debug("after PATCH %s with url %s as source", postUrl, this._location);
9096
+ this._requestLogger.debug("after PATCH %s with url %s as source", patchUrl, this._ingressId);
9020
9097
  return response;
9021
9098
  }
9022
9099
  };
@@ -9051,7 +9128,7 @@ if ("document" in globalThis && "implementation" in globalThis.document) {
9051
9128
  }
9052
9129
  }
9053
9130
  createHttpClient = async () => {
9054
- const undici = await import("undici");
9131
+ const undici = require("undici");
9055
9132
  const agent = new undici.Agent({
9056
9133
  keepAliveTimeout: 1e4,
9057
9134
  connections: 5
@@ -9188,6 +9265,374 @@ var Semaphore = class {
9188
9265
  }
9189
9266
  };
9190
9267
 
9268
+ // node_modules/uuid/dist/esm-node/rng.js
9269
+ var import_crypto = __toESM(require("crypto"));
9270
+ var rnds8Pool = new Uint8Array(256);
9271
+ var poolPtr = rnds8Pool.length;
9272
+ function rng() {
9273
+ if (poolPtr > rnds8Pool.length - 16) {
9274
+ import_crypto.default.randomFillSync(rnds8Pool);
9275
+ poolPtr = 0;
9276
+ }
9277
+ return rnds8Pool.slice(poolPtr, poolPtr += 16);
9278
+ }
9279
+
9280
+ // node_modules/uuid/dist/esm-node/stringify.js
9281
+ var byteToHex = [];
9282
+ for (let i = 0; i < 256; ++i) {
9283
+ byteToHex.push((i + 256).toString(16).slice(1));
9284
+ }
9285
+ function unsafeStringify(arr, offset = 0) {
9286
+ return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
9287
+ }
9288
+
9289
+ // node_modules/uuid/dist/esm-node/native.js
9290
+ var import_crypto2 = __toESM(require("crypto"));
9291
+ var native_default = {
9292
+ randomUUID: import_crypto2.default.randomUUID
9293
+ };
9294
+
9295
+ // node_modules/uuid/dist/esm-node/v4.js
9296
+ function v4(options, buf, offset) {
9297
+ if (native_default.randomUUID && !buf && !options) {
9298
+ return native_default.randomUUID();
9299
+ }
9300
+ options = options || {};
9301
+ const rnds = options.random || (options.rng || rng)();
9302
+ rnds[6] = rnds[6] & 15 | 64;
9303
+ rnds[8] = rnds[8] & 63 | 128;
9304
+ if (buf) {
9305
+ offset = offset || 0;
9306
+ for (let i = 0; i < 16; ++i) {
9307
+ buf[offset + i] = rnds[i];
9308
+ }
9309
+ return buf;
9310
+ }
9311
+ return unsafeStringify(rnds);
9312
+ }
9313
+ var v4_default = v4;
9314
+
9315
+ // src/web_rtc_base.ts
9316
+ var WebRtcBase = class {
9317
+ constructor(getSession, client, requestLogger) {
9318
+ this._pc = null;
9319
+ this._getSession = getSession;
9320
+ this._client = client;
9321
+ this._requestLogger = requestLogger;
9322
+ this._eTag = "";
9323
+ this._queuedCandidates = [];
9324
+ this._offerData = null;
9325
+ }
9326
+ static linkToIceServers(links) {
9327
+ const servers = links !== null ? links.split(", ").map((link) => {
9328
+ const m = link.match(/^<(.+?)>; rel="ice-server"(; username="(.*?)"; credential="(.*?)"; credential-type="password")?/i);
9329
+ if (!m) {
9330
+ return null;
9331
+ }
9332
+ const iceServer = {
9333
+ urls: [m[1]],
9334
+ username: Whip.unquoteCredential(m[3]),
9335
+ credential: Whip.unquoteCredential(m[4])
9336
+ // credentialType: m[3]? "password" : undefined
9337
+ };
9338
+ return iceServer;
9339
+ }) : [];
9340
+ return servers.filter(function(el) {
9341
+ return el != null;
9342
+ });
9343
+ }
9344
+ static editAnswer(answer, videoCodec, audioCodec, videoBitrate, audioBitrate, audioVoice) {
9345
+ const sections = answer.split("m=");
9346
+ for (let i = 0; i < sections.length; i++) {
9347
+ const section = sections[i];
9348
+ if (section.startsWith("video")) {
9349
+ sections[i] = Whip.setVideoBitrate(Whip.setCodec(section, videoCodec), videoBitrate);
9350
+ } else if (section.startsWith("audio")) {
9351
+ sections[i] = Whip.setAudioBitrate(Whip.setCodec(section, audioCodec), audioBitrate, audioVoice);
9352
+ }
9353
+ }
9354
+ return sections.join("m=");
9355
+ }
9356
+ static setCodec(section, codec) {
9357
+ const lines = section.split("\r\n");
9358
+ const lines2 = [];
9359
+ const payloadFormats = [];
9360
+ for (const line of lines) {
9361
+ if (!line.startsWith("a=rtpmap:")) {
9362
+ lines2.push(line);
9363
+ } else {
9364
+ if (codec && line.toLowerCase().includes(codec)) {
9365
+ payloadFormats.push(line.slice("a=rtpmap:".length).split(" ")[0]);
9366
+ lines2.push(line);
9367
+ }
9368
+ }
9369
+ }
9370
+ const lines3 = [];
9371
+ for (const line of lines2) {
9372
+ if (line.startsWith("a=fmtp:")) {
9373
+ if (payloadFormats.includes(line.slice("a=fmtp:".length).split(" ")[0])) {
9374
+ lines3.push(line);
9375
+ }
9376
+ } else if (line.startsWith("a=rtcp-fb:")) {
9377
+ if (payloadFormats.includes(line.slice("a=rtcp-fb:".length).split(" ")[0])) {
9378
+ lines3.push(line);
9379
+ }
9380
+ } else {
9381
+ lines3.push(line);
9382
+ }
9383
+ }
9384
+ return lines3.join("\r\n");
9385
+ }
9386
+ static setVideoBitrate(section, bitrate) {
9387
+ let lines = section.split("\r\n");
9388
+ for (let i = 0; i < lines.length; i++) {
9389
+ if (lines[i].startsWith("c=")) {
9390
+ lines = [...lines.slice(0, i + 1), "b=TIAS:" + (bitrate * 1024).toString(), ...lines.slice(i + 1)];
9391
+ break;
9392
+ }
9393
+ }
9394
+ return lines.join("\r\n");
9395
+ }
9396
+ static setAudioBitrate(section, bitrate, voice) {
9397
+ let opusPayloadFormat = "";
9398
+ let lines = section.split("\r\n");
9399
+ for (let i = 0; i < lines.length; i++) {
9400
+ if (lines[i].startsWith("a=rtpmap:") && lines[i].toLowerCase().includes("opus/")) {
9401
+ opusPayloadFormat = lines[i].slice("a=rtpmap:".length).split(" ")[0];
9402
+ break;
9403
+ }
9404
+ }
9405
+ if (opusPayloadFormat === "") {
9406
+ return section;
9407
+ }
9408
+ for (let i = 0; i < lines.length; i++) {
9409
+ if (lines[i].startsWith("a=fmtp:" + opusPayloadFormat + " ")) {
9410
+ if (voice) {
9411
+ lines[i] = "a=fmtp:" + opusPayloadFormat + " minptime=10;useinbandfec=1;maxaveragebitrate=" + ((bitrate ?? 0) * 1024).toString();
9412
+ } else {
9413
+ lines[i] = "a=fmtp:" + opusPayloadFormat + " maxplaybackrate=48000;stereo=1;sprop-stereo=1;maxaveragebitrate" + ((bitrate ?? 0) * 1024).toString();
9414
+ }
9415
+ }
9416
+ }
9417
+ return lines.join("\r\n");
9418
+ }
9419
+ static parseOffer(offer) {
9420
+ let medias = [];
9421
+ let iceUfrag = "";
9422
+ let icePwd = "";
9423
+ for (const line of offer.split("\r\n")) {
9424
+ if (line.startsWith("m=")) {
9425
+ medias.push(line.slice("m=".length));
9426
+ } else if (iceUfrag === "" && line.startsWith("a=ice-ufrag:")) {
9427
+ iceUfrag = line.slice("a=ice-ufrag:".length);
9428
+ } else if (icePwd === "" && line.startsWith("a=ice-pwd:")) {
9429
+ icePwd = line.slice("a=ice-pwd:".length);
9430
+ }
9431
+ }
9432
+ return {
9433
+ iceUfrag,
9434
+ icePwd,
9435
+ medias
9436
+ };
9437
+ }
9438
+ static generateSdpFragment(offerData, candidates) {
9439
+ const candidatesByMedia = /* @__PURE__ */ new Map();
9440
+ for (const candidate of candidates) {
9441
+ if (candidate.sdpMLineIndex !== null) {
9442
+ const mid2 = candidate.sdpMLineIndex;
9443
+ let matched = candidatesByMedia.get(mid2);
9444
+ if (matched === void 0) {
9445
+ matched = [];
9446
+ candidatesByMedia.set(mid2, matched);
9447
+ }
9448
+ matched.push(candidate);
9449
+ }
9450
+ }
9451
+ let frag = "a=ice-ufrag:" + offerData.iceUfrag + "\r\na=ice-pwd:" + offerData.icePwd + "\r\n";
9452
+ let mid = 0;
9453
+ for (const media of offerData.medias) {
9454
+ let matched = candidatesByMedia.get(mid);
9455
+ if (matched !== void 0) {
9456
+ frag += "m=" + media + "\r\na=mid:" + mid + "\r\n";
9457
+ for (const candidate of matched) {
9458
+ frag += "a=" + candidate.candidate + "\r\n";
9459
+ }
9460
+ }
9461
+ mid++;
9462
+ }
9463
+ return frag;
9464
+ }
9465
+ static unquoteCredential(v) {
9466
+ if (!v) {
9467
+ return "";
9468
+ }
9469
+ return JSON.parse(`"${v}"`);
9470
+ }
9471
+ };
9472
+
9473
+ // src/whip.ts
9474
+ var Whip = class _Whip extends WebRtcBase {
9475
+ constructor(stream, getSession, client, requestLogger) {
9476
+ super(getSession, client, requestLogger);
9477
+ this._ingressId = v4_default().toString();
9478
+ this._stream = stream;
9479
+ }
9480
+ ingressId() {
9481
+ if (!this._ingressId) {
9482
+ throw new Error("not initialized");
9483
+ }
9484
+ return this._ingressId;
9485
+ }
9486
+ async start() {
9487
+ const session = await this._getSession();
9488
+ const ingressUrl = new URL("/liveIngress/whip/" + this._ingressId, session.baseUrl);
9489
+ this._requestLogger.debug("before GET: %s", ingressUrl);
9490
+ const headers = {
9491
+ "Authorization": `Bearer ${session.accessToken}`
9492
+ };
9493
+ const response = await this._client.fetch(ingressUrl, {
9494
+ headers,
9495
+ method: "GET"
9496
+ });
9497
+ if (response.status >= 300) {
9498
+ return Promise.reject(`unknown status code for GET '${ingressUrl}': ${response.status} (${response.statusText})`);
9499
+ }
9500
+ return this.onIceServers(response);
9501
+ }
9502
+ async onIceServers(response) {
9503
+ if (!this._stream) {
9504
+ throw new Error("onIceServers no stream");
9505
+ }
9506
+ const stream = this._stream;
9507
+ const pc = new RTCPeerConnection({
9508
+ iceServers: _Whip.linkToIceServers(response.headers.get("Link"))
9509
+ });
9510
+ this._pc = pc;
9511
+ pc.onicecandidate = (evt) => this.onLocalCandidate(evt);
9512
+ return new Promise(async (resolve2, reject) => {
9513
+ pc.oniceconnectionstatechange = () => {
9514
+ switch (pc.iceConnectionState) {
9515
+ case "failed":
9516
+ case "disconnected":
9517
+ reject(`peer connection: ${pc.iceConnectionState}`);
9518
+ break;
9519
+ case "connected":
9520
+ resolve2(this);
9521
+ break;
9522
+ }
9523
+ };
9524
+ stream.getTracks().forEach((track) => {
9525
+ this._requestLogger.debug("onIceServers our stream has track: %s", track);
9526
+ pc.addTrack(track, stream);
9527
+ });
9528
+ stream.addEventListener("addtrack", (trackEvent) => {
9529
+ this._requestLogger.debug("onIceServers got lazy track: ", trackEvent.track);
9530
+ pc.addTrack(trackEvent.track, stream);
9531
+ });
9532
+ await this.onLocalOffer(await pc.createOffer());
9533
+ });
9534
+ }
9535
+ async onLocalCandidate(evt) {
9536
+ if (evt.candidate !== null) {
9537
+ if (this._eTag === "") {
9538
+ this._queuedCandidates.push(evt.candidate);
9539
+ } else {
9540
+ await this.sendLocalCandidates([evt.candidate]);
9541
+ }
9542
+ }
9543
+ return this;
9544
+ }
9545
+ async onLocalOffer(offer) {
9546
+ if (!this._pc) {
9547
+ throw new Error("onLocalOffer no peer connection");
9548
+ }
9549
+ if (!offer.sdp) {
9550
+ throw new Error("onLocalOffer no sdp");
9551
+ }
9552
+ this._offerData = _Whip.parseOffer(offer.sdp);
9553
+ await this._pc.setLocalDescription(offer);
9554
+ const session = await this._getSession();
9555
+ const ingressUrl = new URL("/liveIngress/whip/" + this._ingressId, session.baseUrl);
9556
+ this._requestLogger.debug("before GET: %s", ingressUrl);
9557
+ const headers = {
9558
+ "Authorization": `Bearer ${session.accessToken}`,
9559
+ "Content-Type": "application/sdp"
9560
+ };
9561
+ const response = await this._client.fetch(ingressUrl, {
9562
+ headers,
9563
+ method: "POST",
9564
+ body: offer.sdp
9565
+ });
9566
+ if (response.status != 201) {
9567
+ return Promise.reject(`unknown status code for POST '${ingressUrl}': ${response.status} (${response.statusText})`);
9568
+ }
9569
+ this._eTag = response.headers.get("ETag") ?? "";
9570
+ return this.onRemoteAnswer(new RTCSessionDescription({
9571
+ type: "answer",
9572
+ sdp: await response.text()
9573
+ }));
9574
+ }
9575
+ async onRemoteAnswer(answer) {
9576
+ if (!this._pc) {
9577
+ throw new Error("onLocalOffer no peer connection");
9578
+ }
9579
+ answer = new RTCSessionDescription({
9580
+ type: "answer",
9581
+ sdp: _Whip.editAnswer(
9582
+ answer.sdp,
9583
+ "h264/90000",
9584
+ void 0,
9585
+ 5e3,
9586
+ void 0,
9587
+ true
9588
+ )
9589
+ });
9590
+ await this._pc.setRemoteDescription(new RTCSessionDescription(answer));
9591
+ if (this._queuedCandidates.length !== 0) {
9592
+ await this.sendLocalCandidates(this._queuedCandidates);
9593
+ this._queuedCandidates = [];
9594
+ }
9595
+ return this;
9596
+ }
9597
+ async sendLocalCandidates(candidates) {
9598
+ if (!this._offerData) {
9599
+ throw new Error("sendLocalCandidates no offerData");
9600
+ }
9601
+ const session = await this._getSession();
9602
+ const ingressUrl = new URL("/liveIngress/whip/" + this._ingressId, session.baseUrl);
9603
+ this._requestLogger.debug("before PATCH: %s", ingressUrl);
9604
+ const headers = {
9605
+ "Authorization": `Bearer ${session.accessToken}`,
9606
+ "Content-Type": "application/trickle-ice-sdpfrag",
9607
+ "If-Match": this._eTag
9608
+ };
9609
+ const response = await this._client.fetch(ingressUrl, {
9610
+ headers,
9611
+ method: "PATCH",
9612
+ body: _Whip.generateSdpFragment(this._offerData, candidates)
9613
+ });
9614
+ if (response.status != 204) {
9615
+ return Promise.reject(`unknown status code for PATCH '${ingressUrl}': ${response.status} (${response.statusText})`);
9616
+ }
9617
+ return this;
9618
+ }
9619
+ async close() {
9620
+ const pc = this._pc;
9621
+ const stream = this._stream;
9622
+ this._stream = null;
9623
+ this._pc = null;
9624
+ if (stream) {
9625
+ const tracks = stream.getTracks();
9626
+ tracks.forEach((track) => {
9627
+ track.stop();
9628
+ });
9629
+ }
9630
+ if (pc) {
9631
+ return pc.close();
9632
+ }
9633
+ }
9634
+ };
9635
+
9191
9636
  // src/shims/local_file.ts
9192
9637
  var resolve;
9193
9638
  if ("document" in globalThis && "implementation" in globalThis.document) {
@@ -9209,8 +9654,8 @@ if ("document" in globalThis && "implementation" in globalThis.document) {
9209
9654
  if (params.file) {
9210
9655
  return params;
9211
9656
  }
9212
- const mime = await Promise.resolve().then(() => __toESM(require_mime_types()));
9213
- const fs = await import("fs");
9657
+ const mime = require_mime_types();
9658
+ const fs = require("fs");
9214
9659
  let mimeType;
9215
9660
  let stream;
9216
9661
  if (params.filePath) {
@@ -9241,7 +9686,11 @@ var Endpoint = class {
9241
9686
  this._token = null;
9242
9687
  this._expire_token_time = null;
9243
9688
  this._client = null;
9244
- this._limit = null;
9689
+ this._state = "Idle" /* Idle */;
9690
+ this._stateChangeHandler = null;
9691
+ this._ingressEventHandler = null;
9692
+ this._ingressEventWs = null;
9693
+ this._limit = new Semaphore(this._options.jobQueueLength ?? 1024);
9245
9694
  let rootLogger;
9246
9695
  if (options.logger) {
9247
9696
  rootLogger = options.logger;
@@ -9251,57 +9700,143 @@ var Endpoint = class {
9251
9700
  this._logger = rootLogger.child({ module: "eyepop" });
9252
9701
  this._requestLogger = this._logger.child({ module: "requests" });
9253
9702
  }
9703
+ onStateChanged(handler) {
9704
+ this._stateChangeHandler = handler;
9705
+ return this;
9706
+ }
9707
+ async startIngressWs() {
9708
+ if (this._ingressEventWs || !this._baseUrl || !this._client) {
9709
+ return;
9710
+ }
9711
+ try {
9712
+ const getTokenUrl = `${this._baseUrl}/liveIngress/events/token`;
9713
+ const headers = {
9714
+ "Authorization": await this.authorizationHeader()
9715
+ };
9716
+ this._requestLogger.debug("before GET %s", getTokenUrl);
9717
+ let response = await this._client.fetch(getTokenUrl, { headers });
9718
+ if (response.status == 401) {
9719
+ this._requestLogger.debug("after GET %s: 401, about to retry with fresh access token", getTokenUrl);
9720
+ this._token = null;
9721
+ const headers2 = {
9722
+ "Authorization": await this.authorizationHeader()
9723
+ };
9724
+ this.updateState("FetchConfig" /* FetchConfig */);
9725
+ response = await this._client.fetch(getTokenUrl, { headers: headers2 });
9726
+ }
9727
+ if (response.status != 200) {
9728
+ const message = await response.text();
9729
+ return Promise.reject(`Unexpected status ${response.status}: ${message}`);
9730
+ }
9731
+ const wsAuthToken = await response.json();
9732
+ const wsUrl = this._baseUrl.startsWith("https://") ? `${this._baseUrl.replace("https://", "wss://")}/liveIngress/events/${wsAuthToken.token}` : `${this._baseUrl.replace("http://", "ws://")}/liveIngress/events/${wsAuthToken.token}`;
9733
+ this._ingressEventWs = new WebSocket(wsUrl);
9734
+ this._ingressEventWs.addEventListener("message", (event) => {
9735
+ const ingressEvent = JSON.parse(event.data);
9736
+ if (this._ingressEventHandler) {
9737
+ this._ingressEventHandler(ingressEvent);
9738
+ }
9739
+ });
9740
+ } finally {
9741
+ this.updateState();
9742
+ }
9743
+ }
9744
+ onIngressEvent(handler) {
9745
+ this._ingressEventHandler = handler;
9746
+ this.startIngressWs().then(() => {
9747
+ }).catch((reason) => {
9748
+ this._logger.warn("unexpected error starting the ingress event handler: %s", reason);
9749
+ });
9750
+ return this;
9751
+ }
9752
+ state() {
9753
+ return this._state;
9754
+ }
9755
+ pendingJobs() {
9756
+ return (this._options.jobQueueLength ?? 1024) - this._limit.getPermits();
9757
+ }
9254
9758
  popName() {
9255
9759
  return this._popName;
9256
9760
  }
9761
+ popId() {
9762
+ return this._options.popId || null;
9763
+ }
9257
9764
  async session() {
9258
9765
  await this.currentAccessToken();
9259
9766
  if (this._token == null || this._expire_token_time == null) {
9260
9767
  return Promise.reject("endpoint not connected");
9261
9768
  }
9262
- const token = {
9769
+ if (this._baseUrl == null || this._pipelineId == null) {
9770
+ await this.reconnect();
9771
+ if (this._baseUrl == null || this._pipelineId == null) {
9772
+ return Promise.reject("endpoint not connected");
9773
+ }
9774
+ }
9775
+ return {
9776
+ eyepopUrl: this._options.eyepopUrl,
9777
+ popId: this._options.popId,
9263
9778
  accessToken: this._token,
9264
- validUntil: new Date(this._expire_token_time * 1e3)
9779
+ validUntil: this._expire_token_time * 1e3,
9780
+ baseUrl: this._baseUrl,
9781
+ pipelineId: this._pipelineId
9265
9782
  };
9266
- return token;
9783
+ }
9784
+ async liveIngress(stream) {
9785
+ if (!this._baseUrl || !this._client) {
9786
+ return Promise.reject("endpoint not connected, use connect() before ingress()");
9787
+ }
9788
+ const job = new Whip(stream, async () => {
9789
+ return this.session();
9790
+ }, this._client, this._requestLogger);
9791
+ return job.start();
9267
9792
  }
9268
9793
  async upload(params) {
9269
9794
  if (!this._baseUrl || !this._pipelineId || !this._client || !this._limit) {
9270
- return Promise.reject("endpoint not connected, use open() before upload()");
9795
+ return Promise.reject("endpoint not connected, use connect() before upload()");
9271
9796
  }
9272
9797
  params = await resolve(params);
9273
9798
  if (!params.mimeType) {
9274
9799
  return Promise.reject("upload for streams requires a mimeType");
9275
9800
  }
9276
9801
  await this._limit.acquire();
9277
- const job = new UploadJob(
9278
- params.file,
9279
- params.mimeType,
9280
- this._baseUrl,
9281
- this._pipelineId,
9282
- await this.authorizationHeader(),
9283
- this._client,
9284
- this._requestLogger
9285
- );
9802
+ this.updateState();
9803
+ const job = new UploadJob(params.file, params.mimeType, async () => {
9804
+ return this.session();
9805
+ }, this._client, this._requestLogger);
9286
9806
  return job.start(() => {
9287
- this._limit?.release();
9807
+ this.jobDone(job);
9808
+ }, (statusCode) => {
9809
+ this.jobStatus(job, statusCode);
9288
9810
  });
9289
9811
  }
9290
9812
  async loadFrom(location) {
9291
9813
  if (!this._baseUrl || !this._pipelineId || !this._client || !this._limit) {
9292
- throw new Error("endpoint not connected, use open() before loadFrom()");
9814
+ throw new Error("endpoint not connected, use connect() before loadFrom()");
9293
9815
  }
9294
9816
  await this._limit.acquire();
9295
- const job = new LoadFromJob(
9296
- location,
9297
- this._baseUrl,
9298
- this._pipelineId,
9299
- await this.authorizationHeader(),
9300
- this._client,
9301
- this._requestLogger
9302
- );
9817
+ this.updateState();
9818
+ const job = new LoadFromJob(location, async () => {
9819
+ return this.session();
9820
+ }, this._client, this._requestLogger);
9303
9821
  return job.start(() => {
9304
- this._limit?.release();
9822
+ this.jobDone(job);
9823
+ }, (statusCode) => {
9824
+ this.jobStatus(job, statusCode);
9825
+ });
9826
+ }
9827
+ async loadLiveIngress(ingressId) {
9828
+ if (!this._baseUrl || !this._pipelineId || !this._client || !this._limit) {
9829
+ throw new Error("endpoint not connected, use connect() before loadLiveIngress()");
9830
+ }
9831
+ await this._limit.acquire();
9832
+ this.updateState();
9833
+ const job = new LoadLiveIngressJob(ingressId, async () => {
9834
+ return this.session();
9835
+ }, this._client, this._requestLogger);
9836
+ return job.start(() => {
9837
+ this.jobDone(job);
9838
+ }, (statusCode) => {
9839
+ this.jobStatus(job, statusCode);
9305
9840
  });
9306
9841
  }
9307
9842
  // noinspection TypeScriptValidateTypes
@@ -9316,20 +9851,72 @@ var Endpoint = class {
9316
9851
  if (!this._options.popId) {
9317
9852
  return Promise.reject("option popId or environment variable EYEPOP_POP_ID is required");
9318
9853
  }
9319
- if (this._options.session) {
9320
- this._token = this._options.session.accessToken;
9321
- this._expire_token_time = this._options.session.validUntil.getTime() / 1e3;
9854
+ if (this._options.auth && this._options.auth.session) {
9855
+ this._token = this._options.auth.session.accessToken;
9856
+ this._expire_token_time = this._options.auth.session.validUntil / 1e3;
9322
9857
  } else {
9323
- if (!this._options.secretKey) {
9858
+ if (!this._options.auth || !this._options.auth.secretKey) {
9324
9859
  return Promise.reject("option secretKey or environment variable EYEPOP_SECRET_KEY is required");
9325
9860
  }
9326
9861
  }
9327
9862
  this._client = await createHttpClient();
9328
- this._limit = new Semaphore(this._options.jobQueueLength);
9329
- const config_url = `${this.eyepopUrl()}/pops/${this._options.popId}/config?auto_start=${this._options.autoStart}`;
9863
+ let result = await this.reconnect();
9864
+ if (this._baseUrl && this._options.stopJobs) {
9865
+ const stop_url = `${this._baseUrl}/pipelines/${this._pipelineId}/source?mode=preempt&processing=sync`;
9866
+ const body = { "sourceType": "NONE" };
9867
+ const headers = {
9868
+ "Authorization": await this.authorizationHeader(),
9869
+ "Content-Type": "application/json"
9870
+ };
9871
+ this._requestLogger.debug("before PATCH %s", stop_url);
9872
+ let response = await this._client.fetch(stop_url, { method: "PATCH", headers, body: JSON.stringify(body) });
9873
+ if (response.status >= 300) {
9874
+ const message = await response.text();
9875
+ return Promise.reject(`Unexpected status ${response.status}: ${message}`);
9876
+ }
9877
+ this._requestLogger.debug("after PATCH %s", stop_url);
9878
+ }
9879
+ if (!this._ingressEventWs && this._ingressEventHandler) {
9880
+ await this.startIngressWs();
9881
+ }
9882
+ return result;
9883
+ }
9884
+ jobDone(job) {
9885
+ this._limit?.release();
9886
+ this.updateState();
9887
+ }
9888
+ updateState(newState = void 0) {
9889
+ const fromState = this._state;
9890
+ if (newState == void 0) {
9891
+ if (this._limit.getPermits() == this._options.jobQueueLength) {
9892
+ newState = "Idle" /* Idle */;
9893
+ } else {
9894
+ newState = "Busy" /* Busy */;
9895
+ }
9896
+ }
9897
+ this._state = newState;
9898
+ if (this._stateChangeHandler) {
9899
+ this._stateChangeHandler(fromState, this._state);
9900
+ }
9901
+ }
9902
+ jobStatus(job, statusCode) {
9903
+ if (statusCode == 404) {
9904
+ this._pipelineId = null;
9905
+ this._baseUrl = null;
9906
+ } else if (statusCode == 401) {
9907
+ this._token = null;
9908
+ this._expire_token_time = null;
9909
+ }
9910
+ }
9911
+ async reconnect() {
9912
+ if (!this._client) {
9913
+ return Promise.reject("endpoint not initialized");
9914
+ }
9915
+ const config_url = `${this.eyepopUrl()}/pops/${this._options.popId}/config?auto_start=false`;
9330
9916
  const headers = {
9331
9917
  "Authorization": await this.authorizationHeader()
9332
9918
  };
9919
+ this.updateState("FetchConfig" /* FetchConfig */);
9333
9920
  this._requestLogger.debug("before GET %s", config_url);
9334
9921
  let response = await this._client.fetch(config_url, { headers });
9335
9922
  if (response.status == 401) {
@@ -9338,41 +9925,47 @@ var Endpoint = class {
9338
9925
  const headers2 = {
9339
9926
  "Authorization": await this.authorizationHeader()
9340
9927
  };
9928
+ this.updateState("FetchConfig" /* FetchConfig */);
9341
9929
  response = await this._client.fetch(config_url, {
9342
9930
  headers: headers2
9343
9931
  // @ts-ignore
9344
9932
  });
9345
9933
  }
9346
9934
  if (response.status != 200) {
9935
+ this.updateState("Error" /* Error */);
9347
9936
  const message = await response.text();
9348
9937
  return Promise.reject(`Unexpected status ${response.status}: ${message}`);
9349
- }
9350
- const data = await response.json();
9351
- const config = data;
9352
- this._baseUrl = config.base_url;
9353
- this._pipelineId = config.pipeline_id;
9354
- this._popName = config.name;
9355
- this._requestLogger.debug("after GET %s: %s / %s", config_url, this._baseUrl, this._pipelineId);
9356
- if (!this._pipelineId || !this._baseUrl) {
9357
- return Promise.reject(`Pop not started`);
9358
- }
9359
- this._baseUrl = this._baseUrl.replace(/\/+$/, "");
9360
- if (this._options.stopJobs) {
9361
- const stop_url = `${this._baseUrl}/pipelines/${this._pipelineId}/source?mode=preempt&processing=sync`;
9362
- const body = { "sourceType": "NONE" };
9363
- const headers2 = {
9364
- "Authorization": await this.authorizationHeader(),
9365
- "Content-Type": "application/json"
9366
- };
9367
- this._requestLogger.debug("before PATCH %s", stop_url);
9368
- let response2 = await this._client.fetch(stop_url, { method: "PATCH", headers: headers2, body: JSON.stringify(body) });
9369
- if (response2.status >= 300) {
9370
- const message = await response2.text();
9371
- return Promise.reject(`Unexpected status ${response2.status}: ${message}`);
9938
+ } else {
9939
+ let config = await response.json();
9940
+ if (!config.base_url && this._options.autoStart) {
9941
+ const auto_start_config_url = `${this.eyepopUrl()}/pops/${this._options.popId}/config?auto_start=true`;
9942
+ this._requestLogger.debug("pop was not running, trying to autostart with: %s", auto_start_config_url);
9943
+ const headers2 = {
9944
+ "Authorization": await this.authorizationHeader()
9945
+ };
9946
+ this.updateState("StartingPop" /* StartingPop */);
9947
+ response = await this._client.fetch(auto_start_config_url, {
9948
+ headers: headers2
9949
+ // @ts-ignore
9950
+ });
9951
+ if (response.status != 200) {
9952
+ this.updateState("Error" /* Error */);
9953
+ const message = await response.text();
9954
+ return Promise.reject(`Unexpected status ${response.status}: ${message}`);
9955
+ }
9956
+ config = await response.json();
9372
9957
  }
9373
- this._requestLogger.debug("after PATCH %s", stop_url);
9958
+ this._baseUrl = config.base_url;
9959
+ this._pipelineId = config.pipeline_id;
9960
+ this._popName = config.name;
9961
+ this._requestLogger.debug("after GET %s: %s / %s", config_url, this._baseUrl, this._pipelineId);
9962
+ if (!this._pipelineId || !this._baseUrl) {
9963
+ return Promise.reject(`Pop not started`);
9964
+ }
9965
+ this._baseUrl = this._baseUrl.replace(/\/+$/, "");
9966
+ this.updateState();
9967
+ return Promise.resolve(this);
9374
9968
  }
9375
- return this;
9376
9969
  }
9377
9970
  async disconnect(wait = true) {
9378
9971
  if (wait && this._limit) {
@@ -9380,13 +9973,13 @@ var Endpoint = class {
9380
9973
  await this._limit.acquire();
9381
9974
  }
9382
9975
  }
9976
+ this._limit = new Semaphore(this._options.jobQueueLength ?? 1024);
9383
9977
  if (this._client) {
9384
9978
  await this._client.close();
9385
9979
  this._client = null;
9386
9980
  }
9387
9981
  this._baseUrl = null;
9388
9982
  this._pipelineId = null;
9389
- this._limit = null;
9390
9983
  }
9391
9984
  async authorizationHeader() {
9392
9985
  return `Bearer ${await this.currentAccessToken()}`;
@@ -9394,12 +9987,13 @@ var Endpoint = class {
9394
9987
  async currentAccessToken() {
9395
9988
  const now = Date.now() / 1e3;
9396
9989
  if (!this._token || this._expire_token_time < now) {
9990
+ this.updateState("Authenticating" /* Authenticating */);
9397
9991
  if (!this._client) {
9398
9992
  return Promise.reject("endpoint not connected");
9399
- } else if (!this._options.secretKey) {
9993
+ } else if (!this._options.auth || !this._options.auth.secretKey) {
9400
9994
  return Promise.reject("temporary access token expired");
9401
9995
  }
9402
- const body = { "secret_key": this._options.secretKey };
9996
+ const body = { "secret_key": this._options.auth.secretKey };
9403
9997
  const headers = { "Content-Type": "application/json" };
9404
9998
  const post_url = `${this.eyepopUrl()}/authentication/token`;
9405
9999
  this._requestLogger.debug("before POST %s", post_url);
@@ -9417,6 +10011,7 @@ var Endpoint = class {
9417
10011
  const token = data;
9418
10012
  this._token = token.access_token;
9419
10013
  this._expire_token_time = now + token.expires_in - 60;
10014
+ this.updateState();
9420
10015
  }
9421
10016
  this._logger.debug("using access token, valid for at least %d seconds", this._expire_token_time - now);
9422
10017
  return this._token;
@@ -9439,17 +10034,19 @@ var _EyePopPlot = class _EyePopPlot {
9439
10034
  }
9440
10035
  prediction(p) {
9441
10036
  if (p && p.objects) {
10037
+ const x_scale = this._context.canvas.width / p.source_width;
10038
+ const y_scale = this._context.canvas.height / p.source_height;
9442
10039
  for (let i = 0; i < p.objects.length; i++) {
9443
- this.object(p.objects[i]);
10040
+ this.object(p.objects[i], x_scale, y_scale);
9444
10041
  }
9445
10042
  }
9446
10043
  }
9447
- object(obj) {
10044
+ object(obj, x_scale = 1, y_scale = 1) {
9448
10045
  const context = this._context;
9449
- const x = obj.x;
9450
- const y = obj.y;
9451
- const w = obj.width;
9452
- const h = obj.height;
10046
+ const x = obj.x * x_scale;
10047
+ const y = obj.y * y_scale;
10048
+ const w = obj.width * x_scale;
10049
+ const h = obj.height * y_scale;
9453
10050
  context.beginPath();
9454
10051
  context.rect(obj.x, obj.y, obj.width, obj.height);
9455
10052
  context.lineWidth = 1;
@@ -9541,11 +10138,50 @@ _EyePopPlot.colors = {
9541
10138
  };
9542
10139
  var EyePopPlot = _EyePopPlot;
9543
10140
 
10141
+ // src/shims/browser_session.ts
10142
+ var authenticateBrowserSession;
10143
+ if ("document" in globalThis && "implementation" in globalThis.document) {
10144
+ authenticateBrowserSession = (oauthUrl, eyepopUrl, popId) => {
10145
+ const queryString = window.location.search;
10146
+ const urlParams = new URLSearchParams(queryString);
10147
+ let token = urlParams.get("pop_token");
10148
+ if (token) {
10149
+ urlParams.delete("pop_token");
10150
+ const url = `${window.location.pathname}?${urlParams}`;
10151
+ window.history.replaceState({}, document.title, url);
10152
+ return {
10153
+ eyepopUrl,
10154
+ popId,
10155
+ accessToken: token,
10156
+ validUntil: Date.now() + 60 * 60 * 1e3
10157
+ };
10158
+ } else {
10159
+ const url = `${oauthUrl}?url=${encodeURIComponent(window.location.href)}`;
10160
+ window.location.replace(url);
10161
+ return {
10162
+ eyepopUrl,
10163
+ popId,
10164
+ accessToken: "in-progress",
10165
+ validUntil: 0
10166
+ };
10167
+ }
10168
+ };
10169
+ } else {
10170
+ authenticateBrowserSession = (oauthUrl, eyepopUrl, popId) => {
10171
+ return null;
10172
+ };
10173
+ }
10174
+
9544
10175
  // src/index.ts
10176
+ var readEnv = (env) => {
10177
+ if (typeof process !== "undefined") {
10178
+ return process.env?.[env] ?? void 0;
10179
+ }
10180
+ return void 0;
10181
+ };
9545
10182
  var EyePopSdk = class {
9546
10183
  static endpoint({
9547
- secretKey = readEnv("EYEPOP_SECRET_KEY"),
9548
- session = void 0,
10184
+ auth = this.defaultAuth,
9549
10185
  popId = readEnv("EYEPOP_POP_ID"),
9550
10186
  eyepopUrl = readEnv("EYEPOP_URL"),
9551
10187
  autoStart = true,
@@ -9554,11 +10190,17 @@ var EyePopSdk = class {
9554
10190
  logger,
9555
10191
  ...opts
9556
10192
  } = {}) {
10193
+ if (auth.oAuth && popId) {
10194
+ let oauthUrl = "https://dashboard.eyepop.ai/sdkauth";
10195
+ if (typeof auth.oAuth == "string") {
10196
+ oauthUrl = auth.oAuth;
10197
+ }
10198
+ auth.session = authenticateBrowserSession(oauthUrl, eyepopUrl ?? "https://api.eyepop.ai", popId) ?? void 0;
10199
+ }
9557
10200
  const options = {
9558
- secretKey,
9559
- session,
9560
- popId,
9561
- eyepopUrl: eyepopUrl ?? "https://api.eyepop.ai",
10201
+ auth,
10202
+ popId: auth.session ? auth.session.popId : popId,
10203
+ eyepopUrl: auth.session ? auth.session.eyepopUrl : eyepopUrl ?? "https://api.eyepop.ai",
9562
10204
  autoStart,
9563
10205
  stopJobs,
9564
10206
  jobQueueLength,
@@ -9571,14 +10213,13 @@ var EyePopSdk = class {
9571
10213
  return new EyePopPlot(context);
9572
10214
  }
9573
10215
  };
9574
- var readEnv = (env) => {
9575
- if (typeof process !== "undefined") {
9576
- return process.env?.[env] ?? void 0;
9577
- }
9578
- return void 0;
10216
+ EyePopSdk.defaultAuth = {
10217
+ secretKey: readEnv("EYEPOP_SECRET_KEY")
9579
10218
  };
10219
+ var src_default = EyePopSdk;
9580
10220
  // Annotate the CommonJS export names for ESM import in node:
9581
10221
  0 && (module.exports = {
10222
+ EndpointState,
9582
10223
  EyePopSdk
9583
10224
  });
9584
10225
  /*! Bundled license information: