alpic 0.0.0-staging.2ab71bc → 0.0.0-staging.2ba052d
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/README.md +40 -0
- package/bin/run.js +5 -0
- package/dist/__tests__/alpic-command.test.d.ts +1 -0
- package/dist/__tests__/alpic-command.test.js +41 -0
- package/dist/__tests__/alpic-command.test.js.map +1 -0
- package/dist/__tests__/audit.e2e.test.d.ts +1 -0
- package/dist/__tests__/audit.e2e.test.js +561 -0
- package/dist/__tests__/audit.e2e.test.js.map +1 -0
- package/dist/__tests__/auth.e2e.test.js +38 -18
- package/dist/__tests__/auth.e2e.test.js.map +1 -1
- package/dist/__tests__/deploy-flags.e2e.test.d.ts +1 -0
- package/dist/__tests__/deploy-flags.e2e.test.js +228 -0
- package/dist/__tests__/deploy-flags.e2e.test.js.map +1 -0
- package/dist/__tests__/deploy.e2e.test.js +33 -66
- 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 +119 -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 +121 -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 +262 -0
- package/dist/__tests__/deployment-logs.e2e.test.js.map +1 -0
- package/dist/__tests__/environment-inspect.e2e.test.d.ts +1 -0
- package/dist/__tests__/environment-inspect.e2e.test.js +78 -0
- package/dist/__tests__/environment-inspect.e2e.test.js.map +1 -0
- package/dist/__tests__/environment-list.e2e.test.d.ts +1 -0
- package/dist/__tests__/environment-list.e2e.test.js +63 -0
- package/dist/__tests__/environment-list.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 +277 -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 +146 -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 +148 -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 +348 -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 +129 -0
- package/dist/__tests__/git-flags.e2e.test.js.map +1 -0
- package/dist/__tests__/git.e2e.test.js +25 -17
- package/dist/__tests__/git.e2e.test.js.map +1 -1
- package/dist/__tests__/link.e2e.test.d.ts +1 -0
- package/dist/__tests__/link.e2e.test.js +282 -0
- package/dist/__tests__/link.e2e.test.js.map +1 -0
- package/dist/__tests__/logs.e2e.test.d.ts +1 -0
- package/dist/__tests__/logs.e2e.test.js +230 -0
- package/dist/__tests__/logs.e2e.test.js.map +1 -0
- package/dist/__tests__/mock-server.d.ts +25 -0
- package/dist/__tests__/mock-server.js +386 -23
- package/dist/__tests__/mock-server.js.map +1 -1
- package/dist/__tests__/playground/playground-configure.e2e.test.d.ts +1 -0
- package/dist/__tests__/playground/playground-configure.e2e.test.js +135 -0
- package/dist/__tests__/playground/playground-configure.e2e.test.js.map +1 -0
- package/dist/__tests__/playground/playground-enable-disable.e2e.test.d.ts +1 -0
- package/dist/__tests__/playground/playground-enable-disable.e2e.test.js +104 -0
- package/dist/__tests__/playground/playground-enable-disable.e2e.test.js.map +1 -0
- package/dist/__tests__/playground/playground-example-prompt.e2e.test.d.ts +1 -0
- package/dist/__tests__/playground/playground-example-prompt.e2e.test.js +282 -0
- package/dist/__tests__/playground/playground-example-prompt.e2e.test.js.map +1 -0
- package/dist/__tests__/playground/playground-headers.e2e.test.d.ts +1 -0
- package/dist/__tests__/playground/playground-headers.e2e.test.js +324 -0
- package/dist/__tests__/playground/playground-headers.e2e.test.js.map +1 -0
- package/dist/__tests__/playground/playground-status.e2e.test.d.ts +1 -0
- package/dist/__tests__/playground/playground-status.e2e.test.js +88 -0
- package/dist/__tests__/playground/playground-status.e2e.test.js.map +1 -0
- package/dist/__tests__/project-inspect.e2e.test.d.ts +1 -0
- package/dist/__tests__/project-inspect.e2e.test.js +83 -0
- package/dist/__tests__/project-inspect.e2e.test.js.map +1 -0
- package/dist/__tests__/project-list.e2e.test.d.ts +1 -0
- package/dist/__tests__/project-list.e2e.test.js +95 -0
- package/dist/__tests__/project-list.e2e.test.js.map +1 -0
- package/dist/__tests__/publish.e2e.test.d.ts +1 -0
- package/dist/__tests__/publish.e2e.test.js +575 -0
- package/dist/__tests__/publish.e2e.test.js.map +1 -0
- package/dist/__tests__/team-inspect.e2e.test.d.ts +1 -0
- package/dist/__tests__/team-inspect.e2e.test.js +86 -0
- package/dist/__tests__/team-inspect.e2e.test.js.map +1 -0
- package/dist/__tests__/team-list.e2e.test.d.ts +1 -0
- package/dist/__tests__/team-list.e2e.test.js +58 -0
- package/dist/__tests__/team-list.e2e.test.js.map +1 -0
- package/dist/__tests__/tunnel.e2e.test.d.ts +1 -0
- package/dist/__tests__/tunnel.e2e.test.js +66 -0
- package/dist/__tests__/tunnel.e2e.test.js.map +1 -0
- package/dist/__tests__/utils.d.ts +17 -5
- package/dist/__tests__/utils.js +120 -26
- package/dist/__tests__/utils.js.map +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/api.js +10 -3
- package/dist/api.js.map +1 -1
- package/dist/commands/audit.d.ts +13 -0
- package/dist/commands/audit.js +45 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/deploy.d.ts +7 -2
- package/dist/commands/deploy.js +67 -25
- 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/inspect.d.ts +10 -0
- package/dist/commands/environment/inspect.js +94 -0
- package/dist/commands/environment/inspect.js.map +1 -0
- package/dist/commands/environment/list.d.ts +10 -0
- package/dist/commands/environment/list.js +79 -0
- package/dist/commands/environment/list.js.map +1 -0
- package/dist/commands/environment-variable/add.d.ts +13 -0
- package/dist/commands/environment-variable/add.js +43 -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 +45 -0
- package/dist/commands/environment-variable/list.js.map +1 -0
- package/dist/commands/environment-variable/remove.d.ts +10 -0
- package/dist/commands/environment-variable/remove.js +29 -0
- package/dist/commands/environment-variable/remove.js.map +1 -0
- package/dist/commands/environment-variable/update.d.ts +12 -0
- package/dist/commands/environment-variable/update.js +37 -0
- package/dist/commands/environment-variable/update.js.map +1 -0
- package/dist/commands/git/connect.d.ts +2 -2
- package/dist/commands/git/connect.js +25 -28
- package/dist/commands/git/connect.js.map +1 -1
- package/dist/commands/git/disconnect.d.ts +0 -3
- package/dist/commands/git/disconnect.js +14 -29
- package/dist/commands/git/disconnect.js.map +1 -1
- package/dist/commands/git.js +2 -2
- package/dist/commands/git.js.map +1 -1
- package/dist/commands/link.d.ts +16 -0
- package/dist/commands/link.js +97 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/login.js +6 -24
- package/dist/commands/login.js.map +1 -1
- 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/playground/configure.d.ts +12 -0
- package/dist/commands/playground/configure.js +39 -0
- package/dist/commands/playground/configure.js.map +1 -0
- package/dist/commands/playground/disable.d.ts +9 -0
- package/dist/commands/playground/disable.js +24 -0
- package/dist/commands/playground/disable.js.map +1 -0
- package/dist/commands/playground/enable.d.ts +9 -0
- package/dist/commands/playground/enable.js +24 -0
- package/dist/commands/playground/enable.js.map +1 -0
- package/dist/commands/playground/example-prompt/add.d.ts +12 -0
- package/dist/commands/playground/example-prompt/add.js +39 -0
- package/dist/commands/playground/example-prompt/add.js.map +1 -0
- package/dist/commands/playground/example-prompt/list.d.ts +9 -0
- package/dist/commands/playground/example-prompt/list.js +24 -0
- package/dist/commands/playground/example-prompt/list.js.map +1 -0
- package/dist/commands/playground/example-prompt/remove.d.ts +11 -0
- package/dist/commands/playground/example-prompt/remove.js +34 -0
- package/dist/commands/playground/example-prompt/remove.js.map +1 -0
- package/dist/commands/playground/headers/add.d.ts +14 -0
- package/dist/commands/playground/headers/add.js +49 -0
- package/dist/commands/playground/headers/add.js.map +1 -0
- package/dist/commands/playground/headers/list.d.ts +9 -0
- package/dist/commands/playground/headers/list.js +24 -0
- package/dist/commands/playground/headers/list.js.map +1 -0
- package/dist/commands/playground/headers/remove.d.ts +11 -0
- package/dist/commands/playground/headers/remove.js +34 -0
- package/dist/commands/playground/headers/remove.js.map +1 -0
- package/dist/commands/playground/status.d.ts +9 -0
- package/dist/commands/playground/status.js +24 -0
- package/dist/commands/playground/status.js.map +1 -0
- package/dist/commands/project/inspect.d.ts +10 -0
- package/dist/commands/project/inspect.js +97 -0
- package/dist/commands/project/inspect.js.map +1 -0
- package/dist/commands/project/list.d.ts +10 -0
- package/dist/commands/project/list.js +50 -0
- package/dist/commands/project/list.js.map +1 -0
- package/dist/commands/publish.d.ts +14 -0
- package/dist/commands/publish.js +47 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/team/inspect.d.ts +10 -0
- package/dist/commands/team/inspect.js +97 -0
- package/dist/commands/team/inspect.js.map +1 -0
- package/dist/commands/team/list.d.ts +9 -0
- package/dist/commands/team/list.js +40 -0
- package/dist/commands/team/list.js.map +1 -0
- package/dist/commands/tunnel.d.ts +10 -0
- package/dist/commands/tunnel.js +132 -0
- package/dist/commands/tunnel.js.map +1 -0
- package/dist/commands/whoami.js +2 -14
- package/dist/commands/whoami.js.map +1 -1
- package/dist/env.js +1 -1
- package/dist/env.js.map +1 -1
- package/dist/lib/alpic-command.d.ts +7 -0
- package/dist/lib/alpic-command.js +24 -6
- package/dist/lib/alpic-command.js.map +1 -1
- package/dist/lib/archive.d.ts +3 -3
- package/dist/lib/archive.js +21 -19
- package/dist/lib/archive.js.map +1 -1
- package/dist/lib/audit.d.ts +16 -0
- package/dist/lib/audit.js +258 -0
- package/dist/lib/audit.js.map +1 -0
- package/dist/lib/auth/auth.d.ts +3 -0
- package/dist/lib/auth/auth.js +26 -3
- package/dist/lib/auth/auth.js.map +1 -1
- package/dist/lib/auth/oauth/client.d.ts +1 -1
- package/dist/lib/auth/oauth/client.js +7 -1
- package/dist/lib/auth/oauth/client.js.map +1 -1
- package/dist/lib/auth/oauth/server/index.d.ts +2 -1
- package/dist/lib/auth/oauth/server/index.js +36 -10
- package/dist/lib/auth/oauth/server/index.js.map +1 -1
- package/dist/lib/auth/whoami.d.ts +1 -28
- package/dist/lib/auth/whoami.js +29 -19
- package/dist/lib/auth/whoami.js.map +1 -1
- 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 +3 -2
- package/dist/lib/config.js +8 -7
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/deployment.d.ts +69 -1
- package/dist/lib/deployment.js +113 -5
- package/dist/lib/deployment.js.map +1 -1
- package/dist/lib/environment-variable.d.ts +37 -0
- package/dist/lib/environment-variable.js +305 -0
- package/dist/lib/environment-variable.js.map +1 -0
- package/dist/lib/git.d.ts +12 -4
- package/dist/lib/git.js +52 -26
- package/dist/lib/git.js.map +1 -1
- package/dist/lib/global-store.d.ts +1 -1
- package/dist/lib/global-store.js +4 -3
- package/dist/lib/global-store.js.map +1 -1
- package/dist/lib/link.d.ts +83 -0
- package/dist/lib/link.js +387 -0
- package/dist/lib/link.js.map +1 -0
- package/dist/lib/logs.d.ts +20 -0
- package/dist/lib/logs.js +87 -0
- package/dist/lib/logs.js.map +1 -0
- package/dist/lib/playground.d.ts +53 -0
- package/dist/lib/playground.js +288 -0
- package/dist/lib/playground.js.map +1 -0
- package/dist/lib/publish.d.ts +22 -0
- package/dist/lib/publish.js +201 -0
- package/dist/lib/publish.js.map +1 -0
- package/dist/lib/resolve.d.ts +6 -0
- package/dist/lib/resolve.js +26 -0
- package/dist/lib/resolve.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 +1 -1
- package/dist/lib/telemetry.js.map +1 -1
- package/dist/lib/utils.d.ts +6 -0
- package/dist/lib/utils.js +54 -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/dist/types.d.ts +1 -0
- package/package.json +28 -21
- package/dist/lib/project.d.ts +0 -67
- package/dist/lib/project.js +0 -285
- package/dist/lib/project.js.map +0 -1
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
1
3
|
import * as https from "node:https";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { contract } from "@alpic-ai/api";
|
|
2
7
|
import { OpenAPIHandler } from "@orpc/openapi/node";
|
|
3
|
-
import {
|
|
8
|
+
import { implement, ORPCError } from "@orpc/server";
|
|
4
9
|
import express, {} from "express";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
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
|
+
}
|
|
8
21
|
export class MockApiServer {
|
|
9
22
|
server = null;
|
|
10
23
|
app;
|
|
@@ -14,9 +27,19 @@ export class MockApiServer {
|
|
|
14
27
|
constructor() {
|
|
15
28
|
this.app = express();
|
|
16
29
|
this.mockData = {
|
|
30
|
+
teams: null,
|
|
17
31
|
projects: new Map(),
|
|
18
32
|
environments: new Map(),
|
|
19
33
|
deployments: new Map(),
|
|
34
|
+
environmentVariables: new Map(),
|
|
35
|
+
runtimeLogs: new Map(),
|
|
36
|
+
runtimeLogPages: new Map(),
|
|
37
|
+
deploymentLogPages: new Map(),
|
|
38
|
+
deploymentLogCallCounts: new Map(),
|
|
39
|
+
publishedServers: new Map(),
|
|
40
|
+
beaconGetResponses: [],
|
|
41
|
+
beaconGetCallCount: 0,
|
|
42
|
+
playgrounds: new Map(),
|
|
20
43
|
};
|
|
21
44
|
}
|
|
22
45
|
async start() {
|
|
@@ -24,8 +47,9 @@ export class MockApiServer {
|
|
|
24
47
|
throw new Error("Server is already running");
|
|
25
48
|
}
|
|
26
49
|
this.configureServer();
|
|
27
|
-
const
|
|
28
|
-
|
|
50
|
+
const tlsAssets = getTlsAssets();
|
|
51
|
+
process.env.NODE_EXTRA_CA_CERTS = tlsAssets.certPath;
|
|
52
|
+
const httpsOptions = { key: tlsAssets.key, cert: tlsAssets.cert };
|
|
29
53
|
return new Promise((resolve) => {
|
|
30
54
|
this.server = https.createServer(httpsOptions, this.app).listen(0, "127.0.0.1", () => {
|
|
31
55
|
if (!this.server) {
|
|
@@ -88,16 +112,29 @@ export class MockApiServer {
|
|
|
88
112
|
});
|
|
89
113
|
});
|
|
90
114
|
const router = implement(contract).router({
|
|
115
|
+
tunnels: {
|
|
116
|
+
getTicket: {
|
|
117
|
+
v1: implement(contract.tunnels.getTicket.v1).handler(async () => {
|
|
118
|
+
return {
|
|
119
|
+
subdomain: "cool-mongoose-123",
|
|
120
|
+
ticket: "mock-ticket",
|
|
121
|
+
tunnelHost: "tunnel.alpic.dev",
|
|
122
|
+
};
|
|
123
|
+
}),
|
|
124
|
+
},
|
|
125
|
+
},
|
|
91
126
|
teams: {
|
|
92
127
|
list: {
|
|
93
128
|
v1: implement(contract.teams.list.v1).handler(async () => {
|
|
129
|
+
if (this.mockData.teams) {
|
|
130
|
+
return this.mockData.teams;
|
|
131
|
+
}
|
|
94
132
|
return [
|
|
95
133
|
{
|
|
96
134
|
id: "mock-team-id",
|
|
97
135
|
name: "Mock Team",
|
|
98
136
|
createdAt: new Date(),
|
|
99
137
|
hasStripeAccount: false,
|
|
100
|
-
hasActiveSubscription: false,
|
|
101
138
|
},
|
|
102
139
|
];
|
|
103
140
|
}),
|
|
@@ -108,7 +145,9 @@ export class MockApiServer {
|
|
|
108
145
|
v1: implement(contract.analytics.get.v1).handler(async ({ input }) => {
|
|
109
146
|
const project = this.mockData.projects.get(input.projectId);
|
|
110
147
|
if (!project) {
|
|
111
|
-
throw new ORPCError("NOT_FOUND", {
|
|
148
|
+
throw new ORPCError("NOT_FOUND", {
|
|
149
|
+
message: "Project not found",
|
|
150
|
+
});
|
|
112
151
|
}
|
|
113
152
|
const emptyTimeSeries = {
|
|
114
153
|
sessions_count: [],
|
|
@@ -134,8 +173,12 @@ export class MockApiServer {
|
|
|
134
173
|
},
|
|
135
174
|
projects: {
|
|
136
175
|
list: {
|
|
137
|
-
v1: implement(contract.projects.list.v1).handler(async () => {
|
|
138
|
-
|
|
176
|
+
v1: implement(contract.projects.list.v1).handler(async ({ input }) => {
|
|
177
|
+
let projects = Array.from(this.mockData.projects.values());
|
|
178
|
+
if (input?.teamId) {
|
|
179
|
+
projects = projects.filter((project) => project.teamId === input.teamId);
|
|
180
|
+
}
|
|
181
|
+
return projects.map((project) => ({
|
|
139
182
|
id: project.id,
|
|
140
183
|
name: project.name,
|
|
141
184
|
teamId: project.teamId,
|
|
@@ -157,7 +200,9 @@ export class MockApiServer {
|
|
|
157
200
|
v1: implement(contract.projects.get.v1).handler(async ({ input }) => {
|
|
158
201
|
const project = this.mockData.projects.get(input.projectId);
|
|
159
202
|
if (!project) {
|
|
160
|
-
throw new ORPCError("NOT_FOUND", {
|
|
203
|
+
throw new ORPCError("NOT_FOUND", {
|
|
204
|
+
message: "Project not found",
|
|
205
|
+
});
|
|
161
206
|
}
|
|
162
207
|
return project;
|
|
163
208
|
}),
|
|
@@ -165,7 +210,7 @@ export class MockApiServer {
|
|
|
165
210
|
create: {
|
|
166
211
|
v1: implement(contract.projects.create.v1).handler(async ({ input }) => {
|
|
167
212
|
const projectId = randomUUID();
|
|
168
|
-
const teamId = "mock-team-id";
|
|
213
|
+
const teamId = input.teamId ?? "mock-team-id";
|
|
169
214
|
const productionEnvId = randomUUID();
|
|
170
215
|
const productionEnvName = "production";
|
|
171
216
|
const project = {
|
|
@@ -203,6 +248,7 @@ export class MockApiServer {
|
|
|
203
248
|
id: productionEnvId,
|
|
204
249
|
name: productionEnvName,
|
|
205
250
|
mcpServerUrl: `https://mcp-${projectId}.alpic.ai`,
|
|
251
|
+
domains: [],
|
|
206
252
|
latestDeployment: null,
|
|
207
253
|
},
|
|
208
254
|
environments: [
|
|
@@ -225,7 +271,9 @@ export class MockApiServer {
|
|
|
225
271
|
v1: implement(contract.projects.update.v1).handler(async ({ input }) => {
|
|
226
272
|
const project = this.mockData.projects.get(input.projectId);
|
|
227
273
|
if (!project) {
|
|
228
|
-
throw new ORPCError("NOT_FOUND", {
|
|
274
|
+
throw new ORPCError("NOT_FOUND", {
|
|
275
|
+
message: "Project not found",
|
|
276
|
+
});
|
|
229
277
|
}
|
|
230
278
|
if (input.sourceRepository !== undefined) {
|
|
231
279
|
project.sourceRepository = input.sourceRepository;
|
|
@@ -238,7 +286,9 @@ export class MockApiServer {
|
|
|
238
286
|
v1: implement(contract.projects.delete.v1).handler(async ({ input }) => {
|
|
239
287
|
const project = this.mockData.projects.get(input.projectId);
|
|
240
288
|
if (!project) {
|
|
241
|
-
throw new ORPCError("NOT_FOUND", {
|
|
289
|
+
throw new ORPCError("NOT_FOUND", {
|
|
290
|
+
message: "Project not found",
|
|
291
|
+
});
|
|
242
292
|
}
|
|
243
293
|
this.mockData.projects.delete(input.projectId);
|
|
244
294
|
return { success: true };
|
|
@@ -250,7 +300,9 @@ export class MockApiServer {
|
|
|
250
300
|
v1: implement(contract.environments.create.v1).handler(async ({ input }) => {
|
|
251
301
|
const project = this.mockData.projects.get(input.projectId);
|
|
252
302
|
if (!project) {
|
|
253
|
-
throw new ORPCError("NOT_FOUND", {
|
|
303
|
+
throw new ORPCError("NOT_FOUND", {
|
|
304
|
+
message: "Project not found",
|
|
305
|
+
});
|
|
254
306
|
}
|
|
255
307
|
const environmentId = randomUUID();
|
|
256
308
|
const mcpServerUrl = `https://mcp-${environmentId}.alpic.ai`;
|
|
@@ -294,21 +346,50 @@ export class MockApiServer {
|
|
|
294
346
|
v1: implement(contract.environments.get.v1).handler(async ({ input }) => {
|
|
295
347
|
const environment = this.mockData.environments.get(input.environmentId);
|
|
296
348
|
if (!environment) {
|
|
297
|
-
throw new ORPCError("NOT_FOUND", {
|
|
349
|
+
throw new ORPCError("NOT_FOUND", {
|
|
350
|
+
message: "Environment not found",
|
|
351
|
+
});
|
|
298
352
|
}
|
|
299
353
|
return environment;
|
|
300
354
|
}),
|
|
301
355
|
},
|
|
356
|
+
getLogs: {
|
|
357
|
+
v1: implement(contract.environments.getLogs.v1).handler(async ({ input }) => {
|
|
358
|
+
const environment = this.mockData.environments.get(input.environmentId);
|
|
359
|
+
if (!environment) {
|
|
360
|
+
throw new ORPCError("NOT_FOUND", {
|
|
361
|
+
message: "Environment not found",
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
const pagedLogs = this.mockData.runtimeLogPages.get(input.environmentId);
|
|
365
|
+
const pageIndex = input.nextToken === undefined ? 0 : Number.parseInt(input.nextToken, 10);
|
|
366
|
+
const allLogs = pagedLogs === undefined
|
|
367
|
+
? (this.mockData.runtimeLogs.get(input.environmentId) ?? [])
|
|
368
|
+
: (pagedLogs[pageIndex] ?? []);
|
|
369
|
+
let logs = allLogs;
|
|
370
|
+
if (input.level !== undefined) {
|
|
371
|
+
const levels = input.level;
|
|
372
|
+
logs = allLogs.filter((log) => levels.includes(log.type));
|
|
373
|
+
}
|
|
374
|
+
const nextToken = pagedLogs === undefined || pageIndex + 1 >= pagedLogs.length ? null : String(pageIndex + 1);
|
|
375
|
+
return { logs, nextToken };
|
|
376
|
+
}),
|
|
377
|
+
},
|
|
302
378
|
deploy: {
|
|
303
379
|
v1: implement(contract.environments.deploy.v1).handler(async ({ input }) => {
|
|
304
380
|
const environment = this.mockData.environments.get(input.environmentId);
|
|
305
381
|
if (!environment) {
|
|
306
|
-
throw new ORPCError("NOT_FOUND", {
|
|
382
|
+
throw new ORPCError("NOT_FOUND", {
|
|
383
|
+
message: "Environment not found",
|
|
384
|
+
});
|
|
307
385
|
}
|
|
308
386
|
const deploymentId = randomUUID();
|
|
309
387
|
const deployment = {
|
|
310
388
|
id: deploymentId,
|
|
311
389
|
status: "ongoing",
|
|
390
|
+
environmentId: environment.id,
|
|
391
|
+
environmentName: environment.name,
|
|
392
|
+
isCurrent: false,
|
|
312
393
|
sourceRef: environment.sourceBranch,
|
|
313
394
|
sourceCommitId: randomUUID().slice(0, 7),
|
|
314
395
|
sourceCommitMessage: "Mock deployment",
|
|
@@ -323,17 +404,225 @@ export class MockApiServer {
|
|
|
323
404
|
}),
|
|
324
405
|
},
|
|
325
406
|
},
|
|
407
|
+
environmentVariables: {
|
|
408
|
+
list: {
|
|
409
|
+
v1: implement(contract.environmentVariables.list.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
|
+
return this.mockData.environmentVariables.get(input.environmentId) ?? [];
|
|
417
|
+
}),
|
|
418
|
+
},
|
|
419
|
+
create: {
|
|
420
|
+
v1: implement(contract.environmentVariables.create.v1).handler(async ({ input }) => {
|
|
421
|
+
const environment = this.mockData.environments.get(input.environmentId);
|
|
422
|
+
if (!environment) {
|
|
423
|
+
throw new ORPCError("NOT_FOUND", {
|
|
424
|
+
message: "Environment not found",
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
const existing = this.mockData.environmentVariables.get(input.environmentId) ?? [];
|
|
428
|
+
const newVars = input.environmentVariables.map((variable) => ({
|
|
429
|
+
id: randomUUID(),
|
|
430
|
+
key: variable.key,
|
|
431
|
+
value: variable.value,
|
|
432
|
+
isSecret: variable.isSecret,
|
|
433
|
+
createdAt: new Date(),
|
|
434
|
+
}));
|
|
435
|
+
for (const newVar of newVars) {
|
|
436
|
+
if (existing.some((existingVar) => existingVar.key === newVar.key)) {
|
|
437
|
+
throw new ORPCError("BAD_REQUEST", {
|
|
438
|
+
message: `Environment variable "${newVar.key}" already exists`,
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
this.mockData.environmentVariables.set(input.environmentId, [...existing, ...newVars]);
|
|
443
|
+
return { success: true };
|
|
444
|
+
}),
|
|
445
|
+
},
|
|
446
|
+
update: {
|
|
447
|
+
v1: implement(contract.environmentVariables.update.v1).handler(async ({ input }) => {
|
|
448
|
+
for (const [environmentId, variables] of this.mockData.environmentVariables.entries()) {
|
|
449
|
+
const index = variables.findIndex((variable) => variable.id === input.environmentVariableId);
|
|
450
|
+
if (index !== -1) {
|
|
451
|
+
const updated = variables.map((variable, i) => i === index
|
|
452
|
+
? {
|
|
453
|
+
...variable,
|
|
454
|
+
key: input.key,
|
|
455
|
+
value: input.value ?? variable.value,
|
|
456
|
+
isSecret: input.isSecret,
|
|
457
|
+
}
|
|
458
|
+
: variable);
|
|
459
|
+
this.mockData.environmentVariables.set(environmentId, updated);
|
|
460
|
+
return { success: true };
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
throw new ORPCError("NOT_FOUND", {
|
|
464
|
+
message: "Environment variable not found",
|
|
465
|
+
});
|
|
466
|
+
}),
|
|
467
|
+
},
|
|
468
|
+
delete: {
|
|
469
|
+
v1: implement(contract.environmentVariables.delete.v1).handler(async ({ input }) => {
|
|
470
|
+
for (const [environmentId, variables] of this.mockData.environmentVariables.entries()) {
|
|
471
|
+
const index = variables.findIndex((variable) => variable.id === input.environmentVariableId);
|
|
472
|
+
if (index !== -1) {
|
|
473
|
+
this.mockData.environmentVariables.set(environmentId, variables.filter((_, i) => i !== index));
|
|
474
|
+
return { success: true };
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
throw new ORPCError("NOT_FOUND", {
|
|
478
|
+
message: "Environment variable not found",
|
|
479
|
+
});
|
|
480
|
+
}),
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
playground: {
|
|
484
|
+
get: {
|
|
485
|
+
v1: implement(contract.playground.get.v1).handler(async ({ input }) => {
|
|
486
|
+
const environment = this.mockData.environments.get(input.environmentId);
|
|
487
|
+
if (!environment) {
|
|
488
|
+
throw new ORPCError("NOT_FOUND", { message: "Environment not found" });
|
|
489
|
+
}
|
|
490
|
+
return (this.mockData.playgrounds.get(input.environmentId) ?? { isPlaygroundEnabled: true, serverMetadata: null });
|
|
491
|
+
}),
|
|
492
|
+
},
|
|
493
|
+
upsert: {
|
|
494
|
+
v1: implement(contract.playground.upsert.v1).handler(async ({ input }) => {
|
|
495
|
+
const environment = this.mockData.environments.get(input.environmentId);
|
|
496
|
+
if (!environment) {
|
|
497
|
+
throw new ORPCError("NOT_FOUND", { message: "Environment not found" });
|
|
498
|
+
}
|
|
499
|
+
const current = this.mockData.playgrounds.get(input.environmentId) ?? {
|
|
500
|
+
isPlaygroundEnabled: true,
|
|
501
|
+
serverMetadata: null,
|
|
502
|
+
};
|
|
503
|
+
const hasMetadataFields = input.name !== undefined ||
|
|
504
|
+
input.description !== undefined ||
|
|
505
|
+
input.headers !== undefined ||
|
|
506
|
+
input.examplePrompts !== undefined;
|
|
507
|
+
const updated = {
|
|
508
|
+
isPlaygroundEnabled: input.isPlaygroundEnabled ?? current.isPlaygroundEnabled,
|
|
509
|
+
serverMetadata: hasMetadataFields
|
|
510
|
+
? {
|
|
511
|
+
name: input.name ?? current.serverMetadata?.name ?? "",
|
|
512
|
+
description: input.description ?? current.serverMetadata?.description ?? "",
|
|
513
|
+
headers: (input.headers ?? current.serverMetadata?.headers ?? []).map((header) => ({
|
|
514
|
+
name: header.name,
|
|
515
|
+
description: header.description,
|
|
516
|
+
isRequired: header.isRequired ?? false,
|
|
517
|
+
isSecret: header.isSecret ?? false,
|
|
518
|
+
})),
|
|
519
|
+
examplePrompts: input.examplePrompts ?? current.serverMetadata?.examplePrompts ?? [],
|
|
520
|
+
}
|
|
521
|
+
: current.serverMetadata,
|
|
522
|
+
};
|
|
523
|
+
this.mockData.playgrounds.set(input.environmentId, updated);
|
|
524
|
+
return updated;
|
|
525
|
+
}),
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
distribution: {
|
|
529
|
+
get: {
|
|
530
|
+
v1: implement(contract.distribution.get.v1).handler(async ({ input }) => {
|
|
531
|
+
const existing = this.mockData.publishedServers.get(`${input.projectId}:${input.domain}`);
|
|
532
|
+
return {
|
|
533
|
+
serverFields: existing ?? {
|
|
534
|
+
$schema: "https://registry.modelcontextprotocol.io/schemas/1.0/server.json",
|
|
535
|
+
name: "",
|
|
536
|
+
description: "",
|
|
537
|
+
},
|
|
538
|
+
};
|
|
539
|
+
}),
|
|
540
|
+
},
|
|
541
|
+
publish: {
|
|
542
|
+
v1: implement(contract.distribution.publish.v1).handler(async ({ input }) => {
|
|
543
|
+
const project = this.mockData.projects.get(input.projectId);
|
|
544
|
+
if (!project) {
|
|
545
|
+
throw new ORPCError("NOT_FOUND", {
|
|
546
|
+
message: "Project not found",
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
const key = `${input.projectId}:${input.domain}`;
|
|
550
|
+
const existing = this.mockData.publishedServers.get(key);
|
|
551
|
+
const version = existing?.version ? (semverInc(existing.version, "patch") ?? "0.0.1") : "0.0.1";
|
|
552
|
+
const serverFields = {
|
|
553
|
+
$schema: "https://registry.modelcontextprotocol.io/schemas/1.0/server.json",
|
|
554
|
+
name: input.domain,
|
|
555
|
+
description: input.description,
|
|
556
|
+
title: input.title,
|
|
557
|
+
version,
|
|
558
|
+
...(input.websiteUrl ? { websiteUrl: input.websiteUrl } : {}),
|
|
559
|
+
...(input.iconSrc ? { icons: [{ src: input.iconSrc }] } : {}),
|
|
560
|
+
};
|
|
561
|
+
if (!input.dryRun) {
|
|
562
|
+
this.mockData.publishedServers.set(key, serverFields);
|
|
563
|
+
}
|
|
564
|
+
return { serverFields };
|
|
565
|
+
}),
|
|
566
|
+
},
|
|
567
|
+
},
|
|
568
|
+
beacon: {
|
|
569
|
+
create: {
|
|
570
|
+
v1: implement(contract.beacon.create.v1).handler(async () => {
|
|
571
|
+
return { id: "mock-analysis-id" };
|
|
572
|
+
}),
|
|
573
|
+
},
|
|
574
|
+
get: {
|
|
575
|
+
v1: implement(contract.beacon.get.v1).handler(async () => {
|
|
576
|
+
if (this.mockData.beaconGetResponses.length > 0) {
|
|
577
|
+
const index = Math.min(this.mockData.beaconGetCallCount, this.mockData.beaconGetResponses.length - 1);
|
|
578
|
+
this.mockData.beaconGetCallCount++;
|
|
579
|
+
const response = this.mockData.beaconGetResponses[index];
|
|
580
|
+
if (!response) {
|
|
581
|
+
throw new Error("Missing mocked beacon.get response");
|
|
582
|
+
}
|
|
583
|
+
return response;
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
id: "mock-analysis-id",
|
|
587
|
+
targetUrl: "https://example.com/mcp",
|
|
588
|
+
status: "completed",
|
|
589
|
+
durationMs: 1234,
|
|
590
|
+
createdAt: new Date(),
|
|
591
|
+
report: {
|
|
592
|
+
schemaVersion: "v20260224",
|
|
593
|
+
auditId: "mock-analysis-id",
|
|
594
|
+
targetUrl: "https://example.com/mcp",
|
|
595
|
+
startedAt: new Date().toISOString(),
|
|
596
|
+
completedAt: new Date().toISOString(),
|
|
597
|
+
durationMs: 1234,
|
|
598
|
+
results: [],
|
|
599
|
+
requiresAuth: false,
|
|
600
|
+
hasViewSupport: false,
|
|
601
|
+
isReadyForPlatform: { chatgpt: true, claudeai: true },
|
|
602
|
+
},
|
|
603
|
+
};
|
|
604
|
+
}),
|
|
605
|
+
},
|
|
606
|
+
},
|
|
326
607
|
deployments: {
|
|
327
608
|
list: {
|
|
328
609
|
v1: implement(contract.deployments.list.v1).handler(async ({ input }) => {
|
|
329
610
|
const project = this.mockData.projects.get(input.projectId);
|
|
330
611
|
if (!project) {
|
|
331
|
-
throw new ORPCError("NOT_FOUND", {
|
|
612
|
+
throw new ORPCError("NOT_FOUND", {
|
|
613
|
+
message: "Project not found",
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
let deployments = Array.from(this.mockData.deployments.values());
|
|
617
|
+
if (input.environmentId) {
|
|
618
|
+
deployments = deployments.filter((deployment) => deployment.environmentId === input.environmentId);
|
|
332
619
|
}
|
|
333
|
-
|
|
620
|
+
if (input.status?.length) {
|
|
621
|
+
deployments = deployments.filter((deployment) => input.status.includes(deployment.status));
|
|
622
|
+
}
|
|
623
|
+
return deployments.map((deployment) => ({
|
|
334
624
|
...deployment,
|
|
335
625
|
isCurrent: deployment.status === "deployed",
|
|
336
|
-
environmentId: project.productionEnvironment?.id ?? "",
|
|
337
626
|
}));
|
|
338
627
|
}),
|
|
339
628
|
},
|
|
@@ -341,7 +630,9 @@ export class MockApiServer {
|
|
|
341
630
|
v1: implement(contract.deployments.get.v1).handler(async ({ input }) => {
|
|
342
631
|
const deployment = this.mockData.deployments.get(input.deploymentId);
|
|
343
632
|
if (!deployment) {
|
|
344
|
-
throw new ORPCError("NOT_FOUND", {
|
|
633
|
+
throw new ORPCError("NOT_FOUND", {
|
|
634
|
+
message: "Deployment not found",
|
|
635
|
+
});
|
|
345
636
|
}
|
|
346
637
|
if (deployment.status === "ongoing") {
|
|
347
638
|
const updatedDeployment = {
|
|
@@ -360,7 +651,16 @@ export class MockApiServer {
|
|
|
360
651
|
v1: implement(contract.deployments.getLogs.v1).handler(async ({ input }) => {
|
|
361
652
|
const deployment = this.mockData.deployments.get(input.deploymentId);
|
|
362
653
|
if (!deployment) {
|
|
363
|
-
throw new ORPCError("NOT_FOUND", {
|
|
654
|
+
throw new ORPCError("NOT_FOUND", {
|
|
655
|
+
message: "Deployment not found",
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
const pages = this.mockData.deploymentLogPages.get(input.deploymentId);
|
|
659
|
+
if (pages !== undefined) {
|
|
660
|
+
const callCount = this.mockData.deploymentLogCallCounts.get(input.deploymentId) ?? 0;
|
|
661
|
+
const pageIndex = Math.min(callCount, pages.length - 1);
|
|
662
|
+
this.mockData.deploymentLogCallCounts.set(input.deploymentId, callCount + 1);
|
|
663
|
+
return pages[pageIndex] ?? { logs: [], hasMoreLogs: false };
|
|
364
664
|
}
|
|
365
665
|
return {
|
|
366
666
|
logs: [{ timestamp: new Date(), content: "Mock log entry" }],
|
|
@@ -389,7 +689,12 @@ export class MockApiServer {
|
|
|
389
689
|
path: req.path,
|
|
390
690
|
timestamp: new Date(),
|
|
391
691
|
};
|
|
392
|
-
if (req.
|
|
692
|
+
if (req.method === "GET") {
|
|
693
|
+
if (Object.keys(req.query).length > 0) {
|
|
694
|
+
apiCall.input = req.query;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
else if (req.body) {
|
|
393
698
|
apiCall.input = req.body;
|
|
394
699
|
}
|
|
395
700
|
const result = await handler.handle(req, res, {
|
|
@@ -405,6 +710,24 @@ export class MockApiServer {
|
|
|
405
710
|
this.callHistory.push(apiCall);
|
|
406
711
|
});
|
|
407
712
|
}
|
|
713
|
+
reset() {
|
|
714
|
+
this.callHistory = [];
|
|
715
|
+
this.mockData = {
|
|
716
|
+
teams: null,
|
|
717
|
+
projects: new Map(),
|
|
718
|
+
environments: new Map(),
|
|
719
|
+
deployments: new Map(),
|
|
720
|
+
environmentVariables: new Map(),
|
|
721
|
+
runtimeLogs: new Map(),
|
|
722
|
+
runtimeLogPages: new Map(),
|
|
723
|
+
deploymentLogPages: new Map(),
|
|
724
|
+
deploymentLogCallCounts: new Map(),
|
|
725
|
+
publishedServers: new Map(),
|
|
726
|
+
beaconGetResponses: [],
|
|
727
|
+
beaconGetCallCount: 0,
|
|
728
|
+
playgrounds: new Map(),
|
|
729
|
+
};
|
|
730
|
+
}
|
|
408
731
|
async stop() {
|
|
409
732
|
return new Promise((resolve, reject) => {
|
|
410
733
|
if (!this.server) {
|
|
@@ -461,6 +784,46 @@ export class MockApiServer {
|
|
|
461
784
|
}
|
|
462
785
|
return undefined;
|
|
463
786
|
}
|
|
787
|
+
setTeams(teams) {
|
|
788
|
+
this.mockData.teams = teams.map((team) => ({
|
|
789
|
+
...team,
|
|
790
|
+
createdAt: new Date("2024-01-01T00:00:00.000Z"),
|
|
791
|
+
hasStripeAccount: false,
|
|
792
|
+
}));
|
|
793
|
+
}
|
|
794
|
+
addEnvironmentVariables(environmentId, variables) {
|
|
795
|
+
this.mockData.environmentVariables.set(environmentId, variables);
|
|
796
|
+
}
|
|
797
|
+
setRuntimeLogs(environmentId, logs) {
|
|
798
|
+
this.mockData.runtimeLogs.set(environmentId, logs);
|
|
799
|
+
this.mockData.runtimeLogPages.delete(environmentId);
|
|
800
|
+
}
|
|
801
|
+
setRuntimeLogPages(environmentId, pages) {
|
|
802
|
+
this.mockData.runtimeLogPages.set(environmentId, pages);
|
|
803
|
+
this.mockData.runtimeLogs.delete(environmentId);
|
|
804
|
+
}
|
|
805
|
+
setPublishedServer(projectId, domain, server) {
|
|
806
|
+
this.mockData.publishedServers.set(`${projectId}:${domain}`, server);
|
|
807
|
+
}
|
|
808
|
+
addDeployments(deployments) {
|
|
809
|
+
for (const deployment of deployments) {
|
|
810
|
+
this.mockData.deployments.set(deployment.id, {
|
|
811
|
+
...deployment,
|
|
812
|
+
deploymentPageUrl: null,
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
setDeploymentLogPages(deploymentId, pages) {
|
|
817
|
+
this.mockData.deploymentLogPages.set(deploymentId, pages);
|
|
818
|
+
this.mockData.deploymentLogCallCounts.set(deploymentId, 0);
|
|
819
|
+
}
|
|
820
|
+
setBeaconGetResponses(responses) {
|
|
821
|
+
this.mockData.beaconGetResponses = responses;
|
|
822
|
+
this.mockData.beaconGetCallCount = 0;
|
|
823
|
+
}
|
|
824
|
+
setPlayground(environmentId, playground) {
|
|
825
|
+
this.mockData.playgrounds.set(environmentId, playground);
|
|
826
|
+
}
|
|
464
827
|
addProject(project) {
|
|
465
828
|
this.mockData.projects.set(project.id, project);
|
|
466
829
|
if (project.productionEnvironment) {
|