Skip to content

Commit 8323372

Browse files
committed
feat: add environment variable chaining with built-in variable resolution
1 parent d9a2841 commit 8323372

File tree

19 files changed

+454
-342
lines changed

19 files changed

+454
-342
lines changed

packages/assertions/package.json

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
{
2-
"name": "@restflow/assertions",
3-
"version": "1.1.1",
4-
"type": "module",
5-
"main": "./dist/index.js",
6-
"module": "./dist/index.js",
7-
"types": "./dist/index.d.ts",
8-
"exports": {
9-
"./package.json": "./package.json",
10-
".": {
11-
"development": "./src/index.ts",
12-
"types": "./dist/index.d.ts",
13-
"import": "./dist/index.js",
14-
"default": "./dist/index.js"
15-
}
16-
},
17-
"files": [
18-
"dist",
19-
"!**/*.tsbuildinfo"
20-
],
21-
"dependencies": {
22-
"@restflow/types": "workspace:*",
23-
"@restflow/variables": "workspace:*",
24-
"jsonpath": "^1.1.1",
25-
"tslib": "^2.3.0"
26-
},
27-
"devDependencies": {
28-
"@types/jsonpath": "^0.2.4"
29-
}
2+
"name": "@restflow/assertions",
3+
"version": "1.1.1",
4+
"type": "module",
5+
"main": "./dist/index.js",
6+
"module": "./dist/index.js",
7+
"types": "./dist/index.d.ts",
8+
"exports": {
9+
"./package.json": "./package.json",
10+
".": {
11+
"development": "./src/index.ts",
12+
"types": "./dist/index.d.ts",
13+
"import": "./dist/index.js",
14+
"default": "./dist/index.js"
15+
}
16+
},
17+
"files": [
18+
"dist",
19+
"!**/*.tsbuildinfo"
20+
],
21+
"dependencies": {
22+
"@restflow/types": "workspace:*",
23+
"@restflow/variables": "workspace:*",
24+
"jsonpath": "^1.1.1",
25+
"tslib": "^2.3.0"
26+
},
27+
"devDependencies": {
28+
"@types/jsonpath": "^0.2.4"
29+
}
3030
}

