alpic 0.0.0-dev.f19a8ca → 0.0.0-dev.f1faa63

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 (179) 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.js +37 -54
  8. package/dist/__tests__/deploy.e2e.test.js.map +1 -1
  9. package/dist/__tests__/deployment-inspect.e2e.test.d.ts +1 -0
  10. package/dist/__tests__/deployment-inspect.e2e.test.js +113 -0
  11. package/dist/__tests__/deployment-inspect.e2e.test.js.map +1 -0
  12. package/dist/__tests__/deployment-list.e2e.test.d.ts +1 -0
  13. package/dist/__tests__/deployment-list.e2e.test.js +108 -0
  14. package/dist/__tests__/deployment-list.e2e.test.js.map +1 -0
  15. package/dist/__tests__/deployment-logs.e2e.test.d.ts +1 -0
  16. package/dist/__tests__/deployment-logs.e2e.test.js +180 -0
  17. package/dist/__tests__/deployment-logs.e2e.test.js.map +1 -0
  18. package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.d.ts +1 -0
  19. package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.js +250 -0
  20. package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.js.map +1 -0
  21. package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.d.ts +1 -0
  22. package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.js +122 -0
  23. package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.js.map +1 -0
  24. package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.d.ts +1 -0
  25. package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.js +139 -0
  26. package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.js.map +1 -0
  27. package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.d.ts +1 -0
  28. package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.js +319 -0
  29. package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.js.map +1 -0
  30. package/dist/__tests__/environment-variable/environment-variable-validation.test.d.ts +1 -0
  31. package/dist/__tests__/environment-variable/environment-variable-validation.test.js +20 -0
  32. package/dist/__tests__/environment-variable/environment-variable-validation.test.js.map +1 -0
  33. package/dist/__tests__/fixtures/demo-project/index.js +1 -1
  34. package/dist/__tests__/fixtures/demo-project/index.js.map +1 -1
  35. package/dist/__tests__/git-flags.e2e.test.d.ts +1 -0
  36. package/dist/__tests__/git-flags.e2e.test.js +124 -0
  37. package/dist/__tests__/git-flags.e2e.test.js.map +1 -0
  38. package/dist/__tests__/git.e2e.test.js +57 -16
  39. package/dist/__tests__/git.e2e.test.js.map +1 -1
  40. package/dist/__tests__/logs.e2e.test.d.ts +1 -0
  41. package/dist/__tests__/logs.e2e.test.js +197 -0
  42. package/dist/__tests__/logs.e2e.test.js.map +1 -0
  43. package/dist/__tests__/mock-server.d.ts +16 -0
  44. package/dist/__tests__/mock-server.js +253 -7
  45. package/dist/__tests__/mock-server.js.map +1 -1
  46. package/dist/__tests__/publish.e2e.test.d.ts +1 -0
  47. package/dist/__tests__/publish.e2e.test.js +485 -0
  48. package/dist/__tests__/publish.e2e.test.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 +21 -4
  53. package/dist/__tests__/utils.js +113 -15
  54. package/dist/__tests__/utils.js.map +1 -1
  55. package/dist/api.d.ts +0 -1
  56. package/dist/api.js +5 -9
  57. package/dist/api.js.map +1 -1
  58. package/dist/commands/deploy.d.ts +5 -2
  59. package/dist/commands/deploy.js +37 -23
  60. package/dist/commands/deploy.js.map +1 -1
  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 +3 -2
  83. package/dist/commands/git/connect.js +26 -33
  84. package/dist/commands/git/connect.js.map +1 -1
  85. package/dist/commands/git/disconnect.d.ts +2 -2
  86. package/dist/commands/git/disconnect.js +16 -30
  87. package/dist/commands/git/disconnect.js.map +1 -1
  88. package/dist/commands/git.js +3 -3
  89. package/dist/commands/git.js.map +1 -1
  90. package/dist/commands/login.d.ts +6 -0
  91. package/dist/commands/login.js +34 -0
  92. package/dist/commands/login.js.map +1 -0
  93. package/dist/commands/logout.d.ts +6 -0
  94. package/dist/commands/logout.js +20 -0
  95. package/dist/commands/logout.js.map +1 -0
  96. package/dist/commands/logs.d.ts +16 -0
  97. package/dist/commands/logs.js +96 -0
  98. package/dist/commands/logs.js.map +1 -0
  99. package/dist/commands/publish.d.ts +15 -0
  100. package/dist/commands/publish.js +51 -0
  101. package/dist/commands/publish.js.map +1 -0
  102. package/dist/commands/tunnel.d.ts +9 -0
  103. package/dist/commands/tunnel.js +53 -0
  104. package/dist/commands/tunnel.js.map +1 -0
  105. package/dist/commands/whoami.d.ts +6 -0
  106. package/dist/commands/whoami.js +13 -0
  107. package/dist/commands/whoami.js.map +1 -0
  108. package/dist/env.d.ts +4 -0
  109. package/dist/env.js +10 -0
  110. package/dist/env.js.map +1 -0
  111. package/dist/lib/alpic-command.d.ts +2 -0
  112. package/dist/lib/alpic-command.js +12 -5
  113. package/dist/lib/alpic-command.js.map +1 -1
  114. package/dist/lib/archive.d.ts +3 -3
  115. package/dist/lib/archive.js +11 -15
  116. package/dist/lib/archive.js.map +1 -1
  117. package/dist/lib/auth/auth.d.ts +2 -0
  118. package/dist/lib/auth/auth.js +21 -0
  119. package/dist/lib/auth/auth.js.map +1 -0
  120. package/dist/lib/auth/oauth/client.d.ts +28 -0
  121. package/dist/lib/auth/oauth/client.js +110 -0
  122. package/dist/lib/auth/oauth/client.js.map +1 -0
  123. package/dist/lib/auth/oauth/constants.d.ts +2 -0
  124. package/dist/lib/auth/oauth/constants.js +3 -0
  125. package/dist/lib/auth/oauth/constants.js.map +1 -0
  126. package/dist/lib/auth/oauth/server/assets/alpic-mountain.png +0 -0
  127. package/dist/lib/auth/oauth/server/assets/authorize.html +195 -0
  128. package/dist/lib/auth/oauth/server/assets/callback.html +88 -0
  129. package/dist/lib/auth/oauth/server/index.d.ts +8 -0
  130. package/dist/lib/auth/oauth/server/index.js +102 -0
  131. package/dist/lib/auth/oauth/server/index.js.map +1 -0
  132. package/dist/lib/auth/whoami.d.ts +1 -0
  133. package/dist/lib/auth/whoami.js +41 -0
  134. package/dist/lib/auth/whoami.js.map +1 -0
  135. package/dist/lib/base-workflow.d.ts +10 -0
  136. package/dist/lib/base-workflow.js +22 -0
  137. package/dist/lib/base-workflow.js.map +1 -0
  138. package/dist/lib/config.d.ts +2 -2
  139. package/dist/lib/config.js +7 -7
  140. package/dist/lib/config.js.map +1 -1
  141. package/dist/lib/deployment.d.ts +70 -3
  142. package/dist/lib/deployment.js +113 -8
  143. package/dist/lib/deployment.js.map +1 -1
  144. package/dist/lib/environment-variable.d.ts +41 -0
  145. package/dist/lib/environment-variable.js +304 -0
  146. package/dist/lib/environment-variable.js.map +1 -0
  147. package/dist/lib/git.d.ts +12 -4
  148. package/dist/lib/git.js +51 -26
  149. package/dist/lib/git.js.map +1 -1
  150. package/dist/lib/global-store.d.ts +28 -0
  151. package/dist/lib/global-store.js +76 -0
  152. package/dist/lib/global-store.js.map +1 -0
  153. package/dist/lib/logs.d.ts +20 -0
  154. package/dist/lib/logs.js +86 -0
  155. package/dist/lib/logs.js.map +1 -0
  156. package/dist/lib/project.d.ts +68 -61
  157. package/dist/lib/project.js +273 -252
  158. package/dist/lib/project.js.map +1 -1
  159. package/dist/lib/publish.d.ts +22 -0
  160. package/dist/lib/publish.js +181 -0
  161. package/dist/lib/publish.js.map +1 -0
  162. package/dist/lib/table.d.ts +8 -0
  163. package/dist/lib/table.js +27 -0
  164. package/dist/lib/table.js.map +1 -0
  165. package/dist/lib/telemetry.js +6 -6
  166. package/dist/lib/telemetry.js.map +1 -1
  167. package/dist/lib/utils.d.ts +4 -0
  168. package/dist/lib/utils.js +21 -0
  169. package/dist/lib/utils.js.map +1 -0
  170. package/dist/lib/utils.test.d.ts +1 -0
  171. package/dist/lib/utils.test.js +21 -0
  172. package/dist/lib/utils.test.js.map +1 -0
  173. package/package.json +32 -19
  174. package/dist/lib/auth.d.ts +0 -1
  175. package/dist/lib/auth.js +0 -10
  176. package/dist/lib/auth.js.map +0 -1
  177. package/dist/lib/global-config.d.ts +0 -9
  178. package/dist/lib/global-config.js +0 -48
  179. package/dist/lib/global-config.js.map +0 -1
