alpic 0.0.0-dev.fc2d21b → 0.0.0-dev.fc7e119

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