@spotify-confidence/openfeature-server-provider-local 0.7.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.7.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,13 +2555,125 @@ 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;
@@ -2435,9 +2730,9 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2435
2730
  signal
2436
2731
  });
2437
2732
  scheduleWithFixedInterval((signal$1) => this.updateState(signal$1), this.stateUpdateInterval, { signal });
2438
- this.status = "READY";
2733
+ this.status = castStringToEnum("READY");
2439
2734
  } catch (e) {
2440
- this.status = "ERROR";
2735
+ this.status = castStringToEnum("ERROR");
2441
2736
  throw e;
2442
2737
  }
2443
2738
  }
@@ -2445,34 +2740,33 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2445
2740
  await this.flush(timeoutSignal(3e3));
2446
2741
  this.main.abort();
2447
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
+ }
2448
2765
  async evaluate(flagKey, defaultValue, context) {
2449
2766
  try {
2450
- const [flagName, ...path] = flagKey.split(".");
2451
- const stickyRequest = {
2452
- resolveRequest: {
2453
- flags: [`flags/${flagName}`],
2454
- evaluationContext: ConfidenceServerProviderLocal.convertEvaluationContext(context),
2455
- apply: true,
2456
- clientSecret: this.options.flagClientSecret,
2457
- sdk: {
2458
- id: SdkId.SDK_ID_JS_LOCAL_SERVER_PROVIDER,
2459
- version: VERSION
2460
- }
2461
- },
2462
- materializations: [],
2463
- failFastOnSticky: false,
2464
- notProcessSticky: false
2465
- };
2466
- const response = await this.resolveWithSticky(stickyRequest);
2467
- return this.extractValue(response.resolvedFlags[0], flagName, path, defaultValue);
2468
- } catch (e) {
2469
- logger$1.warn(`Flag evaluation for '${flagKey}' failed`, e);
2470
- return {
2471
- value: defaultValue,
2472
- reason: "ERROR",
2473
- errorCode: castStringToEnum("GENERAL"),
2474
- errorMessage: String(e)
2475
- };
2767
+ const [flagName] = flagKey.split(".", 1);
2768
+ const resolution = await this.resolve(context, [flagName], true);
2769
+ return resolve(resolution, flagKey, defaultValue, logger$1);
2476
2770
  } finally {
2477
2771
  this.flushAssigned();
2478
2772
  }
@@ -2491,36 +2785,6 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2491
2785
  if (storeVariantOp.length) this.writeMaterializations({ storeVariantOp });
2492
2786
  return ResolveFlagsResponse.create(resolveResponse);
2493
2787
  }
2494
- extractValue(flag, flagName, path, defaultValue) {
2495
- if (!flag) return {
2496
- value: defaultValue,
2497
- reason: "ERROR",
2498
- errorCode: castStringToEnum("FLAG_NOT_FOUND")
2499
- };
2500
- if (flag.reason !== ResolveReason.RESOLVE_REASON_MATCH) return {
2501
- value: defaultValue,
2502
- reason: ConfidenceServerProviderLocal.convertReason(flag.reason)
2503
- };
2504
- let value = flag.value;
2505
- for (const step of path) {
2506
- if (typeof value !== "object" || value === null || !hasKey(value, step)) return {
2507
- value: defaultValue,
2508
- reason: "ERROR",
2509
- errorCode: castStringToEnum("TYPE_MISMATCH")
2510
- };
2511
- value = value[step];
2512
- }
2513
- if (!isAssignableTo(value, defaultValue)) return {
2514
- value: defaultValue,
2515
- reason: "ERROR",
2516
- errorCode: castStringToEnum("TYPE_MISMATCH")
2517
- };
2518
- return {
2519
- value,
2520
- reason: "MATCH",
2521
- variant: flag.variant
2522
- };
2523
- }
2524
2788
  async updateState(signal) {
2525
2789
  const cdnUrl = `https://confidence-resolver-state-cdn.spotifycdn.com/${await sha256Hex(this.options.flagClientSecret)}`;
2526
2790
  const headers = new Headers();
@@ -2578,17 +2842,6 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2578
2842
  }
2579
2843
  throw new Error("Write materialization not supported");
2580
2844
  }
