alpic 0.0.0-dev.f233893 → 0.0.0-dev.f2a3434
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__/deploy.e2e.test.d.ts +1 -0
- package/dist/__tests__/deploy.e2e.test.js +185 -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 +180 -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 +445 -0
- package/dist/__tests__/mock-server.js.map +1 -0
- package/dist/__tests__/utils.d.ts +55 -0
- package/dist/__tests__/utils.js +174 -0
- package/dist/__tests__/utils.js.map +1 -0
- package/dist/api.d.ts +3 -15
- package/dist/api.js +11 -54
- package/dist/api.js.map +1 -1
- package/dist/commands/deploy.d.ts +2 -2
- package/dist/commands/deploy.js +11 -11
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/git/connect.d.ts +9 -0
- package/dist/commands/git/connect.js +65 -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 +55 -0
- package/dist/commands/git/disconnect.js.map +1 -0
- package/dist/commands/git.d.ts +6 -0
- package/dist/commands/git.js +17 -0
- package/dist/commands/git.js.map +1 -0
- package/dist/commands/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/lib/alpic-command.d.ts +4 -0
- package/dist/lib/alpic-command.js +20 -0
- package/dist/lib/alpic-command.js.map +1 -0
- package/dist/lib/auth.d.ts +1 -0
- package/dist/lib/auth.js +10 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/deployment.d.ts +13 -3
- package/dist/lib/deployment.js +3 -3
- package/dist/lib/deployment.js.map +1 -1
- package/dist/lib/git.d.ts +14 -0
- package/dist/lib/git.js +106 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/global-config.d.ts +9 -0
- package/dist/lib/global-config.js +48 -0
- package/dist/lib/global-config.js.map +1 -0
- package/dist/lib/project.d.ts +61 -5
- package/dist/lib/project.js +141 -17
- package/dist/lib/project.js.map +1 -1
- 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/posthog.d.ts +3 -0
- package/dist/posthog.js +10 -0
- package/dist/posthog.js.map +1 -0
- package/dist/types.d.ts +0 -35
- package/package.json +21 -6
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { getMachineId, isEnabled } from "../../lib/telemetry.js";
|
|
4
|
+
export default class TelemetryStatus extends Command {
|
|
5
|
+
static description = "Show Alpic telemetry settings for this machine";
|
|
6
|
+
async run() {
|
|
7
|
+
await this.parse(TelemetryStatus);
|
|
8
|
+
const enabled = isEnabled();
|
|
9
|
+
console.log(chalk.bold.underline("Alpic Telemetry"));
|
|
10
|
+
console.log();
|
|
11
|
+
console.log("Status:", enabled ? chalk.green.bold("Enabled") : chalk.yellow.bold("Disabled"));
|
|
12
|
+
console.log(chalk.gray("Machine ID:"), getMachineId());
|
|
13
|
+
console.log();
|
|
14
|
+
console.log(chalk.gray("To opt out, run: alpic telemetry disable"));
|
|
15
|
+
console.log(chalk.gray("Or set: ALPIC_TELEMETRY_DISABLED=1"));
|
|
16
|
+
console.log(chalk.gray("Debug mode: ALPIC_TELEMETRY_DEBUG=1"));
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/telemetry/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,OAAO;IAClD,MAAM,CAAU,WAAW,GAAG,gDAAgD,CAAC;IAE/E,KAAK,CAAC,GAAG;QACP,MAAM,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAClC,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACrD,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAC9F,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC,CAAC;IACjE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import { Command } from "@oclif/core";
|
|
3
|
+
import { ORPCError } from "@orpc/client";
|
|
4
|
+
export class AlpicCommand extends Command {
|
|
5
|
+
async catch(error) {
|
|
6
|
+
if (error instanceof ORPCError) {
|
|
7
|
+
p.cancel(`An error occurred while connecting to Alpic: ${error.message}`);
|
|
8
|
+
this.exit(1);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (error instanceof Error) {
|
|
12
|
+
p.cancel(error.message);
|
|
13
|
+
this.exit(1);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
p.cancel(String(error));
|
|
17
|
+
this.exit(1);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=alpic-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alpic-command.js","sourceRoot":"","sources":["../../src/lib/alpic-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,MAAM,OAAgB,YAAa,SAAQ,OAAO;IACvC,KAAK,CAAC,KAAK,CAAC,KAAc;QACjC,IAAI,KAAK,YAAY,SAAS,EAAE,CAAC;YAC/B,CAAC,CAAC,MAAM,CAAC,gDAAgD,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1E,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACb,OAAO;QACT,CAAC;QACD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACb,OAAO;QACT,CAAC;QACD,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ensureApiKey(): boolean;
|
package/dist/lib/auth.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
export function ensureApiKey() {
|
|
3
|
+
const apiKey = process.env.ALPIC_API_KEY;
|
|
4
|
+
if (!apiKey) {
|
|
5
|
+
p.cancel("ALPIC_API_KEY environment variable is required. Get your API key from Team settings in the Alpic dashboard.");
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AAEpC,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;IACzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,CAAC,CAAC,MAAM,CACN,6GAA6G,CAC9G,CAAC;QACF,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/lib/deployment.d.ts
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RouterOutput } from "@alpic-ai/api";
|
|
2
2
|
export declare function formatElapsed(ms: number): string;
|
|
3
3
|
export declare function deployAndWait({ initial, startedAt, teamId, projectId, }: {
|
|
4
|
-
initial:
|
|
4
|
+
initial: RouterOutput["deployments"]["get"]["v1"];
|
|
5
5
|
startedAt: number;
|
|
6
6
|
teamId: string;
|
|
7
7
|
projectId: string;
|
|
8
8
|
}): Promise<{
|
|
9
|
-
deployment:
|
|
9
|
+
deployment: {
|
|
10
|
+
id: string;
|
|
11
|
+
status: "ongoing" | "deployed" | "failed" | "canceled";
|
|
12
|
+
sourceRef: string | null;
|
|
13
|
+
sourceCommitId: string | null;
|
|
14
|
+
sourceCommitMessage: string | null;
|
|
15
|
+
authorUsername: string | null;
|
|
16
|
+
authorAvatarUrl: string | null;
|
|
17
|
+
startedAt: Date | null;
|
|
18
|
+
completedAt: Date | null;
|
|
19
|
+
};
|
|
10
20
|
elapsedMs: number;
|
|
11
21
|
}>;
|
package/dist/lib/deployment.js
CHANGED
|
@@ -11,21 +11,21 @@ export async function deployAndWait({ initial, startedAt, teamId, projectId, })
|
|
|
11
11
|
const spinner = p.spinner();
|
|
12
12
|
spinner.start("Deployment in progress");
|
|
13
13
|
const deploymentPageUrl = `${getFrontendBaseUrl()}/team/${teamId}/project/${projectId}/deployments/${initial.id}`;
|
|
14
|
-
p.note(deploymentPageUrl, "View deployment details:");
|
|
14
|
+
p.note(deploymentPageUrl, "View deployment details:", { format: (line) => line });
|
|
15
15
|
const elapsedInterval = setInterval(() => {
|
|
16
16
|
const elapsed = formatElapsed(Date.now() - startedAt);
|
|
17
17
|
spinner.message(`Deployment in progress — ${elapsed}`);
|
|
18
18
|
}, 1000);
|
|
19
19
|
const timeoutMs = 15 * 60 * 1000; // 15 minutes
|
|
20
|
-
let deployment = initial;
|
|
20
|
+
let deployment = await api.deployments.get.v1({ deploymentId: initial.id });
|
|
21
21
|
try {
|
|
22
22
|
while (deployment.status === "ongoing") {
|
|
23
23
|
const elapsedMs = Date.now() - startedAt;
|
|
24
24
|
if (elapsedMs >= timeoutMs) {
|
|
25
25
|
throw new Error(`Deployment aborted after 15 minutes. View status: ${deploymentPageUrl}`);
|
|
26
26
|
}
|
|
27
|
+
deployment = await api.deployments.get.v1({ deploymentId: deployment.id });
|
|
27
28
|
await new Promise((resolve) => setTimeout(resolve, 10_000));
|
|
28
|
-
deployment = await api.getDeployment(deployment.id);
|
|
29
29
|
}
|
|
30
30
|
return { deployment, elapsedMs: Date.now() - startedAt };
|
|
31
31
|
}
|
|
@@ -1 +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;
|
|
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,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAEpD,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,EACT,MAAM,EACN,SAAS,GAMV;IACC,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAE5B,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAExC,MAAM,iBAAiB,GAAG,GAAG,kBAAkB,EAAE,SAAS,MAAM,YAAY,SAAS,gBAAgB,OAAO,CAAC,EAAE,EAAE,CAAC;IAClH,CAAC,CAAC,IAAI,CAAC,iBAAiB,EAAE,0BAA0B,EAAE,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;IAElF,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;IAET,MAAM,SAAS,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,aAAa;IAC/C,IAAI,UAAU,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5E,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,SAAS,EAAE,CAAC;gBAC3B,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,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAC9D,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,106 @@
|
|
|
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 === 1) {
|
|
68
|
+
p.log.info(`Using remote source repository "${remotes[0].sourceRepository}" (${remotes[0].name}).`);
|
|
69
|
+
return remotes[0].sourceRepository;
|
|
70
|
+
}
|
|
71
|
+
const selected = await p.select({
|
|
72
|
+
message: chalk.bold("Choose the remote source to connect"),
|
|
73
|
+
options: remotes.map((remote) => ({
|
|
74
|
+
value: remote.sourceRepository,
|
|
75
|
+
label: `${remote.sourceRepository} (${remote.name})`,
|
|
76
|
+
hint: remote.url,
|
|
77
|
+
})),
|
|
78
|
+
});
|
|
79
|
+
if (p.isCancel(selected)) {
|
|
80
|
+
p.cancel("Git connect cancelled");
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return selected;
|
|
84
|
+
}
|
|
85
|
+
export function showGitSetupInstructions() {
|
|
86
|
+
p.note([
|
|
87
|
+
`Run ${chalk.cyan("git init")} in this directory`,
|
|
88
|
+
`Add a remote: ${chalk.cyan("git remote add origin <your-repo-url>")}`,
|
|
89
|
+
`Then run ${chalk.cyan("alpic git connect")} again`,
|
|
90
|
+
].join("\n"), "To set up a git repository:", { format: (line) => line });
|
|
91
|
+
}
|
|
92
|
+
function parseGitHubSourceRepository(url) {
|
|
93
|
+
const patterns = [
|
|
94
|
+
/^git@github\.com:([^/\s]+\/[^/\s]+?)(?:\.git)?$/,
|
|
95
|
+
/^https:\/\/github\.com\/([^/\s]+\/[^/\s]+?)(?:\.git)?\/?$/,
|
|
96
|
+
/^ssh:\/\/git@github\.com\/([^/\s]+\/[^/\s]+?)(?:\.git)?\/?$/,
|
|
97
|
+
];
|
|
98
|
+
for (const pattern of patterns) {
|
|
99
|
+
const match = url.match(pattern);
|
|
100
|
+
if (match) {
|
|
101
|
+
return match[1] ?? null;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAQlD,SAAS,MAAM,CAAC,IAAc,EAAE,GAAW;IACzC,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE;QAC/B,GAAG;QACH,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;KAClC,CAAC,CAAC,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqB,CAAC;IAC7C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI;YAAE,SAAS;QACrC,IAAI,IAAI,KAAK,OAAO;YAAE,SAAS;QAE/B,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC;QAC7B,MAAM,gBAAgB,GAAG,2BAA2B,CAAC,GAAG,CAAC,CAAC;QAC1D,IAAI,gBAAgB,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE;gBACf,IAAI;gBACJ,GAAG;gBACH,gBAAgB;aACjB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAC/B,CAAC;AAOD,MAAM,CAAC,KAAK,UAAU,oCAAoC,CAAC,OAAoC;IAC7F,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,OAAO,CAAC,IAAI,8BAA8B,OAAO,CAAC,gBAAgB,IAAI,CAAC,CAAC;IAC/F,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC;QAC9B,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC;QAC9D,YAAY,EAAE,KAAK;KACpB,CAAC,CAAC;IACH,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACpC,CAAC,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,OAAoB;IACrE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,mCAAmC,OAAO,CAAC,CAAC,CAAE,CAAC,gBAAgB,MAAM,OAAO,CAAC,CAAC,CAAE,CAAC,IAAI,IAAI,CAAC,CAAC;QACtG,OAAO,OAAO,CAAC,CAAC,CAAE,CAAC,gBAAgB,CAAC;IACtC,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,MAAM,CAAS;QACtC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC;QAC1D,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAChC,KAAK,EAAE,MAAM,CAAC,gBAAgB;YAC9B,KAAK,EAAE,GAAG,MAAM,CAAC,gBAAgB,KAAK,MAAM,CAAC,IAAI,GAAG;YACpD,IAAI,EAAE,MAAM,CAAC,GAAG;SACjB,CAAC,CAAC;KACJ,CAAC,CAAC;IACH,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,CAAC,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,CAAC,CAAC,IAAI,CACJ;QACE,OAAO,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,oBAAoB;QACjD,iBAAiB,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,EAAE;QACtE,YAAY,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,QAAQ;KACpD,CAAC,IAAI,CAAC,IAAI,CAAC,EACZ,6BAA6B,EAC7B,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAC3B,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAAC,GAAW;IAC9C,MAAM,QAAQ,GAAG;QACf,iDAAiD;QACjD,2DAA2D;QAC3D,6DAA6D;KAC9D,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const GLOBAL_CONFIG_FILE: string;
|
|
2
|
+
export interface GlobalConfig {
|
|
3
|
+
machineId: string;
|
|
4
|
+
telemetry: {
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export declare function getGlobalConfig(): GlobalConfig;
|
|
9
|
+
export declare function saveGlobalConfig(config: GlobalConfig): void;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
const GLOBAL_CONFIG_DIR = join(homedir(), ".alpic");
|
|
6
|
+
export const GLOBAL_CONFIG_FILE = join(GLOBAL_CONFIG_DIR, "config.json");
|
|
7
|
+
function readJsonFile(filePath) {
|
|
8
|
+
try {
|
|
9
|
+
if (existsSync(filePath)) {
|
|
10
|
+
const content = readFileSync(filePath, "utf-8");
|
|
11
|
+
return JSON.parse(content);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// Ignore errors reading config
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
function writeJsonFile(filePath, data) {
|
|
20
|
+
try {
|
|
21
|
+
const dir = join(filePath, "..");
|
|
22
|
+
if (!existsSync(dir)) {
|
|
23
|
+
mkdirSync(dir, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Ignore errors writing config
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function getGlobalConfig() {
|
|
32
|
+
const existing = readJsonFile(GLOBAL_CONFIG_FILE);
|
|
33
|
+
if (existing?.machineId && existing?.telemetry !== undefined) {
|
|
34
|
+
return existing;
|
|
35
|
+
}
|
|
36
|
+
const config = {
|
|
37
|
+
machineId: existing?.machineId ?? crypto.randomUUID(),
|
|
38
|
+
telemetry: {
|
|
39
|
+
enabled: existing?.telemetry?.enabled ?? true,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
writeJsonFile(GLOBAL_CONFIG_FILE, config);
|
|
43
|
+
return config;
|
|
44
|
+
}
|
|
45
|
+
export function saveGlobalConfig(config) {
|
|
46
|
+
writeJsonFile(GLOBAL_CONFIG_FILE, config);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=global-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"global-config.js","sourceRoot":"","sources":["../../src/lib/global-config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;AASzE,SAAS,YAAY,CAAI,QAAgB;IACvC,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAM,CAAC;QAClC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,QAAgB,EAAE,IAAa;IACpD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;QACD,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAAG,YAAY,CAAe,kBAAkB,CAAC,CAAC;IAChE,IAAI,QAAQ,EAAE,SAAS,IAAI,QAAQ,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC;QAC7D,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAiB;QAC3B,SAAS,EAAE,QAAQ,EAAE,SAAS,IAAI,MAAM,CAAC,UAAU,EAAE;QACrD,SAAS,EAAE;YACT,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,IAAI,IAAI;SAC9C;KACF,CAAC;IACF,aAAa,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,aAAa,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;AAC5C,CAAC"}
|
package/dist/lib/project.d.ts
CHANGED
|
@@ -1,11 +1,67 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RouterOutput } from "@alpic-ai/api";
|
|
2
|
+
import type { ProjectConfig } from "../types.js";
|
|
2
3
|
export declare function resolveDeployDir(raw: string | undefined): string;
|
|
3
|
-
export declare function confirmDeployWithExistingConfig(existingConfig: ProjectConfig): Promise<boolean>;
|
|
4
|
-
export declare function selectEnvironmentFromList(environments:
|
|
5
|
-
|
|
4
|
+
export declare function confirmDeployWithExistingConfig(existingConfig: ProjectConfig): Promise<boolean | null>;
|
|
5
|
+
export declare function selectEnvironmentFromList(environments: RouterOutput["projects"]["get"]["v1"]["environments"]): Promise<{
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
sourceBranch: string | null;
|
|
9
|
+
mcpServerUrl: string;
|
|
10
|
+
createdAt: Date;
|
|
11
|
+
projectId: string;
|
|
12
|
+
latestDeployment: {
|
|
13
|
+
id: string;
|
|
14
|
+
status: "ongoing" | "deployed" | "failed" | "canceled";
|
|
15
|
+
sourceCommitId: string | null;
|
|
16
|
+
sourceCommitMessage: string | null;
|
|
17
|
+
completedAt: Date | null;
|
|
18
|
+
} | null;
|
|
19
|
+
} | null>;
|
|
20
|
+
export declare function confirmDeployDirectory(deployDir: string): Promise<boolean>;
|
|
6
21
|
export declare function confirmLinkExisting(): Promise<boolean>;
|
|
7
22
|
export declare function confirmLinkToAnotherProject(): Promise<boolean>;
|
|
8
|
-
export declare function selectProjectFromList(projects:
|
|
23
|
+
export declare function selectProjectFromList(projects: RouterOutput["projects"]["list"]["v1"]): Promise<{
|
|
24
|
+
id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
teamId: string;
|
|
27
|
+
sourceRepository: string | null;
|
|
28
|
+
runtime: "python3.13" | "python3.14" | "node22" | "node24";
|
|
29
|
+
transport: "stdio" | "sse" | "streamablehttp" | null;
|
|
30
|
+
rootDirectory: string | null;
|
|
31
|
+
buildCommand: string | null;
|
|
32
|
+
buildOutputDir: string | null;
|
|
33
|
+
installCommand: string | null;
|
|
34
|
+
startCommand: string | null;
|
|
35
|
+
createdAt: Date;
|
|
36
|
+
productionEnvironment: {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
mcpServerUrl: string;
|
|
40
|
+
latestDeployment: {
|
|
41
|
+
id: string;
|
|
42
|
+
status: "ongoing" | "deployed" | "failed" | "canceled";
|
|
43
|
+
sourceCommitId: string | null;
|
|
44
|
+
sourceCommitMessage: string | null;
|
|
45
|
+
completedAt: Date | null;
|
|
46
|
+
} | null;
|
|
47
|
+
} | null;
|
|
48
|
+
environments: {
|
|
49
|
+
id: string;
|
|
50
|
+
name: string;
|
|
51
|
+
sourceBranch: string | null;
|
|
52
|
+
mcpServerUrl: string;
|
|
53
|
+
createdAt: Date;
|
|
54
|
+
projectId: string;
|
|
55
|
+
latestDeployment: {
|
|
56
|
+
id: string;
|
|
57
|
+
status: "ongoing" | "deployed" | "failed" | "canceled";
|
|
58
|
+
sourceCommitId: string | null;
|
|
59
|
+
sourceCommitMessage: string | null;
|
|
60
|
+
completedAt: Date | null;
|
|
61
|
+
} | null;
|
|
62
|
+
}[];
|
|
63
|
+
} | null>;
|
|
64
|
+
export declare function promptRootDirectory(deployDir: string): Promise<string | null | undefined>;
|
|
9
65
|
export declare function resolveProjectForDeploy(deployDir: string): Promise<(ProjectConfig & {
|
|
10
66
|
environmentId: string;
|
|
11
67
|
}) | null>;
|
package/dist/lib/project.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import { existsSync, statSync } from "node:fs";
|
|
3
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
4
4
|
import { resolve } from "node:path";
|
|
5
5
|
import { api } from "../api.js";
|
|
6
6
|
import { config } from "./config.js";
|
|
@@ -21,7 +21,7 @@ export async function confirmDeployWithExistingConfig(existingConfig) {
|
|
|
21
21
|
initialValue: true,
|
|
22
22
|
});
|
|
23
23
|
if (p.isCancel(confirm))
|
|
24
|
-
return
|
|
24
|
+
return null;
|
|
25
25
|
return confirm === true;
|
|
26
26
|
}
|
|
27
27
|
export async function selectEnvironmentFromList(environments) {
|
|
@@ -32,7 +32,7 @@ export async function selectEnvironmentFromList(environments) {
|
|
|
32
32
|
message: chalk.bold("Choose an environment to deploy to"),
|
|
33
33
|
options: environments.map((env) => ({
|
|
34
34
|
value: env.id,
|
|
35
|
-
label: `${env.name} (${env.sourceBranch})
|
|
35
|
+
label: env.sourceBranch ? `${env.name} (${env.sourceBranch})` : env.name,
|
|
36
36
|
})),
|
|
37
37
|
});
|
|
38
38
|
if (p.isCancel(choice))
|
|
@@ -40,7 +40,7 @@ export async function selectEnvironmentFromList(environments) {
|
|
|
40
40
|
const environment = environments.find((e) => e.id === choice);
|
|
41
41
|
return environment ?? null;
|
|
42
42
|
}
|
|
43
|
-
export async function
|
|
43
|
+
export async function confirmDeployDirectory(deployDir) {
|
|
44
44
|
const confirm = await p.confirm({
|
|
45
45
|
message: chalk.bold(`Deploy the directory? `) + chalk.cyan(deployDir),
|
|
46
46
|
initialValue: true,
|
|
@@ -80,8 +80,37 @@ export async function selectProjectFromList(projects) {
|
|
|
80
80
|
const project = projects.find((proj) => proj.id === choice);
|
|
81
81
|
return project ?? null;
|
|
82
82
|
}
|
|
83
|
+
export async function promptRootDirectory(deployDir) {
|
|
84
|
+
while (true) {
|
|
85
|
+
const rootDir = await p.text({
|
|
86
|
+
message: chalk.bold("Root directory"),
|
|
87
|
+
placeholder: ".",
|
|
88
|
+
initialValue: ".",
|
|
89
|
+
validate: (value) => {
|
|
90
|
+
if (value != null && value.length > 512)
|
|
91
|
+
return "Path must be at most 512 characters.";
|
|
92
|
+
return undefined;
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
if (p.isCancel(rootDir))
|
|
96
|
+
return null;
|
|
97
|
+
const trimmed = rootDir.trim();
|
|
98
|
+
if (trimmed === "" || trimmed === ".")
|
|
99
|
+
return undefined;
|
|
100
|
+
const resolved = resolve(deployDir, trimmed);
|
|
101
|
+
if (!existsSync(resolved)) {
|
|
102
|
+
p.log.error(`Path does not exist: ${resolved}`);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (!statSync(resolved).isDirectory()) {
|
|
106
|
+
p.log.error(`Path is not a directory: ${resolved}`);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
return trimmed;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
83
112
|
async function resolveEnvironmentForProject(projectId) {
|
|
84
|
-
const project = await api.
|
|
113
|
+
const project = await api.projects.get.v1({ projectId });
|
|
85
114
|
const environments = project.environments ?? [];
|
|
86
115
|
if (environments.length === 0) {
|
|
87
116
|
throw new Error("No environments found for this project.");
|
|
@@ -92,14 +121,28 @@ async function resolveEnvironmentForProject(projectId) {
|
|
|
92
121
|
return { environmentId: environment.id, environmentName: environment.name };
|
|
93
122
|
}
|
|
94
123
|
export async function resolveProjectForDeploy(deployDir) {
|
|
124
|
+
const ok = await confirmDeployDirectory(deployDir);
|
|
125
|
+
if (!ok)
|
|
126
|
+
return null;
|
|
95
127
|
const existingConfig = config.load(deployDir);
|
|
96
128
|
if (existingConfig) {
|
|
97
|
-
|
|
98
|
-
|
|
129
|
+
let confirm;
|
|
130
|
+
while (true) {
|
|
131
|
+
confirm = await confirmDeployWithExistingConfig(existingConfig);
|
|
132
|
+
if (confirm === null)
|
|
133
|
+
return null;
|
|
134
|
+
if (confirm)
|
|
135
|
+
break;
|
|
99
136
|
const linkAnother = await confirmLinkToAnotherProject();
|
|
100
|
-
if (
|
|
137
|
+
if (p.isCancel(linkAnother))
|
|
101
138
|
return null;
|
|
102
|
-
|
|
139
|
+
if (linkAnother) {
|
|
140
|
+
const linkExisting = await confirmLinkExisting();
|
|
141
|
+
if (!linkExisting) {
|
|
142
|
+
return runCreateProjectFlow(deployDir);
|
|
143
|
+
}
|
|
144
|
+
return runLinkingFlow(deployDir);
|
|
145
|
+
}
|
|
103
146
|
}
|
|
104
147
|
if (existingConfig.environmentId) {
|
|
105
148
|
return {
|
|
@@ -119,21 +162,78 @@ export async function resolveProjectForDeploy(deployDir) {
|
|
|
119
162
|
environmentName: env.environmentName,
|
|
120
163
|
};
|
|
121
164
|
config.save(updatedConfig, deployDir);
|
|
122
|
-
p.note(`Environment "${env.environmentName}" will be used for future deploys
|
|
165
|
+
p.note(`Environment "${env.environmentName}" will be used for future deploys.`, undefined, {
|
|
166
|
+
format: (line) => line,
|
|
167
|
+
});
|
|
123
168
|
return updatedConfig;
|
|
124
169
|
}
|
|
125
|
-
const ok = await confirmDeployWithoutConfig(deployDir);
|
|
126
|
-
if (!ok)
|
|
127
|
-
return null;
|
|
128
170
|
const linkExisting = await confirmLinkExisting();
|
|
129
171
|
if (!linkExisting) {
|
|
130
|
-
|
|
131
|
-
return null;
|
|
172
|
+
return runCreateProjectFlow(deployDir);
|
|
132
173
|
}
|
|
133
174
|
return runLinkingFlow(deployDir);
|
|
134
175
|
}
|
|
176
|
+
async function runCreateProjectFlow(deployDir) {
|
|
177
|
+
const name = await p.text({
|
|
178
|
+
message: chalk.bold("Project name"),
|
|
179
|
+
placeholder: "my-app",
|
|
180
|
+
validate: (value) => {
|
|
181
|
+
if (!value?.trim())
|
|
182
|
+
return "Project name is required.";
|
|
183
|
+
if (value.length > 100)
|
|
184
|
+
return "Project name must be at most 100 characters.";
|
|
185
|
+
return undefined;
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
if (p.isCancel(name))
|
|
189
|
+
return null;
|
|
190
|
+
const detectedRuntime = detectRuntime(deployDir);
|
|
191
|
+
const runtime = await p.select({
|
|
192
|
+
message: chalk.bold("Runtime"),
|
|
193
|
+
options: [
|
|
194
|
+
{ value: "node24", label: "Node.js 24" },
|
|
195
|
+
{ value: "node22", label: "Node.js 22" },
|
|
196
|
+
{ value: "python3.14", label: "Python 3.14" },
|
|
197
|
+
{ value: "python3.13", label: "Python 3.13" },
|
|
198
|
+
],
|
|
199
|
+
initialValue: detectedRuntime ?? "node24",
|
|
200
|
+
});
|
|
201
|
+
if (p.isCancel(runtime))
|
|
202
|
+
return null;
|
|
203
|
+
const rootDirectory = await promptRootDirectory(deployDir);
|
|
204
|
+
const spin = p.spinner();
|
|
205
|
+
spin.start("Creating project...");
|
|
206
|
+
try {
|
|
207
|
+
const projectInput = {
|
|
208
|
+
name: name.trim(),
|
|
209
|
+
runtime,
|
|
210
|
+
};
|
|
211
|
+
if (rootDirectory) {
|
|
212
|
+
projectInput.rootDirectory = rootDirectory;
|
|
213
|
+
}
|
|
214
|
+
const created = await api.projects.create.v1(projectInput);
|
|
215
|
+
spin.stop("Project created.");
|
|
216
|
+
const productionEnv = created.productionEnvironment;
|
|
217
|
+
if (!productionEnv) {
|
|
218
|
+
throw new Error("Project was created but has no Production environment.");
|
|
219
|
+
}
|
|
220
|
+
const newConfig = {
|
|
221
|
+
projectId: created.id,
|
|
222
|
+
teamId: created.teamId,
|
|
223
|
+
projectName: created.name,
|
|
224
|
+
environmentId: productionEnv.id,
|
|
225
|
+
environmentName: productionEnv.name,
|
|
226
|
+
};
|
|
227
|
+
config.save(newConfig, deployDir);
|
|
228
|
+
return newConfig;
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
spin.stop();
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
135
235
|
async function runLinkingFlow(deployDir) {
|
|
136
|
-
const projects = await api.
|
|
236
|
+
const projects = await api.projects.list.v1();
|
|
137
237
|
if (projects.length === 0) {
|
|
138
238
|
throw new Error("No projects found. Create a project in the Alpic dashboard first.");
|
|
139
239
|
}
|
|
@@ -155,7 +255,31 @@ async function runLinkingFlow(deployDir) {
|
|
|
155
255
|
environmentName: environment.name,
|
|
156
256
|
};
|
|
157
257
|
config.save(newConfig, deployDir);
|
|
158
|
-
p.note(`Linked to project "${project.name}", environment "${environment.name}"
|
|
258
|
+
p.note(`Linked to project "${project.name}", environment "${environment.name}".`, undefined, {
|
|
259
|
+
format: (line) => line,
|
|
260
|
+
});
|
|
159
261
|
return newConfig;
|
|
160
262
|
}
|
|
263
|
+
function detectRuntime(dir) {
|
|
264
|
+
const has = (file) => existsSync(resolve(dir, file));
|
|
265
|
+
const read = (file) => {
|
|
266
|
+
try {
|
|
267
|
+
return readFileSync(resolve(dir, file), "utf8");
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
return "";
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
if (has("pyproject.toml") || has("requirements.txt") || has("setup.py") || has(".python-version")) {
|
|
274
|
+
return "python3.13";
|
|
275
|
+
}
|
|
276
|
+
if (has("package.json")) {
|
|
277
|
+
const nvmrc = has(".nvmrc") ? (read(".nvmrc").trim().split(/\s/)[0] ?? "") : "";
|
|
278
|
+
const major = nvmrc.replace(/^v/i, "").match(/^(\d+)/)?.[1];
|
|
279
|
+
if (major === "22")
|
|
280
|
+
return "node22";
|
|
281
|
+
return "node24";
|
|
282
|
+
}
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
161
285
|
//# sourceMappingURL=project.js.map
|