alpic 0.0.0-dev.f2f58a6 → 0.0.0-dev.f330b89
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 +158 -0
- package/dist/__tests__/auth.e2e.test.js.map +1 -0
- package/dist/__tests__/deploy-flags.e2e.test.d.ts +1 -0
- package/dist/__tests__/deploy-flags.e2e.test.js +111 -0
- package/dist/__tests__/deploy-flags.e2e.test.js.map +1 -0
- package/dist/__tests__/deploy.e2e.test.js +51 -150
- package/dist/__tests__/deploy.e2e.test.js.map +1 -1
- package/dist/__tests__/deployment-inspect.e2e.test.d.ts +1 -0
- package/dist/__tests__/deployment-inspect.e2e.test.js +113 -0
- package/dist/__tests__/deployment-inspect.e2e.test.js.map +1 -0
- package/dist/__tests__/deployment-list.e2e.test.d.ts +1 -0
- package/dist/__tests__/deployment-list.e2e.test.js +116 -0
- package/dist/__tests__/deployment-list.e2e.test.js.map +1 -0
- package/dist/__tests__/deployment-logs.e2e.test.d.ts +1 -0
- package/dist/__tests__/deployment-logs.e2e.test.js +255 -0
- package/dist/__tests__/deployment-logs.e2e.test.js.map +1 -0
- package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.d.ts +1 -0
- package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.js +260 -0
- package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.js.map +1 -0
- package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.d.ts +1 -0
- package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.js +140 -0
- package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.js.map +1 -0
- package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.d.ts +1 -0
- package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.js +151 -0
- package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.js.map +1 -0
- package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.d.ts +1 -0
- package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.js +343 -0
- package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.js.map +1 -0
- package/dist/__tests__/environment-variable/environment-variable-validation.test.d.ts +1 -0
- package/dist/__tests__/environment-variable/environment-variable-validation.test.js +20 -0
- package/dist/__tests__/environment-variable/environment-variable-validation.test.js.map +1 -0
- package/dist/__tests__/fixtures/demo-project/index.js +1 -1
- package/dist/__tests__/fixtures/demo-project/index.js.map +1 -1
- package/dist/__tests__/git-flags.e2e.test.d.ts +1 -0
- package/dist/__tests__/git-flags.e2e.test.js +124 -0
- package/dist/__tests__/git-flags.e2e.test.js.map +1 -0
- package/dist/__tests__/git.e2e.test.d.ts +1 -0
- package/dist/__tests__/git.e2e.test.js +221 -0
- package/dist/__tests__/git.e2e.test.js.map +1 -0
- package/dist/__tests__/logs.e2e.test.d.ts +1 -0
- package/dist/__tests__/logs.e2e.test.js +227 -0
- package/dist/__tests__/logs.e2e.test.js.map +1 -0
- package/dist/__tests__/mock-server.d.ts +16 -0
- package/dist/__tests__/mock-server.js +440 -25
- package/dist/__tests__/mock-server.js.map +1 -1
- package/dist/__tests__/publish.e2e.test.d.ts +1 -0
- package/dist/__tests__/publish.e2e.test.js +505 -0
- package/dist/__tests__/publish.e2e.test.js.map +1 -0
- package/dist/__tests__/tunnel.e2e.test.d.ts +1 -0
- package/dist/__tests__/tunnel.e2e.test.js +64 -0
- package/dist/__tests__/tunnel.e2e.test.js.map +1 -0
- package/dist/__tests__/utils.d.ts +44 -1
- package/dist/__tests__/utils.js +195 -11
- package/dist/__tests__/utils.js.map +1 -1
- package/dist/api.d.ts +1 -2
- package/dist/api.js +6 -10
- package/dist/api.js.map +1 -1
- package/dist/commands/deploy.d.ts +7 -4
- package/dist/commands/deploy.js +47 -28
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/deployment/inspect.d.ts +11 -0
- package/dist/commands/deployment/inspect.js +91 -0
- package/dist/commands/deployment/inspect.js.map +1 -0
- package/dist/commands/deployment/list.d.ts +11 -0
- package/dist/commands/deployment/list.js +97 -0
- package/dist/commands/deployment/list.js.map +1 -0
- package/dist/commands/deployment/logs.d.ts +12 -0
- package/dist/commands/deployment/logs.js +50 -0
- package/dist/commands/deployment/logs.js.map +1 -0
- package/dist/commands/environment-variable/add.d.ts +14 -0
- package/dist/commands/environment-variable/add.js +46 -0
- package/dist/commands/environment-variable/add.js.map +1 -0
- package/dist/commands/environment-variable/list.d.ts +9 -0
- package/dist/commands/environment-variable/list.js +44 -0
- package/dist/commands/environment-variable/list.js.map +1 -0
- package/dist/commands/environment-variable/remove.d.ts +11 -0
- package/dist/commands/environment-variable/remove.js +32 -0
- package/dist/commands/environment-variable/remove.js.map +1 -0
- package/dist/commands/environment-variable/update.d.ts +13 -0
- package/dist/commands/environment-variable/update.js +40 -0
- package/dist/commands/environment-variable/update.js.map +1 -0
- package/dist/commands/git/connect.d.ts +10 -0
- package/dist/commands/git/connect.js +60 -0
- package/dist/commands/git/connect.js.map +1 -0
- package/dist/commands/git/disconnect.d.ts +9 -0
- package/dist/commands/git/disconnect.js +45 -0
- package/dist/commands/git/disconnect.js.map +1 -0
- package/dist/commands/git.d.ts +6 -0
- package/dist/commands/git.js +17 -0
- package/dist/commands/git.js.map +1 -0
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.js +34 -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/logs.d.ts +16 -0
- package/dist/commands/logs.js +96 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/publish.d.ts +15 -0
- package/dist/commands/publish.js +51 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/tunnel.d.ts +9 -0
- package/dist/commands/tunnel.js +53 -0
- package/dist/commands/tunnel.js.map +1 -0
- package/dist/commands/whoami.d.ts +6 -0
- package/dist/commands/whoami.js +13 -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 +6 -0
- package/dist/lib/alpic-command.js +27 -0
- package/dist/lib/alpic-command.js.map +1 -0
- package/dist/lib/archive.d.ts +3 -3
- package/dist/lib/archive.js +11 -15
- package/dist/lib/archive.js.map +1 -1
- 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 +28 -0
- package/dist/lib/auth/oauth/client.js +110 -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/assets/alpic-mountain.png +0 -0
- package/dist/lib/auth/oauth/server/assets/authorize.html +195 -0
- package/dist/lib/auth/oauth/server/assets/callback.html +88 -0
- package/dist/lib/auth/oauth/server/index.d.ts +8 -0
- package/dist/lib/auth/oauth/server/index.js +105 -0
- package/dist/lib/auth/oauth/server/index.js.map +1 -0
- package/dist/lib/auth/whoami.d.ts +1 -0
- package/dist/lib/auth/whoami.js +41 -0
- package/dist/lib/auth/whoami.js.map +1 -0
- package/dist/lib/base-workflow.d.ts +10 -0
- package/dist/lib/base-workflow.js +22 -0
- package/dist/lib/base-workflow.js.map +1 -0
- package/dist/lib/config.d.ts +2 -2
- package/dist/lib/config.js +7 -7
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/deployment.d.ts +70 -3
- package/dist/lib/deployment.js +121 -10
- package/dist/lib/deployment.js.map +1 -1
- package/dist/lib/environment-variable.d.ts +41 -0
- package/dist/lib/environment-variable.js +311 -0
- package/dist/lib/environment-variable.js.map +1 -0
- package/dist/lib/git.d.ts +22 -0
- package/dist/lib/git.js +131 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/global-store.d.ts +28 -0
- package/dist/lib/global-store.js +76 -0
- package/dist/lib/global-store.js.map +1 -0
- package/dist/lib/logs.d.ts +20 -0
- package/dist/lib/logs.js +86 -0
- package/dist/lib/logs.js.map +1 -0
- package/dist/lib/project.d.ts +68 -61
- package/dist/lib/project.js +275 -250
- package/dist/lib/project.js.map +1 -1
- package/dist/lib/publish.d.ts +22 -0
- package/dist/lib/publish.js +188 -0
- package/dist/lib/publish.js.map +1 -0
- package/dist/lib/table.d.ts +8 -0
- package/dist/lib/table.js +27 -0
- package/dist/lib/table.js.map +1 -0
- package/dist/lib/telemetry.js +7 -7
- package/dist/lib/telemetry.js.map +1 -1
- package/dist/lib/utils.d.ts +4 -0
- package/dist/lib/utils.js +45 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/utils.test.d.ts +1 -0
- package/dist/lib/utils.test.js +27 -0
- package/dist/lib/utils.test.js.map +1 -0
- package/package.json +35 -31
- 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,8 +1,23 @@
|
|
|
1
|
-
import { OpenAPIHandler } from "@orpc/openapi/node";
|
|
2
|
-
import { ORPCError, implement } from "@orpc/server";
|
|
3
|
-
import express, {} from "express";
|
|
4
1
|
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import * as https from "node:https";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
5
6
|
import { contract } from "@alpic-ai/api";
|
|
7
|
+
import { OpenAPIHandler } from "@orpc/openapi/node";
|
|
8
|
+
import { implement, ORPCError } from "@orpc/server";
|
|
9
|
+
import express, {} from "express";
|
|
10
|
+
import { inc as semverInc } from "semver";
|
|
11
|
+
const __testDirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const FIXTURE_CERT_PATH = join(__testDirname, "fixtures", "certs", "localhost-cert.pem");
|
|
13
|
+
const FIXTURE_KEY_PATH = join(__testDirname, "fixtures", "certs", "localhost-key.pem");
|
|
14
|
+
function getTlsAssets() {
|
|
15
|
+
return {
|
|
16
|
+
key: readFileSync(FIXTURE_KEY_PATH, "utf8"),
|
|
17
|
+
cert: readFileSync(FIXTURE_CERT_PATH, "utf8"),
|
|
18
|
+
certPath: FIXTURE_CERT_PATH,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
6
21
|
export class MockApiServer {
|
|
7
22
|
server = null;
|
|
8
23
|
app;
|
|
@@ -10,12 +25,17 @@ export class MockApiServer {
|
|
|
10
25
|
mockData;
|
|
11
26
|
callHistory = [];
|
|
12
27
|
constructor() {
|
|
13
|
-
this.port;
|
|
14
28
|
this.app = express();
|
|
15
29
|
this.mockData = {
|
|
16
30
|
projects: new Map(),
|
|
17
31
|
environments: new Map(),
|
|
18
32
|
deployments: new Map(),
|
|
33
|
+
environmentVariables: new Map(),
|
|
34
|
+
runtimeLogs: new Map(),
|
|
35
|
+
runtimeLogPages: new Map(),
|
|
36
|
+
deploymentLogPages: new Map(),
|
|
37
|
+
deploymentLogCallCounts: new Map(),
|
|
38
|
+
publishedServers: new Map(),
|
|
19
39
|
};
|
|
20
40
|
}
|
|
21
41
|
async start() {
|
|
@@ -23,11 +43,17 @@ export class MockApiServer {
|
|
|
23
43
|
throw new Error("Server is already running");
|
|
24
44
|
}
|
|
25
45
|
this.configureServer();
|
|
46
|
+
const tlsAssets = getTlsAssets();
|
|
47
|
+
process.env.NODE_EXTRA_CA_CERTS = tlsAssets.certPath;
|
|
48
|
+
const httpsOptions = { key: tlsAssets.key, cert: tlsAssets.cert };
|
|
26
49
|
return new Promise((resolve) => {
|
|
27
|
-
this.server = this.app.listen(0, "127.0.0.1", () => {
|
|
50
|
+
this.server = https.createServer(httpsOptions, this.app).listen(0, "127.0.0.1", () => {
|
|
51
|
+
if (!this.server) {
|
|
52
|
+
throw new Error("Server is not running");
|
|
53
|
+
}
|
|
28
54
|
const address = this.server.address();
|
|
29
55
|
this.port = address.port;
|
|
30
|
-
const url = `
|
|
56
|
+
const url = `https://127.0.0.1:${this.port}`;
|
|
31
57
|
resolve(url);
|
|
32
58
|
});
|
|
33
59
|
});
|
|
@@ -45,7 +71,99 @@ export class MockApiServer {
|
|
|
45
71
|
res.status(200).end();
|
|
46
72
|
});
|
|
47
73
|
this.app.use(express.json());
|
|
48
|
-
|
|
74
|
+
this.app.get("/.well-known/oauth-protected-resource", (_req, res) => {
|
|
75
|
+
const base = `https://127.0.0.1:${this.port}`;
|
|
76
|
+
res.status(200).json({
|
|
77
|
+
resource: "https://api.alpic.ai",
|
|
78
|
+
authorization_servers: [base],
|
|
79
|
+
bearer_methods_supported: ["header"],
|
|
80
|
+
scopes_supported: ["openid", "email", "profile"],
|
|
81
|
+
resource_documentation: "https://docs.alpic.ai",
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
this.app.get("/.well-known/openid-configuration", (_req, res) => {
|
|
85
|
+
const base = `https://127.0.0.1:${this.port}`;
|
|
86
|
+
res.status(200).json({
|
|
87
|
+
issuer: base,
|
|
88
|
+
userinfo_endpoint: `${base}/oauth2/userInfo`,
|
|
89
|
+
authorization_endpoint: `${base}/oauth2/authorize`,
|
|
90
|
+
token_endpoint: `${base}/oauth2/token`,
|
|
91
|
+
jwks_uri: `${base}/.well-known/jwks.json`,
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
this.app.get("/oauth2/userInfo", (req, res) => {
|
|
95
|
+
const auth = req.headers.authorization;
|
|
96
|
+
if (!auth?.startsWith("Bearer ")) {
|
|
97
|
+
res.status(401).json({ error: "Missing or invalid Authorization" });
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
res.status(200).json({
|
|
101
|
+
sub: "test-sub",
|
|
102
|
+
email_verified: "true",
|
|
103
|
+
identities: [],
|
|
104
|
+
name: "Test User",
|
|
105
|
+
email: "test@example.com",
|
|
106
|
+
picture: "",
|
|
107
|
+
username: "testuser",
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
const router = implement(contract).router({
|
|
111
|
+
tunnels: {
|
|
112
|
+
getTicket: {
|
|
113
|
+
v1: implement(contract.tunnels.getTicket.v1).handler(async () => {
|
|
114
|
+
return {
|
|
115
|
+
subdomain: "cool-mongoose-123",
|
|
116
|
+
ticket: "mock-ticket",
|
|
117
|
+
tunnelHost: "tunnel.alpic.dev",
|
|
118
|
+
};
|
|
119
|
+
}),
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
teams: {
|
|
123
|
+
list: {
|
|
124
|
+
v1: implement(contract.teams.list.v1).handler(async () => {
|
|
125
|
+
return [
|
|
126
|
+
{
|
|
127
|
+
id: "mock-team-id",
|
|
128
|
+
name: "Mock Team",
|
|
129
|
+
createdAt: new Date(),
|
|
130
|
+
hasStripeAccount: false,
|
|
131
|
+
},
|
|
132
|
+
];
|
|
133
|
+
}),
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
analytics: {
|
|
137
|
+
get: {
|
|
138
|
+
v1: implement(contract.analytics.get.v1).handler(async ({ input }) => {
|
|
139
|
+
const project = this.mockData.projects.get(input.projectId);
|
|
140
|
+
if (!project) {
|
|
141
|
+
throw new ORPCError("NOT_FOUND", {
|
|
142
|
+
message: "Project not found",
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
const emptyTimeSeries = {
|
|
146
|
+
sessions_count: [],
|
|
147
|
+
requests_count: [],
|
|
148
|
+
requests_latency_mean: [],
|
|
149
|
+
tool_errors: [],
|
|
150
|
+
mcp_errors: [],
|
|
151
|
+
output_token_mean: [],
|
|
152
|
+
task_count: [],
|
|
153
|
+
};
|
|
154
|
+
return {
|
|
155
|
+
metadata: {
|
|
156
|
+
startTimestamp: input.startTimestamp,
|
|
157
|
+
endTimestamp: input.endTimestamp,
|
|
158
|
+
timeZone: input.timeZone,
|
|
159
|
+
startDate: new Date(input.startTimestamp),
|
|
160
|
+
interval: "1h",
|
|
161
|
+
},
|
|
162
|
+
timeSeries: emptyTimeSeries,
|
|
163
|
+
};
|
|
164
|
+
}),
|
|
165
|
+
},
|
|
166
|
+
},
|
|
49
167
|
projects: {
|
|
50
168
|
list: {
|
|
51
169
|
v1: implement(contract.projects.list.v1).handler(async () => {
|
|
@@ -71,7 +189,9 @@ export class MockApiServer {
|
|
|
71
189
|
v1: implement(contract.projects.get.v1).handler(async ({ input }) => {
|
|
72
190
|
const project = this.mockData.projects.get(input.projectId);
|
|
73
191
|
if (!project) {
|
|
74
|
-
throw new ORPCError("NOT_FOUND", {
|
|
192
|
+
throw new ORPCError("NOT_FOUND", {
|
|
193
|
+
message: "Project not found",
|
|
194
|
+
});
|
|
75
195
|
}
|
|
76
196
|
return project;
|
|
77
197
|
}),
|
|
@@ -117,6 +237,7 @@ export class MockApiServer {
|
|
|
117
237
|
id: productionEnvId,
|
|
118
238
|
name: productionEnvName,
|
|
119
239
|
mcpServerUrl: `https://mcp-${projectId}.alpic.ai`,
|
|
240
|
+
domains: [],
|
|
120
241
|
latestDeployment: null,
|
|
121
242
|
},
|
|
122
243
|
environments: [
|
|
@@ -135,27 +256,129 @@ export class MockApiServer {
|
|
|
135
256
|
return project;
|
|
136
257
|
}),
|
|
137
258
|
},
|
|
259
|
+
update: {
|
|
260
|
+
v1: implement(contract.projects.update.v1).handler(async ({ input }) => {
|
|
261
|
+
const project = this.mockData.projects.get(input.projectId);
|
|
262
|
+
if (!project) {
|
|
263
|
+
throw new ORPCError("NOT_FOUND", {
|
|
264
|
+
message: "Project not found",
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
if (input.sourceRepository !== undefined) {
|
|
268
|
+
project.sourceRepository = input.sourceRepository;
|
|
269
|
+
}
|
|
270
|
+
this.mockData.projects.set(input.projectId, project);
|
|
271
|
+
return project;
|
|
272
|
+
}),
|
|
273
|
+
},
|
|
274
|
+
delete: {
|
|
275
|
+
v1: implement(contract.projects.delete.v1).handler(async ({ input }) => {
|
|
276
|
+
const project = this.mockData.projects.get(input.projectId);
|
|
277
|
+
if (!project) {
|
|
278
|
+
throw new ORPCError("NOT_FOUND", {
|
|
279
|
+
message: "Project not found",
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
this.mockData.projects.delete(input.projectId);
|
|
283
|
+
return { success: true };
|
|
284
|
+
}),
|
|
285
|
+
},
|
|
138
286
|
},
|
|
139
287
|
environments: {
|
|
288
|
+
create: {
|
|
289
|
+
v1: implement(contract.environments.create.v1).handler(async ({ input }) => {
|
|
290
|
+
const project = this.mockData.projects.get(input.projectId);
|
|
291
|
+
if (!project) {
|
|
292
|
+
throw new ORPCError("NOT_FOUND", {
|
|
293
|
+
message: "Project not found",
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
const environmentId = randomUUID();
|
|
297
|
+
const mcpServerUrl = `https://mcp-${environmentId}.alpic.ai`;
|
|
298
|
+
const createdAt = new Date();
|
|
299
|
+
const environment = {
|
|
300
|
+
id: environmentId,
|
|
301
|
+
name: input.name,
|
|
302
|
+
sourceBranch: input.sourceBranch,
|
|
303
|
+
mcpServerUrl,
|
|
304
|
+
domains: [mcpServerUrl],
|
|
305
|
+
createdAt,
|
|
306
|
+
projectId: input.projectId,
|
|
307
|
+
};
|
|
308
|
+
this.mockData.environments.set(environmentId, environment);
|
|
309
|
+
this.mockData.projects.set(input.projectId, {
|
|
310
|
+
...project,
|
|
311
|
+
environments: [
|
|
312
|
+
...project.environments,
|
|
313
|
+
{
|
|
314
|
+
id: environmentId,
|
|
315
|
+
name: input.name,
|
|
316
|
+
sourceBranch: input.sourceBranch,
|
|
317
|
+
mcpServerUrl,
|
|
318
|
+
createdAt,
|
|
319
|
+
projectId: input.projectId,
|
|
320
|
+
latestDeployment: null,
|
|
321
|
+
},
|
|
322
|
+
],
|
|
323
|
+
});
|
|
324
|
+
return {
|
|
325
|
+
id: environmentId,
|
|
326
|
+
name: input.name,
|
|
327
|
+
sourceBranch: input.sourceBranch,
|
|
328
|
+
createdAt,
|
|
329
|
+
projectId: input.projectId,
|
|
330
|
+
urls: [mcpServerUrl],
|
|
331
|
+
};
|
|
332
|
+
}),
|
|
333
|
+
},
|
|
140
334
|
get: {
|
|
141
335
|
v1: implement(contract.environments.get.v1).handler(async ({ input }) => {
|
|
142
336
|
const environment = this.mockData.environments.get(input.environmentId);
|
|
143
337
|
if (!environment) {
|
|
144
|
-
throw new ORPCError("NOT_FOUND", {
|
|
338
|
+
throw new ORPCError("NOT_FOUND", {
|
|
339
|
+
message: "Environment not found",
|
|
340
|
+
});
|
|
145
341
|
}
|
|
146
342
|
return environment;
|
|
147
343
|
}),
|
|
148
344
|
},
|
|
345
|
+
getLogs: {
|
|
346
|
+
v1: implement(contract.environments.getLogs.v1).handler(async ({ input }) => {
|
|
347
|
+
const environment = this.mockData.environments.get(input.environmentId);
|
|
348
|
+
if (!environment) {
|
|
349
|
+
throw new ORPCError("NOT_FOUND", {
|
|
350
|
+
message: "Environment not found",
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
const pagedLogs = this.mockData.runtimeLogPages.get(input.environmentId);
|
|
354
|
+
const pageIndex = input.nextToken === undefined ? 0 : Number.parseInt(input.nextToken, 10);
|
|
355
|
+
const allLogs = pagedLogs === undefined
|
|
356
|
+
? (this.mockData.runtimeLogs.get(input.environmentId) ?? [])
|
|
357
|
+
: (pagedLogs[pageIndex] ?? []);
|
|
358
|
+
let logs = allLogs;
|
|
359
|
+
if (input.level !== undefined) {
|
|
360
|
+
const levels = input.level;
|
|
361
|
+
logs = allLogs.filter((log) => levels.includes(log.type));
|
|
362
|
+
}
|
|
363
|
+
const nextToken = pagedLogs === undefined || pageIndex + 1 >= pagedLogs.length ? null : String(pageIndex + 1);
|
|
364
|
+
return { logs, nextToken };
|
|
365
|
+
}),
|
|
366
|
+
},
|
|
149
367
|
deploy: {
|
|
150
368
|
v1: implement(contract.environments.deploy.v1).handler(async ({ input }) => {
|
|
151
369
|
const environment = this.mockData.environments.get(input.environmentId);
|
|
152
370
|
if (!environment) {
|
|
153
|
-
throw new ORPCError("NOT_FOUND", {
|
|
371
|
+
throw new ORPCError("NOT_FOUND", {
|
|
372
|
+
message: "Environment not found",
|
|
373
|
+
});
|
|
154
374
|
}
|
|
155
375
|
const deploymentId = randomUUID();
|
|
156
376
|
const deployment = {
|
|
157
377
|
id: deploymentId,
|
|
158
378
|
status: "ongoing",
|
|
379
|
+
environmentId: environment.id,
|
|
380
|
+
environmentName: environment.name,
|
|
381
|
+
isCurrent: false,
|
|
159
382
|
sourceRef: environment.sourceBranch,
|
|
160
383
|
sourceCommitId: randomUUID().slice(0, 7),
|
|
161
384
|
sourceCommitMessage: "Mock deployment",
|
|
@@ -163,38 +386,197 @@ export class MockApiServer {
|
|
|
163
386
|
authorAvatarUrl: null,
|
|
164
387
|
startedAt: new Date(),
|
|
165
388
|
completedAt: null,
|
|
389
|
+
deploymentPageUrl: "https://app.alpic.ai/deployments/mock",
|
|
166
390
|
};
|
|
167
391
|
this.mockData.deployments.set(deploymentId, deployment);
|
|
168
392
|
return deployment;
|
|
169
393
|
}),
|
|
170
394
|
},
|
|
171
395
|
},
|
|
396
|
+
environmentVariables: {
|
|
397
|
+
list: {
|
|
398
|
+
v1: implement(contract.environmentVariables.list.v1).handler(async ({ input }) => {
|
|
399
|
+
const environment = this.mockData.environments.get(input.environmentId);
|
|
400
|
+
if (!environment) {
|
|
401
|
+
throw new ORPCError("NOT_FOUND", {
|
|
402
|
+
message: "Environment not found",
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
return this.mockData.environmentVariables.get(input.environmentId) ?? [];
|
|
406
|
+
}),
|
|
407
|
+
},
|
|
408
|
+
create: {
|
|
409
|
+
v1: implement(contract.environmentVariables.create.v1).handler(async ({ input }) => {
|
|
410
|
+
const environment = this.mockData.environments.get(input.environmentId);
|
|
411
|
+
if (!environment) {
|
|
412
|
+
throw new ORPCError("NOT_FOUND", {
|
|
413
|
+
message: "Environment not found",
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
const existing = this.mockData.environmentVariables.get(input.environmentId) ?? [];
|
|
417
|
+
const newVars = input.environmentVariables.map((variable) => ({
|
|
418
|
+
id: randomUUID(),
|
|
419
|
+
key: variable.key,
|
|
420
|
+
value: variable.value,
|
|
421
|
+
isSecret: variable.isSecret,
|
|
422
|
+
createdAt: new Date(),
|
|
423
|
+
}));
|
|
424
|
+
for (const newVar of newVars) {
|
|
425
|
+
if (existing.some((existingVar) => existingVar.key === newVar.key)) {
|
|
426
|
+
throw new ORPCError("BAD_REQUEST", {
|
|
427
|
+
message: `Environment variable "${newVar.key}" already exists`,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
this.mockData.environmentVariables.set(input.environmentId, [...existing, ...newVars]);
|
|
432
|
+
return { success: true };
|
|
433
|
+
}),
|
|
434
|
+
},
|
|
435
|
+
update: {
|
|
436
|
+
v1: implement(contract.environmentVariables.update.v1).handler(async ({ input }) => {
|
|
437
|
+
for (const [environmentId, variables] of this.mockData.environmentVariables.entries()) {
|
|
438
|
+
const index = variables.findIndex((variable) => variable.id === input.environmentVariableId);
|
|
439
|
+
if (index !== -1) {
|
|
440
|
+
const updated = variables.map((variable, i) => i === index
|
|
441
|
+
? {
|
|
442
|
+
...variable,
|
|
443
|
+
key: input.key,
|
|
444
|
+
value: input.value ?? variable.value,
|
|
445
|
+
isSecret: input.isSecret,
|
|
446
|
+
}
|
|
447
|
+
: variable);
|
|
448
|
+
this.mockData.environmentVariables.set(environmentId, updated);
|
|
449
|
+
return { success: true };
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
throw new ORPCError("NOT_FOUND", {
|
|
453
|
+
message: "Environment variable not found",
|
|
454
|
+
});
|
|
455
|
+
}),
|
|
456
|
+
},
|
|
457
|
+
delete: {
|
|
458
|
+
v1: implement(contract.environmentVariables.delete.v1).handler(async ({ input }) => {
|
|
459
|
+
for (const [environmentId, variables] of this.mockData.environmentVariables.entries()) {
|
|
460
|
+
const index = variables.findIndex((variable) => variable.id === input.environmentVariableId);
|
|
461
|
+
if (index !== -1) {
|
|
462
|
+
this.mockData.environmentVariables.set(environmentId, variables.filter((_, i) => i !== index));
|
|
463
|
+
return { success: true };
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
throw new ORPCError("NOT_FOUND", {
|
|
467
|
+
message: "Environment variable not found",
|
|
468
|
+
});
|
|
469
|
+
}),
|
|
470
|
+
},
|
|
471
|
+
},
|
|
472
|
+
distribution: {
|
|
473
|
+
info: {
|
|
474
|
+
v1: implement(contract.distribution.info.v1).handler(async ({ input }) => {
|
|
475
|
+
const existing = this.mockData.publishedServers.get(`${input.projectId}:${input.domain}`);
|
|
476
|
+
return {
|
|
477
|
+
serverFields: existing ?? {
|
|
478
|
+
$schema: "https://registry.modelcontextprotocol.io/schemas/1.0/server.json",
|
|
479
|
+
name: "",
|
|
480
|
+
description: "",
|
|
481
|
+
},
|
|
482
|
+
};
|
|
483
|
+
}),
|
|
484
|
+
},
|
|
485
|
+
publish: {
|
|
486
|
+
v1: implement(contract.distribution.publish.v1).handler(async ({ input }) => {
|
|
487
|
+
const project = this.mockData.projects.get(input.projectId);
|
|
488
|
+
if (!project) {
|
|
489
|
+
throw new ORPCError("NOT_FOUND", {
|
|
490
|
+
message: "Project not found",
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
const key = `${input.projectId}:${input.domain}`;
|
|
494
|
+
const existing = this.mockData.publishedServers.get(key);
|
|
495
|
+
const version = existing?.version ? (semverInc(existing.version, "patch") ?? "0.0.1") : "0.0.1";
|
|
496
|
+
const serverFields = {
|
|
497
|
+
$schema: "https://registry.modelcontextprotocol.io/schemas/1.0/server.json",
|
|
498
|
+
name: input.domain,
|
|
499
|
+
description: input.description,
|
|
500
|
+
title: input.title,
|
|
501
|
+
version,
|
|
502
|
+
...(input.websiteUrl ? { websiteUrl: input.websiteUrl } : {}),
|
|
503
|
+
...(input.iconSrc ? { icons: [{ src: input.iconSrc }] } : {}),
|
|
504
|
+
};
|
|
505
|
+
if (!input.dryRun) {
|
|
506
|
+
this.mockData.publishedServers.set(key, serverFields);
|
|
507
|
+
}
|
|
508
|
+
return { serverFields };
|
|
509
|
+
}),
|
|
510
|
+
},
|
|
511
|
+
},
|
|
172
512
|
deployments: {
|
|
513
|
+
list: {
|
|
514
|
+
v1: implement(contract.deployments.list.v1).handler(async ({ input }) => {
|
|
515
|
+
const project = this.mockData.projects.get(input.projectId);
|
|
516
|
+
if (!project) {
|
|
517
|
+
throw new ORPCError("NOT_FOUND", {
|
|
518
|
+
message: "Project not found",
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
let deployments = Array.from(this.mockData.deployments.values());
|
|
522
|
+
if (input.environmentId) {
|
|
523
|
+
deployments = deployments.filter((deployment) => deployment.environmentId === input.environmentId);
|
|
524
|
+
}
|
|
525
|
+
if (input.status?.length) {
|
|
526
|
+
deployments = deployments.filter((deployment) => input.status.includes(deployment.status));
|
|
527
|
+
}
|
|
528
|
+
return deployments.map((deployment) => ({
|
|
529
|
+
...deployment,
|
|
530
|
+
isCurrent: deployment.status === "deployed",
|
|
531
|
+
}));
|
|
532
|
+
}),
|
|
533
|
+
},
|
|
173
534
|
get: {
|
|
174
535
|
v1: implement(contract.deployments.get.v1).handler(async ({ input }) => {
|
|
175
536
|
const deployment = this.mockData.deployments.get(input.deploymentId);
|
|
176
537
|
if (!deployment) {
|
|
177
|
-
throw new ORPCError("NOT_FOUND", {
|
|
538
|
+
throw new ORPCError("NOT_FOUND", {
|
|
539
|
+
message: "Deployment not found",
|
|
540
|
+
});
|
|
178
541
|
}
|
|
179
|
-
if (deployment.status === "ongoing"
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
return updatedDeployment;
|
|
189
|
-
}
|
|
542
|
+
if (deployment.status === "ongoing") {
|
|
543
|
+
const updatedDeployment = {
|
|
544
|
+
...deployment,
|
|
545
|
+
status: "deployed",
|
|
546
|
+
completedAt: new Date(),
|
|
547
|
+
deploymentPageUrl: deployment.deploymentPageUrl ?? null,
|
|
548
|
+
};
|
|
549
|
+
this.mockData.deployments.set(input.deploymentId, updatedDeployment);
|
|
550
|
+
return updatedDeployment;
|
|
190
551
|
}
|
|
191
552
|
return deployment;
|
|
192
553
|
}),
|
|
193
554
|
},
|
|
555
|
+
getLogs: {
|
|
556
|
+
v1: implement(contract.deployments.getLogs.v1).handler(async ({ input }) => {
|
|
557
|
+
const deployment = this.mockData.deployments.get(input.deploymentId);
|
|
558
|
+
if (!deployment) {
|
|
559
|
+
throw new ORPCError("NOT_FOUND", {
|
|
560
|
+
message: "Deployment not found",
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
const pages = this.mockData.deploymentLogPages.get(input.deploymentId);
|
|
564
|
+
if (pages !== undefined) {
|
|
565
|
+
const callCount = this.mockData.deploymentLogCallCounts.get(input.deploymentId) ?? 0;
|
|
566
|
+
const pageIndex = Math.min(callCount, pages.length - 1);
|
|
567
|
+
this.mockData.deploymentLogCallCounts.set(input.deploymentId, callCount + 1);
|
|
568
|
+
return pages[pageIndex] ?? { logs: [], hasMoreLogs: false };
|
|
569
|
+
}
|
|
570
|
+
return {
|
|
571
|
+
logs: [{ timestamp: new Date(), content: "Mock log entry" }],
|
|
572
|
+
hasMoreLogs: false,
|
|
573
|
+
};
|
|
574
|
+
}),
|
|
575
|
+
},
|
|
194
576
|
uploadArtifact: {
|
|
195
577
|
v1: implement(contract.deployments.uploadArtifact.v1).handler(async () => {
|
|
196
578
|
const token = randomUUID();
|
|
197
|
-
const baseUrl = `
|
|
579
|
+
const baseUrl = `https://127.0.0.1:${this.port}`;
|
|
198
580
|
const uploadUrl = `${baseUrl}/__mock__upload/${token}`;
|
|
199
581
|
return {
|
|
200
582
|
uploadUrl,
|
|
@@ -204,7 +586,7 @@ export class MockApiServer {
|
|
|
204
586
|
}),
|
|
205
587
|
},
|
|
206
588
|
},
|
|
207
|
-
};
|
|
589
|
+
});
|
|
208
590
|
const handler = new OpenAPIHandler(router);
|
|
209
591
|
this.app.use(async (req, res) => {
|
|
210
592
|
const apiCall = {
|
|
@@ -212,7 +594,12 @@ export class MockApiServer {
|
|
|
212
594
|
path: req.path,
|
|
213
595
|
timestamp: new Date(),
|
|
214
596
|
};
|
|
215
|
-
if (req.
|
|
597
|
+
if (req.method === "GET") {
|
|
598
|
+
if (Object.keys(req.query).length > 0) {
|
|
599
|
+
apiCall.input = req.query;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
else if (req.body) {
|
|
216
603
|
apiCall.input = req.body;
|
|
217
604
|
}
|
|
218
605
|
const result = await handler.handle(req, res, {
|
|
@@ -266,6 +653,8 @@ export class MockApiServer {
|
|
|
266
653
|
getLastCall(method, pathPattern) {
|
|
267
654
|
for (let i = this.callHistory.length - 1; i >= 0; i--) {
|
|
268
655
|
const call = this.callHistory[i];
|
|
656
|
+
if (!call)
|
|
657
|
+
continue;
|
|
269
658
|
if (method && call.method !== method)
|
|
270
659
|
continue;
|
|
271
660
|
if (pathPattern) {
|
|
@@ -282,6 +671,32 @@ export class MockApiServer {
|
|
|
282
671
|
}
|
|
283
672
|
return undefined;
|
|
284
673
|
}
|
|
674
|
+
addEnvironmentVariables(environmentId, variables) {
|
|
675
|
+
this.mockData.environmentVariables.set(environmentId, variables);
|
|
676
|
+
}
|
|
677
|
+
setRuntimeLogs(environmentId, logs) {
|
|
678
|
+
this.mockData.runtimeLogs.set(environmentId, logs);
|
|
679
|
+
this.mockData.runtimeLogPages.delete(environmentId);
|
|
680
|
+
}
|
|
681
|
+
setRuntimeLogPages(environmentId, pages) {
|
|
682
|
+
this.mockData.runtimeLogPages.set(environmentId, pages);
|
|
683
|
+
this.mockData.runtimeLogs.delete(environmentId);
|
|
684
|
+
}
|
|
685
|
+
setPublishedServer(projectId, domain, server) {
|
|
686
|
+
this.mockData.publishedServers.set(`${projectId}:${domain}`, server);
|
|
687
|
+
}
|
|
688
|
+
addDeployments(deployments) {
|
|
689
|
+
for (const deployment of deployments) {
|
|
690
|
+
this.mockData.deployments.set(deployment.id, {
|
|
691
|
+
...deployment,
|
|
692
|
+
deploymentPageUrl: null,
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
setDeploymentLogPages(deploymentId, pages) {
|
|
697
|
+
this.mockData.deploymentLogPages.set(deploymentId, pages);
|
|
698
|
+
this.mockData.deploymentLogCallCounts.set(deploymentId, 0);
|
|
699
|
+
}
|
|
285
700
|
addProject(project) {
|
|
286
701
|
this.mockData.projects.set(project.id, project);
|
|
287
702
|
if (project.productionEnvironment) {
|