Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

hypertune

Package Overview
Dependencies
Maintainers
3
Versions
156
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

hypertune - npm Package Compare versions

Comparing version 1.9.0 to 1.10.0

15

CHANGELOG.md
# Changelog
## 1.10.0
- Added a `setOverride()` method you can use to set a local override that the
SDK should use when evaluating your flags.
- Added `dehydrate()` and `hydrate()` methods you can use to pass the state of
the SDK from the server to the client during server-side rendering. These
replace the `getInitData()` and `initFromData()` methods which are now
deprecated.
- Added a `getStateHash()` method which replaces the `getCommitHash()` method
which is now deprecated.
## 1.9.0

@@ -80,4 +91,4 @@

- Added `addUpdateListener` and `removeUpdateListener` methods on SDK nodes so
you can be notified when the SDK fetches an update.
- Added `addUpdateListener(listener)` and `removeUpdateListener(listener)`
methods on SDK nodes so you can be notified when the SDK fetches an update.

@@ -84,0 +95,0 @@ ## 1.6.5

4

dist/index.d.ts
import "regenerator-runtime/runtime";
import type { InitResponseBody, ObjectValueWithVariables, Query, LoggingMode, InitializeOptions, CustomLogger, InternalInitializeOptions, VercelEdgeConfigClient } from "./shared/types";
import type { InitResponseBody, ObjectValueWithVariables, Query, LoggingMode, InitializeOptions, CustomLogger, InternalInitializeOptions, VercelEdgeConfigClient, DehydratedState } from "./shared/types";
import initialize from "./lib/initialize";
import Node from "./lib/Node";
export type { InitResponseBody, ObjectValueWithVariables, Query, CustomLogger, VercelEdgeConfigClient, LoggingMode, InitializeOptions, InternalInitializeOptions, };
export type { InitResponseBody, ObjectValueWithVariables, Query, CustomLogger, VercelEdgeConfigClient, LoggingMode, InitializeOptions, InternalInitializeOptions, DehydratedState, };
export { LogLevel } from "./generated/graphql";

@@ -7,0 +7,0 @@ export { initialize, Node };

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

import { InitResponseBody, Expression, Query, Value, ObjectValueWithVariables, InitSource, VercelEdgeConfigClient, Endpoints, UpdateListener, Fetch, ReductionLogs } from "../shared";
import { InitResponseBody, Expression, Query, Value, ObjectValueWithVariables, InitSource, VercelEdgeConfigClient, Endpoints, UpdateListener, Fetch, ReductionLogs, DehydratedState, DeepPartial } from "../shared";
import Logger from "./Logger";

@@ -31,2 +31,3 @@ import LRUCache from "../shared/helpers/LRUCache";

