New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@vue-storefront/middleware

Package Overview
Dependencies
Maintainers
9
Versions
102
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vue-storefront/middleware - npm Package Compare versions

Comparing version 3.6.0-test.0 to 4.0.0-test.0

lib/defineConfig.d.ts

4

lib/apiClientFactory/applyContextToApi.d.ts

@@ -1,7 +0,7 @@

import { ApiMethods, ApplyingContextHooks, MiddlewareContext } from '../types';
import { Method, Context, Hooks } from "../types";
/**
* Wraps api methods with context and hooks triggers
*/
declare const applyContextToApi: <API extends ApiMethods, CONTEXT extends MiddlewareContext<{}>>(api: API, context: CONTEXT, hooks?: ApplyingContextHooks) => API;
declare const applyContextToApi: (api: Record<string, Method>, context: Context, hooks?: Hooks) => Record<string, Method>;
export { applyContextToApi };
//# sourceMappingURL=applyContextToApi.d.ts.map

@@ -1,3 +0,3 @@

import { CustomQuery, ContextQuery, MiddlewareContext } from '../types';
export declare const createExtendQuery: (context: MiddlewareContext) => <T extends ContextQuery<string>, Key extends keyof T>(customQuery: CustomQuery | null, defaults: T) => ContextQuery<Key>;
import { Context, Query, CustomQuery } from "../types";
export declare const createExtendQuery: (context: Context) => <T extends Query<string>, Key extends keyof T>(customQuery: CustomQuery | null, defaults: T) => Query<Key>;
//# sourceMappingURL=createExtendQuery.d.ts.map

@@ -1,4 +0,3 @@

import { ApiClientConfig, ApiClientFactory, ApiClientFactoryParams, ApiMethods } from '../types';
declare const apiClientFactory: <ALL_SETTINGS extends ApiClientConfig<any>, ALL_FUNCTIONS extends ApiMethods>(factoryParams: ApiClientFactoryParams<ALL_SETTINGS, ALL_FUNCTIONS, any>) => ApiClientFactory<any, ALL_FUNCTIONS>;
export { apiClientFactory };
import type { ApiClientFactoryParams, ApiClientFactoryResult } from "../types";
export declare function apiClientFactory<ApiClientFactoryParamsType extends ApiClientFactoryParams>(factoryParams: ApiClientFactoryParamsType): ApiClientFactoryResult<ApiClientFactoryParamsType>;
//# sourceMappingURL=index.d.ts.map

@@ -1,5 +0,5 @@

import type { Express } from 'express';
import type { IntegrationContext, MiddlewareConfig } from './types';
declare function createServer<TIntegrationContext extends Record<string, IntegrationContext>>(config: MiddlewareConfig<TIntegrationContext>): Promise<Express>;
import type { Express } from "express";
import { CreateServerParams } from "./types";
declare function createServer(config: CreateServerParams): Promise<Express>;
export { createServer };
//# sourceMappingURL=createServer.d.ts.map

@@ -1,2 +0,2 @@

