alpic 0.0.0-dev.c848d78 → 0.0.0-dev.c8f1fc4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/__tests__/deploy.e2e.test.d.ts +1 -0
  2. package/dist/__tests__/deploy.e2e.test.js +185 -0
  3. package/dist/__tests__/deploy.e2e.test.js.map +1 -0
  4. package/dist/__tests__/fixtures/demo-project/index.d.ts +1 -0
  5. package/dist/__tests__/fixtures/demo-project/index.js +4 -0
  6. package/dist/__tests__/fixtures/demo-project/index.js.map +1 -0
  7. package/dist/__tests__/git.e2e.test.d.ts +1 -0
  8. package/dist/__tests__/git.e2e.test.js +182 -0
  9. package/dist/__tests__/git.e2e.test.js.map +1 -0
  10. package/dist/__tests__/mock-server.d.ts +22 -0
  11. package/dist/__tests__/mock-server.js +435 -0
  12. package/dist/__tests__/mock-server.js.map +1 -0
  13. package/dist/__tests__/utils.d.ts +55 -0
  14. package/dist/__tests__/utils.js +174 -0
  15. package/dist/__tests__/utils.js.map +1 -0
  16. package/dist/api.d.ts +4 -0
  17. package/dist/api.js +19 -0
  18. package/dist/api.js.map +1 -0
  19. package/dist/commands/deploy.d.ts +9 -0
  20. package/dist/commands/deploy.js +86 -0
  21. package/dist/commands/deploy.js.map +1 -0
  22. package/dist/commands/git/connect.d.ts +9 -0
  23. package/dist/commands/git/connect.js +65 -0
  24. package/dist/commands/git/connect.js.map +1 -0
  25. package/dist/commands/git/disconnect.d.ts +9 -0
  26. package/dist/commands/git/disconnect.js +55 -0
  27. package/dist/commands/git/disconnect.js.map +1 -0
  28. package/dist/commands/{hello.d.ts → git.d.ts} +1 -1
  29. package/dist/commands/git.js +17 -0
  30. package/dist/commands/git.js.map +1 -0
  31. package/dist/commands/telemetry/disable.d.ts +5 -0
  32. package/dist/commands/telemetry/disable.js +14 -0
  33. package/dist/commands/telemetry/disable.js.map +1 -0
  34. package/dist/commands/telemetry/enable.d.ts +5 -0
  35. package/dist/commands/telemetry/enable.js +13 -0
  36. package/dist/commands/telemetry/enable.js.map +1 -0
  37. package/dist/commands/telemetry/status.d.ts +5 -0
  38. package/dist/commands/telemetry/status.js +19 -0
  39. package/dist/commands/telemetry/status.js.map +1 -0
  40. package/dist/lib/alpic-command.d.ts +4 -0
  41. package/dist/lib/alpic-command.js +20 -0
  42. package/dist/lib/alpic-command.js.map +1 -0
  43. package/dist/lib/archive.d.ts +7 -0
  44. package/dist/lib/archive.js +55 -0
  45. package/dist/lib/archive.js.map +1 -0
  46. package/dist/lib/auth.d.ts +1 -0
  47. package/dist/lib/auth.js +10 -0
  48. package/dist/lib/auth.js.map +1 -0
  49. package/dist/lib/config.d.ts +11 -0
  50. package/dist/lib/config.js +31 -0
  51. package/dist/lib/config.js.map +1 -0
  52. package/dist/lib/deployment.d.ts +21 -0
  53. package/dist/lib/deployment.js +38 -0
  54. package/dist/lib/deployment.js.map +1 -0
  55. package/dist/lib/git.d.ts +14 -0
  56. package/dist/lib/git.js +106 -0
  57. package/dist/lib/git.js.map +1 -0
  58. package/dist/lib/global-config.d.ts +9 -0
  59. package/dist/lib/global-config.js +48 -0
  60. package/dist/lib/global-config.js.map +1 -0
  61. package/dist/lib/project.d.ts +67 -0
  62. package/dist/lib/project.js +285 -0
  63. package/dist/lib/project.js.map +1 -0
  64. package/dist/lib/telemetry.d.ts +7 -0
  65. package/dist/lib/telemetry.js +66 -0
  66. package/dist/lib/telemetry.js.map +1 -0
  67. package/dist/lib/upload.d.ts +1 -0
  68. package/dist/lib/upload.js +14 -0
  69. package/dist/lib/upload.js.map +1 -0
  70. package/dist/posthog.d.ts +3 -0
  71. package/dist/posthog.js +10 -0
  72. package/dist/posthog.js.map +1 -0
  73. package/dist/types.d.ts +7 -0
  74. package/dist/types.js +2 -0
  75. package/dist/types.js.map +1 -0
  76. package/package.json +26 -6
  77. package/dist/commands/hello.js +0 -10
  78. package/dist/commands/hello.js.map +0 -1
