@authrim/setup 0.1.81 → 0.1.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/migrate.test.js +31 -4
- package/dist/__tests__/migrate.test.js.map +1 -1
- package/dist/__tests__/paths.test.js.map +1 -1
- package/dist/cli/commands/delete.d.ts.map +1 -1
- package/dist/cli/commands/delete.js +4 -3
- package/dist/cli/commands/delete.js.map +1 -1
- package/dist/cli/commands/deploy.d.ts.map +1 -1
- package/dist/cli/commands/deploy.js +12 -8
- package/dist/cli/commands/deploy.js.map +1 -1
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +2 -1
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/init.d.ts +1 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +255 -201
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +5 -3
- package/dist/cli/commands/migrate.js.map +1 -1
- package/dist/core/keys.d.ts.map +1 -1
- package/dist/core/keys.js.map +1 -1
- package/dist/core/migrate.d.ts.map +1 -1
- package/dist/core/migrate.js.map +1 -1
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +1 -3
- package/dist/core/paths.js.map +1 -1
- package/dist/core/wrangler-sync.d.ts.map +1 -1
- package/dist/core/wrangler-sync.js +2 -2
- package/dist/core/wrangler-sync.js.map +1 -1
- package/dist/i18n/detector.d.ts +28 -0
- package/dist/i18n/detector.d.ts.map +1 -0
- package/dist/i18n/detector.js +103 -0
- package/dist/i18n/detector.js.map +1 -0
- package/dist/i18n/index.d.ts +64 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +194 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/locales/en.d.ts +8 -0
- package/dist/i18n/locales/en.d.ts.map +1 -0
- package/dist/i18n/locales/en.js +593 -0
- package/dist/i18n/locales/en.js.map +1 -0
- package/dist/i18n/locales/ja.d.ts +8 -0
- package/dist/i18n/locales/ja.d.ts.map +1 -0
- package/dist/i18n/locales/ja.js +593 -0
- package/dist/i18n/locales/ja.js.map +1 -0
- package/dist/i18n/types.d.ts +303 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +19 -0
- package/dist/i18n/types.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +7 -2
- package/dist/web/api.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +21 -2
- package/dist/web/server.js.map +1 -1
- package/dist/web/ui.d.ts +2 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +87 -2
- package/dist/web/ui.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { input, select, confirm, password } from '@inquirer/prompts';
|
|
7
7
|
import chalk from 'chalk';
|
|
8
8
|
import ora from 'ora';
|
|
9
|
+
import { initI18n, t, getAvailableLocales, detectSystemLocale, } from '../../i18n/index.js';
|
|
9
10
|
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
10
11
|
import { existsSync } from 'node:fs';
|
|
11
12
|
import { join, resolve } from 'node:path';
|
|
@@ -15,9 +16,27 @@ import { createDefaultConfig, parseConfig } from '../../core/config.js';
|
|
|
15
16
|
import { generateAllSecrets, saveKeysToDirectory, generateKeyId, keysExistForEnvironment, } from '../../core/keys.js';
|
|
16
17
|
import { isWranglerInstalled, checkAuth, provisionResources, toResourceIds, getAccountId, detectEnvironments, getWorkersSubdomain, } from '../../core/cloudflare.js';
|
|
17
18
|
import { createLockFile, saveLockFile, loadLockFile } from '../../core/lock.js';
|
|
18
|
-
import { getEnvironmentPaths, getRelativeKeysPath, AUTHRIM_DIR
|
|
19
|
+
import { getEnvironmentPaths, getRelativeKeysPath, AUTHRIM_DIR } from '../../core/paths.js';
|
|
19
20
|
import { downloadSource, verifySourceStructure, checkForUpdate } from '../../core/source.js';
|
|
20
21
|
// =============================================================================
|
|
22
|
+
// Language Selection
|
|
23
|
+
// =============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* Show language selection prompt
|
|
26
|
+
* This is shown before the banner, so we use hardcoded multilingual prompt
|
|
27
|
+
*/
|
|
28
|
+
async function selectLanguage() {
|
|
29
|
+
const locales = getAvailableLocales();
|
|
30
|
+
const locale = await select({
|
|
31
|
+
message: 'Select language / 言語を選択 / 选择语言',
|
|
32
|
+
choices: locales.map((l) => ({
|
|
33
|
+
value: l.code,
|
|
34
|
+
name: `${l.flag || ''} ${l.nativeName}`.trim(),
|
|
35
|
+
})),
|
|
36
|
+
});
|
|
37
|
+
return locale;
|
|
38
|
+
}
|
|
39
|
+
// =============================================================================
|
|
21
40
|
// Version
|
|
22
41
|
// =============================================================================
|
|
23
42
|
const require = createRequire(import.meta.url);
|
|
@@ -37,21 +56,23 @@ function getVersion() {
|
|
|
37
56
|
function printBanner() {
|
|
38
57
|
const version = getVersion();
|
|
39
58
|
const versionStr = `v${version}`.padEnd(7); // "v0.1.58" = 7 chars
|
|
59
|
+
const title = `🔐 ${t('banner.title')} ${versionStr}`;
|
|
60
|
+
const subtitle = t('banner.subtitle');
|
|
40
61
|
console.log('');
|
|
41
62
|
console.log(chalk.blue('╔═══════════════════════════════════════════════════════════╗'));
|
|
42
63
|
console.log(chalk.blue('║') +
|
|
43
|
-
chalk.bold.white(`
|
|
64
|
+
chalk.bold.white(` ${title} `.slice(0, 59)) +
|
|
44
65
|
chalk.blue('║'));
|
|
45
66
|
console.log(chalk.blue('║') +
|
|
46
|
-
chalk.gray(
|
|
67
|
+
chalk.gray(` ${subtitle} `.slice(0, 55)) +
|
|
47
68
|
chalk.blue('║'));
|
|
48
69
|
console.log(chalk.blue('╚═══════════════════════════════════════════════════════════╝'));
|
|
49
70
|
console.log('');
|
|
50
|
-
console.log(chalk.bgYellow.black(
|
|
51
|
-
console.log(chalk.yellow('
|
|
52
|
-
console.log(chalk.yellow('
|
|
71
|
+
console.log(chalk.bgYellow.black(` ⚠️ ${t('banner.warning')} `));
|
|
72
|
+
console.log(chalk.yellow(` ${t('banner.warningDetail')}`));
|
|
73
|
+
console.log(chalk.yellow(` ${t('banner.adminWarning')}`));
|
|
53
74
|
console.log('');
|
|
54
|
-
console.log(chalk.gray(
|
|
75
|
+
console.log(chalk.gray(` ${t('banner.exitHint')}`));
|
|
55
76
|
console.log('');
|
|
56
77
|
}
|
|
57
78
|
// Store the workers.dev subdomain for URL generation
|
|
@@ -372,6 +393,28 @@ async function updateExistingSource(sourceDir, gitRef) {
|
|
|
372
393
|
// Main Command
|
|
373
394
|
// =============================================================================
|
|
374
395
|
export async function initCommand(options) {
|
|
396
|
+
// Step 0: Language selection (before banner)
|
|
397
|
+
// Priority: --lang option > env var > system locale > interactive selection
|
|
398
|
+
let locale;
|
|
399
|
+
if (options.lang) {
|
|
400
|
+
// Use provided language option
|
|
401
|
+
locale = options.lang;
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
// Check system locale first
|
|
405
|
+
const systemLocale = detectSystemLocale();
|
|
406
|
+
if (systemLocale !== 'en') {
|
|
407
|
+
// Non-English system locale detected, use it
|
|
408
|
+
locale = systemLocale;
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
// Show language selection prompt
|
|
412
|
+
locale = await selectLanguage();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// Initialize i18n with selected locale
|
|
416
|
+
await initI18n(locale);
|
|
417
|
+
// Now show the banner in the selected language
|
|
375
418
|
printBanner();
|
|
376
419
|
// Load existing config if provided
|
|
377
420
|
if (options.config) {
|
|
@@ -388,35 +431,35 @@ export async function initCommand(options) {
|
|
|
388
431
|
// Show startup menu
|
|
389
432
|
console.log(chalk.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
390
433
|
console.log('');
|
|
391
|
-
console.log('
|
|
434
|
+
console.log(` ${t('startup.description')}`);
|
|
392
435
|
console.log('');
|
|
393
436
|
console.log(chalk.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
394
437
|
console.log('');
|
|
395
438
|
const startupChoice = await select({
|
|
396
|
-
message: '
|
|
439
|
+
message: t('mode.prompt'),
|
|
397
440
|
choices: [
|
|
398
441
|
{
|
|
399
442
|
value: 'webui',
|
|
400
|
-
name:
|
|
401
|
-
description: '
|
|
443
|
+
name: `🌐 ${t('mode.quick')}`,
|
|
444
|
+
description: t('mode.quickDesc'),
|
|
402
445
|
},
|
|
403
446
|
{
|
|
404
447
|
value: 'cli',
|
|
405
|
-
name:
|
|
406
|
-
description: '
|
|
448
|
+
name: `⌨️ ${t('mode.advanced')}`,
|
|
449
|
+
description: t('mode.advancedDesc'),
|
|
407
450
|
},
|
|
408
451
|
{
|
|
409
452
|
value: 'cancel',
|
|
410
|
-
name:
|
|
411
|
-
description: '
|
|
453
|
+
name: `❌ ${t('startup.cancel')}`,
|
|
454
|
+
description: t('startup.cancelDesc'),
|
|
412
455
|
},
|
|
413
456
|
],
|
|
414
457
|
});
|
|
415
458
|
if (startupChoice === 'cancel') {
|
|
416
459
|
console.log('');
|
|
417
|
-
console.log(chalk.gray('
|
|
460
|
+
console.log(chalk.gray(t('startup.cancelled')));
|
|
418
461
|
console.log('');
|
|
419
|
-
console.log(chalk.gray('
|
|
462
|
+
console.log(chalk.gray(t('startup.resumeLater')));
|
|
420
463
|
console.log(chalk.cyan(' npx @authrim/setup'));
|
|
421
464
|
console.log('');
|
|
422
465
|
return;
|
|
@@ -430,7 +473,7 @@ export async function initCommand(options) {
|
|
|
430
473
|
else {
|
|
431
474
|
// Start Web UI
|
|
432
475
|
console.log('');
|
|
433
|
-
console.log(chalk.cyan(
|
|
476
|
+
console.log(chalk.cyan(`🌐 ${t('webUi.starting')}`));
|
|
434
477
|
console.log('');
|
|
435
478
|
const { startWebServer } = await import('../../web/server.js');
|
|
436
479
|
await startWebServer({ openBrowser: true });
|
|
@@ -443,38 +486,38 @@ async function runCliSetup(options) {
|
|
|
443
486
|
// Main menu loop - keeps returning to menu until user exits
|
|
444
487
|
while (true) {
|
|
445
488
|
const setupMode = await select({
|
|
446
|
-
message: '
|
|
489
|
+
message: t('menu.prompt'),
|
|
447
490
|
choices: [
|
|
448
491
|
{
|
|
449
492
|
value: 'quick',
|
|
450
|
-
name:
|
|
451
|
-
description: '
|
|
493
|
+
name: `⚡ ${t('menu.quick')}`,
|
|
494
|
+
description: t('menu.quickDesc'),
|
|
452
495
|
},
|
|
453
496
|
{
|
|
454
497
|
value: 'normal',
|
|
455
|
-
name:
|
|
456
|
-
description: '
|
|
498
|
+
name: `🔧 ${t('menu.custom')}`,
|
|
499
|
+
description: t('menu.customDesc'),
|
|
457
500
|
},
|
|
458
501
|
{
|
|
459
502
|
value: 'manage',
|
|
460
|
-
name:
|
|
461
|
-
description: '
|
|
503
|
+
name: `📋 ${t('menu.manage')}`,
|
|
504
|
+
description: t('menu.manageDesc'),
|
|
462
505
|
},
|
|
463
506
|
{
|
|
464
507
|
value: 'load',
|
|
465
|
-
name:
|
|
466
|
-
description: '
|
|
508
|
+
name: `📂 ${t('menu.load')}`,
|
|
509
|
+
description: t('menu.loadDesc'),
|
|
467
510
|
},
|
|
468
511
|
{
|
|
469
512
|
value: 'exit',
|
|
470
|
-
name:
|
|
471
|
-
description: '
|
|
513
|
+
name: `❌ ${t('menu.exit')}`,
|
|
514
|
+
description: t('menu.exitDesc'),
|
|
472
515
|
},
|
|
473
516
|
],
|
|
474
517
|
});
|
|
475
518
|
if (setupMode === 'exit') {
|
|
476
519
|
console.log('');
|
|
477
|
-
console.log(chalk.gray('
|
|
520
|
+
console.log(chalk.gray(t('menu.goodbye')));
|
|
478
521
|
console.log('');
|
|
479
522
|
break;
|
|
480
523
|
}
|
|
@@ -788,60 +831,63 @@ async function runLoadConfig() {
|
|
|
788
831
|
async function runQuickSetup(options) {
|
|
789
832
|
console.log('');
|
|
790
833
|
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
791
|
-
console.log(chalk.bold('
|
|
834
|
+
console.log(chalk.bold(t('quick.title')));
|
|
792
835
|
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
793
836
|
console.log('');
|
|
794
837
|
// Step 1: Environment prefix
|
|
795
838
|
const envPrefix = await input({
|
|
796
|
-
message: '
|
|
839
|
+
message: t('env.prompt'),
|
|
797
840
|
default: options.env || 'prod',
|
|
798
841
|
validate: (value) => {
|
|
799
842
|
if (!/^[a-z][a-z0-9-]*$/.test(value)) {
|
|
800
|
-
return '
|
|
843
|
+
return t('env.customValidation');
|
|
801
844
|
}
|
|
802
845
|
return true;
|
|
803
846
|
},
|
|
804
847
|
});
|
|
805
848
|
// Check if environment already exists
|
|
806
|
-
const checkSpinner = ora('
|
|
849
|
+
const checkSpinner = ora(t('env.checking')).start();
|
|
807
850
|
try {
|
|
808
851
|
const existingEnvs = await detectEnvironments();
|
|
809
852
|
const existingEnv = existingEnvs.find((e) => e.env === envPrefix);
|
|
810
853
|
if (existingEnv) {
|
|
811
|
-
checkSpinner.fail(
|
|
854
|
+
checkSpinner.fail(t('env.alreadyExists', { env: envPrefix }));
|
|
812
855
|
console.log('');
|
|
813
|
-
console.log(chalk.yellow('
|
|
814
|
-
console.log(`
|
|
815
|
-
console.log(`
|
|
816
|
-
console.log(`
|
|
856
|
+
console.log(chalk.yellow(' ' + t('env.existingResources')));
|
|
857
|
+
console.log(` ${t('env.workers', { count: String(existingEnv.workers.length) })}`);
|
|
858
|
+
console.log(` ${t('env.d1Databases', { count: String(existingEnv.d1.length) })}`);
|
|
859
|
+
console.log(` ${t('env.kvNamespaces', { count: String(existingEnv.kv.length) })}`);
|
|
817
860
|
console.log('');
|
|
818
|
-
console.log(chalk.yellow('
|
|
861
|
+
console.log(chalk.yellow(' ' + t('env.chooseAnother')));
|
|
819
862
|
return;
|
|
820
863
|
}
|
|
821
|
-
checkSpinner.succeed('
|
|
864
|
+
checkSpinner.succeed(t('env.available'));
|
|
822
865
|
}
|
|
823
866
|
catch {
|
|
824
|
-
checkSpinner.warn(
|
|
867
|
+
checkSpinner.warn(t('env.checkFailed'));
|
|
825
868
|
}
|
|
826
869
|
// Step 2: Cloudflare API Token
|
|
827
870
|
const cfApiToken = await password({
|
|
828
|
-
message: '
|
|
871
|
+
message: t('cf.apiTokenPrompt'),
|
|
829
872
|
mask: '*',
|
|
830
873
|
validate: (value) => {
|
|
831
874
|
if (!value || value.length < 10) {
|
|
832
|
-
return '
|
|
875
|
+
return t('cf.apiTokenValidation');
|
|
833
876
|
}
|
|
834
877
|
return true;
|
|
835
878
|
},
|
|
836
879
|
});
|
|
837
880
|
// Step 3: Show infrastructure info
|
|
838
881
|
console.log('');
|
|
839
|
-
console.log(chalk.gray('
|
|
840
|
-
|
|
882
|
+
console.log(chalk.gray(' ' +
|
|
883
|
+
t('infra.workersToDeploy', {
|
|
884
|
+
workers: envPrefix + '-ar-router, ' + envPrefix + '-ar-auth, ...',
|
|
885
|
+
})));
|
|
886
|
+
console.log(chalk.gray(' ' + t('infra.defaultApi', { url: getWorkersDevUrl(envPrefix + '-ar-router') })));
|
|
841
887
|
console.log('');
|
|
842
888
|
// Step 4: Domain configuration (single-tenant mode only in Quick Setup)
|
|
843
889
|
const useCustomDomain = await confirm({
|
|
844
|
-
message: '
|
|
890
|
+
message: t('domain.prompt'),
|
|
845
891
|
default: false,
|
|
846
892
|
});
|
|
847
893
|
let apiDomain = null;
|
|
@@ -849,55 +895,59 @@ async function runQuickSetup(options) {
|
|
|
849
895
|
let adminUiDomain = null;
|
|
850
896
|
if (useCustomDomain) {
|
|
851
897
|
console.log('');
|
|
852
|
-
console.log(chalk.gray('
|
|
898
|
+
console.log(chalk.gray(' ' + t('domain.singleTenantNote')));
|
|
853
899
|
console.log('');
|
|
854
900
|
apiDomain = await input({
|
|
855
|
-
message: '
|
|
901
|
+
message: t('domain.apiDomain'),
|
|
856
902
|
validate: (value) => {
|
|
857
903
|
if (!value)
|
|
858
904
|
return true; // Allow empty for workers.dev fallback
|
|
859
905
|
if (!/^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(value)) {
|
|
860
|
-
return '
|
|
906
|
+
return t('domain.customValidation');
|
|
861
907
|
}
|
|
862
908
|
return true;
|
|
863
909
|
},
|
|
864
910
|
});
|
|
865
911
|
loginUiDomain = await input({
|
|
866
|
-
message: '
|
|
912
|
+
message: t('domain.loginUiDomain'),
|
|
867
913
|
default: '',
|
|
868
914
|
});
|
|
869
915
|
adminUiDomain = await input({
|
|
870
|
-
message: '
|
|
916
|
+
message: t('domain.adminUiDomain'),
|
|
871
917
|
default: '',
|
|
872
918
|
});
|
|
873
919
|
}
|
|
874
920
|
// Database Configuration
|
|
875
921
|
console.log('');
|
|
876
|
-
console.log(chalk.blue('━━━
|
|
877
|
-
console.log(chalk.yellow('⚠️
|
|
922
|
+
console.log(chalk.blue('━━━ ' + t('db.title') + ' ━━━'));
|
|
923
|
+
console.log(chalk.yellow('⚠️ ' + t('db.regionWarning')));
|
|
878
924
|
console.log('');
|
|
879
925
|
const locationChoices = [
|
|
880
|
-
{ name: '
|
|
881
|
-
{ name: '──
|
|
882
|
-
{ name: '
|
|
883
|
-
{ name: '
|
|
884
|
-
{ name: '
|
|
885
|
-
{ name: '
|
|
886
|
-
{ name: '
|
|
887
|
-
{ name: '
|
|
888
|
-
{
|
|
889
|
-
|
|
926
|
+
{ name: t('region.auto'), value: 'auto' },
|
|
927
|
+
{ name: '── ' + t('db.locationHints') + ' ──', value: '__separator1__', disabled: true },
|
|
928
|
+
{ name: t('region.wnam'), value: 'wnam' },
|
|
929
|
+
{ name: t('region.enam'), value: 'enam' },
|
|
930
|
+
{ name: t('region.weur'), value: 'weur' },
|
|
931
|
+
{ name: t('region.eeur'), value: 'eeur' },
|
|
932
|
+
{ name: t('region.apac'), value: 'apac' },
|
|
933
|
+
{ name: t('region.oceania'), value: 'oc' },
|
|
934
|
+
{
|
|
935
|
+
name: '── ' + t('db.jurisdictionCompliance') + ' ──',
|
|
936
|
+
value: '__separator2__',
|
|
937
|
+
disabled: true,
|
|
938
|
+
},
|
|
939
|
+
{ name: t('region.euJurisdiction'), value: 'eu' },
|
|
890
940
|
];
|
|
891
|
-
console.log(chalk.gray('
|
|
941
|
+
console.log(chalk.gray(' ' + t('db.coreDescription')));
|
|
892
942
|
const coreDbLocation = await select({
|
|
893
|
-
message: '
|
|
943
|
+
message: t('db.coreRegion'),
|
|
894
944
|
choices: locationChoices,
|
|
895
945
|
default: 'auto',
|
|
896
946
|
});
|
|
897
947
|
console.log('');
|
|
898
|
-
console.log(chalk.gray('
|
|
948
|
+
console.log(chalk.gray(' ' + t('db.piiDescription')));
|
|
899
949
|
const piiDbLocation = await select({
|
|
900
|
-
message: '
|
|
950
|
+
message: t('db.piiRegion'),
|
|
901
951
|
choices: locationChoices,
|
|
902
952
|
default: 'auto',
|
|
903
953
|
});
|
|
@@ -913,43 +963,43 @@ async function runQuickSetup(options) {
|
|
|
913
963
|
}
|
|
914
964
|
// Email Provider Configuration
|
|
915
965
|
console.log('');
|
|
916
|
-
console.log(chalk.blue('━━━
|
|
917
|
-
console.log(chalk.gray('
|
|
966
|
+
console.log(chalk.blue('━━━ ' + t('email.title') + ' ━━━'));
|
|
967
|
+
console.log(chalk.gray(t('email.description')));
|
|
918
968
|
console.log('');
|
|
919
969
|
const configureEmail = await confirm({
|
|
920
|
-
message: '
|
|
970
|
+
message: t('email.prompt'),
|
|
921
971
|
default: false,
|
|
922
972
|
});
|
|
923
973
|
let emailConfig = { provider: 'none' };
|
|
924
974
|
if (configureEmail) {
|
|
925
975
|
console.log('');
|
|
926
|
-
console.log(chalk.gray('
|
|
927
|
-
console.log(chalk.gray('
|
|
928
|
-
console.log(chalk.gray('
|
|
976
|
+
console.log(chalk.gray(t('email.resendDesc')));
|
|
977
|
+
console.log(chalk.gray(t('email.apiKeyHint')));
|
|
978
|
+
console.log(chalk.gray(t('email.domainHint')));
|
|
929
979
|
console.log('');
|
|
930
980
|
const resendApiKey = await password({
|
|
931
|
-
message: '
|
|
981
|
+
message: t('email.apiKeyPrompt'),
|
|
932
982
|
mask: '*',
|
|
933
983
|
validate: (value) => {
|
|
934
984
|
if (!value.trim())
|
|
935
|
-
return '
|
|
985
|
+
return t('email.apiKeyRequired');
|
|
936
986
|
if (!value.startsWith('re_')) {
|
|
937
|
-
return '
|
|
987
|
+
return t('email.apiKeyWarning');
|
|
938
988
|
}
|
|
939
989
|
return true;
|
|
940
990
|
},
|
|
941
991
|
});
|
|
942
992
|
const fromAddress = await input({
|
|
943
|
-
message: '
|
|
993
|
+
message: t('email.fromAddressPrompt'),
|
|
944
994
|
default: 'noreply@yourdomain.com',
|
|
945
995
|
validate: (value) => {
|
|
946
996
|
if (!value.includes('@'))
|
|
947
|
-
return '
|
|
997
|
+
return t('email.fromAddressValidation');
|
|
948
998
|
return true;
|
|
949
999
|
},
|
|
950
1000
|
});
|
|
951
1001
|
const fromName = await input({
|
|
952
|
-
message: '
|
|
1002
|
+
message: t('email.fromNamePrompt'),
|
|
953
1003
|
default: 'Authrim',
|
|
954
1004
|
});
|
|
955
1005
|
emailConfig = {
|
|
@@ -959,8 +1009,8 @@ async function runQuickSetup(options) {
|
|
|
959
1009
|
apiKey: resendApiKey,
|
|
960
1010
|
};
|
|
961
1011
|
console.log('');
|
|
962
|
-
console.log(chalk.yellow('⚠️
|
|
963
|
-
console.log(chalk.gray('
|
|
1012
|
+
console.log(chalk.yellow('⚠️ ' + t('email.domainVerificationRequired')));
|
|
1013
|
+
console.log(chalk.gray(' ' + t('email.seeDocumentation')));
|
|
964
1014
|
}
|
|
965
1015
|
// Create configuration
|
|
966
1016
|
const config = createDefaultConfig(envPrefix);
|
|
@@ -1050,94 +1100,94 @@ async function runQuickSetup(options) {
|
|
|
1050
1100
|
async function runNormalSetup(options) {
|
|
1051
1101
|
console.log('');
|
|
1052
1102
|
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
1053
|
-
console.log(chalk.bold('
|
|
1103
|
+
console.log(chalk.bold(t('custom.title')));
|
|
1054
1104
|
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
1055
1105
|
console.log('');
|
|
1056
1106
|
// Step 1: Environment prefix
|
|
1057
1107
|
const envPrefix = await input({
|
|
1058
|
-
message: '
|
|
1108
|
+
message: t('env.prompt'),
|
|
1059
1109
|
default: options.env || 'prod',
|
|
1060
1110
|
validate: (value) => {
|
|
1061
1111
|
if (!/^[a-z][a-z0-9-]*$/.test(value)) {
|
|
1062
|
-
return '
|
|
1112
|
+
return t('env.customValidation');
|
|
1063
1113
|
}
|
|
1064
1114
|
return true;
|
|
1065
1115
|
},
|
|
1066
1116
|
});
|
|
1067
1117
|
// Check if environment already exists
|
|
1068
|
-
const checkSpinner = ora('
|
|
1118
|
+
const checkSpinner = ora(t('env.checking')).start();
|
|
1069
1119
|
try {
|
|
1070
1120
|
const existingEnvs = await detectEnvironments();
|
|
1071
1121
|
const existingEnv = existingEnvs.find((e) => e.env === envPrefix);
|
|
1072
1122
|
if (existingEnv) {
|
|
1073
|
-
checkSpinner.fail(
|
|
1123
|
+
checkSpinner.fail(t('env.alreadyExists', { env: envPrefix }));
|
|
1074
1124
|
console.log('');
|
|
1075
|
-
console.log(chalk.yellow('
|
|
1076
|
-
console.log(`
|
|
1077
|
-
console.log(`
|
|
1078
|
-
console.log(`
|
|
1125
|
+
console.log(chalk.yellow(' ' + t('env.existingResources')));
|
|
1126
|
+
console.log(` ${t('env.workers', { count: String(existingEnv.workers.length) })}`);
|
|
1127
|
+
console.log(` ${t('env.d1Databases', { count: String(existingEnv.d1.length) })}`);
|
|
1128
|
+
console.log(` ${t('env.kvNamespaces', { count: String(existingEnv.kv.length) })}`);
|
|
1079
1129
|
console.log('');
|
|
1080
|
-
console.log(chalk.yellow('
|
|
1130
|
+
console.log(chalk.yellow(' ' + t('env.chooseAnother')));
|
|
1081
1131
|
return;
|
|
1082
1132
|
}
|
|
1083
|
-
checkSpinner.succeed('
|
|
1133
|
+
checkSpinner.succeed(t('env.available'));
|
|
1084
1134
|
}
|
|
1085
1135
|
catch {
|
|
1086
|
-
checkSpinner.warn(
|
|
1136
|
+
checkSpinner.warn(t('env.checkFailed'));
|
|
1087
1137
|
}
|
|
1088
1138
|
// Step 2: Cloudflare API Token
|
|
1089
1139
|
const cfApiToken = await password({
|
|
1090
|
-
message: '
|
|
1140
|
+
message: t('cf.apiTokenPrompt'),
|
|
1091
1141
|
mask: '*',
|
|
1092
1142
|
validate: (value) => {
|
|
1093
1143
|
if (!value || value.length < 10) {
|
|
1094
|
-
return '
|
|
1144
|
+
return t('cf.apiTokenValidation');
|
|
1095
1145
|
}
|
|
1096
1146
|
return true;
|
|
1097
1147
|
},
|
|
1098
1148
|
});
|
|
1099
1149
|
// Step 3: Profile selection
|
|
1100
1150
|
const profile = await select({
|
|
1101
|
-
message: '
|
|
1151
|
+
message: t('profile.prompt'),
|
|
1102
1152
|
choices: [
|
|
1103
1153
|
{
|
|
1104
1154
|
value: 'basic-op',
|
|
1105
|
-
name: '
|
|
1106
|
-
description: '
|
|
1155
|
+
name: t('profile.basicOp'),
|
|
1156
|
+
description: t('profile.basicOpDesc'),
|
|
1107
1157
|
},
|
|
1108
1158
|
{
|
|
1109
1159
|
value: 'fapi-rw',
|
|
1110
|
-
name: '
|
|
1111
|
-
description: '
|
|
1160
|
+
name: t('profile.fapiRw'),
|
|
1161
|
+
description: t('profile.fapiRwDesc'),
|
|
1112
1162
|
},
|
|
1113
1163
|
{
|
|
1114
1164
|
value: 'fapi2-security',
|
|
1115
|
-
name: '
|
|
1116
|
-
description: '
|
|
1165
|
+
name: t('profile.fapi2Security'),
|
|
1166
|
+
description: t('profile.fapi2SecurityDesc'),
|
|
1117
1167
|
},
|
|
1118
1168
|
],
|
|
1119
1169
|
default: 'basic-op',
|
|
1120
1170
|
});
|
|
1121
1171
|
// Step 4: Infrastructure overview (Workers are auto-generated from env)
|
|
1122
1172
|
console.log('');
|
|
1123
|
-
console.log(chalk.blue('━━━
|
|
1173
|
+
console.log(chalk.blue('━━━ ' + t('infra.title') + ' ━━━'));
|
|
1124
1174
|
console.log('');
|
|
1125
|
-
console.log(chalk.gray('
|
|
1126
|
-
console.log(`
|
|
1127
|
-
console.log(`
|
|
1128
|
-
console.log(`
|
|
1129
|
-
console.log(`
|
|
1130
|
-
console.log(chalk.gray('
|
|
1175
|
+
console.log(chalk.gray(' ' + t('infra.workersNote')));
|
|
1176
|
+
console.log(` ${t('infra.router')} ${chalk.cyan(envPrefix + '-ar-router')}`);
|
|
1177
|
+
console.log(` ${t('infra.auth')} ${chalk.cyan(envPrefix + '-ar-auth')}`);
|
|
1178
|
+
console.log(` ${t('infra.token')} ${chalk.cyan(envPrefix + '-ar-token')}`);
|
|
1179
|
+
console.log(` ${t('infra.management')} ${chalk.cyan(envPrefix + '-ar-management')}`);
|
|
1180
|
+
console.log(chalk.gray(' ' + t('infra.otherWorkers')));
|
|
1131
1181
|
console.log('');
|
|
1132
|
-
console.log(chalk.gray('
|
|
1133
|
-
console.log(`
|
|
1134
|
-
console.log(`
|
|
1182
|
+
console.log(chalk.gray(' ' + t('infra.defaultEndpoints')));
|
|
1183
|
+
console.log(` ${t('infra.api')} ${chalk.gray(getWorkersDevUrl(envPrefix + '-ar-router'))}`);
|
|
1184
|
+
console.log(` ${t('infra.ui')} ${chalk.gray(getPagesDevUrl(envPrefix + '-ar-ui'))}`);
|
|
1135
1185
|
console.log('');
|
|
1136
1186
|
// Step 5: Tenant configuration
|
|
1137
|
-
console.log(chalk.blue('━━━
|
|
1187
|
+
console.log(chalk.blue('━━━ ' + t('tenant.title') + ' ━━━'));
|
|
1138
1188
|
console.log('');
|
|
1139
1189
|
const multiTenant = await confirm({
|
|
1140
|
-
message: '
|
|
1190
|
+
message: t('tenant.multiTenantPrompt'),
|
|
1141
1191
|
default: false,
|
|
1142
1192
|
});
|
|
1143
1193
|
let tenantName = 'default';
|
|
@@ -1150,59 +1200,59 @@ async function runNormalSetup(options) {
|
|
|
1150
1200
|
if (multiTenant) {
|
|
1151
1201
|
// Multi-tenant mode: base domain is required, becomes the issuer base
|
|
1152
1202
|
console.log('');
|
|
1153
|
-
console.log(chalk.blue('━━━
|
|
1203
|
+
console.log(chalk.blue('━━━ ' + t('tenant.multiTenantTitle') + ' ━━━'));
|
|
1154
1204
|
console.log('');
|
|
1155
|
-
console.log(chalk.gray('
|
|
1156
|
-
console.log(chalk.gray(' •
|
|
1157
|
-
console.log(chalk.gray(' •
|
|
1158
|
-
console.log(chalk.gray(' •
|
|
1205
|
+
console.log(chalk.gray(' ' + t('tenant.multiTenantNote1')));
|
|
1206
|
+
console.log(chalk.gray(' • ' + t('tenant.multiTenantNote2')));
|
|
1207
|
+
console.log(chalk.gray(' • ' + t('tenant.multiTenantNote3')));
|
|
1208
|
+
console.log(chalk.gray(' • ' + t('tenant.multiTenantNote4')));
|
|
1159
1209
|
console.log('');
|
|
1160
1210
|
baseDomain = await input({
|
|
1161
|
-
message: '
|
|
1211
|
+
message: t('tenant.baseDomainPrompt'),
|
|
1162
1212
|
validate: (value) => {
|
|
1163
1213
|
if (!value)
|
|
1164
|
-
return '
|
|
1214
|
+
return t('tenant.baseDomainRequired');
|
|
1165
1215
|
if (!/^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(value)) {
|
|
1166
|
-
return '
|
|
1216
|
+
return t('tenant.baseDomainValidation');
|
|
1167
1217
|
}
|
|
1168
1218
|
return true;
|
|
1169
1219
|
},
|
|
1170
1220
|
});
|
|
1171
1221
|
console.log('');
|
|
1172
|
-
console.log(chalk.green(' ✓
|
|
1173
|
-
console.log(chalk.gray('
|
|
1222
|
+
console.log(chalk.green(' ✓ ' + t('tenant.issuerFormat', { domain: baseDomain })));
|
|
1223
|
+
console.log(chalk.gray(' ' + t('tenant.issuerExample', { domain: baseDomain })));
|
|
1174
1224
|
console.log('');
|
|
1175
1225
|
// API domain in multi-tenant is the base domain (or custom apex)
|
|
1176
1226
|
apiDomain = baseDomain;
|
|
1177
1227
|
tenantName = await input({
|
|
1178
|
-
message: '
|
|
1228
|
+
message: t('tenant.defaultTenantPrompt'),
|
|
1179
1229
|
default: 'default',
|
|
1180
1230
|
validate: (value) => {
|
|
1181
1231
|
if (!/^[a-z][a-z0-9-]*$/.test(value)) {
|
|
1182
|
-
return '
|
|
1232
|
+
return t('tenant.defaultTenantValidation');
|
|
1183
1233
|
}
|
|
1184
1234
|
return true;
|
|
1185
1235
|
},
|
|
1186
1236
|
});
|
|
1187
1237
|
tenantDisplayName = await input({
|
|
1188
|
-
message: '
|
|
1238
|
+
message: t('tenant.displayNamePrompt'),
|
|
1189
1239
|
default: 'Default Tenant',
|
|
1190
1240
|
});
|
|
1191
1241
|
// UI domains for multi-tenant
|
|
1192
1242
|
console.log('');
|
|
1193
|
-
console.log(chalk.blue('━━━
|
|
1243
|
+
console.log(chalk.blue('━━━ ' + t('tenant.uiDomainTitle') + ' ━━━'));
|
|
1194
1244
|
console.log('');
|
|
1195
1245
|
const useCustomUiDomain = await confirm({
|
|
1196
|
-
message: '
|
|
1246
|
+
message: t('tenant.customUiDomainPrompt'),
|
|
1197
1247
|
default: false,
|
|
1198
1248
|
});
|
|
1199
1249
|
if (useCustomUiDomain) {
|
|
1200
1250
|
loginUiDomain = await input({
|
|
1201
|
-
message: '
|
|
1251
|
+
message: t('tenant.loginUiDomain'),
|
|
1202
1252
|
default: '',
|
|
1203
1253
|
});
|
|
1204
1254
|
adminUiDomain = await input({
|
|
1205
|
-
message: '
|
|
1255
|
+
message: t('tenant.adminUiDomain'),
|
|
1206
1256
|
default: '',
|
|
1207
1257
|
});
|
|
1208
1258
|
}
|
|
@@ -1210,86 +1260,86 @@ async function runNormalSetup(options) {
|
|
|
1210
1260
|
else {
|
|
1211
1261
|
// Single-tenant mode
|
|
1212
1262
|
console.log('');
|
|
1213
|
-
console.log(chalk.blue('━━━
|
|
1263
|
+
console.log(chalk.blue('━━━ ' + t('tenant.singleTenantTitle') + ' ━━━'));
|
|
1214
1264
|
console.log('');
|
|
1215
|
-
console.log(chalk.gray('
|
|
1216
|
-
console.log(chalk.gray(' •
|
|
1217
|
-
console.log(chalk.gray(' •
|
|
1265
|
+
console.log(chalk.gray(' ' + t('tenant.singleTenantNote1')));
|
|
1266
|
+
console.log(chalk.gray(' • ' + t('tenant.singleTenantNote2')));
|
|
1267
|
+
console.log(chalk.gray(' • ' + t('tenant.singleTenantNote3')));
|
|
1218
1268
|
console.log('');
|
|
1219
1269
|
tenantDisplayName = await input({
|
|
1220
|
-
message: '
|
|
1270
|
+
message: t('tenant.organizationName'),
|
|
1221
1271
|
default: 'Default Tenant',
|
|
1222
1272
|
});
|
|
1223
1273
|
const useCustomDomain = await confirm({
|
|
1224
|
-
message: '
|
|
1274
|
+
message: t('domain.prompt'),
|
|
1225
1275
|
default: false,
|
|
1226
1276
|
});
|
|
1227
1277
|
if (useCustomDomain) {
|
|
1228
1278
|
console.log('');
|
|
1229
|
-
console.log(chalk.gray('
|
|
1279
|
+
console.log(chalk.gray(' ' + t('domain.enterDomains')));
|
|
1230
1280
|
console.log('');
|
|
1231
1281
|
apiDomain = await input({
|
|
1232
|
-
message: '
|
|
1282
|
+
message: t('domain.apiDomain'),
|
|
1233
1283
|
validate: (value) => {
|
|
1234
1284
|
if (!value)
|
|
1235
1285
|
return true;
|
|
1236
1286
|
if (!/^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(value)) {
|
|
1237
|
-
return '
|
|
1287
|
+
return t('domain.customValidation');
|
|
1238
1288
|
}
|
|
1239
1289
|
return true;
|
|
1240
1290
|
},
|
|
1241
1291
|
});
|
|
1242
1292
|
loginUiDomain = await input({
|
|
1243
|
-
message: '
|
|
1293
|
+
message: t('domain.loginUiDomain'),
|
|
1244
1294
|
default: '',
|
|
1245
1295
|
});
|
|
1246
1296
|
adminUiDomain = await input({
|
|
1247
|
-
message: '
|
|
1297
|
+
message: t('domain.adminUiDomain'),
|
|
1248
1298
|
default: '',
|
|
1249
1299
|
});
|
|
1250
1300
|
}
|
|
1251
1301
|
if (apiDomain) {
|
|
1252
1302
|
console.log('');
|
|
1253
|
-
console.log(chalk.green(' ✓
|
|
1303
|
+
console.log(chalk.green(' ✓ ' + t('domain.issuerUrl', { url: 'https://' + apiDomain })));
|
|
1254
1304
|
}
|
|
1255
1305
|
else {
|
|
1256
1306
|
console.log('');
|
|
1257
|
-
console.log(chalk.green(' ✓
|
|
1258
|
-
console.log(chalk.gray('
|
|
1307
|
+
console.log(chalk.green(' ✓ ' + t('domain.issuerUrl', { url: getWorkersDevUrl(envPrefix + '-ar-router') })));
|
|
1308
|
+
console.log(chalk.gray(' ' + t('domain.usingWorkersDev')));
|
|
1259
1309
|
}
|
|
1260
1310
|
}
|
|
1261
1311
|
// Step 5: Optional components
|
|
1262
1312
|
console.log('');
|
|
1263
|
-
console.log(chalk.blue('━━━
|
|
1264
|
-
console.log(chalk.gray('
|
|
1313
|
+
console.log(chalk.blue('━━━ ' + t('components.title') + ' ━━━'));
|
|
1314
|
+
console.log(chalk.gray(' ' + t('components.note')));
|
|
1265
1315
|
console.log('');
|
|
1266
1316
|
const enableSaml = await confirm({
|
|
1267
|
-
message: '
|
|
1317
|
+
message: t('components.samlPrompt'),
|
|
1268
1318
|
default: false,
|
|
1269
1319
|
});
|
|
1270
1320
|
const enableVc = await confirm({
|
|
1271
|
-
message: '
|
|
1321
|
+
message: t('components.vcPrompt'),
|
|
1272
1322
|
default: false,
|
|
1273
1323
|
});
|
|
1274
1324
|
// Step 6: Feature flags
|
|
1275
1325
|
console.log('');
|
|
1276
|
-
console.log(chalk.blue('━━━
|
|
1326
|
+
console.log(chalk.blue('━━━ ' + t('features.title') + ' ━━━'));
|
|
1277
1327
|
console.log('');
|
|
1278
1328
|
const enableQueue = await confirm({
|
|
1279
|
-
message: '
|
|
1329
|
+
message: t('features.queuePrompt'),
|
|
1280
1330
|
default: false,
|
|
1281
1331
|
});
|
|
1282
1332
|
const enableR2 = await confirm({
|
|
1283
|
-
message: '
|
|
1333
|
+
message: t('features.r2Prompt'),
|
|
1284
1334
|
default: false,
|
|
1285
1335
|
});
|
|
1286
1336
|
const emailProviderChoice = await select({
|
|
1287
|
-
message: '
|
|
1337
|
+
message: t('email.title'),
|
|
1288
1338
|
choices: [
|
|
1289
|
-
{ value: 'none', name: '
|
|
1290
|
-
{ value: 'resend', name: '
|
|
1339
|
+
{ value: 'none', name: t('email.skipOption') },
|
|
1340
|
+
{ value: 'resend', name: t('email.resendOption') },
|
|
1291
1341
|
{ value: 'sendgrid', name: 'SendGrid (coming soon)', disabled: true },
|
|
1292
|
-
{ value: 'ses', name: '
|
|
1342
|
+
{ value: 'ses', name: t('email.sesOption') + ' (coming soon)', disabled: true },
|
|
1293
1343
|
],
|
|
1294
1344
|
default: 'none',
|
|
1295
1345
|
});
|
|
@@ -1297,33 +1347,33 @@ async function runNormalSetup(options) {
|
|
|
1297
1347
|
let emailConfigNormal = { provider: 'none' };
|
|
1298
1348
|
if (emailProviderChoice === 'resend') {
|
|
1299
1349
|
console.log('');
|
|
1300
|
-
console.log(chalk.blue('━━━
|
|
1301
|
-
console.log(chalk.gray('
|
|
1302
|
-
console.log(chalk.gray('
|
|
1350
|
+
console.log(chalk.blue('━━━ ' + t('email.resendOption') + ' ━━━'));
|
|
1351
|
+
console.log(chalk.gray(t('email.apiKeyHint')));
|
|
1352
|
+
console.log(chalk.gray(t('email.domainHint')));
|
|
1303
1353
|
console.log('');
|
|
1304
1354
|
const resendApiKey = await password({
|
|
1305
|
-
message: '
|
|
1355
|
+
message: t('email.apiKeyPrompt'),
|
|
1306
1356
|
mask: '*',
|
|
1307
1357
|
validate: (value) => {
|
|
1308
1358
|
if (!value.trim())
|
|
1309
|
-
return '
|
|
1359
|
+
return t('email.apiKeyRequired');
|
|
1310
1360
|
if (!value.startsWith('re_')) {
|
|
1311
|
-
return '
|
|
1361
|
+
return t('email.apiKeyWarning');
|
|
1312
1362
|
}
|
|
1313
1363
|
return true;
|
|
1314
1364
|
},
|
|
1315
1365
|
});
|
|
1316
1366
|
const fromAddress = await input({
|
|
1317
|
-
message: '
|
|
1367
|
+
message: t('email.fromAddressPrompt'),
|
|
1318
1368
|
default: 'noreply@yourdomain.com',
|
|
1319
1369
|
validate: (value) => {
|
|
1320
1370
|
if (!value.includes('@'))
|
|
1321
|
-
return '
|
|
1371
|
+
return t('email.fromAddressValidation');
|
|
1322
1372
|
return true;
|
|
1323
1373
|
},
|
|
1324
1374
|
});
|
|
1325
1375
|
const fromName = await input({
|
|
1326
|
-
message: '
|
|
1376
|
+
message: t('email.fromNamePrompt'),
|
|
1327
1377
|
default: 'Authrim',
|
|
1328
1378
|
});
|
|
1329
1379
|
emailConfigNormal = {
|
|
@@ -1333,12 +1383,12 @@ async function runNormalSetup(options) {
|
|
|
1333
1383
|
apiKey: resendApiKey,
|
|
1334
1384
|
};
|
|
1335
1385
|
console.log('');
|
|
1336
|
-
console.log(chalk.yellow('⚠️
|
|
1337
|
-
console.log(chalk.gray('
|
|
1386
|
+
console.log(chalk.yellow('⚠️ ' + t('email.domainVerificationRequired')));
|
|
1387
|
+
console.log(chalk.gray(' ' + t('email.seeDocumentation')));
|
|
1338
1388
|
}
|
|
1339
1389
|
// Step 7: Advanced OIDC settings
|
|
1340
1390
|
const configureOidc = await confirm({
|
|
1341
|
-
message: '
|
|
1391
|
+
message: t('oidc.configurePrompt'),
|
|
1342
1392
|
default: false,
|
|
1343
1393
|
});
|
|
1344
1394
|
let accessTokenTtl = 3600; // 1 hour
|
|
@@ -1347,76 +1397,76 @@ async function runNormalSetup(options) {
|
|
|
1347
1397
|
let pkceRequired = true;
|
|
1348
1398
|
if (configureOidc) {
|
|
1349
1399
|
console.log('');
|
|
1350
|
-
console.log(chalk.blue('━━━
|
|
1400
|
+
console.log(chalk.blue('━━━ ' + t('oidc.title') + ' ━━━'));
|
|
1351
1401
|
console.log('');
|
|
1352
1402
|
const accessTokenTtlStr = await input({
|
|
1353
|
-
message: '
|
|
1403
|
+
message: t('oidc.accessTokenTtl'),
|
|
1354
1404
|
default: '3600',
|
|
1355
1405
|
validate: (value) => {
|
|
1356
1406
|
const num = parseInt(value, 10);
|
|
1357
1407
|
if (isNaN(num) || num <= 0)
|
|
1358
|
-
return '
|
|
1408
|
+
return t('oidc.positiveInteger');
|
|
1359
1409
|
return true;
|
|
1360
1410
|
},
|
|
1361
1411
|
});
|
|
1362
1412
|
accessTokenTtl = parseInt(accessTokenTtlStr, 10);
|
|
1363
1413
|
const refreshTokenTtlStr = await input({
|
|
1364
|
-
message: '
|
|
1414
|
+
message: t('oidc.refreshTokenTtl'),
|
|
1365
1415
|
default: '604800',
|
|
1366
1416
|
validate: (value) => {
|
|
1367
1417
|
const num = parseInt(value, 10);
|
|
1368
1418
|
if (isNaN(num) || num <= 0)
|
|
1369
|
-
return '
|
|
1419
|
+
return t('oidc.positiveInteger');
|
|
1370
1420
|
return true;
|
|
1371
1421
|
},
|
|
1372
1422
|
});
|
|
1373
1423
|
refreshTokenTtl = parseInt(refreshTokenTtlStr, 10);
|
|
1374
1424
|
const authCodeTtlStr = await input({
|
|
1375
|
-
message: '
|
|
1425
|
+
message: t('oidc.authCodeTtl'),
|
|
1376
1426
|
default: '600',
|
|
1377
1427
|
validate: (value) => {
|
|
1378
1428
|
const num = parseInt(value, 10);
|
|
1379
1429
|
if (isNaN(num) || num <= 0)
|
|
1380
|
-
return '
|
|
1430
|
+
return t('oidc.positiveInteger');
|
|
1381
1431
|
return true;
|
|
1382
1432
|
},
|
|
1383
1433
|
});
|
|
1384
1434
|
authCodeTtl = parseInt(authCodeTtlStr, 10);
|
|
1385
1435
|
pkceRequired = await confirm({
|
|
1386
|
-
message: '
|
|
1436
|
+
message: t('oidc.pkceRequired'),
|
|
1387
1437
|
default: true,
|
|
1388
1438
|
});
|
|
1389
1439
|
}
|
|
1390
1440
|
// Step 8: Sharding settings
|
|
1391
1441
|
const configureSharding = await confirm({
|
|
1392
|
-
message: '
|
|
1442
|
+
message: t('sharding.configurePrompt'),
|
|
1393
1443
|
default: false,
|
|
1394
1444
|
});
|
|
1395
1445
|
let authCodeShards = 64;
|
|
1396
1446
|
let refreshTokenShards = 8;
|
|
1397
1447
|
if (configureSharding) {
|
|
1398
1448
|
console.log('');
|
|
1399
|
-
console.log(chalk.blue('━━━
|
|
1400
|
-
console.log(chalk.gray('
|
|
1449
|
+
console.log(chalk.blue('━━━ ' + t('sharding.title') + ' ━━━'));
|
|
1450
|
+
console.log(chalk.gray(' ' + t('sharding.note')));
|
|
1401
1451
|
console.log('');
|
|
1402
1452
|
const authCodeShardsStr = await input({
|
|
1403
|
-
message: '
|
|
1453
|
+
message: t('sharding.authCodeShards'),
|
|
1404
1454
|
default: '64',
|
|
1405
1455
|
validate: (value) => {
|
|
1406
1456
|
const num = parseInt(value, 10);
|
|
1407
1457
|
if (isNaN(num) || num <= 0)
|
|
1408
|
-
return '
|
|
1458
|
+
return t('oidc.positiveInteger');
|
|
1409
1459
|
return true;
|
|
1410
1460
|
},
|
|
1411
1461
|
});
|
|
1412
1462
|
authCodeShards = parseInt(authCodeShardsStr, 10);
|
|
1413
1463
|
const refreshTokenShardsStr = await input({
|
|
1414
|
-
message: '
|
|
1464
|
+
message: t('sharding.refreshTokenShards'),
|
|
1415
1465
|
default: '8',
|
|
1416
1466
|
validate: (value) => {
|
|
1417
1467
|
const num = parseInt(value, 10);
|
|
1418
1468
|
if (isNaN(num) || num <= 0)
|
|
1419
|
-
return '
|
|
1469
|
+
return t('oidc.positiveInteger');
|
|
1420
1470
|
return true;
|
|
1421
1471
|
},
|
|
1422
1472
|
});
|
|
@@ -1424,32 +1474,36 @@ async function runNormalSetup(options) {
|
|
|
1424
1474
|
}
|
|
1425
1475
|
// Step 9: Database Configuration
|
|
1426
1476
|
console.log('');
|
|
1427
|
-
console.log(chalk.blue('━━━
|
|
1428
|
-
console.log(chalk.yellow('⚠️
|
|
1477
|
+
console.log(chalk.blue('━━━ ' + t('db.title') + ' ━━━'));
|
|
1478
|
+
console.log(chalk.yellow('⚠️ ' + t('db.regionWarning')));
|
|
1429
1479
|
console.log('');
|
|
1430
1480
|
const dbLocationChoices = [
|
|
1431
|
-
{ name: '
|
|
1432
|
-
{ name: '──
|
|
1433
|
-
{ name: '
|
|
1434
|
-
{ name: '
|
|
1435
|
-
{ name: '
|
|
1436
|
-
{ name: '
|
|
1437
|
-
{ name: '
|
|
1438
|
-
{ name: '
|
|
1439
|
-
{
|
|
1440
|
-
|
|
1481
|
+
{ name: t('region.auto'), value: 'auto' },
|
|
1482
|
+
{ name: '── ' + t('db.locationHints') + ' ──', value: '__separator1__', disabled: true },
|
|
1483
|
+
{ name: t('region.wnam'), value: 'wnam' },
|
|
1484
|
+
{ name: t('region.enam'), value: 'enam' },
|
|
1485
|
+
{ name: t('region.weur'), value: 'weur' },
|
|
1486
|
+
{ name: t('region.eeur'), value: 'eeur' },
|
|
1487
|
+
{ name: t('region.apac'), value: 'apac' },
|
|
1488
|
+
{ name: t('region.oceania'), value: 'oc' },
|
|
1489
|
+
{
|
|
1490
|
+
name: '── ' + t('db.jurisdictionCompliance') + ' ──',
|
|
1491
|
+
value: '__separator2__',
|
|
1492
|
+
disabled: true,
|
|
1493
|
+
},
|
|
1494
|
+
{ name: t('region.euJurisdiction'), value: 'eu' },
|
|
1441
1495
|
];
|
|
1442
|
-
console.log(chalk.gray('
|
|
1496
|
+
console.log(chalk.gray(' ' + t('db.coreDescription')));
|
|
1443
1497
|
const coreDbLocation = await select({
|
|
1444
|
-
message: '
|
|
1498
|
+
message: t('db.coreRegion'),
|
|
1445
1499
|
choices: dbLocationChoices,
|
|
1446
1500
|
default: 'auto',
|
|
1447
1501
|
});
|
|
1448
1502
|
console.log('');
|
|
1449
|
-
console.log(chalk.gray('
|
|
1450
|
-
console.log(chalk.gray('
|
|
1503
|
+
console.log(chalk.gray(' ' + t('db.piiDescription')));
|
|
1504
|
+
console.log(chalk.gray(' ' + t('db.piiNote')));
|
|
1451
1505
|
const piiDbLocation = await select({
|
|
1452
|
-
message: '
|
|
1506
|
+
message: t('db.piiRegion'),
|
|
1453
1507
|
choices: dbLocationChoices,
|
|
1454
1508
|
default: 'auto',
|
|
1455
1509
|
});
|