import type { Request, Response } from 'express';
import type { Request, Response } from "express";
/**

@@ -3,0 +3,0 @@ * Default error handler for the middleware

@@ -1,3 +0,3 @@

import type { Request, Response } from 'express';
import type { Request, Response } from "express";
export declare function callApiFunction(req: Request, res: Response): Promise<void>;
//# sourceMappingURL=index.d.ts.map

@@ -1,5 +0,5 @@

export * from './callApiFunction';
export * from './prepareApiFunction';
export * from './prepareErrorHandler';
export * from './prepareArguments';
export * from "./callApiFunction";
export * from "./prepareApiFunction";
export * from "./prepareErrorHandler";
export * from "./prepareArguments";
//# sourceMappingURL=index.d.ts.map

@@ -1,4 +0,4 @@

import type { RequestHandler } from 'express';
import { IntegrationsLoaded } from '../../types';
import type { RequestHandler } from "express";
import { IntegrationsLoaded } from "../../types";
export declare function prepareApiFunction(integrations: IntegrationsLoaded): RequestHandler;
//# sourceMappingURL=index.d.ts.map

@@ -1,3 +0,3 @@

import type { Request, Response, NextFunction } from 'express';
import type { Request, Response, NextFunction } from "express";
export declare function prepareArguments(req: Request, res: Response, next: NextFunction): void;
//# sourceMappingURL=index.d.ts.map

@@ -1,4 +0,4 @@

import type { RequestHandler } from 'express';
import { IntegrationsLoaded } from '../../types';
import type { RequestHandler } from "express";
import { IntegrationsLoaded } from "../../types";
export declare function prepareErrorHandler(integrations: IntegrationsLoaded): RequestHandler;
//# sourceMappingURL=index.d.ts.map

@@ -1,3 +0,4 @@

export * from './utils';
export { getAgnosticStatusCode } from './getAgnosticStatusCode';
export * from "./utils";
export { getAgnosticStatusCode } from "./getAgnosticStatusCode";
export { createEmptyApiClient } from "./createEmptyApiClient";
//# sourceMappingURL=index.d.ts.map

@@ -1,4 +0,4 @@

import { AnyFunction } from '../types';
export declare const isFunction: (x: unknown) => x is AnyFunction;
import { Method } from "../types";
export declare const isFunction: (x: unknown) => x is Method;
export declare function includes<T extends U, U>(coll: ReadonlyArray<T>, el: U): el is T;
//# sourceMappingURL=utils.d.ts.map

@@ -24,4 +24,3 @@ 'use strict';

try {
// eslint-disable-next-line import/no-dynamic-require
// eslint-disable-next-line global-require
// eslint-disable-next-line
return require(require.resolve(name, { paths: [process.cwd()] }));

@@ -39,3 +38,5 @@ }

function lookUpExternal(extension) {
return typeof extension === 'string' ? resolveDependency(extension) : [extension];
return typeof extension === "string"
? resolveDependency(extension)
: [extension];
}

@@ -52,9 +53,12 @@

*/
function createRawExtensions(apiClient, integration) {
function createRawExtensions(apiClientFactoryResult, integration) {
const extensionsCreateFn = integration.extensions;
const predefinedExtensions = apiClient.createApiClient._predefinedExtensions || [];
return extensionsCreateFn ? extensionsCreateFn(predefinedExtensions) : predefinedExtensions;
const predefinedExtensions = apiClientFactoryResult.createApiClient._predefinedExtensions || [];
return extensionsCreateFn
? extensionsCreateFn(predefinedExtensions)
: predefinedExtensions;
}
const isFunction = (x) => typeof x === 'function';
const isFunction = (x) => typeof x === "function";
// eslint-disable-next-line no-use-before-define
function includes(coll, el) {

@@ -64,3 +68,3 @@ return coll.includes(el);

const STATUS_FIELDS = ['status', 'statusCode'];
const STATUS_FIELDS = ["status", "statusCode"];
function isErrorObject(obj) {

@@ -70,12 +74,12 @@ // typeof null is 'object' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof#typeof_null

return false;
return typeof obj === 'object';
return typeof obj === "object";
}
function isAxiosError(error) {
return 'isAxiosError' in error;
return "isAxiosError" in error;
}
function isApolloError(error) {
return 'networkError' in error || 'code' in error;
return "networkError" in error || "code" in error;
}
function reduceStatus(narrowObject, depth) {
return function (statusCode, key) {
return function reduceStatusNested(statusCode, key) {
if (statusCode) {

@@ -88,2 +92,3 @@ return statusCode;

const newDepth = depth + 1;
// eslint-disable-next-line no-use-before-define
return obtainStatusCode(narrowObject[key], newDepth);

@@ -107,8 +112,9 @@ };

if (error.code) {
return typeof error.code === 'string' ? 400 : error.code;
return typeof error.code === "string" ? 400 : error.code;
}
return undefined;
}
function getCodeFromError(error) {
if (!isErrorObject(error)) {
return;
return undefined;
}

@@ -127,7 +133,117 @@ if (isAxiosError(error)) {

async function getInitConfig({ apiClient, tag, integration }) {
if (isFunction(apiClient?.init)) {
const createExtendQuery = (context) => (customQuery, defaults) => {
const { customQueries = {} } = context;
const { metadata = {} } = customQuery || {};
return Object.entries(defaults).reduce((prev, [queryName, initialArgs]) => {
const key = customQuery?.[queryName];
const queryFn = (key && customQueries[key]) || (() => initialArgs);
return {
...prev,
[queryName]: queryFn({ ...initialArgs, metadata }),
};
}, {});
};
const nopBefore = ({ args }) => args;
const nopAfter = ({ response }) => response;
/**
* Wraps api methods with context and hooks triggers
*/
const applyContextToApi = (api, context,
/**
* By default we use NOP function for returning the same parameters as they come.
* It's useful in extensions, when someone don't want to inject into changing arguments or the response,
* in that case, we use default function, to handle that scenario - NOP
*/
hooks = { beforeCall: nopBefore, afterCall: nopAfter }) => Object.entries(api).reduce((prev, [callName, fn]) => ({
...prev,
[callName]: async (...args) => {
const extendQuery = createExtendQuery(context);
const transformedArgs = hooks.beforeCall({ callName, args });
const apiClientContext = { ...context, extendQuery };
const response = await fn(apiClientContext, ...transformedArgs);
const transformedResponse = hooks.afterCall({
callName,
args,
response,
});
return transformedResponse;
},
}), {});
function apiClientFactory(factoryParams) {
const createApiClientFn = (middlewareContext, config, customApi = {}) => {
const rawExtensions = middlewareContext?.extensions || [];
const lifecycles = rawExtensions
.filter((extension) => isFunction(extension?.hooks))
.map(({ hooks }) => hooks(middlewareContext?.req, middlewareContext?.res));
const extendedApis = rawExtensions.reduce((prev, { extendApiMethods }) => ({ ...prev, ...extendApiMethods }), customApi);
const _config = lifecycles
.filter((extension) => isFunction(extension?.beforeCreate))
.reduce((configSoFar, extension) => extension.beforeCreate({ configuration: configSoFar }), config);
const settings = factoryParams.onCreate
? factoryParams.onCreate(_config)
: { config, client: config.client };
settings.config = lifecycles
.filter((extension) => isFunction(extension?.afterCreate))
.reduce((configSoFar, extension) => extension.afterCreate({ configuration: configSoFar }), settings.config);
const extensionHooks = {
beforeCall: (params) => lifecycles
.filter((extension) => isFunction(extension?.beforeCall))
.reduce((args, extension) => extension.beforeCall({
...params,
configuration: settings.config,
args,
}), params.args),
afterCall: (params) => lifecycles
.filter((extension) => isFunction(extension.afterCall))
.reduce((response, extension) => extension.afterCall({
...params,
configuration: settings.config,
response,
}), params.response),
};
const context = { ...settings, ...(middlewareContext || {}) };
const { api: apiOrApiFactory = {} } = factoryParams;
const isApiFactory = typeof apiOrApiFactory === "function";
const api = isApiFactory ? apiOrApiFactory(settings) : apiOrApiFactory;
/**
* FIXME IN-3487
*
* `applyContextToApi` requires `context` to be of type `MiddlewareContextContext`
* However, the above `const context =` does not satisfy that type.
*
* `this.middlewareContext` provides (among others) `{ req: ..., res: ..., ... }`,
* but `middlewareContext || {}` provides `{ req?: ..., res?: ..., ...}`
*
* `MiddlewareContextContext` requires `req` and `res` to be required, not optional, hence the error.
*/
const integrationApi = applyContextToApi(api, context, extensionHooks);
const extensionsApi = applyContextToApi(extendedApis ?? {}, context, extensionHooks);
const mergedApi = {
...integrationApi,
...extensionsApi,
};
// api methods haven't been invoked yet, so we still have time to add them to the context
context.api = integrationApi;
return {
api: mergedApi,
client: settings.client,
settings: settings.config,
};
};
// This is a hack to allow extensions to be added to the apiClientFactory.
// Otherwise, I'd need to refactor the whole logic of passing extensions...
const createApiClient = createApiClientFn;
createApiClient._predefinedExtensions = factoryParams.extensions || [];
return {
createApiClient,
};
}
async function getInitConfig({ apiClientFactoryResult, tag, integrationConfig, }) {
if (isFunction(apiClientFactoryResult?.init)) {
try {
consola__default["default"].success(`- Integration: ${tag} init function Start!`);
const initConfig = await apiClient.init(integration.configuration);
const initConfig = await apiClientFactoryResult.init(integrationConfig.configuration);
consola__default["default"].success(`- Integration: ${tag} init function Done!`);

@@ -164,16 +280,24 @@ return initConfig;

*/
res.send('ServerError: Something went wrong. Please, check the logs for more details.');
res.send("ServerError: Something went wrong. Please, check the logs for more details.");
}
};
async function registerIntegrations(app, integrations) {
return await Object.entries(integrations).reduce(async (prevAsync, [tag, integration]) => {
consola__default["default"].info(`- Loading: ${tag} ${integration.location}`);
async function registerIntegrations(app, integrationsConfig) {
return await Object.entries(integrationsConfig).reduce(async (prevAsync, [tag, integrationConfig]) => {
consola__default["default"].info(`- Loading: ${tag} ${integrationConfig.location ?? ""}`);
const prev = await prevAsync;
const apiClient = resolveDependency(integration.location);
const rawExtensions = createRawExtensions(apiClient, integration);
let apiClientFactoryResult;
if (integrationConfig.location) {
apiClientFactoryResult = resolveDependency(integrationConfig.location);
}
apiClientFactoryResult = integrationConfig.apiClient;
const rawExtensions = createRawExtensions(apiClientFactoryResult, integrationConfig);
const extensions = createExtensions(rawExtensions);
const initConfig = await getInitConfig({ apiClient, integration, tag });
const initConfig = await getInitConfig({
apiClientFactoryResult,
tag,
integrationConfig,
});
const configuration = {
...integration.configuration,
...integrationConfig.configuration,
integrationName: tag,

@@ -191,8 +315,8 @@ };

[tag]: {
apiClient,
apiClient: apiClientFactoryResult,
extensions,
initConfig,
configuration,
customQueries: integration.customQueries,
errorHandler: integration.errorHandler ?? defaultErrorHandler,
customQueries: integrationConfig.customQueries,
errorHandler: integrationConfig.errorHandler ?? defaultErrorHandler,
},

@@ -222,3 +346,3 @@ };

}
const { apiClient, configuration, extensions, customQueries = {}, initConfig } = integrations[integrationName];
const { apiClient, configuration, extensions, customQueries = {}, initConfig, } = integrations[integrationName];
const middlewareContext = {

@@ -234,6 +358,3 @@ req,

}
const createClient = integrations[name].apiClient.createApiClient.bind({
middleware: middlewareContext,
});
return createClient({
return integrations[name].apiClient.createApiClient(middlewareContext, {
...integrations[name].configuration,

@@ -244,6 +365,3 @@ ...integrations[name].initConfig,

};
const createApiClient = apiClient.createApiClient.bind({
middleware: middlewareContext,
});
const apiClientInstance = createApiClient({
const apiClientInstance = apiClient.createApiClient(middlewareContext, {
...configuration,

@@ -270,3 +388,3 @@ ...initConfig,

let args;
if (method === 'GET') {
if (method === "GET") {
/**

@@ -277,3 +395,3 @@ * Falling back to empty object to mimic

*/
const { body: queryBody = '{}' } = query;
const { body: queryBody = "{}" } = query;
args = JSON.parse(queryBody);

@@ -294,7 +412,8 @@ }

credentials: true,
origin: 'http://localhost:3000',
origin: "http://localhost:3000",
}));
app.disable('x-powered-by');
app.disable("x-powered-by");
async function createServer(config) {
consola__default["default"].info('Middleware starting....');
consola__default["default"].info("Middleware starting....");
const helmetOptions = config.helmet || config.helmet || {};
const options = {

@@ -305,119 +424,26 @@ contentSecurityPolicy: false,

permittedCrossDomainPolicies: {
permittedPolicies: 'none',
permittedPolicies: "none",
},
...(config.helmet || {}),
...helmetOptions,
};
const isHelmetEnabled = config.helmet === true || (config.helmet && Object.keys(config.helmet).length > 0);
const isHelmetEnabled = helmetOptions === true ||
(helmetOptions && Object.keys(helmetOptions).length > 0);
if (isHelmetEnabled) {
app.use(helmet__default["default"](options));
consola__default["default"].info('VSF `Helmet` middleware added');
consola__default["default"].info("VSF `Helmet` middleware added");
}
consola__default["default"].info('Loading integrations...');
consola__default["default"].info("Loading integrations...");
const integrations = await registerIntegrations(app, config.integrations);
consola__default["default"].success('Integrations loaded!');
app.post('/:integrationName/:functionName', prepareApiFunction(integrations), prepareErrorHandler(integrations), prepareArguments, callApiFunction);
app.get('/:integrationName/:functionName', prepareApiFunction(integrations), prepareErrorHandler(integrations), prepareArguments, callApiFunction);
app.get('/healthz', (_req, res) => {
res.end('ok');
consola__default["default"].success("Integrations loaded!");
app.post("/:integrationName/:functionName", prepareApiFunction(integrations), prepareErrorHandler(integrations), prepareArguments, callApiFunction);
app.get("/:integrationName/:functionName", prepareApiFunction(integrations), prepareErrorHandler(integrations), prepareArguments, callApiFunction);
app.get("/healthz", (_req, res) => {
res.end("ok");
});
consola__default["default"].success('Middleware created!');
consola__default["default"].success("Middleware created!");
return app;
}
const createExtendQuery = (context) => (customQuery, defaults) => {
const { customQueries = {} } = context;
const { metadata = {} } = customQuery || {};
return Object.entries(defaults).reduce((prev, [queryName, initialArgs]) => {
const key = customQuery?.[queryName];
const queryFn = (key && customQueries[key]) || (() => initialArgs);
return {
...prev,
[queryName]: queryFn({ ...initialArgs, metadata }),
};
}, {});
};
// @ts-check
const nopBefore = ({ args }) => args;
const nopAfter = ({ response }) => response;
/**
* Wraps api methods with context and hooks triggers
*/
const applyContextToApi = (api, context,
/**
* By default we use NOP function for returning the same parameters as they come.
* It's useful in extensions, when someone don't want to inject into changing arguments or the response,
* in that case, we use default function, to handle that scenario - NOP
*/
hooks = { before: nopBefore, after: nopAfter }) => Object.entries(api).reduce((prev, [callName, fn]) => ({
...prev,
[callName]: async (...args) => {
const extendQuery = createExtendQuery(context);
const transformedArgs = hooks.before({ callName, args });
const apiClientContext = { ...context, extendQuery };
const response = await fn(apiClientContext, ...transformedArgs);
const transformedResponse = hooks.after({ callName, args, response });
return transformedResponse;
},
}), {});
const apiClientFactory = (factoryParams) => {
const createApiClient = function (config, customApi = {}) {
const rawExtensions = this?.middleware?.extensions || [];
const lifecycles = rawExtensions
.filter((extension) => isFunction(extension?.hooks))
.map(({ hooks }) => hooks(this?.middleware?.req, this?.middleware?.res));
const extendedApis = rawExtensions.reduce((prev, { extendApiMethods }) => ({ ...prev, ...extendApiMethods }), customApi);
const _config = lifecycles
.filter((extension) => isFunction(extension?.beforeCreate))
.reduce((config, extension) => extension.beforeCreate({ configuration: config }), config);
const settings = factoryParams.onCreate ? factoryParams.onCreate(_config) : { config, client: config.client };
settings.config = lifecycles
.filter((extension) => isFunction(extension?.afterCreate))
.reduce((config, extension) => extension.afterCreate({ configuration: config }), settings.config);
const extensionHooks = {
before: (params) => lifecycles
.filter((extension) => isFunction(extension?.beforeCall))
.reduce((args, extension) => extension.beforeCall({ ...params, configuration: settings.config, args }), params.args),
after: (params) => lifecycles
.filter((extension) => isFunction(extension.afterCall))
.reduce((response, extension) => extension.afterCall({ ...params, configuration: settings.config, response }), params.response),
};
const context = { ...settings, ...(this?.middleware || {}) };
const { api: apiOrApiFactory = {} } = factoryParams;
const isApiFactory = typeof apiOrApiFactory === 'function';
const api = isApiFactory ? apiOrApiFactory(settings) : apiOrApiFactory;
/**
* FIXME IN-3487
*
* `applyContextToApi` requires `context` to be of type `MiddlewareContext`
* However, the above `const context =` does not satisfy that type.
*
* `this.middleware` provides (among others) `{ req: ..., res: ..., ... }`,
* but `this?.middleware || {}` provides `{ req?: ..., res?: ..., ...}`
*
* `MiddlewareContext` requires `req` and `res` to be required, not optional, hence the error.
*/
// @ts-expect-error see above
const integrationApi = applyContextToApi(api, context, extensionHooks);
// @ts-expect-error see above
const extensionsApi = applyContextToApi(extendedApis ?? {}, context, extensionHooks);
const mergedApi = {
...integrationApi,
...extensionsApi,
};
// api methods haven't been invoked yet, so we still have time to add them to the context
context.api = integrationApi;
return {
api: mergedApi,
client: settings.client,
settings: settings.config,
};
};
createApiClient._predefinedExtensions = factoryParams.extensions || [];
return { createApiClient };
};
exports.apiClientFactory = apiClientFactory;
exports.createServer = createServer;
//# sourceMappingURL=index.cjs.js.map

@@ -1,4 +0,4 @@

export * from './types';
export * from './createServer';
export * from './apiClientFactory';
export * from "./deprecated/types";
export * from "./createServer";
export * from "./apiClientFactory";
//# sourceMappingURL=index.d.ts.map

@@ -12,4 +12,3 @@ import consola from 'consola';

try {
// eslint-disable-next-line import/no-dynamic-require
// eslint-disable-next-line global-require
// eslint-disable-next-line
return require(require.resolve(name, { paths: [process.cwd()] }));

@@ -27,3 +26,5 @@ }

function lookUpExternal(extension) {
return typeof extension === 'string' ? resolveDependency(extension) : [extension];
return typeof extension === "string"
? resolveDependency(extension)
: [extension];
}

@@ -40,9 +41,12 @@

*/
function createRawExtensions(apiClient, integration) {
function createRawExtensions(apiClientFactoryResult, integration) {
const extensionsCreateFn = integration.extensions;
const predefinedExtensions = apiClient.createApiClient._predefinedExtensions || [];
return extensionsCreateFn ? extensionsCreateFn(predefinedExtensions) : predefinedExtensions;
const predefinedExtensions = apiClientFactoryResult.createApiClient._predefinedExtensions || [];
return extensionsCreateFn
? extensionsCreateFn(predefinedExtensions)
: predefinedExtensions;
}
const isFunction = (x) => typeof x === 'function';
const isFunction = (x) => typeof x === "function";
// eslint-disable-next-line no-use-before-define
function includes(coll, el) {

@@ -52,3 +56,3 @@ return coll.includes(el);

const STATUS_FIELDS = ['status', 'statusCode'];
const STATUS_FIELDS = ["status", "statusCode"];
function isErrorObject(obj) {

@@ -58,12 +62,12 @@ // typeof null is 'object' https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof#typeof_null

return false;
return typeof obj === 'object';
return typeof obj === "object";
}
function isAxiosError(error) {
return 'isAxiosError' in error;
return "isAxiosError" in error;
}
function isApolloError(error) {
return 'networkError' in error || 'code' in error;
return "networkError" in error || "code" in error;
}
function reduceStatus(narrowObject, depth) {
return function (statusCode, key) {
return function reduceStatusNested(statusCode, key) {
if (statusCode) {

@@ -76,2 +80,3 @@ return statusCode;

const newDepth = depth + 1;
// eslint-disable-next-line no-use-before-define
return obtainStatusCode(narrowObject[key], newDepth);

@@ -95,8 +100,9 @@ };

if (error.code) {
return typeof error.code === 'string' ? 400 : error.code;
return typeof error.code === "string" ? 400 : error.code;
}
return undefined;
}
function getCodeFromError(error) {
if (!isErrorObject(error)) {
return;
return undefined;
}

@@ -115,7 +121,117 @@ if (isAxiosError(error)) {

async function getInitConfig({ apiClient, tag, integration }) {
if (isFunction(apiClient?.init)) {
const createExtendQuery = (context) => (customQuery, defaults) => {
const { customQueries = {} } = context;
const { metadata = {} } = customQuery || {};
return Object.entries(defaults).reduce((prev, [queryName, initialArgs]) => {
const key = customQuery?.[queryName];
const queryFn = (key && customQueries[key]) || (() => initialArgs);
return {
...prev,
[queryName]: queryFn({ ...initialArgs, metadata }),
};
}, {});
};
const nopBefore = ({ args }) => args;
const nopAfter = ({ response }) => response;
/**
* Wraps api methods with context and hooks triggers
*/
const applyContextToApi = (api, context,
/**
* By default we use NOP function for returning the same parameters as they come.
* It's useful in extensions, when someone don't want to inject into changing arguments or the response,
* in that case, we use default function, to handle that scenario - NOP
*/
hooks = { beforeCall: nopBefore, afterCall: nopAfter }) => Object.entries(api).reduce((prev, [callName, fn]) => ({
...prev,
[callName]: async (...args) => {
const extendQuery = createExtendQuery(context);
const transformedArgs = hooks.beforeCall({ callName, args });
const apiClientContext = { ...context, extendQuery };
const response = await fn(apiClientContext, ...transformedArgs);
const transformedResponse = hooks.afterCall({
callName,
args,
response,
});
return transformedResponse;
},
}), {});
function apiClientFactory(factoryParams) {
const createApiClientFn = (middlewareContext, config, customApi = {}) => {
const rawExtensions = middlewareContext?.extensions || [];
const lifecycles = rawExtensions
.filter((extension) => isFunction(extension?.hooks))
.map(({ hooks }) => hooks(middlewareContext?.req, middlewareContext?.res));
const extendedApis = rawExtensions.reduce((prev, { extendApiMethods }) => ({ ...prev, ...extendApiMethods }), customApi);
const _config = lifecycles
.filter((extension) => isFunction(extension?.beforeCreate))
.reduce((configSoFar, extension) => extension.beforeCreate({ configuration: configSoFar }), config);
const settings = factoryParams.onCreate
? factoryParams.onCreate(_config)
: { config, client: config.client };
settings.config = lifecycles
.filter((extension) => isFunction(extension?.afterCreate))
.reduce((configSoFar, extension) => extension.afterCreate({ configuration: configSoFar }), settings.config);
const extensionHooks = {
beforeCall: (params) => lifecycles
.filter((extension) => isFunction(extension?.beforeCall))
.reduce((args, extension) => extension.beforeCall({
...params,
configuration: settings.config,
args,
}), params.args),
afterCall: (params) => lifecycles
.filter((extension) => isFunction(extension.afterCall))
.reduce((response, extension) => extension.afterCall({
...params,
configuration: settings.config,
response,
}), params.response),
};
const context = { ...settings, ...(middlewareContext || {}) };
const { api: apiOrApiFactory = {} } = factoryParams;
const isApiFactory = typeof apiOrApiFactory === "function";
const api = isApiFactory ? apiOrApiFactory(settings) : apiOrApiFactory;
/**
* FIXME IN-3487
*
* `applyContextToApi` requires `context` to be of type `MiddlewareContextContext`
* However, the above `const context =` does not satisfy that type.
*
* `this.middlewareContext` provides (among others) `{ req: ..., res: ..., ... }`,
* but `middlewareContext || {}` provides `{ req?: ..., res?: ..., ...}`
*
* `MiddlewareContextContext` requires `req` and `res` to be required, not optional, hence the error.
*/
const integrationApi = applyContextToApi(api, context, extensionHooks);
const extensionsApi = applyContextToApi(extendedApis ?? {}, context, extensionHooks);
const mergedApi = {
...integrationApi,
...extensionsApi,
};
// api methods haven't been invoked yet, so we still have time to add them to the context
context.api = integrationApi;
return {
api: mergedApi,
client: settings.client,
settings: settings.config,
};
};
// This is a hack to allow extensions to be added to the apiClientFactory.
// Otherwise, I'd need to refactor the whole logic of passing extensions...
const createApiClient = createApiClientFn;
createApiClient._predefinedExtensions = factoryParams.extensions || [];
return {
createApiClient,
};
}
async function getInitConfig({ apiClientFactoryResult, tag, integrationConfig, }) {
if (isFunction(apiClientFactoryResult?.init)) {
try {
consola.success(`- Integration: ${tag} init function Start!`);
const initConfig = await apiClient.init(integration.configuration);
const initConfig = await apiClientFactoryResult.init(integrationConfig.configuration);
consola.success(`- Integration: ${tag} init function Done!`);

@@ -152,16 +268,24 @@ return initConfig;

*/
res.send('ServerError: Something went wrong. Please, check the logs for more details.');
res.send("ServerError: Something went wrong. Please, check the logs for more details.");
}
};
async function registerIntegrations(app, integrations) {
return await Object.entries(integrations).reduce(async (prevAsync, [tag, integration]) => {
consola.info(`- Loading: ${tag} ${integration.location}`);
async function registerIntegrations(app, integrationsConfig) {
return await Object.entries(integrationsConfig).reduce(async (prevAsync, [tag, integrationConfig]) => {
consola.info(`- Loading: ${tag} ${integrationConfig.location ?? ""}`);
const prev = await prevAsync;
const apiClient = resolveDependency(integration.location);
const rawExtensions = createRawExtensions(apiClient, integration);
let apiClientFactoryResult;
if (integrationConfig.location) {
apiClientFactoryResult = resolveDependency(integrationConfig.location);
}
apiClientFactoryResult = integrationConfig.apiClient;
const rawExtensions = createRawExtensions(apiClientFactoryResult, integrationConfig);
const extensions = createExtensions(rawExtensions);
const initConfig = await getInitConfig({ apiClient, integration, tag });
const initConfig = await getInitConfig({
apiClientFactoryResult,
tag,
integrationConfig,
});
const configuration = {
...integration.configuration,
...integrationConfig.configuration,
integrationName: tag,

@@ -179,8 +303,8 @@ };

[tag]: {
apiClient,
apiClient: apiClientFactoryResult,
extensions,
initConfig,
configuration,
customQueries: integration.customQueries,
errorHandler: integration.errorHandler ?? defaultErrorHandler,
customQueries: integrationConfig.customQueries,
errorHandler: integrationConfig.errorHandler ?? defaultErrorHandler,
},

@@ -210,3 +334,3 @@ };

}
const { apiClient, configuration, extensions, customQueries = {}, initConfig } = integrations[integrationName];
const { apiClient, configuration, extensions, customQueries = {}, initConfig, } = integrations[integrationName];
const middlewareContext = {

@@ -222,6 +346,3 @@ req,

}
const createClient = integrations[name].apiClient.createApiClient.bind({
middleware: middlewareContext,
});
return createClient({
return integrations[name].apiClient.createApiClient(middlewareContext, {
...integrations[name].configuration,

@@ -232,6 +353,3 @@ ...integrations[name].initConfig,

};
const createApiClient = apiClient.createApiClient.bind({
middleware: middlewareContext,
});
const apiClientInstance = createApiClient({
const apiClientInstance = apiClient.createApiClient(middlewareContext, {
...configuration,

@@ -258,3 +376,3 @@ ...initConfig,

let args;
if (method === 'GET') {
if (method === "GET") {
/**

@@ -265,3 +383,3 @@ * Falling back to empty object to mimic

*/
const { body: queryBody = '{}' } = query;
const { body: queryBody = "{}" } = query;
args = JSON.parse(queryBody);

@@ -282,7 +400,8 @@ }

credentials: true,
origin: 'http://localhost:3000',
origin: "http://localhost:3000",
}));
app.disable('x-powered-by');
app.disable("x-powered-by");
async function createServer(config) {
consola.info('Middleware starting....');
consola.info("Middleware starting....");
const helmetOptions = config.helmet || config.helmet || {};
const options = {

@@ -293,118 +412,25 @@ contentSecurityPolicy: false,

permittedCrossDomainPolicies: {
permittedPolicies: 'none',
permittedPolicies: "none",
},
...(config.helmet || {}),
...helmetOptions,
};
const isHelmetEnabled = config.helmet === true || (config.helmet && Object.keys(config.helmet).length > 0);
const isHelmetEnabled = helmetOptions === true ||
(helmetOptions && Object.keys(helmetOptions).length > 0);
if (isHelmetEnabled) {
app.use(helmet(options));
consola.info('VSF `Helmet` middleware added');
consola.info("VSF `Helmet` middleware added");
}
consola.info('Loading integrations...');
consola.info("Loading integrations...");
const integrations = await registerIntegrations(app, config.integrations);
consola.success('Integrations loaded!');
app.post('/:integrationName/:functionName', prepareApiFunction(integrations), prepareErrorHandler(integrations), prepareArguments, callApiFunction);
app.get('/:integrationName/:functionName', prepareApiFunction(integrations), prepareErrorHandler(integrations), prepareArguments, callApiFunction);
app.get('/healthz', (_req, res) => {
res.end('ok');
consola.success("Integrations loaded!");
app.post("/:integrationName/:functionName", prepareApiFunction(integrations), prepareErrorHandler(integrations), prepareArguments, callApiFunction);
app.get("/:integrationName/:functionName", prepareApiFunction(integrations), prepareErrorHandler(integrations), prepareArguments, callApiFunction);
app.get("/healthz", (_req, res) => {
res.end("ok");
});
consola.success('Middleware created!');
consola.success("Middleware created!");
return app;
}
const createExtendQuery = (context) => (customQuery, defaults) => {
const { customQueries = {} } = context;
const { metadata = {} } = customQuery || {};
return Object.entries(defaults).reduce((prev, [queryName, initialArgs]) => {
const key = customQuery?.[queryName];
const queryFn = (key && customQueries[key]) || (() => initialArgs);
return {
...prev,
[queryName]: queryFn({ ...initialArgs, metadata }),
};
}, {});
};
// @ts-check
const nopBefore = ({ args }) => args;
const nopAfter = ({ response }) => response;
/**
* Wraps api methods with context and hooks triggers
*/
const applyContextToApi = (api, context,
/**
* By default we use NOP function for returning the same parameters as they come.
* It's useful in extensions, when someone don't want to inject into changing arguments or the response,
* in that case, we use default function, to handle that scenario - NOP
*/
hooks = { before: nopBefore, after: nopAfter }) => Object.entries(api).reduce((prev, [callName, fn]) => ({
...prev,
[callName]: async (...args) => {
const extendQuery = createExtendQuery(context);
const transformedArgs = hooks.before({ callName, args });
const apiClientContext = { ...context, extendQuery };
const response = await fn(apiClientContext, ...transformedArgs);
const transformedResponse = hooks.after({ callName, args, response });
return transformedResponse;
},
}), {});
const apiClientFactory = (factoryParams) => {
const createApiClient = function (config, customApi = {}) {
const rawExtensions = this?.middleware?.extensions || [];
const lifecycles = rawExtensions
.filter((extension) => isFunction(extension?.hooks))
.map(({ hooks }) => hooks(this?.middleware?.req, this?.middleware?.res));
const extendedApis = rawExtensions.reduce((prev, { extendApiMethods }) => ({ ...prev, ...extendApiMethods }), customApi);
const _config = lifecycles
.filter((extension) => isFunction(extension?.beforeCreate))
.reduce((config, extension) => extension.beforeCreate({ configuration: config }), config);
const settings = factoryParams.onCreate ? factoryParams.onCreate(_config) : { config, client: config.client };
settings.config = lifecycles
.filter((extension) => isFunction(extension?.afterCreate))
.reduce((config, extension) => extension.afterCreate({ configuration: config }), settings.config);
const extensionHooks = {
before: (params) => lifecycles
.filter((extension) => isFunction(extension?.beforeCall))
.reduce((args, extension) => extension.beforeCall({ ...params, configuration: settings.config, args }), params.args),
after: (params) => lifecycles
.filter((extension) => isFunction(extension.afterCall))
.reduce((response, extension) => extension.afterCall({ ...params, configuration: settings.config, response }), params.response),
};
const context = { ...settings, ...(this?.middleware || {}) };
const { api: apiOrApiFactory = {} } = factoryParams;
const isApiFactory = typeof apiOrApiFactory === 'function';
const api = isApiFactory ? apiOrApiFactory(settings) : apiOrApiFactory;
/**
* FIXME IN-3487
*
* `applyContextToApi` requires `context` to be of type `MiddlewareContext`
* However, the above `const context =` does not satisfy that type.
*
* `this.middleware` provides (among others) `{ req: ..., res: ..., ... }`,
* but `this?.middleware || {}` provides `{ req?: ..., res?: ..., ...}`
*
* `MiddlewareContext` requires `req` and `res` to be required, not optional, hence the error.
*/
// @ts-expect-error see above
const integrationApi = applyContextToApi(api, context, extensionHooks);
// @ts-expect-error see above
const extensionsApi = applyContextToApi(extendedApis ?? {}, context, extensionHooks);
const mergedApi = {
...integrationApi,
...extensionsApi,
};
// api methods haven't been invoked yet, so we still have time to add them to the context
context.api = integrationApi;
return {
api: mergedApi,
client: settings.client,
settings: settings.config,
};
};
createApiClient._predefinedExtensions = factoryParams.extensions || [];
return { createApiClient };
};
export { apiClientFactory, createServer };
//# sourceMappingURL=index.es.js.map

@@ -1,10 +0,10 @@

import type { Integration, ApiClientFactory, ApiClientExtension, ApiMethods, TObject } from '../../types';
import { Extension, ApiClientFactoryResult, IntegrationConfig } from "../../types";
/**
* Imports extensions if they're represented as strings.
*/
export declare function createExtensions(rawExtensions: (ApiClientExtension | string)[]): ApiClientExtension[];
export declare function createExtensions(rawExtensions: (Extension | string)[]): Extension[];
/**
* Creates an array of extensions schemas or their paths.
*/
export declare function createRawExtensions<CONFIG extends TObject, API extends ApiMethods, CONTEXT extends TObject>(apiClient: ApiClientFactory, integration: Integration<CONFIG, API, CONTEXT>): ApiClientExtension<API, CONTEXT>[];
export declare function createRawExtensions(apiClientFactoryResult: ApiClientFactoryResult<any>, integration: IntegrationConfig): Extension[];
//# sourceMappingURL=createExtensions.d.ts.map

@@ -1,3 +0,9 @@

import { LoadInitConfigProps, TObject } from '../../types';
export declare function getInitConfig({ apiClient, tag, integration }: LoadInitConfigProps): Promise<TObject>;
import { Config, ApiClientFactoryResult, IntegrationConfig } from "../../types";
interface LoadInitConfigProps {
apiClientFactoryResult: ApiClientFactoryResult<any>;
tag: string;
integrationConfig: IntegrationConfig;
}
export declare function getInitConfig({ apiClientFactoryResult, tag, integrationConfig, }: LoadInitConfigProps): Promise<Config>;
export {};
//# sourceMappingURL=getInitConfig.d.ts.map

@@ -1,5 +0,5 @@

export { createExtensions, createRawExtensions } from './createExtensions';
export { getInitConfig } from './getInitConfig';
export { lookUpExternal } from './lookUpExternal';
export { resolveDependency } from './resolveDependency';
export { createExtensions, createRawExtensions } from "./createExtensions";
export { getInitConfig } from "./getInitConfig";
export { lookUpExternal } from "./lookUpExternal";
export { resolveDependency } from "./resolveDependency";
//# sourceMappingURL=index.d.ts.map

@@ -1,6 +0,6 @@

import type { ApiClientExtension } from '../../types';
import { Extension } from "../../types";
/**
* Imports extensions from the current working directory if they're represented as strings.
*/
export declare function lookUpExternal(extension: string | ApiClientExtension): ApiClientExtension[];
export declare function lookUpExternal(extension: string | Extension): Extension[];
//# sourceMappingURL=lookUpExternal.d.ts.map

@@ -1,2 +0,2 @@

export { registerIntegrations } from './registerIntegrations';
export { registerIntegrations } from "./registerIntegrations";
//# sourceMappingURL=index.d.ts.map

@@ -1,4 +0,4 @@

import type { Express } from 'express';
import type { Integrations, IntegrationsLoaded } from '../types';
export declare function registerIntegrations(app: Express, integrations: Integrations): Promise<IntegrationsLoaded>;
import type { Express } from "express";
import { IntegrationsLoaded, IntegrationsConfig } from "../types";
export declare function registerIntegrations(app: Express, integrationsConfig: IntegrationsConfig): Promise<IntegrationsLoaded>;
//# sourceMappingURL=registerIntegrations.d.ts.map

@@ -1,48 +0,4 @@

export type ParamType = string | number | symbol;
export type TObject = Record<string, any>;
export type CustomQuery<T extends ParamType = string> = {
[P in T]?: string;
} & {
metadata?: unknown;
};
export interface ContextQueryParams {
query: string;
variables: TObject;
}
export type ContextQuery<T extends ParamType = string> = {
[Key in T]: ContextQueryParams;
};
export type CustomQueryFunction<T = any> = ({ query, variables, metadata, }: {
query: string;
variables: T;
metadata: unknown;
}) => {
query: string;
variables: T;
metadata?: unknown;
};
export type ComposableFunctionArgs<T> = T & {
customQuery?: CustomQuery;
};
export type ApiClientMethod = (...args: any) => Promise<any>;
export type ApiClientMethods<T> = {
[K in keyof T]: T[K] extends (...args: any) => any ? (...args: [...Parameters<T[K]>, CustomQuery?]) => ReturnType<T[K]> : T[K];
};
export type AxiosError = {
isAxiosError: boolean;
response: {
status: number;
};
};
export type ApolloError = {
networkError?: number;
code?: string | number;
};
export type StatusCode = number | null;
export type UnknownError<T extends string> = {
[K in T]?: number;
} & {
[x: string]: UnknownError<T> | any;
};
export type ErrorObject<T extends string> = AxiosError | ApolloError | UnknownError<T>;
export type Config = Record<string, any>;
export type Method = (...args: any[]) => any;
export type Client = any;
//# sourceMappingURL=base.d.ts.map

@@ -1,15 +0,35 @@

import type { HelmetOptions } from 'helmet';
import { Integration } from './common';
import { TObject } from './base';
import { IntegrationContext } from './server';
export interface Helmet extends HelmetOptions {
import { HelmetOptions } from "helmet";
import { Config } from "./base";
import { Extension } from "./exntensions";
import { CustomQueryFunction } from "./query";
import { OrchestrationMethods } from "./orchestration";
import { ApiClientFactoryResult } from "./apiClientFactory";
export interface IntegrationConfig {
location?: string;
apiClient?: ApiClientFactoryResult<any>;
configuration: Config;
extensions?: (extensions: Extension[]) => Extension[];
customQueries?: Record<string, CustomQueryFunction>;
initConfig?: Config;
errorHandler?: (error: unknown, req: Request, res: Response) => void;
}
export type IntegrationsConfig = Record<string, IntegrationConfig>;
export interface MiddlewareConfig<IntegrationsConfigType extends IntegrationsConfig> {
integrations: IntegrationsConfigType;
orchestration?: OrchestrationMethods<IntegrationsConfigType>;
options?: {
helmet?: boolean | HelmetOptions;
};
}
export interface CreateServerParams {
integrations: IntegrationsConfig;
helmet?: boolean | HelmetOptions;
}
export type Integrations<TIntegrationsContext extends TObject = TObject> = {
[IntegrationCode in keyof TIntegrationsContext]: IntegrationCode extends string ? Integration<TIntegrationsContext[IntegrationCode]['config'], TIntegrationsContext[IntegrationCode]['api'], TIntegrationsContext[IntegrationCode]> : never;
};
export interface MiddlewareConfig<TIntegrationsContext extends Record<string, IntegrationContext> = Record<string, IntegrationContext>> {
integrations: Integrations<TIntegrationsContext>;
helmet?: boolean | Readonly<HelmetOptions>;
type OptionalExtensions<Extensions extends Extension[]> = Extensions extends Extension[] ? Extensions : [];
export interface ApiClientConfig<ApiClientType extends ApiClientFactoryResult<any>, ExtensionType extends Extension> extends Omit<IntegrationConfig, "location"> {
apiClient: ApiClientType;
configuration: ReturnType<ApiClientType["createApiClient"]>["settings"];
extensions?: (extensions: OptionalExtensions<ApiClientType["createApiClient"]["_predefinedExtensions"]>) => ExtensionType[];
}
export {};
//# sourceMappingURL=config.d.ts.map

@@ -1,34 +0,11 @@

export type TODO = any;
export type ObjectRecord<O> = {
[K in keyof O]: O[K];
};
export type ObjectItemRecord<V = string, K = string> = {
[keyof in K as string]: V;
};
export type PartialRecord<O> = {
[K in keyof O]?: O[K];
};
export type NullableRecord<V> = V | null;
export type GetConstructorArgs<T> = T extends new (...args: infer U) => any ? U : never;
export type RecordOverloadedReturnType<T> = T extends {
(...args: any[]): infer R;
(...args: any[]): infer R;
(...args: any[]): infer R;
(...args: any[]): infer R;
} ? R : T extends {
(...args: any[]): infer R;
(...args: any[]): infer R;
(...args: any[]): infer R;
} ? R : T extends {
(...args: any[]): infer R;
(...args: any[]): infer R;
} ? R : T extends (...args: any[]) => infer R ? R : any;
export type AnyFunction = (...args: any) => any;
export type WithRequired<T, K extends keyof T> = T & {
[P in K]-?: T[P];
};
export * from './base';
export * from './common';
export * from './server';
export * from './config';
export * from "./apiClientFactory";
export * from "./base";
export * from "./config";
export * from "./context";
export * from "./errors";
export * from "./exntensions";
export * from "./integrations";
export * from "./orchestration";
export * from "./query";
export * from "./utility";
//# sourceMappingURL=index.d.ts.map

@@ -1,1 +0,21 @@

MIT License Copyright (c) 2021 Vue Storefront Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
MIT License
Copyright (c) 2021 Vue Storefront
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
"name": "@vue-storefront/middleware",
"version": "3.6.0-test.0",
"version": "4.0.0-test.0",
"main": "lib/index.cjs.js",

@@ -12,3 +12,2 @@ "module": "lib/index.es.js",

"scripts": {
"prepare": "husky install",
"dev": "rollup -c -w",

@@ -20,3 +19,3 @@ "build": "rimraf lib && rollup -c",

"lint": "eslint . --ext .ts,.js",
"prepublish": "yarn build",
"prepublishOnly": "yarn build",
"changesets:version": "yarn changeset version && YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install",

@@ -33,18 +32,8 @@ "changesets:publish": "yarn build && yarn changeset publish"

"devDependencies": {
"@changesets/cli": "^2.26.1",
"@types/body-parser": "^1.19.2",
"@types/cookie-parser": "^1.4.3",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@vue-storefront/eslint-config-integrations": "^0.0.17",
"@vue-storefront/integrations-tsconfig": "^0.0.2",
"@vue-storefront/jest-config": "^0.0.2",
"@vue-storefront/rollup-config": "^0.0.2",
"husky": "^8.0.3",
"lint-staged": "^13.2.2",
"supertest": "^6.3.3",
"ts-node": "^10.8.1",
"typescript": "^4"
},
"packageManager": "yarn@1.22.10"
"@types/express": "^4.17.17",
"supertest": "^6.3.3"
}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc