hypertune
Advanced tools
Comparing version 1.0.12 to 1.0.13
@@ -10,3 +10,3 @@ module.exports = { | ||
}, | ||
plugins: ["@typescript-eslint", "prettier"], | ||
plugins: ["@typescript-eslint", "prettier", "unused-imports"], | ||
extends: [ | ||
@@ -22,2 +22,3 @@ "airbnb", | ||
rules: { | ||
"unused-imports/no-unused-imports": "error", | ||
"no-nested-ternary": "off", | ||
@@ -24,0 +25,0 @@ "jsx-a11y/label-has-associated-control": "off", |
{ | ||
"name": "hypertune", | ||
"version": "1.0.12", | ||
"version": "1.0.13", | ||
"description": "Hypertune SDK", | ||
@@ -27,2 +27,3 @@ "exports": "./build/src/index.js", | ||
"@types/node-fetch": "^2.6.1", | ||
"@types/seedrandom": "^3.0.2", | ||
"eslint": "^8.15.0", | ||
@@ -35,2 +36,3 @@ "eslint-config-airbnb": "^19.0.4", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"eslint-plugin-unused-imports": "^2.0.0", | ||
"jest": "^29.1.2", | ||
@@ -51,4 +53,6 @@ "prettier": "^2.6.2", | ||
"node-fetch": "^2.6.7", | ||
"regenerator-runtime": "^0.13.9" | ||
"regenerator-runtime": "^0.13.9", | ||
"seedrandom": "^3.0.5", | ||
"zod": "^3.19.1" | ||
} | ||
} |
@@ -91,4 +91,4 @@ #!/usr/bin/env node | ||
_a = getArguments(), businessToken = _a.businessToken, projectId = _a.projectId, queryCode = _a.queryCode, outputDirectoryPath = _a.outputDirectoryPath; | ||
return [4 /*yield*/, (0, edge_1.codegenRequest)(businessToken, projectId, null, // schemaVersion | ||
queryCode)]; | ||
return [4 /*yield*/, (0, edge_1.codegenRequest)(businessToken, projectId, queryCode, null // schemaVersion | ||
)]; | ||
case 1: | ||
@@ -95,0 +95,0 @@ codegenResponse = _b.sent(); |
@@ -62,3 +62,7 @@ import { GraphQLClient } from 'graphql-request'; | ||
}; | ||
export declare type FunnelDataInput = { | ||
export declare type EvaluationsJsonInput = { | ||
commitId?: InputMaybe<Scalars['ID']>; | ||
projectId?: InputMaybe<Scalars['ID']>; | ||
}; | ||
export declare type FunnelDataJsonInput = { | ||
end: Scalars['String']; | ||
@@ -90,2 +94,22 @@ start: Scalars['String']; | ||
}; | ||
export declare type Log = { | ||
__typename?: 'Log'; | ||
code?: Maybe<Scalars['String']>; | ||
commitId: Scalars['ID']; | ||
contextJson: Scalars['String']; | ||
createdAt: Scalars['String']; | ||
error?: Maybe<Scalars['String']>; | ||
id: Scalars['ID']; | ||
initLogId?: Maybe<Scalars['ID']>; | ||
nanoId: Scalars['ID']; | ||
nodeClassName?: Maybe<Scalars['String']>; | ||
nodeExpressionJson?: Maybe<Scalars['String']>; | ||
nodeOpJson?: Maybe<Scalars['String']>; | ||
nodePath?: Maybe<Scalars['String']>; | ||
queryJson?: Maybe<Scalars['String']>; | ||
reducedExpressionJson?: Maybe<Scalars['String']>; | ||
reductionLogsJson?: Maybe<Scalars['String']>; | ||
type: LogType; | ||
valueJson?: Maybe<Scalars['String']>; | ||
}; | ||
export declare type LogInput = { | ||
@@ -112,6 +136,14 @@ code?: InputMaybe<Scalars['String']>; | ||
GraphQl = "GraphQL", | ||
Hash = "Hash", | ||
Init = "Init", | ||
Js = "JS", | ||
Sdk = "SDK" | ||
Sdk = "SDK", | ||
Schema = "Schema" | ||
} | ||
export declare type LogsInput = { | ||
afterLogId?: InputMaybe<Scalars['ID']>; | ||
beforeLogId?: InputMaybe<Scalars['ID']>; | ||
commitId?: InputMaybe<Scalars['ID']>; | ||
limit?: InputMaybe<Scalars['Int']>; | ||
}; | ||
export declare type Mutation = { | ||
@@ -122,2 +154,3 @@ __typename?: 'Mutation'; | ||
createProject: Scalars['ID']; | ||
updateProject: Scalars['ID']; | ||
}; | ||
@@ -133,2 +166,5 @@ export declare type MutationCreateCommitArgs = { | ||
}; | ||
export declare type MutationUpdateProjectArgs = { | ||
input: UpdateProjectInput; | ||
}; | ||
export declare enum Plan { | ||
@@ -150,2 +186,3 @@ Free = "Free" | ||
funnelDataJson: Scalars['String']; | ||
logs: Array<Log>; | ||
me: User; | ||
@@ -158,8 +195,10 @@ project: Project; | ||
export declare type QueryEvaluationsJsonArgs = { | ||
commitId?: InputMaybe<Scalars['ID']>; | ||
projectId?: InputMaybe<Scalars['ID']>; | ||
input: EvaluationsJsonInput; | ||
}; | ||
export declare type QueryFunnelDataJsonArgs = { | ||
input: FunnelDataInput; | ||
input: FunnelDataJsonInput; | ||
}; | ||
export declare type QueryLogsArgs = { | ||
input: LogsInput; | ||
}; | ||
export declare type QueryProjectArgs = { | ||
@@ -174,2 +213,6 @@ id: Scalars['ID']; | ||
}; | ||
export declare type UpdateProjectInput = { | ||
id: Scalars['ID']; | ||
name: Scalars['String']; | ||
}; | ||
export declare type User = { | ||
@@ -176,0 +219,0 @@ __typename?: 'User'; |
@@ -27,5 +27,7 @@ "use strict"; | ||
LogType["GraphQl"] = "GraphQL"; | ||
LogType["Hash"] = "Hash"; | ||
LogType["Init"] = "Init"; | ||
LogType["Js"] = "JS"; | ||
LogType["Sdk"] = "SDK"; | ||
LogType["Schema"] = "Schema"; | ||
})(LogType = exports.LogType || (exports.LogType = {})); | ||
@@ -32,0 +34,0 @@ var Plan; |
import { LoggingMode } from ".."; | ||
import Node from "./Node"; | ||
import { DbNodeOp, EdgeInitResponseBody, Expression, ObjectValue, Query, ReductionLogs, Value } from "./shared/types"; | ||
import { DbNodeOp, InitResponseBody, Expression, ObjectValue, Query, ReductionLogs, Value } from "./shared/types"; | ||
export default class Context { | ||
@@ -8,5 +8,7 @@ readonly businessToken: string; | ||
readonly schemaVersion: string | null; | ||
private readonly queryCode; | ||
private readonly variableValues; | ||
initResponse: EdgeInitResponseBody; | ||
readonly queryCode: string; | ||
readonly variableValues: { | ||
[variableName: string]: Value; | ||
}; | ||
initResponse: InitResponseBody; | ||
rootNodeRef: WeakRef<Node> | null; | ||
@@ -19,3 +21,3 @@ private readonly loggingMode; | ||
[variableName: string]: Value; | ||
}, initResponse: EdgeInitResponseBody, rootNodeRef: WeakRef<Node> | null, loggingMode: LoggingMode, shouldListenForUpdates: boolean, enableConsoleDebugLogging: boolean); | ||
}, initResponse: InitResponseBody, rootNodeRef: WeakRef<Node> | null, loggingMode: LoggingMode, shouldListenForUpdates: boolean, enableConsoleDebugLogging: boolean); | ||
reinitialize(): Promise<void>; | ||
@@ -22,0 +24,0 @@ reduce(query: Query<ObjectValue> | null, expression: Expression): Expression; |
@@ -80,3 +80,3 @@ "use strict"; | ||
_a.trys.push([1, 6, , 7]); | ||
return [4 /*yield*/, (0, edge_1.hashRequest)(context.businessToken, context.projectId, context.schemaVersion)]; | ||
return [4 /*yield*/, (0, edge_1.hashRequest)(context.businessToken, context.projectId, context.queryCode, context.variableValues, context.schemaVersion)]; | ||
case 2: | ||
@@ -173,3 +173,3 @@ response = _a.sent(); | ||
_a.trys.push([1, 3, , 4]); | ||
return [4 /*yield*/, (0, edge_1.initRequest)(this.businessToken, this.projectId, this.schemaVersion, this.queryCode, this.variableValues)]; | ||
return [4 /*yield*/, (0, edge_1.initRequest)(this.businessToken, this.projectId, this.queryCode, this.variableValues, this.schemaVersion)]; | ||
case 2: | ||
@@ -190,4 +190,4 @@ initResponse = _a.sent(); | ||
Context.prototype.reduce = function (query, expression) { | ||
var _a = this.initResponse, splits = _a.splits, eventTypes = _a.eventTypes, config = _a.config; | ||
return (0, reduce_1.default)(splits, eventTypes, config, query, expression); | ||
var _a = this.initResponse, splits = _a.splits, eventTypes = _a.eventTypes, commitConfig = _a.commitConfig; | ||
return (0, reduce_1.default)(splits, eventTypes, commitConfig, query, expression); | ||
}; | ||
@@ -194,0 +194,0 @@ Context.prototype.logEvaluation = function (nodeClassName, nodePath, nodeExpression, query, reducedExpression, value, reductionLogs) { |
@@ -1,7 +0,9 @@ | ||
import { EdgeCodegenResponseBody, EdgeHashResponseBody, EdgeInitResponseBody, Value } from "./shared/types"; | ||
export declare function codegenRequest(businessToken: string, projectId: number, schemaVersion: string | null, queryCode: string): Promise<EdgeCodegenResponseBody>; | ||
export declare function initRequest(businessToken: string, projectId: number, schemaVersion: string | null, queryCode: string, variableValues: { | ||
import { CodegenResponseBody, HashResponseBody, InitResponseBody, Value } from "./shared/types"; | ||
export declare function codegenRequest(businessToken: string, projectId: number, query: string, schemaVersion: string | null): Promise<CodegenResponseBody>; | ||
export declare function initRequest(businessToken: string, projectId: number, query: string, variables: { | ||
[variableName: string]: Value; | ||
}): Promise<EdgeInitResponseBody>; | ||
export declare function hashRequest(businessToken: string, projectId: number, schemaVersion: string | null): Promise<EdgeHashResponseBody>; | ||
}, schemaVersion: string | null): Promise<InitResponseBody>; | ||
export declare function hashRequest(businessToken: string, projectId: number, query: string, variables: { | ||
[variableName: string]: Value; | ||
}, schemaVersion: string | null): Promise<HashResponseBody>; | ||
//# sourceMappingURL=edge.d.ts.map |
@@ -47,21 +47,21 @@ "use strict"; | ||
var constants_1 = require("./shared/constants"); | ||
var packageName = package_json_1.default.name; | ||
var packageVersion = package_json_1.default.version; | ||
function codegenRequest(businessToken, projectId, schemaVersion, queryCode) { | ||
var sdkVersion = package_json_1.default.version; | ||
function codegenRequest(businessToken, projectId, query, schemaVersion) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var responseString, response; | ||
var body, responseString, response; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, edgeRequest(businessToken, projectId, { | ||
packageName: packageName, | ||
packageVersion: packageVersion, | ||
schemaVersion: schemaVersion, | ||
method: "codegen", | ||
query: queryCode, | ||
case 0: | ||
body = { | ||
query: query, | ||
variables: {}, | ||
})]; | ||
schemaVersion: schemaVersion || undefined, | ||
sdkType: "js", | ||
sdkVersion: sdkVersion, | ||
language: "ts", | ||
}; | ||
return [4 /*yield*/, edgeRequest(businessToken, "codegen", projectId, body)]; | ||
case 1: | ||
responseString = _a.sent(); | ||
response = JSON.parse(responseString); | ||
// TODO: Validate JSON with io-ts or use trpc | ||
if (!response.code) { | ||
@@ -76,19 +76,19 @@ throw new Error("[codegenRequest] unexpected response: ".concat(responseString)); | ||
exports.codegenRequest = codegenRequest; | ||
function initRequest(businessToken, projectId, schemaVersion, queryCode, variableValues) { | ||
function initRequest(businessToken, projectId, query, variables, schemaVersion) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var responseString, response; | ||
var body, responseString, response; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, edgeRequest(businessToken, projectId, { | ||
packageName: packageName, | ||
packageVersion: packageVersion, | ||
schemaVersion: schemaVersion, | ||
method: "init", | ||
query: queryCode, | ||
variables: variableValues, | ||
})]; | ||
case 0: | ||
body = { | ||
query: query, | ||
variables: variables, | ||
schemaVersion: schemaVersion || undefined, | ||
sdkType: "js", | ||
sdkVersion: sdkVersion, | ||
}; | ||
return [4 /*yield*/, edgeRequest(businessToken, "init", projectId, body)]; | ||
case 1: | ||
responseString = _a.sent(); | ||
response = JSON.parse(responseString); | ||
// TODO: Validate JSON with io-ts or use trpc | ||
if (!response.commitId) { | ||
@@ -103,19 +103,19 @@ throw new Error("[initRequest] unexpected response: ".concat(responseString)); | ||
exports.initRequest = initRequest; | ||
function hashRequest(businessToken, projectId, schemaVersion) { | ||
function hashRequest(businessToken, projectId, query, variables, schemaVersion) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
var responseString, response; | ||
var body, responseString, response; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, edgeRequest(businessToken, projectId, { | ||
packageName: packageName, | ||
packageVersion: packageVersion, | ||
schemaVersion: schemaVersion, | ||
method: "hash", | ||
query: "dummy", | ||
case 0: | ||
body = { | ||
query: "", | ||
variables: {}, | ||
})]; | ||
schemaVersion: schemaVersion || undefined, | ||
sdkType: "js", | ||
sdkVersion: sdkVersion, | ||
}; | ||
return [4 /*yield*/, edgeRequest(businessToken, "hash", projectId, body)]; | ||
case 1: | ||
responseString = _a.sent(); | ||
response = JSON.parse(responseString); | ||
// TODO: Validate JSON with io-ts or use trpc | ||
if (!response.commitHash) { | ||
@@ -130,3 +130,3 @@ throw new Error("[hashRequest] unexpected response: ".concat(responseString)); | ||
exports.hashRequest = hashRequest; | ||
function edgeRequest(businessToken, projectId, body) { | ||
function edgeRequest(businessToken, requestType, projectId, body) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
@@ -137,3 +137,3 @@ var url, fetch, response; | ||
case 0: | ||
url = "".concat((0, isProd_1.default)() ? "https://".concat(constants_1.prodEdgeHost) : "http://".concat(constants_1.devEdgeHost), "/").concat(projectId); | ||
url = "".concat((0, isProd_1.default)() ? "https://".concat(constants_1.prodEdgeHost) : "http://".concat(constants_1.devEdgeHost), "/").concat(requestType, "/").concat(projectId); | ||
fetch = (0, getFetchFunction_1.default)(); | ||
@@ -140,0 +140,0 @@ return [4 /*yield*/, fetch(url, { |
@@ -59,3 +59,3 @@ "use strict"; | ||
schemaVersion = options.schemaVersion || null; | ||
return [4 /*yield*/, (0, edge_1.initRequest)(businessToken, projectId, schemaVersion, queryCode, variableValues)]; | ||
return [4 /*yield*/, (0, edge_1.initRequest)(businessToken, projectId, queryCode, variableValues, schemaVersion)]; | ||
case 1: | ||
@@ -62,0 +62,0 @@ initResponse = _a.sent(); |
@@ -8,2 +8,3 @@ export declare const devBackendHost = "localhost:5003"; | ||
export declare const businessTokenEnvironmentVariableNameSuffix = "HYPERTUNE_TOKEN"; | ||
export declare const graphqlTypeNameKey = "__typename"; | ||
export declare const isPartialObjectKey = "__isPartialObject__"; | ||
@@ -10,0 +11,0 @@ export declare const fieldPathSeparator = " > "; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.defaultArmKey = exports.numHashBuckets = exports.fieldPathSeparator = exports.isPartialObjectKey = exports.businessTokenEnvironmentVariableNameSuffix = exports.configFileName = exports.prodEdgeHost = exports.devEdgeHost = exports.backendGraphqlEndpoint = exports.proxyBackendHost = exports.devBackendHost = void 0; | ||
exports.defaultArmKey = exports.numHashBuckets = exports.fieldPathSeparator = exports.isPartialObjectKey = exports.graphqlTypeNameKey = exports.businessTokenEnvironmentVariableNameSuffix = exports.configFileName = exports.prodEdgeHost = exports.devEdgeHost = exports.backendGraphqlEndpoint = exports.proxyBackendHost = exports.devBackendHost = void 0; | ||
exports.devBackendHost = "localhost:5003"; | ||
@@ -11,2 +11,3 @@ exports.proxyBackendHost = "gcp.fasthorse.workers.dev"; | ||
exports.businessTokenEnvironmentVariableNameSuffix = "HYPERTUNE_TOKEN"; | ||
exports.graphqlTypeNameKey = "__typename"; | ||
exports.isPartialObjectKey = "__isPartialObject__"; | ||
@@ -13,0 +14,0 @@ exports.fieldPathSeparator = " > "; |
@@ -16,2 +16,3 @@ "use strict"; | ||
exports.areEqual = exports.complexFormExpressionEvaluationError = void 0; | ||
var constants_1 = require("./constants"); | ||
var nullThrows_1 = __importDefault(require("./nullThrows")); | ||
@@ -45,3 +46,3 @@ var reductionLogs_1 = require("./reductionLogs"); | ||
var value = Object.fromEntries(__spreadArray([ | ||
["__typename", expression.objectTypeName] | ||
[constants_1.graphqlTypeNameKey, expression.objectTypeName] | ||
], Object.entries(fieldEvaluations).map(function (_a) { | ||
@@ -48,0 +49,0 @@ var fieldName = _a[0], evaluation = _a[1]; |
@@ -49,2 +49,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var seedrandom_1 = __importDefault(require("seedrandom")); | ||
var constants_1 = require("./constants"); | ||
@@ -111,2 +112,3 @@ var emptyThrows_1 = __importDefault(require("./emptyThrows")); | ||
function reduce(splits, eventTypes, commitConfig, query, rootExpression) { | ||
var rng = (0, seedrandom_1.default)(); | ||
var assignmentCache = {}; | ||
@@ -686,3 +688,3 @@ function getAssignmentCacheKey(splitId, unitId) { | ||
})); | ||
assignment = getAssignment(commitConfig, split, unitIdValue, featureValues); | ||
assignment = getAssignment(rng, commitConfig, split, unitIdValue, featureValues); | ||
cacheAssignment(split.id, unitIdValue, assignment, featureValues); | ||
@@ -919,3 +921,3 @@ } | ||
} | ||
function getAssignment(commitConfig, split, unitId, featureValues) { | ||
function getAssignment(rng, commitConfig, split, unitId, featureValues) { | ||
if (split.type === "test") { | ||
@@ -955,5 +957,5 @@ var assignment_1 = {}; | ||
var arms = (0, emptyThrows_1.default)(Object.values(dimension.arms), "ML split \"".concat(split.id, "\" has dimension \"").concat(dimension.id, "\" with no arms.")); | ||
var armId = Math.random() < splitConfig.epsilon | ||
? arms[getRandomNumber(arms.length)].id | ||
: dimensionAssignment.armId; | ||
var armId = rng() < splitConfig.epsilon | ||
? arms[Math.floor(rng() * arms.length)].id // Explore | ||
: dimensionAssignment.armId; // Exploit | ||
assignment_2[dimension.id] = { type: "discrete", armId: armId }; | ||
@@ -965,5 +967,2 @@ }); | ||
} | ||
function getRandomNumber(upperBound) { | ||
return Math.floor(Math.random() * upperBound); | ||
} | ||
//# sourceMappingURL=reduce.js.map |
@@ -0,1 +1,2 @@ | ||
import { z } from "zod"; | ||
/** | ||
@@ -370,3 +371,5 @@ * It's difficult to remove fields from server-returned types (Expression, | ||
}; | ||
export declare const dbLogTypes: readonly ["graphql", "js", "codegen", "init", "sdk", "hash"]; | ||
export declare const requestTypes: readonly ["codegen", "init", "hash", "graphql", "js", "schema"]; | ||
export declare type RequestType = typeof requestTypes[number]; | ||
export declare const dbLogTypes: readonly ["codegen", "init", "hash", "graphql", "js", "schema", "sdk"]; | ||
export declare type DbLogType = typeof dbLogTypes[number]; | ||
@@ -383,16 +386,84 @@ export declare type DbNodeOp = { | ||
}; | ||
export declare type EdgeRequestBody = { | ||
packageName: string; | ||
packageVersion: string; | ||
schemaVersion: string | null; | ||
method: Exclude<DbLogType, "sdk">; | ||
export declare const sdkType: z.ZodEnum<["js"]>; | ||
export declare type SdkType = z.infer<typeof sdkType>; | ||
export declare const language: z.ZodEnum<["ts"]>; | ||
export declare type Language = z.infer<typeof language>; | ||
export declare const codegenRequestBody: z.ZodObject<{ | ||
query: z.ZodString; | ||
variables: z.ZodObject<{}, "passthrough", z.ZodTypeAny, {}, {}>; | ||
schemaVersion: z.ZodOptional<z.ZodString>; | ||
sdkType: z.ZodEnum<["js"]>; | ||
sdkVersion: z.ZodString; | ||
language: z.ZodEnum<["ts"]>; | ||
}, "strip", z.ZodTypeAny, { | ||
schemaVersion?: string | undefined; | ||
language: "ts"; | ||
query: string; | ||
variables: { | ||
[variableName: string]: Value; | ||
}; | ||
}; | ||
export declare type EdgeCodegenResponseBody = { | ||
variables: {}; | ||
sdkType: "js"; | ||
sdkVersion: string; | ||
}, { | ||
schemaVersion?: string | undefined; | ||
language: "ts"; | ||
query: string; | ||
variables: {}; | ||
sdkType: "js"; | ||
sdkVersion: string; | ||
}>; | ||
export declare type CodegenRequestBody = z.infer<typeof codegenRequestBody>; | ||
export declare const initRequestBody: z.ZodObject<Pick<{ | ||
query: z.ZodString; | ||
variables: z.ZodObject<{}, "passthrough", z.ZodTypeAny, {}, {}>; | ||
schemaVersion: z.ZodOptional<z.ZodString>; | ||
sdkType: z.ZodEnum<["js"]>; | ||
sdkVersion: z.ZodString; | ||
language: z.ZodEnum<["ts"]>; | ||
}, "query" | "variables" | "schemaVersion" | "sdkType" | "sdkVersion">, "strip", z.ZodTypeAny, { | ||
schemaVersion?: string | undefined; | ||
query: string; | ||
variables: {}; | ||
sdkType: "js"; | ||
sdkVersion: string; | ||
}, { | ||
schemaVersion?: string | undefined; | ||
query: string; | ||
variables: {}; | ||
sdkType: "js"; | ||
sdkVersion: string; | ||
}>; | ||
export declare type InitRequestBody = z.infer<typeof initRequestBody>; | ||
export declare const graphqlRequestBody: z.ZodObject<Pick<{ | ||
query: z.ZodString; | ||
variables: z.ZodObject<{}, "passthrough", z.ZodTypeAny, {}, {}>; | ||
schemaVersion: z.ZodOptional<z.ZodString>; | ||
sdkType: z.ZodEnum<["js"]>; | ||
sdkVersion: z.ZodString; | ||
language: z.ZodEnum<["ts"]>; | ||
}, "query" | "variables" | "schemaVersion">, "strip", z.ZodTypeAny, { | ||
schemaVersion?: string | undefined; | ||
query: string; | ||
variables: {}; | ||
}, { | ||
schemaVersion?: string | undefined; | ||
query: string; | ||
variables: {}; | ||
}>; | ||
export declare type GraphqlRequestBody = z.infer<typeof graphqlRequestBody>; | ||
export declare const schemaRequestBody: z.ZodObject<Pick<{ | ||
query: z.ZodString; | ||
variables: z.ZodObject<{}, "passthrough", z.ZodTypeAny, {}, {}>; | ||
schemaVersion: z.ZodOptional<z.ZodString>; | ||
sdkType: z.ZodEnum<["js"]>; | ||
sdkVersion: z.ZodString; | ||
language: z.ZodEnum<["ts"]>; | ||
}, "schemaVersion">, "strip", z.ZodTypeAny, { | ||
schemaVersion?: string | undefined; | ||
}, { | ||
schemaVersion?: string | undefined; | ||
}>; | ||
export declare type SchemaRequestBody = z.infer<typeof schemaRequestBody>; | ||
export declare type CodegenResponseBody = { | ||
code: string; | ||
}; | ||
export declare type EdgeInitResponseBody = { | ||
export declare type InitResponseBody = { | ||
commitId: number; | ||
@@ -402,7 +473,7 @@ reducedExpression: Expression; | ||
eventTypes: EventTypeMap; | ||
config: CommitConfig; | ||
commitConfig: CommitConfig; | ||
initLogId: number; | ||
commitHash: string; | ||
}; | ||
export declare type EdgeHashResponseBody = { | ||
export declare type HashResponseBody = { | ||
commitHash: string; | ||
@@ -409,0 +480,0 @@ }; |
"use strict"; | ||
/** | ||
* It's difficult to remove fields from server-returned types (Expression, | ||
* Split, EventType, CommitConfig, etc) as old SDK versions will depend on them. | ||
* So we should only add fields to these types if we don't expect to remove them | ||
* later. | ||
*/ | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.dbLogTypes = exports.ApplicationExpressionType = exports.VariableExpressionType = exports.FunctionExpressionType = exports.LogEventExpressionType = exports.ContinuousDimensionType = exports.DiscreteDimensionType = exports.SplitExpressionType = exports.GetUrlQueryParameterExpressionType = exports.StringConcatExpressionType = exports.StringifyNumberExpressionType = exports.RoundNumberExpressionType = exports.ArithmeticExpressionType = exports.arithmeticOperators = exports.ComparisonExpressionType = exports.comparisonOperators = exports.EnumSwitchExpressionType = exports.SwitchExpressionType = exports.ListExpressionType = exports.UpdateObjectExpressionType = exports.GetFieldExpressionType = exports.ObjectExpressionType = exports.EnumExpressionType = exports.RegexExpressionType = exports.StringExpressionType = exports.FloatExpressionType = exports.IntExpressionType = exports.BooleanExpressionType = exports.NoOpExpressionType = void 0; | ||
exports.schemaRequestBody = exports.graphqlRequestBody = exports.initRequestBody = exports.codegenRequestBody = exports.language = exports.sdkType = exports.dbLogTypes = exports.requestTypes = exports.ApplicationExpressionType = exports.VariableExpressionType = exports.FunctionExpressionType = exports.LogEventExpressionType = exports.ContinuousDimensionType = exports.DiscreteDimensionType = exports.SplitExpressionType = exports.GetUrlQueryParameterExpressionType = exports.StringConcatExpressionType = exports.StringifyNumberExpressionType = exports.RoundNumberExpressionType = exports.ArithmeticExpressionType = exports.arithmeticOperators = exports.ComparisonExpressionType = exports.comparisonOperators = exports.EnumSwitchExpressionType = exports.SwitchExpressionType = exports.ListExpressionType = exports.UpdateObjectExpressionType = exports.GetFieldExpressionType = exports.ObjectExpressionType = exports.EnumExpressionType = exports.RegexExpressionType = exports.StringExpressionType = exports.FloatExpressionType = exports.IntExpressionType = exports.BooleanExpressionType = exports.NoOpExpressionType = void 0; | ||
var zod_1 = require("zod"); | ||
exports.NoOpExpressionType = "NoOpExpression"; | ||
@@ -52,10 +56,37 @@ exports.BooleanExpressionType = "BooleanExpression"; | ||
exports.ApplicationExpressionType = "ApplicationExpression"; | ||
exports.dbLogTypes = [ | ||
"graphql", | ||
"js", | ||
exports.requestTypes = [ | ||
"codegen", | ||
"init", | ||
"sdk", | ||
"hash", | ||
"graphql", | ||
"js", | ||
"schema", | ||
]; | ||
exports.dbLogTypes = __spreadArray(__spreadArray([], exports.requestTypes, true), ["sdk"], false); | ||
// Edge Types | ||
exports.sdkType = zod_1.z.enum(["js"]); | ||
exports.language = zod_1.z.enum(["ts"]); | ||
exports.codegenRequestBody = zod_1.z.object({ | ||
query: zod_1.z.string(), | ||
variables: zod_1.z.object({}).passthrough(), | ||
schemaVersion: zod_1.z.optional(zod_1.z.string()), | ||
sdkType: exports.sdkType, | ||
sdkVersion: zod_1.z.string(), | ||
language: exports.language, | ||
}); | ||
exports.initRequestBody = exports.codegenRequestBody.pick({ | ||
query: true, | ||
variables: true, | ||
schemaVersion: true, | ||
sdkType: true, | ||
sdkVersion: true, | ||
}); | ||
exports.graphqlRequestBody = exports.codegenRequestBody.pick({ | ||
query: true, | ||
variables: true, | ||
schemaVersion: true, | ||
}); | ||
exports.schemaRequestBody = exports.codegenRequestBody.pick({ | ||
schemaVersion: true, | ||
}); | ||
//# sourceMappingURL=types.js.map |
{ | ||
"name": "hypertune", | ||
"version": "1.0.12", | ||
"version": "1.0.13", | ||
"description": "Hypertune SDK", | ||
@@ -27,2 +27,3 @@ "exports": "./build/src/index.js", | ||
"@types/node-fetch": "^2.6.1", | ||
"@types/seedrandom": "^3.0.2", | ||
"eslint": "^8.15.0", | ||
@@ -35,2 +36,3 @@ "eslint-config-airbnb": "^19.0.4", | ||
"eslint-plugin-prettier": "^4.0.0", | ||
"eslint-plugin-unused-imports": "^2.0.0", | ||
"jest": "^29.1.2", | ||
@@ -51,4 +53,6 @@ "prettier": "^2.6.2", | ||
"node-fetch": "^2.6.7", | ||
"regenerator-runtime": "^0.13.9" | ||
"regenerator-runtime": "^0.13.9", | ||
"seedrandom": "^3.0.5", | ||
"zod": "^3.19.1" | ||
} | ||
} |
@@ -34,4 +34,4 @@ #!/usr/bin/env node | ||
projectId, | ||
null, // schemaVersion | ||
queryCode | ||
queryCode, | ||
null // schemaVersion | ||
); | ||
@@ -38,0 +38,0 @@ |
@@ -61,3 +61,8 @@ import { GraphQLClient } from 'graphql-request'; | ||
export type FunnelDataInput = { | ||
export type EvaluationsJsonInput = { | ||
commitId?: InputMaybe<Scalars['ID']>; | ||
projectId?: InputMaybe<Scalars['ID']>; | ||
}; | ||
export type FunnelDataJsonInput = { | ||
end: Scalars['String']; | ||
@@ -94,2 +99,23 @@ start: Scalars['String']; | ||
export type Log = { | ||
__typename?: 'Log'; | ||
code?: Maybe<Scalars['String']>; | ||
commitId: Scalars['ID']; | ||
contextJson: Scalars['String']; | ||
createdAt: Scalars['String']; | ||
error?: Maybe<Scalars['String']>; | ||
id: Scalars['ID']; | ||
initLogId?: Maybe<Scalars['ID']>; | ||
nanoId: Scalars['ID']; | ||
nodeClassName?: Maybe<Scalars['String']>; | ||
nodeExpressionJson?: Maybe<Scalars['String']>; | ||
nodeOpJson?: Maybe<Scalars['String']>; | ||
nodePath?: Maybe<Scalars['String']>; | ||
queryJson?: Maybe<Scalars['String']>; | ||
reducedExpressionJson?: Maybe<Scalars['String']>; | ||
reductionLogsJson?: Maybe<Scalars['String']>; | ||
type: LogType; | ||
valueJson?: Maybe<Scalars['String']>; | ||
}; | ||
export type LogInput = { | ||
@@ -117,7 +143,16 @@ code?: InputMaybe<Scalars['String']>; | ||
GraphQl = 'GraphQL', | ||
Hash = 'Hash', | ||
Init = 'Init', | ||
Js = 'JS', | ||
Sdk = 'SDK' | ||
Sdk = 'SDK', | ||
Schema = 'Schema' | ||
} | ||
export type LogsInput = { | ||
afterLogId?: InputMaybe<Scalars['ID']>; | ||
beforeLogId?: InputMaybe<Scalars['ID']>; | ||
commitId?: InputMaybe<Scalars['ID']>; | ||
limit?: InputMaybe<Scalars['Int']>; | ||
}; | ||
export type Mutation = { | ||
@@ -128,2 +163,3 @@ __typename?: 'Mutation'; | ||
createProject: Scalars['ID']; | ||
updateProject: Scalars['ID']; | ||
}; | ||
@@ -146,2 +182,7 @@ | ||
export type MutationUpdateProjectArgs = { | ||
input: UpdateProjectInput; | ||
}; | ||
export enum Plan { | ||
@@ -165,2 +206,3 @@ Free = 'Free' | ||
funnelDataJson: Scalars['String']; | ||
logs: Array<Log>; | ||
me: User; | ||
@@ -177,4 +219,3 @@ project: Project; | ||
export type QueryEvaluationsJsonArgs = { | ||
commitId?: InputMaybe<Scalars['ID']>; | ||
projectId?: InputMaybe<Scalars['ID']>; | ||
input: EvaluationsJsonInput; | ||
}; | ||
@@ -184,6 +225,11 @@ | ||
export type QueryFunnelDataJsonArgs = { | ||
input: FunnelDataInput; | ||
input: FunnelDataJsonInput; | ||
}; | ||
export type QueryLogsArgs = { | ||
input: LogsInput; | ||
}; | ||
export type QueryProjectArgs = { | ||
@@ -200,2 +246,7 @@ id: Scalars['ID']; | ||
export type UpdateProjectInput = { | ||
id: Scalars['ID']; | ||
name: Scalars['String']; | ||
}; | ||
export type User = { | ||
@@ -202,0 +253,0 @@ __typename?: 'User'; |
@@ -21,3 +21,3 @@ import { GraphQLClient } from "graphql-request"; | ||
DbNodeOp, | ||
EdgeInitResponseBody, | ||
InitResponseBody, | ||
Expression, | ||
@@ -54,2 +54,4 @@ ObjectValue, | ||
context.projectId, | ||
context.queryCode, | ||
context.variableValues, | ||
context.schemaVersion | ||
@@ -105,5 +107,5 @@ ); | ||
public readonly schemaVersion: string | null; | ||
private readonly queryCode: string; | ||
private readonly variableValues: { [variableName: string]: Value }; | ||
public initResponse: EdgeInitResponseBody; | ||
public readonly queryCode: string; | ||
public readonly variableValues: { [variableName: string]: Value }; | ||
public initResponse: InitResponseBody; | ||
public rootNodeRef: WeakRef<Node> | null; | ||
@@ -121,3 +123,3 @@ private readonly loggingMode: LoggingMode; | ||
variableValues: { [variableName: string]: Value }, | ||
initResponse: EdgeInitResponseBody, | ||
initResponse: InitResponseBody, | ||
rootNodeRef: WeakRef<Node> | null, | ||
@@ -164,5 +166,5 @@ loggingMode: LoggingMode, | ||
this.projectId, | ||
this.schemaVersion, | ||
this.queryCode, | ||
this.variableValues | ||
this.variableValues, | ||
this.schemaVersion | ||
); | ||
@@ -179,4 +181,4 @@ | ||
reduce(query: Query<ObjectValue> | null, expression: Expression): Expression { | ||
const { splits, eventTypes, config } = this.initResponse; | ||
return reduce(splits, eventTypes, config, query, expression); | ||
const { splits, eventTypes, commitConfig } = this.initResponse; | ||
return reduce(splits, eventTypes, commitConfig, query, expression); | ||
} | ||
@@ -183,0 +185,0 @@ |
@@ -6,11 +6,12 @@ import getFetchFunction from "./getFetchFunction"; | ||
import { | ||
EdgeCodegenResponseBody, | ||
EdgeHashResponseBody, | ||
EdgeInitResponseBody, | ||
EdgeRequestBody, | ||
CodegenRequestBody, | ||
CodegenResponseBody, | ||
HashResponseBody, | ||
InitRequestBody, | ||
InitResponseBody, | ||
RequestType, | ||
Value, | ||
} from "./shared/types"; | ||
const packageName = packageJson.name; | ||
const packageVersion = packageJson.version; | ||
const sdkVersion = packageJson.version; | ||
@@ -20,16 +21,22 @@ export async function codegenRequest( | ||
projectId: number, | ||
schemaVersion: string | null, | ||
queryCode: string | ||
): Promise<EdgeCodegenResponseBody> { | ||
const responseString = await edgeRequest(businessToken, projectId, { | ||
packageName, | ||
packageVersion, | ||
schemaVersion, | ||
method: "codegen", | ||
query: queryCode, | ||
query: string, | ||
schemaVersion: string | null | ||
): Promise<CodegenResponseBody> { | ||
const body: CodegenRequestBody = { | ||
query, | ||
variables: {}, | ||
}); | ||
schemaVersion: schemaVersion || undefined, | ||
sdkType: "js", | ||
sdkVersion, | ||
language: "ts", | ||
}; | ||
const response = JSON.parse(responseString) as EdgeCodegenResponseBody; | ||
// TODO: Validate JSON with io-ts or use trpc | ||
const responseString = await edgeRequest( | ||
businessToken, | ||
"codegen", | ||
projectId, | ||
body | ||
); | ||
const response = JSON.parse(responseString) as CodegenResponseBody; | ||
if (!response.code) { | ||
@@ -45,17 +52,22 @@ throw new Error(`[codegenRequest] unexpected response: ${responseString}`); | ||
projectId: number, | ||
schemaVersion: string | null, | ||
queryCode: string, | ||
variableValues: { [variableName: string]: Value } | ||
): Promise<EdgeInitResponseBody> { | ||
const responseString = await edgeRequest(businessToken, projectId, { | ||
packageName, | ||
packageVersion, | ||
schemaVersion, | ||
method: "init", | ||
query: queryCode, | ||
variables: variableValues, | ||
}); | ||
query: string, | ||
variables: { [variableName: string]: Value }, | ||
schemaVersion: string | null | ||
): Promise<InitResponseBody> { | ||
const body: InitRequestBody = { | ||
query, | ||
variables, | ||
schemaVersion: schemaVersion || undefined, | ||
sdkType: "js", | ||
sdkVersion, | ||
}; | ||
const response = JSON.parse(responseString) as EdgeInitResponseBody; | ||
// TODO: Validate JSON with io-ts or use trpc | ||
const responseString = await edgeRequest( | ||
businessToken, | ||
"init", | ||
projectId, | ||
body | ||
); | ||
const response = JSON.parse(responseString) as InitResponseBody; | ||
if (!response.commitId) { | ||
@@ -71,15 +83,22 @@ throw new Error(`[initRequest] unexpected response: ${responseString}`); | ||
projectId: number, | ||
query: string, | ||
variables: { [variableName: string]: Value }, | ||
schemaVersion: string | null | ||
): Promise<EdgeHashResponseBody> { | ||
const responseString = await edgeRequest(businessToken, projectId, { | ||
packageName, | ||
packageVersion, | ||
schemaVersion, | ||
method: "hash", | ||
query: "dummy", | ||
): Promise<HashResponseBody> { | ||
const body: InitRequestBody = { | ||
query: "", | ||
variables: {}, | ||
}); | ||
schemaVersion: schemaVersion || undefined, | ||
sdkType: "js", | ||
sdkVersion, | ||
}; | ||
const response = JSON.parse(responseString) as EdgeHashResponseBody; | ||
// TODO: Validate JSON with io-ts or use trpc | ||
const responseString = await edgeRequest( | ||
businessToken, | ||
"hash", | ||
projectId, | ||
body | ||
); | ||
const response = JSON.parse(responseString) as HashResponseBody; | ||
if (!response.commitHash) { | ||
@@ -94,8 +113,9 @@ throw new Error(`[hashRequest] unexpected response: ${responseString}`); | ||
businessToken: string, | ||
requestType: RequestType, | ||
projectId: number, | ||
body: EdgeRequestBody | ||
body: CodegenRequestBody | InitRequestBody | ||
): Promise<string> { | ||
const url = `${ | ||
isProd() ? `https://${prodEdgeHost}` : `http://${devEdgeHost}` | ||
}/${projectId}`; | ||
}/${requestType}/${projectId}`; | ||
@@ -102,0 +122,0 @@ const fetch = getFetchFunction(); |
@@ -30,5 +30,5 @@ import { InitializeOptions } from ".."; | ||
projectId, | ||
schemaVersion, | ||
queryCode, | ||
variableValues | ||
variableValues, | ||
schemaVersion | ||
); | ||
@@ -35,0 +35,0 @@ |
@@ -12,2 +12,3 @@ export const devBackendHost = "localhost:5003"; | ||
export const graphqlTypeNameKey = "__typename"; | ||
export const isPartialObjectKey = "__isPartialObject__"; | ||
@@ -14,0 +15,0 @@ export const fieldPathSeparator = " > "; |
@@ -0,1 +1,2 @@ | ||
import { graphqlTypeNameKey } from "./constants"; | ||
import nullThrows from "./nullThrows"; | ||
@@ -46,3 +47,3 @@ import { getEvaluationLogs, mergeLogs } from "./reductionLogs"; | ||
const value: Value = Object.fromEntries([ | ||
["__typename", expression.objectTypeName], | ||
[graphqlTypeNameKey, expression.objectTypeName], | ||
...Object.entries(fieldEvaluations).map(([fieldName, evaluation]) => [ | ||
@@ -49,0 +50,0 @@ fieldName, |
@@ -0,1 +1,2 @@ | ||
import seedrandom from "seedrandom"; | ||
import { | ||
@@ -107,2 +108,4 @@ defaultArmKey, | ||
): Expression { | ||
const rng = seedrandom(); | ||
const assignmentCache: { | ||
@@ -1070,2 +1073,3 @@ [key: string]: { assignment: DbAssignment; featureValues: DbFeatureValues }; | ||
assignment = getAssignment( | ||
rng, | ||
commitConfig, | ||
@@ -1452,2 +1456,3 @@ split, | ||
function getAssignment( | ||
rng: seedrandom.PRNG, | ||
commitConfig: CommitConfig, | ||
@@ -1521,5 +1526,5 @@ split: Split, | ||
const armId = | ||
Math.random() < splitConfig.epsilon | ||
? arms[getRandomNumber(arms.length)].id | ||
: dimensionAssignment.armId; | ||
rng() < splitConfig.epsilon | ||
? arms[Math.floor(rng() * arms.length)].id // Explore | ||
: dimensionAssignment.armId; // Exploit | ||
@@ -1534,5 +1539,1 @@ assignment[dimension.id] = { type: "discrete", armId }; | ||
} | ||
function getRandomNumber(upperBound: number): number { | ||
return Math.floor(Math.random() * upperBound); | ||
} |
@@ -0,1 +1,3 @@ | ||
import { z } from "zod"; | ||
/** | ||
@@ -508,10 +510,13 @@ * It's difficult to remove fields from server-returned types (Expression, | ||
export const dbLogTypes = [ | ||
"graphql", | ||
"js", | ||
export const requestTypes = [ | ||
"codegen", | ||
"init", | ||
"sdk", | ||
"hash", | ||
"graphql", | ||
"js", | ||
"schema", | ||
] as const; | ||
export type RequestType = typeof requestTypes[number]; | ||
export const dbLogTypes = [...requestTypes, "sdk"] as const; | ||
export type DbLogType = typeof dbLogTypes[number]; | ||
@@ -526,14 +531,42 @@ | ||
export type EdgeRequestBody = { | ||
packageName: string; | ||
packageVersion: string; | ||
schemaVersion: string | null; | ||
method: Exclude<DbLogType, "sdk">; | ||
query: string; | ||
variables: { [variableName: string]: Value }; | ||
}; | ||
export const sdkType = z.enum(["js"]); | ||
export type SdkType = z.infer<typeof sdkType>; | ||
export type EdgeCodegenResponseBody = { code: string }; | ||
export const language = z.enum(["ts"]); | ||
export type Language = z.infer<typeof language>; | ||
export type EdgeInitResponseBody = { | ||
export const codegenRequestBody = z.object({ | ||
query: z.string(), | ||
variables: z.object({}).passthrough(), | ||
schemaVersion: z.optional(z.string()), | ||
sdkType, | ||
sdkVersion: z.string(), | ||
language, | ||
}); | ||
export type CodegenRequestBody = z.infer<typeof codegenRequestBody>; | ||
export const initRequestBody = codegenRequestBody.pick({ | ||
query: true, | ||
variables: true, | ||
schemaVersion: true, | ||
sdkType: true, | ||
sdkVersion: true, | ||
}); | ||
export type InitRequestBody = z.infer<typeof initRequestBody>; | ||
export const graphqlRequestBody = codegenRequestBody.pick({ | ||
query: true, | ||
variables: true, | ||
schemaVersion: true, | ||
}); | ||
export type GraphqlRequestBody = z.infer<typeof graphqlRequestBody>; | ||
export const schemaRequestBody = codegenRequestBody.pick({ | ||
schemaVersion: true, | ||
}); | ||
export type SchemaRequestBody = z.infer<typeof schemaRequestBody>; | ||
export type CodegenResponseBody = { code: string }; | ||
export type InitResponseBody = { | ||
commitId: number; | ||
@@ -543,3 +576,3 @@ reducedExpression: Expression; | ||
eventTypes: EventTypeMap; | ||
config: CommitConfig; | ||
commitConfig: CommitConfig; | ||
initLogId: number; | ||
@@ -549,3 +582,3 @@ commitHash: string; // Can't just be commit ID as commit config may change too | ||
export type EdgeHashResponseBody = { | ||
export type HashResponseBody = { | ||
commitHash: string; | ||
@@ -552,0 +585,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
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 too big to display
719297
13237
11
21
+ Addedseedrandom@^3.0.5
+ Addedzod@^3.19.1
+ Addedseedrandom@3.0.5(transitive)
+ Addedzod@3.24.1(transitive)