readonly updateListeners: Map<UpdateListener, boolean>;
override: Value | null;
constructor(token: string, queryCode: string, variableValues: {

@@ -44,4 +45,9 @@ [variableName: string]: Value;

private getUpdateIntervalMs;
getStateHash(): string;
addUpdateListener(listener: UpdateListener): void;
removeUpdateListener(listener: UpdateListener): void;
private notifyUpdateListeners;
setOverride<T>(override: DeepPartial<T>): void;
dehydrate(): DehydratedState;
hydrate(dehydratedState: DehydratedState): void;
reduce(query: Query<ObjectValueWithVariables> | null, expression: Expression): Expression;

@@ -48,0 +54,0 @@ private log;

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

this.updateListeners = new Map();
this.override = null;
if (cacheSize > 0) {

@@ -79,2 +80,3 @@ this.getFieldCache = new LRUCache_1.default(cacheSize);

}
// @internal
initFromData(initData) {

@@ -94,3 +96,3 @@ const initSourceName = (0, getInitSourceName_1.default)("local");

if (newInitData.commitId <= ((_b = (_a = this.initData) === null || _a === void 0 ? void 0 : _a.commitId) !== null && _b !== void 0 ? _b : -1)) {
this.log(graphql_1.LogLevel.Info, `Skipped initialization from ${initSourceName} as commit isn't newer.`);
this.log(graphql_1.LogLevel.Info, `Skipped initialization from ${initSourceName} as commit with id "${newInitData.commitId}" isn't newer.`);
return;

@@ -114,5 +116,3 @@ }

(_e = this.evaluateCache) === null || _e === void 0 ? void 0 : _e.purge();
this.updateListeners.forEach((_, listener) => {
listener(newInitData.commitHash);
});
this.notifyUpdateListeners();
}

@@ -123,2 +123,3 @@ catch (error) {

}
// @internal
initFromServerIfNeeded() {

@@ -279,8 +280,45 @@ const { lastServerInitTime, shouldGetUpdatesFromServer } = this;

}
// @internal
getStateHash() {
var _a, _b;
const commitHash = (_b = (_a = this.initData) === null || _a === void 0 ? void 0 : _a.commitHash) !== null && _b !== void 0 ? _b : null;
const ssOverride = (0, shared_1.stableStringify)(this.override);
return (0, shared_1.hash)(`${commitHash}/${ssOverride}`).toString();
}
// @internal
addUpdateListener(listener) {
this.updateListeners.set(listener, true);
}
// @internal
removeUpdateListener(listener) {
this.updateListeners.delete(listener);
}
notifyUpdateListeners() {
const stateHash = this.getStateHash();
this.updateListeners.forEach((_, listener) => {
listener(stateHash);
});
}
// @internal
setOverride(override) {
if ((0, shared_1.stableStringify)(override) === (0, shared_1.stableStringify)(this.override)) {
this.log(graphql_1.LogLevel.Info, "Skipped setting override as it's equal to the one already set.");
return;
}
this.override = override;
this.log(graphql_1.LogLevel.Info, "Set override.", { override });
this.notifyUpdateListeners();
}
// @internal
dehydrate() {
const { initData, override } = this;
return { initData, override };
}
// @internal
hydrate(dehydratedState) {
this.log(graphql_1.LogLevel.Info, "Hydrating...");
this.initFromData(dehydratedState.initData);
this.setOverride(dehydratedState.override);
}
// @internal
reduce(query, expression) {

@@ -287,0 +325,0 @@ const { splits, eventTypes, commitConfig } = (0, shared_1.nullThrows)(this.initData, "No init data so cannot reduce expression.");

@@ -5,6 +5,5 @@ "use strict";

function getNodeCacheKey(commitHash, nodePath, suffix) {
return (0, shared_1.hash)(`${commitHash}/${nodePath}/${suffix}
)}`).toString();
return (0, shared_1.hash)(`${commitHash}/${nodePath}/${suffix}`).toString();
}
exports.default = getNodeCacheKey;
//# sourceMappingURL=getNodeCacheKey.js.map

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

const fetchMaxKeepAliveRequestSizeBytes = 64000;
// TODO: Merge with BackendLogger
class Logger {

@@ -42,3 +43,4 @@ constructor({ token, loggingMode, customLogger, endpoints, fetchFunction, }) {

nodePath,
nodeExpression }, metadata);
nodeExpression,
reductionLogs }, metadata);
this.localLog(level, logMessage, logMetadata);

@@ -45,0 +47,0 @@ if ((level === graphql_1.LogLevel.Warn || level === graphql_1.LogLevel.Error) &&

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

import { Expression, ObjectValue, Query, Step, Value, InitResponseBody, UpdateListener, ReductionLogs } from "../shared";
import { Expression, ObjectValue, Query, Step, Value, InitResponseBody, UpdateListener, ReductionLogs, DehydratedState, DeepPartial } from "../shared";
import Context from "./Context";

@@ -22,2 +22,3 @@ import Logger from "./Logger";

protected evaluate(query: Query<ObjectValue> | null, fallback: Value): Value;
private getNodeOverride;
protected getValueAndLogsWithCache(query: Query<ObjectValue> | null): {

@@ -33,2 +34,6 @@ value: Value;

private log;
getStateHash(): string | null;
/**
* @deprecated Use getStateHash() instead
*/
getCommitHash(): string | null;

@@ -50,3 +55,12 @@ addUpdateListener(listener: UpdateListener): void;

flushLogs(): Promise<void>;
setOverride<T>(override: DeepPartial<T>): void;
dehydrate(): DehydratedState | null;
hydrate(dehydratedState: DehydratedState): void;
/**
* @deprecated Use dehydrate() instead
*/
getInitData(): InitResponseBody | null;
/**
* @deprecated Use hydrate() instead
*/
initFromData(initData: InitResponseBody): void;

@@ -53,0 +67,0 @@ close(): void;

@@ -167,2 +167,6 @@ "use strict";

evaluate(query, fallback) {
const nodeOverride = this.getNodeOverride();
if (nodeOverride !== null && nodeOverride !== undefined) {
return nodeOverride;
}
const valueAndLogs = this.getValueAndLogsWithCache(query);

@@ -172,7 +176,33 @@ if (!valueAndLogs) {

}
const { value, logs } = valueAndLogs;
const { value, logs: reductionLogs } = valueAndLogs;
this.log(graphql_1.LogLevel.Debug, `Evaluated to ${JSON.stringify(value)}`,
/* metadata */ { query }, logs);
/* metadata */ { query }, reductionLogs);
return value;
}
getNodeOverride() {
var _a, _b, _c;
const { context, parent, step } = this.props;
if (!context) {
return null;
}
if (context.override === null || context.override === undefined) {
// Short-circuit if no override in context
return null;
}
if (!parent) {
// We're the Query node
return (_a = context.override) !== null && _a !== void 0 ? _a : null;
}
if (!step) {
return null;
}
const parentOverride = parent.getNodeOverride();
if (parentOverride === null || parentOverride === undefined) {
return null;
}
if (step.type === "GetFieldStep") {
return (_b = parentOverride[step.fieldName]) !== null && _b !== void 0 ? _b : null;
}
return (_c = parentOverride[step.index]) !== null && _c !== void 0 ? _c : null;
}
// @internal

@@ -256,2 +286,13 @@ getValueAndLogsWithCache(query) {

}
getStateHash() {
const { context } = this.props;
if (!context) {
this.log(graphql_1.LogLevel.Error, "No context so cannot get state hash.");
return null;
}
return context.getStateHash();
}
/**
* @deprecated Use getStateHash() instead
*/
getCommitHash() {

@@ -318,2 +359,29 @@ var _a, _b;

}
setOverride(override) {
const { context } = this.props;
if (!context) {
this.log(graphql_1.LogLevel.Error, "No context so cannot set override.");
return;
}
context.setOverride(override);
}
dehydrate() {
const { context } = this.props;
if (!context) {
this.log(graphql_1.LogLevel.Error, "No context so cannot dehydrate.");
return null;
}
return context.dehydrate();
}
hydrate(dehydratedState) {
const { context } = this.props;
if (!context) {
this.log(graphql_1.LogLevel.Error, "No context so cannot hydrate.");
return;
}
context.hydrate(dehydratedState);
}
/**
* @deprecated Use dehydrate() instead
*/
getInitData() {

@@ -327,2 +395,5 @@ const { context } = this.props;

}
/**
* @deprecated Use hydrate() instead
*/
initFromData(initData) {

@@ -329,0 +400,0 @@ const { context } = this.props;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/** Replaced by the value in package.json on build */
exports.default = "1.9.0";
exports.default = "1.10.0";
//# sourceMappingURL=sdkVersion.js.map

@@ -587,3 +587,3 @@ import { z } from "zod";

export type InitSource = "none" | "local" | "hypertuneEdge" | "vercelEdgeConfig";
export type UpdateListener = (newCommitHash: string) => void;
export type UpdateListener = (newStateHash: string) => void;
export type Fetch = typeof fetch;

@@ -623,2 +623,9 @@ export type InitializeOptions = {

};
export type DehydratedState = {
initData: InitResponseBody | null;
override: Value | null;
};
export type DeepPartial<T> = T extends (infer U)[] ? DeepPartial<U>[] | undefined : T extends object ? {
[P in keyof T]?: DeepPartial<T[P]>;
} : T;
export type CodegenArguments = {

@@ -625,0 +632,0 @@ token: string;

{
"name": "hypertune",
"version": "1.9.0",
"version": "1.10.0",
"private": false,

@@ -5,0 +5,0 @@ "main": "./dist/index.js",

@@ -11,2 +11,3 @@ import "regenerator-runtime/runtime";

VercelEdgeConfigClient,
DehydratedState,
} from "./shared/types";

@@ -25,2 +26,3 @@ import initialize from "./lib/initialize";

InternalInitializeOptions,
DehydratedState,
};

@@ -27,0 +29,0 @@

@@ -17,2 +17,6 @@ import pRetry from "p-retry";

ReductionLogs,
DehydratedState,
DeepPartial,
hash,
stableStringify,
} from "../shared";

@@ -53,2 +57,3 @@ import { hashRequest, initRequest } from "./edge";

public readonly updateListeners: Map<UpdateListener, boolean>;
public override: Value | null;

@@ -93,2 +98,3 @@ // eslint-disable-next-line max-params

this.updateListeners = new Map();
this.override = null;

@@ -128,2 +134,3 @@ if (cacheSize > 0) {

// @internal
initFromData(initData: InitResponseBody | null): void {

@@ -152,3 +159,3 @@ const initSourceName = getInitSourceName("local");

LogLevel.Info,
`Skipped initialization from ${initSourceName} as commit isn't newer.`
`Skipped initialization from ${initSourceName} as commit with id "${newInitData.commitId}" isn't newer.`
);

@@ -191,5 +198,4 @@ return;

this.evaluateCache?.purge();
this.updateListeners.forEach((_, listener) => {
listener(newInitData.commitHash);
});
this.notifyUpdateListeners();
} catch (error) {

@@ -204,2 +210,3 @@ this.log(

// @internal
initFromServerIfNeeded(): Promise<void> {

@@ -455,10 +462,55 @@ const { lastServerInitTime, shouldGetUpdatesFromServer } = this;

public addUpdateListener(listener: UpdateListener): void {
// @internal
getStateHash(): string {
const commitHash = this.initData?.commitHash ?? null;
const ssOverride = stableStringify(this.override);
return hash(`${commitHash}/${ssOverride}`).toString();
}
// @internal
addUpdateListener(listener: UpdateListener): void {
this.updateListeners.set(listener, true);
}
public removeUpdateListener(listener: UpdateListener): void {
// @internal
removeUpdateListener(listener: UpdateListener): void {
this.updateListeners.delete(listener);
}
private notifyUpdateListeners(): void {
const stateHash = this.getStateHash();
this.updateListeners.forEach((_, listener) => {
listener(stateHash);
});
}
// @internal
setOverride<T>(override: DeepPartial<T>): void {
if (stableStringify(override) === stableStringify(this.override)) {
this.log(
LogLevel.Info,
"Skipped setting override as it's equal to the one already set."
);
return;
}
this.override = override as Value | null;
this.log(LogLevel.Info, "Set override.", { override });
this.notifyUpdateListeners();
}
// @internal
dehydrate(): DehydratedState {
const { initData, override } = this;
return { initData, override };
}
// @internal
hydrate(dehydratedState: DehydratedState): void {
this.log(LogLevel.Info, "Hydrating...");
this.initFromData(dehydratedState.initData);
this.setOverride(dehydratedState.override);
}
// @internal
reduce(

@@ -465,0 +517,0 @@ query: Query<ObjectValueWithVariables> | null,

@@ -8,6 +8,3 @@ import { hash } from "../shared";

): string {
return hash(
`${commitHash}/${nodePath}/${suffix}
)}`
).toString();
return hash(`${commitHash}/${nodePath}/${suffix}`).toString();
}

@@ -21,2 +21,3 @@ import {

// TODO: Merge with BackendLogger
export default class Logger {

@@ -82,2 +83,3 @@ public readonly id: string;

nodeExpression,
reductionLogs,
...metadata,

@@ -84,0 +86,0 @@ };

@@ -22,2 +22,4 @@ /* eslint-disable no-underscore-dangle */

asError,
DehydratedState,
DeepPartial,
} from "../shared";

@@ -286,2 +288,7 @@ import getDeepestZodIssue from "../shared/helpers/getDeepestZodIssue";

protected evaluate(query: Query<ObjectValue> | null, fallback: Value): Value {
const nodeOverride = this.getNodeOverride();
if (nodeOverride !== null && nodeOverride !== undefined) {
return nodeOverride;
}
const valueAndLogs = this.getValueAndLogsWithCache(query);

@@ -293,3 +300,3 @@

const { value, logs } = valueAndLogs;
const { value, logs: reductionLogs } = valueAndLogs;

@@ -300,3 +307,3 @@ this.log(

/* metadata */ { query },
logs
reductionLogs
);

@@ -307,2 +314,36 @@

private getNodeOverride(): Value | null {
const { context, parent, step } = this.props;
if (!context) {
return null;
}
if (context.override === null || context.override === undefined) {
// Short-circuit if no override in context
return null;
}
if (!parent) {
// We're the Query node
return context.override ?? null;
}
if (!step) {
return null;
}
const parentOverride = parent.getNodeOverride();
if (parentOverride === null || parentOverride === undefined) {
return null;
}
if (step.type === "GetFieldStep") {
return (parentOverride as ObjectValue)[step.fieldName] ?? null;
}
return (parentOverride as Value[])[step.index] ?? null;
}
// @internal

@@ -447,2 +488,14 @@ protected getValueAndLogsWithCache(

getStateHash(): string | null {
const { context } = this.props;
if (!context) {
this.log(LogLevel.Error, "No context so cannot get state hash.");
return null;
}
return context.getStateHash();
}
/**
* @deprecated Use getStateHash() instead
*/
getCommitHash(): string | null {

@@ -521,2 +574,32 @@ const { context } = this.props;

setOverride<T>(override: DeepPartial<T>): void {
const { context } = this.props;
if (!context) {
this.log(LogLevel.Error, "No context so cannot set override.");
return;
}
context.setOverride<T>(override);
}
dehydrate(): DehydratedState | null {
const { context } = this.props;
if (!context) {
this.log(LogLevel.Error, "No context so cannot dehydrate.");
return null;
}
return context.dehydrate();
}
hydrate(dehydratedState: DehydratedState): void {
const { context } = this.props;
if (!context) {
this.log(LogLevel.Error, "No context so cannot hydrate.");
return;
}
context.hydrate(dehydratedState);
}
/**
* @deprecated Use dehydrate() instead
*/
getInitData(): InitResponseBody | null {

@@ -531,2 +614,5 @@ const { context } = this.props;

/**
* @deprecated Use hydrate() instead
*/
initFromData(initData: InitResponseBody): void {

@@ -533,0 +619,0 @@ const { context } = this.props;

@@ -745,3 +745,3 @@ /* eslint-disable capitalized-comments */

export type UpdateListener = (newCommitHash: string) => void;
export type UpdateListener = (newStateHash: string) => void;

@@ -791,2 +791,15 @@ export type Fetch = typeof fetch;

export type DehydratedState = {
initData: InitResponseBody | null;
override: Value | null;
};
export type DeepPartial<T> = T extends (infer U)[]
? DeepPartial<U>[] | undefined
: T extends object
? {
[P in keyof T]?: DeepPartial<T[P]>;
}
: T;
// Codegen Command

@@ -793,0 +806,0 @@

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