Socket
Socket
Sign inDemoInstall

@growthbook/proxy

Package Overview
Dependencies
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@growthbook/proxy - npm Package Compare versions

Comparing version 1.1.3 to 1.1.5

dist/services/stickyBucket/index.d.ts

5

dist/app.js

@@ -50,2 +50,3 @@ "use strict";

const logger_1 = __importStar(require("./services/logger"));
const stickyBucket_1 = require("./services/stickyBucket");
let build;

@@ -90,2 +91,3 @@ function getBuild() {

enableRemoteEval: true,
enableStickyBucketing: false,
proxyAllRequests: false,

@@ -107,2 +109,5 @@ };

ctx.enableCache && (yield (0, cache_1.initializeCache)(ctx));
ctx.enableRemoteEval &&
ctx.enableStickyBucketing &&
(yield (0, stickyBucket_1.initializeStickyBucketService)(ctx));
ctx.enableEventStream && (0, eventStreamManager_1.initializeEventStreamManager)(ctx);

@@ -109,0 +114,0 @@ // set up handlers

4

dist/controllers/featuresController.js

@@ -20,2 +20,3 @@ "use strict";

const cache_1 = require("../services/cache");
const stickyBucket_1 = require("../services/stickyBucket");
const registrar_1 = require("../services/registrar");

@@ -135,3 +136,3 @@ const apiKeyMiddleware_1 = require("../middleware/apiKeyMiddleware");

