From 1627f1a76dde79e20b28b87755519a8e5dad6190 Mon Sep 17 00:00:00 2001 From: Nadeem Patwekar Date: Wed, 17 Sep 2025 15:24:31 +0530 Subject: [PATCH 1/2] feat: Introduce ContentstackPlugin interface for extensible plugin architecture - Added ContentstackPlugin interface to support custom plugins in the Contentstack SDK. - Updated stack function to utilize plugins for request and response interception. - Implemented comprehensive unit tests for plugin functionality, including various implementation patterns and edge cases. - Enhanced type safety for plugins in StackConfig. - Created tests for plugin interactions with interceptors, error handling, and performance scenarios. - Added support for configurable plugins and state management within plugins. --- .talismanrc | 8 + examples/custom-plugin.ts | 273 ++++++ src/lib/contentstack.ts | 6 +- src/lib/types.ts | 50 +- test/unit/plugin-comprehensive.spec.ts | 592 +++++++++++++ .../plugin-interceptor-comprehensive.spec.ts | 777 ++++++++++++++++++ 6 files changed, 1702 insertions(+), 4 deletions(-) create mode 100644 examples/custom-plugin.ts create mode 100644 test/unit/plugin-comprehensive.spec.ts create mode 100644 test/unit/plugin-interceptor-comprehensive.spec.ts diff --git a/.talismanrc b/.talismanrc index 65ba163..8b72d83 100644 --- a/.talismanrc +++ b/.talismanrc @@ -3,4 +3,12 @@ fileignoreconfig: checksum: dffbcb14c5761976a9b6ab90b96c7e4fc5784eebe381cf48014618cc93355dbc - filename: test/unit/query-optimization-comprehensive.spec.ts checksum: f5aaf6c784d7c101a05ca513c584bbd6e95f963d1e42779f2596050d9bcbac96 +- filename: src/lib/types.ts + checksum: 57d2f7eede6ab19ff92db9799e752e7dfa44c1368314525a41ab1a241778a230 +- filename: examples/custom-plugin.ts + checksum: 51a4b01f7c5f76c97c588bb0575cefd1f9462b28d88b24bb9f7dc2780aa323c5 +- filename: test/unit/plugin-comprehensive.spec.ts + checksum: d508f95f4a7eb5bed873ca91a5e1914aa4d5261f27593edb568502cb5855042e +- filename: test/unit/plugin-interceptor-comprehensive.spec.ts + checksum: b9fbe9da166fd209853307f9f60464d25f805f82e9dbe09d5f476fdd5eb05d47 version: "" diff --git a/examples/custom-plugin.ts b/examples/custom-plugin.ts new file mode 100644 index 0000000..0cf8d03 --- /dev/null +++ b/examples/custom-plugin.ts @@ -0,0 +1,273 @@ +/** + * Example implementations of ContentstackPlugin interface + * This file demonstrates various ways to create and use plugins + */ +import contentstack, { ContentstackPlugin } from '@contentstack/delivery-sdk'; +import { AxiosRequestConfig, AxiosResponse } from 'axios'; + +// Example 1: Simple logging plugin as a class +class LoggingPlugin implements ContentstackPlugin { + private requestCount = 0; + + onRequest(config: AxiosRequestConfig): AxiosRequestConfig { + this.requestCount++; + console.log(`[Plugin] Request #${this.requestCount}: ${config.method?.toUpperCase()} ${config.url}`); + + return { + ...config, + headers: { + ...config.headers, + 'X-Request-ID': `req-${this.requestCount}-${Date.now()}` + } + }; + } + + onResponse(request: AxiosRequestConfig, response: AxiosResponse, data: any): AxiosResponse { + console.log(`[Plugin] Response: ${response.status} for ${request.url}`); + + return { + ...response, + data: { + ...data, + _meta: { + requestId: request.headers?.['X-Request-ID'], + processedAt: new Date().toISOString() + } + } + }; + } + + getRequestCount(): number { + return this.requestCount; + } +} + +// Example 2: Authentication plugin as an object +const authPlugin: ContentstackPlugin = { + onRequest(config: AxiosRequestConfig): AxiosRequestConfig { + return { + ...config, + headers: { + ...config.headers, + 'X-Custom-Auth': 'Bearer my-custom-token', + 'X-Client-Version': '1.0.0' + } + }; + }, + + onResponse(request: AxiosRequestConfig, response: AxiosResponse, data: any): AxiosResponse { + // Remove any sensitive information from the response + if (data && typeof data === 'object') { + const sanitized = { ...data }; + delete sanitized.internal_data; + delete sanitized.debug_info; + + return { + ...response, + data: sanitized + }; + } + + return response; + } +}; + +// Example 3: Performance monitoring plugin +class PerformancePlugin implements ContentstackPlugin { + private requestTimes = new Map(); + private metrics = { + totalRequests: 0, + totalTime: 0, + slowRequests: 0, + errors: 0 + }; + + onRequest(config: AxiosRequestConfig): AxiosRequestConfig { + const requestId = `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; + this.requestTimes.set(requestId, performance.now()); + this.metrics.totalRequests++; + + return { + ...config, + metadata: { + ...config.metadata, + requestId, + startTime: performance.now() + } + }; + } + + onResponse(request: AxiosRequestConfig, response: AxiosResponse, data: any): AxiosResponse { + const requestId = request.metadata?.requestId; + const startTime = this.requestTimes.get(requestId); + + if (startTime) { + const duration = performance.now() - startTime; + this.metrics.totalTime += duration; + + if (duration > 1000) { // Slow request threshold: 1 second + this.metrics.slowRequests++; + console.warn(`[Performance] Slow request detected: ${duration.toFixed(2)}ms for ${request.url}`); + } + + this.requestTimes.delete(requestId); + } + + if (response.status >= 400) { + this.metrics.errors++; + } + + return { + ...response, + data: { + ...data, + _performance: { + duration: startTime ? performance.now() - startTime : 0, + timestamp: new Date().toISOString() + } + } + }; + } + + getMetrics() { + return { + ...this.metrics, + averageTime: this.metrics.totalRequests > 0 + ? this.metrics.totalTime / this.metrics.totalRequests + : 0 + }; + } + + printReport() { + const metrics = this.getMetrics(); + console.log(` +Performance Report: +- Total Requests: ${metrics.totalRequests} +- Average Response Time: ${metrics.averageTime.toFixed(2)}ms +- Slow Requests: ${metrics.slowRequests} +- Errors: ${metrics.errors} + `); + } +} + +// Example 4: Caching plugin with TTL +class CachePlugin implements ContentstackPlugin { + private cache = new Map(); + private defaultTTL = 5 * 60 * 1000; // 5 minutes + + onRequest(config: AxiosRequestConfig): AxiosRequestConfig { + const cacheKey = this.generateCacheKey(config); + const cached = this.cache.get(cacheKey); + + if (cached && Date.now() - cached.timestamp < cached.ttl) { + // In a real implementation, you might want to return cached data directly + // This is just for demonstration + console.log(`[Cache] Cache hit for ${cacheKey}`); + return { ...config, fromCache: true }; + } + + return { ...config, cacheKey }; + } + + onResponse(request: AxiosRequestConfig, response: AxiosResponse, data: any): AxiosResponse { + if (response.status === 200 && request.cacheKey && !request.fromCache) { + this.cache.set(request.cacheKey, { + data, + timestamp: Date.now(), + ttl: this.defaultTTL + }); + console.log(`[Cache] Cached response for ${request.cacheKey}`); + } + + return response; + } + + private generateCacheKey(config: AxiosRequestConfig): string { + return `${config.method || 'GET'}_${config.url}_${JSON.stringify(config.params || {})}`; + } + + clearCache(): void { + this.cache.clear(); + } + + getCacheStats() { + return { + size: this.cache.size, + keys: Array.from(this.cache.keys()) + }; + } +} + +// Example 5: Error handling and retry plugin +const errorHandlingPlugin: ContentstackPlugin = { + onRequest(config: AxiosRequestConfig): AxiosRequestConfig { + return { + ...config, + retryAttempts: config.retryAttempts || 0, + maxRetries: 3 + }; + }, + + onResponse(request: AxiosRequestConfig, response: AxiosResponse, data: any): AxiosResponse { + if (response.status >= 400) { + console.error(`[Error] HTTP ${response.status}: ${response.statusText} for ${request.url}`); + + // Log additional error context + if (response.status >= 500) { + console.error('[Error] Server error detected. Consider implementing retry logic.'); + } else if (response.status === 429) { + console.warn('[Error] Rate limit exceeded. Implementing backoff strategy recommended.'); + } + } + + return { + ...response, + data: { + ...data, + _error_handled: response.status >= 400, + _error_code: response.status >= 400 ? response.status : null + } + }; + } +}; + +// Usage example +function createStackWithPlugins() { + const loggingPlugin = new LoggingPlugin(); + const performancePlugin = new PerformancePlugin(); + const cachePlugin = new CachePlugin(); + + const stack = contentstack.stack({ + apiKey: 'your-api-key', + deliveryToken: 'your-delivery-token', + environment: 'your-environment', + plugins: [ + loggingPlugin, // Logs all requests/responses + authPlugin, // Adds authentication headers + performancePlugin, // Monitors performance + cachePlugin, // Caches responses + errorHandlingPlugin // Handles errors gracefully + ] + }); + + // You can access plugin methods if needed + console.log(`Total requests made: ${loggingPlugin.getRequestCount()}`); + + // Print performance report + performancePlugin.printReport(); + + // Check cache stats + console.log('Cache stats:', cachePlugin.getCacheStats()); + + return stack; +} + +// Export for use in other files +export { + LoggingPlugin, + PerformancePlugin, + CachePlugin, + authPlugin, + errorHandlingPlugin, + createStackWithPlugins +}; diff --git a/src/lib/contentstack.ts b/src/lib/contentstack.ts index c6d62f4..057a4e8 100644 --- a/src/lib/contentstack.ts +++ b/src/lib/contentstack.ts @@ -2,7 +2,7 @@ import { httpClient, retryRequestHandler, retryResponseErrorHandler, retryRespon import { AxiosRequestHeaders } from 'axios'; import { handleRequest } from './cache'; import { Stack as StackClass } from './stack'; -import { Policy, StackConfig } from './types'; +import { Policy, StackConfig, ContentstackPlugin } from './types'; import * as Utility from './utils'; export * as Utils from '@contentstack/utils'; @@ -114,7 +114,7 @@ export function stack(config: StackConfig): StackClass { if (config.plugins) { client.interceptors.request.use((reqConfig: any): any => { if (config && config.plugins) - config.plugins.forEach((pluginInstance) => { + config.plugins.forEach((pluginInstance: ContentstackPlugin) => { reqConfig = pluginInstance.onRequest(reqConfig); }); @@ -123,7 +123,7 @@ export function stack(config: StackConfig): StackClass { client.interceptors.response.use((response: any) => { if (config && config.plugins) - config.plugins.forEach((pluginInstance) => { + config.plugins.forEach((pluginInstance: ContentstackPlugin) => { response = pluginInstance.onResponse(response.request, response, response.data); }); diff --git a/src/lib/types.ts b/src/lib/types.ts index f9c0fd5..e19a032 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,6 +1,7 @@ /* eslint-disable @cspell/spellchecker */ import { HttpClientParams } from "@contentstack/core"; import { PersistanceStoreOptions, StorageType } from "../persistance"; +import { AxiosRequestConfig, AxiosResponse } from "axios"; // Internal Types export type params = { @@ -11,6 +12,53 @@ export type queryParams = { [key: string]: string | boolean | number | string[]; }; +/** + * Interface for creating Contentstack plugins + * + * @example + * ```typescript + * import { ContentstackPlugin } from '@contentstack/delivery-sdk'; + * + * class MyPlugin implements ContentstackPlugin { + * onRequest(config: any): any { + * // Modify request configuration + * console.log('Processing request:', config.url); + * return { ...config, headers: { ...config.headers, 'X-Custom-Header': 'value' } }; + * } + * + * onResponse(request: any, response: any, data: any): any { + * // Process response data + * console.log('Processing response:', response.status); + * return { ...response, data: { ...data, processed: true } }; + * } + * } + * + * const stack = contentstack.stack({ + * apiKey: 'your-api-key', + * deliveryToken: 'your-delivery-token', + * environment: 'your-environment', + * plugins: [new MyPlugin()] + * }); + * ``` + */ +export interface ContentstackPlugin { + /** + * Called before each request is sent + * @param config - Axios request configuration object (with possible custom properties) + * @returns Modified request configuration (can be sync or async) + */ + onRequest(config: any): any; + + /** + * Called after each response is received + * @param request - The original request configuration + * @param response - Axios response object (with possible custom properties) + * @param data - Response data + * @returns Modified response object (can be sync or async) + */ + onResponse(request: any, response: any, data: any): any; +} + // External Types export enum Region { US = "us", @@ -30,7 +78,7 @@ export interface StackConfig extends HttpClientParams { early_access?: string[]; region?: Region; locale?: string; - plugins?: any[]; + plugins?: ContentstackPlugin[]; logHandler?: (level: string, data: any) => void; cacheOptions?: CacheOptions; live_preview?: LivePreview; diff --git a/test/unit/plugin-comprehensive.spec.ts b/test/unit/plugin-comprehensive.spec.ts new file mode 100644 index 0000000..1e7eda5 --- /dev/null +++ b/test/unit/plugin-comprehensive.spec.ts @@ -0,0 +1,592 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * Comprehensive tests for ContentstackPlugin interface, export functionality, + * and basic plugin implementation patterns + */ +import * as Contentstack from "../../src/lib/contentstack"; +import { ContentstackPlugin, StackConfig } from "../../src/lib/types"; +import { ContentstackPlugin as ExportedPlugin } from "../../src/index"; + +// Mock the core module +jest.mock("@contentstack/core", () => ({ + httpClient: jest.fn(() => ({ + defaults: { host: "cdn.contentstack.io" }, + interceptors: { + request: { use: jest.fn() }, + response: { use: jest.fn() }, + }, + })), + retryRequestHandler: jest.fn((req) => req), + retryResponseHandler: jest.fn((res) => res), + retryResponseErrorHandler: jest.fn((error) => Promise.reject(error)), +})); + +describe("Plugin Comprehensive Tests", () => { + describe("ContentstackPlugin Interface", () => { + describe("Interface Implementation", () => { + it("should allow implementing the ContentstackPlugin interface with a class", () => { + class LoggingPlugin implements ContentstackPlugin { + private requestCount = 0; + private responseCount = 0; + + onRequest(config: any): any { + this.requestCount++; + console.log(`Request #${this.requestCount}:`, config.url); + return { + ...config, + headers: { + ...config.headers, + 'X-Request-Count': this.requestCount.toString(), + }, + }; + } + + onResponse(request: any, response: any, data: any): any { + this.responseCount++; + console.log(`Response #${this.responseCount}:`, response.status); + return { + ...response, + data: { + ...data, + _plugin_metadata: { + requestCount: this.requestCount, + responseCount: this.responseCount, + }, + }, + }; + } + + getStats() { + return { + requests: this.requestCount, + responses: this.responseCount, + }; + } + } + + const plugin = new LoggingPlugin(); + expect(plugin).toBeInstanceOf(LoggingPlugin); + expect(typeof plugin.onRequest).toBe('function'); + expect(typeof plugin.onResponse).toBe('function'); + expect(plugin.getStats().requests).toBe(0); + }); + + it("should allow implementing the ContentstackPlugin interface with an object", () => { + const authPlugin: ContentstackPlugin = { + onRequest(config: any): any { + return { + ...config, + headers: { + ...config.headers, + 'Authorization': 'Bearer token123', + 'X-Custom-Auth': 'plugin-auth', + }, + }; + }, + + onResponse(request: any, response: any, data: any): any { + // Remove sensitive data from response + const sanitizedData = { ...data }; + delete sanitizedData.sensitive_field; + + return { + ...response, + data: sanitizedData, + }; + }, + }; + + expect(typeof authPlugin.onRequest).toBe('function'); + expect(typeof authPlugin.onResponse).toBe('function'); + }); + + it("should allow creating performance monitoring plugins", () => { + class PerformancePlugin implements ContentstackPlugin { + private requestTimes = new Map(); + private metrics = { + totalRequests: 0, + totalResponseTime: 0, + errors: 0, + }; + + onRequest(config: any): any { + const requestId = `${config.method}_${config.url}_${Date.now()}`; + this.requestTimes.set(requestId, Date.now()); + this.metrics.totalRequests++; + + return { + ...config, + requestId, + startTime: Date.now(), + }; + } + + onResponse(request: any, response: any, data: any): any { + const requestId = request.requestId; + const startTime = this.requestTimes.get(requestId); + + if (startTime) { + const responseTime = Date.now() - startTime; + this.metrics.totalResponseTime += responseTime; + this.requestTimes.delete(requestId); + } + + if (response.status >= 400) { + this.metrics.errors++; + } + + return { + ...response, + data: { + ...data, + _analytics: { + responseTime: startTime ? Date.now() - startTime : 0, + status: response.status, + }, + }, + }; + } + + getMetrics() { + return { + ...this.metrics, + averageResponseTime: this.metrics.totalRequests > 0 + ? this.metrics.totalResponseTime / this.metrics.totalRequests + : 0, + }; + } + } + + const plugin = new PerformancePlugin(); + expect(plugin.getMetrics().totalRequests).toBe(0); + expect(plugin.getMetrics().averageResponseTime).toBe(0); + }); + }); + + describe("Plugin Integration with Stack", () => { + it("should accept typed plugins in stack configuration", () => { + const mockPlugin: ContentstackPlugin = { + onRequest: jest.fn((config) => config), + onResponse: jest.fn((request, response, data) => response), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [mockPlugin], // This should be type-safe now + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + expect(mockPlugin.onRequest).toHaveBeenCalledTimes(0); // Not called during setup + expect(mockPlugin.onResponse).toHaveBeenCalledTimes(0); + }); + + it("should handle multiple typed plugins", () => { + const requestLogger: ContentstackPlugin = { + onRequest(config: any): any { + console.log('Request logged:', config.url); + return config; + }, + onResponse(request: any, response: any, data: any): any { + return response; + }, + }; + + const responseTransformer: ContentstackPlugin = { + onRequest(config: any): any { + return config; + }, + onResponse(request: any, response: any, data: any): any { + return { + ...response, + data: { + ...data, + transformed: true, + timestamp: new Date().toISOString(), + }, + }; + }, + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [requestLogger, responseTransformer], + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + + it("should provide type safety for plugin method signatures", () => { + // This test verifies that the interface enforces correct method signatures + class TypeSafePlugin implements ContentstackPlugin { + onRequest(config: any): any { + // TypeScript should enforce that config is an object + expect(typeof config).toBe('object'); + return config; + } + + onResponse(request: any, response: any, data: any): any { + // TypeScript should enforce correct parameter types + expect(typeof request).toBe('object'); + expect(typeof response).toBe('object'); + return response; + } + } + + const plugin = new TypeSafePlugin(); + const mockConfig = { url: '/test', method: 'GET' }; + const mockResponse = { status: 200, data: {} }; + + expect(() => plugin.onRequest(mockConfig)).not.toThrow(); + expect(() => plugin.onResponse(mockConfig, mockResponse, {})).not.toThrow(); + }); + }); + + describe("Plugin Examples", () => { + it("should demonstrate common plugin patterns", () => { + // Example 1: Simple request/response logger + const simpleLogger: ContentstackPlugin = { + onRequest(config) { + console.log(`→ ${config.method?.toUpperCase()} ${config.url}`); + return config; + }, + onResponse(request, response, data) { + console.log(`← ${response.status} ${request.url}`); + return response; + }, + }; + + // Example 2: Error handling plugin + const errorHandler: ContentstackPlugin = { + onRequest(config) { + return { ...config, retryAttempts: 0 }; + }, + onResponse(request, response, data) { + if (response.status >= 400) { + console.error(`Error ${response.status}: ${request.url}`); + } + return response; + }, + }; + + expect(typeof simpleLogger.onRequest).toBe('function'); + expect(typeof simpleLogger.onResponse).toBe('function'); + expect(typeof errorHandler.onRequest).toBe('function'); + expect(typeof errorHandler.onResponse).toBe('function'); + }); + + it("should support advanced plugin patterns", () => { + // Caching plugin example + class CachePlugin implements ContentstackPlugin { + private cache = new Map(); + + onRequest(config: any): any { + const cacheKey = `${config.method}_${config.url}`; + const cached = this.cache.get(cacheKey); + + if (cached) { + console.log('Cache hit for:', cacheKey); + } + + return { ...config, cacheKey }; + } + + onResponse(request: any, response: any, data: any): any { + if (response.status === 200 && request.cacheKey) { + this.cache.set(request.cacheKey, data); + } + return response; + } + + clearCache() { + this.cache.clear(); + } + } + + const cachePlugin = new CachePlugin(); + expect(cachePlugin).toBeInstanceOf(CachePlugin); + expect(typeof cachePlugin.clearCache).toBe('function'); + }); + }); + }); + + describe("ContentstackPlugin Export", () => { + it("should export ContentstackPlugin interface from main package", () => { + // We can use it for type annotations + const plugin: ExportedPlugin = { + onRequest(config: any): any { + return config; + }, + onResponse(request: any, response: any, data: any): any { + return response; + } + }; + + expect(typeof plugin.onRequest).toBe('function'); + expect(typeof plugin.onResponse).toBe('function'); + }); + + it("should provide TypeScript intellisense and type checking", () => { + // This test verifies that the interface provides proper TypeScript support + class ExamplePlugin implements ExportedPlugin { + onRequest(config: any): any { + // TypeScript should provide intellisense for config properties + return { + ...config, + headers: { + ...config.headers, + 'X-Plugin': 'example' + } + }; + } + + onResponse(request: any, response: any, data: any): any { + // TypeScript should provide intellisense for response properties + return { + ...response, + data: { + ...data, + processed: true + } + }; + } + } + + const plugin = new ExamplePlugin(); + expect(plugin).toBeInstanceOf(ExamplePlugin); + }); + + it("should allow plugin implementations to be used with stack configuration", () => { + class FullExamplePlugin implements ExportedPlugin { + private pluginName = 'FullExamplePlugin'; + + onRequest(config: any): any { + return { + ...config, + headers: { + ...config.headers, + 'X-Plugin-Name': this.pluginName, + 'X-Plugin-Version': '1.0.0' + } + }; + } + + onResponse(request: any, response: any, data: any): any { + return { + ...response, + data: { + ...data, + _plugin: { + name: this.pluginName, + processedAt: new Date().toISOString() + } + } + }; + } + + getName() { + return this.pluginName; + } + } + + const plugin = new FullExamplePlugin(); + + // Should work in stack configuration + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [plugin] + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + expect(plugin.getName()).toBe('FullExamplePlugin'); + }); + }); + + describe("Plugin Configuration Patterns", () => { + it("should support configurable plugins", () => { + interface PluginConfig { + enabled: boolean; + logLevel: 'debug' | 'info' | 'warn' | 'error'; + prefix?: string; + } + + class ConfigurablePlugin implements ContentstackPlugin { + constructor(private config: PluginConfig) {} + + onRequest(config: any): any { + if (!this.config.enabled) { + return config; + } + + const prefix = this.config.prefix || '[Plugin]'; + if (this.config.logLevel === 'debug') { + console.log(`${prefix} Request:`, config.url); + } + + return { + ...config, + pluginConfig: this.config + }; + } + + onResponse(request: any, response: any, data: any): any { + if (!this.config.enabled) { + return response; + } + + const prefix = this.config.prefix || '[Plugin]'; + if (this.config.logLevel === 'debug') { + console.log(`${prefix} Response:`, response.status); + } + + return response; + } + } + + const plugin = new ConfigurablePlugin({ + enabled: true, + logLevel: 'debug', + prefix: '[MyApp]' + }); + + expect(plugin).toBeInstanceOf(ConfigurablePlugin); + }); + + it("should support plugin composition", () => { + // Base plugin interface + abstract class BasePlugin implements ContentstackPlugin { + abstract onRequest(config: any): any; + abstract onResponse(request: any, response: any, data: any): any; + + protected log(message: string, level: 'info' | 'warn' | 'error' = 'info') { + console.log(`[${level.toUpperCase()}] ${message}`); + } + } + + // Specific plugin implementations + class AuthPlugin extends BasePlugin { + constructor(private token: string) { + super(); + } + + onRequest(config: any): any { + this.log('Adding authentication'); + return { + ...config, + headers: { + ...config.headers, + 'Authorization': `Bearer ${this.token}` + } + }; + } + + onResponse(request: any, response: any, data: any): any { + if (response.status === 401) { + this.log('Authentication failed', 'error'); + } + return response; + } + } + + class MetricsPlugin extends BasePlugin { + private metrics = { requests: 0, responses: 0 }; + + onRequest(config: any): any { + this.metrics.requests++; + this.log(`Request count: ${this.metrics.requests}`); + return config; + } + + onResponse(request: any, response: any, data: any): any { + this.metrics.responses++; + this.log(`Response count: ${this.metrics.responses}`); + return response; + } + + getMetrics() { + return { ...this.metrics }; + } + } + + const authPlugin = new AuthPlugin('test-token'); + const metricsPlugin = new MetricsPlugin(); + + expect(authPlugin).toBeInstanceOf(BasePlugin); + expect(metricsPlugin).toBeInstanceOf(BasePlugin); + expect(metricsPlugin.getMetrics().requests).toBe(0); + }); + }); + + describe("Plugin Error Handling", () => { + it("should handle plugins that throw errors gracefully", () => { + const errorPlugin: ContentstackPlugin = { + onRequest(config: any): any { + throw new Error("Plugin request error"); + }, + onResponse(request: any, response: any, data: any): any { + throw new Error("Plugin response error"); + }, + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [errorPlugin], + }; + + // Stack creation should not throw even if plugins have errors + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + + it("should handle plugins with missing or invalid methods", () => { + // Plugin with missing onResponse method + const incompletePlugin = { + onRequest: jest.fn((req) => req), + // Missing onResponse method + } as any; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [incompletePlugin], + }; + + // Should handle gracefully during stack creation + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + + it("should handle plugins with different return types", () => { + class FlexiblePlugin implements ContentstackPlugin { + onRequest(config: any): any { + // Sometimes return a promise + if (config.async) { + return Promise.resolve({ ...config, asyncProcessed: true }); + } + // Sometimes return synchronously + return { ...config, syncProcessed: true }; + } + + onResponse(request: any, response: any, data: any): any { + // Can return modified response or original + if (request.transform) { + return { + ...response, + data: { ...data, transformed: true } + }; + } + return response; + } + } + + const plugin = new FlexiblePlugin(); + expect(plugin).toBeInstanceOf(FlexiblePlugin); + }); + }); +}); diff --git a/test/unit/plugin-interceptor-comprehensive.spec.ts b/test/unit/plugin-interceptor-comprehensive.spec.ts new file mode 100644 index 0000000..1a09c5c --- /dev/null +++ b/test/unit/plugin-interceptor-comprehensive.spec.ts @@ -0,0 +1,777 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * Comprehensive tests for plugin-interceptor interactions, edge cases, + * execution flow, and integration scenarios + */ +import axios, { AxiosRequestConfig, AxiosResponse } from "axios"; +import * as core from "@contentstack/core"; +import * as Contentstack from "../../src/lib/contentstack"; +import { Stack } from "../../src/lib/stack"; +import { Policy, StackConfig, ContentstackPlugin } from "../../src/lib/types"; + +jest.mock("@contentstack/core"); + +describe("Plugin-Interceptor Comprehensive Tests", () => { + let mockHttpClient: any; + let reqInterceptorCallOrder: string[]; + let resInterceptorCallOrder: string[]; + + beforeEach(() => { + reqInterceptorCallOrder = []; + resInterceptorCallOrder = []; + + mockHttpClient = { + defaults: { + host: "cdn.contentstack.io", + adapter: jest.fn(), + logHandler: jest.fn(), + }, + interceptors: { + request: { + use: jest.fn((handler) => { + // Track the order of request interceptor registrations + if (handler.toString().includes('retryRequestHandler')) { + reqInterceptorCallOrder.push('retry'); + } else if (handler.toString().includes('pluginInstance')) { + reqInterceptorCallOrder.push('plugin'); + } else { + reqInterceptorCallOrder.push('other'); + } + }), + }, + response: { + use: jest.fn((successHandler, errorHandler) => { + // Track the order of response interceptor registrations + if (errorHandler && errorHandler.toString().includes('retryResponseErrorHandler')) { + resInterceptorCallOrder.push('retry-error'); + resInterceptorCallOrder.push('retry-success'); // Both success and error handler for retry + } else if (successHandler && successHandler.toString().includes('pluginInstance')) { + resInterceptorCallOrder.push('plugin-success'); + } else { + resInterceptorCallOrder.push('other-success'); + } + }), + }, + }, + }; + + (core.httpClient as jest.Mock).mockReturnValue(mockHttpClient); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe("Interceptor Registration Order", () => { + it("should register retry interceptors before plugin interceptors", () => { + const mockPlugin = { + onRequest: jest.fn((req) => req), + onResponse: jest.fn((req, res, data) => res), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [mockPlugin], + }; + + Contentstack.stack(config); + + // Verify registration order for request interceptors + expect(reqInterceptorCallOrder).toEqual(['retry', 'plugin']); + + // Verify registration order for response interceptors + expect(resInterceptorCallOrder).toContain('retry-success'); + expect(resInterceptorCallOrder).toContain('retry-error'); + expect(resInterceptorCallOrder).toContain('plugin-success'); + + // Plugin response interceptor should be registered after retry response interceptor + // (which means plugins run BEFORE retry in the response chain due to Axios reverse order) + const pluginIndex = resInterceptorCallOrder.indexOf('plugin-success'); + const retryIndex = resInterceptorCallOrder.indexOf('retry-success'); + expect(pluginIndex).toBeGreaterThan(retryIndex); + }); + + it("should handle empty plugins array", () => { + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [], + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + + // Should only have retry interceptors (but empty plugins array still triggers plugin registration) + expect(mockHttpClient.interceptors.request.use).toHaveBeenCalledTimes(2); + expect(mockHttpClient.interceptors.response.use).toHaveBeenCalledTimes(2); + }); + }); + + describe("Plugin Error Handling Edge Cases", () => { + it("should handle plugin throwing error in onRequest without breaking retry logic", () => { + const errorThrowingPlugin = { + onRequest: jest.fn(() => { + throw new Error("Plugin request error"); + }), + onResponse: jest.fn((req, res, data) => res), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [errorThrowingPlugin], + }; + + // Should not throw during stack creation + expect(() => Contentstack.stack(config)).not.toThrow(); + + // Verify plugin interceptor was still registered + expect(mockHttpClient.interceptors.request.use).toHaveBeenCalledWith( + expect.any(Function) + ); + }); + + it("should handle plugin throwing error in onResponse", () => { + const errorThrowingPlugin = { + onRequest: jest.fn((req) => req), + onResponse: jest.fn(() => { + throw new Error("Plugin response error"); + }), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [errorThrowingPlugin], + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + + it("should handle plugins with async operations", () => { + const asyncPlugin = { + onRequest: jest.fn(async (req) => { + await new Promise(resolve => setTimeout(resolve, 1)); + return { ...req, asyncProcessed: true }; + }), + onResponse: jest.fn(async (req, res, data) => { + await new Promise(resolve => setTimeout(resolve, 1)); + return { ...res, asyncProcessed: true }; + }), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [asyncPlugin], + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + }); + + describe("Plugin Mutation Edge Cases", () => { + it("should handle plugin modifying retry-critical request properties", () => { + const retryPropertyMutatingPlugin = { + onRequest: jest.fn((reqConfig: AxiosRequestConfig) => { + // Plugin modifies properties that retry logic depends on + return { + ...reqConfig, + retryCount: 10, // Should not affect retry logic + url: "https://malicious-host.com", // Should not break retries + timeout: 1, // Very short timeout + }; + }), + onResponse: jest.fn((req, res, data) => res), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [retryPropertyMutatingPlugin], + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + expect(retryPropertyMutatingPlugin.onRequest).not.toHaveBeenCalled(); // Only registered, not called yet + }); + + it("should handle plugin modifying response before retry handler sees it", () => { + const responseModifyingPlugin = { + onRequest: jest.fn((req) => req), + onResponse: jest.fn((req, res, data) => { + // Plugin modifies response that retry logic might depend on + return { + ...res, + status: 200, // Changing from potential error status + data: { modified: true }, + headers: { + ...res.headers, + "x-ratelimit-remaining": "0", // This could affect retry logic + }, + }; + }), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [responseModifyingPlugin], + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + + it("should handle multiple plugins with conflicting modifications", () => { + const plugin1 = { + onRequest: jest.fn((req) => ({ ...req, customHeader1: "value1" })), + onResponse: jest.fn((req, res, data) => ({ ...res, plugin1: true })), + }; + + const plugin2 = { + onRequest: jest.fn((req) => ({ ...req, customHeader1: "value2", customHeader2: "value2" })), + onResponse: jest.fn((req, res, data) => ({ ...res, plugin2: true })), + }; + + const plugin3 = { + onRequest: jest.fn((req) => req), // No modification + onResponse: jest.fn((req, res, data) => ({ ...res, plugin3: true })), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [plugin1, plugin2, plugin3], + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + + // Verify all plugins were registered + expect(mockHttpClient.interceptors.request.use).toHaveBeenCalledTimes(2); // retry + plugin interceptor + expect(mockHttpClient.interceptors.response.use).toHaveBeenCalledTimes(2); // retry + plugin interceptor + }); + }); + + describe("Cache + Plugin + Retry Interaction", () => { + it("should handle plugins with cache adapter and retry logic", () => { + const cacheInterferingPlugin = { + onRequest: jest.fn((req) => { + // Plugin might interfere with cache keys + return { + ...req, + contentTypeUid: "modified-uid", // This affects cache key + maxAge: 0, // This affects cache behavior + }; + }), + onResponse: jest.fn((req, res, data) => { + // Plugin modifies cached response + return { + ...res, + data: { ...data, cached: false }, + }; + }), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [cacheInterferingPlugin], + cacheOptions: { + policy: Policy.CACHE_THEN_NETWORK, + storeType: "localStorage" as any, + }, + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + + // Verify cache adapter was set + expect(mockHttpClient.defaults.adapter).toBeDefined(); + }); + + it("should handle plugins with different cache policies", () => { + const plugin = { + onRequest: jest.fn((req) => req), + onResponse: jest.fn((req, res, data) => res), + }; + + const policies = [ + Policy.IGNORE_CACHE, + Policy.CACHE_THEN_NETWORK, + Policy.CACHE_ELSE_NETWORK, + Policy.NETWORK_ELSE_CACHE, + ]; + + policies.forEach((policy) => { + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [plugin], + cacheOptions: { + policy, + storeType: "localStorage" as any, + }, + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + }); + }); + + describe("Plugin Execution Flow", () => { + let retryRequestHandler: jest.Mock; + let retryResponseHandler: jest.Mock; + let retryResponseErrorHandler: jest.Mock; + let executionOrder: string[]; + + beforeEach(() => { + executionOrder = []; + + retryRequestHandler = jest.fn((req) => { + executionOrder.push('retry-request'); + return { ...req, retryCount: (req.retryCount || 0) + 1 }; + }); + + retryResponseHandler = jest.fn((res) => { + executionOrder.push('retry-response'); + return res; + }); + + retryResponseErrorHandler = jest.fn((error, config, axiosInstance) => { + executionOrder.push('retry-error'); + return Promise.reject(error); + }); + + // Mock the core functions + (core.retryRequestHandler as jest.Mock) = retryRequestHandler; + (core.retryResponseHandler as jest.Mock) = retryResponseHandler; + (core.retryResponseErrorHandler as jest.Mock) = retryResponseErrorHandler; + + // Update mock to use real axios creation but with mocked interceptors + jest.spyOn(axios, 'create').mockImplementation((config) => { + const mockInstance = { + defaults: { ...config }, + interceptors: { + request: { + use: jest.fn((handler) => { + // Store the handler for later execution + mockInstance.requestHandlers = mockInstance.requestHandlers || []; + mockInstance.requestHandlers.push(handler); + return mockInstance.requestHandlers.length - 1; + }), + }, + response: { + use: jest.fn((successHandler, errorHandler) => { + mockInstance.responseHandlers = mockInstance.responseHandlers || []; + mockInstance.responseHandlers.push({ successHandler, errorHandler }); + return mockInstance.responseHandlers.length - 1; + }), + }, + }, + request: jest.fn(), + get: jest.fn(), + post: jest.fn(), + put: jest.fn(), + delete: jest.fn(), + httpClientParams: config, + } as any; + + return mockInstance; + }); + }); + + it("should execute request interceptors in correct order: retry -> plugins", () => { + const plugin1 = { + onRequest: jest.fn((req) => { + executionOrder.push('plugin1-request'); + return req; + }), + onResponse: jest.fn((req, res, data) => { + executionOrder.push('plugin1-response'); + return res; + }), + }; + + const plugin2 = { + onRequest: jest.fn((req) => { + executionOrder.push('plugin2-request'); + return req; + }), + onResponse: jest.fn((req, res, data) => { + executionOrder.push('plugin2-response'); + return res; + }), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [plugin1, plugin2], + }; + + Contentstack.stack(config); + + // Verify interceptors were registered in correct order + const axiosInstance = (core.httpClient as jest.Mock).mock.results[0].value; + expect(axiosInstance.interceptors.request.use).toHaveBeenCalledTimes(2); + expect(axiosInstance.interceptors.response.use).toHaveBeenCalledTimes(2); + + // Get the registered interceptor functions + const requestCalls = axiosInstance.interceptors.request.use.mock.calls; + + // Simulate request execution order (Axios executes in registration order) + const retryRequestInterceptor = requestCalls[0][0]; + const pluginRequestInterceptor = requestCalls[1][0]; + + const mockRequest = { url: '/test', method: 'GET' }; + + // Execute request interceptors in order + let modifiedRequest = retryRequestInterceptor(mockRequest); + modifiedRequest = pluginRequestInterceptor(modifiedRequest); + + expect(plugin1.onRequest).toHaveBeenCalled(); + expect(plugin2.onRequest).toHaveBeenCalled(); + }); + + it("should preserve retry count through plugin modifications", () => { + const retryCountModifyingPlugin = { + onRequest: jest.fn((req) => { + // Plugin tries to modify retry count + return { + ...req, + retryCount: 999, // Should not affect actual retry logic + customProperty: 'added', + }; + }), + onResponse: jest.fn((req, res, data) => res), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [retryCountModifyingPlugin], + }; + + const stack = Contentstack.stack(config); + expect(stack).toBeInstanceOf(Stack); + + // Verify plugin was registered + const axiosInstance = (core.httpClient as jest.Mock).mock.results[0].value; + expect(axiosInstance.interceptors.request.use).toHaveBeenCalledTimes(2); + }); + }); + + describe("Plugin Type Safety Edge Cases", () => { + it("should handle plugin with missing methods", () => { + const incompletePlugin = { + onRequest: jest.fn((req) => req), + // Missing onResponse method + } as any; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [incompletePlugin], + }; + + // Should handle gracefully during stack creation + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + + it("should handle plugins when retry is disabled", () => { + const plugin = { + onRequest: jest.fn((req) => req), + onResponse: jest.fn((req, res, data) => res), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [plugin], + retryOnError: false, + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + + it("should handle plugins with custom retry conditions", () => { + const plugin = { + onRequest: jest.fn((req) => req), + onResponse: jest.fn((req, res, data) => res), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [plugin], + retryCondition: jest.fn(() => true), + retryLimit: 3, + retryDelay: 100, + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + }); + + describe("Plugin State Management", () => { + it("should handle plugins that maintain internal state", () => { + class StatefulPlugin { + private requestCount = 0; + private responseCount = 0; + + onRequest = jest.fn((req) => { + this.requestCount++; + return { ...req, requestId: this.requestCount }; + }); + + onResponse = jest.fn((req, res, data) => { + this.responseCount++; + return { ...res, responseId: this.responseCount }; + }); + } + + const statefulPlugin = new StatefulPlugin(); + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [statefulPlugin], + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + + it("should handle plugins that modify config object", () => { + const configModifyingPlugin = { + onRequest: jest.fn((req) => { + // Plugin tries to modify the original config + if (req.stackConfig) { + req.stackConfig.modified = true; + } + return req; + }), + onResponse: jest.fn((req, res, data) => res), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [configModifyingPlugin], + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + }); + + describe("Performance and Scale Testing", () => { + it("should handle large number of plugins efficiently", () => { + const plugins = Array.from({ length: 50 }, (_, i) => ({ + onRequest: jest.fn((req) => ({ + ...req, + [`plugin${i}`]: true, + })), + onResponse: jest.fn((req, res, data) => ({ + ...res, + data: { + ...data, + [`plugin${i}Processed`]: true, + }, + })), + })); + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins, + }; + + const startTime = Date.now(); + const stack = Contentstack.stack(config); + const endTime = Date.now(); + + expect(stack).toBeInstanceOf(Stack); + expect(endTime - startTime).toBeLessThan(100); // Should be fast + }); + + it("should handle plugins with large data modifications", () => { + const largeDataSize = 10000; // 10KB of data + const largeData = 'x'.repeat(largeDataSize); + + const largeDataPlugin = { + onRequest: jest.fn((req) => ({ + ...req, + largePayload: largeData, + })), + onResponse: jest.fn((req, res, data) => ({ + ...res, + data: { + ...data, + largeResponse: largeData, + }, + })), + }; + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [largeDataPlugin], + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + }); + }); + + describe("Plugin Configuration Edge Cases", () => { + it("should handle plugins with different configuration combinations", () => { + const plugin = { + onRequest: jest.fn((req) => req), + onResponse: jest.fn((req, res, data) => res), + }; + + const configs = [ + // With cache and retry + { + apiKey: "test", + deliveryToken: "test", + environment: "test", + plugins: [plugin], + cacheOptions: { policy: Policy.CACHE_THEN_NETWORK }, + retryOnError: true, + }, + // With custom retry settings + { + apiKey: "test", + deliveryToken: "test", + environment: "test", + plugins: [plugin], + retryLimit: 10, + retryDelay: 1000, + retryCondition: jest.fn(() => false), + }, + // With live preview + { + apiKey: "test", + deliveryToken: "test", + environment: "test", + plugins: [plugin], + live_preview: { enable: true }, + }, + // With early access headers + { + apiKey: "test", + deliveryToken: "test", + environment: "test", + plugins: [plugin], + early_access: ['feature1', 'feature2'], + }, + ]; + + configs.forEach((config) => { + expect(() => Contentstack.stack(config as StackConfig)).not.toThrow(); + }); + }); + + it("should handle real-world plugin scenarios", () => { + // Simulate a complex, real-world plugin + class ProductionPlugin implements ContentstackPlugin { + private metrics = { + requests: 0, + responses: 0, + errors: 0, + cache_hits: 0 + }; + + onRequest(config: any): any { + this.metrics.requests++; + + // Add request ID for tracking + const requestId = `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + + // Add monitoring headers + return { + ...config, + headers: { + ...config.headers, + 'X-Request-ID': requestId, + 'X-Client-Version': '1.0.0', + 'X-Timestamp': new Date().toISOString() + }, + metadata: { + ...config.metadata, + requestId, + startTime: performance.now() + } + }; + } + + onResponse(request: any, response: any, data: any): any { + this.metrics.responses++; + + // Track errors + if (response.status >= 400) { + this.metrics.errors++; + } + + // Track cache hits + if (response.headers['x-cache'] === 'HIT') { + this.metrics.cache_hits++; + } + + // Add response metadata + return { + ...response, + data: { + ...data, + _meta: { + requestId: request.metadata?.requestId, + processingTime: request.metadata?.startTime + ? performance.now() - request.metadata.startTime + : 0, + timestamp: new Date().toISOString() + } + } + }; + } + + getMetrics() { + return { ...this.metrics }; + } + } + + const plugin = new ProductionPlugin(); + + const config: StackConfig = { + apiKey: "test-api-key", + deliveryToken: "test-delivery-token", + environment: "test-env", + plugins: [plugin], + cacheOptions: { + policy: Policy.CACHE_ELSE_NETWORK, + storeType: "localStorage" as any, + }, + retryOnError: true, + retryLimit: 3, + }; + + expect(() => Contentstack.stack(config)).not.toThrow(); + expect(plugin.getMetrics().requests).toBe(0); // Not called during setup + }); + }); +}); From 14170cde5de0ffd84693d16a4301e5634eeac0c8 Mon Sep 17 00:00:00 2001 From: Nadeem Patwekar Date: Wed, 17 Sep 2025 15:39:40 +0530 Subject: [PATCH 2/2] chore: bump version to 4.10.0 in package.json --- .talismanrc | 2 +- CHANGELOG.md | 4 +- package-lock.json | 536 +++++++++++++++++++++++++--------------------- package.json | 2 +- 4 files changed, 292 insertions(+), 252 deletions(-) diff --git a/.talismanrc b/.talismanrc index 9d03945..2aa5661 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,6 +1,6 @@ fileignoreconfig: - filename: package-lock.json - checksum: 17c3944c70209ee40840cee33e891b57cf1c672ecb03b410b71ad6fb0242a86e + checksum: 32308dbe614c142c4804ff7c81baedddba058c5458e1d233fefb1d8070bf1905 - filename: test/unit/query-optimization-comprehensive.spec.ts checksum: f5aaf6c784d7c101a05ca513c584bbd6e95f963d1e42779f2596050d9bcbac96 - filename: src/lib/entries.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index ac5010d..b0700ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ -### Version: 4.9.1 -#### Date: Aug-25-2025 +### Version: 4.10.0 +#### Date: Sep-22-2025 Fix: Enhance retry logic to use configured retryDelay Enhancement: Caching logic to use combination of content type uid and entry uid diff --git a/package-lock.json b/package-lock.json index 81b4ea4..044ddbb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentstack/delivery-sdk", - "version": "4.9.1", + "version": "4.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/delivery-sdk", - "version": "4.9.1", + "version": "4.10.0", "license": "MIT", "dependencies": { "@contentstack/core": "^1.3.0", @@ -39,20 +39,6 @@ "webpack-cli": "^5.1.4" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", @@ -69,9 +55,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", - "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", "dev": true, "license": "MIT", "engines": { @@ -79,22 +65,22 @@ } }, "node_modules/@babel/core": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", - "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "dev": true, "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.3", - "@babel/parser": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.3", - "@babel/types": "^7.28.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -388,27 +374,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", - "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", - "@babel/types": "^7.28.2" + "@babel/types": "^7.28.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", - "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.2" + "@babel/types": "^7.28.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -889,9 +875,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.0.tgz", - "integrity": "sha512-gKKnwjpdx5sER/wl0WN0efUBFzF/56YZO0RJrSYP4CljXnP31ByY7fol89AzomdlLNzI36AvOTmYHsnZTCkq8Q==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.4.tgz", + "integrity": "sha512-1yxmvN0MJHOhPVmAsmoW5liWwoILobu/d/ShymZmj867bAdxGbehIrew1DuLpw2Ukv+qDSSPQdYW1dLNE7t11A==", "dev": true, "license": "MIT", "dependencies": { @@ -939,9 +925,9 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.3.tgz", - "integrity": "sha512-DoEWC5SuxuARF2KdKmGUq3ghfPMO6ZzR12Dnp5gubwbeWJo4dbNWXJPVlwvh4Zlq6Z7YVvL8VFxeSOJgjsx4Sg==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", + "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", "dev": true, "license": "MIT", "dependencies": { @@ -950,7 +936,7 @@ "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", - "@babel/traverse": "^7.28.3" + "@babel/traverse": "^7.28.4" }, "engines": { "node": ">=6.9.0" @@ -1343,9 +1329,9 @@ } }, "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.0.tgz", - "integrity": "sha512-9VNGikXxzu5eCiQjdE4IZn8sb9q7Xsk5EXLDBKUYg1e/Tve8/05+KJEtcxGxAgCY5t/BpKQM+JEL/yT4tvgiUA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", + "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", "dev": true, "license": "MIT", "dependencies": { @@ -1353,7 +1339,7 @@ "@babel/helper-plugin-utils": "^7.27.1", "@babel/plugin-transform-destructuring": "^7.28.0", "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.0" + "@babel/traverse": "^7.28.4" }, "engines": { "node": ">=6.9.0" @@ -1480,9 +1466,9 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.3.tgz", - "integrity": "sha512-K3/M/a4+ESb5LEldjQb+XSrpY0nF+ZBFlTCbSnKaYAMfD8v33O6PMs4uYnOk19HlcsI8WMu3McdFPTiQHF/1/A==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", + "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", "dev": true, "license": "MIT", "dependencies": { @@ -1838,9 +1824,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz", - "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "dev": true, "license": "MIT", "engines": { @@ -1863,18 +1849,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", - "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.3", + "@babel/parser": "^7.28.4", "@babel/template": "^7.27.2", - "@babel/types": "^7.28.2", + "@babel/types": "^7.28.4", "debug": "^4.3.1" }, "engines": { @@ -1882,9 +1868,9 @@ } }, "node_modules/@babel/types": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1903,9 +1889,9 @@ "license": "MIT" }, "node_modules/@contentstack/core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@contentstack/core/-/core-1.3.0.tgz", - "integrity": "sha512-WT1+o9Vv42gKMIqy0sel6tD6OyIY681hawB4sstrioBfxpN3HaE2b/MxQpuSq259vbddoleG4525Dwpq9uAEcw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@contentstack/core/-/core-1.3.1.tgz", + "integrity": "sha512-RuaqNMZreN/ihnFJtGvtxK5NYuQuar1qBwWf0wqMsESHZCp+7Ohk1iSwq5E+7JN8Rzz40eiBiXklllzhoC0+5g==", "license": "MIT", "dependencies": { "axios": "^1.11.0", @@ -1930,9 +1916,9 @@ } }, "node_modules/@contentstack/utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@contentstack/utils/-/utils-1.4.1.tgz", - "integrity": "sha512-P/1Xk3kku1WUHPd+djjZq1NQrUP/OhmiMLRkdNzixMaS4U9LXEJP6iU02YoYnXXjlFuI2dz/OzthCoI5/DPWQQ==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@contentstack/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-OGRYPws6ceM9Qf+s9CPh5OeG+ujBSchqvuAL0lvxMnoFm5pM9bZkxP42e/fVGOZSP96eoSfUzqZyBZgLupxedg==", "license": "MIT" }, "node_modules/@cspotcode/source-map-support": { @@ -2430,9 +2416,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", - "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { @@ -2443,9 +2429,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", "engines": { @@ -2481,9 +2467,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { @@ -2844,6 +2830,17 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -2874,9 +2871,9 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { @@ -3660,9 +3657,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.48.1.tgz", - "integrity": "sha512-rGmb8qoG/zdmKoYELCBwu7vt+9HxZ7Koos3pD0+sH5fR3u3Wb/jGcpnqxcnWsPEKDUyzeLSqksN8LJtgXjqBYw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.2.tgz", + "integrity": "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==", "cpu": [ "arm" ], @@ -3674,9 +3671,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.48.1.tgz", - "integrity": "sha512-4e9WtTxrk3gu1DFE+imNJr4WsL13nWbD/Y6wQcyku5qadlKHY3OQ3LJ/INrrjngv2BJIHnIzbqMk1GTAC2P8yQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.2.tgz", + "integrity": "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==", "cpu": [ "arm64" ], @@ -3688,9 +3685,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.48.1.tgz", - "integrity": "sha512-+XjmyChHfc4TSs6WUQGmVf7Hkg8ferMAE2aNYYWjiLzAS/T62uOsdfnqv+GHRjq7rKRnYh4mwWb4Hz7h/alp8A==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.2.tgz", + "integrity": "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==", "cpu": [ "arm64" ], @@ -3702,9 +3699,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.48.1.tgz", - "integrity": "sha512-upGEY7Ftw8M6BAJyGwnwMw91rSqXTcOKZnnveKrVWsMTF8/k5mleKSuh7D4v4IV1pLxKAk3Tbs0Lo9qYmii5mQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.2.tgz", + "integrity": "sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A==", "cpu": [ "x64" ], @@ -3716,9 +3713,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.48.1.tgz", - "integrity": "sha512-P9ViWakdoynYFUOZhqq97vBrhuvRLAbN/p2tAVJvhLb8SvN7rbBnJQcBu8e/rQts42pXGLVhfsAP0k9KXWa3nQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.2.tgz", + "integrity": "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==", "cpu": [ "arm64" ], @@ -3730,9 +3727,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.48.1.tgz", - "integrity": "sha512-VLKIwIpnBya5/saccM8JshpbxfyJt0Dsli0PjXozHwbSVaHTvWXJH1bbCwPXxnMzU4zVEfgD1HpW3VQHomi2AQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.2.tgz", + "integrity": "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==", "cpu": [ "x64" ], @@ -3744,9 +3741,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.48.1.tgz", - "integrity": "sha512-3zEuZsXfKaw8n/yF7t8N6NNdhyFw3s8xJTqjbTDXlipwrEHo4GtIKcMJr5Ed29leLpB9AugtAQpAHW0jvtKKaQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.2.tgz", + "integrity": "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==", "cpu": [ "arm" ], @@ -3758,9 +3755,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.48.1.tgz", - "integrity": "sha512-leo9tOIlKrcBmmEypzunV/2w946JeLbTdDlwEZ7OnnsUyelZ72NMnT4B2vsikSgwQifjnJUbdXzuW4ToN1wV+Q==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.2.tgz", + "integrity": "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==", "cpu": [ "arm" ], @@ -3772,9 +3769,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.48.1.tgz", - "integrity": "sha512-Vy/WS4z4jEyvnJm+CnPfExIv5sSKqZrUr98h03hpAMbE2aI0aD2wvK6GiSe8Gx2wGp3eD81cYDpLLBqNb2ydwQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.2.tgz", + "integrity": "sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg==", "cpu": [ "arm64" ], @@ -3786,9 +3783,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.48.1.tgz", - "integrity": "sha512-x5Kzn7XTwIssU9UYqWDB9VpLpfHYuXw5c6bJr4Mzv9kIv242vmJHbI5PJJEnmBYitUIfoMCODDhR7KoZLot2VQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.2.tgz", + "integrity": "sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ==", "cpu": [ "arm64" ], @@ -3799,10 +3796,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.48.1.tgz", - "integrity": "sha512-yzCaBbwkkWt/EcgJOKDUdUpMHjhiZT/eDktOPWvSRpqrVE04p0Nd6EGV4/g7MARXXeOqstflqsKuXVM3H9wOIQ==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.50.2.tgz", + "integrity": "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==", "cpu": [ "loong64" ], @@ -3814,9 +3811,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.48.1.tgz", - "integrity": "sha512-UK0WzWUjMAJccHIeOpPhPcKBqax7QFg47hwZTp6kiMhQHeOYJeaMwzeRZe1q5IiTKsaLnHu9s6toSYVUlZ2QtQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.2.tgz", + "integrity": "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==", "cpu": [ "ppc64" ], @@ -3828,9 +3825,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.48.1.tgz", - "integrity": "sha512-3NADEIlt+aCdCbWVZ7D3tBjBX1lHpXxcvrLt/kdXTiBrOds8APTdtk2yRL2GgmnSVeX4YS1JIf0imFujg78vpw==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.2.tgz", + "integrity": "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==", "cpu": [ "riscv64" ], @@ -3842,9 +3839,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.48.1.tgz", - "integrity": "sha512-euuwm/QTXAMOcyiFCcrx0/S2jGvFlKJ2Iro8rsmYL53dlblp3LkUQVFzEidHhvIPPvcIsxDhl2wkBE+I6YVGzA==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.2.tgz", + "integrity": "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==", "cpu": [ "riscv64" ], @@ -3856,9 +3853,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.48.1.tgz", - "integrity": "sha512-w8mULUjmPdWLJgmTYJx/W6Qhln1a+yqvgwmGXcQl2vFBkWsKGUBRbtLRuKJUln8Uaimf07zgJNxOhHOvjSQmBQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.2.tgz", + "integrity": "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==", "cpu": [ "s390x" ], @@ -3870,9 +3867,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.48.1.tgz", - "integrity": "sha512-90taWXCWxTbClWuMZD0DKYohY1EovA+W5iytpE89oUPmT5O1HFdf8cuuVIylE6vCbrGdIGv85lVRzTcpTRZ+kA==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.2.tgz", + "integrity": "sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA==", "cpu": [ "x64" ], @@ -3884,9 +3881,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.48.1.tgz", - "integrity": "sha512-2Gu29SkFh1FfTRuN1GR1afMuND2GKzlORQUP3mNMJbqdndOg7gNsa81JnORctazHRokiDzQ5+MLE5XYmZW5VWg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.2.tgz", + "integrity": "sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw==", "cpu": [ "x64" ], @@ -3897,10 +3894,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.2.tgz", + "integrity": "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.48.1.tgz", - "integrity": "sha512-6kQFR1WuAO50bxkIlAVeIYsz3RUx+xymwhTo9j94dJ+kmHe9ly7muH23sdfWduD0BA8pD9/yhonUvAjxGh34jQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.2.tgz", + "integrity": "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==", "cpu": [ "arm64" ], @@ -3912,9 +3923,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.48.1.tgz", - "integrity": "sha512-RUyZZ/mga88lMI3RlXFs4WQ7n3VyU07sPXmMG7/C1NOi8qisUg57Y7LRarqoGoAiopmGmChUhSwfpvQ3H5iGSQ==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.2.tgz", + "integrity": "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==", "cpu": [ "ia32" ], @@ -3926,9 +3937,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.48.1.tgz", - "integrity": "sha512-8a/caCUN4vkTChxkaIJcMtwIVcBhi4X2PQRoT+yCK3qRYaZ7cURrmJFL5Ux9H9RaMIXj9RuihckdmkBX3zZsgg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.2.tgz", + "integrity": "sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA==", "cpu": [ "x64" ], @@ -4007,18 +4018,17 @@ } }, "node_modules/@slack/oauth": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@slack/oauth/-/oauth-3.0.3.tgz", - "integrity": "sha512-N3pLJPacZ57bqmD1HzHDmHe/CNsL9pESZXRw7pfv6QXJVRgufPIW84aRpAez2Xb0616RpGBYZW5dZH0Nbskwyg==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@slack/oauth/-/oauth-3.0.4.tgz", + "integrity": "sha512-+8H0g7mbrHndEUbYCP7uYyBCbwqmm3E6Mo3nfsDvZZW74zKk1ochfH/fWSvGInYNCVvaBUbg3RZBbTp0j8yJCg==", "dev": true, "license": "MIT", "dependencies": { "@slack/logger": "^4", - "@slack/web-api": "^7.9.1", + "@slack/web-api": "^7.10.0", "@types/jsonwebtoken": "^9", "@types/node": ">=18", - "jsonwebtoken": "^9", - "lodash.isstring": "^4" + "jsonwebtoken": "^9" }, "engines": { "node": ">=18", @@ -4026,14 +4036,14 @@ } }, "node_modules/@slack/socket-mode": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@slack/socket-mode/-/socket-mode-2.0.4.tgz", - "integrity": "sha512-PB2fO4TSv47TXJ6WlKY7BeVNdcHcpPOxZsztGyG7isWXp69MVj+xAzQ3KSZ8aVTgV59f8xFJPXSHipn1x2Z5IQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@slack/socket-mode/-/socket-mode-2.0.5.tgz", + "integrity": "sha512-VaapvmrAifeFLAFaDPfGhEwwunTKsI6bQhYzxRXw7BSujZUae5sANO76WqlVsLXuhVtCVrBWPiS2snAQR2RHJQ==", "dev": true, "license": "MIT", "dependencies": { "@slack/logger": "^4", - "@slack/web-api": "^7.9.1", + "@slack/web-api": "^7.10.0", "@types/node": ">=18", "@types/ws": "^8", "eventemitter3": "^5", @@ -4354,13 +4364,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.0.tgz", - "integrity": "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow==", + "version": "24.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.5.1.tgz", + "integrity": "sha512-/SQdmUP2xa+1rdx7VwB9yPq8PaKej8TD5cQ+XfKDPWWC+VDJU4rvVVagXqKUzhKjtFoNA8rXDJAkCxQPAe00+Q==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~7.10.0" + "undici-types": "~7.12.0" } }, "node_modules/@types/node-localstorage": { @@ -5247,6 +5257,16 @@ ], "license": "MIT" }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.4.tgz", + "integrity": "sha512-L+YvJwGAgwJBV1p6ffpSTa2KRc69EeeYGYjRVWKs0GKrK+LON0GC0gV+rKSNtALEDvMDqkvCFq9r1r94/Gjwxw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -5304,9 +5324,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.3.tgz", - "integrity": "sha512-cDGv1kkDI4/0e5yON9yM5G/0A5u8sf5TnmdX5C9qHzI9PPu++sQ9zjm1k9NiOrf3riY4OkK0zSGqfvJyJsgCBQ==", + "version": "4.26.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", + "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", "dev": true, "funding": [ { @@ -5324,9 +5344,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001735", - "electron-to-chromium": "^1.5.204", - "node-releases": "^2.0.19", + "baseline-browser-mapping": "^2.8.3", + "caniuse-lite": "^1.0.30001741", + "electron-to-chromium": "^1.5.218", + "node-releases": "^2.0.21", "update-browserslist-db": "^1.1.3" }, "bin": { @@ -5484,9 +5505,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001737", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001737.tgz", - "integrity": "sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==", + "version": "1.0.30001743", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", + "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==", "dev": true, "funding": [ { @@ -5930,9 +5951,9 @@ } }, "node_modules/debug": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", - "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "license": "MIT", "dependencies": { @@ -6153,9 +6174,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.208", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.208.tgz", - "integrity": "sha512-ozZyibehoe7tOhNaf16lKmljVf+3npZcJIEbJRVftVsmAg5TeA1mGS9dVCZzOwr2xT7xK15V0p7+GZqSPgkuPg==", + "version": "1.5.220", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.220.tgz", + "integrity": "sha512-TWXijEwR1ggr4BdAKrb1nMNqYLTx1/4aD1fkeZU+FVJGTKu53/T7UyHKXlqEX3Ub02csyHePbHmkvnrjcaYzMA==", "dev": true, "license": "ISC" }, @@ -6253,9 +6274,9 @@ } }, "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6924,9 +6945,9 @@ "license": "MIT" }, "node_modules/fs-extra": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", - "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", "dev": true, "license": "MIT", "dependencies": { @@ -7944,9 +7965,9 @@ } }, "node_modules/jest-circus/node_modules/dedent": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", - "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", "dev": true, "license": "MIT", "peerDependencies": { @@ -8981,9 +9002,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.18", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", - "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", "dev": true, "license": "MIT", "dependencies": { @@ -9252,9 +9273,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", + "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", "dev": true, "license": "MIT" }, @@ -9311,9 +9332,9 @@ } }, "node_modules/nwsapi": { - "version": "2.2.21", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.21.tgz", - "integrity": "sha512-o6nIY3qwiSXl7/LuOU0Dmuctd34Yay0yeuZRLFmDPrrdHpXKFndPj3hM+YEPVHYC5fx2otBx4Ilc/gyYSAUaIA==", + "version": "2.2.22", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.22.tgz", + "integrity": "sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==", "dev": true, "license": "MIT" }, @@ -9796,13 +9817,14 @@ "license": "ISC" }, "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=16" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/path-type": { @@ -10054,19 +10076,36 @@ } }, "node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", + "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", "dev": true, "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", - "iconv-lite": "0.6.3", + "iconv-lite": "0.7.0", "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.10" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/react-is": { @@ -10126,9 +10165,9 @@ "license": "MIT" }, "node_modules/regenerate-unicode-properties": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", "dev": true, "license": "MIT", "dependencies": { @@ -10139,18 +10178,18 @@ } }, "node_modules/regexpu-core": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", - "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.3.1.tgz", + "integrity": "sha512-DzcswPr252wEr7Qz8AyAVbfyBDKLoYp6eRA1We2Fa9qirRFSdtkP5sHr3yglDKy2BbA0fd2T+j/CUSKes3FeVQ==", "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.0", + "regenerate-unicode-properties": "^10.2.2", "regjsgen": "^0.8.0", "regjsparser": "^0.12.0", "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" + "unicode-match-property-value-ecmascript": "^2.2.1" }, "engines": { "node": ">=4" @@ -10307,9 +10346,9 @@ } }, "node_modules/rollup": { - "version": "4.48.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.48.1.tgz", - "integrity": "sha512-jVG20NvbhTYDkGAty2/Yh7HK6/q3DGSRH4o8ALKGArmMuaauM9kLfoMZ+WliPwA5+JHr2lTn3g557FxBV87ifg==", + "version": "4.50.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.2.tgz", + "integrity": "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==", "dev": true, "license": "MIT", "dependencies": { @@ -10323,26 +10362,27 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.48.1", - "@rollup/rollup-android-arm64": "4.48.1", - "@rollup/rollup-darwin-arm64": "4.48.1", - "@rollup/rollup-darwin-x64": "4.48.1", - "@rollup/rollup-freebsd-arm64": "4.48.1", - "@rollup/rollup-freebsd-x64": "4.48.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.48.1", - "@rollup/rollup-linux-arm-musleabihf": "4.48.1", - "@rollup/rollup-linux-arm64-gnu": "4.48.1", - "@rollup/rollup-linux-arm64-musl": "4.48.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.48.1", - "@rollup/rollup-linux-ppc64-gnu": "4.48.1", - "@rollup/rollup-linux-riscv64-gnu": "4.48.1", - "@rollup/rollup-linux-riscv64-musl": "4.48.1", - "@rollup/rollup-linux-s390x-gnu": "4.48.1", - "@rollup/rollup-linux-x64-gnu": "4.48.1", - "@rollup/rollup-linux-x64-musl": "4.48.1", - "@rollup/rollup-win32-arm64-msvc": "4.48.1", - "@rollup/rollup-win32-ia32-msvc": "4.48.1", - "@rollup/rollup-win32-x64-msvc": "4.48.1", + "@rollup/rollup-android-arm-eabi": "4.50.2", + "@rollup/rollup-android-arm64": "4.50.2", + "@rollup/rollup-darwin-arm64": "4.50.2", + "@rollup/rollup-darwin-x64": "4.50.2", + "@rollup/rollup-freebsd-arm64": "4.50.2", + "@rollup/rollup-freebsd-x64": "4.50.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.50.2", + "@rollup/rollup-linux-arm-musleabihf": "4.50.2", + "@rollup/rollup-linux-arm64-gnu": "4.50.2", + "@rollup/rollup-linux-arm64-musl": "4.50.2", + "@rollup/rollup-linux-loong64-gnu": "4.50.2", + "@rollup/rollup-linux-ppc64-gnu": "4.50.2", + "@rollup/rollup-linux-riscv64-gnu": "4.50.2", + "@rollup/rollup-linux-riscv64-musl": "4.50.2", + "@rollup/rollup-linux-s390x-gnu": "4.50.2", + "@rollup/rollup-linux-x64-gnu": "4.50.2", + "@rollup/rollup-linux-x64-musl": "4.50.2", + "@rollup/rollup-openharmony-arm64": "4.50.2", + "@rollup/rollup-win32-arm64-msvc": "4.50.2", + "@rollup/rollup-win32-ia32-msvc": "4.50.2", + "@rollup/rollup-win32-x64-msvc": "4.50.2", "fsevents": "~2.3.2" } }, @@ -10974,15 +11014,15 @@ } }, "node_modules/terser": { - "version": "5.43.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", - "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", + "version": "5.44.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.0.tgz", + "integrity": "sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==", "dev": true, "license": "BSD-2-Clause", "peer": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.14.0", + "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -11159,14 +11199,14 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -11303,9 +11343,9 @@ "license": "Apache-2.0" }, "node_modules/ts-jest": { - "version": "29.4.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.1.tgz", - "integrity": "sha512-SaeUtjfpg9Uqu8IbeDKtdaS0g8lS6FT6OzM3ezrDfErPJPHNDo/Ey+VFGP1bQIDfagYDLyRpd7O15XpG1Es2Uw==", + "version": "29.4.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.2.tgz", + "integrity": "sha512-pBNOkn4HtuLpNrXTMVRC9b642CBaDnKqWXny4OzuoULT9S7Kf8MMlaRe2veKax12rjf5WcpMBhVPbQurlWGNxA==", "dev": true, "license": "MIT", "dependencies": { @@ -11739,9 +11779,9 @@ } }, "node_modules/undici-types": { - "version": "7.10.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", - "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", + "integrity": "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==", "dev": true, "license": "MIT" }, @@ -11770,9 +11810,9 @@ } }, "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", "dev": true, "license": "MIT", "engines": { @@ -11780,9 +11820,9 @@ } }, "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index ffd01bf..3a5e109 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/delivery-sdk", - "version": "4.9.1", + "version": "4.10.0", "type": "module", "license": "MIT", "main": "./dist/legacy/index.cjs",