@@ -0,0 +1,485 @@
1
+ import { rmSync } from "node:fs";
2
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
3
+ import { MockApiServer } from "./mock-server.js";
4
+ import { buildMockProject, cliSession, createConfigFile, expectSuccessfulApiCall, setupTestDirectory, } from "./utils.js";
5
+ const PROJECT_ID = "test-project-id";
6
+ const TEAM_ID = "mock-team-id";
7
+ const ENV_ID = "test-env-id";
8
+ const DOMAIN = "my-server.example.com";
9
+ const SHARED_DOMAIN = `mcp-${PROJECT_ID}.alpic.ai`;
10
+ describe("alpic publish (E2E)", () => {
11
+ let mockServer;
12
+ let serverUrl;
13
+ let cwd;
14
+ let binPath;
15
+ beforeEach(async () => {
16
+ mockServer = new MockApiServer();
17
+ serverUrl = await mockServer.start();
18
+ const setup = await setupTestDirectory();
19
+ cwd = setup.cwd;
20
+ binPath = setup.binPath;
21
+ });
22
+ afterEach(async () => {
23
+ await mockServer.stop();
24
+ if (cwd) {
25
+ rmSync(cwd, { recursive: true, force: true });
26
+ }
27
+ });
28
+ it("publishes interactively with no custom domains — prompts to select the shared domain", async () => {
29
+ mockServer.addProject(buildMockProject({
30
+ projectId: PROJECT_ID,
31
+ teamId: TEAM_ID,
32
+ projectName: "my-server",
33
+ environmentId: ENV_ID,
34
+ environmentName: "production",
35
+ domains: [],
36
+ }));
37
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
38
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "publish"], {
39
+ cwd,
40
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
41
+ }, async (cli) => {
42
+ await cli.expect("Select a domain to publish for");
43
+ await cli.expect(SHARED_DOMAIN);
44
+ await cli.send("");
45
+ await cli.expect("Server title");
46
+ await cli.send("My Server");
47
+ await cli.expect("Server description");
48
+ await cli.send("Does great things");
49
+ await cli.expect("Website URL");
50
+ await cli.send("");
51
+ await cli.expect("Icon URL");
52
+ await cli.send("");
53
+ await cli.expect("Publish to MCP Registry under domain");
54
+ await cli.send("");
55
+ await cli.expect("Registry publication succeeded (v0.0.1)");
56
+ });
57
+ expect(exitCode).toBe(0);
58
+ expect(output).toContain("Registry publication succeeded (v0.0.1)");
59
+ expect(output).toContain("registry.modelcontextprotocol.io/?q=my-server");
60
+ const publishCall = mockServer.getLastCall("POST", "/v1/distribution/publish");
61
+ expectSuccessfulApiCall(publishCall, (call) => {
62
+ expect(call.input).toMatchObject({
63
+ projectId: PROJECT_ID,
64
+ domain: SHARED_DOMAIN,
65
+ title: "My Server",
66
+ description: "Does great things",
67
+ });
68
+ });
69
+ });
70
+ it("prompts to select from shared domain and custom deployed domains", async () => {
71
+ const domain2 = "other.example.com";
72
+ mockServer.addProject(buildMockProject({
73
+ projectId: PROJECT_ID,
74
+ teamId: TEAM_ID,
75
+ projectName: "my-server",
76
+ environmentId: ENV_ID,
77
+ environmentName: "production",
78
+ domains: [
79
+ { domain: DOMAIN, status: "deployed", createdAt: new Date() },
80
+ { domain: domain2, status: "deployed", createdAt: new Date() },
81
+ { domain: "pending.example.com", status: "ongoing", createdAt: new Date() },
82
+ ],
83
+ }));
84
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
85
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "publish"], {
86
+ cwd,
87
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
88
+ }, async (cli) => {
89
+ await cli.expect("Select a domain to publish for");
90
+ await cli.expect(`${SHARED_DOMAIN} (shared)`);
91
+ // Default selection is the first non-shared domain (sorted by length),
92
+ // so move down twice to select the shared domain (last option).
93
+ await cli.send("\x1B[B\x1B[B");
94
+ await cli.send("");
95
+ await cli.expect("Server title");
96
+ await cli.send("My Server");
97
+ await cli.expect("Server description");
98
+ await cli.send("Does great things");
99
+ await cli.expect("Website URL");
100
+ await cli.send("");
101
+ await cli.expect("Icon URL");
102
+ await cli.send("");
103
+ await cli.expect("Publish to MCP Registry under domain");
104
+ await cli.send("");
105
+ await cli.expect("Registry publication succeeded (v0.0.1)");
106
+ });
107
+ expect(exitCode).toBe(0);
108
+ expect(output).toContain("Registry publication succeeded (v0.0.1)");
109
+ const publishCall = mockServer.getLastCall("POST", "/v1/distribution/publish");
110
+ expectSuccessfulApiCall(publishCall, (call) => {
111
+ expect(call.input).toMatchObject({ domain: SHARED_DOMAIN });
112
+ });
113
+ });
114
+ it("publishes with optional websiteUrl and iconSrc", async () => {
115
+ mockServer.addProject(buildMockProject({
116
+ projectId: PROJECT_ID,
117
+ teamId: TEAM_ID,
118
+ projectName: "my-server",
119
+ environmentId: ENV_ID,
120
+ environmentName: "production",
121
+ domains: [{ domain: DOMAIN, status: "deployed", createdAt: new Date() }],
122
+ }));
123
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
124
+ const { exitCode } = await cliSession(process.execPath, [binPath, "publish"], {
125
+ cwd,
126
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
127
+ }, async (cli) => {
128
+ await cli.expect("Select a domain to publish for");
129
+ await cli.send("");
130
+ await cli.expect("Server title");
131
+ await cli.send("My Server");
132
+ await cli.expect("Server description");
133
+ await cli.send("Does great things");
134
+ await cli.expect("Website URL");
135
+ await cli.send("https://my-server.example.com");
136
+ await cli.expect("Icon URL");
137
+ await cli.send("https://my-server.example.com/icon.png");
138
+ await cli.expect("Publish to MCP Registry under domain");
139
+ await cli.send("");
140
+ await cli.expect("Registry publication succeeded (v0.0.1)");
141
+ });
142
+ expect(exitCode).toBe(0);
143
+ const publishCall = mockServer.getLastCall("POST", "/v1/distribution/publish");
144
+ expectSuccessfulApiCall(publishCall, (call) => {
145
+ expect(call.input).toMatchObject({
146
+ websiteUrl: "https://my-server.example.com",
147
+ iconSrc: "https://my-server.example.com/icon.png",
148
+ });
149
+ });
150
+ });
151
+ it("publishes non-interactively with all flags", async () => {
152
+ mockServer.addProject(buildMockProject({
153
+ projectId: PROJECT_ID,
154
+ teamId: TEAM_ID,
155
+ projectName: "my-server",
156
+ environmentId: ENV_ID,
157
+ environmentName: "production",
158
+ domains: [{ domain: DOMAIN, status: "deployed", createdAt: new Date() }],
159
+ }));
160
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
161
+ const { exitCode, output } = await cliSession(process.execPath, [
162
+ binPath,
163
+ "publish",
164
+ "--non-interactive",
165
+ "--domain",
166
+ DOMAIN,
167
+ "--title",
168
+ "My Server",
169
+ "--description",
170
+ "Does things",
171
+ "--website-url",
172
+ "https://example.com",
173
+ "--icon-src",
174
+ "https://example.com/icon.png",
175
+ ], {
176
+ cwd,
177
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
178
+ }, async (cli) => {
179
+ await cli.expect("Registry publication succeeded (v0.0.1)");
180
+ });
181
+ expect(exitCode).toBe(0);
182
+ expect(output).toContain("Registry publication succeeded (v0.0.1)");
183
+ const publishCall = mockServer.getLastCall("POST", "/v1/distribution/publish");
184
+ expectSuccessfulApiCall(publishCall, (call) => {
185
+ expect(call.input).toMatchObject({
186
+ projectId: PROJECT_ID,
187
+ domain: DOMAIN,
188
+ title: "My Server",
189
+ description: "Does things",
190
+ websiteUrl: "https://example.com",
191
+ iconSrc: "https://example.com/icon.png",
192
+ });
193
+ });
194
+ });
195
+ it("errors when no config file is present", async () => {
196
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "publish", "--non-interactive", "--domain", DOMAIN, "--title", "T", "--description", "D"], {
197
+ cwd,
198
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
199
+ });
200
+ expect(exitCode).toBe(1);
201
+ expect(output).toContain("No project specified");
202
+ expect(mockServer.getCalls("POST", "/v1/distribution/publish")).toHaveLength(0);
203
+ });
204
+ it("errors when project has no production environment", async () => {
205
+ const projectWithoutProd = buildMockProject({
206
+ projectId: PROJECT_ID,
207
+ teamId: TEAM_ID,
208
+ projectName: "my-server",
209
+ environmentId: ENV_ID,
210
+ environmentName: "production",
211
+ domains: [],
212
+ });
213
+ mockServer.addProject({ ...projectWithoutProd, productionEnvironment: null });
214
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
215
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "publish", "--non-interactive", "--domain", DOMAIN, "--title", "T", "--description", "D"], {
216
+ cwd,
217
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
218
+ });
219
+ expect(exitCode).toBe(1);
220
+ expect(output).toContain("No production environment found");
221
+ expect(mockServer.getCalls("POST", "/v1/distribution/publish")).toHaveLength(0);
222
+ });
223
+ it("errors non-interactively when --title is missing", async () => {
224
+ mockServer.addProject(buildMockProject({
225
+ projectId: PROJECT_ID,
226
+ teamId: TEAM_ID,
227
+ projectName: "my-server",
228
+ environmentId: ENV_ID,
229
+ environmentName: "production",
230
+ domains: [{ domain: DOMAIN, status: "deployed", createdAt: new Date() }],
231
+ }));
232
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
233
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "publish", "--non-interactive", "--domain", DOMAIN, "--description", "D"], {
234
+ cwd,
235
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
236
+ });
237
+ expect(exitCode).toBe(1);
238
+ expect(output).toContain("--title is required");
239
+ expect(mockServer.getCalls("POST", "/v1/distribution/publish")).toHaveLength(0);
240
+ });
241
+ it("errors non-interactively when --description is missing", async () => {
242
+ mockServer.addProject(buildMockProject({
243
+ projectId: PROJECT_ID,
244
+ teamId: TEAM_ID,
245
+ projectName: "my-server",
246
+ environmentId: ENV_ID,
247
+ environmentName: "production",
248
+ domains: [{ domain: DOMAIN, status: "deployed", createdAt: new Date() }],
249
+ }));
250
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
251
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "publish", "--non-interactive", "--domain", DOMAIN, "--title", "T"], {
252
+ cwd,
253
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
254
+ });
255
+ expect(exitCode).toBe(1);
256
+ expect(output).toContain("--description is required");
257
+ expect(mockServer.getCalls("POST", "/v1/distribution/publish")).toHaveLength(0);
258
+ });
259
+ it("errors non-interactively when multiple domains are available and --domain is missing", async () => {
260
+ mockServer.addProject(buildMockProject({
261
+ projectId: PROJECT_ID,
262
+ teamId: TEAM_ID,
263
+ projectName: "my-server",
264
+ environmentId: ENV_ID,
265
+ environmentName: "production",
266
+ domains: [
267
+ { domain: DOMAIN, status: "deployed", createdAt: new Date() },
268
+ { domain: "another.example.com", status: "deployed", createdAt: new Date() },
269
+ ],
270
+ }));
271
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
272
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "publish", "--non-interactive", "--title", "T", "--description", "D"], {
273
+ cwd,
274
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
275
+ });
276
+ expect(exitCode).toBe(1);
277
+ expect(output).toContain("--domain is required when using --non-interactive. Available:");
278
+ expect(mockServer.getCalls("POST", "/v1/distribution/publish")).toHaveLength(0);
279
+ });
280
+ it("errors non-interactively when a single domain is available and --domain is missing", async () => {
281
+ mockServer.addProject(buildMockProject({
282
+ projectId: PROJECT_ID,
283
+ teamId: TEAM_ID,
284
+ projectName: "my-server",
285
+ environmentId: ENV_ID,
286
+ environmentName: "production",
287
+ domains: [{ domain: DOMAIN, status: "deployed", createdAt: new Date() }],
288
+ }));
289
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
290
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "publish", "--non-interactive", "--title", "T", "--description", "D"], {
291
+ cwd,
292
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
293
+ });
294
+ expect(exitCode).toBe(1);
295
+ expect(output).toContain("--domain is required when using --non-interactive. Available:");
296
+ expect(mockServer.getCalls("POST", "/v1/distribution/publish")).toHaveLength(0);
297
+ });
298
+ it("publishes non-interactively with --project-id when no config file exists", async () => {
299
+ mockServer.addProject(buildMockProject({
300
+ projectId: PROJECT_ID,
301
+ teamId: TEAM_ID,
302
+ projectName: "my-server",
303
+ environmentId: ENV_ID,
304
+ environmentName: "production",
305
+ domains: [{ domain: DOMAIN, status: "deployed", createdAt: new Date() }],
306
+ }));
307
+ const { exitCode, output } = await cliSession(process.execPath, [
308
+ binPath,
309
+ "publish",
310
+ "--non-interactive",
311
+ "--project-id",
312
+ PROJECT_ID,
313
+ "--domain",
314
+ DOMAIN,
315
+ "--title",
316
+ "My Server",
317
+ "--description",
318
+ "Does things",
319
+ ], {
320
+ cwd,
321
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
322
+ }, async (cli) => {
323
+ await cli.expect("Registry publication succeeded (v0.0.1)");
324
+ });
325
+ expect(exitCode).toBe(0);
326
+ expect(output).toContain("Registry publication succeeded (v0.0.1)");
327
+ const publishCall = mockServer.getLastCall("POST", "/v1/distribution/publish");
328
+ expectSuccessfulApiCall(publishCall, (call) => {
329
+ expect(call.input).toMatchObject({ projectId: PROJECT_ID, domain: DOMAIN });
330
+ });
331
+ });
332
+ it("publishes non-interactively with --project-id overriding the config file", async () => {
333
+ const otherProjectId = "other-project-id";
334
+ mockServer.addProject(buildMockProject({
335
+ projectId: otherProjectId,
336
+ teamId: TEAM_ID,
337
+ projectName: "other-server",
338
+ environmentId: "other-env-id",
339
+ environmentName: "production",
340
+ domains: [{ domain: DOMAIN, status: "deployed", createdAt: new Date() }],
341
+ }));
342
+ // Config file points to PROJECT_ID, but --project-id should override it
343
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
344
+ const { exitCode, output } = await cliSession(process.execPath, [
345
+ binPath,
346
+ "publish",
347
+ "--non-interactive",
348
+ "--project-id",
349
+ otherProjectId,
350
+ "--domain",
351
+ DOMAIN,
352
+ "--title",
353
+ "My Server",
354
+ "--description",
355
+ "Does things",
356
+ ], {
357
+ cwd,
358
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
359
+ }, async (cli) => {
360
+ await cli.expect("Registry publication succeeded (v0.0.1)");
361
+ });
362
+ expect(exitCode).toBe(0);
363
+ expect(output).toContain("Registry publication succeeded (v0.0.1)");
364
+ const publishCall = mockServer.getLastCall("POST", "/v1/distribution/publish");
365
+ expectSuccessfulApiCall(publishCall, (call) => {
366
+ expect(call.input).toMatchObject({ projectId: otherProjectId, domain: DOMAIN });
367
+ });
368
+ });
369
+ it("prefills prompts with last published data and shows previous version", async () => {
370
+ mockServer.addProject(buildMockProject({
371
+ projectId: PROJECT_ID,
372
+ teamId: TEAM_ID,
373
+ projectName: "my-server",
374
+ environmentId: ENV_ID,
375
+ environmentName: "production",
376
+ domains: [{ domain: DOMAIN, status: "deployed", createdAt: new Date() }],
377
+ }));
378
+ mockServer.setPublishedServer(PROJECT_ID, DOMAIN, {
379
+ $schema: "https://registry.modelcontextprotocol.io/schemas/1.0/server.json",
380
+ name: "my-server",
381
+ title: "Old Title",
382
+ description: "Old description",
383
+ version: "1.2.3",
384
+ websiteUrl: "https://old.example.com",
385
+ icons: [{ src: "https://old.example.com/icon.png" }],
386
+ });
387
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
388
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "publish"], {
389
+ cwd,
390
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
391
+ }, async (cli) => {
392
+ await cli.expect("Select a domain to publish for");
393
+ await cli.send("");
394
+ // Accept all prefilled values as-is
395
+ await cli.expect("Server title");
396
+ await cli.send("");
397
+ await cli.expect("Server description");
398
+ await cli.send("");
399
+ await cli.expect("Website URL");
400
+ await cli.send("");
401
+ await cli.expect("Icon URL");
402
+ await cli.send("");
403
+ await cli.expect("Publish to MCP Registry under domain");
404
+ await cli.send("");
405
+ await cli.expect("Registry publication succeeded (v1.2.4)");
406
+ });
407
+ expect(exitCode).toBe(0);
408
+ expect(output).toContain("Registry publication succeeded (v1.2.4)");
409
+ const infoCall = mockServer.getLastCall("GET", "/v1/distribution/info");
410
+ expect(infoCall).toBeDefined();
411
+ expect(infoCall.input).toMatchObject({ projectId: PROJECT_ID, domain: DOMAIN });
412
+ const publishCall = mockServer.getLastCall("POST", "/v1/distribution/publish");
413
+ expectSuccessfulApiCall(publishCall, (call) => {
414
+ expect(call.input).toMatchObject({
415
+ title: "Old Title",
416
+ description: "Old description",
417
+ websiteUrl: "https://old.example.com",
418
+ iconSrc: "https://old.example.com/icon.png",
419
+ });
420
+ });
421
+ });
422
+ it("cancels when user declines the confirmation prompt", async () => {
423
+ mockServer.addProject(buildMockProject({
424
+ projectId: PROJECT_ID,
425
+ teamId: TEAM_ID,
426
+ projectName: "my-server",
427
+ environmentId: ENV_ID,
428
+ environmentName: "production",
429
+ domains: [{ domain: DOMAIN, status: "deployed", createdAt: new Date() }],
430
+ }));
431
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
432
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "publish"], {
433
+ cwd,
434
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
435
+ }, async (cli) => {
436
+ await cli.expect("Select a domain to publish for");
437
+ await cli.send("");
438
+ await cli.expect("Server title");
439
+ await cli.send("My Server");
440
+ await cli.expect("Server description");
441
+ await cli.send("Does things");
442
+ await cli.expect("Website URL");
443
+ await cli.send("");
444
+ await cli.expect("Icon URL");
445
+ await cli.send("");
446
+ await cli.expect("Publish to MCP Registry under domain");
447
+ // Arrow down to select "No", then confirm
448
+ await cli.send("\x1B[B");
449
+ });
450
+ expect(exitCode).toBe(1);
451
+ expect(output).toContain("Publish cancelled");
452
+ const publishCalls = mockServer.getCalls("POST", "/v1/distribution/publish");
453
+ expect(publishCalls).toHaveLength(1);
454
+ expect(publishCalls[0].input).toMatchObject({ dryRun: true });
455
+ });
456
+ it("errors non-interactively when --domain is not in deployed domains", async () => {
457
+ mockServer.addProject(buildMockProject({
458
+ projectId: PROJECT_ID,
459
+ teamId: TEAM_ID,
460
+ projectName: "my-server",
461
+ environmentId: ENV_ID,
462
+ environmentName: "production",
463
+ domains: [{ domain: DOMAIN, status: "deployed", createdAt: new Date() }],
464
+ }));
465
+ createConfigFile(cwd, PROJECT_ID, TEAM_ID, "my-server", ENV_ID, "production");
466
+ const { exitCode, output } = await cliSession(process.execPath, [
467
+ binPath,
468
+ "publish",
469
+ "--non-interactive",
470
+ "--domain",
471
+ "unknown.example.com",
472
+ "--title",
473
+ "T",
474
+ "--description",
475
+ "D",
476
+ ], {
477
+ cwd,
478
+ env: { ALPIC_API_BASE_URL: serverUrl, ALPIC_API_KEY: "test-api-key" },
479
+ });
480
+ expect(exitCode).toBe(1);
481
+ expect(output).toContain(`Domain "unknown.example.com" not found`);
482
+ expect(mockServer.getCalls("POST", "/v1/distribution/publish")).toHaveLength(0);
483
+ });
484
+ }, 20_000);
485
+ //# sourceMappingURL=publish.e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/publish.e2e.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAErE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EACL,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,MAAM,UAAU,GAAG,iBAAiB,CAAC;AACrC,MAAM,OAAO,GAAG,cAAc,CAAC;AAC/B,MAAM,MAAM,GAAG,aAAa,CAAC;AAC7B,MAAM,MAAM,GAAG,uBAAuB,CAAC;AACvC,MAAM,aAAa,GAAG,OAAO,UAAU,WAAW,CAAC;AAEnD,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,IAAI,UAAyB,CAAC;IAC9B,IAAI,SAAiB,CAAC;IACtB,IAAI,GAAW,CAAC;IAChB,IAAI,OAAe,CAAC;IAEpB,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,UAAU,GAAG,IAAI,aAAa,EAAE,CAAC;QACjC,SAAS,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;QACzC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QAChB,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sFAAsF,EAAE,KAAK,IAAI,EAAE;QACpG,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,EAAE;SACZ,CAAC,CACH,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,CAAC,EACpB;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,GAAG,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC;YACnD,MAAM,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAChC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACjC,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAE5B,MAAM,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACvC,MAAM,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YAEpC,MAAM,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAChC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC7B,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,sCAAsC,CAAC,CAAC;YACzD,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;QAC9D,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;QACpE,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,+CAA+C,CAAC,CAAC;QAE1E,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;QAC/E,uBAAuB,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;YAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;gBAC/B,SAAS,EAAE,UAAU;gBACrB,MAAM,EAAE,aAAa;gBACrB,KAAK,EAAE,WAAW;gBAClB,WAAW,EAAE,mBAAmB;aACjC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,OAAO,GAAG,mBAAmB,CAAC;QACpC,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE;gBACP,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE;gBAC7D,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE;gBAC9D,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE;aAC5E;SACF,CAAC,CACH,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,CAAC,EACpB;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,GAAG,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC;YACnD,MAAM,GAAG,CAAC,MAAM,CAAC,GAAG,aAAa,WAAW,CAAC,CAAC;YAC9C,uEAAuE;YACvE,gEAAgE;YAChE,MAAM,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC/B,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACjC,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAE5B,MAAM,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACvC,MAAM,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YAEpC,MAAM,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAChC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC7B,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,sCAAsC,CAAC,CAAC;YACzD,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;QAC9D,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;QAEpE,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;QAC/E,uBAAuB,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;YAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SACzE,CAAC,CACH,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,UAAU,CACnC,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,CAAC,EACpB;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,GAAG,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC;YACnD,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACjC,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAE5B,MAAM,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACvC,MAAM,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YAEpC,MAAM,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAChC,MAAM,GAAG,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;YAEhD,MAAM,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC7B,MAAM,GAAG,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;YAEzD,MAAM,GAAG,CAAC,MAAM,CAAC,sCAAsC,CAAC,CAAC;YACzD,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;QAC9D,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEzB,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;QAC/E,uBAAuB,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;YAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;gBAC/B,UAAU,EAAE,+BAA+B;gBAC3C,OAAO,EAAE,wCAAwC;aAClD,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SACzE,CAAC,CACH,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB;YACE,OAAO;YACP,SAAS;YACT,mBAAmB;YACnB,UAAU;YACV,MAAM;YACN,SAAS;YACT,WAAW;YACX,eAAe;YACf,aAAa;YACb,eAAe;YACf,qBAAqB;YACrB,YAAY;YACZ,8BAA8B;SAC/B,EACD;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,GAAG,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;QAC9D,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;QAEpE,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;QAC/E,uBAAuB,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;YAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;gBAC/B,SAAS,EAAE,UAAU;gBACrB,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE,WAAW;gBAClB,WAAW,EAAE,aAAa;gBAC1B,UAAU,EAAE,qBAAqB;gBACjC,OAAO,EAAE,8BAA8B;aACxC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,CAAC,EACnG;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACjD,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;YAC1C,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QACH,UAAU,CAAC,UAAU,CAAC,EAAE,GAAG,kBAAkB,EAAE,qBAAqB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9E,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,CAAC,EACnG;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAC5D,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SACzE,CAAC,CACH,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,CAAC,EACnF;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAChD,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QACtE,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SACzE,CAAC,CACH,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,EAC7E;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;QACtD,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sFAAsF,EAAE,KAAK,IAAI,EAAE;QACpG,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE;gBACP,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE;gBAC7D,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE;aAC7E;SACF,CAAC,CACH,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,CAAC,EAC/E;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,+DAA+D,CAAC,CAAC;QAC1F,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;QAClG,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SACzE,CAAC,CACH,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,CAAC,EAC/E;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,+DAA+D,CAAC,CAAC;QAC1F,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SACzE,CAAC,CACH,CAAC;QAEF,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB;YACE,OAAO;YACP,SAAS;YACT,mBAAmB;YACnB,cAAc;YACd,UAAU;YACV,UAAU;YACV,MAAM;YACN,SAAS;YACT,WAAW;YACX,eAAe;YACf,aAAa;SACd,EACD;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,GAAG,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;QAC9D,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;QAEpE,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;QAC/E,uBAAuB,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;YAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,cAAc,GAAG,kBAAkB,CAAC;QAC1C,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,cAAc;YACzB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,cAAc;YAC3B,aAAa,EAAE,cAAc;YAC7B,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SACzE,CAAC,CACH,CAAC;QACF,wEAAwE;QACxE,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB;YACE,OAAO;YACP,SAAS;YACT,mBAAmB;YACnB,cAAc;YACd,cAAc;YACd,UAAU;YACV,MAAM;YACN,SAAS;YACT,WAAW;YACX,eAAe;YACf,aAAa;SACd,EACD;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,GAAG,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;QAC9D,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;QAEpE,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;QAC/E,uBAAuB,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;YAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACpF,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SACzE,CAAC,CACH,CAAC;QACF,UAAU,CAAC,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE;YAChD,OAAO,EAAE,kEAAkE;YAC3E,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,WAAW;YAClB,WAAW,EAAE,iBAAiB;YAC9B,OAAO,EAAE,OAAO;YAChB,UAAU,EAAE,yBAAyB;YACrC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,kCAAkC,EAAE,CAAC;SACrD,CAAC,CAAC;QACH,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,CAAC,EACpB;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,GAAG,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC;YACnD,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,oCAAoC;YACpC,MAAM,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACjC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACvC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAChC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC7B,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,sCAAsC,CAAC,CAAC;YACzD,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,yCAAyC,CAAC,CAAC;QAC9D,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yCAAyC,CAAC,CAAC;QAEpE,MAAM,QAAQ,GAAG,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE,uBAAuB,CAAC,CAAC;QACxE,MAAM,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,CAAC,QAAS,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QAEjF,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;QAC/E,uBAAuB,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,EAAE;YAC5C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC;gBAC/B,KAAK,EAAE,WAAW;gBAClB,WAAW,EAAE,iBAAiB;gBAC9B,UAAU,EAAE,yBAAyB;gBACrC,OAAO,EAAE,kCAAkC;aAC5C,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SACzE,CAAC,CACH,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB,CAAC,OAAO,EAAE,SAAS,CAAC,EACpB;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,EACD,KAAK,EAAE,GAAG,EAAE,EAAE;YACZ,MAAM,GAAG,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC;YACnD,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;YACjC,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAE5B,MAAM,GAAG,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;YACvC,MAAM,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAE9B,MAAM,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAChC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC7B,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEnB,MAAM,GAAG,CAAC,MAAM,CAAC,sCAAsC,CAAC,CAAC;YACzD,0CAA0C;YAC1C,MAAM,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QAE9C,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;QAC7E,MAAM,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACjF,UAAU,CAAC,UAAU,CACnB,gBAAgB,CAAC;YACf,SAAS,EAAE,UAAU;YACrB,MAAM,EAAE,OAAO;YACf,WAAW,EAAE,WAAW;YACxB,aAAa,EAAE,MAAM;YACrB,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;SACzE,CAAC,CACH,CAAC;QACF,gBAAgB,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;QAE9E,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,UAAU,CAC3C,OAAO,CAAC,QAAQ,EAChB;YACE,OAAO;YACP,SAAS;YACT,mBAAmB;YACnB,UAAU;YACV,qBAAqB;YACrB,SAAS;YACT,GAAG;YACH,eAAe;YACf,GAAG;SACJ,EACD;YACE,GAAG;YACH,GAAG,EAAE,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE;SACtE,CACF,CAAC;QAEF,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,wCAAwC,CAAC,CAAC;QACnE,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC,CAAC;AACL,CAAC,EAAE,MAAM,CAAC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,64 @@
1
+ import { rmSync } from "node:fs";
2
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
3
+ import { MockApiServer } from "./mock-server.js";
4
+ import { cliSession, setupTestDirectory } from "./utils.js";
5
+ describe("alpic tunnel (E2E)", () => {
6
+ let mockServer;
7
+ let serverUrl;
8
+ let cwd;
9
+ let binPath;
10
+ beforeEach(async () => {
11
+ mockServer = new MockApiServer();
12
+ serverUrl = await mockServer.start();
13
+ const setup = await setupTestDirectory();
14
+ cwd = setup.cwd;
15
+ binPath = setup.binPath;
16
+ });
17
+ afterEach(async () => {
18
+ await mockServer.stop();
19
+ if (cwd) {
20
+ rmSync(cwd, { recursive: true, force: true });
21
+ }
22
+ });
23
+ it("requires authentication", async () => {
24
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "tunnel", "--port", "3000"], {
25
+ cwd,
26
+ env: {
27
+ ALPIC_API_BASE_URL: serverUrl,
28
+ },
29
+ }, async (cli) => {
30
+ await cli.expect("Not authenticated");
31
+ });
32
+ expect(exitCode).toBe(1);
33
+ expect(output).toContain("Not authenticated");
34
+ });
35
+ it("requires --port flag", async () => {
36
+ const { exitCode, output } = await cliSession(process.execPath, [binPath, "tunnel"], {
37
+ cwd,
38
+ env: {
39
+ ALPIC_API_BASE_URL: serverUrl,
40
+ ALPIC_API_KEY: "test-api-key",
41
+ },
42
+ }, async (cli) => {
43
+ await cli.expect(/port|Missing required flag/);
44
+ });
45
+ expect(exitCode).toBe(1);
46
+ expect(output).toMatch(/port|Missing required flag/);
47
+ });
48
+ it("requests a tunnel ticket from the API", async () => {
49
+ await cliSession(process.execPath, [binPath, "tunnel", "--port", "3000"], {
50
+ cwd,
51
+ env: {
52
+ ALPIC_API_BASE_URL: serverUrl,
53
+ ALPIC_API_KEY: "test-api-key",
54
+ },
55
+ timeoutMs: 12000,
56
+ }, async (cli) => {
57
+ await cli.expect("Opening tunnel");
58
+ cli.stop();
59
+ });
60
+ const ticketCall = mockServer.getCalls().find((call) => call.path.includes("tunnels"));
61
+ expect(ticketCall).toBeDefined();
62
+ });
63
+ });
64
+ //# sourceMappingURL=tunnel.e2e.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel.e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/tunnel.e2e.test.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,10 @@
1
1
  import type { RouterOutput } from "@alpic-ai/api";
