@authrim/setup 0.1.82 → 0.1.85
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/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 +7 -6
- 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.js +183 -172
- 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 +3 -2
- package/dist/cli/commands/migrate.js.map +1 -1
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +12 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +12 -0
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/types.d.ts +0 -1
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/i18n/types.js +11 -10
- package/dist/i18n/types.js.map +1 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +23 -6
- package/dist/web/ui.js.map +1 -1
- package/package.json +1 -1
|
@@ -31,7 +31,7 @@ async function selectLanguage() {
|
|
|
31
31
|
message: 'Select language / 言語を選択 / 选择语言',
|
|
32
32
|
choices: locales.map((l) => ({
|
|
33
33
|
value: l.code,
|
|
34
|
-
name:
|
|
34
|
+
name: l.nativeName,
|
|
35
35
|
})),
|
|
36
36
|
});
|
|
37
37
|
return locale;
|
|
@@ -831,60 +831,63 @@ async function runLoadConfig() {
|
|
|
831
831
|
async function runQuickSetup(options) {
|
|
832
832
|
console.log('');
|
|
833
833
|
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
834
|
-
console.log(chalk.bold('
|
|
834
|
+
console.log(chalk.bold(t('quick.title')));
|
|
835
835
|
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
836
836
|
console.log('');
|
|
837
837
|
// Step 1: Environment prefix
|
|
838
838
|
const envPrefix = await input({
|
|
839
|
-
message: '
|
|
839
|
+
message: t('env.prompt'),
|
|
840
840
|
default: options.env || 'prod',
|
|
841
841
|
validate: (value) => {
|
|
842
842
|
if (!/^[a-z][a-z0-9-]*$/.test(value)) {
|
|
843
|
-
return '
|
|
843
|
+
return t('env.customValidation');
|
|
844
844
|
}
|
|
845
845
|
return true;
|
|
846
846
|
},
|
|
847
847
|
});
|
|
848
848
|
// Check if environment already exists
|
|
849
|
-
const checkSpinner = ora('
|
|
849
|
+
const checkSpinner = ora(t('env.checking')).start();
|
|
850
850
|
try {
|
|
851
851
|
const existingEnvs = await detectEnvironments();
|
|
852
852
|
const existingEnv = existingEnvs.find((e) => e.env === envPrefix);
|
|
853
853
|
if (existingEnv) {
|
|
854
|
-
checkSpinner.fail(
|
|
854
|
+
checkSpinner.fail(t('env.alreadyExists', { env: envPrefix }));
|
|
855
855
|
console.log('');
|
|
856
|
-
console.log(chalk.yellow('
|
|
857
|
-
console.log(`
|
|
858
|
-
console.log(`
|
|
859
|
-
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) })}`);
|
|
860
860
|
console.log('');
|
|
861
|
-
console.log(chalk.yellow('
|
|
861
|
+
console.log(chalk.yellow(' ' + t('env.chooseAnother')));
|
|
862
862
|
return;
|
|
863
863
|
}
|
|
864
|
-
checkSpinner.succeed('
|
|
864
|
+
checkSpinner.succeed(t('env.available'));
|
|
865
865
|
}
|
|
866
866
|
catch {
|
|
867
|
-
checkSpinner.warn(
|
|
867
|
+
checkSpinner.warn(t('env.checkFailed'));
|
|
868
868
|
}
|
|
869
869
|
// Step 2: Cloudflare API Token
|
|
870
870
|
const cfApiToken = await password({
|
|
871
|
-
message: '
|
|
871
|
+
message: t('cf.apiTokenPrompt'),
|
|
872
872
|
mask: '*',
|
|
873
873
|
validate: (value) => {
|
|
874
874
|
if (!value || value.length < 10) {
|
|
875
|
-
return '
|
|
875
|
+
return t('cf.apiTokenValidation');
|
|
876
876
|
}
|
|
877
877
|
return true;
|
|
878
878
|
},
|
|
879
879
|
});
|
|
880
880
|
// Step 3: Show infrastructure info
|
|
881
881
|
console.log('');
|
|
882
|
-
console.log(chalk.gray('
|
|
883
|
-
|
|
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') })));
|
|
884
887
|
console.log('');
|
|
885
888
|
// Step 4: Domain configuration (single-tenant mode only in Quick Setup)
|
|
886
889
|
const useCustomDomain = await confirm({
|
|
887
|
-
message: '
|
|
890
|
+
message: t('domain.prompt'),
|
|
888
891
|
default: false,
|
|
889
892
|
});
|
|
890
893
|
let apiDomain = null;
|
|
@@ -892,55 +895,59 @@ async function runQuickSetup(options) {
|
|
|
892
895
|
let adminUiDomain = null;
|
|
893
896
|
if (useCustomDomain) {
|
|
894
897
|
console.log('');
|
|
895
|
-
console.log(chalk.gray('
|
|
898
|
+
console.log(chalk.gray(' ' + t('domain.singleTenantNote')));
|
|
896
899
|
console.log('');
|
|
897
900
|
apiDomain = await input({
|
|
898
|
-
message: '
|
|
901
|
+
message: t('domain.apiDomain'),
|
|
899
902
|
validate: (value) => {
|
|
900
903
|
if (!value)
|
|
901
904
|
return true; // Allow empty for workers.dev fallback
|
|
902
905
|
if (!/^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(value)) {
|
|
903
|
-
return '
|
|
906
|
+
return t('domain.customValidation');
|
|
904
907
|
}
|
|
905
908
|
return true;
|
|
906
909
|
},
|
|
907
910
|
});
|
|
908
911
|
loginUiDomain = await input({
|
|
909
|
-
message: '
|
|
912
|
+
message: t('domain.loginUiDomain'),
|
|
910
913
|
default: '',
|
|
911
914
|
});
|
|
912
915
|
adminUiDomain = await input({
|
|
913
|
-
message: '
|
|
916
|
+
message: t('domain.adminUiDomain'),
|
|
914
917
|
default: '',
|
|
915
918
|
});
|
|
916
919
|
}
|
|
917
920
|
// Database Configuration
|
|
918
921
|
console.log('');
|
|
919
|
-
console.log(chalk.blue('━━━
|
|
920
|
-
console.log(chalk.yellow('⚠️
|
|
922
|
+
console.log(chalk.blue('━━━ ' + t('db.title') + ' ━━━'));
|
|
923
|
+
console.log(chalk.yellow('⚠️ ' + t('db.regionWarning')));
|
|
921
924
|
console.log('');
|
|
922
925
|
const locationChoices = [
|
|
923
|
-
{ name: '
|
|
924
|
-
{ name: '──
|
|
925
|
-
{ name: '
|
|
926
|
-
{ name: '
|
|
927
|
-
{ name: '
|
|
928
|
-
{ name: '
|
|
929
|
-
{ name: '
|
|
930
|
-
{ name: '
|
|
931
|
-
{
|
|
932
|
-
|
|
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' },
|
|
933
940
|
];
|
|
934
|
-
console.log(chalk.gray('
|
|
941
|
+
console.log(chalk.gray(' ' + t('db.coreDescription')));
|
|
935
942
|
const coreDbLocation = await select({
|
|
936
|
-
message: '
|
|
943
|
+
message: t('db.coreRegion'),
|
|
937
944
|
choices: locationChoices,
|
|
938
945
|
default: 'auto',
|
|
939
946
|
});
|
|
940
947
|
console.log('');
|
|
941
|
-
console.log(chalk.gray('
|
|
948
|
+
console.log(chalk.gray(' ' + t('db.piiDescription')));
|
|
942
949
|
const piiDbLocation = await select({
|
|
943
|
-
message: '
|
|
950
|
+
message: t('db.piiRegion'),
|
|
944
951
|
choices: locationChoices,
|
|
945
952
|
default: 'auto',
|
|
946
953
|
});
|
|
@@ -956,43 +963,43 @@ async function runQuickSetup(options) {
|
|
|
956
963
|
}
|
|
957
964
|
// Email Provider Configuration
|
|
958
965
|
console.log('');
|
|
959
|
-
console.log(chalk.blue('━━━
|
|
960
|
-
console.log(chalk.gray('
|
|
966
|
+
console.log(chalk.blue('━━━ ' + t('email.title') + ' ━━━'));
|
|
967
|
+
console.log(chalk.gray(t('email.description')));
|
|
961
968
|
console.log('');
|
|
962
969
|
const configureEmail = await confirm({
|
|
963
|
-
message: '
|
|
970
|
+
message: t('email.prompt'),
|
|
964
971
|
default: false,
|
|
965
972
|
});
|
|
966
973
|
let emailConfig = { provider: 'none' };
|
|
967
974
|
if (configureEmail) {
|
|
968
975
|
console.log('');
|
|
969
|
-
console.log(chalk.gray('
|
|
970
|
-
console.log(chalk.gray('
|
|
971
|
-
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')));
|
|
972
979
|
console.log('');
|
|
973
980
|
const resendApiKey = await password({
|
|
974
|
-
message: '
|
|
981
|
+
message: t('email.apiKeyPrompt'),
|
|
975
982
|
mask: '*',
|
|
976
983
|
validate: (value) => {
|
|
977
984
|
if (!value.trim())
|
|
978
|
-
return '
|
|
985
|
+
return t('email.apiKeyRequired');
|
|
979
986
|
if (!value.startsWith('re_')) {
|
|
980
|
-
return '
|
|
987
|
+
return t('email.apiKeyWarning');
|
|
981
988
|
}
|
|
982
989
|
return true;
|
|
983
990
|
},
|
|
984
991
|
});
|
|
985
992
|
const fromAddress = await input({
|
|
986
|
-
message: '
|
|
993
|
+
message: t('email.fromAddressPrompt'),
|
|
987
994
|
default: 'noreply@yourdomain.com',
|
|
988
995
|
validate: (value) => {
|
|
989
996
|
if (!value.includes('@'))
|
|
990
|
-
return '
|
|
997
|
+
return t('email.fromAddressValidation');
|
|
991
998
|
return true;
|
|
992
999
|
},
|
|
993
1000
|
});
|
|
994
1001
|
const fromName = await input({
|
|
995
|
-
message: '
|
|
1002
|
+
message: t('email.fromNamePrompt'),
|
|
996
1003
|
default: 'Authrim',
|
|
997
1004
|
});
|
|
998
1005
|
emailConfig = {
|
|
@@ -1002,8 +1009,8 @@ async function runQuickSetup(options) {
|
|
|
1002
1009
|
apiKey: resendApiKey,
|
|
1003
1010
|
};
|
|
1004
1011
|
console.log('');
|
|
1005
|
-
console.log(chalk.yellow('⚠️
|
|
1006
|
-
console.log(chalk.gray('
|
|
1012
|
+
console.log(chalk.yellow('⚠️ ' + t('email.domainVerificationRequired')));
|
|
1013
|
+
console.log(chalk.gray(' ' + t('email.seeDocumentation')));
|
|
1007
1014
|
}
|
|
1008
1015
|
// Create configuration
|
|
1009
1016
|
const config = createDefaultConfig(envPrefix);
|
|
@@ -1093,94 +1100,94 @@ async function runQuickSetup(options) {
|
|
|
1093
1100
|
async function runNormalSetup(options) {
|
|
1094
1101
|
console.log('');
|
|
1095
1102
|
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
1096
|
-
console.log(chalk.bold('
|
|
1103
|
+
console.log(chalk.bold(t('custom.title')));
|
|
1097
1104
|
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
1098
1105
|
console.log('');
|
|
1099
1106
|
// Step 1: Environment prefix
|
|
1100
1107
|
const envPrefix = await input({
|
|
1101
|
-
message: '
|
|
1108
|
+
message: t('env.prompt'),
|
|
1102
1109
|
default: options.env || 'prod',
|
|
1103
1110
|
validate: (value) => {
|
|
1104
1111
|
if (!/^[a-z][a-z0-9-]*$/.test(value)) {
|
|
1105
|
-
return '
|
|
1112
|
+
return t('env.customValidation');
|
|
1106
1113
|
}
|
|
1107
1114
|
return true;
|
|
1108
1115
|
},
|
|
1109
1116
|
});
|
|
1110
1117
|
// Check if environment already exists
|
|
1111
|
-
const checkSpinner = ora('
|
|
1118
|
+
const checkSpinner = ora(t('env.checking')).start();
|
|
1112
1119
|
try {
|
|
1113
1120
|
const existingEnvs = await detectEnvironments();
|
|
1114
1121
|
const existingEnv = existingEnvs.find((e) => e.env === envPrefix);
|
|
1115
1122
|
if (existingEnv) {
|
|
1116
|
-
checkSpinner.fail(
|
|
1123
|
+
checkSpinner.fail(t('env.alreadyExists', { env: envPrefix }));
|
|
1117
1124
|
console.log('');
|
|
1118
|
-
console.log(chalk.yellow('
|
|
1119
|
-
console.log(`
|
|
1120
|
-
console.log(`
|
|
1121
|
-
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) })}`);
|
|
1122
1129
|
console.log('');
|
|
1123
|
-
console.log(chalk.yellow('
|
|
1130
|
+
console.log(chalk.yellow(' ' + t('env.chooseAnother')));
|
|
1124
1131
|
return;
|
|
1125
1132
|
}
|
|
1126
|
-
checkSpinner.succeed('
|
|
1133
|
+
checkSpinner.succeed(t('env.available'));
|
|
1127
1134
|
}
|
|
1128
1135
|
catch {
|
|
1129
|
-
checkSpinner.warn(
|
|
1136
|
+
checkSpinner.warn(t('env.checkFailed'));
|
|
1130
1137
|
}
|
|
1131
1138
|
// Step 2: Cloudflare API Token
|
|
1132
1139
|
const cfApiToken = await password({
|
|
1133
|
-
message: '
|
|
1140
|
+
message: t('cf.apiTokenPrompt'),
|
|
1134
1141
|
mask: '*',
|
|
1135
1142
|
validate: (value) => {
|
|
1136
1143
|
if (!value || value.length < 10) {
|
|
1137
|
-
return '
|
|
1144
|
+
return t('cf.apiTokenValidation');
|
|
1138
1145
|
}
|
|
1139
1146
|
return true;
|
|
1140
1147
|
},
|
|
1141
1148
|
});
|
|
1142
1149
|
// Step 3: Profile selection
|
|
1143
1150
|
const profile = await select({
|
|
1144
|
-
message: '
|
|
1151
|
+
message: t('profile.prompt'),
|
|
1145
1152
|
choices: [
|
|
1146
1153
|
{
|
|
1147
1154
|
value: 'basic-op',
|
|
1148
|
-
name: '
|
|
1149
|
-
description: '
|
|
1155
|
+
name: t('profile.basicOp'),
|
|
1156
|
+
description: t('profile.basicOpDesc'),
|
|
1150
1157
|
},
|
|
1151
1158
|
{
|
|
1152
1159
|
value: 'fapi-rw',
|
|
1153
|
-
name: '
|
|
1154
|
-
description: '
|
|
1160
|
+
name: t('profile.fapiRw'),
|
|
1161
|
+
description: t('profile.fapiRwDesc'),
|
|
1155
1162
|
},
|
|
1156
1163
|
{
|
|
1157
1164
|
value: 'fapi2-security',
|
|
1158
|
-
name: '
|
|
1159
|
-
description: '
|
|
1165
|
+
name: t('profile.fapi2Security'),
|
|
1166
|
+
description: t('profile.fapi2SecurityDesc'),
|
|
1160
1167
|
},
|
|
1161
1168
|
],
|
|
1162
1169
|
default: 'basic-op',
|
|
1163
1170
|
});
|
|
1164
1171
|
// Step 4: Infrastructure overview (Workers are auto-generated from env)
|
|
1165
1172
|
console.log('');
|
|
1166
|
-
console.log(chalk.blue('━━━
|
|
1173
|
+
console.log(chalk.blue('━━━ ' + t('infra.title') + ' ━━━'));
|
|
1167
1174
|
console.log('');
|
|
1168
|
-
console.log(chalk.gray('
|
|
1169
|
-
console.log(`
|
|
1170
|
-
console.log(`
|
|
1171
|
-
console.log(`
|
|
1172
|
-
console.log(`
|
|
1173
|
-
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')));
|
|
1174
1181
|
console.log('');
|
|
1175
|
-
console.log(chalk.gray('
|
|
1176
|
-
console.log(`
|
|
1177
|
-
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'))}`);
|
|
1178
1185
|
console.log('');
|
|
1179
1186
|
// Step 5: Tenant configuration
|
|
1180
|
-
console.log(chalk.blue('━━━
|
|
1187
|
+
console.log(chalk.blue('━━━ ' + t('tenant.title') + ' ━━━'));
|
|
1181
1188
|
console.log('');
|
|
1182
1189
|
const multiTenant = await confirm({
|
|
1183
|
-
message: '
|
|
1190
|
+
message: t('tenant.multiTenantPrompt'),
|
|
1184
1191
|
default: false,
|
|
1185
1192
|
});
|
|
1186
1193
|
let tenantName = 'default';
|
|
@@ -1193,59 +1200,59 @@ async function runNormalSetup(options) {
|
|
|
1193
1200
|
if (multiTenant) {
|
|
1194
1201
|
// Multi-tenant mode: base domain is required, becomes the issuer base
|
|
1195
1202
|
console.log('');
|
|
1196
|
-
console.log(chalk.blue('━━━
|
|
1203
|
+
console.log(chalk.blue('━━━ ' + t('tenant.multiTenantTitle') + ' ━━━'));
|
|
1197
1204
|
console.log('');
|
|
1198
|
-
console.log(chalk.gray('
|
|
1199
|
-
console.log(chalk.gray(' •
|
|
1200
|
-
console.log(chalk.gray(' •
|
|
1201
|
-
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')));
|
|
1202
1209
|
console.log('');
|
|
1203
1210
|
baseDomain = await input({
|
|
1204
|
-
message: '
|
|
1211
|
+
message: t('tenant.baseDomainPrompt'),
|
|
1205
1212
|
validate: (value) => {
|
|
1206
1213
|
if (!value)
|
|
1207
|
-
return '
|
|
1214
|
+
return t('tenant.baseDomainRequired');
|
|
1208
1215
|
if (!/^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(value)) {
|
|
1209
|
-
return '
|
|
1216
|
+
return t('tenant.baseDomainValidation');
|
|
1210
1217
|
}
|
|
1211
1218
|
return true;
|
|
1212
1219
|
},
|
|
1213
1220
|
});
|
|
1214
1221
|
console.log('');
|
|
1215
|
-
console.log(chalk.green(' ✓
|
|
1216
|
-
console.log(chalk.gray('
|
|
1222
|
+
console.log(chalk.green(' ✓ ' + t('tenant.issuerFormat', { domain: baseDomain })));
|
|
1223
|
+
console.log(chalk.gray(' ' + t('tenant.issuerExample', { domain: baseDomain })));
|
|
1217
1224
|
console.log('');
|
|
1218
1225
|
// API domain in multi-tenant is the base domain (or custom apex)
|
|
1219
1226
|
apiDomain = baseDomain;
|
|
1220
1227
|
tenantName = await input({
|
|
1221
|
-
message: '
|
|
1228
|
+
message: t('tenant.defaultTenantPrompt'),
|
|
1222
1229
|
default: 'default',
|
|
1223
1230
|
validate: (value) => {
|
|
1224
1231
|
if (!/^[a-z][a-z0-9-]*$/.test(value)) {
|
|
1225
|
-
return '
|
|
1232
|
+
return t('tenant.defaultTenantValidation');
|
|
1226
1233
|
}
|
|
1227
1234
|
return true;
|
|
1228
1235
|
},
|
|
1229
1236
|
});
|
|
1230
1237
|
tenantDisplayName = await input({
|
|
1231
|
-
message: '
|
|
1238
|
+
message: t('tenant.displayNamePrompt'),
|
|
1232
1239
|
default: 'Default Tenant',
|
|
1233
1240
|
});
|
|
1234
1241
|
// UI domains for multi-tenant
|
|
1235
1242
|
console.log('');
|
|
1236
|
-
console.log(chalk.blue('━━━
|
|
1243
|
+
console.log(chalk.blue('━━━ ' + t('tenant.uiDomainTitle') + ' ━━━'));
|
|
1237
1244
|
console.log('');
|
|
1238
1245
|
const useCustomUiDomain = await confirm({
|
|
1239
|
-
message: '
|
|
1246
|
+
message: t('tenant.customUiDomainPrompt'),
|
|
1240
1247
|
default: false,
|
|
1241
1248
|
});
|
|
1242
1249
|
if (useCustomUiDomain) {
|
|
1243
1250
|
loginUiDomain = await input({
|
|
1244
|
-
message: '
|
|
1251
|
+
message: t('tenant.loginUiDomain'),
|
|
1245
1252
|
default: '',
|
|
1246
1253
|
});
|
|
1247
1254
|
adminUiDomain = await input({
|
|
1248
|
-
message: '
|
|
1255
|
+
message: t('tenant.adminUiDomain'),
|
|
1249
1256
|
default: '',
|
|
1250
1257
|
});
|
|
1251
1258
|
}
|
|
@@ -1253,86 +1260,86 @@ async function runNormalSetup(options) {
|
|
|
1253
1260
|
else {
|
|
1254
1261
|
// Single-tenant mode
|
|
1255
1262
|
console.log('');
|
|
1256
|
-
console.log(chalk.blue('━━━
|
|
1263
|
+
console.log(chalk.blue('━━━ ' + t('tenant.singleTenantTitle') + ' ━━━'));
|
|
1257
1264
|
console.log('');
|
|
1258
|
-
console.log(chalk.gray('
|
|
1259
|
-
console.log(chalk.gray(' •
|
|
1260
|
-
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')));
|
|
1261
1268
|
console.log('');
|
|
1262
1269
|
tenantDisplayName = await input({
|
|
1263
|
-
message: '
|
|
1270
|
+
message: t('tenant.organizationName'),
|
|
1264
1271
|
default: 'Default Tenant',
|
|
1265
1272
|
});
|
|
1266
1273
|
const useCustomDomain = await confirm({
|
|
1267
|
-
message: '
|
|
1274
|
+
message: t('domain.prompt'),
|
|
1268
1275
|
default: false,
|
|
1269
1276
|
});
|
|
1270
1277
|
if (useCustomDomain) {
|
|
1271
1278
|
console.log('');
|
|
1272
|
-
console.log(chalk.gray('
|
|
1279
|
+
console.log(chalk.gray(' ' + t('domain.enterDomains')));
|
|
1273
1280
|
console.log('');
|
|
1274
1281
|
apiDomain = await input({
|
|
1275
|
-
message: '
|
|
1282
|
+
message: t('domain.apiDomain'),
|
|
1276
1283
|
validate: (value) => {
|
|
1277
1284
|
if (!value)
|
|
1278
1285
|
return true;
|
|
1279
1286
|
if (!/^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(value)) {
|
|
1280
|
-
return '
|
|
1287
|
+
return t('domain.customValidation');
|
|
1281
1288
|
}
|
|
1282
1289
|
return true;
|
|
1283
1290
|
},
|
|
1284
1291
|
});
|
|
1285
1292
|
loginUiDomain = await input({
|
|
1286
|
-
message: '
|
|
1293
|
+
message: t('domain.loginUiDomain'),
|
|
1287
1294
|
default: '',
|
|
1288
1295
|
});
|
|
1289
1296
|
adminUiDomain = await input({
|
|
1290
|
-
message: '
|
|
1297
|
+
message: t('domain.adminUiDomain'),
|
|
1291
1298
|
default: '',
|
|
1292
1299
|
});
|
|
1293
1300
|
}
|
|
1294
1301
|
if (apiDomain) {
|
|
1295
1302
|
console.log('');
|
|
1296
|
-
console.log(chalk.green(' ✓
|
|
1303
|
+
console.log(chalk.green(' ✓ ' + t('domain.issuerUrl', { url: 'https://' + apiDomain })));
|
|
1297
1304
|
}
|
|
1298
1305
|
else {
|
|
1299
1306
|
console.log('');
|
|
1300
|
-
console.log(chalk.green(' ✓
|
|
1301
|
-
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')));
|
|
1302
1309
|
}
|
|
1303
1310
|
}
|
|
1304
1311
|
// Step 5: Optional components
|
|
1305
1312
|
console.log('');
|
|
1306
|
-
console.log(chalk.blue('━━━
|
|
1307
|
-
console.log(chalk.gray('
|
|
1313
|
+
console.log(chalk.blue('━━━ ' + t('components.title') + ' ━━━'));
|
|
1314
|
+
console.log(chalk.gray(' ' + t('components.note')));
|
|
1308
1315
|
console.log('');
|
|
1309
1316
|
const enableSaml = await confirm({
|
|
1310
|
-
message: '
|
|
1317
|
+
message: t('components.samlPrompt'),
|
|
1311
1318
|
default: false,
|
|
1312
1319
|
});
|
|
1313
1320
|
const enableVc = await confirm({
|
|
1314
|
-
message: '
|
|
1321
|
+
message: t('components.vcPrompt'),
|
|
1315
1322
|
default: false,
|
|
1316
1323
|
});
|
|
1317
1324
|
// Step 6: Feature flags
|
|
1318
1325
|
console.log('');
|
|
1319
|
-
console.log(chalk.blue('━━━
|
|
1326
|
+
console.log(chalk.blue('━━━ ' + t('features.title') + ' ━━━'));
|
|
1320
1327
|
console.log('');
|
|
1321
1328
|
const enableQueue = await confirm({
|
|
1322
|
-
message: '
|
|
1329
|
+
message: t('features.queuePrompt'),
|
|
1323
1330
|
default: false,
|
|
1324
1331
|
});
|
|
1325
1332
|
const enableR2 = await confirm({
|
|
1326
|
-
message: '
|
|
1333
|
+
message: t('features.r2Prompt'),
|
|
1327
1334
|
default: false,
|
|
1328
1335
|
});
|
|
1329
1336
|
const emailProviderChoice = await select({
|
|
1330
|
-
message: '
|
|
1337
|
+
message: t('email.title'),
|
|
1331
1338
|
choices: [
|
|
1332
|
-
{ value: 'none', name: '
|
|
1333
|
-
{ value: 'resend', name: '
|
|
1339
|
+
{ value: 'none', name: t('email.skipOption') },
|
|
1340
|
+
{ value: 'resend', name: t('email.resendOption') },
|
|
1334
1341
|
{ value: 'sendgrid', name: 'SendGrid (coming soon)', disabled: true },
|
|
1335
|
-
{ value: 'ses', name: '
|
|
1342
|
+
{ value: 'ses', name: t('email.sesOption') + ' (coming soon)', disabled: true },
|
|
1336
1343
|
],
|
|
1337
1344
|
default: 'none',
|
|
1338
1345
|
});
|
|
@@ -1340,33 +1347,33 @@ async function runNormalSetup(options) {
|
|
|
1340
1347
|
let emailConfigNormal = { provider: 'none' };
|
|
1341
1348
|
if (emailProviderChoice === 'resend') {
|
|
1342
1349
|
console.log('');
|
|
1343
|
-
console.log(chalk.blue('━━━
|
|
1344
|
-
console.log(chalk.gray('
|
|
1345
|
-
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')));
|
|
1346
1353
|
console.log('');
|
|
1347
1354
|
const resendApiKey = await password({
|
|
1348
|
-
message: '
|
|
1355
|
+
message: t('email.apiKeyPrompt'),
|
|
1349
1356
|
mask: '*',
|
|
1350
1357
|
validate: (value) => {
|
|
1351
1358
|
if (!value.trim())
|
|
1352
|
-
return '
|
|
1359
|
+
return t('email.apiKeyRequired');
|
|
1353
1360
|
if (!value.startsWith('re_')) {
|
|
1354
|
-
return '
|
|
1361
|
+
return t('email.apiKeyWarning');
|
|
1355
1362
|
}
|
|
1356
1363
|
return true;
|
|
1357
1364
|
},
|
|
1358
1365
|
});
|
|
1359
1366
|
const fromAddress = await input({
|
|
1360
|
-
message: '
|
|
1367
|
+
message: t('email.fromAddressPrompt'),
|
|
1361
1368
|
default: 'noreply@yourdomain.com',
|
|
1362
1369
|
validate: (value) => {
|
|
1363
1370
|
if (!value.includes('@'))
|
|
1364
|
-
return '
|
|
1371
|
+
return t('email.fromAddressValidation');
|
|
1365
1372
|
return true;
|
|
1366
1373
|
},
|
|
1367
1374
|
});
|
|
1368
1375
|
const fromName = await input({
|
|
1369
|
-
message: '
|
|
1376
|
+
message: t('email.fromNamePrompt'),
|
|
1370
1377
|
default: 'Authrim',
|
|
1371
1378
|
});
|
|
1372
1379
|
emailConfigNormal = {
|
|
@@ -1376,12 +1383,12 @@ async function runNormalSetup(options) {
|
|
|
1376
1383
|
apiKey: resendApiKey,
|
|
1377
1384
|
};
|
|
1378
1385
|
console.log('');
|
|
1379
|
-
console.log(chalk.yellow('⚠️
|
|
1380
|
-
console.log(chalk.gray('
|
|
1386
|
+
console.log(chalk.yellow('⚠️ ' + t('email.domainVerificationRequired')));
|
|
1387
|
+
console.log(chalk.gray(' ' + t('email.seeDocumentation')));
|
|
1381
1388
|
}
|
|
1382
1389
|
// Step 7: Advanced OIDC settings
|
|
1383
1390
|
const configureOidc = await confirm({
|
|
1384
|
-
message: '
|
|
1391
|
+
message: t('oidc.configurePrompt'),
|
|
1385
1392
|
default: false,
|
|
1386
1393
|
});
|
|
1387
1394
|
let accessTokenTtl = 3600; // 1 hour
|
|
@@ -1390,76 +1397,76 @@ async function runNormalSetup(options) {
|
|
|
1390
1397
|
let pkceRequired = true;
|
|
1391
1398
|
if (configureOidc) {
|
|
1392
1399
|
console.log('');
|
|
1393
|
-
console.log(chalk.blue('━━━
|
|
1400
|
+
console.log(chalk.blue('━━━ ' + t('oidc.title') + ' ━━━'));
|
|
1394
1401
|
console.log('');
|
|
1395
1402
|
const accessTokenTtlStr = await input({
|
|
1396
|
-
message: '
|
|
1403
|
+
message: t('oidc.accessTokenTtl'),
|
|
1397
1404
|
default: '3600',
|
|
1398
1405
|
validate: (value) => {
|
|
1399
1406
|
const num = parseInt(value, 10);
|
|
1400
1407
|
if (isNaN(num) || num <= 0)
|
|
1401
|
-
return '
|
|
1408
|
+
return t('oidc.positiveInteger');
|
|
1402
1409
|
return true;
|
|
1403
1410
|
},
|
|
1404
1411
|
});
|
|
1405
1412
|
accessTokenTtl = parseInt(accessTokenTtlStr, 10);
|
|
1406
1413
|
const refreshTokenTtlStr = await input({
|
|
1407
|
-
message: '
|
|
1414
|
+
message: t('oidc.refreshTokenTtl'),
|
|
1408
1415
|
default: '604800',
|
|
1409
1416
|
validate: (value) => {
|
|
1410
1417
|
const num = parseInt(value, 10);
|
|
1411
1418
|
if (isNaN(num) || num <= 0)
|
|
1412
|
-
return '
|
|
1419
|
+
return t('oidc.positiveInteger');
|
|
1413
1420
|
return true;
|
|
1414
1421
|
},
|
|
1415
1422
|
});
|
|
1416
1423
|
refreshTokenTtl = parseInt(refreshTokenTtlStr, 10);
|
|
1417
1424
|
const authCodeTtlStr = await input({
|
|
1418
|
-
message: '
|
|
1425
|
+
message: t('oidc.authCodeTtl'),
|
|
1419
1426
|
default: '600',
|
|
1420
1427
|
validate: (value) => {
|
|
1421
1428
|
const num = parseInt(value, 10);
|
|
1422
1429
|
if (isNaN(num) || num <= 0)
|
|
1423
|
-
return '
|
|
1430
|
+
return t('oidc.positiveInteger');
|
|
1424
1431
|
return true;
|
|
1425
1432
|
},
|
|
1426
1433
|
});
|
|
1427
1434
|
authCodeTtl = parseInt(authCodeTtlStr, 10);
|
|
1428
1435
|
pkceRequired = await confirm({
|
|
1429
|
-
message: '
|
|
1436
|
+
message: t('oidc.pkceRequired'),
|
|
1430
1437
|
default: true,
|
|
1431
1438
|
});
|
|
1432
1439
|
}
|
|
1433
1440
|
// Step 8: Sharding settings
|
|
1434
1441
|
const configureSharding = await confirm({
|
|
1435
|
-
message: '
|
|
1442
|
+
message: t('sharding.configurePrompt'),
|
|
1436
1443
|
default: false,
|
|
1437
1444
|
});
|
|
1438
1445
|
let authCodeShards = 64;
|
|
1439
1446
|
let refreshTokenShards = 8;
|
|
1440
1447
|
if (configureSharding) {
|
|
1441
1448
|
console.log('');
|
|
1442
|
-
console.log(chalk.blue('━━━
|
|
1443
|
-
console.log(chalk.gray('
|
|
1449
|
+
console.log(chalk.blue('━━━ ' + t('sharding.title') + ' ━━━'));
|
|
1450
|
+
console.log(chalk.gray(' ' + t('sharding.note')));
|
|
1444
1451
|
console.log('');
|
|
1445
1452
|
const authCodeShardsStr = await input({
|
|
1446
|
-
message: '
|
|
1453
|
+
message: t('sharding.authCodeShards'),
|
|
1447
1454
|
default: '64',
|
|
1448
1455
|
validate: (value) => {
|
|
1449
1456
|
const num = parseInt(value, 10);
|
|
1450
1457
|
if (isNaN(num) || num <= 0)
|
|
1451
|
-
return '
|
|
1458
|
+
return t('oidc.positiveInteger');
|
|
1452
1459
|
return true;
|
|
1453
1460
|
},
|
|
1454
1461
|
});
|
|
1455
1462
|
authCodeShards = parseInt(authCodeShardsStr, 10);
|
|
1456
1463
|
const refreshTokenShardsStr = await input({
|
|
1457
|
-
message: '
|
|
1464
|
+
message: t('sharding.refreshTokenShards'),
|
|
1458
1465
|
default: '8',
|
|
1459
1466
|
validate: (value) => {
|
|
1460
1467
|
const num = parseInt(value, 10);
|
|
1461
1468
|
if (isNaN(num) || num <= 0)
|
|
1462
|
-
return '
|
|
1469
|
+
return t('oidc.positiveInteger');
|
|
1463
1470
|
return true;
|
|
1464
1471
|
},
|
|
1465
1472
|
});
|
|
@@ -1467,32 +1474,36 @@ async function runNormalSetup(options) {
|
|
|
1467
1474
|
}
|
|
1468
1475
|
// Step 9: Database Configuration
|
|
1469
1476
|
console.log('');
|
|
1470
|
-
console.log(chalk.blue('━━━
|
|
1471
|
-
console.log(chalk.yellow('⚠️
|
|
1477
|
+
console.log(chalk.blue('━━━ ' + t('db.title') + ' ━━━'));
|
|
1478
|
+
console.log(chalk.yellow('⚠️ ' + t('db.regionWarning')));
|
|
1472
1479
|
console.log('');
|
|
1473
1480
|
const dbLocationChoices = [
|
|
1474
|
-
{ name: '
|
|
1475
|
-
{ name: '──
|
|
1476
|
-
{ name: '
|
|
1477
|
-
{ name: '
|
|
1478
|
-
{ name: '
|
|
1479
|
-
{ name: '
|
|
1480
|
-
{ name: '
|
|
1481
|
-
{ name: '
|
|
1482
|
-
{
|
|
1483
|
-
|
|
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' },
|
|
1484
1495
|
];
|
|
1485
|
-
console.log(chalk.gray('
|
|
1496
|
+
console.log(chalk.gray(' ' + t('db.coreDescription')));
|
|
1486
1497
|
const coreDbLocation = await select({
|
|
1487
|
-
message: '
|
|
1498
|
+
message: t('db.coreRegion'),
|
|
1488
1499
|
choices: dbLocationChoices,
|
|
1489
1500
|
default: 'auto',
|
|
1490
1501
|
});
|
|
1491
1502
|
console.log('');
|
|
1492
|
-
console.log(chalk.gray('
|
|
1493
|
-
console.log(chalk.gray('
|
|
1503
|
+
console.log(chalk.gray(' ' + t('db.piiDescription')));
|
|
1504
|
+
console.log(chalk.gray(' ' + t('db.piiNote')));
|
|
1494
1505
|
const piiDbLocation = await select({
|
|
1495
|
-
message: '
|
|
1506
|
+
message: t('db.piiRegion'),
|
|
1496
1507
|
choices: dbLocationChoices,
|
|
1497
1508
|
default: 'auto',
|
|
1498
1509
|
});
|