alpic 0.0.0-dev.fd6fd82 → 0.0.0-dev.fdd8a62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/auth.e2e.test.d.ts +1 -0
- package/dist/__tests__/auth.e2e.test.js +142 -0
- package/dist/__tests__/auth.e2e.test.js.map +1 -0
- package/dist/__tests__/deploy.e2e.test.d.ts +1 -0
- package/dist/__tests__/deploy.e2e.test.js +217 -0
- package/dist/__tests__/deploy.e2e.test.js.map +1 -0
- package/dist/__tests__/fixtures/demo-project/index.d.ts +1 -0
- package/dist/__tests__/fixtures/demo-project/index.js +4 -0
- package/dist/__tests__/fixtures/demo-project/index.js.map +1 -0
- package/dist/__tests__/git.e2e.test.d.ts +1 -0
- package/dist/__tests__/git.e2e.test.js +218 -0
- package/dist/__tests__/git.e2e.test.js.map +1 -0
- package/dist/__tests__/mock-server.d.ts +22 -0
- package/dist/__tests__/mock-server.js +492 -0
- package/dist/__tests__/mock-server.js.map +1 -0
- package/dist/__tests__/utils.d.ts +61 -0
- package/dist/__tests__/utils.js +197 -0
- package/dist/__tests__/utils.js.map +1 -0
- package/dist/api.d.ts +3 -0
- package/dist/api.js +15 -0
- package/dist/api.js.map +1 -0
- package/dist/commands/deploy.d.ts +9 -0
- package/dist/commands/deploy.js +82 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/git/connect.d.ts +9 -0
- package/dist/commands/git/connect.js +59 -0
- package/dist/commands/git/connect.js.map +1 -0
- package/dist/commands/git/disconnect.d.ts +9 -0
- package/dist/commands/git/disconnect.js +51 -0
- package/dist/commands/git/disconnect.js.map +1 -0
- package/dist/commands/{hello.d.ts → git.d.ts} +1 -1
- package/dist/commands/git.js +17 -0
- package/dist/commands/git.js.map +1 -0
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.js +39 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +6 -0
- package/dist/commands/logout.js +20 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/telemetry/disable.d.ts +5 -0
- package/dist/commands/telemetry/disable.js +14 -0
- package/dist/commands/telemetry/disable.js.map +1 -0
- package/dist/commands/telemetry/enable.d.ts +5 -0
- package/dist/commands/telemetry/enable.js +13 -0
- package/dist/commands/telemetry/enable.js.map +1 -0
- package/dist/commands/telemetry/status.d.ts +5 -0
- package/dist/commands/telemetry/status.js +19 -0
- package/dist/commands/telemetry/status.js.map +1 -0
- package/dist/commands/whoami.d.ts +6 -0
- package/dist/commands/whoami.js +25 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/env.d.ts +4 -0
- package/dist/env.js +10 -0
- package/dist/env.js.map +1 -0
- package/dist/lib/alpic-command.d.ts +4 -0
- package/dist/lib/alpic-command.js +17 -0
- package/dist/lib/alpic-command.js.map +1 -0
- package/dist/lib/archive.d.ts +7 -0
- package/dist/lib/archive.js +55 -0
- package/dist/lib/archive.js.map +1 -0
- package/dist/lib/auth/auth.d.ts +2 -0
- package/dist/lib/auth/auth.js +21 -0
- package/dist/lib/auth/auth.js.map +1 -0
- package/dist/lib/auth/oauth/client.d.ts +28 -0
- package/dist/lib/auth/oauth/client.js +110 -0
- package/dist/lib/auth/oauth/client.js.map +1 -0
- package/dist/lib/auth/oauth/constants.d.ts +2 -0
- package/dist/lib/auth/oauth/constants.js +3 -0
- package/dist/lib/auth/oauth/constants.js.map +1 -0
- package/dist/lib/auth/oauth/server/assets/alpic-mountain.png +0 -0
- package/dist/lib/auth/oauth/server/assets/authorize.html +195 -0
- package/dist/lib/auth/oauth/server/assets/callback.html +88 -0
- package/dist/lib/auth/oauth/server/index.d.ts +8 -0
- package/dist/lib/auth/oauth/server/index.js +103 -0
- package/dist/lib/auth/oauth/server/index.js.map +1 -0
- package/dist/lib/auth/whoami.d.ts +28 -0
- package/dist/lib/auth/whoami.js +35 -0
- package/dist/lib/auth/whoami.js.map +1 -0
- package/dist/lib/config.d.ts +11 -0
- package/dist/lib/config.js +31 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/deployment.d.ts +20 -0
- package/dist/lib/deployment.js +43 -0
- package/dist/lib/deployment.js.map +1 -0
- package/dist/lib/git.d.ts +14 -0
- package/dist/lib/git.js +105 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/global-store.d.ts +28 -0
- package/dist/lib/global-store.js +75 -0
- package/dist/lib/global-store.js.map +1 -0
- package/dist/lib/project.d.ts +67 -0
- package/dist/lib/project.js +285 -0
- package/dist/lib/project.js.map +1 -0
- package/dist/lib/telemetry.d.ts +7 -0
- package/dist/lib/telemetry.js +66 -0
- package/dist/lib/telemetry.js.map +1 -0
- package/dist/lib/upload.d.ts +1 -0
- package/dist/lib/upload.js +14 -0
- package/dist/lib/upload.js.map +1 -0
- package/dist/posthog.d.ts +3 -0
- package/dist/posthog.js +10 -0
- package/dist/posthog.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +35 -8
- package/dist/commands/hello.js +0 -10
- package/dist/commands/hello.js.map +0 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Sign in to Alpic</title>
|
|
7
|
+
<link
|
|
8
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Mozilla+Text:wght@200..700&display=swap"
|
|
9
|
+
rel="stylesheet"
|
|
10
|
+
/>
|
|
11
|
+
<style>
|
|
12
|
+
*,
|
|
13
|
+
*::before,
|
|
14
|
+
*::after {
|
|
15
|
+
margin: 0;
|
|
16
|
+
padding: 0;
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
:root {
|
|
21
|
+
--midnight: #051413;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
body {
|
|
25
|
+
font-family: "Inter", system-ui, sans-serif;
|
|
26
|
+
background-color: var(--midnight);
|
|
27
|
+
min-height: 100vh;
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
padding: 64px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.card {
|
|
35
|
+
background: #fff;
|
|
36
|
+
border-radius: 2px;
|
|
37
|
+
padding: 48px;
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
align-items: center;
|
|
41
|
+
justify-content: center;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.message {
|
|
45
|
+
text-align: center;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.message-title {
|
|
49
|
+
font-size: 28px;
|
|
50
|
+
color: var(--midnight);
|
|
51
|
+
display: block;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.message-sub {
|
|
55
|
+
display: block;
|
|
56
|
+
margin-top: 0.5em;
|
|
57
|
+
color: #6b7280;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.message.error .message-title {
|
|
61
|
+
color: #b91c1c;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.message.error .message-sub {
|
|
65
|
+
display: none;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@media (max-width: 768px) {
|
|
69
|
+
body {
|
|
70
|
+
padding: 16px;
|
|
71
|
+
}
|
|
72
|
+
.card {
|
|
73
|
+
width: 100%;
|
|
74
|
+
height: auto;
|
|
75
|
+
padding: 24px;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
</style>
|
|
79
|
+
</head>
|
|
80
|
+
<body>
|
|
81
|
+
<div class="card">
|
|
82
|
+
<p class="message __CALLBACK_STATUS__">
|
|
83
|
+
<span class="message-title">__CALLBACK_TITLE__</span>
|
|
84
|
+
<span class="message-sub">__CALLBACK_SUB__</span>
|
|
85
|
+
</p>
|
|
86
|
+
</div>
|
|
87
|
+
</body>
|
|
88
|
+
</html>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Credentials } from "../../../global-store.js";
|
|
2
|
+
export declare const getLoginPageUrl: () => string;
|
|
3
|
+
export declare const listenToOAuthCallback: ({ state, nonce, codeVerifier, authorizeUrl, }: {
|
|
4
|
+
state: string;
|
|
5
|
+
nonce: string;
|
|
6
|
+
codeVerifier: string;
|
|
7
|
+
authorizeUrl?: string;
|
|
8
|
+
}) => Promise<Credentials>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { createServer } from "node:http";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { oAuthClient } from "../client.js";
|
|
7
|
+
import { LOOPBACK_HOST, LOOPBACK_PORT } from "../constants.js";
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const ASSETS_DIR = path.join(__dirname, "assets");
|
|
10
|
+
const createCallbackServer = ({ state, nonce, codeVerifier, authorizeUrl, onSuccess, onError, }) => createServer(async (req, res) => {
|
|
11
|
+
const url = req.url ?? "/";
|
|
12
|
+
const pathname = url.split("?")[0] ?? "/";
|
|
13
|
+
if (pathname === "/login") {
|
|
14
|
+
try {
|
|
15
|
+
const htmlPath = path.join(ASSETS_DIR, "authorize.html");
|
|
16
|
+
let html = await readFile(htmlPath, "utf-8");
|
|
17
|
+
if (authorizeUrl) {
|
|
18
|
+
html = html.replace(/%AUTH_BASE_URL%/g, authorizeUrl);
|
|
19
|
+
}
|
|
20
|
+
res.writeHead(200, { "Content-Type": "text/html", Connection: "close" });
|
|
21
|
+
res.end(html);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
p.log.error(e instanceof Error ? e.message : String(e));
|
|
26
|
+
res.writeHead(500).end();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (pathname === "/assets/alpic-mountain.png") {
|
|
31
|
+
const filePath = path.join(ASSETS_DIR, "alpic-mountain.png");
|
|
32
|
+
const content = await readFile(filePath);
|
|
33
|
+
res.writeHead(200, { "Content-Type": "image/png", Connection: "close" });
|
|
34
|
+
res.end(content);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (!url.startsWith("/callback")) {
|
|
38
|
+
p.log.message(`Ignoring request to ${url}`);
|
|
39
|
+
res.writeHead(404).end();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const tokens = await oAuthClient.exchangeAuthorizationCode({
|
|
44
|
+
url: new URL(url, `http://${req.headers.host}`),
|
|
45
|
+
codeVerifier,
|
|
46
|
+
state,
|
|
47
|
+
nonce,
|
|
48
|
+
});
|
|
49
|
+
const sub = tokens.claims()?.sub;
|
|
50
|
+
if (!sub || !tokens.refresh_token) {
|
|
51
|
+
throw new Error("ID token did not contain sub");
|
|
52
|
+
}
|
|
53
|
+
const stored = {
|
|
54
|
+
access_token: tokens.access_token,
|
|
55
|
+
refresh_token: tokens.refresh_token,
|
|
56
|
+
expires_at: oAuthClient.getExpiresAt(tokens.expires_in ?? 0),
|
|
57
|
+
sub,
|
|
58
|
+
};
|
|
59
|
+
p.log.success("✅ Authentication successful");
|
|
60
|
+
const successHtmlPath = path.join(ASSETS_DIR, "callback.html");
|
|
61
|
+
let html = await readFile(successHtmlPath, "utf-8");
|
|
62
|
+
html = html
|
|
63
|
+
.replace(/__CALLBACK_STATUS__/g, "success")
|
|
64
|
+
.replace(/__CALLBACK_TITLE__/g, "You are logged in")
|
|
65
|
+
.replace(/__CALLBACK_SUB__/g, "You can close this page.");
|
|
66
|
+
res.writeHead(200, { "Content-Type": "text/html", Connection: "close" });
|
|
67
|
+
res.end(html);
|
|
68
|
+
onSuccess(stored);
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
p.log.error(e instanceof Error ? e.message : String(e));
|
|
72
|
+
const callbackHtmlPath = path.join(ASSETS_DIR, "callback.html");
|
|
73
|
+
let html = await readFile(callbackHtmlPath, "utf-8");
|
|
74
|
+
html = html
|
|
75
|
+
.replace(/__CALLBACK_STATUS__/g, "error")
|
|
76
|
+
.replace(/__CALLBACK_TITLE__/g, "An error occurred. You can close this page.")
|
|
77
|
+
.replace(/__CALLBACK_SUB__/g, "");
|
|
78
|
+
res.writeHead(500, { "Content-Type": "text/html", Connection: "close" });
|
|
79
|
+
res.end(html);
|
|
80
|
+
onError(e instanceof Error ? e : new Error(String(e)));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
export const getLoginPageUrl = () => `http://${LOOPBACK_HOST}:${LOOPBACK_PORT}/login`;
|
|
84
|
+
export const listenToOAuthCallback = ({ state, nonce, codeVerifier, authorizeUrl, }) => {
|
|
85
|
+
return new Promise((resolve, reject) => {
|
|
86
|
+
const callbackServer = createCallbackServer({
|
|
87
|
+
state,
|
|
88
|
+
nonce,
|
|
89
|
+
codeVerifier,
|
|
90
|
+
authorizeUrl,
|
|
91
|
+
onSuccess: (storedToken) => {
|
|
92
|
+
callbackServer.close();
|
|
93
|
+
resolve(storedToken);
|
|
94
|
+
},
|
|
95
|
+
onError: (err) => {
|
|
96
|
+
callbackServer.close();
|
|
97
|
+
reject(err);
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
callbackServer.listen(LOOPBACK_PORT, LOOPBACK_HOST);
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/lib/auth/oauth/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type WhoamiInfo = {
|
|
2
|
+
method: "api_key";
|
|
3
|
+
team: {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
};
|
|
7
|
+
} | {
|
|
8
|
+
method: "oauth";
|
|
9
|
+
email: string;
|
|
10
|
+
name: string;
|
|
11
|
+
} | null;
|
|
12
|
+
export declare function getWhoamiInfo(): Promise<{
|
|
13
|
+
method: string;
|
|
14
|
+
team: {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
createdAt: Date;
|
|
18
|
+
hasStripeAccount: boolean;
|
|
19
|
+
hasActiveSubscription: boolean;
|
|
20
|
+
} | undefined;
|
|
21
|
+
email?: undefined;
|
|
22
|
+
name?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
method: string;
|
|
25
|
+
email: string | undefined;
|
|
26
|
+
name: string | undefined;
|
|
27
|
+
team?: undefined;
|
|
28
|
+
} | null>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { api } from "../../api.js";
|
|
2
|
+
import { oAuthClient } from "./oauth/client.js";
|
|
3
|
+
export async function getWhoamiInfo() {
|
|
4
|
+
if (process.env.ALPIC_API_KEY !== undefined) {
|
|
5
|
+
const team = await getApiKeyTeam();
|
|
6
|
+
return {
|
|
7
|
+
method: "api_key",
|
|
8
|
+
team,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
const token = await oAuthClient.getValidAccessToken();
|
|
12
|
+
if (!token)
|
|
13
|
+
return null;
|
|
14
|
+
const userInfo = await fetchOAuthUserInfo(token);
|
|
15
|
+
if (!userInfo)
|
|
16
|
+
return null;
|
|
17
|
+
return {
|
|
18
|
+
method: "oauth",
|
|
19
|
+
email: userInfo.email,
|
|
20
|
+
name: userInfo.name,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async function fetchOAuthUserInfo(credentials) {
|
|
24
|
+
try {
|
|
25
|
+
return await oAuthClient.fetchUserInfo(credentials);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function getApiKeyTeam() {
|
|
32
|
+
const teams = await api.teams.list.v1();
|
|
33
|
+
return teams[0];
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=whoami.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../../src/lib/auth/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAOhD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,MAAM,aAAa,EAAE,CAAC;QACnC,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,IAAI;SACL,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,mBAAmB,EAAE,CAAC;IACtD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACjD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,OAAO;QACL,MAAM,EAAE,OAAO;QACf,KAAK,EAAE,QAAQ,CAAC,KAAK;QACrB,IAAI,EAAE,QAAQ,CAAC,IAAI;KACpB,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,WAAwB;IACxD,IAAI,CAAC;QACH,OAAO,MAAM,WAAW,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IACtD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa;IAC1B,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;IACxC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ProjectConfig } from "../types.js";
|
|
2
|
+
export declare const config: {
|
|
3
|
+
load: (deployDir: string) => {
|
|
4
|
+
projectId: string;
|
|
5
|
+
teamId: string;
|
|
6
|
+
projectName: string;
|
|
7
|
+
environmentId: string | undefined;
|
|
8
|
+
environmentName: string | undefined;
|
|
9
|
+
} | null;
|
|
10
|
+
save: (config: ProjectConfig, deployDir: string) => void;
|
|
11
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
const getProjectJsonPath = (deployDir) => join(deployDir, ".alpic", "project.json");
|
|
4
|
+
export const config = {
|
|
5
|
+
load: (deployDir) => {
|
|
6
|
+
const path = getProjectJsonPath(deployDir);
|
|
7
|
+
if (!existsSync(path)) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
let raw;
|
|
11
|
+
try {
|
|
12
|
+
raw = JSON.parse(readFileSync(path, "utf8"));
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new Error(`Failed to load project config: ${error.message}`);
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
projectId: raw.projectId,
|
|
19
|
+
teamId: raw.teamId,
|
|
20
|
+
projectName: raw.projectName ?? raw.projectId,
|
|
21
|
+
environmentId: raw.environmentId,
|
|
22
|
+
environmentName: raw.environmentName,
|
|
23
|
+
};
|
|
24
|
+
},
|
|
25
|
+
save: (config, deployDir) => {
|
|
26
|
+
const path = getProjectJsonPath(deployDir);
|
|
27
|
+
mkdirSync(join(deployDir, ".alpic"), { recursive: true });
|
|
28
|
+
writeFileSync(path, JSON.stringify(config, null, 2));
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,MAAM,kBAAkB,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;AAE5F,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,EAAE,CAAC,SAAiB,EAAE,EAAE;QAC1B,MAAM,IAAI,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,GAAmE,CAAC;QACxE,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAG1C,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,kCAAmC,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,OAAO;YACL,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,SAAS;YAC7C,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,eAAe,EAAE,GAAG,CAAC,eAAe;SACrC,CAAC;IACJ,CAAC;IACD,IAAI,EAAE,CAAC,MAAqB,EAAE,SAAiB,EAAE,EAAE;QACjD,MAAM,IAAI,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAC3C,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1D,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { RouterOutput } from "@alpic-ai/api";
|
|
2
|
+
export declare function formatElapsed(ms: number): string;
|
|
3
|
+
export declare function deployAndWait({ initial, startedAt, }: {
|
|
4
|
+
initial: RouterOutput["deployments"]["get"]["v1"];
|
|
5
|
+
startedAt: number;
|
|
6
|
+
}): Promise<{
|
|
7
|
+
deployment: {
|
|
8
|
+
id: string;
|
|
9
|
+
status: "ongoing" | "deployed" | "failed" | "canceled";
|
|
10
|
+
sourceRef: string | null;
|
|
11
|
+
sourceCommitId: string | null;
|
|
12
|
+
sourceCommitMessage: string | null;
|
|
13
|
+
authorUsername: string | null;
|
|
14
|
+
authorAvatarUrl: string | null;
|
|
15
|
+
startedAt: Date | null;
|
|
16
|
+
completedAt: Date | null;
|
|
17
|
+
deploymentPageUrl: string | null;
|
|
18
|
+
};
|
|
19
|
+
elapsedMs: number;
|
|
20
|
+
}>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { api } from "../api.js";
|
|
4
|
+
import { env } from "../env.js";
|
|
5
|
+
export function formatElapsed(ms) {
|
|
6
|
+
const totalSeconds = Math.floor(ms / 1000);
|
|
7
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
8
|
+
const seconds = totalSeconds % 60;
|
|
9
|
+
return minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
|
10
|
+
}
|
|
11
|
+
export async function deployAndWait({ initial, startedAt, }) {
|
|
12
|
+
const spinner = p.spinner();
|
|
13
|
+
let deployment = initial;
|
|
14
|
+
const deploymentPageUrl = deployment.deploymentPageUrl;
|
|
15
|
+
if (deploymentPageUrl) {
|
|
16
|
+
p.note(`🔗 ${deploymentPageUrl}`, "View deployment details:", { format: (line) => line });
|
|
17
|
+
}
|
|
18
|
+
spinner.start("Deployment in progress");
|
|
19
|
+
const FIFTEEN_MINUTES_IN_MS = 15 * 60 * 1000; // 15 minutes
|
|
20
|
+
const elapsedInterval = setInterval(() => {
|
|
21
|
+
const elapsed = formatElapsed(Date.now() - startedAt);
|
|
22
|
+
spinner.message(`Deployment in progress — ${elapsed}`);
|
|
23
|
+
}, 1000);
|
|
24
|
+
try {
|
|
25
|
+
while (deployment.status === "ongoing") {
|
|
26
|
+
const elapsedMs = Date.now() - startedAt;
|
|
27
|
+
if (elapsedMs >= FIFTEEN_MINUTES_IN_MS) {
|
|
28
|
+
throw new Error(`Deployment aborted after 15 minutes. View status: ${deploymentPageUrl}`);
|
|
29
|
+
}
|
|
30
|
+
deployment = await api.deployments.get.v1({ deploymentId: deployment.id });
|
|
31
|
+
if (deployment.status === "ongoing") {
|
|
32
|
+
await new Promise((resolve) => setTimeout(resolve, 10_000));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return { deployment, elapsedMs: Date.now() - startedAt };
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
const message = deployment.status === "deployed" ? chalk.green("Deployment completed") : chalk.red("Deployment failed");
|
|
39
|
+
spinner.stop(message);
|
|
40
|
+
clearInterval(elapsedInterval);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=deployment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deployment.js","sourceRoot":"","sources":["../../src/lib/deployment.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhC,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;IAC9C,MAAM,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;IAClC,OAAO,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,EAClC,OAAO,EACP,SAAS,GAIV;IACC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAE5B,IAAI,UAAU,GAAG,OAAO,CAAC;IACzB,MAAM,iBAAiB,GAAG,UAAU,CAAC,iBAAiB,CAAC;IACvD,IAAI,iBAAiB,EAAE,CAAC;QACtB,CAAC,CAAC,IAAI,CAAC,MAAM,iBAAiB,EAAE,EAAE,0BAA0B,EAAE,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACxC,MAAM,qBAAqB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;IAC3D,MAAM,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;QACvC,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;QACtD,OAAO,CAAC,OAAO,CAAC,4BAA4B,OAAO,EAAE,CAAC,CAAC;IACzD,CAAC,EAAE,IAAI,CAAC,CAAC;IACT,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACvC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YACzC,IAAI,SAAS,IAAI,qBAAqB,EAAE,CAAC;gBACvC,MAAM,IAAI,KAAK,CAAC,qDAAqD,iBAAiB,EAAE,CAAC,CAAC;YAC5F,CAAC;YACD,UAAU,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3E,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBACpC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;QACD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,CAAC;IAC3D,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,GACX,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAC1G,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtB,aAAa,CAAC,eAAe,CAAC,CAAC;IACjC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type GitRemote = {
|
|
2
|
+
name: string;
|
|
3
|
+
url: string;
|
|
4
|
+
sourceRepository: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function isGitRepository(cwd: string): boolean;
|
|
7
|
+
export declare function listGithubRemotes(cwd: string): GitRemote[];
|
|
8
|
+
export type ProjectWithSourceRepository = {
|
|
9
|
+
name: string;
|
|
10
|
+
sourceRepository: string | null;
|
|
11
|
+
};
|
|
12
|
+
export declare function confirmLinkAnotherIfAlreadyConnected(project: ProjectWithSourceRepository): Promise<boolean>;
|
|
13
|
+
export declare function selectRemoteSourceRepository(remotes: GitRemote[]): Promise<string | null>;
|
|
14
|
+
export declare function showGitSetupInstructions(): void;
|
package/dist/lib/git.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { execFileSync } from "node:child_process";
|
|
4
|
+
function runGit(args, cwd) {
|
|
5
|
+
return execFileSync("git", args, {
|
|
6
|
+
cwd,
|
|
7
|
+
encoding: "utf8",
|
|
8
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
9
|
+
}).trim();
|
|
10
|
+
}
|
|
11
|
+
export function isGitRepository(cwd) {
|
|
12
|
+
try {
|
|
13
|
+
return runGit(["rev-parse", "--is-inside-work-tree"], cwd) === "true";
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function listGithubRemotes(cwd) {
|
|
20
|
+
let output;
|
|
21
|
+
try {
|
|
22
|
+
output = runGit(["remote", "-v"], cwd);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const remotes = new Map();
|
|
28
|
+
for (const line of output.split(/\r?\n/)) {
|
|
29
|
+
const match = line.match(/^(\S+)\s+(\S+)\s+\((fetch|push)\)$/);
|
|
30
|
+
if (!match)
|
|
31
|
+
continue;
|
|
32
|
+
const name = match[1];
|
|
33
|
+
const url = match[2];
|
|
34
|
+
const kind = match[3];
|
|
35
|
+
if (!name || !url || !kind)
|
|
36
|
+
continue;
|
|
37
|
+
if (kind !== "fetch")
|
|
38
|
+
continue;
|
|
39
|
+
const key = `${name}:${url}`;
|
|
40
|
+
const sourceRepository = parseGitHubSourceRepository(url);
|
|
41
|
+
if (sourceRepository) {
|
|
42
|
+
remotes.set(key, {
|
|
43
|
+
name,
|
|
44
|
+
url,
|
|
45
|
+
sourceRepository,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return [...remotes.values()];
|
|
50
|
+
}
|
|
51
|
+
export async function confirmLinkAnotherIfAlreadyConnected(project) {
|
|
52
|
+
if (!project.sourceRepository) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
p.log.info(`Project "${project.name}" is already connected to "${project.sourceRepository}".`);
|
|
56
|
+
const confirm = await p.confirm({
|
|
57
|
+
message: chalk.bold("Do you want to link another repository?"),
|
|
58
|
+
initialValue: false,
|
|
59
|
+
});
|
|
60
|
+
if (p.isCancel(confirm) || !confirm) {
|
|
61
|
+
p.cancel("Git connect cancelled");
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
export async function selectRemoteSourceRepository(remotes) {
|
|
67
|
+
if (remotes.length === 0) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const selected = await p.select({
|
|
71
|
+
message: chalk.bold("Choose the remote source to connect"),
|
|
72
|
+
options: remotes.map((remote) => ({
|
|
73
|
+
value: remote.sourceRepository,
|
|
74
|
+
label: `${remote.sourceRepository} (${remote.name})`,
|
|
75
|
+
hint: remote.url,
|
|
76
|
+
})),
|
|
77
|
+
});
|
|
78
|
+
if (p.isCancel(selected)) {
|
|
79
|
+
p.cancel("Git connect cancelled");
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return selected;
|
|
83
|
+
}
|
|
84
|
+
export function showGitSetupInstructions() {
|
|
85
|
+
p.note([
|
|
86
|
+
`Run ${chalk.cyan("git init")} in this directory`,
|
|
87
|
+
`Add a remote: ${chalk.cyan("git remote add origin <your-repo-url>")}`,
|
|
88
|
+
`Then run ${chalk.cyan("alpic git connect")} again`,
|
|
89
|
+
].join("\n"), "To set up a git repository:", { format: (line) => line });
|
|
90
|
+
}
|
|
91
|
+
function parseGitHubSourceRepository(url) {
|
|
92
|
+
const patterns = [
|
|
93
|
+
/^git@github\.com:([^/\s]+\/[^/\s]+?)(?:\.git)?$/,
|
|
94
|
+
/^https:\/\/github\.com\/([^/\s]+\/[^/\s]+?)(?:\.git)?\/?$/,
|
|
95
|
+
/^ssh:\/\/git@github\.com\/([^/\s]+\/[^/\s]+?)(?:\.git)?\/?$/,
|
|
96
|
+
];
|
|
97
|
+
for (const pattern of patterns) {
|
|
98
|
+
const match = url.match(pattern);
|
|
99
|
+
if (match) {
|
|
100
|
+
return match[1] ?? null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface Credentials {
|
|
2
|
+
access_token: string;
|
|
3
|
+
refresh_token: string;
|
|
4
|
+
expires_at: number;
|
|
5
|
+
sub: string;
|
|
6
|
+
}
|
|
7
|
+
export interface Config {
|
|
8
|
+
machineId: string;
|
|
9
|
+
telemetry: {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export declare class GlobalStore {
|
|
14
|
+
private readonly configDir;
|
|
15
|
+
constructor(configDir?: string);
|
|
16
|
+
getCredentials(): Credentials | null;
|
|
17
|
+
saveCredentials(credentials: Credentials): void;
|
|
18
|
+
clearCredentials(): void;
|
|
19
|
+
getConfig(): Config;
|
|
20
|
+
saveConfig(config: Config): void;
|
|
21
|
+
clearConfig(): void;
|
|
22
|
+
private getCredentialsFilePath;
|
|
23
|
+
private getConfigFilePath;
|
|
24
|
+
private parseJsonFile;
|
|
25
|
+
private saveJsonFile;
|
|
26
|
+
private clear;
|
|
27
|
+
}
|
|
28
|
+
export declare const globalStore: GlobalStore;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import XDGAppPaths from "xdg-app-paths";
|
|
5
|
+
export class GlobalStore {
|
|
6
|
+
configDir;
|
|
7
|
+
constructor(configDir) {
|
|
8
|
+
this.configDir = configDir ?? XDGAppPaths({ name: "alpic" }).config();
|
|
9
|
+
}
|
|
10
|
+
getCredentials() {
|
|
11
|
+
const token = this.parseJsonFile(this.getCredentialsFilePath());
|
|
12
|
+
if (!token) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return token;
|
|
16
|
+
}
|
|
17
|
+
saveCredentials(credentials) {
|
|
18
|
+
this.saveJsonFile(this.getCredentialsFilePath(), credentials);
|
|
19
|
+
}
|
|
20
|
+
clearCredentials() {
|
|
21
|
+
this.clear(this.getCredentialsFilePath());
|
|
22
|
+
}
|
|
23
|
+
getConfig() {
|
|
24
|
+
const existing = this.parseJsonFile(this.getConfigFilePath());
|
|
25
|
+
if (existing?.machineId && existing?.telemetry !== undefined) {
|
|
26
|
+
return existing;
|
|
27
|
+
}
|
|
28
|
+
const config = {
|
|
29
|
+
machineId: existing?.machineId ?? crypto.randomUUID(),
|
|
30
|
+
telemetry: {
|
|
31
|
+
enabled: existing?.telemetry?.enabled ?? true,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
this.saveConfig(config);
|
|
35
|
+
return config;
|
|
36
|
+
}
|
|
37
|
+
saveConfig(config) {
|
|
38
|
+
this.saveJsonFile(this.getConfigFilePath(), config);
|
|
39
|
+
}
|
|
40
|
+
clearConfig() {
|
|
41
|
+
this.clear(this.getConfigFilePath());
|
|
42
|
+
}
|
|
43
|
+
getCredentialsFilePath() {
|
|
44
|
+
return join(this.configDir, "credentials.json");
|
|
45
|
+
}
|
|
46
|
+
getConfigFilePath() {
|
|
47
|
+
return join(this.configDir, "config.json");
|
|
48
|
+
}
|
|
49
|
+
parseJsonFile(filePath) {
|
|
50
|
+
if (!existsSync(filePath)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
return JSON.parse(readFileSync(filePath, "utf-8"));
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
this.clear(filePath);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
saveJsonFile(filePath, data) {
|
|
62
|
+
mkdirSync(this.configDir, { recursive: true });
|
|
63
|
+
writeFileSync(filePath, JSON.stringify(data, null, 2), {
|
|
64
|
+
encoding: "utf-8",
|
|
65
|
+
mode: 0o600,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
clear(filePath) {
|
|
69
|
+
if (existsSync(filePath)) {
|
|
70
|
+
unlinkSync(filePath);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export const globalStore = new GlobalStore();
|
|
75
|
+
//# sourceMappingURL=global-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-store.js","sourceRoot":"","sources":["../../src/lib/global-store.ts"],"names":[],"mappings":"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"}
|