alpic 0.0.0-dev.97ff947 → 0.0.0-dev.982ee78
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/__tests__/auth.e2e.test.d.ts +1 -0
- package/dist/__tests__/auth.e2e.test.js +142 -0
- package/dist/__tests__/auth.e2e.test.js.map +1 -0
- package/dist/__tests__/deploy.e2e.test.js +39 -72
- package/dist/__tests__/deploy.e2e.test.js.map +1 -1
- package/dist/__tests__/git.e2e.test.js +106 -138
- package/dist/__tests__/git.e2e.test.js.map +1 -1
- package/dist/__tests__/mock-server.js +132 -7
- package/dist/__tests__/mock-server.js.map +1 -1
- package/dist/__tests__/utils.d.ts +32 -0
- package/dist/__tests__/utils.js +108 -0
- package/dist/__tests__/utils.js.map +1 -1
- package/dist/api.d.ts +0 -1
- package/dist/api.js +5 -9
- package/dist/api.js.map +1 -1
- package/dist/commands/deploy.d.ts +2 -2
- package/dist/commands/deploy.js +6 -9
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/git/connect.d.ts +2 -2
- package/dist/commands/git/connect.js +15 -60
- package/dist/commands/git/connect.js.map +1 -1
- package/dist/commands/git/disconnect.d.ts +2 -2
- package/dist/commands/git/disconnect.js +8 -22
- package/dist/commands/git/disconnect.js.map +1 -1
- package/dist/commands/git.js +1 -1
- package/dist/commands/git.js.map +1 -1
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.js +38 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +6 -0
- package/dist/commands/logout.js +20 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/whoami.d.ts +6 -0
- package/dist/commands/whoami.js +25 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/env.d.ts +4 -0
- package/dist/env.js +10 -0
- package/dist/env.js.map +1 -0
- package/dist/lib/alpic-command.d.ts +4 -0
- package/dist/lib/alpic-command.js +17 -0
- package/dist/lib/alpic-command.js.map +1 -0
- package/dist/lib/auth/auth.d.ts +2 -0
- package/dist/lib/auth/auth.js +21 -0
- package/dist/lib/auth/auth.js.map +1 -0
- package/dist/lib/auth/oauth/client.d.ts +29 -0
- package/dist/lib/auth/oauth/client.js +112 -0
- package/dist/lib/auth/oauth/client.js.map +1 -0
- package/dist/lib/auth/oauth/constants.d.ts +2 -0
- package/dist/lib/auth/oauth/constants.js +3 -0
- package/dist/lib/auth/oauth/constants.js.map +1 -0
- package/dist/lib/auth/oauth/server.d.ts +6 -0
- package/dist/lib/auth/oauth/server.js +88 -0
- package/dist/lib/auth/oauth/server.js.map +1 -0
- package/dist/lib/auth/whoami.d.ts +28 -0
- package/dist/lib/auth/whoami.js +35 -0
- package/dist/lib/auth/whoami.js.map +1 -0
- package/dist/lib/deployment.d.ts +2 -3
- package/dist/lib/deployment.js +13 -8
- package/dist/lib/deployment.js.map +1 -1
- package/dist/lib/git.d.ts +9 -3
- package/dist/lib/git.js +51 -15
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/global-store.d.ts +28 -0
- package/dist/lib/global-store.js +75 -0
- package/dist/lib/global-store.js.map +1 -0
- package/dist/lib/telemetry.js +6 -6
- package/dist/lib/telemetry.js.map +1 -1
- package/package.json +22 -15
- package/dist/lib/auth.d.ts +0 -1
- package/dist/lib/auth.js +0 -10
- package/dist/lib/auth.js.map +0 -1
- package/dist/lib/global-config.d.ts +0 -9
- package/dist/lib/global-config.js +0 -48
- package/dist/lib/global-config.js.map +0 -1
|
@@ -1,23 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { cp, mkdtemp } from "node:fs/promises";
|
|
5
|
-
import { tmpdir } from "node:os";
|
|
6
|
-
import { dirname, join } from "node:path";
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
1
|
+
import { rmSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
8
3
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
9
4
|
import { MockApiServer } from "./mock-server";
|
|
10
|
-
import { cliSession } from "./utils";
|
|
11
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
import { buildMockProject, cliSession, createConfigFile, createOAuthEnv, expectSuccessfulApiCall, runGit, setupTestDirectory, } from "./utils";
|
|
12
6
|
describe("alpic git connect/disconnect (E2E)", () => {
|
|
13
7
|
let mockServer;
|
|
14
8
|
let serverUrl;
|
|
15
9
|
let cwd;
|
|
16
10
|
let binPath;
|
|
11
|
+
const projectId = "project-id";
|
|
12
|
+
const teamId = "team-id";
|
|
13
|
+
const environmentId = "env-id";
|
|
14
|
+
function setupProject(overrides) {
|
|
15
|
+
mockServer.addProject(buildMockProject({
|
|
16
|
+
projectId,
|
|
17
|
+
teamId,
|
|
18
|
+
projectName: "demo",
|
|
19
|
+
environmentId,
|
|
20
|
+
environmentName: "production",
|
|
21
|
+
sourceRepository: null,
|
|
22
|
+
sourceBranch: "main",
|
|
23
|
+
...overrides,
|
|
24
|
+
}));
|
|
25
|
+
createConfigFile(cwd, projectId, teamId, "demo", environmentId, "production");
|
|
26
|
+
}
|
|
17
27
|
beforeEach(async () => {
|
|
18
28
|
mockServer = new MockApiServer();
|
|
19
29
|
serverUrl = await mockServer.start();
|
|
20
|
-
const setup = await
|
|
30
|
+
const setup = await setupTestDirectory({ prefix: "alpic-cli-e2e-git", initGit: true });
|
|
21
31
|
cwd = setup.cwd;
|
|
22
32
|
binPath = setup.binPath;
|
|
23
33
|
});
|
|
@@ -28,28 +38,16 @@ describe("alpic git connect/disconnect (E2E)", () => {
|
|
|
28
38
|
}
|
|
29
39
|
});
|
|
30
40
|
it("connects using selected remote source when multiple remotes are available", async () => {
|
|
31
|
-
|
|
32
|
-
const teamId = "team-id";
|
|
33
|
-
const environmentId = "env-id";
|
|
34
|
-
mockServer.addProject(buildMockProject({
|
|
35
|
-
projectId,
|
|
36
|
-
teamId,
|
|
37
|
-
projectName: "demo",
|
|
38
|
-
environmentId,
|
|
39
|
-
environmentName: "production",
|
|
40
|
-
sourceRepository: null,
|
|
41
|
-
}));
|
|
42
|
-
createConfigFile(cwd, projectId, teamId, "demo", environmentId, "production");
|
|
41
|
+
setupProject();
|
|
43
42
|
const { exitCode, output } = await cliSession(process.execPath, [binPath, "git", "connect"], {
|
|
44
43
|
cwd,
|
|
45
44
|
env: {
|
|
46
45
|
ALPIC_API_BASE_URL: serverUrl,
|
|
47
|
-
ALPIC_FRONTEND_BASE_URL: "http://mocked.frontend.url",
|
|
48
46
|
ALPIC_API_KEY: "test-api-key",
|
|
49
47
|
},
|
|
50
48
|
}, async (cli) => {
|
|
51
49
|
await cli.expect("Choose the remote source to connect");
|
|
52
|
-
await cli.send("\u001B[B"); // Move down one option
|
|
50
|
+
await cli.send("\u001B[B"); // Move down one option (select acme/backend)
|
|
53
51
|
await cli.send("");
|
|
54
52
|
await cli.expect("Connected");
|
|
55
53
|
await cli.expect("every push");
|
|
@@ -57,10 +55,9 @@ describe("alpic git connect/disconnect (E2E)", () => {
|
|
|
57
55
|
expect(exitCode).toBe(0);
|
|
58
56
|
expect(output).toMatch(/Connected .*acme\/backend.* to project .*demo.*\./);
|
|
59
57
|
expect(output).toContain("make sure to install the Alpic GitHub App on this repository.");
|
|
60
|
-
const updateCall = mockServer.getLastCall("PATCH",
|
|
58
|
+
const updateCall = mockServer.getLastCall("PATCH", `/v1/projects/${projectId}`);
|
|
61
59
|
expectSuccessfulApiCall(updateCall, (call) => {
|
|
62
60
|
expect(call.input).toMatchObject({
|
|
63
|
-
projectId,
|
|
64
61
|
sourceRepository: "acme/backend",
|
|
65
62
|
});
|
|
66
63
|
});
|
|
@@ -71,7 +68,6 @@ describe("alpic git connect/disconnect (E2E)", () => {
|
|
|
71
68
|
cwd,
|
|
72
69
|
env: {
|
|
73
70
|
ALPIC_API_BASE_URL: serverUrl,
|
|
74
|
-
ALPIC_FRONTEND_BASE_URL: "http://mocked.frontend.url",
|
|
75
71
|
ALPIC_API_KEY: "test-api-key",
|
|
76
72
|
},
|
|
77
73
|
}, async (cli) => {
|
|
@@ -80,24 +76,12 @@ describe("alpic git connect/disconnect (E2E)", () => {
|
|
|
80
76
|
expect(output).toContain("This directory is not linked to an Alpic project. Link it first using `alpic deploy`.");
|
|
81
77
|
});
|
|
82
78
|
it("shows git setup instructions when directory is not a git repository", async () => {
|
|
83
|
-
|
|
84
|
-
const teamId = "team-id";
|
|
85
|
-
const environmentId = "env-id";
|
|
86
|
-
mockServer.addProject(buildMockProject({
|
|
87
|
-
projectId,
|
|
88
|
-
teamId,
|
|
89
|
-
projectName: "demo",
|
|
90
|
-
environmentId,
|
|
91
|
-
environmentName: "production",
|
|
92
|
-
sourceRepository: null,
|
|
93
|
-
}));
|
|
94
|
-
createConfigFile(cwd, projectId, teamId, "demo", environmentId, "production");
|
|
79
|
+
setupProject();
|
|
95
80
|
rmSync(join(cwd, ".git"), { recursive: true, force: true });
|
|
96
81
|
const { output } = await cliSession(process.execPath, [binPath, "git", "connect"], {
|
|
97
82
|
cwd,
|
|
98
83
|
env: {
|
|
99
84
|
ALPIC_API_BASE_URL: serverUrl,
|
|
100
|
-
ALPIC_FRONTEND_BASE_URL: "http://mocked.frontend.url",
|
|
101
85
|
ALPIC_API_KEY: "test-api-key",
|
|
102
86
|
},
|
|
103
87
|
}, async (cli) => {
|
|
@@ -110,25 +94,13 @@ describe("alpic git connect/disconnect (E2E)", () => {
|
|
|
110
94
|
expect(output).toContain("git init");
|
|
111
95
|
});
|
|
112
96
|
it("shows git setup instructions when repository has no remotes", async () => {
|
|
113
|
-
|
|
114
|
-
const teamId = "team-id";
|
|
115
|
-
const environmentId = "env-id";
|
|
116
|
-
mockServer.addProject(buildMockProject({
|
|
117
|
-
projectId,
|
|
118
|
-
teamId,
|
|
119
|
-
projectName: "demo",
|
|
120
|
-
environmentId,
|
|
121
|
-
environmentName: "production",
|
|
122
|
-
sourceRepository: null,
|
|
123
|
-
}));
|
|
124
|
-
createConfigFile(cwd, projectId, teamId, "demo", environmentId, "production");
|
|
97
|
+
setupProject();
|
|
125
98
|
runGit(["remote", "remove", "origin"], cwd);
|
|
126
99
|
runGit(["remote", "remove", "upstream"], cwd);
|
|
127
100
|
const { output } = await cliSession(process.execPath, [binPath, "git", "connect"], {
|
|
128
101
|
cwd,
|
|
129
102
|
env: {
|
|
130
103
|
ALPIC_API_BASE_URL: serverUrl,
|
|
131
|
-
ALPIC_FRONTEND_BASE_URL: "http://mocked.frontend.url",
|
|
132
104
|
ALPIC_API_KEY: "test-api-key",
|
|
133
105
|
},
|
|
134
106
|
}, async (cli) => {
|
|
@@ -140,111 +112,107 @@ describe("alpic git connect/disconnect (E2E)", () => {
|
|
|
140
112
|
expect(output).toContain("To set up a git repository");
|
|
141
113
|
expect(output).toContain("git init");
|
|
142
114
|
});
|
|
115
|
+
it("when project is already connected, prompts to link another and exits if user declines", async () => {
|
|
116
|
+
setupProject({ sourceRepository: "acme/backend" });
|
|
117
|
+
const { output } = await cliSession(process.execPath, [binPath, "git", "connect"], {
|
|
118
|
+
cwd,
|
|
119
|
+
env: {
|
|
120
|
+
ALPIC_API_BASE_URL: serverUrl,
|
|
121
|
+
ALPIC_API_KEY: "test-api-key",
|
|
122
|
+
},
|
|
123
|
+
}, async (cli) => {
|
|
124
|
+
await cli.expect(/Project .*demo.* is already connected to .*acme\/backend.*\./);
|
|
125
|
+
await cli.expect("Do you want to link another repository?");
|
|
126
|
+
await cli.send(""); // accept default (No)
|
|
127
|
+
await cli.expect("Git connect cancelled");
|
|
128
|
+
});
|
|
129
|
+
expect(output).toMatch(/Project .*demo.* is already connected to .*acme\/backend.*\./);
|
|
130
|
+
expect(output).toContain("Git connect cancelled");
|
|
131
|
+
expect(mockServer.getCalls("PATCH", "/v1/projects/")).toHaveLength(0);
|
|
132
|
+
});
|
|
133
|
+
it("disconnect fails with clear message when project is not connected", async () => {
|
|
134
|
+
setupProject(); // sourceRepository is null by default
|
|
135
|
+
const { output } = await cliSession(process.execPath, [binPath, "git", "disconnect"], {
|
|
136
|
+
cwd,
|
|
137
|
+
env: {
|
|
138
|
+
ALPIC_API_BASE_URL: serverUrl,
|
|
139
|
+
ALPIC_API_KEY: "test-api-key",
|
|
140
|
+
},
|
|
141
|
+
}, async (cli) => {
|
|
142
|
+
await cli.expect(/Project .*demo.* is not connected to any repository\./);
|
|
143
|
+
});
|
|
144
|
+
expect(output).toMatch(/Project .*demo.* is not connected to any repository\./);
|
|
145
|
+
expect(mockServer.getCalls("PATCH", "/v1/projects/")).toHaveLength(0);
|
|
146
|
+
});
|
|
143
147
|
it("disconnects an already connected project repository", async () => {
|
|
144
|
-
|
|
145
|
-
const teamId = "team-id";
|
|
146
|
-
const environmentId = "env-id";
|
|
147
|
-
mockServer.addProject(buildMockProject({
|
|
148
|
-
projectId,
|
|
149
|
-
teamId,
|
|
150
|
-
projectName: "demo",
|
|
151
|
-
environmentId,
|
|
152
|
-
environmentName: "production",
|
|
153
|
-
sourceRepository: "acme/frontend",
|
|
154
|
-
}));
|
|
155
|
-
createConfigFile(cwd, projectId, teamId, "demo", environmentId, "production");
|
|
148
|
+
setupProject({ sourceRepository: "acme/frontend" });
|
|
156
149
|
const { exitCode, output } = await cliSession(process.execPath, [binPath, "git", "disconnect"], {
|
|
157
150
|
cwd,
|
|
158
151
|
env: {
|
|
159
152
|
ALPIC_API_BASE_URL: serverUrl,
|
|
160
|
-
ALPIC_FRONTEND_BASE_URL: "http://mocked.frontend.url",
|
|
161
153
|
ALPIC_API_KEY: "test-api-key",
|
|
162
154
|
},
|
|
163
155
|
}, async (cli) => {
|
|
164
156
|
await cli.expect(/Are you sure you want to disconnect .*acme\/frontend.* from project .*demo.*\?/);
|
|
157
|
+
await cli.send("\u001B[A"); // arrow up to select Yes
|
|
165
158
|
await cli.send("");
|
|
166
159
|
await cli.expect(/Disconnected .*acme\/frontend.* from project .*demo.*\./);
|
|
167
160
|
});
|
|
168
161
|
expect(exitCode).toBe(0);
|
|
169
162
|
expect(output).toMatch(/Disconnected .*acme\/frontend.* from project .*demo.*\./);
|
|
170
|
-
const updateCall = mockServer.getLastCall("PATCH",
|
|
163
|
+
const updateCall = mockServer.getLastCall("PATCH", `/v1/projects/${projectId}`);
|
|
171
164
|
expectSuccessfulApiCall(updateCall, (call) => {
|
|
172
165
|
expect(call.input).toMatchObject({
|
|
173
|
-
projectId,
|
|
174
166
|
sourceRepository: null,
|
|
175
167
|
});
|
|
176
168
|
});
|
|
177
169
|
});
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
teamId,
|
|
186
|
-
environments: [
|
|
187
|
-
{
|
|
188
|
-
id: environmentId,
|
|
189
|
-
name: environmentName,
|
|
190
|
-
sourceBranch: "main",
|
|
191
|
-
mcpServerUrl,
|
|
192
|
-
createdAt: new Date(),
|
|
193
|
-
projectId,
|
|
194
|
-
latestDeployment: null,
|
|
170
|
+
it("git connect works with OAuth auth (no API key)", async () => {
|
|
171
|
+
setupProject();
|
|
172
|
+
const oauthEnv = createOAuthEnv(cwd, serverUrl);
|
|
173
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "git", "connect"], {
|
|
174
|
+
cwd,
|
|
175
|
+
env: {
|
|
176
|
+
...oauthEnv,
|
|
195
177
|
},
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
createdAt: new Date(),
|
|
212
|
-
};
|
|
213
|
-
}
|
|
214
|
-
async function setupGitTestDirectory() {
|
|
215
|
-
const uniqueId = randomUUID();
|
|
216
|
-
const cwd = await mkdtemp(join(tmpdir(), `alpic-cli-e2e-git-${uniqueId}-`));
|
|
217
|
-
const fixturePath = join(__dirname, "fixtures", "demo-project");
|
|
218
|
-
await cp(fixturePath, cwd, { recursive: true });
|
|
219
|
-
runGit(["init"], cwd);
|
|
220
|
-
runGit(["remote", "add", "origin", "git@github.com:acme/frontend.git"], cwd);
|
|
221
|
-
runGit(["remote", "add", "upstream", "https://github.com/acme/backend.git"], cwd);
|
|
222
|
-
const binPath = join(process.cwd(), "bin", "dev.js");
|
|
223
|
-
return { cwd, binPath };
|
|
224
|
-
}
|
|
225
|
-
function createConfigFile(cwd, projectId, teamId, projectName, environmentId, environmentName) {
|
|
226
|
-
const configDir = join(cwd, ".alpic");
|
|
227
|
-
mkdirSync(configDir, { recursive: true });
|
|
228
|
-
const configPath = join(configDir, "project.json");
|
|
229
|
-
writeFileSync(configPath, JSON.stringify({
|
|
230
|
-
projectId,
|
|
231
|
-
teamId,
|
|
232
|
-
projectName,
|
|
233
|
-
environmentId,
|
|
234
|
-
environmentName,
|
|
235
|
-
}));
|
|
236
|
-
}
|
|
237
|
-
function runGit(args, cwd) {
|
|
238
|
-
execFileSync("git", args, {
|
|
239
|
-
cwd,
|
|
240
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
178
|
+
}, async (cli) => {
|
|
179
|
+
await cli.expect("Choose the remote source to connect");
|
|
180
|
+
await cli.send("\u001B[B"); // Move down one option (select acme/backend)
|
|
181
|
+
await cli.send("");
|
|
182
|
+
await cli.expect("Connected");
|
|
183
|
+
await cli.expect("every push");
|
|
184
|
+
});
|
|
185
|
+
expect(exitCode).toBe(0);
|
|
186
|
+
expect(output).toMatch(/Connected .*acme\/backend.* to project .*demo.*\./);
|
|
187
|
+
const updateCall = mockServer.getLastCall("PATCH", `/v1/projects/${projectId}`);
|
|
188
|
+
expectSuccessfulApiCall(updateCall, (call) => {
|
|
189
|
+
expect(call.input).toMatchObject({
|
|
190
|
+
sourceRepository: "acme/backend",
|
|
191
|
+
});
|
|
192
|
+
});
|
|
241
193
|
});
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}
|
|
194
|
+
it("git disconnect works with OAuth auth (no API key)", async () => {
|
|
195
|
+
setupProject({ sourceRepository: "acme/frontend" });
|
|
196
|
+
const oauthEnv = createOAuthEnv(cwd, serverUrl);
|
|
197
|
+
const { exitCode, output } = await cliSession(process.execPath, [binPath, "git", "disconnect"], {
|
|
198
|
+
cwd,
|
|
199
|
+
env: {
|
|
200
|
+
...oauthEnv,
|
|
201
|
+
},
|
|
202
|
+
}, async (cli) => {
|
|
203
|
+
await cli.expect(/Are you sure you want to disconnect .*acme\/frontend.* from project .*demo.*\?/);
|
|
204
|
+
await cli.send("\u001B[A"); // arrow up to select Yes
|
|
205
|
+
await cli.send("");
|
|
206
|
+
await cli.expect(/Disconnected .*acme\/frontend.* from project .*demo.*\./);
|
|
207
|
+
});
|
|
208
|
+
expect(exitCode).toBe(0);
|
|
209
|
+
expect(output).toMatch(/Disconnected .*acme\/frontend.* from project .*demo.*\./);
|
|
210
|
+
const updateCall = mockServer.getLastCall("PATCH", `/v1/projects/${projectId}`);
|
|
211
|
+
expectSuccessfulApiCall(updateCall, (call) => {
|
|
212
|
+
expect(call.input).toMatchObject({
|
|
213
|
+
sourceRepository: null,
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
}, 20_000);
|
|
250
218
|
//# sourceMappingURL=git.e2e.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/git.e2e.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"git.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/git.e2e.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import * as https from "node:https";
|
|
1
2
|
import { OpenAPIHandler } from "@orpc/openapi/node";
|
|
2
3
|
import { ORPCError, implement } from "@orpc/server";
|
|
3
4
|
import express, {} from "express";
|
|
4
5
|
import { randomUUID } from "node:crypto";
|
|
6
|
+
import selfsigned from "selfsigned";
|
|
5
7
|
import { contract } from "@alpic-ai/api";
|
|
6
8
|
export class MockApiServer {
|
|
7
9
|
server = null;
|
|
@@ -22,11 +24,16 @@ export class MockApiServer {
|
|
|
22
24
|
throw new Error("Server is already running");
|
|
23
25
|
}
|
|
24
26
|
this.configureServer();
|
|
27
|
+
const pems = await selfsigned.generate();
|
|
28
|
+
const httpsOptions = { key: pems.private, cert: pems.cert };
|
|
25
29
|
return new Promise((resolve) => {
|
|
26
|
-
this.server = this.app.listen(0, "127.0.0.1", () => {
|
|
30
|
+
this.server = https.createServer(httpsOptions, this.app).listen(0, "127.0.0.1", () => {
|
|
31
|
+
if (!this.server) {
|
|
32
|
+
throw new Error("Server is not running");
|
|
33
|
+
}
|
|
27
34
|
const address = this.server.address();
|
|
28
35
|
this.port = address.port;
|
|
29
|
-
const url = `
|
|
36
|
+
const url = `https://127.0.0.1:${this.port}`;
|
|
30
37
|
resolve(url);
|
|
31
38
|
});
|
|
32
39
|
});
|
|
@@ -44,7 +51,87 @@ export class MockApiServer {
|
|
|
44
51
|
res.status(200).end();
|
|
45
52
|
});
|
|
46
53
|
this.app.use(express.json());
|
|
54
|
+
this.app.get("/.well-known/oauth-protected-resource", (_req, res) => {
|
|
55
|
+
const base = `https://127.0.0.1:${this.port}`;
|
|
56
|
+
res.status(200).json({
|
|
57
|
+
resource: "https://api.alpic.ai",
|
|
58
|
+
authorization_servers: [base],
|
|
59
|
+
bearer_methods_supported: ["header"],
|
|
60
|
+
scopes_supported: ["openid", "email", "profile"],
|
|
61
|
+
resource_documentation: "https://docs.alpic.ai",
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
this.app.get("/.well-known/openid-configuration", (_req, res) => {
|
|
65
|
+
const base = `https://127.0.0.1:${this.port}`;
|
|
66
|
+
res.status(200).json({
|
|
67
|
+
issuer: base,
|
|
68
|
+
userinfo_endpoint: `${base}/oauth2/userInfo`,
|
|
69
|
+
authorization_endpoint: `${base}/oauth2/authorize`,
|
|
70
|
+
token_endpoint: `${base}/oauth2/token`,
|
|
71
|
+
jwks_uri: `${base}/.well-known/jwks.json`,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
this.app.get("/oauth2/userInfo", (req, res) => {
|
|
75
|
+
const auth = req.headers.authorization;
|
|
76
|
+
if (!auth?.startsWith("Bearer ")) {
|
|
77
|
+
res.status(401).json({ error: "Missing or invalid Authorization" });
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
res.status(200).json({
|
|
81
|
+
sub: "test-sub",
|
|
82
|
+
email_verified: "true",
|
|
83
|
+
identities: [],
|
|
84
|
+
name: "Test User",
|
|
85
|
+
email: "test@example.com",
|
|
86
|
+
picture: "",
|
|
87
|
+
username: "testuser",
|
|
88
|
+
});
|
|
89
|
+
});
|
|
47
90
|
const router = implement(contract).router({
|
|
91
|
+
teams: {
|
|
92
|
+
list: {
|
|
93
|
+
v1: implement(contract.teams.list.v1).handler(async () => {
|
|
94
|
+
return [
|
|
95
|
+
{
|
|
96
|
+
id: "mock-team-id",
|
|
97
|
+
name: "Mock Team",
|
|
98
|
+
createdAt: new Date(),
|
|
99
|
+
hasStripeAccount: false,
|
|
100
|
+
hasActiveSubscription: false,
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
}),
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
analytics: {
|
|
107
|
+
get: {
|
|
108
|
+
v1: implement(contract.analytics.get.v1).handler(async ({ input }) => {
|
|
109
|
+
const project = this.mockData.projects.get(input.projectId);
|
|
110
|
+
if (!project) {
|
|
111
|
+
throw new ORPCError("NOT_FOUND", { message: "Project not found" });
|
|
112
|
+
}
|
|
113
|
+
const emptyTimeSeries = {
|
|
114
|
+
sessions_count: [],
|
|
115
|
+
requests_count: [],
|
|
116
|
+
requests_latency_mean: [],
|
|
117
|
+
tool_errors: [],
|
|
118
|
+
mcp_errors: [],
|
|
119
|
+
output_token_mean: [],
|
|
120
|
+
task_count: [],
|
|
121
|
+
};
|
|
122
|
+
return {
|
|
123
|
+
metadata: {
|
|
124
|
+
startTimestamp: input.startTimestamp,
|
|
125
|
+
endTimestamp: input.endTimestamp,
|
|
126
|
+
timeZone: input.timeZone,
|
|
127
|
+
startDate: new Date(input.startTimestamp),
|
|
128
|
+
interval: "1h",
|
|
129
|
+
},
|
|
130
|
+
timeSeries: emptyTimeSeries,
|
|
131
|
+
};
|
|
132
|
+
}),
|
|
133
|
+
},
|
|
134
|
+
},
|
|
48
135
|
projects: {
|
|
49
136
|
list: {
|
|
50
137
|
v1: implement(contract.projects.list.v1).handler(async () => {
|
|
@@ -140,12 +227,21 @@ export class MockApiServer {
|
|
|
140
227
|
if (!project) {
|
|
141
228
|
throw new ORPCError("NOT_FOUND", { message: "Project not found" });
|
|
142
229
|
}
|
|
143
|
-
let nextProject = project;
|
|
144
230
|
if (input.sourceRepository !== undefined) {
|
|
145
|
-
|
|
231
|
+
project.sourceRepository = input.sourceRepository;
|
|
146
232
|
}
|
|
147
|
-
this.mockData.projects.set(input.projectId,
|
|
148
|
-
return
|
|
233
|
+
this.mockData.projects.set(input.projectId, project);
|
|
234
|
+
return project;
|
|
235
|
+
}),
|
|
236
|
+
},
|
|
237
|
+
delete: {
|
|
238
|
+
v1: implement(contract.projects.delete.v1).handler(async ({ input }) => {
|
|
239
|
+
const project = this.mockData.projects.get(input.projectId);
|
|
240
|
+
if (!project) {
|
|
241
|
+
throw new ORPCError("NOT_FOUND", { message: "Project not found" });
|
|
242
|
+
}
|
|
243
|
+
this.mockData.projects.delete(input.projectId);
|
|
244
|
+
return { success: true };
|
|
149
245
|
}),
|
|
150
246
|
},
|
|
151
247
|
},
|
|
@@ -220,6 +316,7 @@ export class MockApiServer {
|
|
|
220
316
|
authorAvatarUrl: null,
|
|
221
317
|
startedAt: new Date(),
|
|
222
318
|
completedAt: null,
|
|
319
|
+
deploymentPageUrl: "https://app.alpic.ai/deployments/mock",
|
|
223
320
|
};
|
|
224
321
|
this.mockData.deployments.set(deploymentId, deployment);
|
|
225
322
|
return deployment;
|
|
@@ -227,6 +324,19 @@ export class MockApiServer {
|
|
|
227
324
|
},
|
|
228
325
|
},
|
|
229
326
|
deployments: {
|
|
327
|
+
list: {
|
|
328
|
+
v1: implement(contract.deployments.list.v1).handler(async ({ input }) => {
|
|
329
|
+
const project = this.mockData.projects.get(input.projectId);
|
|
330
|
+
if (!project) {
|
|
331
|
+
throw new ORPCError("NOT_FOUND", { message: "Project not found" });
|
|
332
|
+
}
|
|
333
|
+
return Array.from(this.mockData.deployments.values()).map((deployment) => ({
|
|
334
|
+
...deployment,
|
|
335
|
+
isCurrent: deployment.status === "deployed",
|
|
336
|
+
environmentId: project.productionEnvironment?.id ?? "",
|
|
337
|
+
}));
|
|
338
|
+
}),
|
|
339
|
+
},
|
|
230
340
|
get: {
|
|
231
341
|
v1: implement(contract.deployments.get.v1).handler(async ({ input }) => {
|
|
232
342
|
const deployment = this.mockData.deployments.get(input.deploymentId);
|
|
@@ -238,6 +348,7 @@ export class MockApiServer {
|
|
|
238
348
|
...deployment,
|
|
239
349
|
status: "deployed",
|
|
240
350
|
completedAt: new Date(),
|
|
351
|
+
deploymentPageUrl: deployment.deploymentPageUrl ?? null,
|
|
241
352
|
};
|
|
242
353
|
this.mockData.deployments.set(input.deploymentId, updatedDeployment);
|
|
243
354
|
return updatedDeployment;
|
|
@@ -245,10 +356,22 @@ export class MockApiServer {
|
|
|
245
356
|
return deployment;
|
|
246
357
|
}),
|
|
247
358
|
},
|
|
359
|
+
getLogs: {
|
|
360
|
+
v1: implement(contract.deployments.getLogs.v1).handler(async ({ input }) => {
|
|
361
|
+
const deployment = this.mockData.deployments.get(input.deploymentId);
|
|
362
|
+
if (!deployment) {
|
|
363
|
+
throw new ORPCError("NOT_FOUND", { message: "Deployment not found" });
|
|
364
|
+
}
|
|
365
|
+
return {
|
|
366
|
+
logs: [{ timestamp: new Date(), content: "Mock log entry" }],
|
|
367
|
+
hasMoreLogs: false,
|
|
368
|
+
};
|
|
369
|
+
}),
|
|
370
|
+
},
|
|
248
371
|
uploadArtifact: {
|
|
249
372
|
v1: implement(contract.deployments.uploadArtifact.v1).handler(async () => {
|
|
250
373
|
const token = randomUUID();
|
|
251
|
-
const baseUrl = `
|
|
374
|
+
const baseUrl = `https://127.0.0.1:${this.port}`;
|
|
252
375
|
const uploadUrl = `${baseUrl}/__mock__upload/${token}`;
|
|
253
376
|
return {
|
|
254
377
|
uploadUrl,
|
|
@@ -320,6 +443,8 @@ export class MockApiServer {
|
|
|
320
443
|
getLastCall(method, pathPattern) {
|
|
321
444
|
for (let i = this.callHistory.length - 1; i >= 0; i--) {
|
|
322
445
|
const call = this.callHistory[i];
|
|
446
|
+
if (!call)
|
|
447
|
+
continue;
|
|
323
448
|
if (method && call.method !== method)
|
|
324
449
|
continue;
|
|
325
450
|
if (pathPattern) {
|