@blaxel/core 0.3.20-preview.288 → 0.3.20-preview.289
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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/common/env.js +25 -9
- package/dist/cjs/common/env.test.js +68 -6
- package/dist/cjs/common/settings.js +2 -2
- package/dist/cjs-browser/.tsbuildinfo +1 -1
- package/dist/cjs-browser/common/env.js +25 -9
- package/dist/cjs-browser/common/env.test.js +68 -6
- package/dist/cjs-browser/common/settings.js +2 -2
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/common/env.js +25 -9
- package/dist/esm/common/env.test.js +68 -6
- package/dist/esm/common/settings.js +2 -2
- package/dist/esm-browser/.tsbuildinfo +1 -1
- package/dist/esm-browser/common/env.js +25 -9
- package/dist/esm-browser/common/env.test.js +68 -6
- package/dist/esm-browser/common/settings.js +2 -2
- package/package.json +2 -2
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
import toml from "toml";
|
|
1
|
+
import toml from "smol-toml";
|
|
2
2
|
import { dotenv, fs } from "./node.js";
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const hasOwn = (source, prop) => Object.prototype.hasOwnProperty.call(source, prop);
|
|
4
|
+
const secretEnv = Object.create(null);
|
|
5
|
+
const configEnv = Object.create(null);
|
|
6
|
+
const stringifyTomlEnvValue = (value) => {
|
|
7
|
+
if (typeof value === "string") {
|
|
8
|
+
return value;
|
|
9
|
+
}
|
|
10
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
11
|
+
return String(value);
|
|
12
|
+
}
|
|
13
|
+
if (value instanceof Date) {
|
|
14
|
+
return value.toISOString();
|
|
15
|
+
}
|
|
16
|
+
const serialized = JSON.stringify(value);
|
|
17
|
+
return serialized === undefined ? String(value) : serialized;
|
|
18
|
+
};
|
|
5
19
|
if (fs !== null) {
|
|
6
20
|
try {
|
|
7
21
|
const configFile = fs.readFileSync("blaxel.toml", "utf8");
|
|
8
|
-
const configInfos = toml.parse(configFile);
|
|
9
|
-
|
|
10
|
-
|
|
22
|
+
const configInfos = toml.parse(configFile, { maxDepth: 100 });
|
|
23
|
+
if (configInfos.env && typeof configInfos.env === "object") {
|
|
24
|
+
for (const [key, value] of Object.entries(configInfos.env)) {
|
|
25
|
+
configEnv[key] = stringifyTomlEnvValue(value);
|
|
26
|
+
}
|
|
11
27
|
}
|
|
12
28
|
}
|
|
13
29
|
catch {
|
|
@@ -36,13 +52,13 @@ if (fs !== null) {
|
|
|
36
52
|
}
|
|
37
53
|
const env = new Proxy({}, {
|
|
38
54
|
get: (target, prop) => {
|
|
39
|
-
if (secretEnv
|
|
55
|
+
if (hasOwn(secretEnv, prop)) {
|
|
40
56
|
return secretEnv[prop];
|
|
41
57
|
}
|
|
42
|
-
if (configEnv
|
|
58
|
+
if (hasOwn(configEnv, prop)) {
|
|
43
59
|
return configEnv[prop];
|
|
44
60
|
}
|
|
45
|
-
if (typeof process !== "undefined" && process.env) {
|
|
61
|
+
if (typeof process !== "undefined" && process.env && hasOwn(process.env, prop)) {
|
|
46
62
|
return process.env[prop];
|
|
47
63
|
}
|
|
48
64
|
return undefined;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import toml from "toml";
|
|
4
|
+
import toml from "smol-toml";
|
|
5
5
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
6
6
|
const originalCwd = process.cwd();
|
|
7
|
+
const originalWorkspace = process.env.BL_WORKSPACE;
|
|
7
8
|
let currentTempDir;
|
|
8
9
|
const importEnvFromTempConfig = async (config) => {
|
|
9
10
|
currentTempDir = mkdtempSync(join(tmpdir(), "blaxel-env-"));
|
|
@@ -14,6 +15,14 @@ const importEnvFromTempConfig = async (config) => {
|
|
|
14
15
|
};
|
|
15
16
|
afterEach(() => {
|
|
16
17
|
process.chdir(originalCwd);
|
|
18
|
+
if (originalWorkspace === undefined) {
|
|
19
|
+
delete process.env.BL_WORKSPACE;
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
process.env.BL_WORKSPACE = originalWorkspace;
|
|
23
|
+
}
|
|
24
|
+
delete Object.prototype.BL_WORKSPACE;
|
|
25
|
+
delete Object.prototype.SECRET_ENV;
|
|
17
26
|
vi.resetModules();
|
|
18
27
|
if (currentTempDir) {
|
|
19
28
|
rmSync(currentTempDir, { force: true, recursive: true });
|
|
@@ -30,10 +39,63 @@ BL_API_URL = "https://api.example.test"
|
|
|
30
39
|
expect(env.BL_WORKSPACE).toBe("test-workspace");
|
|
31
40
|
expect(env.BL_API_URL).toBe("https://api.example.test");
|
|
32
41
|
});
|
|
33
|
-
it("
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
it("serializes supported TOML env value types through the SDK env proxy", async () => {
|
|
43
|
+
const { env } = await importEnvFromTempConfig(`
|
|
44
|
+
[env]
|
|
45
|
+
BOOLEAN_VALUE = true
|
|
46
|
+
NUMBER_VALUE = 42
|
|
47
|
+
ARRAY_VALUE = ["a", "b"]
|
|
48
|
+
INLINE_TABLE_VALUE = { name = "sandbox", enabled = true }
|
|
49
|
+
MULTILINE_VALUE = """
|
|
50
|
+
line one
|
|
51
|
+
line two
|
|
52
|
+
"""
|
|
53
|
+
`);
|
|
54
|
+
expect(env.BOOLEAN_VALUE).toBe("true");
|
|
55
|
+
expect(env.NUMBER_VALUE).toBe("42");
|
|
56
|
+
expect(env.ARRAY_VALUE).toBe('["a","b"]');
|
|
57
|
+
expect(env.INLINE_TABLE_VALUE).toBe('{"name":"sandbox","enabled":true}');
|
|
58
|
+
expect(env.MULTILINE_VALUE).toBe("line one\nline two\n");
|
|
59
|
+
});
|
|
60
|
+
it("bounds array and inline-table nesting in the selected TOML parser", () => {
|
|
61
|
+
const nestedArray = `value = ${"[".repeat(6)}0${"]".repeat(6)}`;
|
|
62
|
+
const nestedInlineTable = `value = ${"{ a = ".repeat(6)}0${"}".repeat(6)}`;
|
|
63
|
+
expect(() => toml.parse(nestedArray, { maxDepth: 5 })).toThrow(/excessively nested structures/);
|
|
64
|
+
expect(() => toml.parse(nestedInlineTable, { maxDepth: 5 })).toThrow(/excessively nested structures/);
|
|
65
|
+
});
|
|
66
|
+
it("uses the SDK loader bounded TOML parser for default config parsing", async () => {
|
|
67
|
+
process.env.BL_WORKSPACE = "process-workspace";
|
|
68
|
+
const nestedArray = `${"[".repeat(101)}0${"]".repeat(101)}`;
|
|
69
|
+
const { env } = await importEnvFromTempConfig(`
|
|
70
|
+
[env]
|
|
71
|
+
BL_WORKSPACE = "toml-workspace"
|
|
72
|
+
TOO_DEEP = ${nestedArray}
|
|
73
|
+
`);
|
|
74
|
+
expect(env.BL_WORKSPACE).toBe("process-workspace");
|
|
75
|
+
});
|
|
76
|
+
it("does not load inherited env keys from config or secret sources", async () => {
|
|
77
|
+
delete process.env.BL_WORKSPACE;
|
|
78
|
+
Object.prototype.BL_WORKSPACE = "polluted-workspace";
|
|
79
|
+
Object.prototype.SECRET_ENV = "polluted-secret";
|
|
80
|
+
const { env } = await importEnvFromTempConfig(`
|
|
81
|
+
[env]
|
|
82
|
+
LEGITIMATE_ENV = "kept"
|
|
83
|
+
`);
|
|
84
|
+
expect(env.BL_WORKSPACE).toBeUndefined();
|
|
85
|
+
expect(env.SECRET_ENV).toBeUndefined();
|
|
86
|
+
expect(env.LEGITIMATE_ENV).toBe("kept");
|
|
87
|
+
});
|
|
88
|
+
it("does not pollute prototypes while loading malicious TOML env keys", async () => {
|
|
89
|
+
delete process.env.BL_WORKSPACE;
|
|
90
|
+
const { env } = await importEnvFromTempConfig(`
|
|
91
|
+
[env]
|
|
92
|
+
BL_WORKSPACE = "legitimate-workspace"
|
|
93
|
+
|
|
94
|
+
[env.__proto__]
|
|
95
|
+
INJECTED = "polluted-workspace"
|
|
96
|
+
`);
|
|
97
|
+
expect(env.BL_WORKSPACE).toBe("legitimate-workspace");
|
|
98
|
+
expect(env.INJECTED).toBeUndefined();
|
|
99
|
+
expect(Object.prototype).not.toHaveProperty("INJECTED");
|
|
38
100
|
});
|
|
39
101
|
});
|
|
@@ -24,8 +24,8 @@ function missingCredentialsMessage() {
|
|
|
24
24
|
return "No Blaxel credentials found. Set the BL_API_KEY and BL_WORKSPACE environment variables, or run `bl login`.";
|
|
25
25
|
}
|
|
26
26
|
// Build info - these placeholders are replaced at build time by build:replace-imports
|
|
27
|
-
const BUILD_VERSION = "0.3.20-preview.
|
|
28
|
-
const BUILD_COMMIT = "
|
|
27
|
+
const BUILD_VERSION = "0.3.20-preview.289";
|
|
28
|
+
const BUILD_COMMIT = "58aa51d749f749507d5fee77ee0393ec7d9c4753";
|
|
29
29
|
const BUILD_SENTRY_DSN = "https://fd5e60e1c9820e1eef5ccebb84a07127@o4508714045276160.ingest.us.sentry.io/4510465864564736";
|
|
30
30
|
const BLAXEL_API_VERSION = "2026-04-28";
|
|
31
31
|
// Bun < 1.3.11 never sends connection-level WINDOW_UPDATE: the pooled h2
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blaxel/core",
|
|
3
|
-
"version": "0.3.20-preview.
|
|
3
|
+
"version": "0.3.20-preview.289",
|
|
4
4
|
"description": "Blaxel Core SDK for TypeScript",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Blaxel, INC (https://blaxel.ai)",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"dotenv": "^17.4.2",
|
|
73
73
|
"form-data": "^4.0.2",
|
|
74
74
|
"jwt-decode": "^4.0.0",
|
|
75
|
-
"toml": "
|
|
75
|
+
"smol-toml": "^1.8.0",
|
|
76
76
|
"uuid": "^11.1.0",
|
|
77
77
|
"ws": "^8.18.2",
|
|
78
78
|
"yaml": "^2.7.1",
|