alpic 0.0.0-dev.f2f58a6 → 0.0.0-dev.f330b89

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 (178) hide show
  1. package/dist/__tests__/auth.e2e.test.d.ts +1 -0
  2. package/dist/__tests__/auth.e2e.test.js +158 -0
  3. package/dist/__tests__/auth.e2e.test.js.map +1 -0
  4. package/dist/__tests__/deploy-flags.e2e.test.d.ts +1 -0
  5. package/dist/__tests__/deploy-flags.e2e.test.js +111 -0
  6. package/dist/__tests__/deploy-flags.e2e.test.js.map +1 -0
  7. package/dist/__tests__/deploy.e2e.test.js +51 -150
  8. package/dist/__tests__/deploy.e2e.test.js.map +1 -1
  9. package/dist/__tests__/deployment-inspect.e2e.test.d.ts +1 -0
  10. package/dist/__tests__/deployment-inspect.e2e.test.js +113 -0
  11. package/dist/__tests__/deployment-inspect.e2e.test.js.map +1 -0
  12. package/dist/__tests__/deployment-list.e2e.test.d.ts +1 -0
  13. package/dist/__tests__/deployment-list.e2e.test.js +116 -0
  14. package/dist/__tests__/deployment-list.e2e.test.js.map +1 -0
  15. package/dist/__tests__/deployment-logs.e2e.test.d.ts +1 -0
  16. package/dist/__tests__/deployment-logs.e2e.test.js +255 -0
  17. package/dist/__tests__/deployment-logs.e2e.test.js.map +1 -0
  18. package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.d.ts +1 -0
  19. package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.js +260 -0
  20. package/dist/__tests__/environment-variable/environment-variable-add.e2e.test.js.map +1 -0
  21. package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.d.ts +1 -0
  22. package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.js +140 -0
  23. package/dist/__tests__/environment-variable/environment-variable-list.e2e.test.js.map +1 -0
  24. package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.d.ts +1 -0
  25. package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.js +151 -0
  26. package/dist/__tests__/environment-variable/environment-variable-remove.e2e.test.js.map +1 -0
  27. package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.d.ts +1 -0
  28. package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.js +343 -0
  29. package/dist/__tests__/environment-variable/environment-variable-update.e2e.test.js.map +1 -0
  30. package/dist/__tests__/environment-variable/environment-variable-validation.test.d.ts +1 -0
  31. package/dist/__tests__/environment-variable/environment-variable-validation.test.js +20 -0
  32. package/dist/__tests__/environment-variable/environment-variable-validation.test.js.map +1 -0
  33. package/dist/__tests__/fixtures/demo-project/index.js +1 -1
  34. package/dist/__tests__/fixtures/demo-project/index.js.map +1 -1
  35. package/dist/__tests__/git-flags.e2e.test.d.ts +1 -0
  36. package/dist/__tests__/git-flags.e2e.test.js +124 -0
  37. package/dist/__tests__/git-flags.e2e.test.js.map +1 -0
  38. package/dist/__tests__/git.e2e.test.d.ts +1 -0
  39. package/dist/__tests__/git.e2e.test.js +221 -0
  40. package/dist/__tests__/git.e2e.test.js.map +1 -0
  41. package/dist/__tests__/logs.e2e.test.d.ts +1 -0
  42. package/dist/__tests__/logs.e2e.test.js +227 -0
  43. package/dist/__tests__/logs.e2e.test.js.map +1 -0
  44. package/dist/__tests__/mock-server.d.ts +16 -0
  45. package/dist/__tests__/mock-server.js +440 -25
  46. package/dist/__tests__/mock-server.js.map +1 -1
  47. package/dist/__tests__/publish.e2e.test.d.ts +1 -0
  48. package/dist/__tests__/publish.e2e.test.js +505 -0
  49. package/dist/__tests__/publish.e2e.test.js.map +1 -0
  50. package/dist/__tests__/tunnel.e2e.test.d.ts +1 -0
  51. package/dist/__tests__/tunnel.e2e.test.js +64 -0
  52. package/dist/__tests__/tunnel.e2e.test.js.map +1 -0
  53. package/dist/__tests__/utils.d.ts +44 -1
  54. package/dist/__tests__/utils.js +195 -11
  55. package/dist/__tests__/utils.js.map +1 -1
  56. package/dist/api.d.ts +1 -2
  57. package/dist/api.js +6 -10
  58. package/dist/api.js.map +1 -1
  59. package/dist/commands/deploy.d.ts +7 -4
  60. package/dist/commands/deploy.js +47 -28
  61. package/dist/commands/deploy.js.map +1 -1
  62. package/dist/commands/deployment/inspect.d.ts +11 -0
  63. package/dist/commands/deployment/inspect.js +91 -0
  64. package/dist/commands/deployment/inspect.js.map +1 -0
  65. package/dist/commands/deployment/list.d.ts +11 -0
  66. package/dist/commands/deployment/list.js +97 -0
  67. package/dist/commands/deployment/list.js.map +1 -0
  68. package/dist/commands/deployment/logs.d.ts +12 -0
  69. package/dist/commands/deployment/logs.js +50 -0
  70. package/dist/commands/deployment/logs.js.map +1 -0
  71. package/dist/commands/environment-variable/add.d.ts +14 -0
  72. package/dist/commands/environment-variable/add.js +46 -0
  73. package/dist/commands/environment-variable/add.js.map +1 -0
  74. package/dist/commands/environment-variable/list.d.ts +9 -0
  75. package/dist/commands/environment-variable/list.js +44 -0
  76. package/dist/commands/environment-variable/list.js.map +1 -0
  77. package/dist/commands/environment-variable/remove.d.ts +11 -0
  78. package/dist/commands/environment-variable/remove.js +32 -0
  79. package/dist/commands/environment-variable/remove.js.map +1 -0
  80. package/dist/commands/environment-variable/update.d.ts +13 -0
  81. package/dist/commands/environment-variable/update.js +40 -0
  82. package/dist/commands/environment-variable/update.js.map +1 -0
  83. package/dist/commands/git/connect.d.ts +10 -0
  84. package/dist/commands/git/connect.js +60 -0
  85. package/dist/commands/git/connect.js.map +1 -0
  86. package/dist/commands/git/disconnect.d.ts +9 -0
  87. package/dist/commands/git/disconnect.js +45 -0
  88. package/dist/commands/git/disconnect.js.map +1 -0
  89. package/dist/commands/git.d.ts +6 -0
  90. package/dist/commands/git.js +17 -0
  91. package/dist/commands/git.js.map +1 -0
  92. package/dist/commands/login.d.ts +6 -0
  93. package/dist/commands/login.js +34 -0
  94. package/dist/commands/login.js.map +1 -0
  95. package/dist/commands/logout.d.ts +6 -0
  96. package/dist/commands/logout.js +20 -0
  97. package/dist/commands/logout.js.map +1 -0
  98. package/dist/commands/logs.d.ts +16 -0
  99. package/dist/commands/logs.js +96 -0
  100. package/dist/commands/logs.js.map +1 -0
  101. package/dist/commands/publish.d.ts +15 -0
  102. package/dist/commands/publish.js +51 -0
  103. package/dist/commands/publish.js.map +1 -0
  104. package/dist/commands/tunnel.d.ts +9 -0
  105. package/dist/commands/tunnel.js +53 -0
  106. package/dist/commands/tunnel.js.map +1 -0
  107. package/dist/commands/whoami.d.ts +6 -0
  108. package/dist/commands/whoami.js +13 -0
  109. package/dist/commands/whoami.js.map +1 -0
  110. package/dist/env.d.ts +4 -0
  111. package/dist/env.js +10 -0
  112. package/dist/env.js.map +1 -0
  113. package/dist/lib/alpic-command.d.ts +6 -0
  114. package/dist/lib/alpic-command.js +27 -0
  115. package/dist/lib/alpic-command.js.map +1 -0
  116. package/dist/lib/archive.d.ts +3 -3
  117. package/dist/lib/archive.js +11 -15
  118. package/dist/lib/archive.js.map +1 -1
  119. package/dist/lib/auth/auth.d.ts +2 -0
  120. package/dist/lib/auth/auth.js +21 -0
  121. package/dist/lib/auth/auth.js.map +1 -0
  122. package/dist/lib/auth/oauth/client.d.ts +28 -0
  123. package/dist/lib/auth/oauth/client.js +110 -0
  124. package/dist/lib/auth/oauth/client.js.map +1 -0
  125. package/dist/lib/auth/oauth/constants.d.ts +2 -0
  126. package/dist/lib/auth/oauth/constants.js +3 -0
  127. package/dist/lib/auth/oauth/constants.js.map +1 -0
  128. package/dist/lib/auth/oauth/server/assets/alpic-mountain.png +0 -0
  129. package/dist/lib/auth/oauth/server/assets/authorize.html +195 -0
  130. package/dist/lib/auth/oauth/server/assets/callback.html +88 -0
  131. package/dist/lib/auth/oauth/server/index.d.ts +8 -0
  132. package/dist/lib/auth/oauth/server/index.js +105 -0
  133. package/dist/lib/auth/oauth/server/index.js.map +1 -0
  134. package/dist/lib/auth/whoami.d.ts +1 -0
  135. package/dist/lib/auth/whoami.js +41 -0
  136. package/dist/lib/auth/whoami.js.map +1 -0
  137. package/dist/lib/base-workflow.d.ts +10 -0
  138. package/dist/lib/base-workflow.js +22 -0
  139. package/dist/lib/base-workflow.js.map +1 -0
  140. package/dist/lib/config.d.ts +2 -2
  141. package/dist/lib/config.js +7 -7
  142. package/dist/lib/config.js.map +1 -1
  143. package/dist/lib/deployment.d.ts +70 -3
  144. package/dist/lib/deployment.js +121 -10
  145. package/dist/lib/deployment.js.map +1 -1
  146. package/dist/lib/environment-variable.d.ts +41 -0
  147. package/dist/lib/environment-variable.js +311 -0
  148. package/dist/lib/environment-variable.js.map +1 -0
  149. package/dist/lib/git.d.ts +22 -0
  150. package/dist/lib/git.js +131 -0
  151. package/dist/lib/git.js.map +1 -0
  152. package/dist/lib/global-store.d.ts +28 -0
  153. package/dist/lib/global-store.js +76 -0
  154. package/dist/lib/global-store.js.map +1 -0
  155. package/dist/lib/logs.d.ts +20 -0
  156. package/dist/lib/logs.js +86 -0
  157. package/dist/lib/logs.js.map +1 -0
  158. package/dist/lib/project.d.ts +68 -61
  159. package/dist/lib/project.js +275 -250
  160. package/dist/lib/project.js.map +1 -1
  161. package/dist/lib/publish.d.ts +22 -0
  162. package/dist/lib/publish.js +188 -0
  163. package/dist/lib/publish.js.map +1 -0
  164. package/dist/lib/table.d.ts +8 -0
  165. package/dist/lib/table.js +27 -0
  166. package/dist/lib/table.js.map +1 -0
  167. package/dist/lib/telemetry.js +7 -7
  168. package/dist/lib/telemetry.js.map +1 -1
  169. package/dist/lib/utils.d.ts +4 -0
  170. package/dist/lib/utils.js +45 -0
  171. package/dist/lib/utils.js.map +1 -0
  172. package/dist/lib/utils.test.d.ts +1 -0
  173. package/dist/lib/utils.test.js +27 -0
  174. package/dist/lib/utils.test.js.map +1 -0
  175. package/package.json +35 -31
  176. package/dist/lib/global-config.d.ts +0 -9
  177. package/dist/lib/global-config.js +0 -48
  178. package/dist/lib/global-config.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/lib/auth/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,CAAC,MAAM,WAAW,CAAC,mBAAmB,EAAE,CAAC,EAAE,YAAY,CAAC;IAEnG,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,wBAAwB,GAAG,SAAS,EAAE,CAAC;IAC7C,IAAI,wBAAwB;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,uBAAuB,GAAG,MAAM,mBAAmB,EAAE,CAAC;IAC5D,IAAI,uBAAuB;QAAE,OAAO,IAAI,CAAC;IAEzC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,SAAS,CAAC;AACjD,CAAC;AAED,KAAK,UAAU,mBAAmB;IAChC,OAAO,CAAC,MAAM,WAAW,CAAC,mBAAmB,EAAE,CAAC,KAAK,IAAI,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,28 @@
