@spotify-confidence/openfeature-server-provider-local 0.6.0 → 0.8.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.
@@ -1112,14 +1112,14 @@ const ResolveFlagsResponse = {
1112
1112
  fromJSON(object) {
1113
1113
  return {
1114
1114
  resolvedFlags: globalThis.Array.isArray(object?.resolvedFlags) ? object.resolvedFlags.map((e) => ResolvedFlag.fromJSON(e)) : [],
1115
- resolveToken: isSet$3(object.resolveToken) ? bytesFromBase64$1(object.resolveToken) : new Uint8Array(0),
1115
+ resolveToken: isSet$3(object.resolveToken) ? bytesFromBase64$2(object.resolveToken) : new Uint8Array(0),
1116
1116
  resolveId: isSet$3(object.resolveId) ? globalThis.String(object.resolveId) : ""
1117
1117
  };
1118
1118
  },
1119
1119
  toJSON(message) {
1120
1120
  const obj = {};
1121
1121
  if (message.resolvedFlags?.length) obj.resolvedFlags = message.resolvedFlags.map((e) => ResolvedFlag.toJSON(e));
1122
- if (message.resolveToken.length !== 0) obj.resolveToken = base64FromBytes$1(message.resolveToken);
1122
+ if (message.resolveToken.length !== 0) obj.resolveToken = base64FromBytes$2(message.resolveToken);
1123
1123
  if (message.resolveId !== "") obj.resolveId = message.resolveId;
1124
1124
  return obj;
1125
1125
  },
@@ -1134,13 +1134,151 @@ const ResolveFlagsResponse = {
1134
1134
  return message;
1135
1135
  }
1136
1136
  };
1137
+ function createBaseApplyFlagsRequest() {
1138
+ return {
1139
+ flags: [],
1140
+ clientSecret: "",
1141
+ resolveToken: new Uint8Array(0),
1142
+ sendTime: void 0,
1143
+ sdk: void 0
1144
+ };
1145
+ }
1146
+ const ApplyFlagsRequest = {
1147
+ encode(message, writer = new BinaryWriter()) {
1148
+ for (const v of message.flags) AppliedFlag.encode(v, writer.uint32(10).fork()).join();
1149
+ if (message.clientSecret !== "") writer.uint32(18).string(message.clientSecret);
1150
+ if (message.resolveToken.length !== 0) writer.uint32(26).bytes(message.resolveToken);
1151
+ if (message.sendTime !== void 0) Timestamp.encode(toTimestamp(message.sendTime), writer.uint32(34).fork()).join();
1152
+ if (message.sdk !== void 0) Sdk.encode(message.sdk, writer.uint32(42).fork()).join();
1153
+ return writer;
1154
+ },
1155
+ decode(input, length) {
1156
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
1157
+ const end = length === void 0 ? reader.len : reader.pos + length;
1158
+ const message = createBaseApplyFlagsRequest();
1159
+ while (reader.pos < end) {
1160
+ const tag = reader.uint32();
1161
+ switch (tag >>> 3) {
1162
+ case 1:
1163
+ if (tag !== 10) break;
1164
+ message.flags.push(AppliedFlag.decode(reader, reader.uint32()));
1165
+ continue;
1166
+ case 2:
1167
+ if (tag !== 18) break;
1168
+ message.clientSecret = reader.string();
1169
+ continue;
1170
+ case 3:
1171
+ if (tag !== 26) break;
1172
+ message.resolveToken = reader.bytes();
1173
+ continue;
1174
+ case 4:
1175
+ if (tag !== 34) break;
1176
+ message.sendTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
1177
+ continue;
1178
+ case 5:
1179
+ if (tag !== 42) break;
1180
+ message.sdk = Sdk.decode(reader, reader.uint32());
1181
+ continue;
1182
+ }
1183
+ if ((tag & 7) === 4 || tag === 0) break;
1184
+ reader.skip(tag & 7);
1185
+ }
1186
+ return message;
1187
+ },
1188
+ fromJSON(object) {
1189
+ return {
1190
+ flags: globalThis.Array.isArray(object?.flags) ? object.flags.map((e) => AppliedFlag.fromJSON(e)) : [],
1191
+ clientSecret: isSet$3(object.clientSecret) ? globalThis.String(object.clientSecret) : "",
1192
+ resolveToken: isSet$3(object.resolveToken) ? bytesFromBase64$2(object.resolveToken) : new Uint8Array(0),
1193
+ sendTime: isSet$3(object.sendTime) ? fromJsonTimestamp(object.sendTime) : void 0,
1194
+ sdk: isSet$3(object.sdk) ? Sdk.fromJSON(object.sdk) : void 0
1195
+ };
1196
+ },
1197
+ toJSON(message) {
1198
+ const obj = {};
1199
+ if (message.flags?.length) obj.flags = message.flags.map((e) => AppliedFlag.toJSON(e));
1200
+ if (message.clientSecret !== "") obj.clientSecret = message.clientSecret;
1201
+ if (message.resolveToken.length !== 0) obj.resolveToken = base64FromBytes$2(message.resolveToken);
1202
+ if (message.sendTime !== void 0) obj.sendTime = message.sendTime.toISOString();
1203
+ if (message.sdk !== void 0) obj.sdk = Sdk.toJSON(message.sdk);
1204
+ return obj;
1205
+ },
1206
+ create(base) {
1207
+ return ApplyFlagsRequest.fromPartial(base ?? {});
1208
+ },
1209
+ fromPartial(object) {
1210
+ const message = createBaseApplyFlagsRequest();
1211
+ message.flags = object.flags?.map((e) => AppliedFlag.fromPartial(e)) || [];
1212
+ message.clientSecret = object.clientSecret ?? "";
1213
+ message.resolveToken = object.resolveToken ?? new Uint8Array(0);
1214
+ message.sendTime = object.sendTime ?? void 0;
1215
+ message.sdk = object.sdk !== void 0 && object.sdk !== null ? Sdk.fromPartial(object.sdk) : void 0;
1216
+ return message;
1217
+ }
1218
+ };
1219
+ function createBaseAppliedFlag() {
1220
+ return {
1221
+ flag: "",
1222
+ applyTime: void 0
1223
+ };
1224
+ }
1225
+ const AppliedFlag = {
1226
+ encode(message, writer = new BinaryWriter()) {
1227
+ if (message.flag !== "") writer.uint32(10).string(message.flag);
1228
+ if (message.applyTime !== void 0) Timestamp.encode(toTimestamp(message.applyTime), writer.uint32(18).fork()).join();
1229
+ return writer;
1230
+ },
1231
+ decode(input, length) {
1232
+ const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
1233
+ const end = length === void 0 ? reader.len : reader.pos + length;
1234
+ const message = createBaseAppliedFlag();
1235
+ while (reader.pos < end) {
1236
+ const tag = reader.uint32();
1237
+ switch (tag >>> 3) {
1238
+ case 1:
1239
+ if (tag !== 10) break;
1240
+ message.flag = reader.string();
1241
+ continue;
1242
+ case 2:
1243
+ if (tag !== 18) break;
1244
+ message.applyTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
1245
+ continue;
1246
+ }
1247
+ if ((tag & 7) === 4 || tag === 0) break;
1248
+ reader.skip(tag & 7);
1249
+ }
1250
+ return message;
1251
+ },
1252
+ fromJSON(object) {
1253
+ return {
1254
+ flag: isSet$3(object.flag) ? globalThis.String(object.flag) : "",
1255
+ applyTime: isSet$3(object.applyTime) ? fromJsonTimestamp(object.applyTime) : void 0
1256
+ };
1257
+ },
1258
+ toJSON(message) {
1259
+ const obj = {};
1260
+ if (message.flag !== "") obj.flag = message.flag;
1261
+ if (message.applyTime !== void 0) obj.applyTime = message.applyTime.toISOString();
1262
+ return obj;
1263
+ },
1264
+ create(base) {
1265
+ return AppliedFlag.fromPartial(base ?? {});
1266
+ },
1267
+ fromPartial(object) {
1268
+ const message = createBaseAppliedFlag();
1269
+ message.flag = object.flag ?? "";
1270
+ message.applyTime = object.applyTime ?? void 0;
1271
+ return message;
1272
+ }
1273
+ };
1137
1274
  function createBaseResolvedFlag() {
1138
1275
  return {
1139
1276
  flag: "",
1140
1277
  variant: "",
1141
1278
  value: void 0,
1142
1279
  flagSchema: void 0,
1143
- reason: 0
1280
+ reason: 0,
1281
+ shouldApply: false
1144
1282
  };
1145
1283
  }
