instant-cli 1.0.21-branch-cli-codex-update.25192174695.1 → 1.0.21-branch-cli-codex-update.25193076159.1
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/.turbo/turbo-build.log +1 -1
- package/dist/commands/auth/client/add.d.ts +1 -2
- package/dist/commands/auth/client/add.d.ts.map +1 -1
- package/dist/commands/auth/client/add.js +28 -229
- package/dist/commands/auth/client/add.js.map +1 -1
- package/dist/commands/auth/client/list.d.ts.map +1 -1
- package/dist/commands/auth/client/list.js +2 -7
- package/dist/commands/auth/client/list.js.map +1 -1
- package/dist/commands/auth/client/shared.d.ts +74 -0
- package/dist/commands/auth/client/shared.d.ts.map +1 -0
- package/dist/commands/auth/client/shared.js +163 -0
- package/dist/commands/auth/client/shared.js.map +1 -0
- package/dist/commands/auth/client/update.d.ts +1 -2
- package/dist/commands/auth/client/update.d.ts.map +1 -1
- package/dist/commands/auth/client/update.js +49 -213
- package/dist/commands/auth/client/update.js.map +1 -1
- package/package.json +4 -4
- package/src/commands/auth/client/add.ts +46 -249
- package/src/commands/auth/client/list.ts +2 -6
- package/src/commands/auth/client/shared.ts +210 -0
- package/src/commands/auth/client/update.ts +65 -246
- package/dist/util/flags.d.ts +0 -6
- package/dist/util/flags.d.ts.map +0 -1
- package/dist/util/flags.js +0 -6
- package/dist/util/flags.js.map +0 -1
- package/src/util/flags.ts +0 -14
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
|
|
2
|
-
> instant-cli@1.0.21-branch-cli-codex-update.
|
|
2
|
+
> instant-cli@1.0.21-branch-cli-codex-update.25193076159.1 build /home/runner/work/instant/instant/client/packages/cli
|
|
3
3
|
> rm -rf dist; tsc -p tsconfig.build.json
|
|
4
4
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Effect, Schema } from 'effect';
|
|
2
|
-
import { FileSystem } from '@effect/platform';
|
|
3
2
|
import { GlobalOpts } from '../../../context/globalOpts.ts';
|
|
4
3
|
export declare const ClientTypeSchema: Schema.Literal<["google", "github", "apple", "linkedin", "clerk", "firebase"]>;
|
|
5
4
|
export declare const authClientAddCmd: (opts: {
|
|
6
5
|
type?: string | undefined;
|
|
7
6
|
name?: string | undefined;
|
|
8
7
|
app?: string | undefined;
|
|
9
|
-
} & Record<string, unknown>) => Effect.Effect<void | undefined, import("../../../lib/ui.ts").UIError | import("../../../lib/http.ts").InstantHttpError | import("effect/Cause").TimeoutException | import("@effect/platform/HttpClientError").RequestError | import("effect/ParseResult").ParseError | import("@effect/platform/HttpClientError").ResponseError, GlobalOpts | FileSystem.FileSystem | import("../../../lib/http.ts").InstantHttpAuthed | import("../../../context/currentApp.ts").CurrentApp>;
|
|
8
|
+
} & Record<string, unknown>) => Effect.Effect<void | undefined, import("../../../lib/ui.ts").UIError | import("../../../lib/http.ts").InstantHttpError | import("effect/Cause").TimeoutException | import("@effect/platform/HttpClientError").RequestError | import("effect/ParseResult").ParseError | import("@effect/platform/HttpClientError").ResponseError, GlobalOpts | import("@effect/platform/FileSystem").FileSystem | import("../../../lib/http.ts").InstantHttpAuthed | import("../../../context/currentApp.ts").CurrentApp>;
|
|
10
9
|
//# sourceMappingURL=add.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../../src/commands/auth/client/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAiB,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../../src/commands/auth/client/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAiB,MAAM,EAAE,MAAM,QAAQ,CAAC;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAiD5D,eAAO,MAAM,gBAAgB,gFAO5B,CAAC;AAosBF,eAAO,MAAM,gBAAgB;;;;wgBAwD5B,CAAC"}
|
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
import { Effect, Match, Option, Schema } from 'effect';
|
|
2
|
-
import { FileSystem } from '@effect/platform';
|
|
3
2
|
import { BadArgsError } from "../../../errors.js";
|
|
4
3
|
import { GlobalOpts } from "../../../context/globalOpts.js";
|
|
5
|
-
import { optOrPrompt, optOrPromptBoolean, runUIEffect,
|
|
4
|
+
import { optOrPrompt, optOrPromptBoolean, runUIEffect, validateRequired, } from "../../../lib/ui.js";
|
|
6
5
|
import { addOAuthClient, findName, getClientNameAndProvider, getOrCreateProvider, } from "../../../lib/oauth.js";
|
|
7
6
|
import { DEFAULT_OAUTH_CALLBACK_URL, GOOGLE_AUTHORIZATION_ENDPOINT, GOOGLE_DISCOVERY_ENDPOINT, GOOGLE_TOKEN_ENDPOINT, APPLE_AUTHORIZATION_ENDPOINT, APPLE_DISCOVERY_ENDPOINT, APPLE_TOKEN_ENDPOINT, LINKEDIN_AUTHORIZATION_ENDPOINT, LINKEDIN_DISCOVERY_ENDPOINT, LINKEDIN_TOKEN_ENDPOINT, } from '@instantdb/platform';
|
|
8
7
|
import { UI } from "../../../ui/index.js";
|
|
9
8
|
import chalk from 'chalk';
|
|
10
9
|
import boxen from 'boxen';
|
|
11
10
|
import { link } from "../../../logging.js";
|
|
12
|
-
import { getFlag, hasAnyFlag, isTrueFlag } from "
|
|
11
|
+
import { appleKeyIdPrompt, applePrivateKeyFilePrompt, appleServicesIdPrompt, appleTeamIdPrompt, clerkPublishableKeyPrompt, clientIdPrompt, clientSecretPrompt, domainFromClerkKey, firebaseDiscoveryEndpoint, firebaseProjectIdPrompt, getFlag, hasAnyFlag, isTrueFlag, readPrivateKeyFile, redirectUriPrompt, validateFirebaseProjectId, } from "./shared.js";
|
|
13
12
|
export const ClientTypeSchema = Schema.Literal('google', 'github', 'apple', 'linkedin', 'clerk', 'firebase');
|
|
14
13
|
const GoogleAppTypeSchema = Schema.Literal('web', 'ios', 'android', 'button-for-web');
|
|
14
|
+
const googleConsoleUrl = 'https://console.developers.google.com/apis/credentials';
|
|
15
|
+
const githubDeveloperUrl = 'https://github.com/settings/developers';
|
|
16
|
+
const linkedinDeveloperUrl = 'https://www.linkedin.com/developers/apps';
|
|
17
|
+
const optionalRedirectPrompt = redirectUriPrompt({
|
|
18
|
+
heading: 'Custom redirect URI (optional):',
|
|
19
|
+
});
|
|
15
20
|
const selectGoogleAppType = (value) => Effect.gen(function* () {
|
|
16
21
|
const { yes } = yield* GlobalOpts;
|
|
17
22
|
return yield* Option.fromNullable(value).pipe(Effect.catchTag('NoSuchElementException', () => {
|
|
@@ -164,14 +169,7 @@ const handleGoogleClient = Effect.fn(function* (opts) {
|
|
|
164
169
|
required: !useSharedCredentials,
|
|
165
170
|
skipIf: useSharedCredentials,
|
|
166
171
|
skipMessage: '--client-id is not compatible with --dev-credentials. Drop one or the other.',
|
|
167
|
-
prompt: {
|
|
168
|
-
prompt: `Client ID: ${chalk.dim(`(from ${link('https://console.developers.google.com/apis/credentials')})`)}`,
|
|
169
|
-
modifyOutput: UI.modifiers.piped([
|
|
170
|
-
UI.modifiers.topPadding,
|
|
171
|
-
UI.modifiers.dimOnComplete,
|
|
172
|
-
]),
|
|
173
|
-
validate: validateRequired,
|
|
174
|
-
},
|
|
172
|
+
prompt: clientIdPrompt({ providerUrl: googleConsoleUrl }),
|
|
175
173
|
});
|
|
176
174
|
const usesCustomWebCredentials = !useSharedCredentials && appType === 'web';
|
|
177
175
|
const clientSecret = yield* optOrPrompt(opts['client-secret'], {
|
|
@@ -181,34 +179,11 @@ const handleGoogleClient = Effect.fn(function* (opts) {
|
|
|
181
179
|
skipMessage: useSharedCredentials
|
|
182
180
|
? '--client-secret is not compatible with --dev-credentials. Drop one or the other.'
|
|
183
181
|
: undefined,
|
|
184
|
-
prompt: {
|
|
185
|
-
prompt: `Client Secret: ${chalk.dim(`(from ${link('https://console.developers.google.com/apis/credentials')})`)}`,
|
|
186
|
-
validate: validateRequired,
|
|
187
|
-
sensitive: true,
|
|
188
|
-
modifyOutput: UI.modifiers.piped([
|
|
189
|
-
UI.modifiers.topPadding,
|
|
190
|
-
UI.modifiers.dimOnComplete,
|
|
191
|
-
]),
|
|
192
|
-
},
|
|
182
|
+
prompt: clientSecretPrompt({ providerUrl: googleConsoleUrl }),
|
|
193
183
|
});
|
|
194
184
|
const customRedirectUri = yield* optOrPrompt(opts['custom-redirect-uri'], {
|
|
195
185
|
required: false,
|
|
196
|
-
prompt:
|
|
197
|
-
prompt: '',
|
|
198
|
-
placeholder: 'https://yoursite.com/oauth/callback',
|
|
199
|
-
modifyOutput: UI.modifiers.piped([
|
|
200
|
-
(output, status) => {
|
|
201
|
-
if (status === 'idle') {
|
|
202
|
-
return (`\nCustom redirect URI (optional):
|
|
203
|
-
${chalk.dim('With a custom redirect URI, users will see "Redirecting to yoursite.com..." for a more branded experience.')}
|
|
204
|
-
${chalk.dim(`Your URI must forward to ${DEFAULT_OAUTH_CALLBACK_URL} with all query parameters preserved.`)}\n\n` +
|
|
205
|
-
stripFirstBlankLine(output));
|
|
206
|
-
}
|
|
207
|
-
return `\nCustom redirect URI (optional):\n${stripFirstBlankLine(output)}`;
|
|
208
|
-
},
|
|
209
|
-
UI.modifiers.dimOnComplete,
|
|
210
|
-
]),
|
|
211
|
-
},
|
|
186
|
+
prompt: optionalRedirectPrompt,
|
|
212
187
|
simpleName: '--custom-redirect-uri',
|
|
213
188
|
skipIf: !usesCustomWebCredentials,
|
|
214
189
|
skipMessage: useSharedCredentials
|
|
@@ -257,49 +232,19 @@ const handleGithubClient = Effect.fn(function* (opts) {
|
|
|
257
232
|
simpleName: '--client-id',
|
|
258
233
|
required: true,
|
|
259
234
|
skipIf: false,
|
|
260
|
-
prompt: {
|
|
261
|
-
prompt: `Client ID ${chalk.dim(`(from ${link('https://github.com/settings/developers')})`)}`,
|
|
262
|
-
modifyOutput: UI.modifiers.piped([
|
|
263
|
-
UI.modifiers.topPadding,
|
|
264
|
-
UI.modifiers.dimOnComplete,
|
|
265
|
-
]),
|
|
266
|
-
validate: validateRequired,
|
|
267
|
-
},
|
|
235
|
+
prompt: clientIdPrompt({ providerUrl: githubDeveloperUrl }),
|
|
268
236
|
});
|
|
269
237
|
const clientSecret = yield* optOrPrompt(opts['client-secret'], {
|
|
270
238
|
required: true,
|
|
271
239
|
skipIf: false,
|
|
272
240
|
simpleName: '--client-secret',
|
|
273
|
-
prompt: {
|
|
274
|
-
prompt: `Client Secret: ${chalk.dim(`(from ${link('https://github.com/settings/developers')})`)}`,
|
|
275
|
-
validate: validateRequired,
|
|
276
|
-
sensitive: true,
|
|
277
|
-
modifyOutput: UI.modifiers.piped([
|
|
278
|
-
UI.modifiers.topPadding,
|
|
279
|
-
UI.modifiers.dimOnComplete,
|
|
280
|
-
]),
|
|
281
|
-
},
|
|
241
|
+
prompt: clientSecretPrompt({ providerUrl: githubDeveloperUrl }),
|
|
282
242
|
});
|
|
283
243
|
const customRedirectUri = yield* optOrPrompt(opts['custom-redirect-uri'], {
|
|
284
244
|
required: false,
|
|
285
245
|
simpleName: '--custom-redirect-uri',
|
|
286
246
|
skipIf: false,
|
|
287
|
-
prompt:
|
|
288
|
-
prompt: '',
|
|
289
|
-
placeholder: 'https://yoursite.com/oauth/callback',
|
|
290
|
-
modifyOutput: UI.modifiers.piped([
|
|
291
|
-
(output, status) => {
|
|
292
|
-
if (status === 'idle') {
|
|
293
|
-
return (`\nCustom redirect URI (optional):
|
|
294
|
-
${chalk.dim('With a custom redirect URI, users will see "Redirecting to yoursite.com..." for a more branded experience.')}
|
|
295
|
-
${chalk.dim(`Your URI must forward to ${DEFAULT_OAUTH_CALLBACK_URL} with all query parameters preserved.`)}\n\n` +
|
|
296
|
-
stripFirstBlankLine(output));
|
|
297
|
-
}
|
|
298
|
-
return `\nCustom redirect URI (optional):\n${stripFirstBlankLine(output)}`;
|
|
299
|
-
},
|
|
300
|
-
UI.modifiers.dimOnComplete,
|
|
301
|
-
]),
|
|
302
|
-
},
|
|
247
|
+
prompt: optionalRedirectPrompt,
|
|
303
248
|
});
|
|
304
249
|
if (!clientName) {
|
|
305
250
|
return yield* BadArgsError.make({ message: 'Client name is required.' });
|
|
@@ -335,49 +280,19 @@ const handleLinkedInClient = Effect.fn(function* (opts) {
|
|
|
335
280
|
simpleName: '--client-id',
|
|
336
281
|
required: true,
|
|
337
282
|
skipIf: false,
|
|
338
|
-
prompt: {
|
|
339
|
-
prompt: `Client ID: ${chalk.dim(`(from ${link('https://www.linkedin.com/developers/apps')})`)}`,
|
|
340
|
-
modifyOutput: UI.modifiers.piped([
|
|
341
|
-
UI.modifiers.topPadding,
|
|
342
|
-
UI.modifiers.dimOnComplete,
|
|
343
|
-
]),
|
|
344
|
-
validate: validateRequired,
|
|
345
|
-
},
|
|
283
|
+
prompt: clientIdPrompt({ providerUrl: linkedinDeveloperUrl }),
|
|
346
284
|
});
|
|
347
285
|
const clientSecret = yield* optOrPrompt(opts['client-secret'], {
|
|
348
286
|
required: true,
|
|
349
287
|
skipIf: false,
|
|
350
288
|
simpleName: '--client-secret',
|
|
351
|
-
prompt: {
|
|
352
|
-
prompt: `Client Secret: ${chalk.dim(`(from ${link('https://www.linkedin.com/developers/apps')})`)}`,
|
|
353
|
-
validate: validateRequired,
|
|
354
|
-
sensitive: true,
|
|
355
|
-
modifyOutput: UI.modifiers.piped([
|
|
356
|
-
UI.modifiers.topPadding,
|
|
357
|
-
UI.modifiers.dimOnComplete,
|
|
358
|
-
]),
|
|
359
|
-
},
|
|
289
|
+
prompt: clientSecretPrompt({ providerUrl: linkedinDeveloperUrl }),
|
|
360
290
|
});
|
|
361
291
|
const customRedirectUri = yield* optOrPrompt(opts['custom-redirect-uri'], {
|
|
362
292
|
required: false,
|
|
363
293
|
simpleName: '--custom-redirect-uri',
|
|
364
294
|
skipIf: false,
|
|
365
|
-
prompt:
|
|
366
|
-
prompt: '',
|
|
367
|
-
placeholder: 'https://yoursite.com/oauth/callback',
|
|
368
|
-
modifyOutput: UI.modifiers.piped([
|
|
369
|
-
(output, status) => {
|
|
370
|
-
if (status === 'idle') {
|
|
371
|
-
return (`\nCustom redirect URI (optional):
|
|
372
|
-
${chalk.dim('With a custom redirect URI, users will see "Redirecting to yoursite.com..." for a more branded experience.')}
|
|
373
|
-
${chalk.dim(`Your URI must forward to ${DEFAULT_OAUTH_CALLBACK_URL} with all query parameters preserved.`)}\n\n` +
|
|
374
|
-
stripFirstBlankLine(output));
|
|
375
|
-
}
|
|
376
|
-
return `\nCustom redirect URI (optional):\n${stripFirstBlankLine(output)}`;
|
|
377
|
-
},
|
|
378
|
-
UI.modifiers.dimOnComplete,
|
|
379
|
-
]),
|
|
380
|
-
},
|
|
295
|
+
prompt: optionalRedirectPrompt,
|
|
381
296
|
});
|
|
382
297
|
if (!clientName) {
|
|
383
298
|
return yield* BadArgsError.make({ message: 'Client name is required.' });
|
|
@@ -407,22 +322,6 @@ ${chalk.dim(`Your URI must forward to ${DEFAULT_OAUTH_CALLBACK_URL} with all que
|
|
|
407
322
|
...redirectMessages,
|
|
408
323
|
].join('\n'), { dimBorder: true, padding: { right: 1, left: 1 } }));
|
|
409
324
|
});
|
|
410
|
-
const readPrivateKeyFile = Effect.fn('readPrivateKeyFile')(function* (path) {
|
|
411
|
-
const fs = yield* FileSystem.FileSystem;
|
|
412
|
-
// Strip shell-escape backslashes so paths like "file\ (2).p8" resolve correctly.
|
|
413
|
-
// Only on POSIX — Windows uses backslashes as path separators.
|
|
414
|
-
const normalizedPath = process.platform === 'win32' ? path : path.replace(/\\(.)/g, '$1');
|
|
415
|
-
const contents = yield* fs.readFileString(normalizedPath, 'utf8').pipe(Effect.mapError((e) => new BadArgsError({
|
|
416
|
-
message: `Could not read private key file at ${normalizedPath}: ${e.message}`,
|
|
417
|
-
})));
|
|
418
|
-
const trimmed = contents.trim();
|
|
419
|
-
if (!trimmed) {
|
|
420
|
-
return yield* BadArgsError.make({
|
|
421
|
-
message: `Private key file at ${normalizedPath} is empty.`,
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
return trimmed;
|
|
425
|
-
});
|
|
426
325
|
const handleAppleClient = Effect.fn(function* (opts) {
|
|
427
326
|
const { yes } = yield* GlobalOpts;
|
|
428
327
|
const { clientName, provider } = yield* getClientNameAndProvider('apple', opts);
|
|
@@ -430,14 +329,7 @@ const handleAppleClient = Effect.fn(function* (opts) {
|
|
|
430
329
|
simpleName: '--services-id',
|
|
431
330
|
required: true,
|
|
432
331
|
skipIf: false,
|
|
433
|
-
prompt: {
|
|
434
|
-
prompt: `Services ID ${chalk.dim(`(from ${link('https://developer.apple.com/account/resources/identifiers/list/serviceId')})`)}`,
|
|
435
|
-
modifyOutput: UI.modifiers.piped([
|
|
436
|
-
UI.modifiers.topPadding,
|
|
437
|
-
UI.modifiers.dimOnComplete,
|
|
438
|
-
]),
|
|
439
|
-
validate: validateRequired,
|
|
440
|
-
},
|
|
332
|
+
prompt: appleServicesIdPrompt({}),
|
|
441
333
|
});
|
|
442
334
|
// If any web-flow flag is provided, enable web flow; otherwise ask
|
|
443
335
|
// (non-interactively with --yes we default to native-only).
|
|
@@ -463,42 +355,21 @@ const handleAppleClient = Effect.fn(function* (opts) {
|
|
|
463
355
|
required: true,
|
|
464
356
|
skipIf: skipWeb,
|
|
465
357
|
skipMessage: `--team-id ${webSkipMessage}`,
|
|
466
|
-
prompt: {
|
|
467
|
-
prompt: `Team ID ${chalk.dim(`(from ${link('https://developer.apple.com/account#MembershipDetailsCard')})`)}`,
|
|
468
|
-
validate: validateRequired,
|
|
469
|
-
modifyOutput: UI.modifiers.piped([
|
|
470
|
-
UI.modifiers.topPadding,
|
|
471
|
-
UI.modifiers.dimOnComplete,
|
|
472
|
-
]),
|
|
473
|
-
},
|
|
358
|
+
prompt: appleTeamIdPrompt({}),
|
|
474
359
|
});
|
|
475
360
|
const keyId = yield* optOrPrompt(opts['key-id'], {
|
|
476
361
|
simpleName: '--key-id',
|
|
477
362
|
required: true,
|
|
478
363
|
skipIf: skipWeb,
|
|
479
364
|
skipMessage: `--key-id ${webSkipMessage}`,
|
|
480
|
-
prompt: {
|
|
481
|
-
prompt: `Key ID ${chalk.dim(`(from ${link('https://developer.apple.com/account/resources/authkeys/list')})`)}`,
|
|
482
|
-
validate: validateRequired,
|
|
483
|
-
modifyOutput: UI.modifiers.piped([
|
|
484
|
-
UI.modifiers.topPadding,
|
|
485
|
-
UI.modifiers.dimOnComplete,
|
|
486
|
-
]),
|
|
487
|
-
},
|
|
365
|
+
prompt: appleKeyIdPrompt({}),
|
|
488
366
|
});
|
|
489
367
|
const privateKeyPath = yield* optOrPrompt(opts['private-key-file'], {
|
|
490
368
|
simpleName: '--private-key-file',
|
|
491
369
|
required: true,
|
|
492
370
|
skipIf: skipWeb,
|
|
493
371
|
skipMessage: `--private-key-file ${webSkipMessage}`,
|
|
494
|
-
prompt: {
|
|
495
|
-
prompt: `Path to .p8 private key file ${chalk.dim('(downloaded from Apple)')}`,
|
|
496
|
-
validate: validateRequired,
|
|
497
|
-
modifyOutput: UI.modifiers.piped([
|
|
498
|
-
UI.modifiers.topPadding,
|
|
499
|
-
UI.modifiers.dimOnComplete,
|
|
500
|
-
]),
|
|
501
|
-
},
|
|
372
|
+
prompt: applePrivateKeyFilePrompt({}),
|
|
502
373
|
});
|
|
503
374
|
const privateKey = privateKeyPath
|
|
504
375
|
? yield* readPrivateKeyFile(privateKeyPath)
|
|
@@ -508,22 +379,7 @@ const handleAppleClient = Effect.fn(function* (opts) {
|
|
|
508
379
|
simpleName: '--custom-redirect-uri',
|
|
509
380
|
skipIf: skipWeb,
|
|
510
381
|
skipMessage: `--custom-redirect-uri ${webSkipMessage}`,
|
|
511
|
-
prompt:
|
|
512
|
-
prompt: '',
|
|
513
|
-
placeholder: 'https://yoursite.com/oauth/callback',
|
|
514
|
-
modifyOutput: UI.modifiers.piped([
|
|
515
|
-
(output, status) => {
|
|
516
|
-
if (status === 'idle') {
|
|
517
|
-
return (`\nCustom redirect URI (optional):
|
|
518
|
-
${chalk.dim('With a custom redirect URI, users will see "Redirecting to yoursite.com..." for a more branded experience.')}
|
|
519
|
-
${chalk.dim(`Your URI must forward to ${DEFAULT_OAUTH_CALLBACK_URL} with all query parameters preserved.`)}\n\n` +
|
|
520
|
-
stripFirstBlankLine(output));
|
|
521
|
-
}
|
|
522
|
-
return `\nCustom redirect URI (optional):\n${stripFirstBlankLine(output)}`;
|
|
523
|
-
},
|
|
524
|
-
UI.modifiers.dimOnComplete,
|
|
525
|
-
]),
|
|
526
|
-
},
|
|
382
|
+
prompt: optionalRedirectPrompt,
|
|
527
383
|
});
|
|
528
384
|
if (!clientName) {
|
|
529
385
|
return yield* BadArgsError.make({ message: 'Client name is required.' });
|
|
@@ -572,22 +428,7 @@ const handleClerkClient = Effect.fn(function* (opts) {
|
|
|
572
428
|
simpleName: '--publishable-key',
|
|
573
429
|
required: true,
|
|
574
430
|
skipIf: false,
|
|
575
|
-
prompt: {
|
|
576
|
-
prompt: `Clerk publishable key ${chalk.dim(`(from ${link('https://dashboard.clerk.com/last-active?path=api-keys')})`)}`,
|
|
577
|
-
placeholder: 'pk_********************************************************',
|
|
578
|
-
modifyOutput: UI.modifiers.piped([
|
|
579
|
-
UI.modifiers.topPadding,
|
|
580
|
-
UI.modifiers.dimOnComplete,
|
|
581
|
-
]),
|
|
582
|
-
validate: (val) => {
|
|
583
|
-
if (!val) {
|
|
584
|
-
return 'Publishable key is required';
|
|
585
|
-
}
|
|
586
|
-
if (!val.startsWith('pk_')) {
|
|
587
|
-
return 'Invalid publishable key. It should start with "pk_".';
|
|
588
|
-
}
|
|
589
|
-
},
|
|
590
|
-
},
|
|
431
|
+
prompt: clerkPublishableKeyPrompt({}),
|
|
591
432
|
});
|
|
592
433
|
if (!clientName) {
|
|
593
434
|
return yield* BadArgsError.make({ message: 'Client name is required.' });
|
|
@@ -624,27 +465,11 @@ const handleClerkClient = Effect.fn(function* (opts) {
|
|
|
624
465
|
});
|
|
625
466
|
const handleFirebaseClient = Effect.fn(function* (opts) {
|
|
626
467
|
const { clientName, provider } = yield* getClientNameAndProvider('firebase', opts);
|
|
627
|
-
const firebaseProjectIdRegex = /^[a-z][a-z0-9-]{4,28}[a-z0-9]$/;
|
|
628
468
|
const projectId = yield* optOrPrompt(opts['project-id'], {
|
|
629
469
|
simpleName: '--project-id',
|
|
630
470
|
required: true,
|
|
631
471
|
skipIf: false,
|
|
632
|
-
prompt: {
|
|
633
|
-
prompt: `Firebase project ID: (From Project Settings page on ${link('https://console.firebase.google.com/')})`,
|
|
634
|
-
placeholder: '',
|
|
635
|
-
modifyOutput: UI.modifiers.piped([
|
|
636
|
-
UI.modifiers.topPadding,
|
|
637
|
-
UI.modifiers.dimOnComplete,
|
|
638
|
-
]),
|
|
639
|
-
validate: (val) => {
|
|
640
|
-
if (!val) {
|
|
641
|
-
return 'Project ID is required';
|
|
642
|
-
}
|
|
643
|
-
if (!firebaseProjectIdRegex.test(val)) {
|
|
644
|
-
return 'Invalid Firebase project ID. It must be 6-30 characters, start with a lowercase letter, contain only lowercase letters, digits, and hyphens, and not end with a hyphen.';
|
|
645
|
-
}
|
|
646
|
-
},
|
|
647
|
-
},
|
|
472
|
+
prompt: firebaseProjectIdPrompt({}),
|
|
648
473
|
});
|
|
649
474
|
// typeguard
|
|
650
475
|
if (!clientName || !projectId) {
|
|
@@ -652,15 +477,14 @@ const handleFirebaseClient = Effect.fn(function* (opts) {
|
|
|
652
477
|
message: 'Missing required arguments',
|
|
653
478
|
});
|
|
654
479
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
});
|
|
480
|
+
const validationError = validateFirebaseProjectId(projectId);
|
|
481
|
+
if (validationError) {
|
|
482
|
+
return yield* BadArgsError.make({ message: validationError });
|
|
659
483
|
}
|
|
660
484
|
const response = yield* addOAuthClient({
|
|
661
485
|
providerId: provider.id,
|
|
662
486
|
clientName,
|
|
663
|
-
discoveryEndpoint:
|
|
487
|
+
discoveryEndpoint: firebaseDiscoveryEndpoint(projectId),
|
|
664
488
|
});
|
|
665
489
|
yield* Effect.log(boxen([
|
|
666
490
|
`Firebase OAuth client created: ${response.client.client_name}`,
|
|
@@ -694,29 +518,4 @@ export const authClientAddCmd = Effect.fn(function* (opts) {
|
|
|
694
518
|
yield* Effect.logError(e.message);
|
|
695
519
|
yield* Effect.log(chalk.dim('hint: run `instant-cli auth client add --help` for the list of available arguments'));
|
|
696
520
|
})));
|
|
697
|
-
function domainFromClerkKey(key) {
|
|
698
|
-
try {
|
|
699
|
-
const parts = key.split('_');
|
|
700
|
-
const domainPartB64 = parts[parts.length - 1];
|
|
701
|
-
const domainPart = base64Decode(domainPartB64);
|
|
702
|
-
return domainPart.replace('$', '');
|
|
703
|
-
}
|
|
704
|
-
catch (e) {
|
|
705
|
-
console.error('Error getting domain from clerk key', e);
|
|
706
|
-
return null;
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
// Base64 decode, switching to url-safe decode if we hit an error
|
|
710
|
-
// Can't be sure which method Clerk uses because you can't generate
|
|
711
|
-
// `+` or `/` with characters that go in a normal host. Urls with
|
|
712
|
-
// chinese characters exist, they might encode to `+` or `/`, and
|
|
713
|
-
// Clerk might support them, so we'll be safe and do both.
|
|
714
|
-
function base64Decode(s) {
|
|
715
|
-
try {
|
|
716
|
-
return Buffer.from(s, 'base64').toString('utf-8');
|
|
717
|
-
}
|
|
718
|
-
catch (e) {
|
|
719
|
-
return Buffer.from(s, 'base64url').toString('utf-8');
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
521
|
//# sourceMappingURL=add.js.map
|