2
- import { type ApiCall } from "./mock-server";
2
+ import type { ApiCall, MockApiServer } from "./mock-server.js";
3
3
  type Expectable = string | RegExp;
4
4
  type ProjectGetV1 = RouterOutput["projects"]["get"]["v1"];
5
+ type DeploymentGetV1 = RouterOutput["deployments"]["get"]["v1"];
6
+ type ProductionEnvironment = NonNullable<ProjectGetV1["productionEnvironment"]>;
7
+ type ProductionEnvironmentDomains = ProductionEnvironment["domains"];
5
8
  export type CliSessionOptions = {
6
9
  cwd?: string;
7
10
  env?: Record<string, string | undefined>;
@@ -25,7 +28,7 @@ export type CliController = {
25
28
  /** End session (SIGTERM) */
26
29
  stop: () => void;
27
30
  };
28
- export declare function cliSession(cmd: string, args: string[], options: CliSessionOptions, fn: (cli: CliController) => Promise<void>): Promise<{
31
+ export declare function cliSession(cmd: string, args: string[], options: CliSessionOptions, fn?: (cli: CliController) => Promise<void> | void): Promise<{
29
32
  exitCode: number | null;
30
33
  output: string;
31
34
  }>;
@@ -37,11 +40,11 @@ export type BuildMockProjectParams = {
37
40
  environmentName: string;
38
41
  sourceRepository?: string | null;
39
42
  sourceBranch?: string | null;
43
+ domains?: ProductionEnvironmentDomains;
40
44
  };
41
45
  export declare function buildMockProject(params: BuildMockProjectParams): ProjectGetV1;
46
+ export declare function buildMockDeployment(overrides?: Partial<DeploymentGetV1>): DeploymentGetV1;
42
47
  export type SetupTestDirectoryOptions = {
43
- /** Temp directory prefix (default: "alpic-cli-e2e") */
44
- prefix?: string;
45
48
  /** If true, run git init and add origin/upstream remotes */
46
49
  initGit?: boolean;
47
50
  };
@@ -52,4 +55,18 @@ export declare function setupTestDirectory(options?: SetupTestDirectoryOptions):
52
55
  export declare function createConfigFile(cwd: string, projectId: string, teamId: string, projectName: string, environmentId: string, environmentName: string): void;
53
56
  export declare function runGit(args: string[], cwd: string): void;
54
57
  export declare function expectSuccessfulApiCall(call: ApiCall | undefined, customAssertions?: (call: ApiCall) => void): asserts call is ApiCall;
58
+ /**
59
+ * Create OAuth credentials in a temp config dir and return env for CLI subprocess.
60
+ * Use this to run commands with OAuth auth (no ALPIC_API_KEY).
61
+ * Caller must pass serverUrl so userinfo can be pointed at the mock server.
62
+ */
63
+ export declare function createOAuthEnv(cwd: string, serverUrl: string): Record<string, string>;
64
+ export declare function verifyConfigFile(cwd: string, output: string, expected: {
65
+ projectName: string;
66
+ projectId?: string;
67
+ teamId?: string;
68
+ environmentId?: string;
69
+ environmentName?: string;
70
+ }): Promise<void>;
71
+ export declare function verifyDeploymentFlow(cli: CliController, mockServer: MockApiServer): Promise<void>;
55
72
  export {};