1146
1284
  const ResolvedFlag = {
@@ -1150,6 +1288,7 @@ const ResolvedFlag = {
1150
1288
  if (message.value !== void 0) Struct.encode(Struct.wrap(message.value), writer.uint32(26).fork()).join();
1151
1289
  if (message.flagSchema !== void 0) FlagSchema_StructFlagSchema.encode(message.flagSchema, writer.uint32(34).fork()).join();
1152
1290
  if (message.reason !== 0) writer.uint32(40).int32(message.reason);
1291
+ if (message.shouldApply !== false) writer.uint32(48).bool(message.shouldApply);
1153
1292
  return writer;
1154
1293
  },
1155
1294
  decode(input, length) {
@@ -1179,6 +1318,10 @@ const ResolvedFlag = {
1179
1318
  if (tag !== 40) break;
1180
1319
  message.reason = reader.int32();
1181
1320
  continue;
1321
+ case 6:
1322
+ if (tag !== 48) break;
1323
+ message.shouldApply = reader.bool();
1324
+ continue;
1182
1325
  }
1183
1326
  if ((tag & 7) === 4 || tag === 0) break;
1184
1327
  reader.skip(tag & 7);
@@ -1191,7 +1334,8 @@ const ResolvedFlag = {
1191
1334
  variant: isSet$3(object.variant) ? globalThis.String(object.variant) : "",
1192
1335
  value: isObject(object.value) ? object.value : void 0,
1193
1336
  flagSchema: isSet$3(object.flagSchema) ? FlagSchema_StructFlagSchema.fromJSON(object.flagSchema) : void 0,
1194
- reason: isSet$3(object.reason) ? resolveReasonFromJSON(object.reason) : 0
1337
+ reason: isSet$3(object.reason) ? resolveReasonFromJSON(object.reason) : 0,
1338
+ shouldApply: isSet$3(object.shouldApply) ? globalThis.Boolean(object.shouldApply) : false
1195
1339
  };
1196
1340
  },
1197
1341
  toJSON(message) {
@@ -1201,6 +1345,7 @@ const ResolvedFlag = {
1201
1345
  if (message.value !== void 0) obj.value = message.value;
1202
1346
  if (message.flagSchema !== void 0) obj.flagSchema = FlagSchema_StructFlagSchema.toJSON(message.flagSchema);
1203
1347
  if (message.reason !== 0) obj.reason = resolveReasonToJSON(message.reason);
1348
+ if (message.shouldApply !== false) obj.shouldApply = message.shouldApply;
1204
1349
  return obj;
1205
1350
  },
1206
1351
  create(base) {
@@ -1213,10 +1358,11 @@ const ResolvedFlag = {
1213
1358
  message.value = object.value ?? void 0;
1214
1359
  message.flagSchema = object.flagSchema !== void 0 && object.flagSchema !== null ? FlagSchema_StructFlagSchema.fromPartial(object.flagSchema) : void 0;
1215
1360
  message.reason = object.reason ?? 0;
1361
+ message.shouldApply = object.shouldApply ?? false;
1216
1362
  return message;
1217
1363
  }
1218
1364
  };
1219
- function bytesFromBase64$1(b64) {
1365
+ function bytesFromBase64$2(b64) {
1220
1366
  if (globalThis.Buffer) return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
1221
1367
  else {
1222
1368
  const bin = globalThis.atob(b64);
@@ -1225,7 +1371,7 @@ function bytesFromBase64$1(b64) {
1225
1371
  return arr;
1226
1372
  }
1227
1373
  }
1228
- function base64FromBytes$1(arr) {
1374
+ function base64FromBytes$2(arr) {
1229
1375
  if (globalThis.Buffer) return globalThis.Buffer.from(arr).toString("base64");
1230
1376
  else {
1231
1377
  const bin = [];
@@ -1235,13 +1381,31 @@ function base64FromBytes$1(arr) {
1235
1381
  return globalThis.btoa(bin.join(""));
1236
1382
  }
1237
1383
  }
1384
+ function toTimestamp(date) {
1385
+ const seconds = Math.trunc(date.getTime() / 1e3);
1386
+ const nanos = date.getTime() % 1e3 * 1e6;
1387
+ return {
1388
+ seconds,
1389
+ nanos
1390
+ };
1391
+ }
1392
+ function fromTimestamp(t) {
1393
+ let millis = (t.seconds || 0) * 1e3;
1394
+ millis += (t.nanos || 0) / 1e6;
1395
+ return new globalThis.Date(millis);
1396
+ }
1397
+ function fromJsonTimestamp(o) {
1398
+ if (o instanceof globalThis.Date) return o;
1399
+ else if (typeof o === "string") return new globalThis.Date(o);
1400
+ else return fromTimestamp(Timestamp.fromJSON(o));
1401
+ }
1238
1402
  function isObject(value) {
1239
1403
  return typeof value === "object" && value !== null;
1240
1404
  }
1241
1405
  function isSet$3(value) {
1242
1406
  return value !== null && value !== void 0;
1243
1407
  }
1244
- const VERSION = "0.6.0";
1408
+ const VERSION = "0.8.0";
1245
1409
  const NOOP_LOG_FN = Object.assign(() => {}, { enabled: false });
1246
1410
  const debugBackend = loadDebug();
1247
1411
  const logger$2 = new class LoggerImpl {
@@ -1341,11 +1505,11 @@ function abortableSleep(milliseconds, signal) {
1341
1505
  if (signal?.aborted) return Promise.reject(signal.reason);
1342
1506
  if (milliseconds <= 0) return Promise.resolve();
1343
1507
  if (milliseconds === Infinity) return signal ? promiseSignal(signal) : new Promise(() => {});
1344
- return new Promise((resolve, reject) => {
1508
+ return new Promise((resolve$1, reject) => {
1345
1509
  let timeout;
1346
1510
  const onTimeout = () => {
1347
1511
  cleanup();
1348
- resolve();
1512
+ resolve$1();
1349
1513
  };
1350
1514
  const onAbort = () => {
1351
1515
  cleanup();
@@ -1373,13 +1537,32 @@ function hasKey(obj, key) {
1373
1537
  function castStringToEnum(value) {
1374
1538
  return value;
1375
1539
  }
1540
+ function bytesFromBase64(b64) {
1541
+ if (globalThis.Buffer) return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
1542
+ else {
1543
+ const bin = globalThis.atob(b64);
1544
+ const arr = new Uint8Array(bin.length);
1545
+ for (let i = 0; i < bin.length; ++i) arr[i] = bin.charCodeAt(i);
1546
+ return arr;
1547
+ }
1548
+ }
1549
+ function base64FromBytes(arr) {
1550
+ if (globalThis.Buffer) return globalThis.Buffer.from(arr).toString("base64");
1551
+ else {
1552
+ const bin = [];
1553
+ arr.forEach((byte) => {
1554
+ bin.push(String.fromCharCode(byte));
1555
+ });
1556
+ return globalThis.btoa(bin.join(""));
1557
+ }
1558
+ }
1376
1559
  const logger$3 = logger$2.getLogger("fetch");
1377
1560
  let Fetch;
1378
1561
  (function(_Fetch) {
1379
- function create(middleware, sink = fetch) {
1562
+ function create$1(middleware, sink = fetch) {
1380
1563
  return middleware.reduceRight((next, middleware$1) => middleware$1(next), sink);
1381
1564
  }
1382
- _Fetch.create = create;
1565
+ _Fetch.create = create$1;
1383
1566
  })(Fetch || (Fetch = {}));
1384
1567
  let FetchMiddleware;
1385
1568
  (function(_FetchMiddleware) {
@@ -1449,9 +1632,9 @@ function withRetry(opts) {
1449
1632
  await abortableSleep(serverDelay ?? deadline - Date.now(), signal);
1450
1633
  return doTry();
1451
1634
  };
1452
- const onError = async (error) => {
1453
- logger$3.debug("withRetry %s failed attempt %d with %s", url, attempts - 1, error);
1454
- if (signal?.aborted || attempts >= maxAttempts) throw error;
1635
+ const onError = async (error$1) => {
1636
+ logger$3.debug("withRetry %s failed attempt %d with %s", url, attempts - 1, error$1);
1637
+ if (signal?.aborted || attempts >= maxAttempts) throw error$1;
1455
1638
  await abortableSleep(deadline - Date.now(), signal);
1456
1639
  return doTry();
1457
1640
  };
@@ -2233,13 +2416,13 @@ const SetResolverStateRequest = {
2233
2416
  },
2234
2417
  fromJSON(object) {
2235
2418
  return {
2236
- state: isSet$1(object.state) ? bytesFromBase64(object.state) : new Uint8Array(0),
2419
+ state: isSet$1(object.state) ? bytesFromBase64$1(object.state) : new Uint8Array(0),
2237
2420
  accountId: isSet$1(object.accountId) ? globalThis.String(object.accountId) : ""
2238
2421
  };
2239
2422
  },
2240
2423
  toJSON(message) {
2241
2424
  const obj = {};
2242
- if (message.state.length !== 0) obj.state = base64FromBytes(message.state);
2425
+ if (message.state.length !== 0) obj.state = base64FromBytes$1(message.state);
2243
2426
  if (message.accountId !== "") obj.accountId = message.accountId;
2244
2427
  return obj;
2245
2428
  },
@@ -2279,11 +2462,11 @@ const Request = {
2279
2462
  return message;
2280
2463
  },
2281
2464
  fromJSON(object) {
2282
- return { data: isSet$1(object.data) ? bytesFromBase64(object.data) : new Uint8Array(0) };
2465
+ return { data: isSet$1(object.data) ? bytesFromBase64$1(object.data) : new Uint8Array(0) };
2283
2466
  },
2284
2467
  toJSON(message) {
2285
2468
  const obj = {};
2286
- if (message.data.length !== 0) obj.data = base64FromBytes(message.data);
2469
+ if (message.data.length !== 0) obj.data = base64FromBytes$1(message.data);
2287
2470
  return obj;
2288
2471
  },
2289
2472
  create(base) {
@@ -2330,13 +2513,13 @@ const Response$1 = {
2330
2513
  },
2331
2514
  fromJSON(object) {
2332
2515
  return {
2333
- data: isSet$1(object.data) ? bytesFromBase64(object.data) : void 0,
2516
+ data: isSet$1(object.data) ? bytesFromBase64$1(object.data) : void 0,
2334
2517
  error: isSet$1(object.error) ? globalThis.String(object.error) : void 0
2335
2518
  };
2336
2519
  },
2337
2520
  toJSON(message) {
2338
2521
  const obj = {};
2339
- if (message.data !== void 0) obj.data = base64FromBytes(message.data);
2522
+ if (message.data !== void 0) obj.data = base64FromBytes$1(message.data);
2340
2523
  if (message.error !== void 0) obj.error = message.error;
2341
2524
  return obj;
2342
2525
  },
@@ -2350,7 +2533,7 @@ const Response$1 = {
2350
2533
  return message;
2351
2534
  }
2352
2535
  };
2353
- function bytesFromBase64(b64) {
2536
+ function bytesFromBase64$1(b64) {
2354
2537
  if (globalThis.Buffer) return Uint8Array.from(globalThis.Buffer.from(b64, "base64"));
2355
2538
  else {
2356
2539
  const bin = globalThis.atob(b64);
@@ -2359,7 +2542,7 @@ function bytesFromBase64(b64) {
2359
2542
  return arr;
2360
2543
  }
2361
2544
  }
2362
- function base64FromBytes(arr) {
2545
+ function base64FromBytes$1(arr) {
2363
2546
  if (globalThis.Buffer) return globalThis.Buffer.from(arr).toString("base64");
2364
2547
  else {
2365
2548
  const bin = [];
@@ -2372,21 +2555,137 @@ function base64FromBytes(arr) {
2372
2555
  function isSet$1(value) {
2373
2556
  return value !== null && value !== void 0;
2374
2557
  }
2558
+ let ErrorCode = /* @__PURE__ */ function(ErrorCode$1) {
2559
+ ErrorCode$1["PROVIDER_NOT_READY"] = "PROVIDER_NOT_READY";
2560
+ ErrorCode$1["PROVIDER_FATAL"] = "PROVIDER_FATAL";
2561
+ ErrorCode$1["FLAG_NOT_FOUND"] = "FLAG_NOT_FOUND";
2562
+ ErrorCode$1["TYPE_MISMATCH"] = "TYPE_MISMATCH";
2563
+ ErrorCode$1["GENERAL"] = "GENERAL";
2564
+ return ErrorCode$1;
2565
+ }({});
2566
+ const encodeToken = base64FromBytes;
2567
+ const decodeToken = bytesFromBase64;
2568
+ function create({ resolveId, resolveToken, resolvedFlags }) {
2569
+ return {
2570
+ flags: Object.fromEntries(resolvedFlags.map(({ flag, reason, variant, value, shouldApply }) => {
2571
+ const name = flag.slice(6);
2572
+ const details = {
2573
+ reason: convertReason(reason),
2574
+ variant,
2575
+ value: value ?? null,
2576
+ shouldApply
2577
+ };
2578
+ return [name, details];
2579
+ })),
2580
+ resolveId,
2581
+ resolveToken: encodeToken(resolveToken)
2582
+ };
2583
+ }
2584
+ function error(errorCode, errorMessage) {
2585
+ return {
2586
+ flags: {},
2587
+ resolveId: "",
2588
+ resolveToken: "",
2589
+ errorCode,
2590
+ errorMessage
2591
+ };
2592
+ }
2593
+ function resolve(bundle, flagKey, defaultValue, logger$4) {
2594
+ const [flagName, ...path] = flagKey.split(".");
2595
+ const flag = bundle?.flags[flagName];
2596
+ if (bundle?.errorCode) {
2597
+ logger$4?.warn(`Flag evaluation for "%s" failed. %s %s`, flagKey, bundle.errorCode, bundle?.errorMessage);
2598
+ return {
2599
+ reason: "ERROR",
2600
+ errorCode: bundle.errorCode,
2601
+ errorMessage: bundle.errorMessage,
2602
+ value: defaultValue,
2603
+ shouldApply: false
2604
+ };
2605
+ }
2606
+ if (!flag) {
2607
+ logger$4?.warn(`Flag evaluation for '${flagKey}' failed: flag not found`);
2608
+ return {
2609
+ reason: "ERROR",
2610
+ errorCode: ErrorCode.FLAG_NOT_FOUND,
2611
+ value: defaultValue,
2612
+ shouldApply: false
2613
+ };
2614
+ }
2615
+ let value = flag.value;
2616
+ for (let i = 0; i < path.length; i++) {
2617
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return {
2618
+ reason: "ERROR",
2619
+ value: defaultValue,
2620
+ errorCode: ErrorCode.TYPE_MISMATCH,
2621
+ errorMessage: `resolved value is not an object at ${[flagName, ...path.slice(0, i)].join(".")}`,
2622
+ shouldApply: false
2623
+ };
2624
+ value = value[path[i]];
2625
+ }
2626
+ try {
2627
+ const validated = evaluateAssignment(value, defaultValue, [flagName, ...path]);
2628
+ return {
2629
+ ...flag,
2630
+ value: validated
2631
+ };
2632
+ } catch (e) {
2633
+ return {
2634
+ reason: "ERROR",
2635
+ value: defaultValue,
2636
+ errorCode: ErrorCode.TYPE_MISMATCH,
2637
+ errorMessage: String(e),
2638
+ shouldApply: false
2639
+ };
2640
+ }
2641
+ }
2642
+ function evaluateAssignment(resolvedValue, defaultValue, path) {
2643
+ const resolvedType = typeof resolvedValue;
2644
+ const defaultType = typeof defaultValue;
2645
+ if (Array.isArray(defaultValue)) throw `arrays are not supported as flag values at ${path.join(".")}`;
2646
+ if (defaultValue === null) return resolvedValue;
2647
+ if (resolvedValue === null) return defaultValue;
2648
+ if (resolvedType !== defaultType) throw `resolved value (${resolvedType}) isn't assignable to default type (${defaultType}) at ${path.join(".")}`;
2649
+ if (typeof resolvedValue === "object") {
2650
+ const result = { ...resolvedValue };
2651
+ for (const [key, value] of Object.entries(defaultValue)) {
2652
+ if (!hasKey(resolvedValue, key)) throw `resolved value is missing field "${key}" at ${path.join(".")}`;
2653
+ result[key] = evaluateAssignment(resolvedValue[key], value, [...path, key]);
2654
+ }
2655
+ return result;
2656
+ }
2657
+ return resolvedValue;
2658
+ }
2659
+ function convertReason(reason) {
2660
+ switch (reason) {
2661
+ case ResolveReason.RESOLVE_REASON_ERROR: return "ERROR";
2662
+ case ResolveReason.RESOLVE_REASON_FLAG_ARCHIVED: return "FLAG_ARCHIVED";
2663
+ case ResolveReason.RESOLVE_REASON_MATCH: return "MATCH";
2664
+ case ResolveReason.RESOLVE_REASON_NO_SEGMENT_MATCH: return "NO_SEGMENT_MATCH";
2665
+ case ResolveReason.RESOLVE_REASON_TARGETING_KEY_ERROR: return "TARGETING_KEY_ERROR";
2666
+ case ResolveReason.RESOLVE_REASON_NO_TREATMENT_MATCH: return "NO_TREATMENT_MATCH";
2667
+ default: return "UNSPECIFIED";
2668
+ }
2669
+ }
2375
2670
  const logger$1 = getLogger("provider");
2376
2671
  const DEFAULT_INITIALIZE_TIMEOUT = 3e4;
2377
2672
  const DEFAULT_STATE_INTERVAL = 3e4;
2378
2673
  const DEFAULT_FLUSH_INTERVAL = 1e4;
2379
2674
  var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2380
2675
  metadata = { name: "ConfidenceServerProviderLocal" };
2381
- status = "NOT_READY";
2676
+ status = castStringToEnum("NOT_READY");
2382
2677
  main = new AbortController();
2383
2678
  fetch;
2384
2679
  stateUpdateInterval;
2385
2680
  flushInterval;
2386
2681
  materializationStore;
2387
2682
  stateEtag = null;
2388
- constructor(resolver$1, options) {
2389
- this.resolver = resolver$1;
2683
+ get resolver() {
2684
+ if (this.resolverOrPromise instanceof Promise) throw new Error("Resolver not ready");
2685
+ return this.resolverOrPromise;
2686
+ }
2687
+ constructor(resolverOrPromise, options) {
2688
+ this.resolverOrPromise = resolverOrPromise;
2390
2689
  this.options = options;
2391
2690
  this.stateUpdateInterval = options.stateUpdateInterval ?? DEFAULT_STATE_INTERVAL;
2392
2691
  if (!Number.isInteger(this.stateUpdateInterval) || this.stateUpdateInterval < 1e3) throw new Error(`stateUpdateInterval must be an integer >= 1000 (1s), currently: ${this.stateUpdateInterval}`);
@@ -2424,15 +2723,16 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2424
2723
  const signal = this.main.signal;
2425
2724
  const initialUpdateSignal = AbortSignal.any([signal, timeoutSignal(this.options.initializeTimeout ?? DEFAULT_INITIALIZE_TIMEOUT)]);
2426
2725
  try {
2726
+ this.resolverOrPromise = await this.resolverOrPromise;
2427
2727
  await this.updateState(initialUpdateSignal);
2428
2728
  scheduleWithFixedInterval((signal$1) => this.flush(signal$1), this.flushInterval, {
2429
2729
  maxConcurrent: 3,
2430
2730
  signal
2431
2731
  });
2432
2732
  scheduleWithFixedInterval((signal$1) => this.updateState(signal$1), this.stateUpdateInterval, { signal });
2433
- this.status = "READY";
2733
+ this.status = castStringToEnum("READY");
2434
2734
  } catch (e) {
2435
- this.status = "ERROR";
2735
+ this.status = castStringToEnum("ERROR");
2436
2736
  throw e;
2437
2737
  }
2438
2738
  }
@@ -2440,34 +2740,33 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2440
2740
  await this.flush(timeoutSignal(3e3));
2441
2741
  this.main.abort();
2442
2742
  }
2743
+ async resolve(context, flagNames, apply = false) {
2744
+ const stickyRequest = {
2745
+ resolveRequest: {
2746
+ flags: flagNames.map((name) => `flags/${name}`),
2747
+ evaluationContext: ConfidenceServerProviderLocal.convertEvaluationContext(context),
2748
+ apply,
2749
+ clientSecret: this.options.flagClientSecret,
2750
+ sdk: {
2751
+ id: SdkId.SDK_ID_JS_LOCAL_SERVER_PROVIDER,
2752
+ version: VERSION
2753
+ }
2754
+ },
2755
+ materializations: [],
2756
+ failFastOnSticky: false,
2757
+ notProcessSticky: false
2758
+ };
2759
+ try {
2760
+ return create(await this.resolveWithSticky(stickyRequest));
2761
+ } catch (err) {
2762
+ return error(ErrorCode.GENERAL, String(err));
2763
+ }
2764
+ }
2443
2765
  async evaluate(flagKey, defaultValue, context) {
2444
2766
  try {
2445
- const [flagName, ...path] = flagKey.split(".");
2446
- const stickyRequest = {
2447
- resolveRequest: {
2448
- flags: [`flags/${flagName}`],
2449
- evaluationContext: ConfidenceServerProviderLocal.convertEvaluationContext(context),
2450
- apply: true,
2451
- clientSecret: this.options.flagClientSecret,
2452
- sdk: {
2453
- id: SdkId.SDK_ID_JS_LOCAL_SERVER_PROVIDER,
2454
- version: VERSION
2455
- }
2456
- },
2457
- materializations: [],
2458
- failFastOnSticky: false,
2459
- notProcessSticky: false
2460
- };
2461
- const response = await this.resolveWithSticky(stickyRequest);
2462
- return this.extractValue(response.resolvedFlags[0], flagName, path, defaultValue);
2463
- } catch (e) {
2464
- logger$1.warn(`Flag evaluation for '${flagKey}' failed`, e);
2465
- return {
2466
- value: defaultValue,
2467
- reason: "ERROR",
2468
- errorCode: castStringToEnum("GENERAL"),
2469
- errorMessage: String(e)
2470
- };
2767
+ const [flagName] = flagKey.split(".", 1);
2768
+ const resolution = await this.resolve(context, [flagName], true);
2769
+ return resolve(resolution, flagKey, defaultValue, logger$1);
2471
2770
  } finally {
2472
2771
  this.flushAssigned();
2473
2772
  }
@@ -2486,36 +2785,6 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2486
2785
  if (storeVariantOp.length) this.writeMaterializations({ storeVariantOp });
2487
2786
  return ResolveFlagsResponse.create(resolveResponse);
2488
2787
  }
2489
- extractValue(flag, flagName, path, defaultValue) {
2490
- if (!flag) return {
2491
- value: defaultValue,
2492
- reason: "ERROR",
2493
- errorCode: castStringToEnum("FLAG_NOT_FOUND")
2494
- };
2495
- if (flag.reason !== ResolveReason.RESOLVE_REASON_MATCH) return {
2496
- value: defaultValue,
2497
- reason: ConfidenceServerProviderLocal.convertReason(flag.reason)
2498
- };
2499
- let value = flag.value;
2500
- for (const step of path) {
2501
- if (typeof value !== "object" || value === null || !hasKey(value, step)) return {
2502
- value: defaultValue,
2503
- reason: "ERROR",
2504
- errorCode: castStringToEnum("TYPE_MISMATCH")
2505
- };
2506
- value = value[step];
2507
- }
2508
- if (!isAssignableTo(value, defaultValue)) return {
2509
- value: defaultValue,
2510
- reason: "ERROR",
2511
- errorCode: castStringToEnum("TYPE_MISMATCH")
2512
- };
2513
- return {
2514
- value,
2515
- reason: "MATCH",
2516
- variant: flag.variant
2517
- };
2518
- }
2519
2788
  async updateState(signal) {
2520
2789
  const cdnUrl = `https://confidence-resolver-state-cdn.spotifycdn.com/${await sha256Hex(this.options.flagClientSecret)}`;
2521
2790
  const headers = new Headers();
@@ -2573,17 +2842,6 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2573
2842
  }
2574
2843
  throw new Error("Write materialization not supported");
2575
2844
  }
2576
- static convertReason(reason) {
2577
- switch (reason) {
2578
- case ResolveReason.RESOLVE_REASON_ERROR: return "ERROR";
2579
- case ResolveReason.RESOLVE_REASON_FLAG_ARCHIVED: return "FLAG_ARCHIVED";
2580
- case ResolveReason.RESOLVE_REASON_MATCH: return "MATCH";
2581
- case ResolveReason.RESOLVE_REASON_NO_SEGMENT_MATCH: return "NO_SEGMENT_MATCH";
2582
- case ResolveReason.RESOLVE_REASON_TARGETING_KEY_ERROR: return "TARGETING_KEY_ERROR";
2583
- case ResolveReason.RESOLVE_REASON_NO_TREATMENT_MATCH: return "NO_TREATMENT_MATCH";
2584
- default: return "UNSPECIFIED";
2585
- }
2586
- }
2587
2845
  static convertEvaluationContext({ targetingKey: targeting_key,...rest }) {
2588
2846
  return {
2589
2847
  targeting_key,
@@ -2602,23 +2860,23 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2602
2860
  resolveStringEvaluation(flagKey, defaultValue, context) {
2603
2861
  return Promise.resolve(this.evaluate(flagKey, defaultValue, context));
2604
2862
  }
2605
- };
2606
- function isAssignableTo(value, schema) {
2607
- if (typeof schema !== typeof value) return false;
2608
- if (typeof value === "object" && typeof schema === "object") {
2609
- if (schema === null) return value === null;
2610
- if (Array.isArray(schema)) {
2611
- if (!Array.isArray(value)) return false;
2612
- if (schema.length == 0) return true;
2613
- return value.every((item) => isAssignableTo(item, schema[0]));
2614
- }
2615
- for (const [key, schemaValue] of Object.entries(schema)) {
2616
- if (!hasKey(value, key)) return false;
2617
- if (!isAssignableTo(value[key], schemaValue)) return false;
2618
- }
2863
+ applyFlag(resolveToken, flagName) {
2864
+ const request = {
2865
+ flags: [{
2866
+ flag: `flags/${flagName}`,
2867
+ applyTime: /* @__PURE__ */ new Date()
2868
+ }],
2869
+ clientSecret: this.options.flagClientSecret,
2870
+ resolveToken: decodeToken(resolveToken),
2871
+ sendTime: /* @__PURE__ */ new Date(),
2872
+ sdk: {
2873
+ id: SdkId.SDK_ID_JS_LOCAL_SERVER_PROVIDER,
2874
+ version: VERSION
2875
+ }
2876
+ };
2877
+ this.resolver.applyFlags(request);
2619
2878
  }
2620
- return true;
2621
- }
2879
+ };
2622
2880
  function createBaseResolveWithStickyRequest() {
2623
2881
  return {
2624
2882
  resolveRequest: void 0,
@@ -2812,7 +3070,8 @@ const EXPORT_FN_NAMES = [
2812
3070
  "wasm_msg_guest_resolve_with_sticky",
2813
3071
  "wasm_msg_guest_set_resolver_state",
2814
3072
  "wasm_msg_guest_bounded_flush_logs",
2815
- "wasm_msg_guest_bounded_flush_assign"
3073
+ "wasm_msg_guest_bounded_flush_assign",
3074
+ "wasm_msg_guest_apply_flags"
2816
3075
  ];
2817
3076
  function verifyExports(exports) {
2818
3077
  for (const fnName of EXPORT_FN_NAMES) if (typeof exports[fnName] !== "function") throw new Error(`Expected Function export "${fnName}" found ${exports[fnName]}`);
@@ -2821,8 +3080,8 @@ function verifyExports(exports) {
2821
3080
  var UnsafeWasmResolver = class {
2822
3081
  exports;
2823
3082
  flushCount = 0;
2824
- constructor(module$1) {
2825
- const { exports } = new WebAssembly.Instance(module$1, { wasm_msg: { wasm_msg_host_current_time: () => {
3083
+ constructor(module) {
3084
+ const { exports } = new WebAssembly.Instance(module, { wasm_msg: { wasm_msg_host_current_time: () => {
2826
3085
  const epochMillisecond = Date.now();
2827
3086
  const seconds = Math.floor(epochMillisecond / 1e3);
2828
3087
  const nanos = (epochMillisecond - 1e3 * seconds) * 1e6;
@@ -2846,23 +3105,28 @@ var UnsafeWasmResolver = class {
2846
3105
  }
2847
3106
  flushLogs() {
2848
3107
  const resPtr = this.exports.wasm_msg_guest_bounded_flush_logs(0);
2849
- const { data, error } = this.consume(resPtr, Response$1);
2850
- if (error) throw new Error(error);
3108
+ const { data, error: error$1 } = this.consume(resPtr, Response$1);
3109
+ if (error$1) throw new Error(error$1);
2851
3110
  return data;
2852
3111
  }
2853
3112
  flushAssigned() {
2854
3113
  const resPtr = this.exports.wasm_msg_guest_bounded_flush_assign(0);
2855
- const { data, error } = this.consume(resPtr, Response$1);
2856
- if (error) throw new Error(error);
3114
+ const { data, error: error$1 } = this.consume(resPtr, Response$1);
3115
+ if (error$1) throw new Error(error$1);
2857
3116
  return data;
2858
3117
  }
3118
+ applyFlags(request) {
3119
+ const reqPtr = this.transferRequest(request, ApplyFlagsRequest);
3120
+ const resPtr = this.exports.wasm_msg_guest_apply_flags(reqPtr);
3121
+ this.consumeResponse(resPtr, Void);
3122
+ }
2859
3123
  transferRequest(value, codec) {
2860
3124
  const data = codec.encode(value).finish();
2861
3125
  return this.transfer({ data }, Request);
2862
3126
  }
2863
3127
  consumeResponse(ptr, codec) {
2864
- const { data, error } = this.consume(ptr, Response$1);
2865
- if (error) throw new Error(error);
3128
+ const { data, error: error$1 } = this.consume(ptr, Response$1);
3129
+ if (error$1) throw new Error(error$1);
2866
3130
  return codec.decode(data);
2867
3131
  }
2868
3132
  transfer(data, codec) {
@@ -2885,18 +3149,18 @@ var UnsafeWasmResolver = class {
2885
3149
  this.exports.wasm_msg_free(ptr);
2886
3150
  }
2887
3151
  };
2888
- const DEFAULT_DELEGATE_FACTORY = (module$1) => new UnsafeWasmResolver(module$1);
3152
+ const DEFAULT_DELEGATE_FACTORY = (module) => new UnsafeWasmResolver(module);
2889
3153
  var WasmResolver = class {
2890
3154
  delegate;
2891
3155
  currentState;
2892
3156
  bufferedLogs = [];
2893
- constructor(module$1, delegateFactory = DEFAULT_DELEGATE_FACTORY) {
2894
- this.module = module$1;
3157
+ constructor(module, delegateFactory = DEFAULT_DELEGATE_FACTORY) {
3158
+ this.module = module;
2895
3159
  this.delegateFactory = delegateFactory;
2896
- this.delegate = delegateFactory(module$1);
3160
+ this.delegate = delegateFactory(module);
2897
3161
  }
2898
- reloadInstance(error) {
2899
- logger.error("Failure calling into wasm:", error);
3162
+ reloadInstance(error$1) {
3163
+ logger.error("Failure calling into wasm:", error$1);
2900
3164
  try {
2901
3165
  this.bufferedLogs.push(this.delegate.flushLogs());
2902
3166
  } catch (_) {
@@ -2908,46 +3172,57 @@ var WasmResolver = class {
2908
3172
  resolveWithSticky(request) {
2909
3173
  try {
2910
3174
  return this.delegate.resolveWithSticky(request);
2911
- } catch (error) {
2912
- if (error instanceof WebAssembly.RuntimeError) this.reloadInstance(error);
2913
- throw error;
3175
+ } catch (error$1) {
3176
+ if (error$1 instanceof WebAssembly.RuntimeError) this.reloadInstance(error$1);
3177
+ throw error$1;
2914
3178
  }
2915
3179
  }
2916
3180
  setResolverState(request) {
2917
3181
  this.currentState = request;
2918
3182
  try {
2919
3183
  this.delegate.setResolverState(request);
2920
- } catch (error) {
2921
- if (error instanceof WebAssembly.RuntimeError) this.reloadInstance(error);
2922
- throw error;
3184
+ } catch (error$1) {
3185
+ if (error$1 instanceof WebAssembly.RuntimeError) this.reloadInstance(error$1);
3186
+ throw error$1;
2923
3187
  }
2924
3188
  }
2925
3189
  flushLogs() {
2926
3190
  try {
2927
3191
  this.bufferedLogs.push(this.delegate.flushLogs());
2928
3192
  const len = this.bufferedLogs.reduce((sum, chunk) => sum + chunk.length, 0);
2929
- const buffer$1 = new Uint8Array(len);
3193
+ const buffer = new Uint8Array(len);
2930
3194
  let offset = 0;
2931
3195
  for (const chunk of this.bufferedLogs) {
2932
- buffer$1.set(chunk, offset);
3196
+ buffer.set(chunk, offset);
2933
3197
  offset += chunk.length;
2934
3198
  }
2935
3199
  this.bufferedLogs.length = 0;
2936
- return buffer$1;
2937
- } catch (error) {
2938
- if (error instanceof WebAssembly.RuntimeError) this.reloadInstance(error);
2939
- throw error;
3200
+ return buffer;
3201
+ } catch (error$1) {
3202
+ if (error$1 instanceof WebAssembly.RuntimeError) this.reloadInstance(error$1);
3203
+ throw error$1;
2940
3204
  }
2941
3205
  }
2942
3206
  flushAssigned() {
2943
3207
  return this.delegate.flushAssigned();
2944
3208
  }
3209
+ applyFlags(request) {
3210
+ try {
3211
+ this.delegate.applyFlags(request);
3212
+ } catch (error$1) {
3213
+ if (error$1 instanceof WebAssembly.RuntimeError) this.reloadInstance(error$1);
3214
+ throw error$1;
3215
+ }
3216
+ }
2945
3217
  };
2946
- const wasmPath = __require.resolve("./confidence_resolver.wasm");
2947
- const buffer = await fs.readFile(wasmPath);
2948
- const module = await WebAssembly.compile(buffer);
2949
- const resolver = new WasmResolver(module);
2950
- function createConfidenceServerProvider(options) {
3218
+ let resolver = null;
3219
+ function createConfidenceServerProvider({ wasmPath,...options }) {
3220
+ if (!resolver) resolver = createResolver(wasmPath ?? __require.resolve("./confidence_resolver.wasm"));
2951
3221
  return new ConfidenceServerProviderLocal(resolver, options);
2952
3222
  }
3223
+ async function createResolver(wasmPath) {
3224
+ const buffer = await fs.readFile(wasmPath);
3225
+ const module = await WebAssembly.compile(buffer);
3226
+ return new WasmResolver(module);
3227
+ }
2953
3228
  export { createConfidenceServerProvider };