@configdirector/nuxt-sdk 0.5.0 → 0.7.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.json +1 -1
- 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/useConfigDirectorContext.d.mts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorContext.d.ts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorValue.d.mts +1 -1
- package/dist/runtime/app/composables/useConfigDirectorValue.d.ts +1 -1
- package/dist/runtime/nitro/plugin.d.mts +1 -1
- package/dist/runtime/nitro/plugin.d.ts +1 -1
- package/dist/runtime/nitro/plugin.mjs +7 -6
- package/dist/runtime/plugin.client.mjs +12 -6
- package/dist/runtime/server/composables/useConfigDirectorClient.d.mts +1 -1
- package/dist/runtime/server/composables/useConfigDirectorClient.d.ts +1 -1
- package/dist/runtime/{types-DGQ1B6mZ.d.mts → types-BDwzL0dp.d.mts} +1 -1
- package/dist/runtime/{types-D9IS8RoC.d.mts → types-BkRZRTVv.d.mts} +1 -1
- package/dist/runtime/{types-BWxsGnk2.d.mts → types-f2z6DgES.d.mts} +8 -0
- package/package.json +3 -3
package/dist/module.json
CHANGED
|
@@ -1009,11 +1009,12 @@ const defaultUrlFactory = (input, base) => new URL(input, base?.toString());
|
|
|
1009
1009
|
const CONFIG_VALUE_MAX_LENGTH = 500;
|
|
1010
1010
|
const sanitizeValue = (value, type) => {
|
|
1011
1011
|
if (type === "json" || type == null && typeof value === "object") try {
|
|
1012
|
-
return djb2Hash(JSON.stringify(value));
|
|
1012
|
+
return { digest: djb2Hash(JSON.stringify(value)) };
|
|
1013
1013
|
} catch {
|
|
1014
|
-
return value.toString()
|
|
1014
|
+
return { digest: value.toString() };
|
|
1015
1015
|
}
|
|
1016
|
-
|
|
1016
|
+
if (value.toString().length > CONFIG_VALUE_MAX_LENGTH) return { digest: djb2Hash(value.toString()) };
|
|
1017
|
+
else return { value: value.toString() };
|
|
1017
1018
|
};
|
|
1018
1019
|
const djb2Hash = (data) => {
|
|
1019
1020
|
return djb2(new TextEncoder().encode(data)).toString(16).padStart(8, "0");
|
|
@@ -1270,10 +1271,10 @@ var ServerTelemetryEventCollector = class extends TelemetryEventCollector {
|
|
|
1270
1271
|
}
|
|
1271
1272
|
evaluatedConfig(payload) {
|
|
1272
1273
|
if (!this.collectEvents) return;
|
|
1273
|
-
if (payload.context?.id) this.contexts.set(payload.context.id, payload.context);
|
|
1274
|
+
if (payload.context?.id && !payload.context.anonymous) this.contexts.set(payload.context.id, payload.context);
|
|
1274
1275
|
const event = {
|
|
1275
1276
|
...payload.evaluation,
|
|
1276
|
-
contextId: payload.context?.id
|
|
1277
|
+
contextId: payload.context?.anonymous ? void 0 : payload.context?.id
|
|
1277
1278
|
};
|
|
1278
1279
|
this.evaluationEventQueue.push(this.sanitizeEvaluatedConfigEvent(event));
|
|
1279
1280
|
}
|
|
@@ -1551,7 +1552,7 @@ var plugin_default = defineNitroPlugin((nitroApp) => {
|
|
|
1551
1552
|
const { serverSdkKey, baseUrl } = runtimeConfig.configdirector;
|
|
1552
1553
|
const client = new DefaultConfigDirectorClient(serverSdkKey, {
|
|
1553
1554
|
sdkName: "nuxt-sdk",
|
|
1554
|
-
sdkVersion: "0.
|
|
1555
|
+
sdkVersion: "0.7.0"
|
|
1555
1556
|
}, {
|
|
1556
1557
|
logger,
|
|
1557
1558
|
...baseUrl ? { connection: { url: baseUrl } } : {}
|
|
@@ -407,7 +407,8 @@ var StreamingTransport = class {
|
|
|
407
407
|
body: JSON.stringify({
|
|
408
408
|
givenContext: context,
|
|
409
409
|
metaContext: this.options.metaContext,
|
|
410
|
-
clientSdkKey: this.options.clientSdkKey
|
|
410
|
+
clientSdkKey: this.options.clientSdkKey,
|
|
411
|
+
instanceId: this.options.instanceId
|
|
411
412
|
}),
|
|
412
413
|
onMessage: ({ data }) => {
|
|
413
414
|
this.dispatchMessage(data);
|
|
@@ -764,6 +765,7 @@ var PollingTransport = class extends AbstractPollingTransport {
|
|
|
764
765
|
givenContext: context,
|
|
765
766
|
metaContext: this.options.metaContext,
|
|
766
767
|
clientSdkKey: this.options.clientSdkKey,
|
|
768
|
+
instanceId: this.options.instanceId,
|
|
767
769
|
lastUpdateTimestamp: this.lastUpdateTimestamp
|
|
768
770
|
})
|
|
769
771
|
}, this.logger);
|
|
@@ -824,7 +826,9 @@ var DefaultConfigDirectorClient = class {
|
|
|
824
826
|
readyResolve;
|
|
825
827
|
currentContext;
|
|
826
828
|
connectionMode;
|
|
829
|
+
instanceId;
|
|
827
830
|
constructor(telemetryClient, clientSdkKey, sdkOptions, clientOptions, internalClientOptions) {
|
|
831
|
+
this.instanceId = crypto.randomUUID();
|
|
828
832
|
this.logger = clientOptions?.logger ?? createDefaultLogger$1();
|
|
829
833
|
this.timeout = clientOptions?.connection?.timeout ?? 3e3;
|
|
830
834
|
const urlFactory = internalClientOptions?.urlFactory ?? defaultUrlFactory;
|
|
@@ -833,6 +837,7 @@ var DefaultConfigDirectorClient = class {
|
|
|
833
837
|
const transportConstructor = this.getTransportConstructor(this.connectionMode);
|
|
834
838
|
this.telemetryClient = telemetryClient;
|
|
835
839
|
this.transport = new transportConstructor({
|
|
840
|
+
instanceId: this.instanceId,
|
|
836
841
|
clientSdkKey,
|
|
837
842
|
baseUrl,
|
|
838
843
|
resolveUrl: urlFactory,
|
|
@@ -1034,11 +1039,12 @@ var DefaultConfigDirectorClient = class {
|
|
|
1034
1039
|
const CONFIG_VALUE_MAX_LENGTH = 500;
|
|
1035
1040
|
const sanitizeValue = (value, type) => {
|
|
1036
1041
|
if (type === "json" || type == null && typeof value === "object") try {
|
|
1037
|
-
return djb2Hash(JSON.stringify(value));
|
|
1042
|
+
return { digest: djb2Hash(JSON.stringify(value)) };
|
|
1038
1043
|
} catch {
|
|
1039
|
-
return value.toString()
|
|
1044
|
+
return { digest: value.toString() };
|
|
1040
1045
|
}
|
|
1041
|
-
|
|
1046
|
+
if (value.toString().length > CONFIG_VALUE_MAX_LENGTH) return { digest: djb2Hash(value.toString()) };
|
|
1047
|
+
else return { value: value.toString() };
|
|
1042
1048
|
};
|
|
1043
1049
|
const djb2Hash = (data) => {
|
|
1044
1050
|
return djb2(new TextEncoder().encode(data)).toString(16).padStart(8, "0");
|
|
@@ -1071,7 +1077,7 @@ var WebWorkerTelemetryClient = class {
|
|
|
1071
1077
|
flushIntervalDelay: options.flushIntervalDelay ?? 3e4
|
|
1072
1078
|
}
|
|
1073
1079
|
};
|
|
1074
|
-
this.worker = new Worker(URL.createObjectURL(new Blob(["(function(){let e=(e,n)=>{if(n===`json`||n==null&&typeof e==`object`)try{return
|
|
1080
|
+
this.worker = new Worker(URL.createObjectURL(new Blob(["(function(){let e=(e,n)=>{if(n===`json`||n==null&&typeof e==`object`)try{return{digest:t(JSON.stringify(e))}}catch{return{digest:e.toString()}}return e.toString().length>500?{digest:t(e.toString())}:{value:e.toString()}},t=e=>n(new TextEncoder().encode(e)).toString(16).padStart(8,`0`),n=e=>{let t=5381;for(let n=0;n<e.length;n++)t=(t<<5)+t+(e[n]??0),t>>>=0;return t},r=e=>{let t=Object.keys(e);if(t.length==0)return!0;for(let n of t)if((e[n]?.length??0)>0)return!1;return!0},i=e=>{if(!e)return!0;let t=Object.keys(e);if(t.length==0)return!0;for(let n of t)if((e[n]??0)>0)return!1;return!0},a=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(typeof t==`string`||t instanceof Request?t:t.toString(),{...n,signal:i.signal});return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}},o=e=>e?.name===`NotAllowedError`?!0:e instanceof TypeError;var s=class{constructor(e){this.executeRequests=!0,this.sdkKey=e.sdkKey,this.logger=e.logger,this.url=e.urlFactory(`client/telemetry/v1`,e.baseUrl)}async report({context:e,discreteEvents:t,aggregatedEvents:n,droppedEvents:r}){if(!this.executeRequests)return{success:!1,fatalError:!0};let i={clientSdkKey:this.sdkKey,context:e,discreteEvents:t,aggregatedEvents:n,droppedEvents:r};if(this.isReportEmpty(i))return{success:!0,fatalError:!1};let a=await this.sendReport(i);return a.fatalError&&(this.executeRequests=!1),a}isReportEmpty(e){return r(e.discreteEvents)&&r(e.aggregatedEvents)&&i(e.droppedEvents)}async sendReport(e){try{let t=await a(5e3,this.url,{method:`POST`,body:JSON.stringify(e),keepalive:!0},this.logger),n=this.isStatusFatal(t.status);return n&&this.logger.warn(`[EventReporter] Received a fatal status response (${t.status}) from the telemetry endpoint. No more telemetry data will be sent.`),{success:t.ok,fatalError:n}}catch(e){let t=o(e);return this.logger.warn(`[EventReporter] Error attempting to send telemetry data: ${e}`,{error:e}),{success:!1,fatalError:t}}}isStatusFatal(e){return!!e&&e>=400&&e<500}},c=class{aggregate(e){if(e.events.length==0)return[];let t=new Map;for(let n of e.events){let e=JSON.stringify(n),r=t.get(e)?.count||0;t.set(e,{event:n,count:r+1})}return Array.from(t).map(([,t])=>({startTime:e.startTime,endTime:e.endTime,count:t.count,event:t.event}))}},l=class{constructor(e){this._events=[],this._droppedEventCount=0,this.limit=e??1e3}get events(){return this._events}get reachedLimit(){return this._events.length>=this.limit}get droppedEventCount(){return this._droppedEventCount}push(...e){this.startTime||=new Date;let t=Math.max(0,e.length-this.limit),n=e.slice(t,e.length);if(this._droppedEventCount+=t,this._events.length+n.length>this.limit){let e=this._events.length+n.length-this.limit;this._events.splice(0,e),this._droppedEventCount+=e}return this._events.push(...n)}takeSnapshot(){let e=new Date,t=this.startTime??e,n=this._events.splice(0),r=this._droppedEventCount;return this.startTime=void 0,this._droppedEventCount=0,{startTime:t,endTime:e,events:n,droppedCount:r}}clear(){this._events=[],this.startTime=void 0,this._droppedEventCount=0}},u=class{constructor(e){this.aggregator=new c,this.collectEvents=!0,this.logger=e.logger,this.evaluationEventQueue=new l(e.evaluationQueueLimit??1e3),this.flushIntervalDelay=e.flushIntervalDelay??3e4;let t=e.initialFlushIntervalDelay??5e3;this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),t)}sanitizeValue(t,n){return e(t,n)}async flushAndScheduleNext(){(await this.flush()).fatalError?(this.collectEvents=!1,this.close(),this.logger.warn(`[TelemetryEventCollector] Received a fatal error from telemetry collection. No longer collecting events.`)):this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),this.flushIntervalDelay)}async flush(){if(!this.reporter)return{success:!1,fatalError:!1};let e=this.evaluationEventQueue.takeSnapshot();return await this.reporter?.report({context:this._context,discreteEvents:{},aggregatedEvents:{evaluatedConfig:this.aggregator.aggregate(e)},droppedEvents:{evaluatedConfig:e.droppedCount}})}cancelScheduledFlush(){clearTimeout(this.flushTimeout)}async close(){this.collectEvents=!1,clearTimeout(this.flushTimeout),await this.flush(),this.evaluationEventQueue.clear()}dispose(){this.close()}},d=class extends u{constructor(e){super(e),this.reporter=new s(e)}async updateContext(e){this.cancelScheduledFlush(),await this.flush(),this._context=e,await this.flushAndScheduleNext()}evaluatedConfig(e){this.collectEvents&&this.evaluationEventQueue.push(e)}async forceFlush(){this.cancelScheduledFlush(),await this.flushAndScheduleNext()}};let f=(e,t)=>new URL(e,t?.toString()),p,m=(e,t,...n)=>({type:`Log`,payload:{level:e,message:t,args:n}}),h=e=>{try{self.postMessage(e)}catch{self.postMessage(m(e.payload.level,e.payload.message))}},g={debug:function(e,...t){h(m(`debug`,e,t))},info:function(e,...t){h(m(`info`,e,t))},warn:function(e,...t){h(m(`warn`,e,t))},error:function(e,...t){h(m(`error`,e,t))}};addEventListener(`message`,e=>{let t=e.data;if(t.type!=`Initialize`&&!p){g.info(`[TelemetryWorker] Ignoring ${t.type} because no collector is configured`);return}switch(g.debug(`[TelemetryWorker] Received '${t.type}' event:`,t),t.type){case`Initialize`:p=new d({...t.payload,baseUrl:f(t.payload.baseUrl),urlFactory:f,logger:g});break;case`EvaluatedConfigEvent`:p?.evaluatedConfig(t.payload);break;case`UpdateContext`:p?.updateContext(t.payload.context);break;case`Flush`:p?.forceFlush();break;case`Close`:(p?.close()??Promise.resolve()).then(()=>{self.postMessage({type:`Closed`}),self.close()});break}})})();"], { type: "application/javascript" })));
|
|
1075
1081
|
this.worker.onmessage = (message) => {
|
|
1076
1082
|
this.handleWorkerEvent(message.data);
|
|
1077
1083
|
};
|
|
@@ -1211,7 +1217,7 @@ var plugin_client_default = defineNuxtPlugin((nuxtApp) => {
|
|
|
1211
1217
|
const { clientSdkKey, appName, appVersion, baseUrl } = runtimeConfig.public.configdirector;
|
|
1212
1218
|
const client = createBrowserClient(clientSdkKey, {
|
|
1213
1219
|
sdkName: "nuxt-sdk",
|
|
1214
|
-
sdkVersion: "0.
|
|
1220
|
+
sdkVersion: "0.7.0"
|
|
1215
1221
|
}, {
|
|
1216
1222
|
metadata: {
|
|
1217
1223
|
appName,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ConfigDirectorClient } from "../../types-
|
|
1
|
+
import { t as ConfigDirectorClient } from "../../types-BDwzL0dp.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/server/composables/useConfigDirectorClient.d.ts
|
|
4
4
|
declare const useConfigDirectorClient: () => ConfigDirectorClient;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ConfigDirectorClient } from "../../types-
|
|
1
|
+
import { t as ConfigDirectorClient } from "../../types-BDwzL0dp.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/server/composables/useConfigDirectorClient.d.ts
|
|
4
4
|
declare const useConfigDirectorClient: () => ConfigDirectorClient;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as ConfigState, r as ConfigValueType, t as ConfigDirectorContext } from "./types-
|
|
1
|
+
import { n as ConfigState, r as ConfigValueType, t as ConfigDirectorContext } from "./types-f2z6DgES.mjs";
|
|
2
2
|
|
|
3
3
|
//#region ../js-server-sdk/src/types.d.ts
|
|
4
4
|
type ClientEvents = {
|
|
@@ -37,6 +37,14 @@ type ConfigDirectorContext = {
|
|
|
37
37
|
traits?: {
|
|
38
38
|
[key: string]: unknown;
|
|
39
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Whether or not to treat the context as anonymous during evaluation. When `true`, the
|
|
42
|
+
* context values will be used for targeting rules evaluation but the context will not be
|
|
43
|
+
* persisted and will not appear in the dashboard.
|
|
44
|
+
*
|
|
45
|
+
* @default false
|
|
46
|
+
*/
|
|
47
|
+
anonymous?: boolean;
|
|
40
48
|
};
|
|
41
49
|
//#endregion
|
|
42
50
|
export { ConfigState as n, ConfigValueType as r, ConfigDirectorContext as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@configdirector/nuxt-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Nuxt SDK for ConfigDirector. ConfigDirector is a remote configuration and feature flag service.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ConfigDirector",
|
|
@@ -63,13 +63,13 @@
|
|
|
63
63
|
"@types/node": "latest",
|
|
64
64
|
"changelogen": "^0.6.2",
|
|
65
65
|
"eslint": "^10.2.1",
|
|
66
|
-
"nuxt": "^4.4.
|
|
66
|
+
"nuxt": "^4.4.8",
|
|
67
67
|
"playwright": "^1.60.0",
|
|
68
68
|
"rimraf": "^6.1.3",
|
|
69
69
|
"tsdown": "^0.21.7",
|
|
70
70
|
"tslib": "^2.8.1",
|
|
71
71
|
"typescript": "~6.0.3",
|
|
72
|
-
"vite": "^8.0.
|
|
72
|
+
"vite": "^8.0.16",
|
|
73
73
|
"vitest": "^4.1.8",
|
|
74
74
|
"vue-tsc": "^3.2.7"
|
|
75
75
|
}
|