packages/cli/package.json

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,40 @@
11
{
2-
"name": "@restflow/cli",
3-
"version": "1.1.1",
4-
"type": "module",
5-
"main": "./dist/index.js",
6-
"module": "./dist/index.js",
7-
"types": "./dist/index.d.ts",
8-
"exports": {
9-
"./package.json": "./package.json",
10-
".": {
11-
"development": "./src/index.ts",
12-
"types": "./dist/index.d.ts",
13-
"import": "./dist/index.js",
14-
"default": "./dist/index.js"
15-
}
16-
},
17-
"files": [
18-
"dist",
19-
"!**/*.tsbuildinfo"
20-
],
21-
"bin": {
22-
"restflow": "./dist/bin/restflow.js"
23-
},
24-
"dependencies": {
25-
"@clack/prompts": "^0.11.0",
26-
"@restflow/engine": "workspace:*",
27-
"@restflow/environment": "workspace:*",
28-
"@restflow/http": "workspace:*",
29-
"@restflow/parser": "workspace:*",
30-
"@restflow/reporter": "workspace:*",
31-
"@restflow/types": "workspace:*",
32-
"@restflow/utils": "workspace:*",
33-
"commander": "^14.0.0",
34-
"figures": "^6.1.0",
35-
"glob": "^10.3.10",
36-
"picocolors": "^1.1.1",
37-
"strip-ansi": "^7.1.0",
38-
"tslib": "^2.3.0"
39-
}
2+
"name": "@restflow/cli",
3+
"version": "1.1.1",
4+
"type": "module",
5+
"main": "./dist/index.js",
6+
"module": "./dist/index.js",
7+
"types": "./dist/index.d.ts",
8+
"exports": {
9+
"./package.json": "./package.json",
10+
".": {
11+
"development": "./src/index.ts",
12+
"types": "./dist/index.d.ts",
13+
"import": "./dist/index.js",
14+
"default": "./dist/index.js"
15+
}
16+
},
17+
"files": [
18+
"dist",
19+
"!**/*.tsbuildinfo"
20+
],
21+
"bin": {
22+
"restflow": "./dist/bin/restflow.js"
23+
},
24+
"dependencies": {
25+
"@clack/prompts": "^0.11.0",
26+
"@restflow/engine": "workspace:*",
27+
"@restflow/environment": "workspace:*",
28+
"@restflow/http": "workspace:*",
29+
"@restflow/parser": "workspace:*",
30+
"@restflow/reporter": "workspace:*",
31+
"@restflow/types": "workspace:*",
32+
"@restflow/utils": "workspace:*",
33+
"commander": "^14.0.0",
34+
"figures": "^6.1.0",
35+
"glob": "^10.3.10",
36+
"picocolors": "^1.1.1",
37+
"strip-ansi": "^7.1.0",
38+
"tslib": "^2.3.0"
39+
}
4040
}
Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,36 @@
11
{
2-
"name": "create-restflow",
3-
"version": "1.1.1",
4-
"type": "module",
5-
"main": "./dist/index.js",
6-
"module": "./dist/index.js",
7-
"types": "./dist/index.d.ts",
8-
"exports": {
9-
"./package.json": "./package.json",
10-
".": {
11-
"development": "./src/index.ts",
12-
"types": "./dist/index.d.ts",
13-
"import": "./dist/index.js",
14-
"default": "./dist/index.js"
15-
}
16-
},
17-
"bin": {
18-
"create-restflow": "./dist/cli.js"
19-
},
20-
"files": [
21-
"dist",
22-
"templates",
23-
"!**/*.tsbuildinfo"
24-
],
25-
"dependencies": {
26-
"@clack/prompts": "^0.11.0",
27-
"ejs": "^3.1.10",
28-
"fs-extra": "^11.3.1",
29-
"picocolors": "^1.1.1",
30-
"tslib": "^2.3.0"
31-
},
32-
"devDependencies": {
33-
"@types/ejs": "^3.1.5",
34-
"@types/fs-extra": "^11.0.4"
35-
}
2+
"name": "create-restflow",
3+
"version": "1.1.1",
4+
"type": "module",
5+
"main": "./dist/index.js",
6+
"module": "./dist/index.js",
7+
"types": "./dist/index.d.ts",
8+
"exports": {
9+
"./package.json": "./package.json",
10+
".": {
11+
"development": "./src/index.ts",
12+
"types": "./dist/index.d.ts",
13+
"import": "./dist/index.js",
14+
"default": "./dist/index.js"
15+
}
16+
},
17+
"bin": {
18+
"create-restflow": "./dist/cli.js"
19+
},
20+
"files": [
21+
"dist",
22+
"templates",
23+
"!**/*.tsbuildinfo"
24+
],
25+
"dependencies": {
26+
"@clack/prompts": "^0.11.0",
27+
"ejs": "^3.1.10",
28+
"fs-extra": "^11.3.1",
29+
"picocolors": "^1.1.1",
30+
"tslib": "^2.3.0"
31+
},
32+
"devDependencies": {
33+
"@types/ejs": "^3.1.5",
34+
"@types/fs-extra": "^11.0.4"
35+
}
3636
}

packages/engine/package.json

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,31 @@
11
{
2-
"name": "@restflow/engine",
3-
"version": "1.1.1",
4-
"type": "module",
5-
"main": "./dist/index.js",
6-
"module": "./dist/index.js",
7-
"types": "./dist/index.d.ts",
8-
"exports": {
9-
"./package.json": "./package.json",
10-
".": {
11-
"development": "./src/index.ts",
12-
"types": "./dist/index.d.ts",
13-
"import": "./dist/index.js",
14-
"default": "./dist/index.js"
15-
}
16-
},
17-
"files": [
18-
"dist",
19-
"!**/*.tsbuildinfo"
20-
],
21-
"dependencies": {
22-
"@restflow/types": "workspace:*",
23-
"@restflow/parser": "workspace:*",
24-
"@restflow/variables": "workspace:*",
25-
"@restflow/environment": "workspace:*",
26-
"@restflow/http": "workspace:*",
27-
"@restflow/assertions": "workspace:*",
28-
"@restflow/reporter": "workspace:*",
29-
"tslib": "^2.3.0"
30-
}
2+
"name": "@restflow/engine",
3+
"version": "1.1.1",
4+
"type": "module",
5+
"main": "./dist/index.js",
6+
"module": "./dist/index.js",
7+
"types": "./dist/index.d.ts",
8+
"exports": {
9+
"./package.json": "./package.json",
10+
".": {
11+
"development": "./src/index.ts",
12+
"types": "./dist/index.d.ts",
13+
"import": "./dist/index.js",
14+
"default": "./dist/index.js"
15+
}
16+
},
17+
"files": [
18+
"dist",
19+
"!**/*.tsbuildinfo"
20+
],
21+
"dependencies": {
22+
"@restflow/types": "workspace:*",
23+
"@restflow/parser": "workspace:*",
24+
"@restflow/variables": "workspace:*",
25+
"@restflow/environment": "workspace:*",
26+
"@restflow/http": "workspace:*",
27+
"@restflow/assertions": "workspace:*",
28+
"@restflow/reporter": "workspace:*",
29+
"tslib": "^2.3.0"
30+
}
3131
}

