@devtion/devcli 0.0.0-004e6ad

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 (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +120 -0
  3. package/dist/.env +55 -0
  4. package/dist/index.js +3635 -0
  5. package/dist/public/mini-semaphore.wasm +0 -0
  6. package/dist/public/mini-semaphore.zkey +0 -0
  7. package/dist/types/commands/auth.d.ts +25 -0
  8. package/dist/types/commands/authBandada.d.ts +2 -0
  9. package/dist/types/commands/authSIWE.d.ts +7 -0
  10. package/dist/types/commands/ceremony/index.d.ts +3 -0
  11. package/dist/types/commands/ceremony/listParticipants.d.ts +2 -0
  12. package/dist/types/commands/clean.d.ts +6 -0
  13. package/dist/types/commands/contribute.d.ts +139 -0
  14. package/dist/types/commands/finalize.d.ts +52 -0
  15. package/dist/types/commands/index.d.ts +11 -0
  16. package/dist/types/commands/listCeremonies.d.ts +5 -0
  17. package/dist/types/commands/logout.d.ts +6 -0
  18. package/dist/types/commands/observe.d.ts +22 -0
  19. package/dist/types/commands/setup.d.ts +86 -0
  20. package/dist/types/commands/validate.d.ts +8 -0
  21. package/dist/types/index.d.ts +2 -0
  22. package/dist/types/lib/bandada.d.ts +6 -0
  23. package/dist/types/lib/errors.d.ts +60 -0
  24. package/dist/types/lib/files.d.ts +65 -0
  25. package/dist/types/lib/localConfigs.d.ts +148 -0
  26. package/dist/types/lib/prompts.d.ts +104 -0
  27. package/dist/types/lib/services.d.ts +31 -0
  28. package/dist/types/lib/theme.d.ts +42 -0
  29. package/dist/types/lib/utils.d.ts +159 -0
  30. package/dist/types/types/index.d.ts +134 -0
  31. package/package.json +108 -0
  32. package/src/commands/auth.ts +214 -0
  33. package/src/commands/authBandada.ts +120 -0
  34. package/src/commands/authSIWE.ts +185 -0
  35. package/src/commands/ceremony/index.ts +20 -0
  36. package/src/commands/ceremony/listParticipants.ts +56 -0
  37. package/src/commands/clean.ts +49 -0
  38. package/src/commands/contribute.ts +1116 -0
  39. package/src/commands/finalize.ts +395 -0
  40. package/src/commands/index.ts +11 -0
  41. package/src/commands/listCeremonies.ts +31 -0
  42. package/src/commands/logout.ts +69 -0
  43. package/src/commands/observe.ts +197 -0
  44. package/src/commands/setup.ts +912 -0
  45. package/src/commands/validate.ts +28 -0
  46. package/src/index.ts +88 -0
  47. package/src/lib/bandada.ts +51 -0
  48. package/src/lib/errors.ts +77 -0
  49. package/src/lib/files.ts +102 -0
  50. package/src/lib/localConfigs.ts +240 -0
  51. package/src/lib/prompts.ts +745 -0
  52. package/src/lib/services.ts +214 -0
  53. package/src/lib/theme.ts +45 -0
  54. package/src/lib/utils.ts +813 -0
  55. package/src/types/conf.d.ts +16 -0
  56. package/src/types/index.ts +145 -0
@@ -0,0 +1,214 @@
1
+ import {
2
+ getCurrentFirebaseAuthUser,
3
+ initializeFirebaseCoreServices,
4
+ signInToFirebaseWithCredentials
5
+ } from "@devtion/actions"
6
+ import clear from "clear"
7
+ import figlet from "figlet"
8
+ import { FirebaseApp } from "firebase/app"
9
+ import { OAuthCredential, getAuth, signInWithCustomToken } from "firebase/auth"
10
+ import dotenv from "dotenv"
11
+ import { fileURLToPath } from "url"
12
+ import { dirname } from "path"
13
+ import { AuthUser } from "../types/index.js"
14
+ import { CONFIG_ERRORS, CORE_SERVICES_ERRORS, showError, THIRD_PARTY_SERVICES_ERRORS } from "./errors.js"
15
+ import {
16
+ checkLocalAccessToken,
17
+ deleteLocalAccessToken,
18
+ getLocalAccessToken,
19
+ getLocalAuthMethod
20
+ } from "./localConfigs.js"
21
+ import theme from "./theme.js"
22
+ import { exchangeGithubTokenForCredentials, getGithubProviderUserId, getUserHandleFromProviderUserId } from "./utils.js"
23
+
24
+ const packagePath = `${dirname(fileURLToPath(import.meta.url))}`
25
+ dotenv.config({
26
+ path: packagePath.includes(`src/lib`)
27
+ ? `${dirname(fileURLToPath(import.meta.url))}/../../.env`
28
+ : `${dirname(fileURLToPath(import.meta.url))}/.env`
29
+ })
30
+
31
+ /**
32
+ * Bootstrap services and configs is needed for a new command execution and related services.
33
+ * @returns <Promise<FirebaseServices>>
34
+ */
35
+ export const bootstrapCommandExecutionAndServices = async (): Promise<any> => {
36
+ // Clean terminal window.
37
+ clear()
38
+
39
+ // Print header.
40
+ console.log(theme.colors.magenta(figlet.textSync("Phase 2 cli", { font: "Ogre" })))
41
+
42
+ // Check configs.
43
+ if (!process.env.AUTH_GITHUB_CLIENT_ID) showError(CONFIG_ERRORS.CONFIG_GITHUB_ERROR, true)
44
+ if (
45
+ !process.env.FIREBASE_API_KEY ||
46
+ !process.env.FIREBASE_AUTH_DOMAIN ||
47
+ !process.env.FIREBASE_PROJECT_ID ||
48
+ !process.env.FIREBASE_MESSAGING_SENDER_ID ||
49
+ !process.env.FIREBASE_APP_ID ||
50
+ !process.env.FIREBASE_CF_URL_VERIFY_CONTRIBUTION
51
+ )
52
+ showError(CONFIG_ERRORS.CONFIG_FIREBASE_ERROR, true)
53
+ if (
54
+ !process.env.CONFIG_STREAM_CHUNK_SIZE_IN_MB ||
55
+ !process.env.CONFIG_CEREMONY_BUCKET_POSTFIX ||
56
+ !process.env.CONFIG_PRESIGNED_URL_EXPIRATION_IN_SECONDS
57
+ )
58
+ showError(CONFIG_ERRORS.CONFIG_OTHER_ERROR, true)
59
+
60
+ // Initialize and return Firebase services instances (App, Firestore, Functions)
61
+ return initializeFirebaseCoreServices(
62
+ String(process.env.FIREBASE_API_KEY),
63
+ String(process.env.FIREBASE_AUTH_DOMAIN),
64
+ String(process.env.FIREBASE_PROJECT_ID),
65
+ String(process.env.FIREBASE_MESSAGING_SENDER_ID),
66
+ String(process.env.FIREBASE_APP_ID)
67
+ )
68
+ }
69
+
70
+ /**
71
+ * Execute the sign in to Firebase using OAuth credentials.
72
+ * @dev wrapper method to handle custom errors.
73
+ * @param firebaseApp <FirebaseApp> - the configured instance of the Firebase App in use.
74
+ * @param credentials <OAuthCredential> - the OAuth credential generated from token exchange.
75
+ * @returns <Promise<void>>
76
+ */
77
+ export const signInToFirebase = async (firebaseApp: FirebaseApp, credentials: OAuthCredential): Promise<void> => {
78
+ try {
79
+ // Sign in with credentials to Firebase.
80
+ await signInToFirebaseWithCredentials(firebaseApp, credentials)
81
+ } catch (error: any) {
82
+ // Error handling by parsing error message.
83
+ if (error.toString().includes("Firebase: Unsuccessful check authorization response from Github")) {
84
+ showError(CORE_SERVICES_ERRORS.FIREBASE_TOKEN_EXPIRED_REMOVED_PERMISSIONS, false)
85
+
86
+ // Clean expired access token from local storage.
87
+ deleteLocalAccessToken()
88
+
89
+ // Inform user.
90
+ console.log(
91
+ `${theme.symbols.info} We have successfully removed your local token to make you able to repeat the authorization process once again. Please, run the auth command again whenever you are ready and complete the association with the CLI application.`
92
+ )
93
+
94
+ // Gracefully exit.
95
+ process.exit(0)
96
+ }
97
+
98
+ if (error.toString().includes("Firebase: Error (auth/user-disabled)"))
99
+ showError(CORE_SERVICES_ERRORS.FIREBASE_USER_DISABLED, true)
100
+
101
+ if (
102
+ error
103
+ .toString()
104
+ .includes("Firebase: Remote site 5XX from github.com for VERIFY_CREDENTIAL (auth/invalid-credential)")
105
+ )
106
+ showError(CORE_SERVICES_ERRORS.FIREBASE_FAILED_CREDENTIALS_VERIFICATION, true)
107
+
108
+ if (error.toString().includes("Firebase: Error (auth/network-request-failed)"))
109
+ showError(CORE_SERVICES_ERRORS.FIREBASE_NETWORK_ERROR, true)
110
+
111
+ if (error.toString().includes("HttpError: The authorization request was denied"))
112
+ showError(THIRD_PARTY_SERVICES_ERRORS.GITHUB_ACCOUNT_ASSOCIATION_REJECTED, true)
113
+
114
+ if (
115
+ error
116
+ .toString()
117
+ .includes(
118
+ "HttpError: request to https://github.com/login/device/code failed, reason: connect ETIMEDOUT"
119
+ )
120
+ )
121
+ showError(THIRD_PARTY_SERVICES_ERRORS.GITHUB_SERVER_TIMEDOUT, true)
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Ensure that the callee is an authenticated user.
127
+ * @notice The token will be passed as parameter.
128
+ * @dev This method can be used within GitHub actions or other CI/CD pipelines.
129
+ * @param firebaseApp <FirebaseApp> - the configured instance of the Firebase App in use.
130
+ * @param token <string> - the token to be used for authentication.
131
+ * @returns <Promise<AuthUser>> - a custom object containing info about the authenticated user, the token and github handle.
132
+ */
133
+ export const authWithToken = async (firebaseApp: FirebaseApp, token: string): Promise<AuthUser> => {
134
+ // Get credentials.
135
+ const credentials = exchangeGithubTokenForCredentials(token)
136
+
137
+ // Sign in to Firebase using credentials.
138
+ await signInToFirebase(firebaseApp, credentials)
139
+
140
+ // Get current authenticated user.
141
+ const user = getCurrentFirebaseAuthUser(firebaseApp)
142
+
143
+ // Get Github unique identifier (handle-id).
144
+ const providerUserId = await getGithubProviderUserId(String(token))
145
+
146
+ // Greet the user.
147
+ console.log(
148
+ `Greetings, @${theme.text.bold(getUserHandleFromProviderUserId(providerUserId))} ${theme.emojis.wave}\n`
149
+ )
150
+
151
+ return {
152
+ user,
153
+ token,
154
+ providerUserId
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Ensure that the callee is an authenticated user.
160
+ * @dev This method MUST be executed before each command to avoid authentication errors when interacting with the command.
161
+ * @returns <Promise<AuthUser>> - a custom object containing info about the authenticated user, the token and github handle.
162
+ */
163
+ export const checkAuth = async (firebaseApp: FirebaseApp): Promise<AuthUser> => {
164
+ // Check for local token.
165
+ const isLocalTokenStored = checkLocalAccessToken()
166
+
167
+ if (!isLocalTokenStored) showError(THIRD_PARTY_SERVICES_ERRORS.GITHUB_NOT_AUTHENTICATED, true)
168
+
169
+ // Retrieve local access token.
170
+ const token = String(getLocalAccessToken())
171
+
172
+ let providerUserId: string
173
+ let username: string
174
+ const authMethod = getLocalAuthMethod()
175
+ switch (authMethod) {
176
+ case "github": {
177
+ // Get credentials.
178
+ const credentials = exchangeGithubTokenForCredentials(token)
179
+ // Sign in to Firebase using credentials.
180
+ await signInToFirebase(firebaseApp, credentials)
181
+ // Get Github unique identifier (handle-id).
182
+ providerUserId = await getGithubProviderUserId(String(token))
183
+ username = getUserHandleFromProviderUserId(providerUserId)
184
+ break
185
+ }
186
+ case "bandada": {
187
+ const userCredentials = await signInWithCustomToken(getAuth(), token)
188
+ providerUserId = userCredentials.user.uid
189
+ username = providerUserId
190
+ break
191
+ }
192
+ case "siwe": {
193
+ const userCredentials = await signInWithCustomToken(getAuth(), token)
194
+ providerUserId = userCredentials.user.uid
195
+ username = providerUserId
196
+ break
197
+ }
198
+ default: {
199
+ break
200
+ }
201
+ }
202
+
203
+ // Get current authenticated user.
204
+ const user = getCurrentFirebaseAuthUser(firebaseApp)
205
+
206
+ // Greet the user.
207
+ console.log(`Greetings, @${theme.text.bold(username)} ${theme.emojis.wave}\n`)
208
+
209
+ return {
210
+ user,
211
+ token,
212
+ providerUserId
213
+ }
214
+ }
@@ -0,0 +1,45 @@
1
+ import chalk from "chalk"
2
+ import logSymbols from "log-symbols"
3
+ import emoji from "node-emoji"
4
+
5
+ /**
6
+ * Custom theme object.
7
+ */
8
+ export default {
9
+ colors: {
10
+ yellow: chalk.yellow,
11
+ magenta: chalk.magenta,
12
+ red: chalk.red,
13
+ green: chalk.green
14
+ },
15
+ text: {
16
+ underlined: chalk.underline,
17
+ bold: chalk.bold,
18
+ italic: chalk.italic
19
+ },
20
+ symbols: {
21
+ success: logSymbols.success,
22
+ warning: logSymbols.warning,
23
+ error: logSymbols.error,
24
+ info: logSymbols.info
25
+ },
26
+ emojis: {
27
+ tada: emoji.get("tada"),
28
+ key: emoji.get("key"),
29
+ broom: emoji.get("broom"),
30
+ pointDown: emoji.get("point_down"),
31
+ eyes: emoji.get("eyes"),
32
+ wave: emoji.get("wave"),
33
+ clipboard: emoji.get("clipboard"),
34
+ fire: emoji.get("fire"),
35
+ clock: emoji.get("hourglass"),
36
+ dizzy: emoji.get("dizzy_face"),
37
+ rocket: emoji.get("rocket"),
38
+ oldKey: emoji.get("old_key"),
39
+ pray: emoji.get("pray"),
40
+ moon: emoji.get("moon"),
41
+ upsideDown: emoji.get("upside_down_face"),
42
+ arrowUp: emoji.get("arrow_up"),
43
+ arrowDown: emoji.get("arrow_down")
44
+ }
45
+ }