@launchdarkly/js-sdk-common 2.20.0 → 2.21.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.
@@ -1 +1 @@
1
- {"version":3,"file":"proto.d.ts","sourceRoot":"","sources":["../../../src/internal/fdv2/proto.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,eAAe,GACf,YAAY,GACZ,eAAe,GACf,qBAAqB,GACrB,SAAS,GACT,OAAO,GACP,YAAY,CAAC;AACjB,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,MAAM,CAAC;AAC/D,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5C,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EACA,gBAAgB,GAChB,SAAS,GACT,YAAY,GACZ,kBAAkB,GAClB,aAAa,GACb,WAAW,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb"}
1
+ {"version":3,"file":"proto.d.ts","sourceRoot":"","sources":["../../../src/internal/fdv2/proto.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GACjB,eAAe,GACf,YAAY,GACZ,eAAe,GACf,qBAAqB,GACrB,SAAS,GACT,OAAO,GACP,YAAY,CAAC;AAEjB,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,cAAc,GAAG,MAAM,CAAC;AAC/D,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5C,MAAM,WAAW,SAAS;IACxB;;;OAGG;IACH,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;IAC1B;;;OAGG;IACH,IAAI,EACA,gBAAgB,GAChB,SAAS,GACT,YAAY,GACZ,kBAAkB,GAClB,aAAa,GACb,WAAW,GACX,OAAO,CAAC;CACb;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,SAAS,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,GAAG,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,UAAU,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb"}
@@ -0,0 +1,76 @@
1
+ import { LDLogger } from '../../api';
2
+ import { FDv2Event } from './proto';
3
+ /**
4
+ * Defines object processing between deserialization and payload emission.
5
+ * Can be used to provide object sanitization logic per kind.
6
+ */
7
+ export interface ObjProcessors {
8
+ [kind: string]: (object: any) => any;
9
+ }
10
+ export interface Update {
11
+ kind: string;
12
+ key: string;
13
+ version: number;
14
+ object?: any;
15
+ deleted?: boolean;
16
+ }
17
+ export type PayloadType = 'full' | 'partial' | 'none';
18
+ /**
19
+ * A collection of updates from the FDv2 services.
20
+ *
21
+ * - `full`: the updates represent the complete state and replace everything.
22
+ * - `partial`: the updates are incremental changes to apply.
23
+ * - `none`: no changes are needed; the SDK is up-to-date.
24
+ */
25
+ export interface Payload {
26
+ id: string;
27
+ version: number;
28
+ state?: string;
29
+ type: PayloadType;
30
+ updates: Update[];
31
+ }
32
+ export type PayloadListener = (payload: Payload) => void;
33
+ /**
34
+ * - `inactive`: No server intent has been expressed (initial state).
35
+ * - `changes`: Currently receiving incremental changes.
36
+ * - `full`: Currently receiving a full transfer.
37
+ */
38
+ export type ProtocolState = 'inactive' | 'changes' | 'full';
39
+ export type ProtocolErrorKind = 'UNKNOWN_EVENT' | 'MISSING_PAYLOAD' | 'PROTOCOL_ERROR';
40
+ /**
41
+ * - `none`: No special action should be taken.
42
+ * - `payload`: A changeset should be applied.
43
+ * - `error`: An internal protocol error was encountered.
44
+ * - `goodbye`: The server intends to disconnect.
45
+ * - `serverError`: A server-side application error was encountered.
46
+ */
47
+ export type ProtocolAction = {
48
+ type: 'none';
49
+ } | {
50
+ type: 'payload';
51
+ payload: Payload;
52
+ } | {
53
+ type: 'error';
54
+ kind: ProtocolErrorKind;
55
+ message: string;
56
+ } | {
57
+ type: 'goodbye';
58
+ reason: string;
59
+ } | {
60
+ type: 'serverError';
61
+ id?: string;
62
+ reason: string;
63
+ };
64
+ /**
65
+ * Pure FDv2 protocol state machine. Processes a single event at a time and
66
+ * returns an action describing what the caller should do. Contains no I/O
67
+ * or callbacks.
68
+ */
69
+ export interface ProtocolHandler {
70
+ readonly state: ProtocolState;
71
+ processEvent(event: FDv2Event): ProtocolAction;
72
+ /** Resets the handler to inactive. Should be called when a connection is reset. */
73
+ reset(): void;
74
+ }
75
+ export declare function createProtocolHandler(objProcessors: ObjProcessors, logger?: LDLogger): ProtocolHandler;
76
+ //# sourceMappingURL=protocolHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocolHandler.d.ts","sourceRoot":"","sources":["../../../src/internal/fdv2/protocolHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAEL,SAAS,EAKV,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC;CACtC;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAEzD;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5D,MAAM,MAAM,iBAAiB,GAAG,eAAe,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAEvF;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAIzD;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,cAAc,CAAC;IAC/C,mFAAmF;IACnF,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,qBAAqB,CACnC,aAAa,EAAE,aAAa,EAC5B,MAAM,CAAC,EAAE,QAAQ,GAChB,eAAe,CAyMjB"}
@@ -3016,135 +3016,200 @@ function fdv1PayloadAdaptor(processor) {
3016
3016
  };
3017
3017
  }
3018
3018
 
3019
- /**
3020
- * A FDv2 PayloadProcessor can be used to parse payloads from a stream of FDv2 events. It will send payloads
3021
- * to the PayloadListeners as the payloads are received. Invalid series of events may be dropped silently,
3022
- * but the payload processor will continue to operate.
3023
- */
3024
- class PayloadProcessor {
3025
- /**
3026
- * Creates a PayloadProcessor
3027
- *
3028
- * @param _objProcessors defines object processors for each object kind.
3029
- * @param _errorHandler that will be called with parsing errors as they are encountered
3030
- * @param _logger for logging
3031
- */
3032
- constructor(_objProcessors, _errorHandler, _logger) {
3033
- this._objProcessors = _objProcessors;
3034
- this._errorHandler = _errorHandler;
3035
- this._logger = _logger;
3036
- this._listeners = [];
3037
- this._tempId = undefined;
3038
- this._tempBasis = false;
3039
- this._tempUpdates = [];
3040
- this._processServerIntent = (data) => {
3041
- // clear state in prep for handling data
3042
- this._resetAll();
3043
- // if there's no payloads, return
3044
- if (!data.payloads.length) {
3045
- return;
3046
- }
3047
- // at the time of writing this, it was agreed upon that SDKs could assume exactly 1 element in this list. In the future, a negotiation of protocol version will be required to remove this assumption.
3048
- const payload = data.payloads[0];
3049
- switch (payload?.intentCode) {
3050
- case 'xfer-full':
3051
- this._tempBasis = true;
3052
- break;
3053
- case 'xfer-changes':
3054
- this._tempBasis = false;
3055
- break;
3056
- case 'none':
3057
- this._tempBasis = false;
3058
- this._processIntentNone(payload);
3059
- break;
3060
- default:
3061
- // unrecognized intent code, return
3062
- this._logger?.warn(`Unable to process intent code '${payload?.intentCode}'.`);
3063
- return;
3064
- }
3065
- this._tempId = payload?.id;
3066
- };
3067
- this._processPutObject = (data) => {
3068
- // if the following properties haven't been provided by now, we should ignore the event
3069
- if (!this._tempId || // server intent hasn't been received yet.
3070
- !data.kind ||
3071
- !data.key ||
3072
- !data.version ||
3073
- !data.object) {
3074
- return;
3075
- }
3076
- const obj = this._processObj(data.kind, data.object);
3077
- if (!obj) {
3078
- this._logger?.warn(`Unable to process object for kind: '${data.kind}'`);
3079
- // ignore unrecognized kinds
3080
- return;
3081
- }
3082
- this._tempUpdates.push({
3083
- kind: data.kind,
3084
- key: data.key,
3085
- version: data.version,
3086
- object: obj,
3087
- // intentionally omit deleted for this put
3088
- });
3089
- };
3090
- this._processDeleteObject = (data) => {
3091
- // if the following properties haven't been provided by now, we should ignore the event
3092
- if (!this._tempId || !data.kind || !data.key || !data.version) {
3093
- return;
3094
- }
3095
- this._tempUpdates.push({
3096
- kind: data.kind,
3097
- key: data.key,
3098
- version: data.version,
3099
- // intentionally omit object for this delete
3100
- deleted: true,
3101
- });
3102
- };
3103
- this._processIntentNone = (intent) => {
3104
- // if the following properties aren't present ignore the event
3105
- if (!intent.id || !intent.target) {
3106
- return;
3107
- }
3108
- const payload = {
3019
+ const ACTION_NONE = { type: 'none' };
3020
+ function createProtocolHandler(objProcessors, logger) {
3021
+ let protocolState = 'inactive';
3022
+ let tempId;
3023
+ let tempType = 'partial';
3024
+ let tempUpdates = [];
3025
+ function processObj(kind, jsonObj) {
3026
+ return objProcessors[kind]?.(jsonObj);
3027
+ }
3028
+ function resetAll() {
3029
+ protocolState = 'inactive';
3030
+ tempId = undefined;
3031
+ tempType = 'partial';
3032
+ tempUpdates = [];
3033
+ }
3034
+ function resetAfterEmission() {
3035
+ protocolState = 'changes';
3036
+ tempType = 'partial';
3037
+ tempUpdates = [];
3038
+ }
3039
+ function resetAfterError() {
3040
+ tempUpdates = [];
3041
+ }
3042
+ function processIntentNone(intent) {
3043
+ if (!intent.id || !intent.target) {
3044
+ return ACTION_NONE;
3045
+ }
3046
+ return {
3047
+ type: 'payload',
3048
+ payload: {
3109
3049
  id: intent.id,
3110
3050
  version: intent.target,
3111
- basis: false,
3112
- updates: [], // payload with no updates to hide the intent none concept from the consumer
3113
- // note: state is absent here as that only appears in payload transferred events
3114
- };
3115
- this._listeners.forEach((it) => it(payload));
3116
- this._resetAfterEmission();
3051
+ type: 'none',
3052
+ updates: [],
3053
+ },
3117
3054
  };
3118
- this._processPayloadTransferred = (data) => {
3119
- // if the following properties haven't been provided by now, we should reset
3120
- if (
3121
- // server intent hasn't been received yet.
3122
- !this._tempId ||
3123
- // selector can be an empty string if we are using a file data initilizer
3124
- data.state === null ||
3125
- data.state === undefined ||
3126
- !data.version) {
3127
- this._resetAll(); // a reset is best defensive action since payload transferred terminates a payload
3128
- return;
3129
- }
3130
- const payload = {
3131
- id: this._tempId,
3055
+ }
3056
+ function processServerIntent(data) {
3057
+ if (!data.payloads?.length) {
3058
+ return {
3059
+ type: 'error',
3060
+ kind: 'MISSING_PAYLOAD',
3061
+ message: 'No payload present in server-intent',
3062
+ };
3063
+ }
3064
+ // Per spec 3.4.2: SDK uses only the first payload.
3065
+ const payload = data.payloads[0];
3066
+ switch (payload?.intentCode) {
3067
+ case 'xfer-full':
3068
+ protocolState = 'full';
3069
+ tempUpdates = [];
3070
+ tempType = 'full';
3071
+ tempId = payload.id;
3072
+ return ACTION_NONE;
3073
+ case 'xfer-changes':
3074
+ protocolState = 'changes';
3075
+ tempUpdates = [];
3076
+ tempType = 'partial';
3077
+ tempId = payload.id;
3078
+ return ACTION_NONE;
3079
+ case 'none':
3080
+ protocolState = 'changes';
3081
+ tempUpdates = [];
3082
+ tempType = 'partial';
3083
+ tempId = payload.id;
3084
+ return processIntentNone(payload);
3085
+ default:
3086
+ logger?.warn(`Unable to process intent code '${payload?.intentCode}'.`);
3087
+ return ACTION_NONE;
3088
+ }
3089
+ }
3090
+ function processPutObject(data) {
3091
+ if (protocolState === 'inactive' ||
3092
+ !tempId ||
3093
+ !data.kind ||
3094
+ !data.key ||
3095
+ !data.version ||
3096
+ !data.object) {
3097
+ return ACTION_NONE;
3098
+ }
3099
+ const obj = processObj(data.kind, data.object);
3100
+ if (!obj) {
3101
+ logger?.warn(`Unable to process object for kind: '${data.kind}'`);
3102
+ return ACTION_NONE;
3103
+ }
3104
+ tempUpdates.push({
3105
+ kind: data.kind,
3106
+ key: data.key,
3107
+ version: data.version,
3108
+ object: obj,
3109
+ });
3110
+ return ACTION_NONE;
3111
+ }
3112
+ function processDeleteObject(data) {
3113
+ if (protocolState === 'inactive' || !tempId || !data.kind || !data.key || !data.version) {
3114
+ return ACTION_NONE;
3115
+ }
3116
+ tempUpdates.push({
3117
+ kind: data.kind,
3118
+ key: data.key,
3119
+ version: data.version,
3120
+ deleted: true,
3121
+ });
3122
+ return ACTION_NONE;
3123
+ }
3124
+ function processPayloadTransferred(data) {
3125
+ if (protocolState === 'inactive') {
3126
+ return {
3127
+ type: 'error',
3128
+ kind: 'PROTOCOL_ERROR',
3129
+ message: 'A payload transferred has been received without an intent having been established.',
3130
+ };
3131
+ }
3132
+ if (!tempId || data.state === null || data.state === undefined || !data.version) {
3133
+ resetAll();
3134
+ return ACTION_NONE;
3135
+ }
3136
+ const result = {
3137
+ type: 'payload',
3138
+ payload: {
3139
+ id: tempId,
3132
3140
  version: data.version,
3133
3141
  state: data.state,
3134
- basis: this._tempBasis,
3135
- updates: this._tempUpdates,
3136
- };
3137
- this._listeners.forEach((it) => it(payload));
3138
- this._resetAfterEmission();
3139
- };
3140
- this._processGoodbye = (data) => {
3141
- this._logger?.info(`Goodbye was received from the LaunchDarkly connection with reason: ${data.reason}.`);
3142
- this._resetAll();
3143
- };
3144
- this._processError = (data) => {
3145
- this._logger?.info(`An issue was encountered receiving updates for payload ${this._tempId} with reason: ${data.reason}.`);
3146
- this._resetAfterError();
3142
+ type: tempType,
3143
+ updates: tempUpdates,
3144
+ },
3147
3145
  };
3146
+ resetAfterEmission();
3147
+ return result;
3148
+ }
3149
+ function processGoodbye(data) {
3150
+ logger?.info(`Goodbye was received from the LaunchDarkly connection with reason: ${data.reason}.`);
3151
+ resetAll();
3152
+ return { type: 'goodbye', reason: data.reason };
3153
+ }
3154
+ function processError(data) {
3155
+ logger?.info(`An issue was encountered receiving updates for payload ${tempId} with reason: ${data.reason}.`);
3156
+ resetAfterError();
3157
+ return { type: 'serverError', id: data.payload_id, reason: data.reason };
3158
+ }
3159
+ return {
3160
+ get state() {
3161
+ return protocolState;
3162
+ },
3163
+ processEvent(event) {
3164
+ switch (event.event) {
3165
+ case 'server-intent':
3166
+ return processServerIntent(event.data);
3167
+ case 'put-object':
3168
+ return processPutObject(event.data);
3169
+ case 'delete-object':
3170
+ return processDeleteObject(event.data);
3171
+ case 'payload-transferred':
3172
+ return processPayloadTransferred(event.data);
3173
+ case 'goodbye':
3174
+ return processGoodbye(event.data);
3175
+ case 'error':
3176
+ return processError(event.data);
3177
+ case 'heart-beat':
3178
+ return ACTION_NONE;
3179
+ default:
3180
+ return {
3181
+ type: 'error',
3182
+ kind: 'UNKNOWN_EVENT',
3183
+ message: `Received an unknown event of type '${event.event}'`,
3184
+ };
3185
+ }
3186
+ },
3187
+ reset() {
3188
+ resetAll();
3189
+ },
3190
+ };
3191
+ }
3192
+
3193
+ /**
3194
+ * Errors that indicate a problem with the data or protocol flow and should
3195
+ * be reported to the error handler. Informational errors like UNKNOWN_EVENT
3196
+ * are intentionally excluded to preserve forward compatibility — older SDKs
3197
+ * should silently ignore new event types added to the protocol.
3198
+ */
3199
+ function isActionableError(kind) {
3200
+ return kind === 'MISSING_PAYLOAD' || kind === 'PROTOCOL_ERROR';
3201
+ }
3202
+ /**
3203
+ * Parses payloads from a stream of FDv2 events by delegating to a protocol handler.
3204
+ * Sends completed payloads to registered listeners.
3205
+ * Invalid event sequences may be dropped silently, but the processor will continue to operate.
3206
+ */
3207
+ class PayloadProcessor {
3208
+ constructor(objProcessors, _errorHandler, _logger) {
3209
+ this._errorHandler = _errorHandler;
3210
+ this._logger = _logger;
3211
+ this._listeners = [];
3212
+ this._handler = createProtocolHandler(objProcessors, _logger);
3148
3213
  }
3149
3214
  addPayloadListener(listener) {
3150
3215
  this._listeners.push(listener);
@@ -3155,56 +3220,24 @@ class PayloadProcessor {
3155
3220
  this._listeners.splice(index, 1);
3156
3221
  }
3157
3222
  }
3158
- /**
3159
- * Gives the {@link PayloadProcessor} a series of events that it will statefully, incrementally process.
3160
- * This may lead to listeners being invoked as necessary.
3161
- * @param events to be processed (can be a single element)
3162
- */
3163
3223
  processEvents(events) {
3164
3224
  events.forEach((event) => {
3165
- switch (event.event) {
3166
- case 'server-intent': {
3167
- this._processServerIntent(event.data);
3168
- break;
3169
- }
3170
- case 'put-object': {
3171
- this._processPutObject(event.data);
3225
+ const action = this._handler.processEvent(event);
3226
+ switch (action.type) {
3227
+ case 'payload':
3228
+ this._listeners.forEach((it) => it(action.payload));
3172
3229
  break;
3173
- }
3174
- case 'delete-object': {
3175
- this._processDeleteObject(event.data);
3176
- break;
3177
- }
3178
- case 'payload-transferred': {
3179
- this._processPayloadTransferred(event.data);
3180
- break;
3181
- }
3182
- case 'goodbye': {
3183
- this._processGoodbye(event.data);
3184
- break;
3185
- }
3186
- case 'error': {
3187
- this._processError(event.data);
3230
+ case 'error':
3231
+ if (isActionableError(action.kind)) {
3232
+ this._errorHandler?.(DataSourceErrorKind.InvalidData, action.message);
3233
+ }
3234
+ else {
3235
+ this._logger?.warn(action.message);
3236
+ }
3188
3237
  break;
3189
- }
3190
3238
  }
3191
3239
  });
3192
3240
  }
3193
- _processObj(kind, jsonObj) {
3194
- return this._objProcessors[kind]?.(jsonObj);
3195
- }
3196
- _resetAfterEmission() {
3197
- this._tempBasis = false;
3198
- this._tempUpdates = [];
3199
- }
3200
- _resetAfterError() {
3201
- this._tempUpdates = [];
3202
- }
3203
- _resetAll() {
3204
- this._tempId = undefined;
3205
- this._tempBasis = false;
3206
- this._tempUpdates = [];
3207
- }
3208
3241
  }
3209
3242
 
3210
3243
  /**
@@ -3333,6 +3366,7 @@ var index = /*#__PURE__*/Object.freeze({
3333
3366
  PayloadProcessor: PayloadProcessor,
3334
3367
  PayloadStreamReader: PayloadStreamReader,
3335
3368
  canonicalize: canonicalize,
3369
+ createProtocolHandler: createProtocolHandler,
3336
3370
  initMetadataFromHeaders: initMetadataFromHeaders,
3337
3371
  isLegacyUser: isLegacyUser,
3338
3372
  isMultiKind: isMultiKind,