@openfeature/flagd-provider 0.9.0 → 0.10.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/index.esm.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { GeneralError, FlagNotFoundError, TypeMismatchError, ParseError, StandardResolutionReasons, ProviderStatus, OpenFeatureEventEmitter, ProviderEvents } from '@openfeature/server-sdk';
2
2
  import { makeGenericClientConstructor, status, credentials } from '@grpc/grpc-js';
3
+ import { ConnectivityState } from '@grpc/grpc-js/build/src/connectivity-state';
3
4
  import { LRUCache } from 'lru-cache';
4
5
  import { promisify } from 'util';
6
+ import { FlagdCore } from '@openfeature/flagd-core';
5
7
 
6
- const BASE_EVENT_STREAM_RETRY_BACKOFF_MS = 1000;
7
- const DEFAULT_MAX_EVENT_STREAM_RETRIES = 5;
8
8
  const EVENT_CONFIGURATION_CHANGE = 'configuration_change';
9
9
  const EVENT_PROVIDER_READY = 'provider_ready';
10
10
  const DEFAULT_MAX_CACHE_SIZE = 1000;
@@ -13,9 +13,10 @@ const DEFAULT_CONFIG = {
13
13
  host: 'localhost',
14
14
  port: 8013,
15
15
  tls: false,
16
+ resolverType: 'rpc',
17
+ selector: '',
16
18
  cache: 'lru',
17
19
  maxCacheSize: DEFAULT_MAX_CACHE_SIZE,
18
- maxEventStreamRetries: DEFAULT_MAX_EVENT_STREAM_RETRIES,
19
20
  };
20
21
  var ENV_VAR;
21
22
  (function (ENV_VAR) {
@@ -25,11 +26,12 @@ var ENV_VAR;
25
26
  ENV_VAR["FLAGD_SOCKET_PATH"] = "FLAGD_SOCKET_PATH";
26
27
  ENV_VAR["FLAGD_CACHE"] = "FLAGD_CACHE";
27
28
  ENV_VAR["FLAGD_MAX_CACHE_SIZE"] = "FLAGD_MAX_CACHE_SIZE";
28
- ENV_VAR["FLAGD_MAX_EVENT_STREAM_RETRIES"] = "FLAGD_MAX_EVENT_STREAM_RETRIES";
29
+ ENV_VAR["FLAGD_SOURCE_SELECTOR"] = "FLAGD_SOURCE_SELECTOR";
30
+ ENV_VAR["FLAGD_RESOLVER"] = "FLAGD_RESOLVER";
29
31
  })(ENV_VAR || (ENV_VAR = {}));
30
32
  const getEnvVarConfig = () => {
31
33
  var _a;
32
- return (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (process.env[ENV_VAR.FLAGD_HOST] && {
34
+ return (Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (process.env[ENV_VAR.FLAGD_HOST] && {
33
35
  host: process.env[ENV_VAR.FLAGD_HOST],
34
36
  })), (Number(process.env[ENV_VAR.FLAGD_PORT]) && {
35
37
  port: Number(process.env[ENV_VAR.FLAGD_PORT]),
@@ -41,8 +43,10 @@ const getEnvVarConfig = () => {
41
43
  cache: process.env[ENV_VAR.FLAGD_CACHE],
42
44
  })), (process.env[ENV_VAR.FLAGD_MAX_CACHE_SIZE] && {
43
45
  maxCacheSize: Number(process.env[ENV_VAR.FLAGD_MAX_CACHE_SIZE]),
44
- })), (process.env[ENV_VAR.FLAGD_MAX_EVENT_STREAM_RETRIES] && {
45
- maxEventStreamRetries: Number(process.env[ENV_VAR.FLAGD_MAX_EVENT_STREAM_RETRIES]),
46
+ })), (process.env[ENV_VAR.FLAGD_SOURCE_SELECTOR] && {
47
+ selector: process.env[ENV_VAR.FLAGD_SOURCE_SELECTOR],
48
+ })), ((process.env[ENV_VAR.FLAGD_RESOLVER] === 'rpc' || process.env[ENV_VAR.FLAGD_RESOLVER] === 'in-process') && {
49
+ resolverType: process.env[ENV_VAR.FLAGD_RESOLVER],
46
50
  })));
47
51
  };
