@atsignal/js-core 0.1.1 → 0.1.2

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
@@ -188,22 +188,16 @@ var SnapshotQueueStorage = class {
188
188
  };
189
189
 
190
190
  // src/timers.ts
191
- function resolveTimerApi() {
192
- const maybeSetTimeout = globalThis.setTimeout;
193
- const maybeClearTimeout = globalThis.clearTimeout;
191
+ function resolveTimerApi(timerApi) {
192
+ const timers = timerApi != null ? timerApi : globalThis;
193
+ const maybeSetTimeout = timers == null ? void 0 : timers.setTimeout;
194
+ const maybeClearTimeout = timers == null ? void 0 : timers.clearTimeout;
194
195
  if (typeof maybeSetTimeout !== "function" || typeof maybeClearTimeout !== "function") {
195
196
  return null;
196
197
  }
197
- return {
198
- setTimeout: maybeSetTimeout,
199
- clearTimeout: maybeClearTimeout
200
- };
198
+ return timers;
201
199
  }
202
- function scheduleTask(callback, delayMs) {
203
- const timers = resolveTimerApi();
204
- if (!timers) {
205
- return null;
206
- }
200
+ function scheduleTask(callback, delayMs, timers) {
207
201
  const handle = timers.setTimeout(callback, delayMs);
208
202
  return {
209
203
  cancel: () => {
@@ -211,14 +205,10 @@ function scheduleTask(callback, delayMs) {
211
205
  }
212
206
  };
213
207
  }
214
- function createTimeoutController(timeoutMs, createTimeoutValue) {
208
+ function createTimeoutController(timeoutMs, createTimeoutValue, timers) {
215
209
  if (typeof timeoutMs !== "number" || timeoutMs <= 0) {
216
210
  return null;
217
211
  }
218
- const timers = resolveTimerApi();
219
- if (!timers) {
220
- return null;
221
- }
222
212
  let handle;
223
213
  const timeout = new Promise((resolve) => {
224
214
  handle = timers.setTimeout(() => resolve(createTimeoutValue()), timeoutMs);
@@ -264,7 +254,7 @@ function encodeRequestBody(request) {
264
254
  return parts.join("&");
265
255
  }
266
256
  var FetchTransport = class {
267
- constructor(options = {}) {
257
+ constructor(timers, options = {}) {
268
258
  var _a, _b, _c;
269
259
  const fetchImpl = (_a = options.fetch) != null ? _a : resolveGlobalFetch();
270
260
  if (!fetchImpl) {
@@ -273,14 +263,19 @@ var FetchTransport = class {
273
263
  this._fetch = fetchImpl;
274
264
  this._keepalive = (_b = options.keepalive) != null ? _b : false;
275
265
  this._headers = (_c = options.headers) != null ? _c : {};
266
+ this._timers = timers;
276
267
  }
277
268
  async send(request) {
278
- const timer = createTimeoutController(request.timeoutMs, () => ({
279
- ok: false,
280
- retryable: true,
281
- status: 0,
282
- error: new Error("Request timed out")
283
- }));
269
+ const timer = createTimeoutController(
270
+ request.timeoutMs,
271
+ () => ({
272
+ ok: false,
273
+ retryable: true,
274
+ status: 0,
275
+ error: new Error("Request timed out")
276
+ }),
277
+ this._timers
278
+ );
284
279
  const requestPromise = this._fetch(request.endpoint, {
285
280
  method: "POST",
286
281
  headers: {
@@ -316,7 +311,7 @@ var FetchTransport = class {
316
311
  }
317
312
  };
318
313
  function createFetchTransport(options = {}) {
319
- return new FetchTransport(options);
314
+ return (runtime) => new FetchTransport(runtime.timers, options);
320
315
  }
321
316
 
322
317
  // src/client-config.ts
@@ -425,7 +420,16 @@ function createQueueStorage(storage) {
425
420
  }
426
421
  return new SnapshotQueueStorage(storage, QUEUE_STORAGE_KEY);
427
422
  }
428
- function normalizeConfig(apiKey, config) {
423
+ function resolveRuntime(runtime) {
424
+ const timers = resolveTimerApi(runtime == null ? void 0 : runtime.timers);
425
+ if (!timers) {
426
+ throw new Error("Signal client requires a timer implementation");
427
+ }
428
+ return {
429
+ timers
430
+ };
431
+ }
432
+ function normalizeConfig(apiKey, config, runtime) {
429
433
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
430
434
  if (!apiKey) {
431
435
  throw new Error("Signal client requires apiKey");
@@ -435,18 +439,19 @@ function normalizeConfig(apiKey, config) {
435
439
  userId: resolveInitialUserId(config.userId),
436
440
  deviceId: resolveInitialDeviceId(config.deviceId)
437
441
  };
442
+ const transportFactory = (_b = config.transportFactory) != null ? _b : createFetchTransport();
438
443
  return {
439
444
  apiKey,
440
445
  resolvedConfig: {
441
- endpoint: (_b = config.endpoint) != null ? _b : DEFAULT_ENDPOINT,
446
+ endpoint: (_c = config.endpoint) != null ? _c : DEFAULT_ENDPOINT,
442
447
  flushIntervalMs: toInteger(config.flushIntervalMs, DEFAULT_FLUSH_INTERVAL_MS),
443
448
  maxBatchSize: toInteger(config.maxBatchSize, DEFAULT_MAX_BATCH_SIZE),
444
449
  maxQueueSize: toInteger(config.maxQueueSize, DEFAULT_MAX_QUEUE_SIZE),
445
450
  retry: {
446
- baseMs: toInteger((_c = config.retry) == null ? void 0 : _c.baseMs, DEFAULT_RETRY_BASE_MS),
447
- maxMs: toInteger((_d = config.retry) == null ? void 0 : _d.maxMs, DEFAULT_RETRY_MAX_MS),
448
- maxAttempts: toInteger((_e = config.retry) == null ? void 0 : _e.maxAttempts, DEFAULT_RETRY_ATTEMPTS),
449
- jitter: typeof ((_f = config.retry) == null ? void 0 : _f.jitter) === "number" ? config.retry.jitter : DEFAULT_RETRY_JITTER
451
+ baseMs: toInteger((_d = config.retry) == null ? void 0 : _d.baseMs, DEFAULT_RETRY_BASE_MS),
452
+ maxMs: toInteger((_e = config.retry) == null ? void 0 : _e.maxMs, DEFAULT_RETRY_MAX_MS),
453
+ maxAttempts: toInteger((_f = config.retry) == null ? void 0 : _f.maxAttempts, DEFAULT_RETRY_ATTEMPTS),
454
+ jitter: typeof ((_g = config.retry) == null ? void 0 : _g.jitter) === "number" ? config.retry.jitter : DEFAULT_RETRY_JITTER
450
455
  },
451
456
  persistQueue,
452
457
  locationFromIp: resolveLocationFromIp(config.locationFromIp),
@@ -456,10 +461,10 @@ function normalizeConfig(apiKey, config) {
456
461
  blockedProperties: resolveBlockedProperties(config.blockedProperties)
457
462
  },
458
463
  storage: {
459
- identity: createIdentityStorage((_g = config.storage) == null ? void 0 : _g.identity),
460
- queue: persistQueue ? createQueueStorage((_h = config.storage) == null ? void 0 : _h.queue) : NOOP_QUEUE_STORAGE
464
+ identity: createIdentityStorage((_h = config.storage) == null ? void 0 : _h.identity),
465
+ queue: persistQueue ? createQueueStorage((_i = config.storage) == null ? void 0 : _i.queue) : NOOP_QUEUE_STORAGE
461
466
  },
462
- transport: (_i = config.transport) != null ? _i : createFetchTransport(),
467
+ transport: transportFactory(runtime),
463
468
  plugins: (_j = config.plugins) != null ? _j : [],
464
469
  initialIdentityOverrides
465
470
  };
@@ -983,7 +988,10 @@ var SignalClient = class {
983
988
  }
984
989
  this._state = "initializing";
985
990
  try {
986
- const normalized = normalizeConfig(apiKey, this.resolveInitConfig(options));
991
+ const initConfig = this.resolveInitConfig(options);
992
+ const runtime = resolveRuntime(initConfig.runtime);
993
+ const normalized = normalizeConfig(apiKey, initConfig, runtime);
994
+ this._runtime = runtime;
987
995
  this._applyNormalizedConfig(normalized);
988
996
  this._ready = this._initialize(normalized.initialIdentityOverrides);
989
997
  await this._ready;
@@ -1652,13 +1660,13 @@ var SignalClient = class {
1652
1660
  enqueueAutomaticFlush();
1653
1661
  return;
1654
1662
  }
1655
- const task = scheduleTask(() => {
1656
- enqueueAutomaticFlush();
1657
- }, delayMs);
1658
- if (!task) {
1659
- enqueueAutomaticFlush();
1660
- return;
1661
- }
1663
+ const task = scheduleTask(
1664
+ () => {
1665
+ enqueueAutomaticFlush();
1666
+ },
1667
+ delayMs,
1668
+ this._runtime.timers
1669
+ );
1662
1670
  this._flushTask = task;
1663
1671
  }
1664
1672
  async _performFlush(reason) {
package/dist/index.d.cts CHANGED
@@ -95,6 +95,14 @@ interface Transport {
95
95
  flush?(): Promise<void>;
96
96
  shutdown?(): Promise<void>;
97
97
  }
98
+ interface TimerApi {
99
+ setTimeout(callback: () => void, delayMs: number): unknown;
100
+ clearTimeout(handle: unknown): void;
101
+ }
102
+ interface ClientRuntime {
103
+ timers: TimerApi;
104
+ }
105
+ type TransportFactory = (runtime: Readonly<ClientRuntime>) => Transport;
98
106
  interface ClientIdentity {
99
107
  userId: string | null;
100
108
  deviceId: string;
@@ -246,7 +254,8 @@ interface ClientConfig {
246
254
  blockedProperties?: readonly string[];
247
255
  plugins?: ClientPlugin[];
248
256
  storage?: Partial<ClientStorageConfig>;
249
- transport?: Transport;
257
+ runtime?: Partial<ClientRuntime>;
258
+ transportFactory?: TransportFactory;
250
259
  }
251
260
 
252
261
  declare class SignalClient<TInitOptions extends object = ClientConfig> {
@@ -254,6 +263,7 @@ declare class SignalClient<TInitOptions extends object = ClientConfig> {
254
263
  private _config;
255
264
  private _storage;
256
265
  private _transport;
266
+ private _runtime;
257
267
  private _hooks;
258
268
  private _insertIdGenerator;
259
269
  private _pluginRuntime;
@@ -396,6 +406,6 @@ interface FetchTransportOptions {
396
406
  keepalive?: boolean;
397
407
  headers?: Record<string, string>;
398
408
  }
399
- declare function createFetchTransport(options?: FetchTransportOptions): Transport;
409
+ declare function createFetchTransport(options?: FetchTransportOptions): TransportFactory;
400
410
 
401
- export { type ClientConfig, type ClientHooks, type ClientIdentity, type ClientPlugin, type FlushMode, type FlushReason, HookRegistry, InMemoryStorage, type KeyValueStorage, type PersistedQueueEntry, type PluginSetupContext, type QueueStorage, type QueueStorageInput, type ResolvedClientConfig, type RetryConfig, SignalClient, type TrackOptions, type TrackProperties, type TrackedEvent, type Transport, type TransportEventGroup, type TransportRequest, type TransportResult, createFetchTransport };
411
+ export { type ClientConfig, type ClientHooks, type ClientIdentity, type ClientPlugin, type ClientRuntime, type FlushMode, type FlushReason, HookRegistry, InMemoryStorage, type KeyValueStorage, type PersistedQueueEntry, type PluginSetupContext, type QueueStorage, type QueueStorageInput, type ResolvedClientConfig, type RetryConfig, SignalClient, type TimerApi, type TrackOptions, type TrackProperties, type TrackedEvent, type Transport, type TransportEventGroup, type TransportFactory, type TransportRequest, type TransportResult, createFetchTransport };
package/dist/index.d.ts CHANGED
@@ -95,6 +95,14 @@ interface Transport {
95
95
  flush?(): Promise<void>;
96
96
  shutdown?(): Promise<void>;
97
97
  }
98
+ interface TimerApi {
99
+ setTimeout(callback: () => void, delayMs: number): unknown;
100
+ clearTimeout(handle: unknown): void;
101
+ }
102
+ interface ClientRuntime {
103
+ timers: TimerApi;
104
+ }
105
+ type TransportFactory = (runtime: Readonly<ClientRuntime>) => Transport;
98
106
  interface ClientIdentity {
99
107
  userId: string | null;
100
108
  deviceId: string;
@@ -246,7 +254,8 @@ interface ClientConfig {
246
254
  blockedProperties?: readonly string[];
247
255
  plugins?: ClientPlugin[];
248
256
  storage?: Partial<ClientStorageConfig>;
249
- transport?: Transport;
257
+ runtime?: Partial<ClientRuntime>;
258
+ transportFactory?: TransportFactory;
250
259
  }
251
260
 
252
261
  declare class SignalClient<TInitOptions extends object = ClientConfig> {
@@ -254,6 +263,7 @@ declare class SignalClient<TInitOptions extends object = ClientConfig> {
254
263
  private _config;
255
264
  private _storage;
256
265
  private _transport;
266
+ private _runtime;
257
267
  private _hooks;
258
268
  private _insertIdGenerator;
259
269
  private _pluginRuntime;
@@ -396,6 +406,6 @@ interface FetchTransportOptions {
396
406
  keepalive?: boolean;
397
407
  headers?: Record<string, string>;
398
408
  }
399
- declare function createFetchTransport(options?: FetchTransportOptions): Transport;
409
+ declare function createFetchTransport(options?: FetchTransportOptions): TransportFactory;
400
410
 
401
- export { type ClientConfig, type ClientHooks, type ClientIdentity, type ClientPlugin, type FlushMode, type FlushReason, HookRegistry, InMemoryStorage, type KeyValueStorage, type PersistedQueueEntry, type PluginSetupContext, type QueueStorage, type QueueStorageInput, type ResolvedClientConfig, type RetryConfig, SignalClient, type TrackOptions, type TrackProperties, type TrackedEvent, type Transport, type TransportEventGroup, type TransportRequest, type TransportResult, createFetchTransport };
411
+ export { type ClientConfig, type ClientHooks, type ClientIdentity, type ClientPlugin, type ClientRuntime, type FlushMode, type FlushReason, HookRegistry, InMemoryStorage, type KeyValueStorage, type PersistedQueueEntry, type PluginSetupContext, type QueueStorage, type QueueStorageInput, type ResolvedClientConfig, type RetryConfig, SignalClient, type TimerApi, type TrackOptions, type TrackProperties, type TrackedEvent, type Transport, type TransportEventGroup, type TransportFactory, type TransportRequest, type TransportResult, createFetchTransport };
package/dist/index.js CHANGED
@@ -159,22 +159,16 @@ var SnapshotQueueStorage = class {
159
159
  };
160
160
 
161
161
  // src/timers.ts
162
- function resolveTimerApi() {
163
- const maybeSetTimeout = globalThis.setTimeout;
164
- const maybeClearTimeout = globalThis.clearTimeout;
162
+ function resolveTimerApi(timerApi) {
163
+ const timers = timerApi != null ? timerApi : globalThis;
164
+ const maybeSetTimeout = timers == null ? void 0 : timers.setTimeout;
165
+ const maybeClearTimeout = timers == null ? void 0 : timers.clearTimeout;
165
166
  if (typeof maybeSetTimeout !== "function" || typeof maybeClearTimeout !== "function") {
166
167
  return null;
167
168
  }
168
- return {
169
- setTimeout: maybeSetTimeout,
170
- clearTimeout: maybeClearTimeout
171
- };
169
+ return timers;
172
170
  }
173
- function scheduleTask(callback, delayMs) {
174
- const timers = resolveTimerApi();
175
- if (!timers) {
176
- return null;
177
- }
171
+ function scheduleTask(callback, delayMs, timers) {
178
172
  const handle = timers.setTimeout(callback, delayMs);
179
173
  return {
180
174
  cancel: () => {
@@ -182,14 +176,10 @@ function scheduleTask(callback, delayMs) {
182
176
  }
183
177
  };
184
178
  }
185
- function createTimeoutController(timeoutMs, createTimeoutValue) {
179
+ function createTimeoutController(timeoutMs, createTimeoutValue, timers) {
186
180
  if (typeof timeoutMs !== "number" || timeoutMs <= 0) {
187
181
  return null;
188
182
  }
189
- const timers = resolveTimerApi();
190
- if (!timers) {
191
- return null;
192
- }
193
183
  let handle;
194
184
  const timeout = new Promise((resolve) => {
195
185
  handle = timers.setTimeout(() => resolve(createTimeoutValue()), timeoutMs);
@@ -235,7 +225,7 @@ function encodeRequestBody(request) {
235
225
  return parts.join("&");
236
226
  }
237
227
  var FetchTransport = class {
238
- constructor(options = {}) {
228
+ constructor(timers, options = {}) {
239
229
  var _a, _b, _c;
240
230
  const fetchImpl = (_a = options.fetch) != null ? _a : resolveGlobalFetch();
241
231
  if (!fetchImpl) {
@@ -244,14 +234,19 @@ var FetchTransport = class {
244
234
  this._fetch = fetchImpl;
245
235
  this._keepalive = (_b = options.keepalive) != null ? _b : false;
246
236
  this._headers = (_c = options.headers) != null ? _c : {};
237
+ this._timers = timers;
247
238
  }
248
239
  async send(request) {
249
- const timer = createTimeoutController(request.timeoutMs, () => ({
250
- ok: false,
251
- retryable: true,
252
- status: 0,
253
- error: new Error("Request timed out")
254
- }));
240
+ const timer = createTimeoutController(
241
+ request.timeoutMs,
242
+ () => ({
243
+ ok: false,
244
+ retryable: true,
245
+ status: 0,
246
+ error: new Error("Request timed out")
247
+ }),
248
+ this._timers
249
+ );
255
250
  const requestPromise = this._fetch(request.endpoint, {
256
251
  method: "POST",
257
252
  headers: {
@@ -287,7 +282,7 @@ var FetchTransport = class {
287
282
  }
288
283
  };
289
284
  function createFetchTransport(options = {}) {
290
- return new FetchTransport(options);
285
+ return (runtime) => new FetchTransport(runtime.timers, options);
291
286
  }
292
287
 
293
288
  // src/client-config.ts
@@ -396,7 +391,16 @@ function createQueueStorage(storage) {
396
391
  }
397
392
  return new SnapshotQueueStorage(storage, QUEUE_STORAGE_KEY);
398
393
  }
399
- function normalizeConfig(apiKey, config) {
394
+ function resolveRuntime(runtime) {
395
+ const timers = resolveTimerApi(runtime == null ? void 0 : runtime.timers);
396
+ if (!timers) {
397
+ throw new Error("Signal client requires a timer implementation");
398
+ }
399
+ return {
400
+ timers
401
+ };
402
+ }
403
+ function normalizeConfig(apiKey, config, runtime) {
400
404
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
401
405
  if (!apiKey) {
402
406
  throw new Error("Signal client requires apiKey");
@@ -406,18 +410,19 @@ function normalizeConfig(apiKey, config) {
406
410
  userId: resolveInitialUserId(config.userId),
407
411
  deviceId: resolveInitialDeviceId(config.deviceId)
408
412
  };
413
+ const transportFactory = (_b = config.transportFactory) != null ? _b : createFetchTransport();
409
414
  return {
410
415
  apiKey,
411
416
  resolvedConfig: {
412
- endpoint: (_b = config.endpoint) != null ? _b : DEFAULT_ENDPOINT,
417
+ endpoint: (_c = config.endpoint) != null ? _c : DEFAULT_ENDPOINT,
413
418
  flushIntervalMs: toInteger(config.flushIntervalMs, DEFAULT_FLUSH_INTERVAL_MS),
414
419
  maxBatchSize: toInteger(config.maxBatchSize, DEFAULT_MAX_BATCH_SIZE),
415
420
  maxQueueSize: toInteger(config.maxQueueSize, DEFAULT_MAX_QUEUE_SIZE),
416
421
  retry: {
417
- baseMs: toInteger((_c = config.retry) == null ? void 0 : _c.baseMs, DEFAULT_RETRY_BASE_MS),
418
- maxMs: toInteger((_d = config.retry) == null ? void 0 : _d.maxMs, DEFAULT_RETRY_MAX_MS),
419
- maxAttempts: toInteger((_e = config.retry) == null ? void 0 : _e.maxAttempts, DEFAULT_RETRY_ATTEMPTS),
420
- jitter: typeof ((_f = config.retry) == null ? void 0 : _f.jitter) === "number" ? config.retry.jitter : DEFAULT_RETRY_JITTER
422
+ baseMs: toInteger((_d = config.retry) == null ? void 0 : _d.baseMs, DEFAULT_RETRY_BASE_MS),
423
+ maxMs: toInteger((_e = config.retry) == null ? void 0 : _e.maxMs, DEFAULT_RETRY_MAX_MS),
424
+ maxAttempts: toInteger((_f = config.retry) == null ? void 0 : _f.maxAttempts, DEFAULT_RETRY_ATTEMPTS),
425
+ jitter: typeof ((_g = config.retry) == null ? void 0 : _g.jitter) === "number" ? config.retry.jitter : DEFAULT_RETRY_JITTER
421
426
  },
422
427
  persistQueue,
423
428
  locationFromIp: resolveLocationFromIp(config.locationFromIp),
@@ -427,10 +432,10 @@ function normalizeConfig(apiKey, config) {
427
432
  blockedProperties: resolveBlockedProperties(config.blockedProperties)
428
433
  },
429
434
  storage: {
430
- identity: createIdentityStorage((_g = config.storage) == null ? void 0 : _g.identity),
431
- queue: persistQueue ? createQueueStorage((_h = config.storage) == null ? void 0 : _h.queue) : NOOP_QUEUE_STORAGE
435
+ identity: createIdentityStorage((_h = config.storage) == null ? void 0 : _h.identity),
436
+ queue: persistQueue ? createQueueStorage((_i = config.storage) == null ? void 0 : _i.queue) : NOOP_QUEUE_STORAGE
432
437
  },
433
- transport: (_i = config.transport) != null ? _i : createFetchTransport(),
438
+ transport: transportFactory(runtime),
434
439
  plugins: (_j = config.plugins) != null ? _j : [],
435
440
  initialIdentityOverrides
436
441
  };
@@ -954,7 +959,10 @@ var SignalClient = class {
954
959
  }
955
960
  this._state = "initializing";
956
961
  try {
957
- const normalized = normalizeConfig(apiKey, this.resolveInitConfig(options));
962
+ const initConfig = this.resolveInitConfig(options);
963
+ const runtime = resolveRuntime(initConfig.runtime);
964
+ const normalized = normalizeConfig(apiKey, initConfig, runtime);
965
+ this._runtime = runtime;
958
966
  this._applyNormalizedConfig(normalized);
959
967
  this._ready = this._initialize(normalized.initialIdentityOverrides);
960
968
  await this._ready;
@@ -1623,13 +1631,13 @@ var SignalClient = class {
1623
1631
  enqueueAutomaticFlush();
1624
1632
  return;
1625
1633
  }
1626
- const task = scheduleTask(() => {
1627
- enqueueAutomaticFlush();
1628
- }, delayMs);
1629
- if (!task) {
1630
- enqueueAutomaticFlush();
1631
- return;
1632
- }
1634
+ const task = scheduleTask(
1635
+ () => {
1636
+ enqueueAutomaticFlush();
1637
+ },
1638
+ delayMs,
1639
+ this._runtime.timers
1640
+ );
1633
1641
  this._flushTask = task;
1634
1642
  }
1635
1643
  async _performFlush(reason) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atsignal/js-core",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Shared core module for Signal JavaScript SDKs.",
5
5
  "license": "MIT",
6
6
  "type": "module",