@barekey/sdk 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/internal/node-runtime.d.ts +2 -1
- package/dist/internal/node-runtime.d.ts.map +1 -1
- package/dist/internal/node-runtime.js +7 -4
- package/dist/internal/public-runtime.d.ts +14 -0
- package/dist/internal/public-runtime.d.ts.map +1 -0
- package/dist/internal/public-runtime.js +78 -0
- package/dist/internal/typegen.d.ts +5 -0
- package/dist/internal/typegen.d.ts.map +1 -1
- package/dist/internal/typegen.js +41 -10
- package/dist/public-client.d.ts +36 -0
- package/dist/public-client.d.ts.map +1 -0
- package/dist/public-client.js +150 -0
- package/dist/public-types.d.ts +26 -0
- package/dist/public-types.d.ts.map +1 -0
- package/dist/public-types.js +1 -0
- package/dist/public.d.ts +6 -0
- package/dist/public.d.ts.map +1 -0
- package/dist/public.js +3 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +3 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.d.ts.map +1 -1
- package/generated.public.d.ts +8 -0
- package/{generated.d.ts → generated.server.d.ts} +8 -2
- package/index.d.ts +0 -1
- package/package.json +18 -3
- package/public.d.ts +2 -0
- package/server.d.ts +2 -0
- package/src/index.ts +7 -0
- package/src/internal/node-runtime.ts +9 -5
- package/src/internal/public-runtime.ts +123 -0
- package/src/internal/typegen.ts +63 -10
- package/src/public-client.ts +229 -0
- package/src/public-types.ts +57 -0
- package/src/public.ts +69 -0
- package/src/server.ts +60 -0
- package/src/types.ts +2 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
/* This file is generated by barekey typegen. */
|
|
3
|
-
/* barekey-manifest-version: REnQvc_83Zn-Xs-tvl2fA375JUy3Jp1IOIoYFB8y-74 */
|
|
4
3
|
|
|
5
4
|
import type { AB, Env, Linear, Secret } from "./dist/types.js";
|
|
6
5
|
|
|
@@ -9,7 +8,14 @@ declare module "./dist/types.js" {
|
|
|
9
8
|
"CODEX_TEST_SECRET": Env<Secret, string>;
|
|
10
9
|
"DATABASE_URL": Env<Secret, string>;
|
|
11
10
|
"foo": Env<Secret, string>;
|
|
12
|
-
"JSON_DEEP": Env<
|
|
11
|
+
"JSON_DEEP": Env<
|
|
12
|
+
Secret,
|
|
13
|
+
{
|
|
14
|
+
bar: boolean;
|
|
15
|
+
foo: string;
|
|
16
|
+
nested: { count: number; flags: Array<boolean>; meta: { label: string } };
|
|
17
|
+
}
|
|
18
|
+
>;
|
|
13
19
|
}
|
|
14
20
|
}
|
|
15
21
|
|
package/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barekey/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Barekey TypeScript SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -11,18 +11,33 @@
|
|
|
11
11
|
"import": "./dist/index.js",
|
|
12
12
|
"default": "./dist/index.js"
|
|
13
13
|
},
|
|
14
|
+
"./public": {
|
|
15
|
+
"types": "./public.d.ts",
|
|
16
|
+
"import": "./dist/public.js",
|
|
17
|
+
"default": "./dist/public.js"
|
|
18
|
+
},
|
|
19
|
+
"./server": {
|
|
20
|
+
"types": "./server.d.ts",
|
|
21
|
+
"import": "./dist/server.js",
|
|
22
|
+
"default": "./dist/server.js"
|
|
23
|
+
},
|
|
14
24
|
"./package.json": "./package.json"
|
|
15
25
|
},
|
|
16
26
|
"files": [
|
|
17
27
|
"dist",
|
|
18
|
-
"generated.d.ts",
|
|
28
|
+
"generated.public.d.ts",
|
|
29
|
+
"generated.server.d.ts",
|
|
19
30
|
"index.d.ts",
|
|
31
|
+
"public.d.ts",
|
|
32
|
+
"server.d.ts",
|
|
20
33
|
"src"
|
|
21
34
|
],
|
|
22
35
|
"scripts": {
|
|
23
36
|
"build": "tsc -p tsconfig.json",
|
|
24
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
37
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
38
|
+
"test": "bun test test"
|
|
25
39
|
},
|
|
40
|
+
"packageManager": "bun@1.2.22",
|
|
26
41
|
"devDependencies": {
|
|
27
42
|
"@types/node": "^24.10.1",
|
|
28
43
|
"typescript": "^5.9.3"
|
package/public.d.ts
ADDED
package/server.d.ts
ADDED
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { BarekeyClient } from "./client.js";
|
|
2
|
+
export { PublicBarekeyClient } from "./public-client.js";
|
|
2
3
|
export { BarekeyEnvHandle } from "./handle.js";
|
|
3
4
|
export {
|
|
4
5
|
BarekeyError,
|
|
@@ -58,3 +59,9 @@ export type {
|
|
|
58
59
|
Linear,
|
|
59
60
|
Secret,
|
|
60
61
|
} from "./types.js";
|
|
62
|
+
|
|
63
|
+
export type {
|
|
64
|
+
BarekeyPublicGeneratedTypeMap,
|
|
65
|
+
BarekeyPublicKnownKey,
|
|
66
|
+
PublicBarekeyClientOptions,
|
|
67
|
+
} from "./public-types.js";
|
|
@@ -476,7 +476,8 @@ function isMissingModuleError(error: unknown): boolean {
|
|
|
476
476
|
|
|
477
477
|
type InstalledSdkTypegenTarget = {
|
|
478
478
|
packageRoot: string;
|
|
479
|
-
|
|
479
|
+
serverGeneratedTypesPath: string;
|
|
480
|
+
publicGeneratedTypesPath: string;
|
|
480
481
|
typegenMetadataPath: string;
|
|
481
482
|
};
|
|
482
483
|
|
|
@@ -508,19 +509,22 @@ export async function resolveInstalledSdkTypegenTarget(): Promise<InstalledSdkTy
|
|
|
508
509
|
const candidatePackageJson = runtime.path.join(current, "package.json");
|
|
509
510
|
const rawPackageJson = await readJsonFile<Record<string, unknown>>(runtime, candidatePackageJson);
|
|
510
511
|
if (rawPackageJson !== null && rawPackageJson.name === "@barekey/sdk") {
|
|
511
|
-
const
|
|
512
|
+
const serverGeneratedTypesPath = runtime.path.join(current, "generated.server.d.ts");
|
|
513
|
+
const publicGeneratedTypesPath = runtime.path.join(current, "generated.public.d.ts");
|
|
512
514
|
try {
|
|
513
|
-
await runtime.fs.access(
|
|
515
|
+
await runtime.fs.access(serverGeneratedTypesPath);
|
|
516
|
+
await runtime.fs.access(publicGeneratedTypesPath);
|
|
514
517
|
} catch (error: unknown) {
|
|
515
518
|
throw new TypegenUnsupportedSdkError({
|
|
516
|
-
message: `The installed @barekey/sdk module at ${current} does not include generated.d.ts.`,
|
|
519
|
+
message: `The installed @barekey/sdk module at ${current} does not include generated.server.d.ts and generated.public.d.ts.`,
|
|
517
520
|
cause: error,
|
|
518
521
|
});
|
|
519
522
|
}
|
|
520
523
|
|
|
521
524
|
return {
|
|
522
525
|
packageRoot: current,
|
|
523
|
-
|
|
526
|
+
serverGeneratedTypesPath,
|
|
527
|
+
publicGeneratedTypesPath,
|
|
524
528
|
typegenMetadataPath: runtime.path.join(current, "typegen.json"),
|
|
525
529
|
};
|
|
526
530
|
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FsNotAvailableError,
|
|
3
|
+
InvalidConfigurationProvidedError,
|
|
4
|
+
NoConfigurationProvidedError,
|
|
5
|
+
} from "../errors.js";
|
|
6
|
+
import type { PublicBarekeyClientOptions } from "../public-types.js";
|
|
7
|
+
import type { BarekeyJsonConfig, BarekeyStandardSchemaV1 } from "../types.js";
|
|
8
|
+
import { normalizeBaseUrl } from "./http.js";
|
|
9
|
+
import { isFilesystemAvailable, loadBarekeyJsonConfig } from "./node-runtime.js";
|
|
10
|
+
|
|
11
|
+
const DEFAULT_BAREKEY_API_URL = "https://api.barekey.dev";
|
|
12
|
+
|
|
13
|
+
type BarekeyResolvedScope = {
|
|
14
|
+
organization: string;
|
|
15
|
+
project: string;
|
|
16
|
+
environment: string;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type BarekeyPublicRuntimeContext = BarekeyResolvedScope & {
|
|
20
|
+
baseUrl: string;
|
|
21
|
+
requirements?: BarekeyStandardSchemaV1;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
function readConfigString(value: unknown): string | undefined {
|
|
25
|
+
return typeof value === "string" ? value.trim() : undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function normalizeScope(input: {
|
|
29
|
+
organization?: unknown;
|
|
30
|
+
project?: unknown;
|
|
31
|
+
environment?: unknown;
|
|
32
|
+
source: string;
|
|
33
|
+
}): BarekeyResolvedScope {
|
|
34
|
+
const organization = readConfigString(input.organization) ?? "";
|
|
35
|
+
const project = readConfigString(input.project) ?? "";
|
|
36
|
+
const environment = readConfigString(input.environment) ?? "";
|
|
37
|
+
if (organization.length === 0 || project.length === 0 || environment.length === 0) {
|
|
38
|
+
throw new InvalidConfigurationProvidedError({
|
|
39
|
+
message: `${input.source} must provide organization, project, and environment.`,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
organization,
|
|
45
|
+
project,
|
|
46
|
+
environment,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function normalizeJsonConfig(
|
|
51
|
+
input: BarekeyJsonConfig | Record<string, unknown>,
|
|
52
|
+
source: string,
|
|
53
|
+
): BarekeyResolvedScope {
|
|
54
|
+
return normalizeScope({
|
|
55
|
+
organization: input.organization ?? input.org,
|
|
56
|
+
project: input.project,
|
|
57
|
+
environment: input.environment ?? input.stage,
|
|
58
|
+
source,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function resolveScope(options: PublicBarekeyClientOptions): Promise<BarekeyResolvedScope> {
|
|
63
|
+
const explicitOrganization = "organization" in options ? options.organization : undefined;
|
|
64
|
+
const explicitProject = "project" in options ? options.project : undefined;
|
|
65
|
+
const explicitEnvironment = "environment" in options ? options.environment : undefined;
|
|
66
|
+
const explicitJson = "json" in options ? options.json : undefined;
|
|
67
|
+
|
|
68
|
+
const explicitCount =
|
|
69
|
+
Number(explicitOrganization !== undefined) +
|
|
70
|
+
Number(explicitProject !== undefined) +
|
|
71
|
+
Number(explicitEnvironment !== undefined);
|
|
72
|
+
|
|
73
|
+
if (explicitJson !== undefined && explicitCount > 0) {
|
|
74
|
+
throw new InvalidConfigurationProvidedError({
|
|
75
|
+
message: "Pass either json or organization/project/environment, not both.",
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (explicitCount > 0 && explicitCount < 3) {
|
|
80
|
+
throw new InvalidConfigurationProvidedError({
|
|
81
|
+
message: "organization, project, and environment must be provided together.",
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (explicitJson !== undefined) {
|
|
86
|
+
return normalizeJsonConfig(explicitJson, "The provided json configuration");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (explicitCount === 3) {
|
|
90
|
+
return normalizeScope({
|
|
91
|
+
organization: explicitOrganization,
|
|
92
|
+
project: explicitProject,
|
|
93
|
+
environment: explicitEnvironment,
|
|
94
|
+
source: "The provided Barekey configuration",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const loadedConfig = await loadBarekeyJsonConfig();
|
|
99
|
+
if (loadedConfig === null) {
|
|
100
|
+
if (!(await isFilesystemAvailable())) {
|
|
101
|
+
throw new FsNotAvailableError();
|
|
102
|
+
}
|
|
103
|
+
throw new NoConfigurationProvidedError({
|
|
104
|
+
message: "No Barekey configuration was found and no barekey.json file could be loaded.",
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return normalizeJsonConfig(
|
|
109
|
+
loadedConfig.json,
|
|
110
|
+
`The barekey.json file at ${loadedConfig.path}`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function resolvePublicRuntimeContext(
|
|
115
|
+
options: PublicBarekeyClientOptions,
|
|
116
|
+
): Promise<BarekeyPublicRuntimeContext> {
|
|
117
|
+
const scope = await resolveScope(options);
|
|
118
|
+
return {
|
|
119
|
+
...scope,
|
|
120
|
+
baseUrl: normalizeBaseUrl(options.baseUrl?.trim() || DEFAULT_BAREKEY_API_URL),
|
|
121
|
+
requirements: options.requirements,
|
|
122
|
+
};
|
|
123
|
+
}
|
package/src/internal/typegen.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
|
|
12
12
|
export type TypegenManifestVariable = {
|
|
13
13
|
name: string;
|
|
14
|
+
visibility: "private" | "public";
|
|
14
15
|
kind: "secret" | "ab_roll" | "rollout";
|
|
15
16
|
declaredType: "string" | "boolean" | "int64" | "float" | "date" | "json";
|
|
16
17
|
required: boolean;
|
|
@@ -87,9 +88,18 @@ function renderVariableType(row: TypegenManifestVariable): string {
|
|
|
87
88
|
return `Env<AB, ${row.typeScriptType}, ${renderRolloutMetadataType(row)}>`;
|
|
88
89
|
}
|
|
89
90
|
|
|
90
|
-
function buildGeneratedTypesContents(
|
|
91
|
+
function buildGeneratedTypesContents(
|
|
92
|
+
manifest: TypegenManifest,
|
|
93
|
+
input: {
|
|
94
|
+
typeModulePath: "./dist/types.js" | "./dist/public-types.js";
|
|
95
|
+
declaredModulePath: "./dist/types.js" | "./dist/public-types.js";
|
|
96
|
+
interfaceName: "BarekeyGeneratedTypeMap" | "BarekeyPublicGeneratedTypeMap";
|
|
97
|
+
include: (row: TypegenManifestVariable) => boolean;
|
|
98
|
+
},
|
|
99
|
+
): string {
|
|
91
100
|
const mapLines = manifest.variables
|
|
92
101
|
.slice()
|
|
102
|
+
.filter(input.include)
|
|
93
103
|
.sort((left, right) => left.name.localeCompare(right.name))
|
|
94
104
|
.map((row) => ` ${JSON.stringify(row.name)}: ${renderVariableType(row)};`)
|
|
95
105
|
.join("\n");
|
|
@@ -98,10 +108,10 @@ function buildGeneratedTypesContents(manifest: TypegenManifest): string {
|
|
|
98
108
|
/* This file is generated by barekey typegen. */
|
|
99
109
|
/* barekey-manifest-version: ${manifest.manifestVersion} */
|
|
100
110
|
|
|
101
|
-
import type { AB, EaseInOut, Env, Linear, Secret, Step } from "
|
|
111
|
+
import type { AB, EaseInOut, Env, Linear, Secret, Step } from "${input.typeModulePath}";
|
|
102
112
|
|
|
103
|
-
declare module "
|
|
104
|
-
interface
|
|
113
|
+
declare module "${input.declaredModulePath}" {
|
|
114
|
+
interface ${input.interfaceName} {
|
|
105
115
|
${mapLines.length > 0 ? mapLines : ""}
|
|
106
116
|
}
|
|
107
117
|
}
|
|
@@ -191,7 +201,27 @@ function buildTypegenMetadataContents(
|
|
|
191
201
|
|
|
192
202
|
export async function resolveInstalledSdkGeneratedTypesPath(): Promise<string | null> {
|
|
193
203
|
const target = await resolveInstalledSdkTypegenTarget();
|
|
194
|
-
return target?.
|
|
204
|
+
return target?.serverGeneratedTypesPath ?? null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function renderGeneratedTypesForManifest(manifest: TypegenManifest): {
|
|
208
|
+
serverContents: string;
|
|
209
|
+
publicContents: string;
|
|
210
|
+
} {
|
|
211
|
+
return {
|
|
212
|
+
serverContents: buildGeneratedTypesContents(manifest, {
|
|
213
|
+
typeModulePath: "./dist/types.js",
|
|
214
|
+
declaredModulePath: "./dist/types.js",
|
|
215
|
+
interfaceName: "BarekeyGeneratedTypeMap",
|
|
216
|
+
include: () => true,
|
|
217
|
+
}),
|
|
218
|
+
publicContents: buildGeneratedTypesContents(manifest, {
|
|
219
|
+
typeModulePath: "./dist/public-types.js",
|
|
220
|
+
declaredModulePath: "./dist/public-types.js",
|
|
221
|
+
interfaceName: "BarekeyPublicGeneratedTypeMap",
|
|
222
|
+
include: (row) => row.visibility === "public",
|
|
223
|
+
}),
|
|
224
|
+
};
|
|
195
225
|
}
|
|
196
226
|
|
|
197
227
|
export async function hasFreshInstalledSdkTypegen(
|
|
@@ -229,31 +259,54 @@ export async function writeInstalledSdkGeneratedTypes(
|
|
|
229
259
|
return {
|
|
230
260
|
written: false,
|
|
231
261
|
path: "",
|
|
262
|
+
serverPath: "",
|
|
263
|
+
publicPath: "",
|
|
232
264
|
manifestVersion: manifest.manifestVersion,
|
|
233
265
|
};
|
|
234
266
|
}
|
|
235
267
|
|
|
236
|
-
const
|
|
237
|
-
|
|
268
|
+
const [existingServerContents, existingPublicContents] = await Promise.all([
|
|
269
|
+
readTextFile(target.serverGeneratedTypesPath),
|
|
270
|
+
readTextFile(target.publicGeneratedTypesPath),
|
|
271
|
+
]);
|
|
272
|
+
if (
|
|
273
|
+
readManifestVersion(existingServerContents) === manifest.manifestVersion &&
|
|
274
|
+
readManifestVersion(existingPublicContents) === manifest.manifestVersion
|
|
275
|
+
) {
|
|
238
276
|
await writeTextFileAtomic(
|
|
239
277
|
target.typegenMetadataPath,
|
|
240
278
|
buildTypegenMetadataContents(new Date(), identity),
|
|
241
279
|
);
|
|
242
280
|
return {
|
|
243
281
|
written: false,
|
|
244
|
-
path: target.
|
|
282
|
+
path: target.serverGeneratedTypesPath,
|
|
283
|
+
serverPath: target.serverGeneratedTypesPath,
|
|
284
|
+
publicPath: target.publicGeneratedTypesPath,
|
|
245
285
|
manifestVersion: manifest.manifestVersion,
|
|
246
286
|
};
|
|
247
287
|
}
|
|
248
288
|
|
|
249
|
-
|
|
289
|
+
const rendered = renderGeneratedTypesForManifest(manifest);
|
|
290
|
+
|
|
291
|
+
await Promise.all([
|
|
292
|
+
writeTextFileAtomic(
|
|
293
|
+
target.serverGeneratedTypesPath,
|
|
294
|
+
rendered.serverContents,
|
|
295
|
+
),
|
|
296
|
+
writeTextFileAtomic(
|
|
297
|
+
target.publicGeneratedTypesPath,
|
|
298
|
+
rendered.publicContents,
|
|
299
|
+
),
|
|
300
|
+
]);
|
|
250
301
|
await writeTextFileAtomic(
|
|
251
302
|
target.typegenMetadataPath,
|
|
252
303
|
buildTypegenMetadataContents(new Date(), identity),
|
|
253
304
|
);
|
|
254
305
|
return {
|
|
255
306
|
written: true,
|
|
256
|
-
path: target.
|
|
307
|
+
path: target.serverGeneratedTypesPath,
|
|
308
|
+
serverPath: target.serverGeneratedTypesPath,
|
|
309
|
+
publicPath: target.publicGeneratedTypesPath,
|
|
257
310
|
manifestVersion: manifest.manifestVersion,
|
|
258
311
|
};
|
|
259
312
|
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { VariableNotFoundError } from "./errors.js";
|
|
2
|
+
import { BarekeyEnvHandle } from "./handle.js";
|
|
3
|
+
import {
|
|
4
|
+
evaluateDefinition,
|
|
5
|
+
parseDeclaredValue,
|
|
6
|
+
validateDynamicOptions,
|
|
7
|
+
} from "./internal/evaluate.js";
|
|
8
|
+
import { postJson } from "./internal/http.js";
|
|
9
|
+
import { MemoryCache } from "./internal/cache.js";
|
|
10
|
+
import { validateRequirements } from "./internal/requirements.js";
|
|
11
|
+
import {
|
|
12
|
+
resolvePublicRuntimeContext,
|
|
13
|
+
type BarekeyPublicRuntimeContext,
|
|
14
|
+
} from "./internal/public-runtime.js";
|
|
15
|
+
import { resolveTtlMilliseconds } from "./internal/ttl.js";
|
|
16
|
+
import type {
|
|
17
|
+
BarekeyPublicGeneratedTypeMap,
|
|
18
|
+
BarekeyPublicKnownKey,
|
|
19
|
+
PublicBarekeyClientOptions,
|
|
20
|
+
} from "./public-types.js";
|
|
21
|
+
import type {
|
|
22
|
+
BarekeyEvaluatedValue,
|
|
23
|
+
BarekeyGetOptions,
|
|
24
|
+
BarekeyJsonConfig,
|
|
25
|
+
BarekeyVariableDefinition,
|
|
26
|
+
} from "./types.js";
|
|
27
|
+
|
|
28
|
+
type DefinitionsResponse = {
|
|
29
|
+
definitions: Array<BarekeyVariableDefinition>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
function createDefaultFetch(): typeof globalThis.fetch {
|
|
33
|
+
if (typeof globalThis.fetch === "function") {
|
|
34
|
+
return globalThis.fetch.bind(globalThis);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (async () => {
|
|
38
|
+
throw new Error("fetch is not available in this runtime.");
|
|
39
|
+
}) as typeof globalThis.fetch;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class PublicBarekeyClient {
|
|
43
|
+
private readonly options: PublicBarekeyClientOptions;
|
|
44
|
+
private readonly fetchFn: typeof globalThis.fetch;
|
|
45
|
+
private readonly definitionCache = new MemoryCache<BarekeyVariableDefinition>();
|
|
46
|
+
private readonly evaluationCache = new MemoryCache<BarekeyEvaluatedValue>();
|
|
47
|
+
private runtimeContextPromise: Promise<BarekeyPublicRuntimeContext> | null = null;
|
|
48
|
+
private requirementsPromise: Promise<void> | null = null;
|
|
49
|
+
|
|
50
|
+
constructor();
|
|
51
|
+
constructor(options: {
|
|
52
|
+
organization: string;
|
|
53
|
+
project: string;
|
|
54
|
+
environment: string;
|
|
55
|
+
requirements?: PublicBarekeyClientOptions["requirements"];
|
|
56
|
+
baseUrl?: string;
|
|
57
|
+
});
|
|
58
|
+
constructor(options: {
|
|
59
|
+
json: BarekeyJsonConfig;
|
|
60
|
+
requirements?: PublicBarekeyClientOptions["requirements"];
|
|
61
|
+
baseUrl?: string;
|
|
62
|
+
});
|
|
63
|
+
constructor(options: PublicBarekeyClientOptions = {}) {
|
|
64
|
+
this.options = options;
|
|
65
|
+
this.fetchFn = createDefaultFetch();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get<TKey extends BarekeyPublicKnownKey>(
|
|
69
|
+
name: TKey,
|
|
70
|
+
options?: BarekeyGetOptions,
|
|
71
|
+
): BarekeyEnvHandle<BarekeyPublicGeneratedTypeMap[TKey]>;
|
|
72
|
+
get(name: string, options?: BarekeyGetOptions): BarekeyEnvHandle<unknown>;
|
|
73
|
+
get(name: string, options?: BarekeyGetOptions): BarekeyEnvHandle<unknown> {
|
|
74
|
+
return new BarekeyEnvHandle(
|
|
75
|
+
async () => await this.resolveEvaluatedValue(name, options),
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private async getRuntimeContext(): Promise<BarekeyPublicRuntimeContext> {
|
|
80
|
+
if (this.runtimeContextPromise === null) {
|
|
81
|
+
const runtimeContextPromise = resolvePublicRuntimeContext(this.options);
|
|
82
|
+
runtimeContextPromise.catch(() => {
|
|
83
|
+
if (this.runtimeContextPromise === runtimeContextPromise) {
|
|
84
|
+
this.runtimeContextPromise = null;
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
this.runtimeContextPromise = runtimeContextPromise;
|
|
88
|
+
}
|
|
89
|
+
return await this.runtimeContextPromise;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private buildDefinitionCacheKey(context: BarekeyPublicRuntimeContext, name: string): string {
|
|
93
|
+
return [context.organization, context.project, context.environment, name].join("|");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private buildEvaluationCacheKey(
|
|
97
|
+
context: BarekeyPublicRuntimeContext,
|
|
98
|
+
name: string,
|
|
99
|
+
options?: BarekeyGetOptions,
|
|
100
|
+
): string {
|
|
101
|
+
return [
|
|
102
|
+
context.organization,
|
|
103
|
+
context.project,
|
|
104
|
+
context.environment,
|
|
105
|
+
name,
|
|
106
|
+
options?.seed ?? "",
|
|
107
|
+
options?.key ?? "",
|
|
108
|
+
].join("|");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private async fetchDefinitions(names?: Array<string>): Promise<Array<BarekeyVariableDefinition>> {
|
|
112
|
+
const context = await this.getRuntimeContext();
|
|
113
|
+
const response = await postJson<DefinitionsResponse>({
|
|
114
|
+
fetchFn: this.fetchFn,
|
|
115
|
+
baseUrl: context.baseUrl,
|
|
116
|
+
path: "/v1/public/env/definitions",
|
|
117
|
+
payload: {
|
|
118
|
+
orgSlug: context.organization,
|
|
119
|
+
projectSlug: context.project,
|
|
120
|
+
stageSlug: context.environment,
|
|
121
|
+
...(names === undefined ? {} : { names }),
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
for (const definition of response.definitions) {
|
|
126
|
+
this.definitionCache.set(this.buildDefinitionCacheKey(context, definition.name), definition);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return response.definitions;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private async ensureRequirementsValidated(): Promise<void> {
|
|
133
|
+
const context = await this.getRuntimeContext();
|
|
134
|
+
const requirements = context.requirements;
|
|
135
|
+
if (requirements === undefined) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (this.requirementsPromise === null) {
|
|
140
|
+
const requirementsPromise = (async () => {
|
|
141
|
+
const definitions = await this.fetchDefinitions();
|
|
142
|
+
const values: Record<string, unknown> = {};
|
|
143
|
+
for (const definition of definitions) {
|
|
144
|
+
const evaluated = await evaluateDefinition(definition);
|
|
145
|
+
values[definition.name] = parseDeclaredValue(evaluated.value, evaluated.declaredType);
|
|
146
|
+
}
|
|
147
|
+
await validateRequirements(requirements, values);
|
|
148
|
+
})();
|
|
149
|
+
requirementsPromise.catch(() => {
|
|
150
|
+
if (this.requirementsPromise === requirementsPromise) {
|
|
151
|
+
this.requirementsPromise = null;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
this.requirementsPromise = requirementsPromise;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
await this.requirementsPromise;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private async getStaticDefinition(name: string): Promise<BarekeyVariableDefinition> {
|
|
161
|
+
await this.ensureRequirementsValidated();
|
|
162
|
+
const context = await this.getRuntimeContext();
|
|
163
|
+
const cacheKey = this.buildDefinitionCacheKey(context, name);
|
|
164
|
+
const cached = this.definitionCache.get(cacheKey);
|
|
165
|
+
if (cached !== null) {
|
|
166
|
+
return cached;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const definitions = await this.fetchDefinitions([name]);
|
|
170
|
+
const resolved = definitions[0];
|
|
171
|
+
if (resolved === undefined) {
|
|
172
|
+
throw new VariableNotFoundError();
|
|
173
|
+
}
|
|
174
|
+
return resolved;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private async resolveStaticValue(
|
|
178
|
+
name: string,
|
|
179
|
+
options?: BarekeyGetOptions,
|
|
180
|
+
): Promise<BarekeyEvaluatedValue> {
|
|
181
|
+
const definition = await this.getStaticDefinition(name);
|
|
182
|
+
return await evaluateDefinition(definition, options);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private async resolveDynamicValue(
|
|
186
|
+
name: string,
|
|
187
|
+
options?: BarekeyGetOptions,
|
|
188
|
+
): Promise<BarekeyEvaluatedValue> {
|
|
189
|
+
await this.ensureRequirementsValidated();
|
|
190
|
+
const context = await this.getRuntimeContext();
|
|
191
|
+
const cacheKey = this.buildEvaluationCacheKey(context, name, options);
|
|
192
|
+
const dynamic = options?.dynamic;
|
|
193
|
+
const dynamicTtlMs =
|
|
194
|
+
dynamic !== undefined && dynamic !== true
|
|
195
|
+
? resolveTtlMilliseconds(dynamic.ttl, "dynamic.ttl")
|
|
196
|
+
: null;
|
|
197
|
+
|
|
198
|
+
if (dynamic !== true) {
|
|
199
|
+
const cached = this.evaluationCache.getRecord(cacheKey);
|
|
200
|
+
if (cached !== null && dynamicTtlMs !== null && Date.now() - cached.storedAtMs <= dynamicTtlMs) {
|
|
201
|
+
return cached.value;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const freshDefinitions = await this.fetchDefinitions([name]);
|
|
206
|
+
const freshDefinition = freshDefinitions[0];
|
|
207
|
+
if (freshDefinition === undefined) {
|
|
208
|
+
throw new VariableNotFoundError();
|
|
209
|
+
}
|
|
210
|
+
const resolved = await evaluateDefinition(freshDefinition, options);
|
|
211
|
+
|
|
212
|
+
if (dynamicTtlMs !== null) {
|
|
213
|
+
this.evaluationCache.set(cacheKey, resolved);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return resolved;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private async resolveEvaluatedValue(
|
|
220
|
+
name: string,
|
|
221
|
+
options?: BarekeyGetOptions,
|
|
222
|
+
): Promise<BarekeyEvaluatedValue> {
|
|
223
|
+
validateDynamicOptions(options);
|
|
224
|
+
if (options?.dynamic === undefined) {
|
|
225
|
+
return await this.resolveStaticValue(name, options);
|
|
226
|
+
}
|
|
227
|
+
return await this.resolveDynamicValue(name, options);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
AB,
|
|
3
|
+
BarekeyCoerceTarget,
|
|
4
|
+
BarekeyDeclaredType,
|
|
5
|
+
BarekeyDecision,
|
|
6
|
+
BarekeyErrorCode,
|
|
7
|
+
BarekeyEvaluatedValue,
|
|
8
|
+
BarekeyGetOptions,
|
|
9
|
+
BarekeyJsonConfig,
|
|
10
|
+
BarekeyResolvedKind,
|
|
11
|
+
BarekeyRolloutFunction,
|
|
12
|
+
BarekeyRolloutMatchedRule,
|
|
13
|
+
BarekeyRolloutMilestone,
|
|
14
|
+
BarekeyStandardSchemaPathSegment,
|
|
15
|
+
BarekeyStandardSchemaResult,
|
|
16
|
+
BarekeyStandardSchemaV1,
|
|
17
|
+
BarekeyTemporalInstant,
|
|
18
|
+
BarekeyTemporalInstantLike,
|
|
19
|
+
BarekeyTtlInput,
|
|
20
|
+
BarekeyTypegenResult,
|
|
21
|
+
BarekeyVariableDefinition,
|
|
22
|
+
EaseInOut,
|
|
23
|
+
Env,
|
|
24
|
+
Linear,
|
|
25
|
+
Secret,
|
|
26
|
+
Step,
|
|
27
|
+
} from "./types.js";
|
|
28
|
+
import type { BarekeyJsonConfig, BarekeyStandardSchemaV1 } from "./types.js";
|
|
29
|
+
|
|
30
|
+
export interface BarekeyPublicGeneratedTypeMap {}
|
|
31
|
+
|
|
32
|
+
export type BarekeyPublicKnownKey = Extract<keyof BarekeyPublicGeneratedTypeMap, string>;
|
|
33
|
+
|
|
34
|
+
type BarekeyPublicBaseClientOptions = {
|
|
35
|
+
requirements?: BarekeyStandardSchemaV1;
|
|
36
|
+
baseUrl?: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type PublicBarekeyClientOptions =
|
|
40
|
+
| (BarekeyPublicBaseClientOptions & {
|
|
41
|
+
organization: string;
|
|
42
|
+
project: string;
|
|
43
|
+
environment: string;
|
|
44
|
+
json?: never;
|
|
45
|
+
})
|
|
46
|
+
| (BarekeyPublicBaseClientOptions & {
|
|
47
|
+
json: BarekeyJsonConfig;
|
|
48
|
+
organization?: never;
|
|
49
|
+
project?: never;
|
|
50
|
+
environment?: never;
|
|
51
|
+
})
|
|
52
|
+
| (BarekeyPublicBaseClientOptions & {
|
|
53
|
+
organization?: never;
|
|
54
|
+
project?: never;
|
|
55
|
+
environment?: never;
|
|
56
|
+
json?: never;
|
|
57
|
+
});
|