48
52
  function getConfig(options = {}) {
@@ -4074,7 +4078,7 @@ var minimal = indexMinimal;
4074
4078
  * `NullValue` is a singleton enumeration to represent the null value for the
4075
4079
  * `Value` type union.
4076
4080
  *
4077
- * The JSON representation for `NullValue` is JSON `null`.
4081
+ * The JSON representation for `NullValue` is JSON `null`.
4078
4082
  */
4079
4083
  var NullValue;
4080
4084
  (function (NullValue) {
@@ -4235,7 +4239,7 @@ const Struct_FieldsEntry = {
4235
4239
  return message;
4236
4240
  },
4237
4241
  fromJSON(object) {
4238
- return { key: isSet$1(object.key) ? String(object.key) : "", value: isSet$1(object === null || object === void 0 ? void 0 : object.value) ? object.value : undefined };
4242
+ return { key: isSet$2(object.key) ? String(object.key) : "", value: isSet$2(object === null || object === void 0 ? void 0 : object.value) ? object.value : undefined };
4239
4243
  },
4240
4244
  toJSON(message) {
4241
4245
  const obj = {};
@@ -4343,10 +4347,10 @@ const Value = {
4343
4347
  },
4344
4348
  fromJSON(object) {
4345
4349
  return {
4346
- nullValue: isSet$1(object.nullValue) ? nullValueFromJSON(object.nullValue) : undefined,
4347
- numberValue: isSet$1(object.numberValue) ? Number(object.numberValue) : undefined,
4348
- stringValue: isSet$1(object.stringValue) ? String(object.stringValue) : undefined,
4349
- boolValue: isSet$1(object.boolValue) ? Boolean(object.boolValue) : undefined,
4350
+ nullValue: isSet$2(object.nullValue) ? nullValueFromJSON(object.nullValue) : undefined,
4351
+ numberValue: isSet$2(object.numberValue) ? Number(object.numberValue) : undefined,
4352
+ stringValue: isSet$2(object.stringValue) ? String(object.stringValue) : undefined,
4353
+ boolValue: isSet$2(object.boolValue) ? Boolean(object.boolValue) : undefined,
4350
4354
  structValue: isObject$1(object.structValue) ? object.structValue : undefined,
4351
4355
  listValue: Array.isArray(object.listValue) ? [...object.listValue] : undefined,
4352
4356
  };
@@ -4502,7 +4506,7 @@ const ListValue = {
4502
4506
  function isObject$1(value) {
4503
4507
  return typeof value === "object" && value !== null;
4504
4508
  }
4505
- function isSet$1(value) {
4509
+ function isSet$2(value) {
4506
4510
  return value !== null && value !== undefined;
4507
4511
  }
4508
4512
 
@@ -4672,8 +4676,8 @@ const ResolveAllResponse_FlagsEntry = {
4672
4676
  },
4673
4677
  fromJSON(object) {
4674
4678
  return {
4675
- key: isSet(object.key) ? String(object.key) : "",
4676
- value: isSet(object.value) ? AnyFlag.fromJSON(object.value) : undefined,
4679
+ key: isSet$1(object.key) ? String(object.key) : "",
4680
+ value: isSet$1(object.value) ? AnyFlag.fromJSON(object.value) : undefined,
4677
4681
  };
4678
4682
  },
4679
4683
  toJSON(message) {
@@ -4784,11 +4788,11 @@ const AnyFlag = {
4784
4788
  },
4785
4789
  fromJSON(object) {
4786
4790
  return {
4787
- reason: isSet(object.reason) ? String(object.reason) : "",
4788
- variant: isSet(object.variant) ? String(object.variant) : "",
4789
- boolValue: isSet(object.boolValue) ? Boolean(object.boolValue) : undefined,
4790
- stringValue: isSet(object.stringValue) ? String(object.stringValue) : undefined,
4791
- doubleValue: isSet(object.doubleValue) ? Number(object.doubleValue) : undefined,
4791
+ reason: isSet$1(object.reason) ? String(object.reason) : "",
4792
+ variant: isSet$1(object.variant) ? String(object.variant) : "",
4793
+ boolValue: isSet$1(object.boolValue) ? Boolean(object.boolValue) : undefined,
4794
+ stringValue: isSet$1(object.stringValue) ? String(object.stringValue) : undefined,
4795
+ doubleValue: isSet$1(object.doubleValue) ? Number(object.doubleValue) : undefined,
4792
4796
  objectValue: isObject(object.objectValue) ? object.objectValue : undefined,
4793
4797
  };
4794
4798
  },
@@ -4871,7 +4875,7 @@ const ResolveBooleanRequest = {
4871
4875
  },
4872
4876
  fromJSON(object) {
4873
4877
  return {
4874
- flagKey: isSet(object.flagKey) ? String(object.flagKey) : "",
4878
+ flagKey: isSet$1(object.flagKey) ? String(object.flagKey) : "",
4875
4879
  context: isObject(object.context) ? object.context : undefined,
4876
4880
  };
4877
4881
  },
@@ -4956,9 +4960,9 @@ const ResolveBooleanResponse = {
4956
4960
  },
4957
4961
  fromJSON(object) {
4958
4962
  return {
4959
- value: isSet(object.value) ? Boolean(object.value) : false,
4960
- reason: isSet(object.reason) ? String(object.reason) : "",
4961
- variant: isSet(object.variant) ? String(object.variant) : "",
4963
+ value: isSet$1(object.value) ? Boolean(object.value) : false,
4964
+ reason: isSet$1(object.reason) ? String(object.reason) : "",
4965
+ variant: isSet$1(object.variant) ? String(object.variant) : "",
4962
4966
  metadata: isObject(object.metadata) ? object.metadata : undefined,
4963
4967
  };
4964
4968
  },
@@ -5033,7 +5037,7 @@ const ResolveStringRequest = {
5033
5037
  },
5034
5038
  fromJSON(object) {
5035
5039
  return {
5036
- flagKey: isSet(object.flagKey) ? String(object.flagKey) : "",
5040
+ flagKey: isSet$1(object.flagKey) ? String(object.flagKey) : "",
5037
5041
  context: isObject(object.context) ? object.context : undefined,
5038
5042
  };
5039
5043
  },
@@ -5118,9 +5122,9 @@ const ResolveStringResponse = {
5118
5122
  },
5119
5123
  fromJSON(object) {
5120
5124
  return {
5121
- value: isSet(object.value) ? String(object.value) : "",
5122
- reason: isSet(object.reason) ? String(object.reason) : "",
5123
- variant: isSet(object.variant) ? String(object.variant) : "",
5125
+ value: isSet$1(object.value) ? String(object.value) : "",
5126
+ reason: isSet$1(object.reason) ? String(object.reason) : "",
5127
+ variant: isSet$1(object.variant) ? String(object.variant) : "",
5124
5128
  metadata: isObject(object.metadata) ? object.metadata : undefined,
5125
5129
  };
5126
5130
  },
@@ -5195,7 +5199,7 @@ const ResolveFloatRequest = {
5195
5199
  },
5196
5200
  fromJSON(object) {
5197
5201
  return {
5198
- flagKey: isSet(object.flagKey) ? String(object.flagKey) : "",
5202
+ flagKey: isSet$1(object.flagKey) ? String(object.flagKey) : "",
5199
5203
  context: isObject(object.context) ? object.context : undefined,
5200
5204
  };
5201
5205
  },
@@ -5280,9 +5284,9 @@ const ResolveFloatResponse = {
5280
5284
  },
5281
5285
  fromJSON(object) {
5282
5286
  return {
5283
- value: isSet(object.value) ? Number(object.value) : 0,
5284
- reason: isSet(object.reason) ? String(object.reason) : "",
5285
- variant: isSet(object.variant) ? String(object.variant) : "",
5287
+ value: isSet$1(object.value) ? Number(object.value) : 0,
5288
+ reason: isSet$1(object.reason) ? String(object.reason) : "",
5289
+ variant: isSet$1(object.variant) ? String(object.variant) : "",
5286
5290
  metadata: isObject(object.metadata) ? object.metadata : undefined,
5287
5291
  };
5288
5292
  },
@@ -5357,7 +5361,7 @@ const ResolveIntRequest = {
5357
5361
  },
5358
5362
  fromJSON(object) {
5359
5363
  return {
5360
- flagKey: isSet(object.flagKey) ? String(object.flagKey) : "",
5364
+ flagKey: isSet$1(object.flagKey) ? String(object.flagKey) : "",
5361
5365
  context: isObject(object.context) ? object.context : undefined,
5362
5366
  };
5363
5367
  },
@@ -5442,9 +5446,9 @@ const ResolveIntResponse = {
5442
5446
  },
5443
5447
  fromJSON(object) {
5444
5448
  return {
5445
- value: isSet(object.value) ? String(object.value) : "0",
5446
- reason: isSet(object.reason) ? String(object.reason) : "",
5447
- variant: isSet(object.variant) ? String(object.variant) : "",
5449
+ value: isSet$1(object.value) ? String(object.value) : "0",
5450
+ reason: isSet$1(object.reason) ? String(object.reason) : "",
5451
+ variant: isSet$1(object.variant) ? String(object.variant) : "",
5448
5452
  metadata: isObject(object.metadata) ? object.metadata : undefined,
5449
5453
  };
5450
5454
  },
@@ -5519,7 +5523,7 @@ const ResolveObjectRequest = {
5519
5523
  },
5520
5524
  fromJSON(object) {
5521
5525
  return {
5522
- flagKey: isSet(object.flagKey) ? String(object.flagKey) : "",
5526
+ flagKey: isSet$1(object.flagKey) ? String(object.flagKey) : "",
5523
5527
  context: isObject(object.context) ? object.context : undefined,
5524
5528
  };
5525
5529
  },
@@ -5605,8 +5609,8 @@ const ResolveObjectResponse = {
5605
5609
  fromJSON(object) {
5606
5610
  return {
5607
5611
  value: isObject(object.value) ? object.value : undefined,
5608
- reason: isSet(object.reason) ? String(object.reason) : "",
5609
- variant: isSet(object.variant) ? String(object.variant) : "",
5612
+ reason: isSet$1(object.reason) ? String(object.reason) : "",
5613
+ variant: isSet$1(object.variant) ? String(object.variant) : "",
5610
5614
  metadata: isObject(object.metadata) ? object.metadata : undefined,
5611
5615
  };
5612
5616
  },
@@ -5681,7 +5685,7 @@ const EventStreamResponse = {
5681
5685
  },
5682
5686
  fromJSON(object) {
5683
5687
  return {
5684
- type: isSet(object.type) ? String(object.type) : "",
5688
+ type: isSet$1(object.type) ? String(object.type) : "",
5685
5689
  data: isObject(object.data) ? object.data : undefined,
5686
5690
  };
5687
5691
  },
@@ -5817,23 +5821,19 @@ if (minimal.util.Long !== long) {
5817
5821
  function isObject(value) {
5818
5822
  return typeof value === "object" && value !== null;
5819
5823
  }
5820
- function isSet(value) {
5824
+ function isSet$1(value) {
5821
5825
  return value !== null && value !== undefined;
5822
5826
  }
5823
5827
 
5824
5828
  class GRPCService {
5825
5829
  get _cacheActive() {
5826
5830
  // the cache is "active" (able to be used) if the config enabled it, AND the gRPC stream is live
5827
- return this._cacheEnabled && this._streamAlive;
5831
+ return this._cacheEnabled && this._client.getChannel().getConnectivityState(false) === ConnectivityState.READY;
5828
5832
  }
5829
5833
  constructor(config, client, logger) {
5830
- var _a;
5831
5834
  this.logger = logger;
5832
5835
  this._cacheEnabled = false;
5833
- this._streamAlive = false;
5834
- this._streamConnectAttempt = 0;
5835
- this._stream = undefined;
5836
- this._streamConnectBackoff = BASE_EVENT_STREAM_RETRY_BACKOFF_MS;
5836
+ this._eventStream = undefined;
5837
5837
  this.onRejected = (err) => {
5838
5838
  // map the errors
5839
5839
  switch (err === null || err === void 0 ? void 0 : err.code) {
@@ -5850,7 +5850,6 @@ class GRPCService {
5850
5850
  }
5851
5851
  };
5852
5852
  const { host, port, tls, socketPath } = config;
5853
- this._maxEventStreamRetries = (_a = config.maxEventStreamRetries) !== null && _a !== void 0 ? _a : DEFAULT_MAX_EVENT_STREAM_RETRIES;
5854
5853
  this._client = client
5855
5854
  ? client
5856
5855
  : new ServiceClient(socketPath ? `unix://${socketPath}` : `${host}:${port}`, tls ? credentials.createSsl() : credentials.createInsecure());
@@ -5859,73 +5858,62 @@ class GRPCService {
5859
5858
  this._cache = new LRUCache({ maxSize: config.maxCacheSize || DEFAULT_MAX_CACHE_SIZE, sizeCalculation: () => 1 });
5860
5859
  }
5861
5860
  }
5862
- connect(connectCallback, changedCallback, disconnectCallback) {
5863
- return this.connectStream(connectCallback, changedCallback, disconnectCallback);
5861
+ connect(reconnectCallback, changedCallback, disconnectCallback) {
5862
+ return new Promise((resolve, reject) => this.listen(reconnectCallback, changedCallback, disconnectCallback, resolve, reject));
5864
5863
  }
5865
5864
  disconnect() {
5866
5865
  var _a;
5867
5866
  return __awaiter(this, void 0, void 0, function* () {
5868
5867
  // cancel the stream and close the connection
5869
- (_a = this._stream) === null || _a === void 0 ? void 0 : _a.cancel();
5868
+ (_a = this._eventStream) === null || _a === void 0 ? void 0 : _a.cancel();
5870
5869
  this._client.close();
5871
5870
  });
5872
5871
  }
5873
- resolveBoolean(flagKey, context, logger) {
5872
+ resolveBoolean(flagKey, _, context, logger) {
5874
5873
  return __awaiter(this, void 0, void 0, function* () {
5875
5874
  return this.resolve(this._client.resolveBoolean, flagKey, context, logger);
5876
5875
  });
5877
5876
  }
5878
- resolveString(flagKey, context, logger) {
5877
+ resolveString(flagKey, _, context, logger) {
5879
5878
  return __awaiter(this, void 0, void 0, function* () {
5880
5879
  return this.resolve(this._client.resolveString, flagKey, context, logger);
5881
5880
  });
5882
5881
  }
5883
- resolveNumber(flagKey, context, logger) {
5882
+ resolveNumber(flagKey, _, context, logger) {
5884
5883
  return __awaiter(this, void 0, void 0, function* () {
5885
5884
  return this.resolve(this._client.resolveFloat, flagKey, context, logger);
5886
5885
  });
5887
5886
  }
5888
- resolveObject(flagKey, context, logger) {
5887
+ resolveObject(flagKey, _, context, logger) {
5889
5888
  return __awaiter(this, void 0, void 0, function* () {
5890
5889
  return this.resolve(this._client.resolveObject, flagKey, context, logger);
5891
5890
  });
5892
5891
  }
5893
- connectStream(connectCallback, changedCallback, disconnectCallback) {
5894
- return new Promise((resolve, reject) => {
5892
+ listen(reconnectCallback, changedCallback, disconnectCallback, resolveConnect, rejectConnect) {
5893
+ var _a;
5894
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`${FlagdProvider.name}: connecting stream...`);
5895
+ const stream = this._client.eventStream({}, {});
5896
+ stream.on('error', (err) => {
5897
+ rejectConnect === null || rejectConnect === void 0 ? void 0 : rejectConnect(err);
5898
+ this.handleError(reconnectCallback, changedCallback, disconnectCallback);
5899
+ });
5900
+ stream.on('data', (message) => {
5895
5901
  var _a;
5896
- (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`${FlagdProvider.name}: connecting stream, attempt ${this._streamConnectAttempt}...`);
5897
- const stream = this._client.eventStream({}, {});
5898
- stream.on('error', (err) => {
5899
- var _a;
5900
- if ((err === null || err === void 0 ? void 0 : err.code) === status.CANCELLED) {
5901
- (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`${FlagdProvider.name}: stream cancelled, will not be re-established`);
5902
+ if (message.type === EVENT_PROVIDER_READY) {
5903
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`${FlagdProvider.name}: streaming connection established with flagd`);
5904
+ // if resolveConnect is undefined, this is a reconnection; we only want to fire the reconnect callback in that case
5905
+ if (resolveConnect) {
5906
+ resolveConnect();
5902
5907
  }
5903
5908
  else {
5904
- this.handleError(reject, connectCallback, changedCallback, disconnectCallback);
5905
- }
5906
- });
5907
- stream.on('close', () => {
5908
- this.handleClose();
5909
- });
5910
- stream.on('data', (message) => {
5911
- if (message.type === EVENT_PROVIDER_READY) {
5912
- this.handleProviderReady(resolve, connectCallback);
5913
- }
5914
- else if (message.type === EVENT_CONFIGURATION_CHANGE) {
5915
- this.handleFlagsChanged(message, changedCallback);
5909
+ reconnectCallback();
5916
5910
  }
5917
- });
5918
- this._stream = stream;
5911
+ }
5912
+ else if (message.type === EVENT_CONFIGURATION_CHANGE) {
5913
+ this.handleFlagsChanged(message, changedCallback);
5914
+ }
5919
5915
  });
5920
- }
5921
- handleProviderReady(resolve, connectCallback) {
5922
- var _a;
5923
- connectCallback();
5924
- (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`${FlagdProvider.name}: streaming connection established with flagd`);
5925
- this._streamAlive = true;
5926
- this._streamConnectAttempt = 0;
5927
- this._streamConnectBackoff = BASE_EVENT_STREAM_RETRY_BACKOFF_MS;
5928
- resolve();
5916
+ this._eventStream = stream;
5929
5917
  }
5930
5918
  handleFlagsChanged(message, changedCallback) {
5931
5919
  var _a;
@@ -5946,34 +5934,18 @@ class GRPCService {
5946
5934
  }
5947
5935
  }
5948
5936
  }
5949
- handleError(reject, connectCallback, changedCallback, disconnectCallback) {
5950
- var _a, _b, _c;
5951
- disconnectCallback();
5952
- (_a = this.logger) === null || _a === void 0 ? void 0 : _a.error(`${FlagdProvider.name}: streaming connection error, will attempt reconnect...`);
5953
- (_b = this._cache) === null || _b === void 0 ? void 0 : _b.clear();
5954
- this._streamAlive = false;
5955
- // if we haven't reached max attempt, reconnect after backoff
5956
- if (this._streamConnectAttempt <= this._maxEventStreamRetries) {
5957
- this._streamConnectAttempt++;
5958
- setTimeout(() => {
5959
- this._streamConnectBackoff = this._streamConnectBackoff * 2;
5960
- this.connectStream(connectCallback, changedCallback, disconnectCallback).catch(() => {
5961
- // empty catch to avoid unhandled promise rejection
5962
- });
5963
- }, this._streamConnectBackoff);
5964
- }
5965
- else {
5966
- // after max attempts, give up
5967
- const errorMessage = `${FlagdProvider.name}: max stream connect attempts (${this._maxEventStreamRetries} reached)`;
5968
- (_c = this.logger) === null || _c === void 0 ? void 0 : _c.error(errorMessage);
5969
- reject(new Error(errorMessage));
5970
- }
5937
+ reconnect(reconnectCallback, changedCallback, disconnectCallback) {
5938
+ const channel = this._client.getChannel();
5939
+ channel.watchConnectivityState(channel.getConnectivityState(true), Infinity, () => {
5940
+ this.listen(reconnectCallback, changedCallback, disconnectCallback);
5941
+ });
5971
5942
  }
5972
- handleClose() {
5943
+ handleError(reconnectCallback, changedCallback, disconnectCallback) {
5973
5944
  var _a, _b;
5974
- (_a = this.logger) === null || _a === void 0 ? void 0 : _a.info(`${FlagdProvider.name}: streaming connection closed`);
5945
+ disconnectCallback();
5946
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.error(`${FlagdProvider.name}: streaming connection error, will attempt reconnect...`);
5975
5947
  (_b = this._cache) === null || _b === void 0 ? void 0 : _b.clear();
5976
- this._streamAlive = false;
5948
+ this.reconnect(reconnectCallback, changedCallback, disconnectCallback);
5977
5949
  }
5978
5950
  resolve(promise, flagKey, context, logger) {
5979
5951
  var _a, _b;
@@ -6005,6 +5977,444 @@ class GRPCService {
6005
5977
  }
6006
5978
  }
6007
5979
 
5980
+ /* eslint-disable */
5981
+ /**
5982
+ * Flag definition sync API
5983
+ *
5984
+ * This proto defines a simple API to synchronize a feature flag definition.
5985
+ * It supports establishing a stream for getting notifications about changes in a flag definition.
5986
+ */
5987
+ /**
5988
+ * SyncState conveys the state of the payload. These states are related to flagd isync.go type definitions but
5989
+ * contains extras to optimize grpc use case. Refer - https://github.com/open-feature/flagd/blob/main/pkg/sync/isync.go
5990
+ */
5991
+ var SyncState;
5992
+ (function (SyncState) {
5993
+ /** SYNC_STATE_UNSPECIFIED - Value is ignored by the listening flagd */
5994
+ SyncState[SyncState["SYNC_STATE_UNSPECIFIED"] = 0] = "SYNC_STATE_UNSPECIFIED";
5995
+ /**
5996
+ * SYNC_STATE_ALL - All the flags matching the request. This is the default response and other states can be ignored
5997
+ * by the implementation. Flagd internally replaces all existing flags for this response state.
5998
+ */
5999
+ SyncState[SyncState["SYNC_STATE_ALL"] = 1] = "SYNC_STATE_ALL";
6000
+ /** SYNC_STATE_ADD - Convey an addition of a flag. Flagd internally handles this by combining new flags with existing ones */
6001
+ SyncState[SyncState["SYNC_STATE_ADD"] = 2] = "SYNC_STATE_ADD";
6002
+ /**
6003
+ * SYNC_STATE_UPDATE - Convey an update of a flag. Flagd internally attempts to update if the updated flag already exist OR if it does not,
6004
+ * it will get added
6005
+ */
6006
+ SyncState[SyncState["SYNC_STATE_UPDATE"] = 3] = "SYNC_STATE_UPDATE";
6007
+ /** SYNC_STATE_DELETE - Convey a deletion of a flag. Flagd internally removes the flag */
6008
+ SyncState[SyncState["SYNC_STATE_DELETE"] = 4] = "SYNC_STATE_DELETE";
6009
+ /** SYNC_STATE_PING - Optional server ping to check client connectivity. Handling is ignored by flagd and is to merely support live check */
6010
+ SyncState[SyncState["SYNC_STATE_PING"] = 5] = "SYNC_STATE_PING";
6011
+ SyncState[SyncState["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
6012
+ })(SyncState || (SyncState = {}));
6013
+ function syncStateFromJSON(object) {
6014
+ switch (object) {
6015
+ case 0:
6016
+ case "SYNC_STATE_UNSPECIFIED":
6017
+ return SyncState.SYNC_STATE_UNSPECIFIED;
6018
+ case 1:
6019
+ case "SYNC_STATE_ALL":
6020
+ return SyncState.SYNC_STATE_ALL;
6021
+ case 2:
6022
+ case "SYNC_STATE_ADD":
6023
+ return SyncState.SYNC_STATE_ADD;
6024
+ case 3:
6025
+ case "SYNC_STATE_UPDATE":
6026
+ return SyncState.SYNC_STATE_UPDATE;
6027
+ case 4:
6028
+ case "SYNC_STATE_DELETE":
6029
+ return SyncState.SYNC_STATE_DELETE;
6030
+ case 5:
6031
+ case "SYNC_STATE_PING":
6032
+ return SyncState.SYNC_STATE_PING;
6033
+ case -1:
6034
+ case "UNRECOGNIZED":
6035
+ default:
6036
+ return SyncState.UNRECOGNIZED;
6037
+ }
6038
+ }
6039
+ function syncStateToJSON(object) {
6040
+ switch (object) {
6041
+ case SyncState.SYNC_STATE_UNSPECIFIED:
6042
+ return "SYNC_STATE_UNSPECIFIED";
6043
+ case SyncState.SYNC_STATE_ALL:
6044
+ return "SYNC_STATE_ALL";
6045
+ case SyncState.SYNC_STATE_ADD:
6046
+ return "SYNC_STATE_ADD";
6047
+ case SyncState.SYNC_STATE_UPDATE:
6048
+ return "SYNC_STATE_UPDATE";
6049
+ case SyncState.SYNC_STATE_DELETE:
6050
+ return "SYNC_STATE_DELETE";
6051
+ case SyncState.SYNC_STATE_PING:
6052
+ return "SYNC_STATE_PING";
6053
+ case SyncState.UNRECOGNIZED:
6054
+ default:
6055
+ return "UNRECOGNIZED";
6056
+ }
6057
+ }
6058
+ function createBaseSyncFlagsRequest() {
6059
+ return { providerId: "", selector: "" };
6060
+ }
6061
+ const SyncFlagsRequest = {
6062
+ encode(message, writer = minimal.Writer.create()) {
6063
+ if (message.providerId !== "") {
6064
+ writer.uint32(10).string(message.providerId);
6065
+ }
6066
+ if (message.selector !== "") {
6067
+ writer.uint32(18).string(message.selector);
6068
+ }
6069
+ return writer;
6070
+ },
6071
+ decode(input, length) {
6072
+ const reader = input instanceof minimal.Reader ? input : minimal.Reader.create(input);
6073
+ let end = length === undefined ? reader.len : reader.pos + length;
6074
+ const message = createBaseSyncFlagsRequest();
6075
+ while (reader.pos < end) {
6076
+ const tag = reader.uint32();
6077
+ switch (tag >>> 3) {
6078
+ case 1:
6079
+ if (tag !== 10) {
6080
+ break;
6081
+ }
6082
+ message.providerId = reader.string();
6083
+ continue;
6084
+ case 2:
6085
+ if (tag !== 18) {
6086
+ break;
6087
+ }
6088
+ message.selector = reader.string();
6089
+ continue;
6090
+ }
6091
+ if ((tag & 7) === 4 || tag === 0) {
6092
+ break;
6093
+ }
6094
+ reader.skipType(tag & 7);
6095
+ }
6096
+ return message;
6097
+ },
6098
+ fromJSON(object) {
6099
+ return {
6100
+ providerId: isSet(object.providerId) ? String(object.providerId) : "",
6101
+ selector: isSet(object.selector) ? String(object.selector) : "",
6102
+ };
6103
+ },
6104
+ toJSON(message) {
6105
+ const obj = {};
6106
+ if (message.providerId !== "") {
6107
+ obj.providerId = message.providerId;
6108
+ }
6109
+ if (message.selector !== "") {
6110
+ obj.selector = message.selector;
6111
+ }
6112
+ return obj;
6113
+ },
6114
+ create(base) {
6115
+ return SyncFlagsRequest.fromPartial(base !== null && base !== void 0 ? base : {});
6116
+ },
6117
+ fromPartial(object) {
6118
+ var _a, _b;
6119
+ const message = createBaseSyncFlagsRequest();
6120
+ message.providerId = (_a = object.providerId) !== null && _a !== void 0 ? _a : "";
6121
+ message.selector = (_b = object.selector) !== null && _b !== void 0 ? _b : "";
6122
+ return message;
6123
+ },
6124
+ };
6125
+ function createBaseSyncFlagsResponse() {
6126
+ return { flagConfiguration: "", state: 0 };
6127
+ }
6128
+ const SyncFlagsResponse = {
6129
+ encode(message, writer = minimal.Writer.create()) {
6130
+ if (message.flagConfiguration !== "") {
6131
+ writer.uint32(10).string(message.flagConfiguration);
6132
+ }
6133
+ if (message.state !== 0) {
6134
+ writer.uint32(16).int32(message.state);
6135
+ }
6136
+ return writer;
6137
+ },
6138
+ decode(input, length) {
6139
+ const reader = input instanceof minimal.Reader ? input : minimal.Reader.create(input);
6140
+ let end = length === undefined ? reader.len : reader.pos + length;
6141
+ const message = createBaseSyncFlagsResponse();
6142
+ while (reader.pos < end) {
6143
+ const tag = reader.uint32();
6144
+ switch (tag >>> 3) {
6145
+ case 1:
6146
+ if (tag !== 10) {
6147
+ break;
6148
+ }
6149
+ message.flagConfiguration = reader.string();
6150
+ continue;
6151
+ case 2:
6152
+ if (tag !== 16) {
6153
+ break;
6154
+ }
6155
+ message.state = reader.int32();
6156
+ continue;
6157
+ }
6158
+ if ((tag & 7) === 4 || tag === 0) {
6159
+ break;
6160
+ }
6161
+ reader.skipType(tag & 7);
6162
+ }
6163
+ return message;
6164
+ },
6165
+ fromJSON(object) {
6166
+ return {
6167
+ flagConfiguration: isSet(object.flagConfiguration) ? String(object.flagConfiguration) : "",
6168
+ state: isSet(object.state) ? syncStateFromJSON(object.state) : 0,
6169
+ };
6170
+ },
6171
+ toJSON(message) {
6172
+ const obj = {};
6173
+ if (message.flagConfiguration !== "") {
6174
+ obj.flagConfiguration = message.flagConfiguration;
6175
+ }
6176
+ if (message.state !== 0) {
6177
+ obj.state = syncStateToJSON(message.state);
6178
+ }
6179
+ return obj;
6180
+ },
6181
+ create(base) {
6182
+ return SyncFlagsResponse.fromPartial(base !== null && base !== void 0 ? base : {});
6183
+ },
6184
+ fromPartial(object) {
6185
+ var _a, _b;
6186
+ const message = createBaseSyncFlagsResponse();
6187
+ message.flagConfiguration = (_a = object.flagConfiguration) !== null && _a !== void 0 ? _a : "";
6188
+ message.state = (_b = object.state) !== null && _b !== void 0 ? _b : 0;
6189
+ return message;
6190
+ },
6191
+ };
6192
+ function createBaseFetchAllFlagsRequest() {
6193
+ return { providerId: "", selector: "" };
6194
+ }
6195
+ const FetchAllFlagsRequest = {
6196
+ encode(message, writer = minimal.Writer.create()) {
6197
+ if (message.providerId !== "") {
6198
+ writer.uint32(10).string(message.providerId);
6199
+ }
6200
+ if (message.selector !== "") {
6201
+ writer.uint32(18).string(message.selector);
6202
+ }
6203
+ return writer;
6204
+ },
6205
+ decode(input, length) {
6206
+ const reader = input instanceof minimal.Reader ? input : minimal.Reader.create(input);
6207
+ let end = length === undefined ? reader.len : reader.pos + length;
6208
+ const message = createBaseFetchAllFlagsRequest();
6209
+ while (reader.pos < end) {
6210
+ const tag = reader.uint32();
6211
+ switch (tag >>> 3) {
6212
+ case 1:
6213
+ if (tag !== 10) {
6214
+ break;
6215
+ }
6216
+ message.providerId = reader.string();
6217
+ continue;
6218
+ case 2:
6219
+ if (tag !== 18) {
6220
+ break;
6221
+ }
6222
+ message.selector = reader.string();
6223
+ continue;
6224
+ }
6225
+ if ((tag & 7) === 4 || tag === 0) {
6226
+ break;
6227
+ }
6228
+ reader.skipType(tag & 7);
6229
+ }
6230
+ return message;
6231
+ },
6232
+ fromJSON(object) {
6233
+ return {
6234
+ providerId: isSet(object.providerId) ? String(object.providerId) : "",
6235
+ selector: isSet(object.selector) ? String(object.selector) : "",
6236
+ };
6237
+ },
6238
+ toJSON(message) {
6239
+ const obj = {};
6240
+ if (message.providerId !== "") {
6241
+ obj.providerId = message.providerId;
6242
+ }
6243
+ if (message.selector !== "") {
6244
+ obj.selector = message.selector;
6245
+ }
6246
+ return obj;
6247
+ },
6248
+ create(base) {
6249
+ return FetchAllFlagsRequest.fromPartial(base !== null && base !== void 0 ? base : {});
6250
+ },
6251
+ fromPartial(object) {
6252
+ var _a, _b;
6253
+ const message = createBaseFetchAllFlagsRequest();
6254
+ message.providerId = (_a = object.providerId) !== null && _a !== void 0 ? _a : "";
6255
+ message.selector = (_b = object.selector) !== null && _b !== void 0 ? _b : "";
6256
+ return message;
6257
+ },
6258
+ };
6259
+ function createBaseFetchAllFlagsResponse() {
6260
+ return { flagConfiguration: "" };
6261
+ }
6262
+ const FetchAllFlagsResponse = {
6263
+ encode(message, writer = minimal.Writer.create()) {
6264
+ if (message.flagConfiguration !== "") {
6265
+ writer.uint32(10).string(message.flagConfiguration);
6266
+ }
6267
+ return writer;
6268
+ },
6269
+ decode(input, length) {
6270
+ const reader = input instanceof minimal.Reader ? input : minimal.Reader.create(input);
6271
+ let end = length === undefined ? reader.len : reader.pos + length;
6272
+ const message = createBaseFetchAllFlagsResponse();
6273
+ while (reader.pos < end) {
6274
+ const tag = reader.uint32();
6275
+ switch (tag >>> 3) {
6276
+ case 1:
6277
+ if (tag !== 10) {
6278
+ break;
6279
+ }
6280
+ message.flagConfiguration = reader.string();
6281
+ continue;
6282
+ }
6283
+ if ((tag & 7) === 4 || tag === 0) {
6284
+ break;
6285
+ }
6286
+ reader.skipType(tag & 7);
6287
+ }
6288
+ return message;
6289
+ },
6290
+ fromJSON(object) {
6291
+ return { flagConfiguration: isSet(object.flagConfiguration) ? String(object.flagConfiguration) : "" };
6292
+ },
6293
+ toJSON(message) {
6294
+ const obj = {};
6295
+ if (message.flagConfiguration !== "") {
6296
+ obj.flagConfiguration = message.flagConfiguration;
6297
+ }
6298
+ return obj;
6299
+ },
6300
+ create(base) {
6301
+ return FetchAllFlagsResponse.fromPartial(base !== null && base !== void 0 ? base : {});
6302
+ },
6303
+ fromPartial(object) {
6304
+ var _a;
6305
+ const message = createBaseFetchAllFlagsResponse();
6306
+ message.flagConfiguration = (_a = object.flagConfiguration) !== null && _a !== void 0 ? _a : "";
6307
+ return message;
6308
+ },
6309
+ };
6310
+ const FlagSyncServiceService = {
6311
+ syncFlags: {
6312
+ path: "/sync.v1.FlagSyncService/SyncFlags",
6313
+ requestStream: false,
6314
+ responseStream: true,
6315
+ requestSerialize: (value) => Buffer.from(SyncFlagsRequest.encode(value).finish()),
6316
+ requestDeserialize: (value) => SyncFlagsRequest.decode(value),
6317
+ responseSerialize: (value) => Buffer.from(SyncFlagsResponse.encode(value).finish()),
6318
+ responseDeserialize: (value) => SyncFlagsResponse.decode(value),
6319
+ },
6320
+ fetchAllFlags: {
6321
+ path: "/sync.v1.FlagSyncService/FetchAllFlags",
6322
+ requestStream: false,
6323
+ responseStream: false,
6324
+ requestSerialize: (value) => Buffer.from(FetchAllFlagsRequest.encode(value).finish()),
6325
+ requestDeserialize: (value) => FetchAllFlagsRequest.decode(value),
6326
+ responseSerialize: (value) => Buffer.from(FetchAllFlagsResponse.encode(value).finish()),
6327
+ responseDeserialize: (value) => FetchAllFlagsResponse.decode(value),
6328
+ },
6329
+ };
6330
+ const FlagSyncServiceClient = makeGenericClientConstructor(FlagSyncServiceService, "sync.v1.FlagSyncService");
6331
+ function isSet(value) {
6332
+ return value !== null && value !== undefined;
6333
+ }
6334
+
6335
+ /**
6336
+ * Implements the gRPC sync contract to fetch flag data.
6337
+ */
6338
+ class GrpcFetch {
6339
+ constructor(config, syncServiceClient, logger) {
6340
+ const { host, port, tls, socketPath, selector } = config;
6341
+ this._syncClient = syncServiceClient
6342
+ ? syncServiceClient
6343
+ : new FlagSyncServiceClient(socketPath ? `unix://${socketPath}` : `${host}:${port}`, tls ? credentials.createSsl() : credentials.createInsecure());
6344
+ this._logger = logger;
6345
+ this._request = { providerId: '', selector: selector ? selector : '' };
6346
+ }
6347
+ connect(dataFillCallback, reconnectCallback, changedCallback, disconnectCallback) {
6348
+ // note that we never reject the promise as sync is a long-running operation
6349
+ return new Promise((resolve, reject) => this.listen(dataFillCallback, reconnectCallback, changedCallback, disconnectCallback, resolve, reject));
6350
+ }
6351
+ disconnect() {
6352
+ var _a, _b;
6353
+ (_a = this._logger) === null || _a === void 0 ? void 0 : _a.debug('Disconnecting gRPC sync connection');
6354
+ (_b = this._syncStream) === null || _b === void 0 ? void 0 : _b.destroy();
6355
+ this._syncClient.close();
6356
+ }
6357
+ listen(dataFillCallback, reconnectCallback, changedCallback, disconnectCallback, resolveConnect, rejectConnect) {
6358
+ this._syncStream = this._syncClient.syncFlags(this._request);
6359
+ this._syncStream.on('data', (data) => {
6360
+ var _a;
6361
+ (_a = this._logger) === null || _a === void 0 ? void 0 : _a.debug('Received sync payload');
6362
+ dataFillCallback(data.flagConfiguration);
6363
+ changedCallback([]); // flags changed list not supported
6364
+ // if resolveConnect is undefined, this is a reconnection; we only want to fire the reconnect callback in that case
6365
+ if (resolveConnect) {
6366
+ resolveConnect();
6367
+ }
6368
+ else {
6369
+ reconnectCallback();
6370
+ }
6371
+ });
6372
+ this._syncStream.on('error', (err) => {
6373
+ var _a;
6374
+ (_a = this._logger) === null || _a === void 0 ? void 0 : _a.error('Connection error, attempting to reconnect', err);
6375
+ disconnectCallback();
6376
+ rejectConnect === null || rejectConnect === void 0 ? void 0 : rejectConnect(new GeneralError('Failed to connect stream'));
6377
+ this.reconnect(dataFillCallback, reconnectCallback, changedCallback, disconnectCallback);
6378
+ });
6379
+ }
6380
+ reconnect(dataFillCallback, reconnectCallback, changedCallback, disconnectCallback) {
6381
+ const channel = this._syncClient.getChannel();
6382
+ channel.watchConnectivityState(channel.getConnectivityState(true), Infinity, () => {
6383
+ this.listen(dataFillCallback, reconnectCallback, changedCallback, disconnectCallback);
6384
+ });
6385
+ }
6386
+ }
6387
+
6388
+ class InProcessService {
6389
+ constructor(config, dataFetcher, logger) {
6390
+ this._flagdCore = new FlagdCore();
6391
+ this._dataFetcher = dataFetcher ? dataFetcher : new GrpcFetch(config, undefined, logger);
6392
+ }
6393
+ connect(reconnectCallback, changedCallback, disconnectCallback) {
6394
+ return this._dataFetcher.connect(this.fill.bind(this), reconnectCallback, changedCallback, disconnectCallback);
6395
+ }
6396
+ disconnect() {
6397
+ return __awaiter(this, void 0, void 0, function* () {
6398
+ this._dataFetcher.disconnect();
6399
+ });
6400
+ }
6401
+ resolveBoolean(flagKey, defaultValue, context, logger) {
6402
+ return Promise.resolve(this._flagdCore.resolveBooleanEvaluation(flagKey, defaultValue, context, logger));
6403
+ }
6404
+ resolveNumber(flagKey, defaultValue, context, logger) {
6405
+ return Promise.resolve(this._flagdCore.resolveNumberEvaluation(flagKey, defaultValue, context, logger));
6406
+ }
6407
+ resolveString(flagKey, defaultValue, context, logger) {
6408
+ return Promise.resolve(this._flagdCore.resolveStringEvaluation(flagKey, defaultValue, context, logger));
6409
+ }
6410
+ resolveObject(flagKey, defaultValue, context, logger) {
6411
+ return Promise.resolve(this._flagdCore.resolveObjectEvaluation(flagKey, defaultValue, context, logger));
6412
+ }
6413
+ fill(flags) {
6414
+ this._flagdCore.setConfigurations(flags);
6415
+ }
6416
+ }
6417
+
6008
6418
  class FlagdProvider {
6009
6419
  get status() {
6010
6420
  return this._status;
@@ -6032,11 +6442,16 @@ class FlagdProvider {
6032
6442
  logger.error(err === null || err === void 0 ? void 0 : err.stack);
6033
6443
  throw err;
6034
6444
  };
6035
- this._service = service ? service : new GRPCService(getConfig(options), undefined, logger);
6445
+ const config = getConfig(options);
6446
+ this._service = service
6447
+ ? service
6448
+ : config.resolverType === 'in-process'
6449
+ ? new InProcessService(config, undefined, logger)
6450
+ : new GRPCService(config, undefined, logger);
6036
6451
  }
6037
6452
  initialize() {
6038
6453
  return this._service
6039
- .connect(this.setReady.bind(this), this.emitChanged.bind(this), this.setError.bind(this))
6454
+ .connect(this.handleReconnect.bind(this), this.handleChanged.bind(this), this.handleError.bind(this))
6040
6455
  .then(() => {
6041
6456
  var _a;
6042
6457
  (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`${this.metadata.name}: ready`);
@@ -6054,33 +6469,35 @@ class FlagdProvider {
6054
6469
  (_a = this.logger) === null || _a === void 0 ? void 0 : _a.debug(`${this.metadata.name}: shutting down`);
6055
6470
  return this._service.disconnect();
6056
6471
  }
6057
- resolveBooleanEvaluation(flagKey, _, transformedContext, logger) {
6472
+ resolveBooleanEvaluation(flagKey, defaultValue, transformedContext, logger) {
6058
6473
  return this._service
6059
- .resolveBoolean(flagKey, transformedContext, logger)
6474
+ .resolveBoolean(flagKey, defaultValue, transformedContext, logger)
6060
6475
  .catch((err) => this.logRejected(err, flagKey, logger));
6061
6476
  }
6062
- resolveStringEvaluation(flagKey, _, transformedContext, logger) {
6477
+ resolveStringEvaluation(flagKey, defaultValue, transformedContext, logger) {
6063
6478
  return this._service
6064
- .resolveString(flagKey, transformedContext, logger)
6479
+ .resolveString(flagKey, defaultValue, transformedContext, logger)
6065
6480
  .catch((err) => this.logRejected(err, flagKey, logger));
6066
6481
  }
6067
- resolveNumberEvaluation(flagKey, _, transformedContext, logger) {
6482
+ resolveNumberEvaluation(flagKey, defaultValue, transformedContext, logger) {
6068
6483
  return this._service
6069
- .resolveNumber(flagKey, transformedContext, logger)
6484
+ .resolveNumber(flagKey, defaultValue, transformedContext, logger)
6070
6485
  .catch((err) => this.logRejected(err, flagKey, logger));
6071
6486
  }
6072
- resolveObjectEvaluation(flagKey, _, transformedContext, logger) {
6487
+ resolveObjectEvaluation(flagKey, defaultValue, transformedContext, logger) {
6073
6488
  return this._service
6074
- .resolveObject(flagKey, transformedContext, logger)
6489
+ .resolveObject(flagKey, defaultValue, transformedContext, logger)
6075
6490
  .catch((err) => this.logRejected(err, flagKey, logger));
6076
6491
  }
6077
- setReady() {
6492
+ handleReconnect() {
6078
6493
  this._status = ProviderStatus.READY;
6494
+ this._events.emit(ProviderEvents.Ready);
6079
6495
  }
6080
- setError() {
6496
+ handleError() {
6081
6497
  this._status = ProviderStatus.ERROR;
6498
+ this._events.emit(ProviderEvents.Error);
6082
6499
  }
6083
- emitChanged(flagsChanged) {
6500
+ handleChanged(flagsChanged) {
6084
6501
  this._events.emit(ProviderEvents.ConfigurationChanged, { flagsChanged });
6085
6502
  }
6086
6503
  }