@configdirector/nuxt-sdk 0.9.5 → 1.0.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 CHANGED
@@ -4,5 +4,5 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=4.0.0"
6
6
  },
7
- "version": "0.9.5"
7
+ "version": "1.0.0"
8
8
  }
@@ -610,18 +610,9 @@ const compareText = (value, operator, targetValues) => {
610
610
  case "does not start with any of": return !targetValues.some((target) => value.startsWith(target));
611
611
  case "ends with any of": return targetValues.some((target) => value.endsWith(target));
612
612
  case "does not end with any of": return !targetValues.some((target) => value.endsWith(target));
613
- case "matches regex": return first !== void 0 && matchesRegex(first, value);
614
- case "does not match regex": return first !== void 0 && !matchesRegex(first, value);
615
613
  default: return false;
616
614
  }
617
615
  };
618
- const matchesRegex = (regexString, value) => {
619
- try {
620
- return new RegExp(regexString).test(value);
621
- } catch {
622
- return false;
623
- }
624
- };
625
616
  //#endregion
626
617
  //#region ../config-evaluator/src/numeric-comparison.ts
627
618
  /**
@@ -7049,13 +7040,14 @@ var ConfigEvaluator = class {
7049
7040
  configId: config.id,
7050
7041
  contextIdentifier: context?.context?.id ?? crypto.randomUUID()
7051
7042
  });
7052
- let index = 0;
7053
7043
  let sum = 0;
7054
7044
  let bucket = void 0;
7055
- while (!bucket && index < percentages.length) {
7056
- if (assignedPercentage <= percentages[index].percentage + sum) bucket = percentages[index];
7057
- sum += percentages[index].percentage;
7058
- index += 1;
7045
+ for (const percentage of percentages) {
7046
+ if (assignedPercentage < percentage.percentage + sum) {
7047
+ bucket = percentage;
7048
+ break;
7049
+ }
7050
+ sum += percentage.percentage;
7059
7051
  }
7060
7052
  if (bucket?.value != null) return {
7061
7053
  success: true,
@@ -7064,13 +7056,7 @@ var ConfigEvaluator = class {
7064
7056
  return { success: false };
7065
7057
  }
7066
7058
  evaluateConditionalRule(rule, config, context) {
7067
- const conditions = rule.conditions ?? [];
7068
- let index = 0;
7069
- let condition = void 0;
7070
- while (!condition && index < conditions.length) {
7071
- if (this.conditionEvaluator.evaluate(conditions[index], context)) condition = conditions[index];
7072
- index += 1;
7073
- }
7059
+ const condition = (rule.conditions ?? []).find((candidate) => this.conditionEvaluator.evaluate(candidate, context));
7074
7060
  if (condition && rule.target == "value" && rule.value != null) return {
7075
7061
  success: true,
7076
7062
  value: rule.value.toString()
@@ -7318,11 +7304,13 @@ const isDroppedEventsEmpty = (droppedEvents) => {
7318
7304
  //#region ../js-server-sdk/src/telemetry/ServerEventReporter.ts
7319
7305
  var ServerEventReporter = class {
7320
7306
  sdkKey;
7307
+ sdkIdentity;
7321
7308
  logger;
7322
7309
  url;
7323
7310
  executeRequests = true;
7324
7311
  constructor(options) {
7325
7312
  this.sdkKey = options.sdkKey;
7313
+ this.sdkIdentity = options.sdkIdentity;
7326
7314
  this.logger = options.logger;
7327
7315
  this.url = new URL("server/telemetry/v1", options.baseUrl.toString());
7328
7316
  }
@@ -7333,6 +7321,10 @@ var ServerEventReporter = class {
7333
7321
  };
7334
7322
  const eventReport = {
7335
7323
  serverSdkKey: this.sdkKey,
7324
+ metaContext: {
7325
+ sdkName: this.sdkIdentity.sdkName,
7326
+ sdkVersion: this.sdkIdentity.sdkVersion
7327
+ },
7336
7328
  discreteEvents,
7337
7329
  aggregatedEvents,
7338
7330
  droppedEvents
@@ -7652,6 +7644,7 @@ var DefaultConfigDirectorClient = class {
7652
7644
  const queueLimit = clientOptions?.telemetry?.eventQueueLimit ?? DEFAULT_EVENT_QUEUE_LIMIT;
7653
7645
  this.usageEventCollector = new ServerTelemetryEventCollector({
7654
7646
  sdkKey: serverSdkKey,
7647
+ sdkIdentity: sdkOptions,
7655
7648
  logger: this.logger,
7656
7649
  baseUrl,
7657
7650
  flushIntervalDelay: clientOptions?.telemetry?.flushInterval ?? DEFAULT_FLUSH_INTERVAL,
@@ -7894,7 +7887,7 @@ var plugin_default = defineNitroPlugin((nitroApp) => {
7894
7887
  const { serverSdkKey, baseUrl } = runtimeConfig.configdirector;
7895
7888
  const client = new DefaultConfigDirectorClient(serverSdkKey, {
7896
7889
  sdkName: "nuxt-sdk",
7897
- sdkVersion: "0.9.5"
7890
+ sdkVersion: "1.0.0"
7898
7891
  }, {
7899
7892
  logger,
7900
7893
  ...baseUrl ? { connection: { url: baseUrl } } : {}
@@ -1134,13 +1134,14 @@ var WebWorkerTelemetryClient = class {
1134
1134
  type: "Initialize",
1135
1135
  payload: {
1136
1136
  sdkKey: options.sdkKey,
1137
+ sdkIdentity: options.sdkIdentity,
1137
1138
  baseUrl: options.baseUrl.toString(),
1138
1139
  evaluationQueueLimit: options.evaluationQueueLimit ?? 1e3,
1139
1140
  initialFlushIntervalDelay: options.initialFlushIntervalDelay ?? 5e3,
1140
1141
  flushIntervalDelay: options.flushIntervalDelay ?? 3e4
1141
1142
  }
1142
1143
  };
1143
- this.worker = new Worker(URL.createObjectURL(new Blob(["(function(){let e=async(e,t)=>e.valueId?{valueId:e.valueId}:e.value?e.value.length<=500&&e.type!=`json`?{value:e.value}:{valueId:await t(e.value)}:e,t=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},n=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},r=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}},i=e=>e?.name===`NotAllowedError`?!0:e instanceof TypeError;var a=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 t(e.discreteEvents)&&t(e.aggregatedEvents)&&n(e.droppedEvents)}async sendReport(e){try{let t=await r(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=i(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}},o=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}))}},s=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}},c=class{constructor(e){this.aggregator=new o,this.collectEvents=!0,this.logger=e.logger,this.evaluationEventQueue=new s(e.evaluationQueueLimit??1e3),this.flushIntervalDelay=e.flushIntervalDelay??3e4;let t=e.initialFlushIntervalDelay??5e3;this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),t)}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)}cancelScheduledFlush(){clearTimeout(this.flushTimeout)}async close(){this.collectEvents=!1,clearTimeout(this.flushTimeout),await this.flush(),this.evaluationEventQueue.clear()}dispose(){this.close()}},l=class{constructor(e){this.valueIdGenerator=e,this.valueIdGenerator=e}async process(t){let n=await Promise.all(t.events.map(async t=>({...t,defaultValue:await e(t.defaultValue,this.valueIdGenerator),evaluatedValue:await e(t.evaluatedValue,this.valueIdGenerator)})));return{...t,events:n}}},u=class extends c{constructor(e){super(e),this.reporter=new a(e),this.evaluationEventSnapshotPreprocessor=new l(e.valueIdGenerator)}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()}async flush(){if(!this.reporter)return{success:!1,fatalError:!1};let e=await this.evaluationEventSnapshotPreprocessor.process(this.evaluationEventQueue.takeSnapshot());return await this.reporter?.report({context:this._context,discreteEvents:{},aggregatedEvents:{evaluatedConfig:this.aggregator.aggregate(e)},droppedEvents:{evaluatedConfig:e.droppedCount}})}};let d=(e,t)=>new URL(e,t?.toString()),f=(e,t)=>{let n=BigInt(0),r=BigInt(62),i=Array.from(e).map(e=>e.toString(16).padStart(2,`0`)).join(``),a=BigInt(`0x`+i),o=``;for(;a>n;)o=`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`[Number(a%r)]+o,a/=r;return o.padStart(t,`0`)},p=Math.ceil(128/Math.log2(62)),m=new TextEncoder,h=async e=>{let t=await crypto.subtle.digest(`SHA-256`,m.encode(e?.toString()??``));return f(new Uint8Array(t,0,16),p)},g,_=(e,t,...n)=>({type:`Log`,payload:{level:e,message:t,args:n}}),v=e=>{try{self.postMessage(e)}catch{self.postMessage(_(e.payload.level,e.payload.message))}},y={debug:function(e,...t){v(_(`debug`,e,t))},info:function(e,...t){v(_(`info`,e,t))},warn:function(e,...t){v(_(`warn`,e,t))},error:function(e,...t){v(_(`error`,e,t))}};addEventListener(`message`,e=>{let t=e.data;if(t.type!=`Initialize`&&!g){y.info(`[TelemetryWorker] Ignoring ${t.type} because no collector is configured`);return}switch(y.debug(`[TelemetryWorker] Received '${t.type}' event:`,t),t.type){case`Initialize`:g=new u({...t.payload,baseUrl:d(t.payload.baseUrl),urlFactory:d,valueIdGenerator:h,logger:y});break;case`EvaluatedConfigEvent`:g?.evaluatedConfig(t.payload);break;case`UpdateContext`:g?.updateContext(t.payload.context);break;case`Flush`:g?.forceFlush();break;case`Close`:(g?.close()??Promise.resolve()).then(()=>{self.postMessage({type:`Closed`}),self.close()});break}})})();"], { type: "application/javascript" })));
1144
+ this.worker = new Worker(URL.createObjectURL(new Blob(["(function(){let e=async(e,t)=>e.valueId?{valueId:e.valueId}:e.value?e.value.length<=500&&e.type!=`json`?{value:e.value}:{valueId:await t(e.value)}:e,t=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},n=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},r=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}},i=e=>e?.name===`NotAllowedError`?!0:e instanceof TypeError;var a=class{constructor(e){this.executeRequests=!0,this.sdkKey=e.sdkKey,this.logger=e.logger,this.sdkIdentity=e.sdkIdentity,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,metaContext:{sdkName:this.sdkIdentity.sdkName,sdkVersion:this.sdkIdentity.sdkVersion},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 t(e.discreteEvents)&&t(e.aggregatedEvents)&&n(e.droppedEvents)}async sendReport(e){try{let t=await r(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=i(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}},o=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}))}},s=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}},c=class{constructor(e){this.aggregator=new o,this.collectEvents=!0,this.logger=e.logger,this.evaluationEventQueue=new s(e.evaluationQueueLimit??1e3),this.flushIntervalDelay=e.flushIntervalDelay??3e4;let t=e.initialFlushIntervalDelay??5e3;this.flushTimeout=setTimeout(()=>this.flushAndScheduleNext(),t)}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)}cancelScheduledFlush(){clearTimeout(this.flushTimeout)}async close(){this.collectEvents=!1,clearTimeout(this.flushTimeout),await this.flush(),this.evaluationEventQueue.clear()}dispose(){this.close()}},l=class{constructor(e){this.valueIdGenerator=e,this.valueIdGenerator=e}async process(t){let n=await Promise.all(t.events.map(async t=>({...t,defaultValue:await e(t.defaultValue,this.valueIdGenerator),evaluatedValue:await e(t.evaluatedValue,this.valueIdGenerator)})));return{...t,events:n}}},u=class extends c{constructor(e){super(e),this.reporter=new a(e),this.evaluationEventSnapshotPreprocessor=new l(e.valueIdGenerator)}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()}async flush(){if(!this.reporter)return{success:!1,fatalError:!1};let e=await this.evaluationEventSnapshotPreprocessor.process(this.evaluationEventQueue.takeSnapshot());return await this.reporter?.report({context:this._context,discreteEvents:{},aggregatedEvents:{evaluatedConfig:this.aggregator.aggregate(e)},droppedEvents:{evaluatedConfig:e.droppedCount}})}};let d=(e,t)=>new URL(e,t?.toString()),f=(e,t)=>{let n=BigInt(0),r=BigInt(62),i=Array.from(e).map(e=>e.toString(16).padStart(2,`0`)).join(``),a=BigInt(`0x`+i),o=``;for(;a>n;)o=`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`[Number(a%r)]+o,a/=r;return o.padStart(t,`0`)},p=Math.ceil(128/Math.log2(62)),m=new TextEncoder,h=async e=>{let t=await crypto.subtle.digest(`SHA-256`,m.encode(e?.toString()??``));return f(new Uint8Array(t,0,16),p)},g,_=(e,t,...n)=>({type:`Log`,payload:{level:e,message:t,args:n}}),v=e=>{try{self.postMessage(e)}catch{self.postMessage(_(e.payload.level,e.payload.message))}},y={debug:function(e,...t){v(_(`debug`,e,t))},info:function(e,...t){v(_(`info`,e,t))},warn:function(e,...t){v(_(`warn`,e,t))},error:function(e,...t){v(_(`error`,e,t))}};addEventListener(`message`,e=>{let t=e.data;if(t.type!=`Initialize`&&!g){y.info(`[TelemetryWorker] Ignoring ${t.type} because no collector is configured`);return}switch(y.debug(`[TelemetryWorker] Received '${t.type}' event:`,t),t.type){case`Initialize`:g=new u({...t.payload,baseUrl:d(t.payload.baseUrl),urlFactory:d,valueIdGenerator:h,logger:y});break;case`EvaluatedConfigEvent`:g?.evaluatedConfig(t.payload);break;case`UpdateContext`:g?.updateContext(t.payload.context);break;case`Flush`:g?.forceFlush();break;case`Close`:(g?.close()??Promise.resolve()).then(()=>{self.postMessage({type:`Closed`}),self.close()});break}})})();"], { type: "application/javascript" })));
1144
1145
  this.worker.onmessage = (message) => {
1145
1146
  this.handleWorkerEvent(message.data);
1146
1147
  };
@@ -1247,10 +1248,15 @@ const generateValueId = async (v) => {
1247
1248
  //#region ../js-browser-client/src/BrowserConfigDirectorClient.ts
1248
1249
  const createBrowserClient = (clientSdkKey, sdkOptions, clientOptions) => {
1249
1250
  const logger = clientOptions?.logger ?? createDefaultLogger$1();
1251
+ const baseUrl = parseUrl(clientOptions?.connection?.url) ?? "https://client-sdk-api.configdirector.com";
1250
1252
  return new DefaultConfigDirectorClient(new WebWorkerTelemetryClient({
1251
1253
  sdkKey: clientSdkKey,
1254
+ sdkIdentity: {
1255
+ sdkName: sdkOptions.sdkName,
1256
+ sdkVersion: sdkOptions.sdkVersion
1257
+ },
1252
1258
  logger,
1253
- baseUrl: parseUrl(clientOptions?.connection?.url) ?? "https://client-sdk-api.configdirector.com",
1259
+ baseUrl,
1254
1260
  urlFactory: defaultUrlFactory,
1255
1261
  valueIdGenerator: generateValueId
1256
1262
  }), clientSdkKey, sdkOptions, {
@@ -1311,7 +1317,7 @@ var plugin_client_default = defineNuxtPlugin((nuxtApp) => {
1311
1317
  const { clientSdkKey, appName, appVersion, baseUrl } = runtimeConfig.public.configdirector;
1312
1318
  const client = createBrowserClient(clientSdkKey, {
1313
1319
  sdkName: "nuxt-sdk",
1314
- sdkVersion: "0.9.5"
1320
+ sdkVersion: "1.0.0"
1315
1321
  }, {
1316
1322
  metadata: {
1317
1323
  appName,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@configdirector/nuxt-sdk",
3
- "version": "0.9.5",
3
+ "version": "1.0.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",
@@ -40,12 +40,14 @@
40
40
  ],
41
41
  "scripts": {
42
42
  "build": "nuxt prepare && tsdown",
43
+ "verify:dist": "node ../../scripts/verify-dist-version.mjs",
43
44
  "prepack": "nuxt prepare && tsdown",
44
- "release": "nuxt prepare && yarn lint && yarn ci:test && yarn build && npm publish --access public",
45
+ "release": "nuxt prepare && yarn lint && yarn ci:test && yarn build && yarn verify:dist && npm publish --access public",
45
46
  "lint": "eslint .",
46
47
  "ci:test": "vitest run",
47
48
  "test": "vitest watch",
48
- "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
49
+ "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
50
+ "typecheck": "tsc --noEmit"
49
51
  },
50
52
  "dependencies": {
51
53
  "@jsonjoy.com/json-pointer": "^18.1.0",
@@ -58,9 +60,9 @@
58
60
  "devDependencies": {
59
61
  "@nuxt/devtools": "^3.2.4",
60
62
  "@nuxt/eslint-config": "^1.15.2",
61
- "@nuxt/schema": "^4.4.2",
63
+ "@nuxt/schema": "4.4.8",
62
64
  "@nuxt/test-utils": "^4.0.2",
63
- "@types/node": "latest",
65
+ "@types/node": "^24.13.3",
64
66
  "changelogen": "^0.6.2",
65
67
  "eslint": "^10.7.0",
66
68
  "nuxt": "^4.4.8",