2581
- static convertReason(reason) {
2582
- switch (reason) {
2583
- case ResolveReason.RESOLVE_REASON_ERROR: return "ERROR";
2584
- case ResolveReason.RESOLVE_REASON_FLAG_ARCHIVED: return "FLAG_ARCHIVED";
2585
- case ResolveReason.RESOLVE_REASON_MATCH: return "MATCH";
2586
- case ResolveReason.RESOLVE_REASON_NO_SEGMENT_MATCH: return "NO_SEGMENT_MATCH";
2587
- case ResolveReason.RESOLVE_REASON_TARGETING_KEY_ERROR: return "TARGETING_KEY_ERROR";
2588
- case ResolveReason.RESOLVE_REASON_NO_TREATMENT_MATCH: return "NO_TREATMENT_MATCH";
2589
- default: return "UNSPECIFIED";
2590
- }
2591
- }
2592
2845
  static convertEvaluationContext({ targetingKey: targeting_key,...rest }) {
2593
2846
  return {
2594
2847
  targeting_key,
@@ -2607,23 +2860,23 @@ var ConfidenceServerProviderLocal = class ConfidenceServerProviderLocal {
2607
2860
  resolveStringEvaluation(flagKey, defaultValue, context) {
2608
2861
  return Promise.resolve(this.evaluate(flagKey, defaultValue, context));
2609
2862
  }
2610
- };
2611
- function isAssignableTo(value, schema) {
2612
- if (typeof schema !== typeof value) return false;
2613
- if (typeof value === "object" && typeof schema === "object") {
2614
- if (schema === null) return value === null;
2615
- if (Array.isArray(schema)) {
2616
- if (!Array.isArray(value)) return false;
2617
- if (schema.length == 0) return true;
2618
- return value.every((item) => isAssignableTo(item, schema[0]));
2619
- }
2620
- for (const [key, schemaValue] of Object.entries(schema)) {
2621
- if (!hasKey(value, key)) return false;
2622
- if (!isAssignableTo(value[key], schemaValue)) return false;
2623
- }
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);
2624
2878
  }
2625
- return true;
2626
- }
2879
+ };
2627
2880
  function createBaseResolveWithStickyRequest() {
2628
2881
  return {
2629
2882
  resolveRequest: void 0,
@@ -2817,7 +3070,8 @@ const EXPORT_FN_NAMES = [
2817
3070
  "wasm_msg_guest_resolve_with_sticky",
2818
3071
  "wasm_msg_guest_set_resolver_state",
2819
3072
  "wasm_msg_guest_bounded_flush_logs",
2820
- "wasm_msg_guest_bounded_flush_assign"
3073
+ "wasm_msg_guest_bounded_flush_assign",
3074
+ "wasm_msg_guest_apply_flags"
2821
3075
  ];
2822
3076
  function verifyExports(exports) {
2823
3077
  for (const fnName of EXPORT_FN_NAMES) if (typeof exports[fnName] !== "function") throw new Error(`Expected Function export "${fnName}" found ${exports[fnName]}`);
@@ -2851,23 +3105,28 @@ var UnsafeWasmResolver = class {
2851
3105
  }
2852
3106
  flushLogs() {
2853
3107
  const resPtr = this.exports.wasm_msg_guest_bounded_flush_logs(0);
2854
- const { data, error } = this.consume(resPtr, Response$1);
2855
- 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);
2856
3110
  return data;
2857
3111
  }
2858
3112
  flushAssigned() {
2859
3113
  const resPtr = this.exports.wasm_msg_guest_bounded_flush_assign(0);
2860
- const { data, error } = this.consume(resPtr, Response$1);
2861
- 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);
2862
3116
  return data;
2863
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
+ }
2864
3123
  transferRequest(value, codec) {
2865
3124
  const data = codec.encode(value).finish();
2866
3125
  return this.transfer({ data }, Request);
2867
3126
  }
2868
3127
  consumeResponse(ptr, codec) {
2869
- const { data, error } = this.consume(ptr, Response$1);
2870
- 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);
2871
3130
  return codec.decode(data);
2872
3131
  }
2873
3132
  transfer(data, codec) {
@@ -2900,8 +3159,8 @@ var WasmResolver = class {
2900
3159
  this.delegateFactory = delegateFactory;
2901
3160
  this.delegate = delegateFactory(module);
2902
3161
  }
2903
- reloadInstance(error) {
2904
- logger.error("Failure calling into wasm:", error);
3162
+ reloadInstance(error$1) {
3163
+ logger.error("Failure calling into wasm:", error$1);
2905
3164
  try {
2906
3165
  this.bufferedLogs.push(this.delegate.flushLogs());
2907
3166
  } catch (_) {
@@ -2913,18 +3172,18 @@ var WasmResolver = class {
2913
3172
  resolveWithSticky(request) {
2914
3173
  try {
2915
3174
  return this.delegate.resolveWithSticky(request);
2916
- } catch (error) {
2917
- if (error instanceof WebAssembly.RuntimeError) this.reloadInstance(error);
2918
- throw error;
3175
+ } catch (error$1) {
3176
+ if (error$1 instanceof WebAssembly.RuntimeError) this.reloadInstance(error$1);
3177
+ throw error$1;
2919
3178
  }
2920
3179
  }
2921
3180
  setResolverState(request) {
2922
3181
  this.currentState = request;
2923
3182
  try {
2924
3183
  this.delegate.setResolverState(request);
2925
- } catch (error) {
2926
- if (error instanceof WebAssembly.RuntimeError) this.reloadInstance(error);
2927
- throw error;
3184
+ } catch (error$1) {
3185
+ if (error$1 instanceof WebAssembly.RuntimeError) this.reloadInstance(error$1);
3186
+ throw error$1;
2928
3187
  }
2929
3188
  }
2930
3189
  flushLogs() {
@@ -2939,14 +3198,22 @@ var WasmResolver = class {
2939
3198
  }
2940
3199
  this.bufferedLogs.length = 0;
2941
3200
  return buffer;
2942
- } catch (error) {
2943
- if (error instanceof WebAssembly.RuntimeError) this.reloadInstance(error);
2944
- throw error;
3201
+ } catch (error$1) {
3202
+ if (error$1 instanceof WebAssembly.RuntimeError) this.reloadInstance(error$1);
3203
+ throw error$1;
2945
3204
  }
2946
3205
  }
2947
3206
  flushAssigned() {
2948
3207
  return this.delegate.flushAssigned();
2949
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
+ }
2950
3217
  };
2951
3218
  let resolver = null;
2952
3219
  function createConfidenceServerProvider({ wasmPath,...options }) {