@@ -0,0 +1,55 @@
1
+ import { execSync } from "node:child_process";
2
+ import { existsSync, mkdtempSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join, resolve } from "node:path";
5
+ import { create as tarCreate } from "tar";
6
+ const GIT_FILES_MAX_BUFFER = 10 * 1024 * 1024;
7
+ function isGitRepository(dir) {
8
+ return existsSync(join(resolve(dir), ".git"));
9
+ }
10
+ export function ensureGitAvailable() {
11
+ try {
12
+ execSync("git --version", { stdio: "ignore" });
13
+ }
14
+ catch {
15
+ throw new Error("Git is required to deploy. Please install git and ensure it is available in your PATH.");
16
+ }
17
+ }
18
+ export function getGitFiles(deployDir) {
19
+ const dir = resolve(deployDir);
20
+ const output = execSync("git ls-files -z --cached --others --exclude-standard -- .", {
21
+ cwd: dir,
22
+ encoding: "utf8",
23
+ maxBuffer: GIT_FILES_MAX_BUFFER,
24
+ });
25
+ const files = output.split("\0").filter(Boolean);
26
+ if (files.length === 0) {
27
+ throw new Error("No tracked or untracked files found. Ensure you are in a git repository with files to deploy.");
28
+ }
29
+ return files;
30
+ }
31
+ export function getFilesToPack(deployDir) {
32
+ const dir = resolve(deployDir);
33
+ if (isGitRepository(dir)) {
34
+ return getGitFiles(deployDir);
35
+ }
36
+ ensureGitAvailable();
37
+ execSync("git init", { cwd: dir });
38
+ try {
39
+ return getGitFiles(deployDir);
40
+ }
41
+ finally {
42
+ rmSync(join(dir, ".git"), { recursive: true });
43
+ }
44
+ }
45
+ export async function createTarArchive(files, deployDir) {
46
+ const tmpDir = mkdtempSync(join(tmpdir(), "alpic-deploy-"));
47
+ const archivePath = join(tmpDir, "source.tar.gz");
48
+ await tarCreate({
49
+ gzip: true,
50
+ file: archivePath,
51
+ cwd: deployDir,
52
+ }, files);
53
+ return { tmpDir, archivePath };
54
+ }
55
+ //# sourceMappingURL=archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/lib/archive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,KAAK,CAAC;AAE1C,MAAM,oBAAoB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9C,SAAS,eAAe,CAAC,GAAW;IAClC,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC;QACH,QAAQ,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,wFAAwF,CAAC,CAAC;IAC5G,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,SAAiB;IAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,QAAQ,CAAC,2DAA2D,EAAE;QACnF,GAAG,EAAE,GAAG;QACR,QAAQ,EAAE,MAAM;QAChB,SAAS,EAAE,oBAAoB;KAChC,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,+FAA+F,CAAC,CAAC;IACnH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;IACD,kBAAkB,EAAE,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAe,EAAE,SAAiB;IACvE,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC;IAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAClD,MAAM,SAAS,CACb;QACE,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,WAAW;QACjB,GAAG,EAAE,SAAS;KACf,EACD,KAAK,CACN,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;AACjC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function ensureApiKey(): boolean;
@@ -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"}
@@ -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,21 @@
1
+ import type { RouterOutput } from "@alpic-ai/api";
2
+ export declare function formatElapsed(ms: number): string;
3
+ export declare function deployAndWait({ initial, startedAt, teamId, projectId, }: {
4
+ initial: RouterOutput["deployments"]["get"]["v1"];
5
+ startedAt: number;
6
+ teamId: string;
7
+ projectId: string;
8
+ }): Promise<{
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
+ };
20
+ elapsedMs: number;
21
+ }>;
@@ -0,0 +1,38 @@
1
+ import * as p from "@clack/prompts";
2
+ import chalk from "chalk";
3
+ import { api, getFrontendBaseUrl } from "../api.js";
4
+ export function formatElapsed(ms) {
5
+ const totalSeconds = Math.floor(ms / 1000);
6
+ const minutes = Math.floor(totalSeconds / 60);
7
+ const seconds = totalSeconds % 60;
8
+ return minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
9
+ }
10
+ export async function deployAndWait({ initial, startedAt, teamId, projectId, }) {
11
+ const spinner = p.spinner();
12
+ spinner.start("Deployment in progress");
13
+ const deploymentPageUrl = `${getFrontendBaseUrl()}/team/${teamId}/project/${projectId}/deployments/${initial.id}`;
14
+ p.note(deploymentPageUrl, "View deployment details:", { format: (line) => line });
15
+ const elapsedInterval = setInterval(() => {
16
+ const elapsed = formatElapsed(Date.now() - startedAt);
17
+ spinner.message(`Deployment in progress — ${elapsed}`);
18
+ }, 1000);
19
+ const timeoutMs = 15 * 60 * 1000; // 15 minutes
20
+ let deployment = await api.deployments.get.v1({ deploymentId: initial.id });
21
+ try {
22
+ while (deployment.status === "ongoing") {
23
+ const elapsedMs = Date.now() - startedAt;
24
+ if (elapsedMs >= timeoutMs) {
25
+ throw new Error(`Deployment aborted after 15 minutes. View status: ${deploymentPageUrl}`);
26
+ }
27
+ deployment = await api.deployments.get.v1({ deploymentId: deployment.id });
28
+ await new Promise((resolve) => setTimeout(resolve, 10_000));
29
+ }
30
+ return { deployment, elapsedMs: Date.now() - startedAt };
31
+ }
32
+ finally {
33
+ const message = deployment.status === "deployed" ? chalk.green("Deployment completed") : chalk.red("Deployment failed");
34
+ spinner.stop(message);
35
+ clearInterval(elapsedInterval);
36
+ }
37
+ }
38
+ //# 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,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;
@@ -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":"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"}
@@ -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"}
@@ -0,0 +1,67 @@
1
+ import type { RouterOutput } from "@alpic-ai/api";
2
+ import type { ProjectConfig } from "../types.js";
3
+ export declare function resolveDeployDir(raw: string | undefined): string;
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>;
21
+ export declare function confirmLinkExisting(): Promise<boolean>;
22
+ export declare function confirmLinkToAnotherProject(): Promise<boolean>;
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>;
65
+ export declare function resolveProjectForDeploy(deployDir: string): Promise<(ProjectConfig & {
66
+ environmentId: string;
67
+ }) | null>;