@uengage.io/platform-sdk 0.15.0 → 1.0.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.
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ /**
3
+ * Dependency-free envelope guard for the browser realtime client.
4
+ *
5
+ * This mirrors `@uengage/common`'s `platformEventSchema` and the SDK's own
6
+ * `events/schema.ts`, but hand-rolled: the `/realtime` subpath ships with
7
+ * zero runtime dependencies (no zod, no Node built-ins) so it stays a few
8
+ * KB in a frontend bundle. Change one, change all three.
9
+ *
10
+ * NO DOMAIN CROSS-CHECK, deliberately — this is the one mirror that does
11
+ * not carry the resource→domain map, and it is not an oversight:
12
+ *
13
+ * - It would be checking the wrong thing. The producing SDK derives
14
+ * `domain` from `type` and the consuming service re-validates the pair
15
+ * before it ever publishes to a channel. By the time an envelope
16
+ * reaches a browser the pair has been checked twice server-side; a
17
+ * third check can only reject, never repair.
18
+ * - It would rot dangerously. A browser bundle sits in someone's cache
19
+ * for weeks. Baking today's map into it means that the day a new
20
+ * domain ships, every un-refreshed tab starts silently dropping live
21
+ * events for it — a stale client rejecting the future, which is the
22
+ * failure mode `validatePlatformEvent` is careful to avoid even
23
+ * server-side.
24
+ *
25
+ * So the guard is structural only: shapes and types, not membership.
26
+ * `packages/platform-sdk/test/events/domain-map.test.ts` asserts that
27
+ * every canonical domain is accepted, and that an unlisted one is too.
28
+ */
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ exports.asRealtimeEvent = asRealtimeEvent;
31
+ exports.isNewer = isNewer;
32
+ /** ULID: Crockford base32, 26 chars, excludes I/L/O/U. */
33
+ const ULID_RE = /^[0-9A-HJKMNP-TV-Z]{26}$/;
34
+ /** Dotted `resource.operation`, e.g. `order.status_changed`. */
35
+ const EVENT_TYPE_RE = /^[a-z][a-z0-9_]*\.[a-z][a-z0-9_]*$/;
36
+ /**
37
+ * Structural check on an untrusted payload. Returns the event or null —
38
+ * never throws, because a single malformed frame must not tear down a
39
+ * live subscription.
40
+ */
41
+ function asRealtimeEvent(value) {
42
+ if (typeof value !== 'object' || value === null)
43
+ return null;
44
+ const v = value;
45
+ if (typeof v.id !== 'string' || !ULID_RE.test(v.id))
46
+ return null;
47
+ if (typeof v.type !== 'string' || !EVENT_TYPE_RE.test(v.type))
48
+ return null;
49
+ if (typeof v.domain !== 'string' || v.domain.length === 0)
50
+ return null;
51
+ if (typeof v.source !== 'string' || v.source.length === 0)
52
+ return null;
53
+ if (typeof v.version !== 'number' || !Number.isInteger(v.version) || v.version < 1)
54
+ return null;
55
+ if (typeof v.occurredAt !== 'string' || v.occurredAt.length === 0)
56
+ return null;
57
+ if (typeof v.tenantId !== 'string' || v.tenantId.length === 0)
58
+ return null;
59
+ if (typeof v.data !== 'object' || v.data === null || Array.isArray(v.data))
60
+ return null;
61
+ return v;
62
+ }
63
+ /**
64
+ * Ordering/dedupe guard, keyed on the envelope's monotonic ULID.
65
+ *
66
+ * ULIDs are lexicographically sortable by mint time, so a plain string
67
+ * compare orders events without parsing timestamps or knowing anything
68
+ * about the domain. This is what makes at-least-once delivery and the
69
+ * snapshot/stream race both harmless: whichever arrives second with an
70
+ * id <= the one already rendered is dropped.
71
+ */
72
+ function isNewer(candidateId, seenId) {
73
+ if (seenId === undefined)
74
+ return true;
75
+ return candidateId > seenId;
76
+ }
77
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW52ZWxvcGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVhbHRpbWUvZW52ZWxvcGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBCRzs7QUF5QkgsMENBWUM7QUFXRCwwQkFHQztBQWpERCwwREFBMEQ7QUFDMUQsTUFBTSxPQUFPLEdBQUcsMEJBQTBCLENBQUM7QUFFM0MsZ0VBQWdFO0FBQ2hFLE1BQU0sYUFBYSxHQUFHLG9DQUFvQyxDQUFDO0FBYzNEOzs7O0dBSUc7QUFDSCxTQUFnQixlQUFlLENBQUMsS0FBYztJQUM1QyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxLQUFLLEtBQUssSUFBSTtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzdELE1BQU0sQ0FBQyxHQUFHLEtBQWdDLENBQUM7SUFDM0MsSUFBSSxPQUFPLENBQUMsQ0FBQyxFQUFFLEtBQUssUUFBUSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDakUsSUFBSSxPQUFPLENBQUMsQ0FBQyxJQUFJLEtBQUssUUFBUSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDM0UsSUFBSSxPQUFPLENBQUMsQ0FBQyxNQUFNLEtBQUssUUFBUSxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUN2RSxJQUFJLE9BQU8sQ0FBQyxDQUFDLE1BQU0sS0FBSyxRQUFRLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3ZFLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxLQUFLLFFBQVEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ2hHLElBQUksT0FBTyxDQUFDLENBQUMsVUFBVSxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDL0UsSUFBSSxPQUFPLENBQUMsQ0FBQyxRQUFRLEtBQUssUUFBUSxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUMzRSxJQUFJLE9BQU8sQ0FBQyxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDeEYsT0FBTyxDQUE2QixDQUFDO0FBQ3ZDLENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILFNBQWdCLE9BQU8sQ0FBQyxXQUFtQixFQUFFLE1BQTBCO0lBQ3JFLElBQUksTUFBTSxLQUFLLFNBQVM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUN0QyxPQUFPLFdBQVcsR0FBRyxNQUFNLENBQUM7QUFDOUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRGVwZW5kZW5jeS1mcmVlIGVudmVsb3BlIGd1YXJkIGZvciB0aGUgYnJvd3NlciByZWFsdGltZSBjbGllbnQuXG4gKlxuICogVGhpcyBtaXJyb3JzIGBAdWVuZ2FnZS9jb21tb25gJ3MgYHBsYXRmb3JtRXZlbnRTY2hlbWFgIGFuZCB0aGUgU0RLJ3Mgb3duXG4gKiBgZXZlbnRzL3NjaGVtYS50c2AsIGJ1dCBoYW5kLXJvbGxlZDogdGhlIGAvcmVhbHRpbWVgIHN1YnBhdGggc2hpcHMgd2l0aFxuICogemVybyBydW50aW1lIGRlcGVuZGVuY2llcyAobm8gem9kLCBubyBOb2RlIGJ1aWx0LWlucykgc28gaXQgc3RheXMgYSBmZXdcbiAqIEtCIGluIGEgZnJvbnRlbmQgYnVuZGxlLiBDaGFuZ2Ugb25lLCBjaGFuZ2UgYWxsIHRocmVlLlxuICpcbiAqIE5PIERPTUFJTiBDUk9TUy1DSEVDSywgZGVsaWJlcmF0ZWx5IOKAlCB0aGlzIGlzIHRoZSBvbmUgbWlycm9yIHRoYXQgZG9lc1xuICogbm90IGNhcnJ5IHRoZSByZXNvdXJjZeKGkmRvbWFpbiBtYXAsIGFuZCBpdCBpcyBub3QgYW4gb3ZlcnNpZ2h0OlxuICpcbiAqICAgLSBJdCB3b3VsZCBiZSBjaGVja2luZyB0aGUgd3JvbmcgdGhpbmcuIFRoZSBwcm9kdWNpbmcgU0RLIGRlcml2ZXNcbiAqICAgICBgZG9tYWluYCBmcm9tIGB0eXBlYCBhbmQgdGhlIGNvbnN1bWluZyBzZXJ2aWNlIHJlLXZhbGlkYXRlcyB0aGUgcGFpclxuICogICAgIGJlZm9yZSBpdCBldmVyIHB1Ymxpc2hlcyB0byBhIGNoYW5uZWwuIEJ5IHRoZSB0aW1lIGFuIGVudmVsb3BlXG4gKiAgICAgcmVhY2hlcyBhIGJyb3dzZXIgdGhlIHBhaXIgaGFzIGJlZW4gY2hlY2tlZCB0d2ljZSBzZXJ2ZXItc2lkZTsgYVxuICogICAgIHRoaXJkIGNoZWNrIGNhbiBvbmx5IHJlamVjdCwgbmV2ZXIgcmVwYWlyLlxuICogICAtIEl0IHdvdWxkIHJvdCBkYW5nZXJvdXNseS4gQSBicm93c2VyIGJ1bmRsZSBzaXRzIGluIHNvbWVvbmUncyBjYWNoZVxuICogICAgIGZvciB3ZWVrcy4gQmFraW5nIHRvZGF5J3MgbWFwIGludG8gaXQgbWVhbnMgdGhhdCB0aGUgZGF5IGEgbmV3XG4gKiAgICAgZG9tYWluIHNoaXBzLCBldmVyeSB1bi1yZWZyZXNoZWQgdGFiIHN0YXJ0cyBzaWxlbnRseSBkcm9wcGluZyBsaXZlXG4gKiAgICAgZXZlbnRzIGZvciBpdCDigJQgYSBzdGFsZSBjbGllbnQgcmVqZWN0aW5nIHRoZSBmdXR1cmUsIHdoaWNoIGlzIHRoZVxuICogICAgIGZhaWx1cmUgbW9kZSBgdmFsaWRhdGVQbGF0Zm9ybUV2ZW50YCBpcyBjYXJlZnVsIHRvIGF2b2lkIGV2ZW5cbiAqICAgICBzZXJ2ZXItc2lkZS5cbiAqXG4gKiBTbyB0aGUgZ3VhcmQgaXMgc3RydWN0dXJhbCBvbmx5OiBzaGFwZXMgYW5kIHR5cGVzLCBub3QgbWVtYmVyc2hpcC5cbiAqIGBwYWNrYWdlcy9wbGF0Zm9ybS1zZGsvdGVzdC9ldmVudHMvZG9tYWluLW1hcC50ZXN0LnRzYCBhc3NlcnRzIHRoYXRcbiAqIGV2ZXJ5IGNhbm9uaWNhbCBkb21haW4gaXMgYWNjZXB0ZWQsIGFuZCB0aGF0IGFuIHVubGlzdGVkIG9uZSBpcyB0b28uXG4gKi9cblxuLyoqIFVMSUQ6IENyb2NrZm9yZCBiYXNlMzIsIDI2IGNoYXJzLCBleGNsdWRlcyBJL0wvTy9VLiAqL1xuY29uc3QgVUxJRF9SRSA9IC9eWzAtOUEtSEpLTU5QLVRWLVpdezI2fSQvO1xuXG4vKiogRG90dGVkIGByZXNvdXJjZS5vcGVyYXRpb25gLCBlLmcuIGBvcmRlci5zdGF0dXNfY2hhbmdlZGAuICovXG5jb25zdCBFVkVOVF9UWVBFX1JFID0gL15bYS16XVthLXowLTlfXSpcXC5bYS16XVthLXowLTlfXSokLztcblxuLyoqIFRoZSBwbGF0Zm9ybSBldmVudC1idXMgZW52ZWxvcGUsIGFzIGl0IGFycml2ZXMgYXQgYSBicm93c2VyLiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWFsdGltZUV2ZW50IHtcbiAgaWQ6IHN0cmluZztcbiAgdHlwZTogc3RyaW5nO1xuICBkb21haW46IHN0cmluZztcbiAgc291cmNlOiBzdHJpbmc7XG4gIHZlcnNpb246IG51bWJlcjtcbiAgb2NjdXJyZWRBdDogc3RyaW5nO1xuICB0ZW5hbnRJZDogc3RyaW5nO1xuICBkYXRhOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuLyoqXG4gKiBTdHJ1Y3R1cmFsIGNoZWNrIG9uIGFuIHVudHJ1c3RlZCBwYXlsb2FkLiBSZXR1cm5zIHRoZSBldmVudCBvciBudWxsIOKAlFxuICogbmV2ZXIgdGhyb3dzLCBiZWNhdXNlIGEgc2luZ2xlIG1hbGZvcm1lZCBmcmFtZSBtdXN0IG5vdCB0ZWFyIGRvd24gYVxuICogbGl2ZSBzdWJzY3JpcHRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc1JlYWx0aW1lRXZlbnQodmFsdWU6IHVua25vd24pOiBSZWFsdGltZUV2ZW50IHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnIHx8IHZhbHVlID09PSBudWxsKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgdiA9IHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBpZiAodHlwZW9mIHYuaWQgIT09ICdzdHJpbmcnIHx8ICFVTElEX1JFLnRlc3Qodi5pZCkpIHJldHVybiBudWxsO1xuICBpZiAodHlwZW9mIHYudHlwZSAhPT0gJ3N0cmluZycgfHwgIUVWRU5UX1RZUEVfUkUudGVzdCh2LnR5cGUpKSByZXR1cm4gbnVsbDtcbiAgaWYgKHR5cGVvZiB2LmRvbWFpbiAhPT0gJ3N0cmluZycgfHwgdi5kb21haW4ubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgaWYgKHR5cGVvZiB2LnNvdXJjZSAhPT0gJ3N0cmluZycgfHwgdi5zb3VyY2UubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgaWYgKHR5cGVvZiB2LnZlcnNpb24gIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKHYudmVyc2lvbikgfHwgdi52ZXJzaW9uIDwgMSkgcmV0dXJuIG51bGw7XG4gIGlmICh0eXBlb2Ygdi5vY2N1cnJlZEF0ICE9PSAnc3RyaW5nJyB8fCB2Lm9jY3VycmVkQXQubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgaWYgKHR5cGVvZiB2LnRlbmFudElkICE9PSAnc3RyaW5nJyB8fCB2LnRlbmFudElkLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG4gIGlmICh0eXBlb2Ygdi5kYXRhICE9PSAnb2JqZWN0JyB8fCB2LmRhdGEgPT09IG51bGwgfHwgQXJyYXkuaXNBcnJheSh2LmRhdGEpKSByZXR1cm4gbnVsbDtcbiAgcmV0dXJuIHYgYXMgdW5rbm93biBhcyBSZWFsdGltZUV2ZW50O1xufVxuXG4vKipcbiAqIE9yZGVyaW5nL2RlZHVwZSBndWFyZCwga2V5ZWQgb24gdGhlIGVudmVsb3BlJ3MgbW9ub3RvbmljIFVMSUQuXG4gKlxuICogVUxJRHMgYXJlIGxleGljb2dyYXBoaWNhbGx5IHNvcnRhYmxlIGJ5IG1pbnQgdGltZSwgc28gYSBwbGFpbiBzdHJpbmdcbiAqIGNvbXBhcmUgb3JkZXJzIGV2ZW50cyB3aXRob3V0IHBhcnNpbmcgdGltZXN0YW1wcyBvciBrbm93aW5nIGFueXRoaW5nXG4gKiBhYm91dCB0aGUgZG9tYWluLiBUaGlzIGlzIHdoYXQgbWFrZXMgYXQtbGVhc3Qtb25jZSBkZWxpdmVyeSBhbmQgdGhlXG4gKiBzbmFwc2hvdC9zdHJlYW0gcmFjZSBib3RoIGhhcm1sZXNzOiB3aGljaGV2ZXIgYXJyaXZlcyBzZWNvbmQgd2l0aCBhblxuICogaWQgPD0gdGhlIG9uZSBhbHJlYWR5IHJlbmRlcmVkIGlzIGRyb3BwZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc05ld2VyKGNhbmRpZGF0ZUlkOiBzdHJpbmcsIHNlZW5JZDogc3RyaW5nIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gIGlmIChzZWVuSWQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHRydWU7XG4gIHJldHVybiBjYW5kaWRhdGVJZCA+IHNlZW5JZDtcbn1cbiJdfQ==
@@ -0,0 +1,37 @@
1
+ /**
2
+ * `@uengage.io/platform-sdk/realtime` — browser-safe realtime client.
3
+ *
4
+ * A thin client for the platform's AppSync Events API: it owns the wire
5
+ * protocol, the keepalive watchdog, reconnect with jittered backoff,
6
+ * resubscribe, token refresh, snapshot catch-up on every (re)connect,
7
+ * and ULID-based ordering/dedupe. Apps own rendering and channel names.
8
+ *
9
+ * ```ts
10
+ * import { realtime } from '@uengage.io/platform-sdk/realtime';
11
+ *
12
+ * const client = realtime.connect({
13
+ * env: 'prod',
14
+ * getToken: () => session.jwt(),
15
+ * });
16
+ *
17
+ * const sub = client.subscribe(`/orders/${orderId}`, {
18
+ * onUpdate(event, meta) { render(event.data); },
19
+ * onError(err) { showOffline(err); },
20
+ * });
21
+ *
22
+ * sub.unsubscribe();
23
+ * ```
24
+ *
25
+ * This subpath is deliberately isolated from the SDK's main entry: zero
26
+ * runtime dependencies, no Node built-ins, no server auth code, so it
27
+ * stays a few KB in a frontend bundle and works unchanged in React
28
+ * Native. Do not import from `../` here.
29
+ */
30
+ import { connect } from './connect';
31
+ export declare const realtime: {
32
+ connect: typeof connect;
33
+ };
34
+ export { connect, jitteredBackoff, type RealtimeClient, type RealtimeConnectOptions, type Subscription, type SubscribeOptions, type UpdateMeta, type MinimalWebSocket, type WebSocketCtor, } from './connect';
35
+ export { asRealtimeEvent, isNewer, type RealtimeEvent } from './envelope';
36
+ export { API_BASE, endpointsFor, type RealtimeEndpoints, type RealtimeEnv } from './endpoints';
37
+ export { EVENT_WS_SUBPROTOCOL, authHeader, authSubprotocol, base64UrlEncode } from './protocol';
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.base64UrlEncode = exports.authSubprotocol = exports.authHeader = exports.EVENT_WS_SUBPROTOCOL = exports.endpointsFor = exports.API_BASE = exports.isNewer = exports.asRealtimeEvent = exports.jitteredBackoff = exports.connect = exports.realtime = void 0;
4
+ /**
5
+ * `@uengage.io/platform-sdk/realtime` — browser-safe realtime client.
6
+ *
7
+ * A thin client for the platform's AppSync Events API: it owns the wire
8
+ * protocol, the keepalive watchdog, reconnect with jittered backoff,
9
+ * resubscribe, token refresh, snapshot catch-up on every (re)connect,
10
+ * and ULID-based ordering/dedupe. Apps own rendering and channel names.
11
+ *
12
+ * ```ts
13
+ * import { realtime } from '@uengage.io/platform-sdk/realtime';
14
+ *
15
+ * const client = realtime.connect({
16
+ * env: 'prod',
17
+ * getToken: () => session.jwt(),
18
+ * });
19
+ *
20
+ * const sub = client.subscribe(`/orders/${orderId}`, {
21
+ * onUpdate(event, meta) { render(event.data); },
22
+ * onError(err) { showOffline(err); },
23
+ * });
24
+ *
25
+ * sub.unsubscribe();
26
+ * ```
27
+ *
28
+ * This subpath is deliberately isolated from the SDK's main entry: zero
29
+ * runtime dependencies, no Node built-ins, no server auth code, so it
30
+ * stays a few KB in a frontend bundle and works unchanged in React
31
+ * Native. Do not import from `../` here.
32
+ */
33
+ const connect_1 = require("./connect");
34
+ exports.realtime = { connect: connect_1.connect };
35
+ var connect_2 = require("./connect");
36
+ Object.defineProperty(exports, "connect", { enumerable: true, get: function () { return connect_2.connect; } });
37
+ Object.defineProperty(exports, "jitteredBackoff", { enumerable: true, get: function () { return connect_2.jitteredBackoff; } });
38
+ var envelope_1 = require("./envelope");
39
+ Object.defineProperty(exports, "asRealtimeEvent", { enumerable: true, get: function () { return envelope_1.asRealtimeEvent; } });
40
+ Object.defineProperty(exports, "isNewer", { enumerable: true, get: function () { return envelope_1.isNewer; } });
41
+ var endpoints_1 = require("./endpoints");
42
+ Object.defineProperty(exports, "API_BASE", { enumerable: true, get: function () { return endpoints_1.API_BASE; } });
43
+ Object.defineProperty(exports, "endpointsFor", { enumerable: true, get: function () { return endpoints_1.endpointsFor; } });
44
+ var protocol_1 = require("./protocol");
45
+ Object.defineProperty(exports, "EVENT_WS_SUBPROTOCOL", { enumerable: true, get: function () { return protocol_1.EVENT_WS_SUBPROTOCOL; } });
46
+ Object.defineProperty(exports, "authHeader", { enumerable: true, get: function () { return protocol_1.authHeader; } });
47
+ Object.defineProperty(exports, "authSubprotocol", { enumerable: true, get: function () { return protocol_1.authSubprotocol; } });
48
+ Object.defineProperty(exports, "base64UrlEncode", { enumerable: true, get: function () { return protocol_1.base64UrlEncode; } });
49
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVhbHRpbWUvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E0Qkc7QUFDSCx1Q0FBb0M7QUFFdkIsUUFBQSxRQUFRLEdBQUcsRUFBRSxPQUFPLEVBQVAsaUJBQU8sRUFBRSxDQUFDO0FBRXBDLHFDQVVtQjtBQVRqQixrR0FBQSxPQUFPLE9BQUE7QUFDUCwwR0FBQSxlQUFlLE9BQUE7QUFTakIsdUNBQTBFO0FBQWpFLDJHQUFBLGVBQWUsT0FBQTtBQUFFLG1HQUFBLE9BQU8sT0FBQTtBQUNqQyx5Q0FBK0Y7QUFBdEYscUdBQUEsUUFBUSxPQUFBO0FBQUUseUdBQUEsWUFBWSxPQUFBO0FBQy9CLHVDQUFnRztBQUF2RixnSEFBQSxvQkFBb0IsT0FBQTtBQUFFLHNHQUFBLFVBQVUsT0FBQTtBQUFFLDJHQUFBLGVBQWUsT0FBQTtBQUFFLDJHQUFBLGVBQWUsT0FBQSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogYEB1ZW5nYWdlLmlvL3BsYXRmb3JtLXNkay9yZWFsdGltZWAg4oCUIGJyb3dzZXItc2FmZSByZWFsdGltZSBjbGllbnQuXG4gKlxuICogQSB0aGluIGNsaWVudCBmb3IgdGhlIHBsYXRmb3JtJ3MgQXBwU3luYyBFdmVudHMgQVBJOiBpdCBvd25zIHRoZSB3aXJlXG4gKiBwcm90b2NvbCwgdGhlIGtlZXBhbGl2ZSB3YXRjaGRvZywgcmVjb25uZWN0IHdpdGggaml0dGVyZWQgYmFja29mZixcbiAqIHJlc3Vic2NyaWJlLCB0b2tlbiByZWZyZXNoLCBzbmFwc2hvdCBjYXRjaC11cCBvbiBldmVyeSAocmUpY29ubmVjdCxcbiAqIGFuZCBVTElELWJhc2VkIG9yZGVyaW5nL2RlZHVwZS4gQXBwcyBvd24gcmVuZGVyaW5nIGFuZCBjaGFubmVsIG5hbWVzLlxuICpcbiAqIGBgYHRzXG4gKiBpbXBvcnQgeyByZWFsdGltZSB9IGZyb20gJ0B1ZW5nYWdlLmlvL3BsYXRmb3JtLXNkay9yZWFsdGltZSc7XG4gKlxuICogY29uc3QgY2xpZW50ID0gcmVhbHRpbWUuY29ubmVjdCh7XG4gKiAgIGVudjogJ3Byb2QnLFxuICogICBnZXRUb2tlbjogKCkgPT4gc2Vzc2lvbi5qd3QoKSxcbiAqIH0pO1xuICpcbiAqIGNvbnN0IHN1YiA9IGNsaWVudC5zdWJzY3JpYmUoYC9vcmRlcnMvJHtvcmRlcklkfWAsIHtcbiAqICAgb25VcGRhdGUoZXZlbnQsIG1ldGEpIHsgcmVuZGVyKGV2ZW50LmRhdGEpOyB9LFxuICogICBvbkVycm9yKGVycikgeyBzaG93T2ZmbGluZShlcnIpOyB9LFxuICogfSk7XG4gKlxuICogc3ViLnVuc3Vic2NyaWJlKCk7XG4gKiBgYGBcbiAqXG4gKiBUaGlzIHN1YnBhdGggaXMgZGVsaWJlcmF0ZWx5IGlzb2xhdGVkIGZyb20gdGhlIFNESydzIG1haW4gZW50cnk6IHplcm9cbiAqIHJ1bnRpbWUgZGVwZW5kZW5jaWVzLCBubyBOb2RlIGJ1aWx0LWlucywgbm8gc2VydmVyIGF1dGggY29kZSwgc28gaXRcbiAqIHN0YXlzIGEgZmV3IEtCIGluIGEgZnJvbnRlbmQgYnVuZGxlIGFuZCB3b3JrcyB1bmNoYW5nZWQgaW4gUmVhY3RcbiAqIE5hdGl2ZS4gRG8gbm90IGltcG9ydCBmcm9tIGAuLi9gIGhlcmUuXG4gKi9cbmltcG9ydCB7IGNvbm5lY3QgfSBmcm9tICcuL2Nvbm5lY3QnO1xuXG5leHBvcnQgY29uc3QgcmVhbHRpbWUgPSB7IGNvbm5lY3QgfTtcblxuZXhwb3J0IHtcbiAgY29ubmVjdCxcbiAgaml0dGVyZWRCYWNrb2ZmLFxuICB0eXBlIFJlYWx0aW1lQ2xpZW50LFxuICB0eXBlIFJlYWx0aW1lQ29ubmVjdE9wdGlvbnMsXG4gIHR5cGUgU3Vic2NyaXB0aW9uLFxuICB0eXBlIFN1YnNjcmliZU9wdGlvbnMsXG4gIHR5cGUgVXBkYXRlTWV0YSxcbiAgdHlwZSBNaW5pbWFsV2ViU29ja2V0LFxuICB0eXBlIFdlYlNvY2tldEN0b3IsXG59IGZyb20gJy4vY29ubmVjdCc7XG5leHBvcnQgeyBhc1JlYWx0aW1lRXZlbnQsIGlzTmV3ZXIsIHR5cGUgUmVhbHRpbWVFdmVudCB9IGZyb20gJy4vZW52ZWxvcGUnO1xuZXhwb3J0IHsgQVBJX0JBU0UsIGVuZHBvaW50c0ZvciwgdHlwZSBSZWFsdGltZUVuZHBvaW50cywgdHlwZSBSZWFsdGltZUVudiB9IGZyb20gJy4vZW5kcG9pbnRzJztcbmV4cG9ydCB7IEVWRU5UX1dTX1NVQlBST1RPQ09MLCBhdXRoSGVhZGVyLCBhdXRoU3VicHJvdG9jb2wsIGJhc2U2NFVybEVuY29kZSB9IGZyb20gJy4vcHJvdG9jb2wnO1xuIl19
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The AppSync Events WebSocket wire protocol, as documented at
3
+ * https://docs.aws.amazon.com/appsync/latest/eventapi/event-api-websocket-protocol.html
4
+ *
5
+ * Everything here is pure data + string manipulation: no I/O, no
6
+ * dependencies, no Node built-ins. The socket lifecycle lives in
7
+ * `connect.ts`.
8
+ */
9
+ /** WebSocket subprotocol that selects the Events (not GraphQL) protocol. */
10
+ export declare const EVENT_WS_SUBPROTOCOL = "aws-appsync-event-ws";
11
+ /**
12
+ * AppSync takes connection auth as a *subprotocol*, because a browser
13
+ * WebSocket cannot set request headers. The auth header object is
14
+ * JSON-encoded, base64url-encoded, and prefixed with `header-`.
15
+ */
16
+ export declare function authSubprotocol(header: Record<string, string>): string;
17
+ /**
18
+ * The auth object AppSync expects, for both the connection handshake and
19
+ * each `subscribe` frame. `host` must be the API's HTTP domain (not the
20
+ * realtime domain) — AppSync validates the signature/token against it.
21
+ */
22
+ export declare function authHeader(httpHost: string, token: string): Record<string, string>;
23
+ /**
24
+ * base64url with padding stripped. Uses `btoa` over UTF-8 bytes rather
25
+ * than `Buffer`, which does not exist in a browser.
26
+ */
27
+ export declare function base64UrlEncode(input: string): string;
28
+ export interface ConnectionAckFrame {
29
+ type: 'connection_ack';
30
+ /**
31
+ * How long the server will tolerate silence before it closes the
32
+ * connection. The client watchdog uses this rather than a hard-coded
33
+ * 60s so a server-side change doesn't strand us.
34
+ */
35
+ connectionTimeoutMs?: number;
36
+ }
37
+ export interface DataFrame {
38
+ type: 'data';
39
+ id: string;
40
+ /**
41
+ * The published payload, JSON-encoded *inside* the already-JSON frame.
42
+ * Double-encoded on the wire; `parseDataFrameEvent` unwraps both.
43
+ */
44
+ event: string;
45
+ }
46
+ export interface ErrorFrame {
47
+ type: 'connection_error' | 'subscribe_error' | 'publish_error';
48
+ id?: string;
49
+ errors?: Array<{
50
+ errorType?: string;
51
+ message?: string;
52
+ }>;
53
+ }
54
+ export type ServerFrame = ConnectionAckFrame | DataFrame | ErrorFrame | {
55
+ type: 'ka';
56
+ } | {
57
+ type: 'subscribe_success';
58
+ id: string;
59
+ } | {
60
+ type: 'unsubscribe_success';
61
+ id: string;
62
+ } | {
63
+ type: string;
64
+ [k: string]: unknown;
65
+ };
66
+ export declare function parseServerFrame(raw: string): ServerFrame | null;
67
+ /** Unwrap the inner JSON of a `data` frame. Null if it isn't parseable. */
68
+ export declare function parseDataFrameEvent(frame: DataFrame): unknown;
69
+ /** Human-readable text from an error frame, for `onError`. */
70
+ export declare function errorFrameMessage(frame: ErrorFrame): string;
71
+ export declare function connectionInitFrame(): string;
72
+ export declare function subscribeFrame(id: string, channel: string, auth: Record<string, string>): string;
73
+ export declare function unsubscribeFrame(id: string): string;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ /**
3
+ * The AppSync Events WebSocket wire protocol, as documented at
4
+ * https://docs.aws.amazon.com/appsync/latest/eventapi/event-api-websocket-protocol.html
5
+ *
6
+ * Everything here is pure data + string manipulation: no I/O, no
7
+ * dependencies, no Node built-ins. The socket lifecycle lives in
8
+ * `connect.ts`.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.EVENT_WS_SUBPROTOCOL = void 0;
12
+ exports.authSubprotocol = authSubprotocol;
13
+ exports.authHeader = authHeader;
14
+ exports.base64UrlEncode = base64UrlEncode;
15
+ exports.parseServerFrame = parseServerFrame;
16
+ exports.parseDataFrameEvent = parseDataFrameEvent;
17
+ exports.errorFrameMessage = errorFrameMessage;
18
+ exports.connectionInitFrame = connectionInitFrame;
19
+ exports.subscribeFrame = subscribeFrame;
20
+ exports.unsubscribeFrame = unsubscribeFrame;
21
+ /** WebSocket subprotocol that selects the Events (not GraphQL) protocol. */
22
+ exports.EVENT_WS_SUBPROTOCOL = 'aws-appsync-event-ws';
23
+ /**
24
+ * AppSync takes connection auth as a *subprotocol*, because a browser
25
+ * WebSocket cannot set request headers. The auth header object is
26
+ * JSON-encoded, base64url-encoded, and prefixed with `header-`.
27
+ */
28
+ function authSubprotocol(header) {
29
+ return `header-${base64UrlEncode(JSON.stringify(header))}`;
30
+ }
31
+ /**
32
+ * The auth object AppSync expects, for both the connection handshake and
33
+ * each `subscribe` frame. `host` must be the API's HTTP domain (not the
34
+ * realtime domain) — AppSync validates the signature/token against it.
35
+ */
36
+ function authHeader(httpHost, token) {
37
+ return { host: httpHost, Authorization: token };
38
+ }
39
+ /**
40
+ * base64url with padding stripped. Uses `btoa` over UTF-8 bytes rather
41
+ * than `Buffer`, which does not exist in a browser.
42
+ */
43
+ function base64UrlEncode(input) {
44
+ const bytes = new TextEncoder().encode(input);
45
+ let binary = '';
46
+ for (let i = 0; i < bytes.length; i++)
47
+ binary += String.fromCharCode(bytes[i]);
48
+ return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
49
+ }
50
+ function parseServerFrame(raw) {
51
+ try {
52
+ const parsed = JSON.parse(raw);
53
+ if (typeof parsed !== 'object' || parsed === null)
54
+ return null;
55
+ const frame = parsed;
56
+ if (typeof frame.type !== 'string')
57
+ return null;
58
+ return parsed;
59
+ }
60
+ catch {
61
+ return null;
62
+ }
63
+ }
64
+ /** Unwrap the inner JSON of a `data` frame. Null if it isn't parseable. */
65
+ function parseDataFrameEvent(frame) {
66
+ try {
67
+ return JSON.parse(frame.event);
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ }
73
+ /** Human-readable text from an error frame, for `onError`. */
74
+ function errorFrameMessage(frame) {
75
+ const parts = (frame.errors ?? [])
76
+ .map((e) => e.message ?? e.errorType)
77
+ .filter((m) => typeof m === 'string' && m.length > 0);
78
+ return parts.length > 0 ? parts.join('; ') : frame.type;
79
+ }
80
+ function connectionInitFrame() {
81
+ return JSON.stringify({ type: 'connection_init' });
82
+ }
83
+ function subscribeFrame(id, channel, auth) {
84
+ return JSON.stringify({ type: 'subscribe', id, channel, authorization: auth });
85
+ }
86
+ function unsubscribeFrame(id) {
87
+ return JSON.stringify({ type: 'unsubscribe', id });
88
+ }
89
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVhbHRpbWUvcHJvdG9jb2wudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7O0dBT0c7OztBQVVILDBDQUVDO0FBT0QsZ0NBRUM7QUFNRCwwQ0FLQztBQXVDRCw0Q0FVQztBQUdELGtEQU1DO0FBR0QsOENBS0M7QUFFRCxrREFFQztBQUVELHdDQUVDO0FBRUQsNENBRUM7QUE1R0QsNEVBQTRFO0FBQy9ELFFBQUEsb0JBQW9CLEdBQUcsc0JBQXNCLENBQUM7QUFFM0Q7Ozs7R0FJRztBQUNILFNBQWdCLGVBQWUsQ0FBQyxNQUE4QjtJQUM1RCxPQUFPLFVBQVUsZUFBZSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQzdELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBZ0IsVUFBVSxDQUFDLFFBQWdCLEVBQUUsS0FBYTtJQUN4RCxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLENBQUM7QUFDbEQsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQWdCLGVBQWUsQ0FBQyxLQUFhO0lBQzNDLE1BQU0sS0FBSyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzlDLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztJQUNoQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUU7UUFBRSxNQUFNLElBQUksTUFBTSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvRSxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNqRixDQUFDO0FBdUNELFNBQWdCLGdCQUFnQixDQUFDLEdBQVc7SUFDMUMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQVksQ0FBQztRQUMxQyxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsSUFBSSxNQUFNLEtBQUssSUFBSTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQy9ELE1BQU0sS0FBSyxHQUFHLE1BQTRCLENBQUM7UUFDM0MsSUFBSSxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssUUFBUTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQ2hELE9BQU8sTUFBcUIsQ0FBQztJQUMvQixDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0FBQ0gsQ0FBQztBQUVELDJFQUEyRTtBQUMzRSxTQUFnQixtQkFBbUIsQ0FBQyxLQUFnQjtJQUNsRCxJQUFJLENBQUM7UUFDSCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBWSxDQUFDO0lBQzVDLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDO0FBRUQsOERBQThEO0FBQzlELFNBQWdCLGlCQUFpQixDQUFDLEtBQWlCO0lBQ2pELE1BQU0sS0FBSyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUM7U0FDL0IsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUM7U0FDcEMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFlLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUksQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNyRSxPQUFPLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDO0FBQzFELENBQUM7QUFFRCxTQUFnQixtQkFBbUI7SUFDakMsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFLENBQUMsQ0FBQztBQUNyRCxDQUFDO0FBRUQsU0FBZ0IsY0FBYyxDQUFDLEVBQVUsRUFBRSxPQUFlLEVBQUUsSUFBNEI7SUFDdEYsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ2pGLENBQUM7QUFFRCxTQUFnQixnQkFBZ0IsQ0FBQyxFQUFVO0lBQ3pDLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUNyRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgQXBwU3luYyBFdmVudHMgV2ViU29ja2V0IHdpcmUgcHJvdG9jb2wsIGFzIGRvY3VtZW50ZWQgYXRcbiAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBzeW5jL2xhdGVzdC9ldmVudGFwaS9ldmVudC1hcGktd2Vic29ja2V0LXByb3RvY29sLmh0bWxcbiAqXG4gKiBFdmVyeXRoaW5nIGhlcmUgaXMgcHVyZSBkYXRhICsgc3RyaW5nIG1hbmlwdWxhdGlvbjogbm8gSS9PLCBub1xuICogZGVwZW5kZW5jaWVzLCBubyBOb2RlIGJ1aWx0LWlucy4gVGhlIHNvY2tldCBsaWZlY3ljbGUgbGl2ZXMgaW5cbiAqIGBjb25uZWN0LnRzYC5cbiAqL1xuXG4vKiogV2ViU29ja2V0IHN1YnByb3RvY29sIHRoYXQgc2VsZWN0cyB0aGUgRXZlbnRzIChub3QgR3JhcGhRTCkgcHJvdG9jb2wuICovXG5leHBvcnQgY29uc3QgRVZFTlRfV1NfU1VCUFJPVE9DT0wgPSAnYXdzLWFwcHN5bmMtZXZlbnQtd3MnO1xuXG4vKipcbiAqIEFwcFN5bmMgdGFrZXMgY29ubmVjdGlvbiBhdXRoIGFzIGEgKnN1YnByb3RvY29sKiwgYmVjYXVzZSBhIGJyb3dzZXJcbiAqIFdlYlNvY2tldCBjYW5ub3Qgc2V0IHJlcXVlc3QgaGVhZGVycy4gVGhlIGF1dGggaGVhZGVyIG9iamVjdCBpc1xuICogSlNPTi1lbmNvZGVkLCBiYXNlNjR1cmwtZW5jb2RlZCwgYW5kIHByZWZpeGVkIHdpdGggYGhlYWRlci1gLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXV0aFN1YnByb3RvY29sKGhlYWRlcjogUmVjb3JkPHN0cmluZywgc3RyaW5nPik6IHN0cmluZyB7XG4gIHJldHVybiBgaGVhZGVyLSR7YmFzZTY0VXJsRW5jb2RlKEpTT04uc3RyaW5naWZ5KGhlYWRlcikpfWA7XG59XG5cbi8qKlxuICogVGhlIGF1dGggb2JqZWN0IEFwcFN5bmMgZXhwZWN0cywgZm9yIGJvdGggdGhlIGNvbm5lY3Rpb24gaGFuZHNoYWtlIGFuZFxuICogZWFjaCBgc3Vic2NyaWJlYCBmcmFtZS4gYGhvc3RgIG11c3QgYmUgdGhlIEFQSSdzIEhUVFAgZG9tYWluIChub3QgdGhlXG4gKiByZWFsdGltZSBkb21haW4pIOKAlCBBcHBTeW5jIHZhbGlkYXRlcyB0aGUgc2lnbmF0dXJlL3Rva2VuIGFnYWluc3QgaXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhdXRoSGVhZGVyKGh0dHBIb3N0OiBzdHJpbmcsIHRva2VuOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgcmV0dXJuIHsgaG9zdDogaHR0cEhvc3QsIEF1dGhvcml6YXRpb246IHRva2VuIH07XG59XG5cbi8qKlxuICogYmFzZTY0dXJsIHdpdGggcGFkZGluZyBzdHJpcHBlZC4gVXNlcyBgYnRvYWAgb3ZlciBVVEYtOCBieXRlcyByYXRoZXJcbiAqIHRoYW4gYEJ1ZmZlcmAsIHdoaWNoIGRvZXMgbm90IGV4aXN0IGluIGEgYnJvd3Nlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJhc2U2NFVybEVuY29kZShpbnB1dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgYnl0ZXMgPSBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoaW5wdXQpO1xuICBsZXQgYmluYXJ5ID0gJyc7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpKyspIGJpbmFyeSArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGVzW2ldKTtcbiAgcmV0dXJuIGJ0b2EoYmluYXJ5KS5yZXBsYWNlKC9cXCsvZywgJy0nKS5yZXBsYWNlKC9cXC8vZywgJ18nKS5yZXBsYWNlKC89KyQvLCAnJyk7XG59XG5cbi8vIOKUgOKUgOKUgCBGcmFtZXMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29ubmVjdGlvbkFja0ZyYW1lIHtcbiAgdHlwZTogJ2Nvbm5lY3Rpb25fYWNrJztcbiAgLyoqXG4gICAqIEhvdyBsb25nIHRoZSBzZXJ2ZXIgd2lsbCB0b2xlcmF0ZSBzaWxlbmNlIGJlZm9yZSBpdCBjbG9zZXMgdGhlXG4gICAqIGNvbm5lY3Rpb24uIFRoZSBjbGllbnQgd2F0Y2hkb2cgdXNlcyB0aGlzIHJhdGhlciB0aGFuIGEgaGFyZC1jb2RlZFxuICAgKiA2MHMgc28gYSBzZXJ2ZXItc2lkZSBjaGFuZ2UgZG9lc24ndCBzdHJhbmQgdXMuXG4gICAqL1xuICBjb25uZWN0aW9uVGltZW91dE1zPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERhdGFGcmFtZSB7XG4gIHR5cGU6ICdkYXRhJztcbiAgaWQ6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBwdWJsaXNoZWQgcGF5bG9hZCwgSlNPTi1lbmNvZGVkICppbnNpZGUqIHRoZSBhbHJlYWR5LUpTT04gZnJhbWUuXG4gICAqIERvdWJsZS1lbmNvZGVkIG9uIHRoZSB3aXJlOyBgcGFyc2VEYXRhRnJhbWVFdmVudGAgdW53cmFwcyBib3RoLlxuICAgKi9cbiAgZXZlbnQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFcnJvckZyYW1lIHtcbiAgdHlwZTogJ2Nvbm5lY3Rpb25fZXJyb3InIHwgJ3N1YnNjcmliZV9lcnJvcicgfCAncHVibGlzaF9lcnJvcic7XG4gIGlkPzogc3RyaW5nO1xuICBlcnJvcnM/OiBBcnJheTx7IGVycm9yVHlwZT86IHN0cmluZzsgbWVzc2FnZT86IHN0cmluZyB9Pjtcbn1cblxuZXhwb3J0IHR5cGUgU2VydmVyRnJhbWUgPVxuICB8IENvbm5lY3Rpb25BY2tGcmFtZVxuICB8IERhdGFGcmFtZVxuICB8IEVycm9yRnJhbWVcbiAgfCB7IHR5cGU6ICdrYScgfVxuICB8IHsgdHlwZTogJ3N1YnNjcmliZV9zdWNjZXNzJzsgaWQ6IHN0cmluZyB9XG4gIHwgeyB0eXBlOiAndW5zdWJzY3JpYmVfc3VjY2Vzcyc7IGlkOiBzdHJpbmcgfVxuICB8IHsgdHlwZTogc3RyaW5nOyBbazogc3RyaW5nXTogdW5rbm93biB9O1xuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VTZXJ2ZXJGcmFtZShyYXc6IHN0cmluZyk6IFNlcnZlckZyYW1lIHwgbnVsbCB7XG4gIHRyeSB7XG4gICAgY29uc3QgcGFyc2VkID0gSlNPTi5wYXJzZShyYXcpIGFzIHVua25vd247XG4gICAgaWYgKHR5cGVvZiBwYXJzZWQgIT09ICdvYmplY3QnIHx8IHBhcnNlZCA9PT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgZnJhbWUgPSBwYXJzZWQgYXMgeyB0eXBlPzogdW5rbm93biB9O1xuICAgIGlmICh0eXBlb2YgZnJhbWUudHlwZSAhPT0gJ3N0cmluZycpIHJldHVybiBudWxsO1xuICAgIHJldHVybiBwYXJzZWQgYXMgU2VydmVyRnJhbWU7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbi8qKiBVbndyYXAgdGhlIGlubmVyIEpTT04gb2YgYSBgZGF0YWAgZnJhbWUuIE51bGwgaWYgaXQgaXNuJ3QgcGFyc2VhYmxlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlRGF0YUZyYW1lRXZlbnQoZnJhbWU6IERhdGFGcmFtZSk6IHVua25vd24ge1xuICB0cnkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKGZyYW1lLmV2ZW50KSBhcyB1bmtub3duO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG4vKiogSHVtYW4tcmVhZGFibGUgdGV4dCBmcm9tIGFuIGVycm9yIGZyYW1lLCBmb3IgYG9uRXJyb3JgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVycm9yRnJhbWVNZXNzYWdlKGZyYW1lOiBFcnJvckZyYW1lKTogc3RyaW5nIHtcbiAgY29uc3QgcGFydHMgPSAoZnJhbWUuZXJyb3JzID8/IFtdKVxuICAgIC5tYXAoKGUpID0+IGUubWVzc2FnZSA/PyBlLmVycm9yVHlwZSlcbiAgICAuZmlsdGVyKChtKTogbSBpcyBzdHJpbmcgPT4gdHlwZW9mIG0gPT09ICdzdHJpbmcnICYmIG0ubGVuZ3RoID4gMCk7XG4gIHJldHVybiBwYXJ0cy5sZW5ndGggPiAwID8gcGFydHMuam9pbignOyAnKSA6IGZyYW1lLnR5cGU7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb25uZWN0aW9uSW5pdEZyYW1lKCk6IHN0cmluZyB7XG4gIHJldHVybiBKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICdjb25uZWN0aW9uX2luaXQnIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3Vic2NyaWJlRnJhbWUoaWQ6IHN0cmluZywgY2hhbm5lbDogc3RyaW5nLCBhdXRoOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogc3RyaW5nIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHsgdHlwZTogJ3N1YnNjcmliZScsIGlkLCBjaGFubmVsLCBhdXRob3JpemF0aW9uOiBhdXRoIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdW5zdWJzY3JpYmVGcmFtZShpZDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHsgdHlwZTogJ3Vuc3Vic2NyaWJlJywgaWQgfSk7XG59XG4iXX0=
package/package.json CHANGED
@@ -1,9 +1,34 @@
1
1
  {
2
2
  "name": "@uengage.io/platform-sdk",
3
- "version": "0.15.0",
4
- "description": "Client SDK for the uEngage platform API (audit, business, zones, wallet, auth). Single createClient(...) factory; OAuth2 client_credentials, static Bearer, or legacy session-token auth modes.",
3
+ "version": "1.0.0",
4
+ "description": "Client SDK for the uEngage platform API (audit, business, zones, wallet, auth, events). Single createClient(...) factory; OAuth2 client_credentials, static Bearer, or legacy session-token auth modes. Browser-safe realtime client at the /realtime subpath.",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ },
12
+ "./events": {
13
+ "types": "./dist/events/index.d.ts",
14
+ "default": "./dist/events/index.js"
15
+ },
16
+ "./realtime": {
17
+ "types": "./dist/realtime/index.d.ts",
18
+ "default": "./dist/realtime/index.js"
19
+ },
20
+ "./package.json": "./package.json"
21
+ },
22
+ "typesVersions": {
23
+ "*": {
24
+ "events": [
25
+ "./dist/events/index.d.ts"
26
+ ],
27
+ "realtime": [
28
+ "./dist/realtime/index.d.ts"
29
+ ]
30
+ }
31
+ },
7
32
  "files": [
8
33
  "dist/",
9
34
  "README.md"
@@ -18,6 +43,8 @@
18
43
  "sdk",
19
44
  "audit",
20
45
  "business",
46
+ "events",
47
+ "realtime",
21
48
  "hmac"
22
49
  ],
23
50
  "dependencies": {
@@ -27,12 +54,21 @@
27
54
  "@uengage.io/js-logger": "0.10.0"
28
55
  },
29
56
  "devDependencies": {
57
+ "@aws-sdk/client-sns": "^3.668.0",
30
58
  "@types/jest": "^29.5.14",
31
59
  "@types/node": "^20.14.10",
32
60
  "jest": "^29.7.0",
33
61
  "ts-jest": "^29.2.5",
34
62
  "typescript": "^5.5.4"
35
63
  },
64
+ "peerDependencies": {
65
+ "@aws-sdk/client-sns": "^3.0.0"
66
+ },
67
+ "peerDependenciesMeta": {
68
+ "@aws-sdk/client-sns": {
69
+ "optional": true
70
+ }
71
+ },
36
72
  "scripts": {
37
73
  "build": "tsc",
38
74
  "typecheck": "tsc --noEmit",