@configdirector/nuxt-sdk 1.10.0 → 1.11.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/dist/module.d.mts +76 -15
- package/dist/module.json +1 -1
- package/dist/module.mjs +13 -4
- package/dist/runtime/app/composables/useConfigDirectorClient.d.mts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorClient.d.ts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorClientHooks.d.mts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorClientHooks.d.ts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorContext.d.mts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorContext.d.ts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorStatus.d.mts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorStatus.d.ts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorValue.d.mts +2 -2
- package/dist/runtime/app/composables/useConfigDirectorValue.d.ts +2 -2
- package/dist/runtime/{types-IPLvRsUO.d.mts → native-values-BV2k_xR2.d.mts} +11 -1
- package/dist/runtime/native-values-DZJjFBvk.mjs +116 -0
- package/dist/runtime/nitro/middleware.mjs +5 -1
- package/dist/runtime/nitro/offline-values.d.mts +7 -0
- package/dist/runtime/nitro/offline-values.d.ts +7 -0
- package/dist/runtime/nitro/offline-values.mjs +15 -0
- package/dist/runtime/nitro/plugin.d.mts +3 -1
- package/dist/runtime/nitro/plugin.d.ts +3 -1
- package/dist/runtime/nitro/plugin.mjs +232 -83
- package/dist/runtime/plugin.client.mjs +341 -86
- package/dist/runtime/server/composables/useConfigDirectorServerClient.d.mts +6 -0
- package/dist/runtime/server/composables/useConfigDirectorServerClient.d.ts +6 -0
- package/dist/runtime/server/composables/{useConfigDirectorClient.mjs → useConfigDirectorServerClient.mjs} +3 -3
- package/dist/runtime/server/composables/useConfigDirectorServerHooks.d.mts +1 -1
- package/dist/runtime/server/composables/useConfigDirectorServerHooks.d.ts +1 -1
- package/dist/runtime/{types-B9_4pADA.d.mts → types-CS7AMNWe.d.mts} +1 -1
- package/dist/runtime/{types-DQhBe4Ei.d.mts → types-Dt3bENKf.d.mts} +1 -1
- package/dist/testing.d.mts +13 -13
- package/dist/testing.mjs +292 -156
- package/package.json +1 -1
- package/dist/runtime/server/composables/useConfigDirectorClient.d.mts +0 -6
- package/dist/runtime/server/composables/useConfigDirectorClient.d.ts +0 -6
- /package/dist/runtime/{types-F0fKKk6-.d.mts → types-C30VJ25l.d.mts} +0 -0
|
@@ -491,6 +491,183 @@ var StreamingTransport = class {
|
|
|
491
491
|
}
|
|
492
492
|
};
|
|
493
493
|
//#endregion
|
|
494
|
+
//#region ../shared/src/native-values.ts
|
|
495
|
+
const encodeNativeValue = (key, value) => {
|
|
496
|
+
if (key.trim().length == 0) throw new ConfigDirectorValidationError("Invalid config key. The key of a value cannot be empty.");
|
|
497
|
+
return encode(key, value);
|
|
498
|
+
};
|
|
499
|
+
const encode = (key, value) => {
|
|
500
|
+
switch (typeof value) {
|
|
501
|
+
case "boolean": return {
|
|
502
|
+
type: "boolean",
|
|
503
|
+
value: value ? "true" : "false"
|
|
504
|
+
};
|
|
505
|
+
case "number": return encodeNumber(key, value);
|
|
506
|
+
case "string": return {
|
|
507
|
+
type: "string",
|
|
508
|
+
value
|
|
509
|
+
};
|
|
510
|
+
case "object": if (value !== null) {
|
|
511
|
+
assertJsonContents(key, value, "");
|
|
512
|
+
return {
|
|
513
|
+
type: "json",
|
|
514
|
+
value: JSON.stringify(value)
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
throw new ConfigDirectorValidationError(`Invalid value for '${key}': ${describe(value)}. Use a boolean, a number, a string, a plain object, or an array.`);
|
|
519
|
+
};
|
|
520
|
+
const encodeNumber = (key, value) => {
|
|
521
|
+
if (!Number.isFinite(value)) throw new ConfigDirectorValidationError(`Invalid value for '${key}': ${describe(value)} is not a finite number.`);
|
|
522
|
+
if (Number.isInteger(value)) {
|
|
523
|
+
if (!Number.isSafeInteger(value)) throw new ConfigDirectorValidationError(`Invalid value for '${key}': ${value} is not a safe integer, so the SDK could not read it back exactly.`);
|
|
524
|
+
return {
|
|
525
|
+
type: "integer",
|
|
526
|
+
value: String(value)
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
return {
|
|
530
|
+
type: "float",
|
|
531
|
+
value: toPlainDecimal(value)
|
|
532
|
+
};
|
|
533
|
+
};
|
|
534
|
+
const toPlainDecimal = (value) => {
|
|
535
|
+
const text = String(value);
|
|
536
|
+
const exponentIndex = text.indexOf("e-");
|
|
537
|
+
if (exponentIndex < 0) return text;
|
|
538
|
+
const sign = text.startsWith("-") ? "-" : "";
|
|
539
|
+
const [integerDigits = "", fractionDigits = ""] = text.slice(sign.length, exponentIndex).split(".");
|
|
540
|
+
const leadingZeros = Number(text.slice(exponentIndex + 2)) - integerDigits.length;
|
|
541
|
+
return `${sign}0.${"0".repeat(leadingZeros)}${integerDigits}${fractionDigits}`;
|
|
542
|
+
};
|
|
543
|
+
const assertJsonContents = (key, value, path) => {
|
|
544
|
+
if (value === null || typeof value === "boolean" || typeof value === "string") return;
|
|
545
|
+
if (typeof value === "number") {
|
|
546
|
+
if (!Number.isFinite(value)) throw invalidJsonContents(key, path, `${describe(value)} is not a finite number`);
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
if (Array.isArray(value)) {
|
|
550
|
+
value.forEach((item, index) => assertJsonContents(key, item, `${path}[${index}]`));
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
if (isPlainObject$1(value)) {
|
|
554
|
+
for (const [property, item] of Object.entries(value)) assertJsonContents(key, item, path ? `${path}.${property}` : property);
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
throw invalidJsonContents(key, path, `${describe(value)} cannot be encoded as JSON`);
|
|
558
|
+
};
|
|
559
|
+
const invalidJsonContents = (key, path, problem) => new ConfigDirectorValidationError(`Invalid value for '${key}'${path ? ` at '${path}'` : ""}: ${problem}. JSON contents can hold booleans, finite numbers, strings, null, arrays, and plain objects.`);
|
|
560
|
+
const isPlainObject$1 = (value) => {
|
|
561
|
+
if (typeof value !== "object" || value === null) return false;
|
|
562
|
+
const prototype = Object.getPrototypeOf(value);
|
|
563
|
+
return prototype === Object.prototype || prototype === null;
|
|
564
|
+
};
|
|
565
|
+
const describe = (value) => {
|
|
566
|
+
if (value === null) return "null";
|
|
567
|
+
if (typeof value === "function") return "a function";
|
|
568
|
+
if (typeof value === "object") return `a ${value.constructor?.name ?? "object"} instance`;
|
|
569
|
+
if (typeof value === "symbol") return "a symbol";
|
|
570
|
+
return String(value);
|
|
571
|
+
};
|
|
572
|
+
//#endregion
|
|
573
|
+
//#region ../js-client-core/src/native-values.ts
|
|
574
|
+
const nativeValueConfigState = (id, key, value, valueId) => {
|
|
575
|
+
const encoded = encodeNativeValue(key, value);
|
|
576
|
+
return {
|
|
577
|
+
id,
|
|
578
|
+
key,
|
|
579
|
+
type: encoded.type,
|
|
580
|
+
value: encoded.value,
|
|
581
|
+
valueId
|
|
582
|
+
};
|
|
583
|
+
};
|
|
584
|
+
//#endregion
|
|
585
|
+
//#region ../js-client-core/src/OfflineTransport.ts
|
|
586
|
+
const OFFLINE_ENVIRONMENT = {
|
|
587
|
+
environmentId: "offline",
|
|
588
|
+
projectId: "offline"
|
|
589
|
+
};
|
|
590
|
+
var OfflineTransport = class {
|
|
591
|
+
emitter = new Emitter();
|
|
592
|
+
constructor(source) {
|
|
593
|
+
this.source = source;
|
|
594
|
+
}
|
|
595
|
+
async connect() {
|
|
596
|
+
const configs = loadOfflineConfigs(this.source);
|
|
597
|
+
this.emitter.emit("configSetReceived", {
|
|
598
|
+
...OFFLINE_ENVIRONMENT,
|
|
599
|
+
kind: "full",
|
|
600
|
+
configs
|
|
601
|
+
});
|
|
602
|
+
return this;
|
|
603
|
+
}
|
|
604
|
+
on = (name, handler) => this.emitter.on(name, handler);
|
|
605
|
+
off = (name, handler) => this.emitter.off(name, handler);
|
|
606
|
+
clear() {
|
|
607
|
+
this.emitter.clear();
|
|
608
|
+
}
|
|
609
|
+
close() {}
|
|
610
|
+
dispose() {
|
|
611
|
+
this.clear();
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
const loadOfflineConfigs = (source) => {
|
|
615
|
+
switch (source.kind) {
|
|
616
|
+
case "in-code-defaults": return {};
|
|
617
|
+
case "values": return encodeOfflineValues(source.values);
|
|
618
|
+
case "rejected": throw new ConfigDirectorInitializationError(source.message);
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
const encodeOfflineValues = (values) => {
|
|
622
|
+
try {
|
|
623
|
+
return Object.fromEntries(Object.entries(values).map(([key, value]) => [key, nativeValueConfigState(`offline:${key}`, key, value, void 0)]));
|
|
624
|
+
} catch (error) {
|
|
625
|
+
if (error instanceof ConfigDirectorValidationError) throw new ConfigDirectorInitializationError(`The offline values could not be loaded. ${error.message}`);
|
|
626
|
+
throw error;
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
//#endregion
|
|
630
|
+
//#region ../shared/src/constants.ts
|
|
631
|
+
const CLIENT_BASE_URL = "https://client-sdk-api.configdirector.com";
|
|
632
|
+
//#endregion
|
|
633
|
+
//#region ../js-client-core/src/connection-plan.ts
|
|
634
|
+
const planConnection = (clientSdkKey, connection, urlFactory) => {
|
|
635
|
+
if (connection?.mode === "offline") return {
|
|
636
|
+
kind: "stay-offline",
|
|
637
|
+
source: offlineSourceOf(connection)
|
|
638
|
+
};
|
|
639
|
+
const mode = connection?.mode ?? "streaming";
|
|
640
|
+
if (!clientSdkKey || clientSdkKey.trim().length == 0) throw new ConfigDirectorValidationError("No client SDK key was provided, the client cannot be instantiated without a valid client SDK key");
|
|
641
|
+
if (connection?.values !== void 0) return {
|
|
642
|
+
kind: "stay-offline",
|
|
643
|
+
source: {
|
|
644
|
+
kind: "rejected",
|
|
645
|
+
message: `The connection option 'values' applies only when the connection mode is 'offline', but the mode is '${mode}'.`
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
return {
|
|
649
|
+
kind: "connect",
|
|
650
|
+
mode,
|
|
651
|
+
clientSdkKey,
|
|
652
|
+
baseUrl: baseUrlOf(connection?.url, urlFactory)
|
|
653
|
+
};
|
|
654
|
+
};
|
|
655
|
+
const baseUrlOf = (url, urlFactory) => {
|
|
656
|
+
if (!url) return CLIENT_BASE_URL;
|
|
657
|
+
try {
|
|
658
|
+
return urlFactory(url);
|
|
659
|
+
} catch (error) {
|
|
660
|
+
throw new ConfigDirectorValidationError(`Invalid base URL '${url}'. Parsing failed: ${error}`);
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
const offlineSourceOf = (connection) => {
|
|
664
|
+
if (connection.values !== void 0) return {
|
|
665
|
+
kind: "values",
|
|
666
|
+
values: connection.values
|
|
667
|
+
};
|
|
668
|
+
return { kind: "in-code-defaults" };
|
|
669
|
+
};
|
|
670
|
+
//#endregion
|
|
494
671
|
//#region ../shared/src/value-parser.ts
|
|
495
672
|
const getRequestedType = (defaultValue) => {
|
|
496
673
|
const baseType = typeof defaultValue;
|
|
@@ -710,16 +887,16 @@ const createDefaultLogger$1 = (level, messageDecorator) => {
|
|
|
710
887
|
return new DefaultConsoleLogger(level ?? "warn", messageDecorator ?? new LogMessageDecorator());
|
|
711
888
|
};
|
|
712
889
|
//#endregion
|
|
890
|
+
//#region ../js-client-core/src/telemetry/discarding.ts
|
|
891
|
+
const discardingTelemetryClient = {
|
|
892
|
+
updateContext: async () => {},
|
|
893
|
+
evaluatedConfig: () => {},
|
|
894
|
+
recordInvalidContext: () => {},
|
|
895
|
+
close: async () => {}
|
|
896
|
+
};
|
|
897
|
+
//#endregion
|
|
713
898
|
//#region ../shared/src/url.ts
|
|
714
899
|
const defaultUrlFactory = (input, base) => new URL(input, base?.toString());
|
|
715
|
-
const parseUrl = (url) => {
|
|
716
|
-
if (!url) return;
|
|
717
|
-
try {
|
|
718
|
-
return new URL(url);
|
|
719
|
-
} catch (error) {
|
|
720
|
-
throw new ConfigDirectorValidationError(`Invalid URL '${url}'. Parsing failed: ${error}`);
|
|
721
|
-
}
|
|
722
|
-
};
|
|
723
900
|
//#endregion
|
|
724
901
|
//#region ../shared/src/transport/pollingInterval.ts
|
|
725
902
|
const resolvePollingInterval = (configuredSeconds, defaults) => {
|
|
@@ -1078,7 +1255,7 @@ const admitContext = (context) => {
|
|
|
1078
1255
|
//#endregion
|
|
1079
1256
|
//#region ../js-client-core/src/DefaultConfigDirectorClient.ts
|
|
1080
1257
|
const MAX_EXPONENTIAL_DELAY = 9;
|
|
1081
|
-
var DefaultConfigDirectorClient = class {
|
|
1258
|
+
var DefaultConfigDirectorClient = class DefaultConfigDirectorClient {
|
|
1082
1259
|
logger;
|
|
1083
1260
|
telemetryClient;
|
|
1084
1261
|
configSet;
|
|
@@ -1093,18 +1270,20 @@ var DefaultConfigDirectorClient = class {
|
|
|
1093
1270
|
readyPromise;
|
|
1094
1271
|
readyResolve;
|
|
1095
1272
|
currentContext;
|
|
1096
|
-
|
|
1273
|
+
connectionPlan;
|
|
1097
1274
|
clientSession;
|
|
1098
|
-
|
|
1275
|
+
static from(liveTelemetryClient, clientSdkKeyOrOptions, sdkOptions, clientOptions) {
|
|
1276
|
+
if (typeof clientSdkKeyOrOptions === "object") return new DefaultConfigDirectorClient(liveTelemetryClient, void 0, sdkOptions, clientSdkKeyOrOptions);
|
|
1277
|
+
return new DefaultConfigDirectorClient(liveTelemetryClient, clientSdkKeyOrOptions, sdkOptions, clientOptions);
|
|
1278
|
+
}
|
|
1279
|
+
constructor(liveTelemetryClient, clientSdkKey, sdkOptions, clientOptions, internalClientOptions) {
|
|
1099
1280
|
this.logger = clientOptions?.logger ?? createDefaultLogger$1();
|
|
1100
1281
|
this.clientSession = resolveClientSession(this.logger, internalClientOptions?.instanceIdStorage);
|
|
1101
1282
|
this.timeout = clientOptions?.connection?.timeout ?? 3e3;
|
|
1102
|
-
this.validateSdkKeyPresence(clientSdkKey);
|
|
1103
1283
|
const urlFactory = internalClientOptions?.urlFactory ?? defaultUrlFactory;
|
|
1104
|
-
|
|
1105
|
-
this.
|
|
1106
|
-
this.
|
|
1107
|
-
this.transport = internalClientOptions?.transport ?? this.buildTransport(clientSdkKey, sdkOptions, baseUrl, urlFactory, clientOptions, internalClientOptions);
|
|
1284
|
+
this.connectionPlan = planConnection(clientSdkKey, clientOptions?.connection, urlFactory);
|
|
1285
|
+
this.telemetryClient = this.buildTelemetryClient(liveTelemetryClient, clientOptions);
|
|
1286
|
+
this.transport = internalClientOptions?.transport ?? this.buildTransport(sdkOptions, clientOptions, urlFactory, internalClientOptions);
|
|
1108
1287
|
this.transport.on("configSetReceived", (configSet) => {
|
|
1109
1288
|
this.hasReceivedConfigSet = true;
|
|
1110
1289
|
this.readyResolve?.();
|
|
@@ -1141,8 +1320,8 @@ var DefaultConfigDirectorClient = class {
|
|
|
1141
1320
|
const handlers = Array.isArray(handler) ? handler : [handler];
|
|
1142
1321
|
for (const h of handlers) if (typeof h === "function") this.on(event, h);
|
|
1143
1322
|
}
|
|
1144
|
-
|
|
1145
|
-
if (
|
|
1323
|
+
pollingIntervalFor(mode, configuredSeconds) {
|
|
1324
|
+
if (mode !== "polling") return;
|
|
1146
1325
|
const resolved = resolvePollingInterval(configuredSeconds, {
|
|
1147
1326
|
defaultSeconds: 60,
|
|
1148
1327
|
minimumSeconds: 30
|
|
@@ -1150,31 +1329,47 @@ var DefaultConfigDirectorClient = class {
|
|
|
1150
1329
|
if (resolved.warning) this.logger.warn(`[ConfigDirectorClient] ${resolved.warning}`);
|
|
1151
1330
|
return resolved.seconds;
|
|
1152
1331
|
}
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1332
|
+
buildTelemetryClient(liveTelemetryClient, clientOptions) {
|
|
1333
|
+
const plan = this.connectionPlan;
|
|
1334
|
+
switch (plan.kind) {
|
|
1335
|
+
case "stay-offline": return discardingTelemetryClient;
|
|
1336
|
+
case "connect": return liveTelemetryClient({
|
|
1337
|
+
clientSdkKey: plan.clientSdkKey,
|
|
1338
|
+
baseUrl: plan.baseUrl,
|
|
1339
|
+
logger: this.logger,
|
|
1340
|
+
metadata: clientOptions?.metadata
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
buildTransport(sdkOptions, clientOptions, urlFactory, internalClientOptions) {
|
|
1345
|
+
const plan = this.connectionPlan;
|
|
1346
|
+
switch (plan.kind) {
|
|
1347
|
+
case "stay-offline": return new OfflineTransport(plan.source);
|
|
1348
|
+
case "connect": return new (this.getTransportConstructor(plan.mode))({
|
|
1349
|
+
clientSession: this.clientSession,
|
|
1350
|
+
clientSdkKey: plan.clientSdkKey,
|
|
1351
|
+
baseUrl: plan.baseUrl,
|
|
1352
|
+
resolveUrl: urlFactory,
|
|
1353
|
+
metaContext: {
|
|
1354
|
+
...clientOptions?.metadata,
|
|
1355
|
+
sdkName: sdkOptions.sdkName,
|
|
1356
|
+
sdkVersion: sdkOptions.sdkVersion,
|
|
1357
|
+
userAgent: readUserAgent(),
|
|
1358
|
+
host: readHost()
|
|
1359
|
+
},
|
|
1360
|
+
logger: this.logger,
|
|
1361
|
+
fetch: internalClientOptions?.fetch,
|
|
1362
|
+
connectionRetryDelay: internalClientOptions?.connectionRetryDelay ?? ((attempt) => {
|
|
1363
|
+
return Math.pow(2, Math.min(attempt, MAX_EXPONENTIAL_DELAY)) * 1e3;
|
|
1364
|
+
}),
|
|
1365
|
+
pollingInterval: this.pollingIntervalFor(plan.mode, clientOptions?.connection?.pollingInterval)
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1173
1368
|
}
|
|
1174
|
-
getTransportConstructor(
|
|
1175
|
-
switch (
|
|
1369
|
+
getTransportConstructor(mode) {
|
|
1370
|
+
switch (mode) {
|
|
1176
1371
|
case "polling": return PollingTransport;
|
|
1177
|
-
|
|
1372
|
+
case "streaming": return StreamingTransport;
|
|
1178
1373
|
}
|
|
1179
1374
|
}
|
|
1180
1375
|
async initialize(context) {
|
|
@@ -1182,17 +1377,28 @@ var DefaultConfigDirectorClient = class {
|
|
|
1182
1377
|
await this.submitContext(context, "initialization");
|
|
1183
1378
|
}
|
|
1184
1379
|
async updateContext(context) {
|
|
1185
|
-
|
|
1380
|
+
switch (this.connectionPlan.kind) {
|
|
1381
|
+
case "connect":
|
|
1382
|
+
await this.submitContext(context, "context update");
|
|
1383
|
+
return;
|
|
1384
|
+
case "stay-offline":
|
|
1385
|
+
this.storeContext(this.admittedContextFor(context, "context update"));
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
storeContext(context) {
|
|
1390
|
+
this.currentContext = context;
|
|
1391
|
+
this.emit("contextUpdated", { context });
|
|
1186
1392
|
}
|
|
1187
1393
|
async submitContext(context, submission) {
|
|
1188
|
-
await this.connectToTransport(this.
|
|
1394
|
+
await this.connectToTransport(this.admittedContextFor(context, submission), submission);
|
|
1189
1395
|
}
|
|
1190
|
-
|
|
1396
|
+
admittedContextFor(suppliedContext, submission) {
|
|
1191
1397
|
const admission = admitContext(suppliedContext);
|
|
1192
1398
|
switch (admission.outcome) {
|
|
1193
1399
|
case "admitted": return admission.context;
|
|
1194
1400
|
case "ignored":
|
|
1195
|
-
this.logger.error(`[ConfigDirectorClient] Ignored the context supplied for ${submission} because its kind '${admission.kindSample}' is invalid;
|
|
1401
|
+
this.logger.error(`[ConfigDirectorClient] Ignored the context supplied for ${submission} because its kind '${admission.kindSample}' is invalid; continuing as if no context was supplied. A context kind has 1 to 64 characters, using only lowercase letters, digits, '-' and '_'.`);
|
|
1196
1402
|
this.telemetryClient.recordInvalidContext(admission.kindSample);
|
|
1197
1403
|
return;
|
|
1198
1404
|
}
|
|
@@ -1224,11 +1430,21 @@ var DefaultConfigDirectorClient = class {
|
|
|
1224
1430
|
if (remainingTimeout > 0) await Promise.race([this.readyPromise, new Promise((resolve) => {
|
|
1225
1431
|
this.timeoutTimer = setTimeout(() => resolve(), remainingTimeout);
|
|
1226
1432
|
})]).finally(() => clearTimeout(this.timeoutTimer));
|
|
1227
|
-
if (!this.ready) this.logger.warn(`[ConfigDirectorClient] Timed out waiting for ${caller} after ${this.timeout}ms.
|
|
1433
|
+
if (!this.ready) this.logger.warn(`[ConfigDirectorClient] Timed out waiting for ${caller} after ${this.timeout}ms. ${this.timeoutWarningDetails()}`);
|
|
1228
1434
|
} catch (error) {
|
|
1435
|
+
if (error instanceof ConfigDirectorInitializationError) {
|
|
1436
|
+
this.initializing = false;
|
|
1437
|
+
throw error;
|
|
1438
|
+
}
|
|
1229
1439
|
this.logger.error(`[ConfigDirectorClient] An error occurred during ${caller}: `, error);
|
|
1230
1440
|
}
|
|
1231
1441
|
}
|
|
1442
|
+
timeoutWarningDetails() {
|
|
1443
|
+
switch (this.connectionPlan.kind) {
|
|
1444
|
+
case "connect": return "The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds.";
|
|
1445
|
+
case "stay-offline": return "The offline values were not delivered, so configs return the default value.";
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1232
1448
|
findKeysRemovedBy(configSet) {
|
|
1233
1449
|
if (!this.configSet || configSet.kind != "full") return [];
|
|
1234
1450
|
return Object.keys(this.configSet.configs).filter((key) => !Object.prototype.hasOwnProperty.call(configSet.configs, key));
|
|
@@ -1323,17 +1539,6 @@ var DefaultConfigDirectorClient = class {
|
|
|
1323
1539
|
this.logger.error(`[ConfigDirectorClient] Error executing event handlers for '${name}'`, error);
|
|
1324
1540
|
}
|
|
1325
1541
|
}
|
|
1326
|
-
parseUrl(url, urlFactory) {
|
|
1327
|
-
if (!url) return;
|
|
1328
|
-
try {
|
|
1329
|
-
return urlFactory(url);
|
|
1330
|
-
} catch (error) {
|
|
1331
|
-
throw new ConfigDirectorValidationError(`Invalid base URL '${url}'. Parsing failed: ${error}`);
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
validateSdkKeyPresence(sdkKey) {
|
|
1335
|
-
if (!sdkKey || sdkKey.trim().length == 0) throw new ConfigDirectorValidationError("No client SDK key was provided, the client cannot be instantiated without a valid client SDK key");
|
|
1336
|
-
}
|
|
1337
1542
|
validateDefaultValue(defaultValue) {
|
|
1338
1543
|
if (defaultValue === void 0 || defaultValue === null) throw new ConfigDirectorValidationError("Invalid default value. The default value for a config must be defined and non-null.");
|
|
1339
1544
|
if (typeof defaultValue === "function") throw new ConfigDirectorValidationError("Invalid default value. The default value for a config cannot be a function.");
|
|
@@ -1359,14 +1564,24 @@ var DefaultConfigDirectorClient = class {
|
|
|
1359
1564
|
this.handlersMap.clear();
|
|
1360
1565
|
}
|
|
1361
1566
|
pauseNetwork() {
|
|
1362
|
-
this.
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1567
|
+
switch (this.connectionPlan.kind) {
|
|
1568
|
+
case "stay-offline": return;
|
|
1569
|
+
case "connect":
|
|
1570
|
+
this.logger.debug("[ConfigDirectorClient] pauseNetwork() called, pausing transport connection");
|
|
1571
|
+
clearTimeout(this.timeoutTimer);
|
|
1572
|
+
this.timeoutTimer = void 0;
|
|
1573
|
+
this.transport.close();
|
|
1574
|
+
this.ready = false;
|
|
1575
|
+
return;
|
|
1576
|
+
}
|
|
1367
1577
|
}
|
|
1368
1578
|
async resumeNetwork() {
|
|
1369
|
-
|
|
1579
|
+
switch (this.connectionPlan.kind) {
|
|
1580
|
+
case "stay-offline": return;
|
|
1581
|
+
case "connect":
|
|
1582
|
+
await this.connectToTransport(this.currentContext, "network resume");
|
|
1583
|
+
return;
|
|
1584
|
+
}
|
|
1370
1585
|
}
|
|
1371
1586
|
async close() {
|
|
1372
1587
|
this.logger.debug("[ConfigDirectorClient] close() has been called, closing connection to server");
|
|
@@ -1665,27 +1880,28 @@ const generateValueId = async (v) => {
|
|
|
1665
1880
|
};
|
|
1666
1881
|
//#endregion
|
|
1667
1882
|
//#region ../js-browser-client/src/BrowserConfigDirectorClient.ts
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1883
|
+
/**
|
|
1884
|
+
* Creates a browser client. With a client SDK key it connects to ConfigDirector; with
|
|
1885
|
+
* {@link OfflineClientOptions} alone it runs in `offline` mode and serves `connection.values`. An
|
|
1886
|
+
* absent key with `clientOptions` is the same as the options alone when their mode is `offline`,
|
|
1887
|
+
* and fails like a missing key otherwise.
|
|
1888
|
+
*/
|
|
1889
|
+
const createBrowserClient = (clientSdkKeyOrOptions, sdkOptions, clientOptions) => {
|
|
1890
|
+
return DefaultConfigDirectorClient.from(({ clientSdkKey, baseUrl, logger, metadata }) => new WebWorkerTelemetryClient({
|
|
1672
1891
|
sdkKey: clientSdkKey,
|
|
1673
1892
|
sdkIdentity: {
|
|
1674
1893
|
sdkName: sdkOptions.sdkName,
|
|
1675
1894
|
sdkVersion: sdkOptions.sdkVersion
|
|
1676
1895
|
},
|
|
1677
1896
|
metaContext: {
|
|
1678
|
-
appName:
|
|
1679
|
-
appVersion:
|
|
1897
|
+
appName: metadata?.appName,
|
|
1898
|
+
appVersion: metadata?.appVersion
|
|
1680
1899
|
},
|
|
1681
1900
|
logger,
|
|
1682
1901
|
baseUrl,
|
|
1683
1902
|
urlFactory: defaultUrlFactory,
|
|
1684
1903
|
valueIdGenerator: generateValueId
|
|
1685
|
-
}),
|
|
1686
|
-
...clientOptions,
|
|
1687
|
-
logger
|
|
1688
|
-
});
|
|
1904
|
+
}), clientSdkKeyOrOptions, sdkOptions, clientOptions);
|
|
1689
1905
|
};
|
|
1690
1906
|
//#endregion
|
|
1691
1907
|
//#region ../js-client-core/src/installedTestClient.ts
|
|
@@ -1717,6 +1933,13 @@ const decideMountAction = (client, context) => {
|
|
|
1717
1933
|
return "none";
|
|
1718
1934
|
};
|
|
1719
1935
|
//#endregion
|
|
1936
|
+
//#region ../shared/src/browser-half.ts
|
|
1937
|
+
const decideBrowserHalfSource = (browserHalf, serverConnectionMode) => {
|
|
1938
|
+
if (browserHalf.mode !== void 0 || browserHalf.values !== void 0) return "as-given";
|
|
1939
|
+
if (serverConnectionMode === "offline") return "inherit-offline";
|
|
1940
|
+
return "connect";
|
|
1941
|
+
};
|
|
1942
|
+
//#endregion
|
|
1720
1943
|
//#region src/runtime/app/composables/useConfigDirectorClient.ts
|
|
1721
1944
|
const useConfigDirectorClient = () => {
|
|
1722
1945
|
const { $configDirectorClient } = useNuxtApp();
|
|
@@ -1761,13 +1984,16 @@ const createDefaultLogger = (level) => {
|
|
|
1761
1984
|
return logger;
|
|
1762
1985
|
};
|
|
1763
1986
|
//#endregion
|
|
1987
|
+
//#region src/runtime/offline-values-route.ts
|
|
1988
|
+
const OFFLINE_VALUES_ROUTE = "/_configdirector/offline-values";
|
|
1989
|
+
//#endregion
|
|
1764
1990
|
//#region src/runtime/plugin.client.ts
|
|
1765
1991
|
const DEFAULT_INITIALIZATION_TIMEOUT_MILLISECONDS = 2e3;
|
|
1766
|
-
var plugin_client_default = defineNuxtPlugin((nuxtApp) => {
|
|
1992
|
+
var plugin_client_default = defineNuxtPlugin(async (nuxtApp) => {
|
|
1767
1993
|
const runtimeConfig = useRuntimeConfig();
|
|
1768
1994
|
const logger = createDefaultLogger(runtimeConfig.public?.configdirector?.logLevel);
|
|
1769
1995
|
const installedTestClient = readInstalledTestClient();
|
|
1770
|
-
const client = installedTestClient ?? buildClient(runtimeConfig.public?.configdirector, logger);
|
|
1996
|
+
const client = installedTestClient ?? await buildClient(runtimeConfig.public?.configdirector, logger);
|
|
1771
1997
|
logger.debug(installedTestClient ? "Installed ConfigDirector Nuxt plugin with a test client" : "Installed ConfigDirector Nuxt plugin");
|
|
1772
1998
|
const readyStatus = shallowRef(client.isReady ? "ready" : "loading");
|
|
1773
1999
|
client.on("clientReady", () => {
|
|
@@ -1788,29 +2014,58 @@ var plugin_client_default = defineNuxtPlugin((nuxtApp) => {
|
|
|
1788
2014
|
configDirectorClientReadyStatus: readonly(readyStatus)
|
|
1789
2015
|
} };
|
|
1790
2016
|
});
|
|
1791
|
-
const buildClient = (configdirector, logger) => {
|
|
1792
|
-
|
|
2017
|
+
const buildClient = async (configdirector, logger) => {
|
|
2018
|
+
const browserHalf = await browserHalfConnectionOf(configdirector, logger);
|
|
2019
|
+
if (browserHalf.mode !== "offline" && !configdirector?.clientSdkKey) {
|
|
1793
2020
|
const message = "The ConfigDirector clientSdkKey must be configured for the plugin to initialize. You can provide it in nuxt.config.ts under 'runtimeConfig.public.configdirector.clientSdkKey' or as a runtime environment variable named NUXT_PUBLIC_CONFIGDIRECTOR_CLIENT_SDK_KEY";
|
|
1794
2021
|
logger.error(message);
|
|
1795
2022
|
throw new ConfigDirectorInitializationError(message);
|
|
1796
2023
|
}
|
|
1797
|
-
|
|
1798
|
-
return createBrowserClient(clientSdkKey, {
|
|
2024
|
+
return createBrowserClient(configdirector?.clientSdkKey || void 0, {
|
|
1799
2025
|
sdkName: "nuxt-sdk",
|
|
1800
|
-
sdkVersion: "1.
|
|
2026
|
+
sdkVersion: "1.11.0"
|
|
1801
2027
|
}, {
|
|
1802
2028
|
metadata: {
|
|
1803
|
-
appName,
|
|
1804
|
-
appVersion
|
|
2029
|
+
appName: configdirector?.appName,
|
|
2030
|
+
appVersion: configdirector?.appVersion
|
|
1805
2031
|
},
|
|
1806
2032
|
connection: {
|
|
1807
|
-
url: baseUrl || void 0,
|
|
1808
|
-
mode:
|
|
1809
|
-
|
|
1810
|
-
|
|
2033
|
+
url: configdirector?.baseUrl || void 0,
|
|
2034
|
+
mode: browserHalf.mode,
|
|
2035
|
+
values: browserHalf.values,
|
|
2036
|
+
pollingInterval: configdirector?.connection?.pollingInterval || void 0,
|
|
2037
|
+
timeout: configdirector?.connection?.timeout || DEFAULT_INITIALIZATION_TIMEOUT_MILLISECONDS
|
|
1811
2038
|
},
|
|
1812
2039
|
logger
|
|
1813
2040
|
});
|
|
1814
2041
|
};
|
|
2042
|
+
const browserHalfConnectionOf = async (configdirector, logger) => {
|
|
2043
|
+
const givenConnection = {
|
|
2044
|
+
mode: configdirector?.connection?.mode || void 0,
|
|
2045
|
+
values: configdirector?.connection?.values
|
|
2046
|
+
};
|
|
2047
|
+
const source = decideBrowserHalfSource(givenConnection, configdirector?.serverConnectionMode);
|
|
2048
|
+
logger.debug(`Browser half source: ${source}`);
|
|
2049
|
+
switch (source) {
|
|
2050
|
+
case "as-given": return givenConnection;
|
|
2051
|
+
case "inherit-offline": return {
|
|
2052
|
+
mode: "offline",
|
|
2053
|
+
values: await fetchServerOfflineValues(logger)
|
|
2054
|
+
};
|
|
2055
|
+
case "connect": return {
|
|
2056
|
+
mode: void 0,
|
|
2057
|
+
values: void 0
|
|
2058
|
+
};
|
|
2059
|
+
}
|
|
2060
|
+
};
|
|
2061
|
+
const fetchServerOfflineValues = async (logger) => {
|
|
2062
|
+
try {
|
|
2063
|
+
return await $fetch(OFFLINE_VALUES_ROUTE);
|
|
2064
|
+
} catch (error) {
|
|
2065
|
+
const message = `The server runs ConfigDirector in offline mode, but its values could not be fetched from ${OFFLINE_VALUES_ROUTE}: ${error instanceof Error ? error.message : String(error)}. A statically generated site has no server to serve them; set 'runtimeConfig.public.configdirector.connection' to { mode: "offline", values } in nuxt.config.ts to give the browser its own values.`;
|
|
2066
|
+
logger.error(message);
|
|
2067
|
+
throw new ConfigDirectorInitializationError(message);
|
|
2068
|
+
}
|
|
2069
|
+
};
|
|
1815
2070
|
//#endregion
|
|
1816
2071
|
export { plugin_client_default as default };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { n as ConfigDirectorClient } from "../../types-CS7AMNWe.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/runtime/server/composables/useConfigDirectorServerClient.d.ts
|
|
4
|
+
declare const useConfigDirectorServerClient: () => ConfigDirectorClient;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { useConfigDirectorServerClient };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { n as ConfigDirectorClient } from "../../types-CS7AMNWe.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/runtime/server/composables/useConfigDirectorServerClient.d.ts
|
|
4
|
+
declare const useConfigDirectorServerClient: () => ConfigDirectorClient;
|
|
5
|
+
//#endregion
|
|
6
|
+
export { useConfigDirectorServerClient };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useNitroApp } from "nitropack/runtime";
|
|
2
|
-
//#region src/runtime/server/composables/
|
|
3
|
-
const
|
|
2
|
+
//#region src/runtime/server/composables/useConfigDirectorServerClient.ts
|
|
3
|
+
const useConfigDirectorServerClient = () => {
|
|
4
4
|
const serverSdkClient = useNitroApp().configDirectorClient;
|
|
5
5
|
if (!serverSdkClient) throw "The nitro ConfigDirector plugin was not initialized";
|
|
6
6
|
return serverSdkClient;
|
|
7
7
|
};
|
|
8
8
|
//#endregion
|
|
9
|
-
export {
|
|
9
|
+
export { useConfigDirectorServerClient };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ClientHooks } from "../../types-
|
|
1
|
+
import { t as ClientHooks } from "../../types-CS7AMNWe.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/server/composables/useConfigDirectorServerHooks.d.ts
|
|
4
4
|
declare const useConfigDirectorServerHooks: (hooks: ClientHooks) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ClientHooks } from "../../types-
|
|
1
|
+
import { t as ClientHooks } from "../../types-CS7AMNWe.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/server/composables/useConfigDirectorServerHooks.d.ts
|
|
4
4
|
declare const useConfigDirectorServerHooks: (hooks: ClientHooks) => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as ConfigValueType, i as ConfigState, n as ConfigDirectorContext, r as ConfigEvaluation } from "./native-values-BV2k_xR2.mjs";
|
|
2
2
|
|
|
3
3
|
//#region ../js-server-sdk/src/types.d.ts
|
|
4
4
|
type ClientEvents = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as ConfigValueType, n as ConfigDirectorContext, r as ConfigEvaluation } from "./native-values-BV2k_xR2.mjs";
|
|
2
2
|
|
|
3
3
|
//#region ../js-client-core/src/Emitter.d.ts
|
|
4
4
|
type EventType = string | symbol;
|