1
+ import * as openid from "openid-client";
2
+ import { type Credentials } from "../../global-store.js";
3
+ export declare class OAuthClient {
4
+ private config;
5
+ initialize: Promise<void>;
6
+ constructor();
7
+ getValidAccessToken(): Promise<Credentials | null>;
8
+ fetchUserInfo(credentials: Credentials): Promise<openid.UserInfoResponse>;
9
+ refreshAccessToken(credentials: Credentials): Promise<Credentials>;
10
+ prepareOAuthConfig(): Promise<{
11
+ authorizeUrl: URL;
12
+ state: string;
13
+ nonce: string;
14
+ codeVerifier: string;
15
+ }>;
16
+ exchangeAuthorizationCode({ url, codeVerifier, state, nonce, }: {
17
+ url: URL;
18
+ codeVerifier: string;
19
+ state: string;
20
+ nonce: string;
21
+ }): Promise<openid.TokenEndpointResponse & openid.TokenEndpointResponseHelpers>;
22
+ getExpiresAt(expires_in: number): number;
23
+ private loadConfig;
24
+ private fetchOAuthProtectedResourceConfig;
25
+ private getConfig;
26
+ private isAccessTokenExpired;
27
+ }
28
+ export declare const oAuthClient: OAuthClient;
@@ -0,0 +1,110 @@
1
+ import * as openid from "openid-client";
2
+ import { env } from "../../../env.js";
3
+ import { globalStore } from "../../global-store.js";
4
+ import { LOOPBACK_HOST, LOOPBACK_PORT } from "./constants.js";
5
+ const SCOPES = ["openid", "email", "profile"];
6
+ export class OAuthClient {
7
+ config = null;
8
+ initialize;
9
+ constructor() {
10
+ this.initialize = this.loadConfig();
11
+ }
12
+ async getValidAccessToken() {
13
+ await this.initialize;
14
+ const stored = globalStore.getCredentials();
15
+ if (!stored) {
16
+ return null;
17
+ }
18
+ if (this.isAccessTokenExpired(stored)) {
19
+ try {
20
+ return await this.refreshAccessToken(stored);
21
+ }
22
+ catch {
23
+ return null;
24
+ }
25
+ }
26
+ return stored;
27
+ }
28
+ async fetchUserInfo(credentials) {
29
+ return openid.fetchUserInfo(await this.getConfig(), credentials.access_token, credentials.sub);
30
+ }
31
+ async refreshAccessToken(credentials) {
32
+ if (!credentials.refresh_token) {
33
+ throw new Error("No refresh token available");
34
+ }
35
+ const response = await openid.refreshTokenGrant(await this.getConfig(), credentials.refresh_token);
36
+ const refreshed = {
37
+ access_token: response.access_token,
38
+ refresh_token: response.refresh_token ?? credentials.refresh_token,
39
+ expires_at: this.getExpiresAt(response.expires_in ?? 0),
40
+ sub: credentials.sub,
41
+ };
42
+ globalStore.saveCredentials(refreshed);
43
+ return refreshed;
44
+ }
45
+ async prepareOAuthConfig() {
46
+ await this.initialize;
47
+ if (!this.config) {
48
+ throw new Error("Config not loaded");
49
+ }
50
+ const codeVerifier = openid.randomPKCECodeVerifier();
51
+ const codeChallenge = await openid.calculatePKCECodeChallenge(codeVerifier);
52
+ const state = openid.randomState();
53
+ const nonce = openid.randomNonce();
54
+ const callbackUrl = new URL(`http://${LOOPBACK_HOST}:${LOOPBACK_PORT}/callback`);
55
+ const authorizeUrl = openid.buildAuthorizationUrl(this.config, {
56
+ redirect_uri: callbackUrl.toString(),
57
+ scope: SCOPES.join(" "),
58
+ code_challenge: codeChallenge,
59
+ code_challenge_method: "S256",
60
+ state,
61
+ nonce,
62
+ });
63
+ return { authorizeUrl, state, nonce, codeVerifier };
64
+ }
65
+ async exchangeAuthorizationCode({ url, codeVerifier, state, nonce, }) {
66
+ return await openid.authorizationCodeGrant(await this.getConfig(), url, {
67
+ pkceCodeVerifier: codeVerifier,
68
+ expectedState: state,
69
+ expectedNonce: nonce,
70
+ });
71
+ }
72
+ getExpiresAt(expires_in) {
73
+ return expires_in !== undefined ? Math.floor(Date.now() / 1000) + expires_in : Date.now() / 1000 + 3600;
74
+ }
75
+ async loadConfig() {
76
+ const protectedResourceConfig = await this.fetchOAuthProtectedResourceConfig();
77
+ const issuer = protectedResourceConfig.authorization_servers[0];
78
+ if (!issuer) {
79
+ throw new Error("No authorization server in OAuth protected resource config");
80
+ }
81
+ const issuerUrl = new URL(issuer);
82
+ try {
83
+ this.config = await openid.discovery(issuerUrl, env.ALPIC_COGNITO_CLIENT_ID);
84
+ }
85
+ catch {
86
+ throw new Error("Failed to discover OAuth config");
87
+ }
88
+ }
89
+ async fetchOAuthProtectedResourceConfig() {
90
+ const baseUrl = env.ALPIC_API_BASE_URL;
91
+ const response = await fetch(`${baseUrl}/.well-known/oauth-protected-resource`);
92
+ if (!response.ok) {
93
+ throw new Error(`Failed to load service config from ${baseUrl} (${response.status} ${response.statusText})`);
94
+ }
95
+ return (await response.json());
96
+ }
97
+ async getConfig() {
98
+ await this.initialize;
99
+ if (!this.config) {
100
+ throw new Error("Config not loaded");
101
+ }
102
+ return this.config;
103
+ }
104
+ isAccessTokenExpired(credentials) {
105
+ const EXPIRATION_WINDOW_IN_SECONDS = 300;
106
+ return Date.now() / 1000 + EXPIRATION_WINDOW_IN_SECONDS >= credentials.expires_at;
107
+ }
108
+ }
109
+ export const oAuthClient = new OAuthClient();
110
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../src/lib/auth/oauth/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAC;AAExC,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AACtC,OAAO,EAAoB,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE9D,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;AAU9C,MAAM,OAAO,WAAW;IACd,MAAM,GAAgC,IAAI,CAAC;IACnD,UAAU,CAAgB;IAE1B;QACE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,MAAM,IAAI,CAAC,UAAU,CAAC;QACtB,MAAM,MAAM,GAAG,WAAW,CAAC,cAAc,EAAE,CAAC;QAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC/C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,WAAwB;QAC1C,OAAO,MAAM,CAAC,aAAa,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,EAAE,WAAW,CAAC,YAAY,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC;IACjG,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,WAAwB;QAC/C,IAAI,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;QAEnG,MAAM,SAAS,GAAgB;YAC7B,YAAY,EAAE,QAAQ,CAAC,YAAY;YACnC,aAAa,EAAE,QAAQ,CAAC,aAAa,IAAI,WAAW,CAAC,aAAa;YAClE,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,UAAU,IAAI,CAAC,CAAC;YACvD,GAAG,EAAE,WAAW,CAAC,GAAG;SACrB,CAAC;QAEF,WAAW,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QACvC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,KAAK,CAAC,kBAAkB;QACtB,MAAM,IAAI,CAAC,UAAU,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,CAAC,sBAAsB,EAAE,CAAC;QACrD,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,0BAA0B,CAAC,YAAY,CAAC,CAAC;QAC5E,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QACnC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,UAAU,aAAa,IAAI,aAAa,WAAW,CAAC,CAAC;QAEjF,MAAM,YAAY,GAAG,MAAM,CAAC,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE;YAC7D,YAAY,EAAE,WAAW,CAAC,QAAQ,EAAE;YACpC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;YACvB,cAAc,EAAE,aAAa;YAC7B,qBAAqB,EAAE,MAAM;YAC7B,KAAK;YACL,KAAK;SACN,CAAC,CAAC;QAEH,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IACtD,CAAC;IAED,KAAK,CAAC,yBAAyB,CAAC,EAC9B,GAAG,EACH,YAAY,EACZ,KAAK,EACL,KAAK,GAMN;QACC,OAAO,MAAM,MAAM,CAAC,sBAAsB,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE;YACtE,gBAAgB,EAAE,YAAY;YAC9B,aAAa,EAAE,KAAK;YACpB,aAAa,EAAE,KAAK;SACrB,CAAC,CAAC;IACL,CAAC;IAED,YAAY,CAAC,UAAkB;QAC7B,OAAO,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1G,CAAC;IAEO,KAAK,CAAC,UAAU;QACtB,MAAM,uBAAuB,GAAG,MAAM,IAAI,CAAC,iCAAiC,EAAE,CAAC;QAC/E,MAAM,MAAM,GAAG,uBAAuB,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAChE,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAChF,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAClC,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,GAAG,CAAC,uBAAuB,CAAC,CAAC;QAC/E,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,iCAAiC;QAC7C,MAAM,OAAO,GAAG,GAAG,CAAC,kBAAkB,CAAC;QACvC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,uCAAuC,CAAC,CAAC;QAChF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,sCAAsC,OAAO,KAAK,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC;QAC/G,CAAC;QACD,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAiC,CAAC;IACjE,CAAC;IAEO,KAAK,CAAC,SAAS;QACrB,MAAM,IAAI,CAAC,UAAU,CAAC;QACtB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEO,oBAAoB,CAAC,WAAwB;QACnD,MAAM,4BAA4B,GAAG,GAAG,CAAC;QACzC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,4BAA4B,IAAI,WAAW,CAAC,UAAU,CAAC;IACpF,CAAC;CACF;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const LOOPBACK_HOST = "127.0.0.1";
2
+ export declare const LOOPBACK_PORT = 38472;
@@ -0,0 +1,3 @@
1
+ export const LOOPBACK_HOST = "127.0.0.1";
2
+ export const LOOPBACK_PORT = 38472;
3
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/lib/auth/oauth/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AACzC,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC"}
@@ -0,0 +1,195 @@
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
+ background-image: url("/assets/alpic-mountain.png");
30
+ background-repeat: no-repeat;
31
+ background-position: right bottom;
32
+ background-size: auto;
33
+ padding: 64px;
34
+ }
35
+
36
+ .card {
37
+ background: #fff;
38
+ border-radius: 2px;
39
+ padding: 48px;
40
+ width: 50%;
41
+ min-height: calc(100vh - 128px);
42
+ display: flex;
43
+ flex-direction: column;
44
+ align-items: center;
45
+ justify-content: center;
46
+ }
47
+
48
+ h1 {
49
+ font-family: "Mozilla Text", system-ui, sans-serif;
50
+ font-weight: 400;
51
+ font-size: 48px;
52
+ color: var(--midnight);
53
+ margin-bottom: 8px;
54
+ }
55
+
56
+ .subtitle {
57
+ font-size: 20px;
58
+ color: var(--midnight);
59
+ margin-bottom: 32px;
60
+ }
61
+
62
+ .buttons {
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: 12px;
66
+ }
67
+
68
+ .btn {
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+ gap: 8px;
73
+ height: 48px;
74
+ width: 256px;
75
+ padding: 0 16px;
76
+ border-radius: 2px;
77
+ border: 1px solid var(--midnight);
78
+ font-family: "Inter", system-ui, sans-serif;
79
+ font-size: 16px;
80
+ font-weight: 500;
81
+ cursor: pointer;
82
+ transition: background 0.15s;
83
+ }
84
+
85
+ .btn:focus-visible {
86
+ outline: none;
87
+ box-shadow: 0 0 0 2px var(--midnight);
88
+ }
89
+
90
+ .btn svg {
91
+ width: 20px;
92
+ height: 20px;
93
+ flex-shrink: 0;
94
+ }
95
+
96
+ .btn-github {
97
+ background: var(--midnight);
98
+ color: #fff;
99
+ }
100
+ .btn-github svg {
101
+ fill: #fff;
102
+ }
103
+ .btn-github:hover {
104
+ background: rgba(5, 20, 19, 0.9);
105
+ }
106
+
107
+ .btn-google {
108
+ background: #fff;
109
+ color: var(--midnight);
110
+ }
111
+ .btn-google svg {
112
+ fill: var(--midnight);
113
+ }
114
+ .btn-google:hover {
115
+ background: rgba(5, 20, 19, 0.1);
116
+ }
117
+
118
+ .btn-loading {
119
+ opacity: 0.7;
120
+ pointer-events: none;
121
+ cursor: default;
122
+ transition: opacity 0.2s;
123
+ }
124
+ .spinner {
125
+ width: 20px;
126
+ height: 20px;
127
+ animation: spin 0.8s linear infinite;
128
+ }
129
+ @keyframes spin {
130
+ to {
131
+ transform: rotate(360deg);
132
+ }
133
+ }
134
+
135
+ @media (max-width: 768px) {
136
+ body {
137
+ padding: 16px;
138
+ }
139
+ .card {
140
+ width: 100%;
141
+ height: auto;
142
+ padding: 24px;
143
+ }
144
+ h1 {
145
+ font-size: 36px;
146
+ }
147
+ .subtitle {
148
+ font-size: 18px;
149
+ }
150
+ }
151
+ </style>
152
+ </head>
153
+ <body>
154
+ <div class="card">
155
+ <h1>Welcome to Alpic</h1>
156
+ <p class="subtitle">Sign in to use Alpic CLI</p>
157
+ <div class="buttons">
158
+ <button class="btn btn-github" onclick="login('Github', this)" type="button">
159
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
160
+ <title>GitHub</title>
161
+ <path
162
+ d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
163
+ />
164
+ </svg>
165
+ Sign in with GitHub
166
+ </button>
167
+ <button class="btn btn-google" onclick="login('google', this)" type="button">
168
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
169
+ <title>Google</title>
170
+ <path
171
+ d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.8 4.133-1.147 1.147-2.933 2.4-6.04 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z"
172
+ />
173
+ </svg>
174
+ Sign in with Google
175
+ </button>
176
+ </div>
177
+ </div>
178
+ <script>
179
+ var loaderSvg =
180
+ '<svg class="spinner" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v4"/><path d="m16.2 7.8 2.9-2.9"/><path d="M18 12h4"/><path d="m16.2 16.2 2.9 2.9"/><path d="M12 18v4"/><path d="m4.9 19.1 2.9-2.9"/><path d="M2 12h4"/><path d="m4.9 4.9 2.9 2.9"/></svg>';
181
+ // biome-ignore lint/correctness/noUnusedVariables: The function is used within the buttons onclick handlers
182
+ function login(provider, btn) {
183
+ const icon = btn.querySelector("svg");
184
+ const wrap = document.createElement("div");
185
+ wrap.innerHTML = loaderSvg;
186
+ icon.replaceWith(wrap.firstChild);
187
+ btn.classList.add("btn-loading");
188
+ btn.disabled = true;
189
+ const url = new URL("%AUTH_BASE_URL%");
190
+ url.searchParams.set("identity_provider", provider);
191
+ window.location.href = url.toString();
192
+ }
193
+ </script>
194
+ </body>
195
+ </html>
@@ -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,105 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { createServer } from "node:http";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import * as p from "@clack/prompts";
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, {
21
+ "Content-Type": "text/html",
22
+ Connection: "close",
23
+ });
24
+ res.end(html);
25
+ return;
26
+ }
27
+ catch (e) {
28
+ p.log.error(e instanceof Error ? e.message : String(e));
29
+ res.writeHead(500).end();
30
+ return;
31
+ }
32
+ }
33
+ if (pathname === "/assets/alpic-mountain.png") {
34
+ const filePath = path.join(ASSETS_DIR, "alpic-mountain.png");
35
+ const content = await readFile(filePath);
36
+ res.writeHead(200, { "Content-Type": "image/png", Connection: "close" });
37
+ res.end(content);
38
+ return;
39
+ }
40
+ if (!url.startsWith("/callback")) {
41
+ res.writeHead(404).end();
42
+ return;
43
+ }
44
+ try {
45
+ const tokens = await oAuthClient.exchangeAuthorizationCode({
46
+ url: new URL(url, `http://${req.headers.host}`),
47
+ codeVerifier,
48
+ state,
49
+ nonce,
50
+ });
51
+ const sub = tokens.claims()?.sub;
52
+ if (!sub || !tokens.refresh_token) {
53
+ throw new Error("ID token did not contain sub");
54
+ }
55
+ const stored = {
56
+ access_token: tokens.access_token,
57
+ refresh_token: tokens.refresh_token,
58
+ expires_at: oAuthClient.getExpiresAt(tokens.expires_in ?? 0),
59
+ sub,
60
+ };
61
+ p.log.success("✅ Authentication successful");
62
+ const successHtmlPath = path.join(ASSETS_DIR, "callback.html");
63
+ let html = await readFile(successHtmlPath, "utf-8");
64
+ html = html
65
+ .replace(/__CALLBACK_STATUS__/g, "success")
66
+ .replace(/__CALLBACK_TITLE__/g, "You are logged in")
67
+ .replace(/__CALLBACK_SUB__/g, "You can close this page.");
68
+ res.writeHead(200, { "Content-Type": "text/html", Connection: "close" });
69
+ res.end(html);
70
+ onSuccess(stored);
71
+ }
72
+ catch (e) {
73
+ p.log.error(e instanceof Error ? e.message : String(e));
74
+ const callbackHtmlPath = path.join(ASSETS_DIR, "callback.html");
75
+ let html = await readFile(callbackHtmlPath, "utf-8");
76
+ html = html
77
+ .replace(/__CALLBACK_STATUS__/g, "error")
78
+ .replace(/__CALLBACK_TITLE__/g, "An error occurred. You can close this page.")
79
+ .replace(/__CALLBACK_SUB__/g, "");
80
+ res.writeHead(500, { "Content-Type": "text/html", Connection: "close" });
81
+ res.end(html);
82
+ onError(e instanceof Error ? e : new Error(String(e)));
83
+ }
84
+ });
85
+ export const getLoginPageUrl = () => `http://${LOOPBACK_HOST}:${LOOPBACK_PORT}/login`;
86
+ export const listenToOAuthCallback = ({ state, nonce, codeVerifier, authorizeUrl, }) => {
87
+ return new Promise((resolve, reject) => {
88
+ const callbackServer = createCallbackServer({
89
+ state,
90
+ nonce,
91
+ codeVerifier,
92
+ authorizeUrl,
93
+ onSuccess: (storedToken) => {
94
+ callbackServer.close();
95
+ resolve(storedToken);
96
+ },
97
+ onError: (err) => {
98
+ callbackServer.close();
99
+ reject(err);
100
+ },
101
+ });
102
+ callbackServer.listen(LOOPBACK_PORT, LOOPBACK_HOST);
103
+ });
104
+ };
105
+ //# 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 @@
1
+ export declare function getWhoamiInfoMessage(): Promise<string>;
@@ -0,0 +1,41 @@
1
+ import chalk from "chalk";
2
+ import { api } from "../../api.js";
3
+ import { oAuthClient } from "./oauth/client.js";
4
+ export async function getWhoamiInfoMessage() {
5
+ const info = (await getWhoamiInfoFromApiKey()) ?? (await getWhoamiInfoFromOAuth());
6
+ if (info === null) {
7
+ return "Not logged in. Run `alpic login` or set ALPIC_API_KEY.";
8
+ }
9
+ if (info.method === "api_key") {
10
+ return `Authenticated via API key — Team: ${chalk.green(info.team?.name ?? "unknown")}`;
11
+ }
12
+ return `Authenticated as ${chalk.green(info.name)} (${chalk.cyan(info.email)})`;
13
+ }
14
+ async function getWhoamiInfoFromApiKey() {
15
+ if (process.env.ALPIC_API_KEY === undefined) {
16
+ return null;
17
+ }
18
+ const team = await getApiKeyTeam();
19
+ return {
20
+ method: "api_key",
21
+ team,
22
+ };
23
+ }
24
+ async function getWhoamiInfoFromOAuth() {
25
+ const token = await oAuthClient.getValidAccessToken();
26
+ if (!token)
27
+ return null;
28
+ const userInfo = await oAuthClient.fetchUserInfo(token);
29
+ if (!userInfo)
30
+ return null;
31
+ return {
32
+ method: "oauth",
33
+ email: userInfo.email ?? "unknown",
34
+ name: userInfo.name ?? "unknown",
35
+ };
36
+ }
37
+ async function getApiKeyTeam() {
38
+ const teams = await api.teams.list.v1();
39
+ return teams[0];
40
+ }
41
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../../src/lib/auth/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAahD,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,IAAI,GAAG,CAAC,MAAM,uBAAuB,EAAE,CAAC,IAAI,CAAC,MAAM,sBAAsB,EAAE,CAAC,CAAC;IAEnF,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,wDAAwD,CAAC;IAClE,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,qCAAqC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,SAAS,CAAC,EAAE,CAAC;IAC1F,CAAC;IAED,OAAO,oBAAoB,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;AAClF,CAAC;AAED,KAAK,UAAU,uBAAuB;IACpC,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,aAAa,EAAE,CAAC;IACnC,OAAO;QACL,MAAM,EAAE,SAAS;QACjB,IAAI;KACL,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,sBAAsB;IACnC,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,mBAAmB,EAAE,CAAC;IACtD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACxD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,OAAO;QACL,MAAM,EAAE,OAAO;QACf,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,SAAS;QAClC,IAAI,EAAE,QAAQ,CAAC,IAAI,IAAI,SAAS;KACjC,CAAC;AACJ,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,10 @@
1
+ import * as p from "@clack/prompts";
2
+ export type Flags = {
3
+ "non-interactive"?: boolean;
4
+ };
5
+ export declare abstract class BaseWorkflow<F extends Flags = Flags> {
6
+ readonly flags: F;
7
+ constructor(flags: F);
8
+ protected confirm(options: p.ConfirmOptions, defaultValue?: boolean): Promise<boolean | symbol>;
9
+ protected isNonInteractive(): boolean;
10
+ }
@@ -0,0 +1,22 @@
1
+ import * as p from "@clack/prompts";
2
+ import * as ci from "ci-info";
3
+ export class BaseWorkflow {
4
+ flags;
5
+ constructor(flags) {
6
+ this.flags = flags;
7
+ }
8
+ confirm(options, defaultValue = true) {
9
+ if (this.isNonInteractive()) {
10
+ return Promise.resolve(defaultValue);
11
+ }
12
+ return p.confirm(options);
13
+ }
14
+ isNonInteractive() {
15
+ if (this.flags["non-interactive"])
16
+ return true;
17
+ if (process.env.VITEST)
18
+ return false;
19
+ return ci.isCI ?? false;
20
+ }
21
+ }
22
+ //# sourceMappingURL=base-workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-workflow.js","sourceRoot":"","sources":["../../src/lib/base-workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAM9B,MAAM,OAAgB,YAAY;IACJ;IAA5B,YAA4B,KAAQ;QAAR,UAAK,GAAL,KAAK,CAAG;IAAG,CAAC;IAE9B,OAAO,CAAC,OAAyB,EAAE,eAAwB,IAAI;QACvE,IAAI,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;YAC5B,OAAO,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;IAES,gBAAgB;QACxB,IAAI,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QAErC,OAAO,EAAE,CAAC,IAAI,IAAI,KAAK,CAAC;IAC1B,CAAC;CACF"}