const url = (_f = req.body) === null || _f === void 0 ? void 0 : _f.url;
payload = (0, proxy_eval_1.evaluateFeatures)({
payload = yield (0, proxy_eval_1.evaluateFeatures)({
payload,

@@ -142,2 +143,3 @@ attributes,

url,
stickyBucketService: stickyBucket_1.stickyBucketService,
ctx: (_g = req.app.locals) === null || _g === void 0 ? void 0 : _g.ctx,

@@ -144,0 +146,0 @@ });

@@ -45,16 +45,16 @@ "use strict";

exports.default = () => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
const context = {
growthbookApiHost: process.env.GROWTHBOOK_API_HOST,
growthbookApiHost: ((_a = process.env.GROWTHBOOK_API_HOST) !== null && _a !== void 0 ? _a : "").replace(/\/*$/, ""),
secretApiKey: process.env.SECRET_API_KEY,
environment: process.env.NODE_ENV,
enableAdmin: ["true", "1"].includes((_a = process.env.ENABLE_ADMIN) !== null && _a !== void 0 ? _a : "0"),
enableAdmin: ["true", "1"].includes((_b = process.env.ENABLE_ADMIN) !== null && _b !== void 0 ? _b : "0"),
adminKey: process.env.ADMIN_KEY,
multiOrg: ["true", "1"].includes((_b = process.env.MULTI_ORG) !== null && _b !== void 0 ? _b : "0"),
verboseDebugging: ["true", "1"].includes((_c = process.env.VERBOSE_DEBUGGING) !== null && _c !== void 0 ? _c : "0"),
maxPayloadSize: (_d = process.env.MAX_PAYLOAD_SIZE) !== null && _d !== void 0 ? _d : exports.MAX_PAYLOAD_SIZE,
multiOrg: ["true", "1"].includes((_c = process.env.MULTI_ORG) !== null && _c !== void 0 ? _c : "0"),
verboseDebugging: ["true", "1"].includes((_d = process.env.VERBOSE_DEBUGGING) !== null && _d !== void 0 ? _d : "0"),
maxPayloadSize: (_e = process.env.MAX_PAYLOAD_SIZE) !== null && _e !== void 0 ? _e : exports.MAX_PAYLOAD_SIZE,
// SDK Connections settings:
createConnectionsFromEnv: ["true", "1"].includes((_e = process.env.CREATE_CONNECTIONS_FROM_ENV) !== null && _e !== void 0 ? _e : "1"),
pollForConnections: ["true", "1"].includes((_f = process.env.POLL_FOR_CONNECTIONS) !== null && _f !== void 0 ? _f : "1"),
connectionPollingFrequency: parseInt((_g = process.env.CONNECTION_POLLING_FREQUENCY) !== null && _g !== void 0 ? _g : "60000"),
createConnectionsFromEnv: ["true", "1"].includes((_f = process.env.CREATE_CONNECTIONS_FROM_ENV) !== null && _f !== void 0 ? _f : "1"),
pollForConnections: ["true", "1"].includes((_g = process.env.POLL_FOR_CONNECTIONS) !== null && _g !== void 0 ? _g : "1"),
connectionPollingFrequency: parseInt((_h = process.env.CONNECTION_POLLING_FREQUENCY) !== null && _h !== void 0 ? _h : "60000"),
// Cache settings:

@@ -65,3 +65,3 @@ cacheSettings: {

expiresTTL: parseInt(process.env.CACHE_EXPIRES_TTL || "600"),
allowStale: ["true", "1"].includes((_h = process.env.CACHE_ALLOW_STALE) !== null && _h !== void 0 ? _h : "1"),
allowStale: ["true", "1"].includes((_j = process.env.CACHE_ALLOW_STALE) !== null && _j !== void 0 ? _j : "1"),
connectionUrl: process.env.CACHE_CONNECTION_URL,

@@ -73,5 +73,5 @@ useAdditionalMemoryCache: true,

// Redis only - pub/sub:
publishPayloadToChannel: ["true", "1"].includes((_j = process.env.PUBLISH_PAYLOAD_TO_CHANNEL) !== null && _j !== void 0 ? _j : "0"),
publishPayloadToChannel: ["true", "1"].includes((_k = process.env.PUBLISH_PAYLOAD_TO_CHANNEL) !== null && _k !== void 0 ? _k : "0"),
// Redis only - cluster:
useCluster: ["true", "1"].includes((_k = process.env.USE_CLUSTER) !== null && _k !== void 0 ? _k : "0"),
useCluster: ["true", "1"].includes((_l = process.env.USE_CLUSTER) !== null && _l !== void 0 ? _l : "0"),
clusterRootNodesJSON: process.env.CLUSTER_ROOT_NODES_JSON

@@ -85,8 +85,23 @@ ? JSON.parse(process.env.CLUSTER_ROOT_NODES_JSON)

// SSE settings:
enableEventStream: ["true", "1"].includes((_l = process.env.ENABLE_EVENT_STREAM) !== null && _l !== void 0 ? _l : "1"),
enableEventStreamHeaders: ["true", "1"].includes((_m = process.env.ENABLE_EVENT_STREAM_HEADERS) !== null && _m !== void 0 ? _m : "1"),
eventStreamMaxDurationMs: parseInt((_o = process.env.EVENT_STREAM_MAX_DURATION_MS) !== null && _o !== void 0 ? _o : "60000"),
eventStreamPingIntervalMs: parseInt((_p = process.env.EVENT_STREAM_PING_INTERVAL_MS) !== null && _p !== void 0 ? _p : "30000"),
enableEventStream: ["true", "1"].includes((_m = process.env.ENABLE_EVENT_STREAM) !== null && _m !== void 0 ? _m : "1"),
enableEventStreamHeaders: ["true", "1"].includes((_o = process.env.ENABLE_EVENT_STREAM_HEADERS) !== null && _o !== void 0 ? _o : "1"),
eventStreamMaxDurationMs: parseInt((_p = process.env.EVENT_STREAM_MAX_DURATION_MS) !== null && _p !== void 0 ? _p : "60000"),
eventStreamPingIntervalMs: parseInt((_q = process.env.EVENT_STREAM_PING_INTERVAL_MS) !== null && _q !== void 0 ? _q : "30000"),
// Remote eval settings:
enableRemoteEval: ["true", "1"].includes((_q = process.env.ENABLE_REMOTE_EVAL) !== null && _q !== void 0 ? _q : "1"),
enableRemoteEval: ["true", "1"].includes((_r = process.env.ENABLE_REMOTE_EVAL) !== null && _r !== void 0 ? _r : "1"),
// Sticky Bucket settings (for remote eval):
enableStickyBucketing: ["true", "1"].includes((_s = process.env.ENABLE_STICKY_BUCKETING) !== null && _s !== void 0 ? _s : "0"),
stickyBucketSettings: {
engine: (process.env.STICKY_BUCKET_ENGINE ||
"none"),
connectionUrl: process.env.STICKY_BUCKET_CONNECTION_URL,
// Redis only - cluster:
useCluster: ["true", "1"].includes((_t = process.env.STICKY_BUCKET_USE_CLUSTER) !== null && _t !== void 0 ? _t : "0"),
clusterRootNodesJSON: process.env.STICKY_BUCKET_CLUSTER_ROOT_NODES_JSON
? JSON.parse(process.env.STICKY_BUCKET_CLUSTER_ROOT_NODES_JSON)
: undefined,
clusterOptionsJSON: process.env.STICKY_BUCKET_CLUSTER_OPTIONS_JSON
? JSON.parse(process.env.STICKY_BUCKET_CLUSTER_OPTIONS_JSON)
: undefined,
},
};

@@ -93,0 +108,0 @@ // Express configuration consts:

@@ -8,4 +8,4 @@ import { Context } from "../../types";

}): Promise<{
payload: any;
payload: {};
oldEntry: import("../cache").CacheEntry | undefined;
} | undefined>;

@@ -79,8 +79,22 @@ "use strict";

promise = fetch(url, fetchOptions)
.then((resp) => resp.json())
.catch((e) => logger_1.default.error(e, "Refresh stale cache error"))
.then((resp) => {
if (!resp.ok) {
throw new Error(`HTTP error: ${resp.status}`);
}
return resp.json();
})
.catch((e) => {
logger_1.default.error(e, "Refresh stale cache error");
return Promise.reject(e);
})
.finally(() => delete activeFetches[url]);
activeFetches[url] = promise;
}
const payload = yield promise;
let payload = null;
try {
payload = yield promise;
}
catch (e) {
// ignore, logging handled in promise
}
if (payload) {

@@ -87,0 +101,0 @@ logger_1.default.debug("cache STALE, refreshing cache...");

@@ -95,3 +95,3 @@ "use strict";

const maxPages = 10;
let respConnections = {};
const respConnections = {};
while (page <= maxPages) {

@@ -98,0 +98,0 @@ page++;

@@ -6,2 +6,3 @@ import { Express } from "express";

import { FeaturesCache, CacheSettings } from "./services/cache";
import { StickyBucketSettings } from "./services/stickyBucket";
export interface GrowthBookProxy {

@@ -29,2 +30,5 @@ app: Express;

} & CacheSettings;
stickyBucketSettings?: {
engine: StickyBucketEngine;
} & StickyBucketSettings;
enableHealthCheck?: boolean;

@@ -40,2 +44,3 @@ enableCors?: boolean;

enableRemoteEval?: boolean;
enableStickyBucketing?: boolean;
proxyAllRequests?: boolean;

@@ -47,1 +52,2 @@ environment?: "development" | "production";

export type CacheEngine = "memory" | "redis" | "mongo";
export type StickyBucketEngine = "redis" | "none";

@@ -7,3 +7,3 @@ {

"description": "GrowthBook proxy server for caching, realtime updates, telemetry, etc",
"version": "1.1.3",
"version": "1.1.5",
"main": "dist/app.js",

@@ -35,3 +35,3 @@ "license": "MIT",

"uuid": "^9.0.0",
"@growthbook/proxy-eval": "^1.0.0"
"@growthbook/proxy-eval": "^1.0.2"
},

@@ -47,6 +47,7 @@ "devDependencies": {

"nodemon": "^3.0.1",
"pino-pretty": "^10.2.3",
"pino-pretty": "^10.3.1",
"rimraf": "^5.0.5",
"typescript": "5.2.2"
"typescript": "5.2.2",
"@growthbook/growthbook": "^0.34.0"
}
}

@@ -17,2 +17,3 @@ import fs from "fs";

import logger, { initializeLogger } from "./services/logger";
import { initializeStickyBucketService } from "./services/stickyBucket";

@@ -61,2 +62,3 @@ export { Context, GrowthBookProxy, CacheEngine } from "./types";

enableRemoteEval: true,
enableStickyBucketing: false,
proxyAllRequests: false,

@@ -77,3 +79,2 @@ };

// initialize

@@ -83,2 +84,5 @@ initializeLogger(ctx);

ctx.enableCache && (await initializeCache(ctx));
ctx.enableRemoteEval &&
ctx.enableStickyBucketing &&
(await initializeStickyBucketService(ctx));
ctx.enableEventStream && initializeEventStreamManager(ctx);

@@ -85,0 +89,0 @@

@@ -5,2 +5,3 @@ import express, { NextFunction, Request, Response } from "express";

import { featuresCache } from "../services/cache";
import { stickyBucketService } from "../services/stickyBucket";
import { registrar } from "../services/registrar";

@@ -148,3 +149,3 @@ import { apiKeyMiddleware } from "../middleware/apiKeyMiddleware";

payload = evaluateFeatures({
payload = await evaluateFeatures({
payload,

@@ -155,2 +156,3 @@ attributes,

url,
stickyBucketService,
ctx: req.app.locals?.ctx,

@@ -157,0 +159,0 @@ });

import express from "express";
import * as spdy from "spdy";
import dotenv from "dotenv";
import { CacheEngine, Context } from "./types";
import { CacheEngine, Context, StickyBucketEngine } from "./types";
dotenv.config({ path: "./.env.local" });

@@ -11,3 +11,6 @@

const context: Partial<Context> = {
growthbookApiHost: process.env.GROWTHBOOK_API_HOST,
growthbookApiHost: (process.env.GROWTHBOOK_API_HOST ?? "").replace(
/\/*$/,
"",
),
secretApiKey: process.env.SECRET_API_KEY,

@@ -23,5 +26,11 @@ environment: process.env.NODE_ENV as Context["environment"],

// SDK Connections settings:
createConnectionsFromEnv: ["true", "1"].includes(process.env.CREATE_CONNECTIONS_FROM_ENV ?? "1"),
pollForConnections: ["true", "1"].includes(process.env.POLL_FOR_CONNECTIONS ?? "1"),
connectionPollingFrequency: parseInt(process.env.CONNECTION_POLLING_FREQUENCY ?? "60000"),
createConnectionsFromEnv: ["true", "1"].includes(
process.env.CREATE_CONNECTIONS_FROM_ENV ?? "1",
),
pollForConnections: ["true", "1"].includes(
process.env.POLL_FOR_CONNECTIONS ?? "1",
),
connectionPollingFrequency: parseInt(
process.env.CONNECTION_POLLING_FREQUENCY ?? "60000",
),
// Cache settings:

@@ -68,2 +77,21 @@ cacheSettings: {

),
// Sticky Bucket settings (for remote eval):
enableStickyBucketing: ["true", "1"].includes(
process.env.ENABLE_STICKY_BUCKETING ?? "0",
),
stickyBucketSettings: {
engine: (process.env.STICKY_BUCKET_ENGINE ||
"none") as StickyBucketEngine,
connectionUrl: process.env.STICKY_BUCKET_CONNECTION_URL,
// Redis only - cluster:
useCluster: ["true", "1"].includes(
process.env.STICKY_BUCKET_USE_CLUSTER ?? "0",
),
clusterRootNodesJSON: process.env.STICKY_BUCKET_CLUSTER_ROOT_NODES_JSON
? JSON.parse(process.env.STICKY_BUCKET_CLUSTER_ROOT_NODES_JSON)
: undefined,
clusterOptionsJSON: process.env.STICKY_BUCKET_CLUSTER_OPTIONS_JSON
? JSON.parse(process.env.STICKY_BUCKET_CLUSTER_OPTIONS_JSON)
: undefined,
},
};

@@ -70,0 +98,0 @@

@@ -56,4 +56,12 @@ import * as https from "https";

promise = fetch(url, fetchOptions)
.then((resp) => resp.json())
.catch((e) => logger.error(e, "Refresh stale cache error"))
.then((resp) => {
if (!resp.ok) {
throw new Error(`HTTP error: ${resp.status}`);
}
return resp.json();
})
.catch((e) => {
logger.error(e, "Refresh stale cache error");
return Promise.reject(e);
})
.finally(() => delete activeFetches[url]);

@@ -64,3 +72,8 @@

const payload = await promise;
let payload: unknown = null;
try {
payload = await promise;
} catch (e) {
// ignore, logging handled in promise
}

@@ -67,0 +80,0 @@ if (payload) {

@@ -106,7 +106,11 @@ import https from "https";

const maxPages = 10;
let respConnections: { [key: string]: Partial<Connection> } = {};
const respConnections: { [key: string]: Partial<Connection> } = {};
while (page <= maxPages) {
page++;
const url = `${this.growthbookApiHost}/api/v1/sdk-connections?withProxy=1&limit=${limit}&offset=${offset}${this.multiOrg ? "&multiOrg=1" : ""}`;
const url = `${
this.growthbookApiHost
}/api/v1/sdk-connections?withProxy=1&limit=${limit}&offset=${offset}${
this.multiOrg ? "&multiOrg=1" : ""
}`;
const headers = {

@@ -129,10 +133,12 @@ Authorization: `Bearer ${this.secretApiKey}`,

let data: {
connections: ConnectionDoc[];
limit?: number;
offset?: number;
total?: number;
hasMore?: boolean;
nextOffset?: number | null;
} | undefined = undefined;
let data:
| {
connections: ConnectionDoc[];
limit?: number;
offset?: number;
total?: number;
hasMore?: boolean;
nextOffset?: number | null;
}
| undefined = undefined;
try {

@@ -139,0 +145,0 @@ data = await resp.json();

@@ -6,2 +6,3 @@ import { Express } from "express";

import { FeaturesCache, CacheSettings } from "./services/cache";
import { StickyBucketSettings } from "./services/stickyBucket";

@@ -31,2 +32,5 @@ export interface GrowthBookProxy {

} & CacheSettings;
stickyBucketSettings?: {
engine: StickyBucketEngine;
} & StickyBucketSettings;
enableHealthCheck?: boolean;

@@ -42,2 +46,3 @@ enableCors?: boolean;

enableRemoteEval?: boolean;
enableStickyBucketing?: boolean;
proxyAllRequests?: boolean;

@@ -50,1 +55,2 @@ environment?: "development" | "production";

export type CacheEngine = "memory" | "redis" | "mongo";
export type StickyBucketEngine = "redis" | "none";

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