packages/environment/package.json

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
{
2-
"name": "@restflow/environment",
3-
"version": "1.1.1",
4-
"type": "module",
5-
"main": "./dist/index.js",
6-
"module": "./dist/index.js",
7-
"types": "./dist/index.d.ts",
8-
"exports": {
9-
"./package.json": "./package.json",
10-
".": {
11-
"development": "./src/index.ts",
12-
"types": "./dist/index.d.ts",
13-
"import": "./dist/index.js",
14-
"default": "./dist/index.js"
15-
}
16-
},
17-
"files": [
18-
"dist",
19-
"!**/*.tsbuildinfo"
20-
],
21-
"dependencies": {
22-
"dotenv": "^17.2.1",
23-
"tslib": "^2.3.0",
24-
"@restflow/types": "workspace:*"
25-
}
2+
"name": "@restflow/environment",
3+
"version": "1.1.1",
4+
"type": "module",
5+
"main": "./dist/index.js",
6+
"module": "./dist/index.js",
7+
"types": "./dist/index.d.ts",
8+
"exports": {
9+
"./package.json": "./package.json",
10+
".": {
11+
"development": "./src/index.ts",
12+
"types": "./dist/index.d.ts",
13+
"import": "./dist/index.js",
14+
"default": "./dist/index.js"
15+
}
16+
},
17+
"files": [
18+
"dist",
19+
"!**/*.tsbuildinfo"
20+
],
21+
"dependencies": {
22+
"dotenv": "^17.2.1",
23+
"tslib": "^2.3.0",
24+
"@restflow/types": "workspace:*",
25+
"@restflow/variables": "workspace:*"
26+
}
2627
}

packages/environment/src/managers/environment-manager.spec.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,57 @@ describe("EnvironmentManager", () => {
4343

4444
expect(result.valid).toBe(true);
4545
});
46+
47+
it("should resolve built-in variables in environment values", async () => {
48+
const dotenvLoaderMock = {
49+
load: vi.fn().mockReturnValue({
50+
USER: "user-{{randomString}}",
51+
EMAIL: "{{USER}}@example.com",
52+
}),
53+
loadFromString: vi.fn(),
54+
};
55+
vi.mocked(DotenvLoader).mockImplementation(() => dotenvLoaderMock);
56+
57+
const manager = new EnvironmentManager();
58+
const env = await manager.loadEnvironment("test.env");
59+
60+
expect(env.variables.USER).toMatch(/^user-[a-z0-9]+$/);
61+
expect(env.variables.EMAIL).toMatch(/^user-[a-z0-9]+@example\.com$/);
62+
});
63+
64+
it("should resolve variable references between environment variables", async () => {
65+
const dotenvLoaderMock = {
66+
load: vi.fn().mockReturnValue({
67+
BASE_URL: "https://api.example.com",
68+
API_ENDPOINT: "{{BASE_URL}}/v1",
69+
FULL_PATH: "{{API_ENDPOINT}}/users",
70+
}),
71+
loadFromString: vi.fn(),
72+
};
73+
vi.mocked(DotenvLoader).mockImplementation(() => dotenvLoaderMock);
74+
75+
const manager = new EnvironmentManager();
76+
const env = await manager.loadEnvironment("test.env");
77+
78+
expect(env.variables.BASE_URL).toBe("https://api.example.com");
79+
expect(env.variables.API_ENDPOINT).toBe("https://api.example.com/v1");
80+
expect(env.variables.FULL_PATH).toBe("https://api.example.com/v1/users");
81+
});
82+
83+
it("should handle mixed built-in and reference variables", async () => {
84+
const dotenvLoaderMock = {
85+
load: vi.fn().mockReturnValue({
86+
SESSION_ID: "session-{{uuid}}",
87+
LOG_FILE: "/logs/{{SESSION_ID}}.log",
88+
}),
89+
loadFromString: vi.fn(),
90+
};
91+
vi.mocked(DotenvLoader).mockImplementation(() => dotenvLoaderMock);
92+
93+
const manager = new EnvironmentManager();
94+
const env = await manager.loadEnvironment("test.env");
95+
96+
expect(env.variables.SESSION_ID).toMatch(/^session-[0-9a-f-]+$/);
97+
expect(env.variables.LOG_FILE).toMatch(/^\/logs\/session-[0-9a-f-]+\.log$/);
98+
});
4699
});

0 commit comments

Comments
 (0)