@authrim/setup 0.1.49 → 0.1.51
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/init.js +274 -7
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/core/cloudflare.d.ts +16 -4
- package/dist/core/cloudflare.d.ts.map +1 -1
- package/dist/core/cloudflare.js +45 -4
- package/dist/core/cloudflare.js.map +1 -1
- package/dist/core/config.d.ts +225 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +42 -0
- package/dist/core/config.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +101 -4
- package/dist/web/api.js.map +1 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +590 -28
- package/dist/web/ui.js.map +1 -1
- package/package.json +1 -1
|
@@ -719,8 +719,112 @@ async function runQuickSetup(options) {
|
|
|
719
719
|
default: '',
|
|
720
720
|
});
|
|
721
721
|
}
|
|
722
|
+
// Database Configuration
|
|
723
|
+
console.log('');
|
|
724
|
+
console.log(chalk.blue('━━━ Database Configuration ━━━'));
|
|
725
|
+
console.log(chalk.yellow('⚠️ Database region cannot be changed after creation.'));
|
|
726
|
+
console.log('');
|
|
727
|
+
const locationChoices = [
|
|
728
|
+
{ name: 'Automatic (nearest to you)', value: 'auto' },
|
|
729
|
+
{ name: '── Location Hints ──', value: '__separator1__', disabled: true },
|
|
730
|
+
{ name: 'North America (West)', value: 'wnam' },
|
|
731
|
+
{ name: 'North America (East)', value: 'enam' },
|
|
732
|
+
{ name: 'Europe (West)', value: 'weur' },
|
|
733
|
+
{ name: 'Europe (East)', value: 'eeur' },
|
|
734
|
+
{ name: 'Asia Pacific', value: 'apac' },
|
|
735
|
+
{ name: 'Oceania', value: 'oc' },
|
|
736
|
+
{ name: '── Jurisdiction (Compliance) ──', value: '__separator2__', disabled: true },
|
|
737
|
+
{ name: 'EU Jurisdiction (GDPR compliance)', value: 'eu' },
|
|
738
|
+
];
|
|
739
|
+
console.log(chalk.gray(' Core DB: Stores OAuth clients, tokens, sessions, audit logs'));
|
|
740
|
+
const coreDbLocation = await select({
|
|
741
|
+
message: 'Core Database region',
|
|
742
|
+
choices: locationChoices,
|
|
743
|
+
default: 'auto',
|
|
744
|
+
});
|
|
745
|
+
console.log('');
|
|
746
|
+
console.log(chalk.gray(' PII DB: Stores user profiles, credentials, personal data'));
|
|
747
|
+
const piiDbLocation = await select({
|
|
748
|
+
message: 'PII Database region',
|
|
749
|
+
choices: locationChoices,
|
|
750
|
+
default: 'auto',
|
|
751
|
+
});
|
|
752
|
+
// Parse location vs jurisdiction
|
|
753
|
+
function parseDbLocation(value) {
|
|
754
|
+
if (value === 'eu') {
|
|
755
|
+
return { location: 'auto', jurisdiction: 'eu' };
|
|
756
|
+
}
|
|
757
|
+
return {
|
|
758
|
+
location: value,
|
|
759
|
+
jurisdiction: 'none',
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
// Email Provider Configuration
|
|
763
|
+
console.log('');
|
|
764
|
+
console.log(chalk.blue('━━━ Email Provider ━━━'));
|
|
765
|
+
console.log(chalk.gray('Configure email sending for magic links and verification codes.'));
|
|
766
|
+
console.log('');
|
|
767
|
+
const configureEmail = await confirm({
|
|
768
|
+
message: 'Configure email provider now?',
|
|
769
|
+
default: false,
|
|
770
|
+
});
|
|
771
|
+
let emailConfig = { provider: 'none' };
|
|
772
|
+
if (configureEmail) {
|
|
773
|
+
console.log('');
|
|
774
|
+
console.log(chalk.gray('Resend is the supported email provider.'));
|
|
775
|
+
console.log(chalk.gray('Get your API key at: https://resend.com/api-keys'));
|
|
776
|
+
console.log(chalk.gray('Set up domain at: https://resend.com/domains'));
|
|
777
|
+
console.log('');
|
|
778
|
+
const resendApiKey = await password({
|
|
779
|
+
message: 'Resend API key',
|
|
780
|
+
mask: '*',
|
|
781
|
+
validate: (value) => {
|
|
782
|
+
if (!value.trim())
|
|
783
|
+
return 'API key is required';
|
|
784
|
+
if (!value.startsWith('re_')) {
|
|
785
|
+
return 'Warning: Resend API keys typically start with "re_"';
|
|
786
|
+
}
|
|
787
|
+
return true;
|
|
788
|
+
},
|
|
789
|
+
});
|
|
790
|
+
const fromAddress = await input({
|
|
791
|
+
message: 'From email address',
|
|
792
|
+
default: 'noreply@yourdomain.com',
|
|
793
|
+
validate: (value) => {
|
|
794
|
+
if (!value.includes('@'))
|
|
795
|
+
return 'Please enter a valid email address';
|
|
796
|
+
return true;
|
|
797
|
+
},
|
|
798
|
+
});
|
|
799
|
+
const fromName = await input({
|
|
800
|
+
message: 'From display name (optional)',
|
|
801
|
+
default: 'Authrim',
|
|
802
|
+
});
|
|
803
|
+
emailConfig = {
|
|
804
|
+
provider: 'resend',
|
|
805
|
+
fromAddress,
|
|
806
|
+
fromName: fromName || undefined,
|
|
807
|
+
apiKey: resendApiKey,
|
|
808
|
+
};
|
|
809
|
+
console.log('');
|
|
810
|
+
console.log(chalk.yellow('⚠️ Domain verification required for sending from your own domain.'));
|
|
811
|
+
console.log(chalk.gray(' See: https://resend.com/docs/dashboard/domains/introduction'));
|
|
812
|
+
}
|
|
722
813
|
// Create configuration
|
|
723
814
|
const config = createDefaultConfig(envPrefix);
|
|
815
|
+
config.database = {
|
|
816
|
+
core: parseDbLocation(coreDbLocation),
|
|
817
|
+
pii: parseDbLocation(piiDbLocation),
|
|
818
|
+
};
|
|
819
|
+
config.features = {
|
|
820
|
+
...config.features,
|
|
821
|
+
email: {
|
|
822
|
+
provider: emailConfig.provider,
|
|
823
|
+
fromAddress: emailConfig.fromAddress,
|
|
824
|
+
fromName: emailConfig.fromName,
|
|
825
|
+
configured: emailConfig.provider === 'resend',
|
|
826
|
+
},
|
|
827
|
+
};
|
|
724
828
|
config.urls = {
|
|
725
829
|
api: {
|
|
726
830
|
custom: apiDomain || null,
|
|
@@ -750,6 +854,18 @@ async function runQuickSetup(options) {
|
|
|
750
854
|
console.log(` Login UI: ${chalk.cyan(config.urls.loginUi.custom || config.urls.loginUi.auto)}`);
|
|
751
855
|
console.log(` Admin UI: ${chalk.cyan(config.urls.adminUi.custom || config.urls.adminUi.auto)}`);
|
|
752
856
|
console.log('');
|
|
857
|
+
console.log(chalk.bold('Email:'));
|
|
858
|
+
if (emailConfig.provider === 'resend') {
|
|
859
|
+
console.log(` Provider: ${chalk.cyan('Resend')}`);
|
|
860
|
+
console.log(` From Address: ${chalk.cyan(emailConfig.fromAddress)}`);
|
|
861
|
+
if (emailConfig.fromName) {
|
|
862
|
+
console.log(` From Name: ${chalk.cyan(emailConfig.fromName)}`);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
else {
|
|
866
|
+
console.log(` Provider: ${chalk.gray('Not configured (configure later)')}`);
|
|
867
|
+
}
|
|
868
|
+
console.log('');
|
|
753
869
|
const proceed = await confirm({
|
|
754
870
|
message: 'Start setup with this configuration?',
|
|
755
871
|
default: true,
|
|
@@ -758,6 +874,19 @@ async function runQuickSetup(options) {
|
|
|
758
874
|
console.log(chalk.yellow('Setup cancelled.'));
|
|
759
875
|
return;
|
|
760
876
|
}
|
|
877
|
+
// Save email secrets if configured
|
|
878
|
+
if (emailConfig.provider === 'resend' && emailConfig.apiKey) {
|
|
879
|
+
const keysDir = `.keys/${envPrefix}`;
|
|
880
|
+
await import('node:fs/promises').then(async (fs) => {
|
|
881
|
+
await fs.mkdir(keysDir, { recursive: true });
|
|
882
|
+
await fs.writeFile(`${keysDir}/resend_api_key.txt`, emailConfig.apiKey.trim());
|
|
883
|
+
await fs.writeFile(`${keysDir}/email_from.txt`, emailConfig.fromAddress.trim());
|
|
884
|
+
if (emailConfig.fromName) {
|
|
885
|
+
await fs.writeFile(`${keysDir}/email_from_name.txt`, emailConfig.fromName.trim());
|
|
886
|
+
}
|
|
887
|
+
});
|
|
888
|
+
console.log(chalk.gray(`📧 Email secrets saved to ${keysDir}/`));
|
|
889
|
+
}
|
|
761
890
|
// Run setup
|
|
762
891
|
await executeSetup(config, cfApiToken, options.keep);
|
|
763
892
|
}
|
|
@@ -1000,16 +1129,59 @@ async function runNormalSetup(options) {
|
|
|
1000
1129
|
message: 'Enable Cloudflare R2? (for avatars)',
|
|
1001
1130
|
default: false,
|
|
1002
1131
|
});
|
|
1003
|
-
const
|
|
1132
|
+
const emailProviderChoice = await select({
|
|
1004
1133
|
message: 'Select email provider',
|
|
1005
1134
|
choices: [
|
|
1006
|
-
{ value: 'none', name: 'None (
|
|
1135
|
+
{ value: 'none', name: 'None (configure later)' },
|
|
1007
1136
|
{ value: 'resend', name: 'Resend' },
|
|
1008
|
-
{ value: 'sendgrid', name: 'SendGrid' },
|
|
1009
|
-
{ value: 'ses', name: 'AWS SES' },
|
|
1137
|
+
{ value: 'sendgrid', name: 'SendGrid (coming soon)', disabled: true },
|
|
1138
|
+
{ value: 'ses', name: 'AWS SES (coming soon)', disabled: true },
|
|
1010
1139
|
],
|
|
1011
1140
|
default: 'none',
|
|
1012
1141
|
});
|
|
1142
|
+
// Email configuration details
|
|
1143
|
+
let emailConfigNormal = { provider: 'none' };
|
|
1144
|
+
if (emailProviderChoice === 'resend') {
|
|
1145
|
+
console.log('');
|
|
1146
|
+
console.log(chalk.blue('━━━ Resend Configuration ━━━'));
|
|
1147
|
+
console.log(chalk.gray('Get your API key at: https://resend.com/api-keys'));
|
|
1148
|
+
console.log(chalk.gray('Set up domain at: https://resend.com/domains'));
|
|
1149
|
+
console.log('');
|
|
1150
|
+
const resendApiKey = await password({
|
|
1151
|
+
message: 'Resend API key',
|
|
1152
|
+
mask: '*',
|
|
1153
|
+
validate: (value) => {
|
|
1154
|
+
if (!value.trim())
|
|
1155
|
+
return 'API key is required';
|
|
1156
|
+
if (!value.startsWith('re_')) {
|
|
1157
|
+
return 'Warning: Resend API keys typically start with "re_"';
|
|
1158
|
+
}
|
|
1159
|
+
return true;
|
|
1160
|
+
},
|
|
1161
|
+
});
|
|
1162
|
+
const fromAddress = await input({
|
|
1163
|
+
message: 'From email address',
|
|
1164
|
+
default: 'noreply@yourdomain.com',
|
|
1165
|
+
validate: (value) => {
|
|
1166
|
+
if (!value.includes('@'))
|
|
1167
|
+
return 'Please enter a valid email address';
|
|
1168
|
+
return true;
|
|
1169
|
+
},
|
|
1170
|
+
});
|
|
1171
|
+
const fromName = await input({
|
|
1172
|
+
message: 'From display name (optional)',
|
|
1173
|
+
default: 'Authrim',
|
|
1174
|
+
});
|
|
1175
|
+
emailConfigNormal = {
|
|
1176
|
+
provider: 'resend',
|
|
1177
|
+
fromAddress,
|
|
1178
|
+
fromName: fromName || undefined,
|
|
1179
|
+
apiKey: resendApiKey,
|
|
1180
|
+
};
|
|
1181
|
+
console.log('');
|
|
1182
|
+
console.log(chalk.yellow('⚠️ Domain verification required for sending from your own domain.'));
|
|
1183
|
+
console.log(chalk.gray(' See: https://resend.com/docs/dashboard/domains/introduction'));
|
|
1184
|
+
}
|
|
1013
1185
|
// Step 7: Advanced OIDC settings
|
|
1014
1186
|
const configureOidc = await confirm({
|
|
1015
1187
|
message: 'Configure OIDC settings? (token TTL, etc.)',
|
|
@@ -1096,9 +1268,54 @@ async function runNormalSetup(options) {
|
|
|
1096
1268
|
});
|
|
1097
1269
|
refreshTokenShards = parseInt(refreshTokenShardsStr, 10);
|
|
1098
1270
|
}
|
|
1271
|
+
// Step 9: Database Configuration
|
|
1272
|
+
console.log('');
|
|
1273
|
+
console.log(chalk.blue('━━━ Database Configuration ━━━'));
|
|
1274
|
+
console.log(chalk.yellow('⚠️ Database region cannot be changed after creation.'));
|
|
1275
|
+
console.log('');
|
|
1276
|
+
const dbLocationChoices = [
|
|
1277
|
+
{ name: 'Automatic (nearest to you)', value: 'auto' },
|
|
1278
|
+
{ name: '── Location Hints ──', value: '__separator1__', disabled: true },
|
|
1279
|
+
{ name: 'North America (West)', value: 'wnam' },
|
|
1280
|
+
{ name: 'North America (East)', value: 'enam' },
|
|
1281
|
+
{ name: 'Europe (West)', value: 'weur' },
|
|
1282
|
+
{ name: 'Europe (East)', value: 'eeur' },
|
|
1283
|
+
{ name: 'Asia Pacific', value: 'apac' },
|
|
1284
|
+
{ name: 'Oceania', value: 'oc' },
|
|
1285
|
+
{ name: '── Jurisdiction (Compliance) ──', value: '__separator2__', disabled: true },
|
|
1286
|
+
{ name: 'EU Jurisdiction (GDPR compliance)', value: 'eu' },
|
|
1287
|
+
];
|
|
1288
|
+
console.log(chalk.gray(' Core DB: Stores OAuth clients, tokens, sessions, audit logs'));
|
|
1289
|
+
const coreDbLocation = await select({
|
|
1290
|
+
message: 'Core Database region',
|
|
1291
|
+
choices: dbLocationChoices,
|
|
1292
|
+
default: 'auto',
|
|
1293
|
+
});
|
|
1294
|
+
console.log('');
|
|
1295
|
+
console.log(chalk.gray(' PII DB: Stores user profiles, credentials, personal data'));
|
|
1296
|
+
console.log(chalk.gray(' Consider your data protection requirements.'));
|
|
1297
|
+
const piiDbLocation = await select({
|
|
1298
|
+
message: 'PII Database region',
|
|
1299
|
+
choices: dbLocationChoices,
|
|
1300
|
+
default: 'auto',
|
|
1301
|
+
});
|
|
1302
|
+
// Parse location vs jurisdiction
|
|
1303
|
+
function parseDbLocationNormal(value) {
|
|
1304
|
+
if (value === 'eu') {
|
|
1305
|
+
return { location: 'auto', jurisdiction: 'eu' };
|
|
1306
|
+
}
|
|
1307
|
+
return {
|
|
1308
|
+
location: value,
|
|
1309
|
+
jurisdiction: 'none',
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1099
1312
|
// Create configuration
|
|
1100
1313
|
const config = createDefaultConfig(envPrefix);
|
|
1101
1314
|
config.profile = profile;
|
|
1315
|
+
config.database = {
|
|
1316
|
+
core: parseDbLocationNormal(coreDbLocation),
|
|
1317
|
+
pii: parseDbLocationNormal(piiDbLocation),
|
|
1318
|
+
};
|
|
1102
1319
|
config.tenant = {
|
|
1103
1320
|
name: tenantName,
|
|
1104
1321
|
displayName: tenantDisplayName,
|
|
@@ -1141,7 +1358,12 @@ async function runNormalSetup(options) {
|
|
|
1141
1358
|
config.features = {
|
|
1142
1359
|
queue: { enabled: enableQueue },
|
|
1143
1360
|
r2: { enabled: enableR2 },
|
|
1144
|
-
email: {
|
|
1361
|
+
email: {
|
|
1362
|
+
provider: emailConfigNormal.provider,
|
|
1363
|
+
fromAddress: emailConfigNormal.fromAddress,
|
|
1364
|
+
fromName: emailConfigNormal.fromName,
|
|
1365
|
+
configured: emailConfigNormal.provider === 'resend',
|
|
1366
|
+
},
|
|
1145
1367
|
};
|
|
1146
1368
|
// Show summary
|
|
1147
1369
|
console.log('');
|
|
@@ -1190,7 +1412,18 @@ async function runNormalSetup(options) {
|
|
|
1190
1412
|
console.log(chalk.bold('Feature Flags:'));
|
|
1191
1413
|
console.log(` Queue: ${enableQueue ? chalk.green('Enabled') : chalk.gray('Disabled')}`);
|
|
1192
1414
|
console.log(` R2: ${enableR2 ? chalk.green('Enabled') : chalk.gray('Disabled')}`);
|
|
1193
|
-
console.log(
|
|
1415
|
+
console.log('');
|
|
1416
|
+
console.log(chalk.bold('Email:'));
|
|
1417
|
+
if (emailConfigNormal.provider === 'resend') {
|
|
1418
|
+
console.log(` Provider: ${chalk.cyan('Resend')}`);
|
|
1419
|
+
console.log(` From Address: ${chalk.cyan(emailConfigNormal.fromAddress)}`);
|
|
1420
|
+
if (emailConfigNormal.fromName) {
|
|
1421
|
+
console.log(` From Name: ${chalk.cyan(emailConfigNormal.fromName)}`);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
else {
|
|
1425
|
+
console.log(` Provider: ${chalk.gray('Not configured (configure later)')}`);
|
|
1426
|
+
}
|
|
1194
1427
|
console.log('');
|
|
1195
1428
|
console.log(chalk.bold('OIDC Settings:'));
|
|
1196
1429
|
console.log(` Access TTL: ${chalk.cyan(accessTokenTtl + 'sec')}`);
|
|
@@ -1202,6 +1435,20 @@ async function runNormalSetup(options) {
|
|
|
1202
1435
|
console.log(` Auth Code: ${chalk.cyan(authCodeShards)} shards`);
|
|
1203
1436
|
console.log(` Refresh Token: ${chalk.cyan(refreshTokenShards)} shards`);
|
|
1204
1437
|
console.log('');
|
|
1438
|
+
console.log(chalk.bold('Database:'));
|
|
1439
|
+
const coreDbDisplay = coreDbLocation === 'eu'
|
|
1440
|
+
? 'EU Jurisdiction'
|
|
1441
|
+
: coreDbLocation === 'auto'
|
|
1442
|
+
? 'Automatic'
|
|
1443
|
+
: coreDbLocation.toUpperCase();
|
|
1444
|
+
const piiDbDisplay = piiDbLocation === 'eu'
|
|
1445
|
+
? 'EU Jurisdiction'
|
|
1446
|
+
: piiDbLocation === 'auto'
|
|
1447
|
+
? 'Automatic'
|
|
1448
|
+
: piiDbLocation.toUpperCase();
|
|
1449
|
+
console.log(` Core DB: ${chalk.cyan(coreDbDisplay)}`);
|
|
1450
|
+
console.log(` PII DB: ${chalk.cyan(piiDbDisplay)}`);
|
|
1451
|
+
console.log('');
|
|
1205
1452
|
const proceed = await confirm({
|
|
1206
1453
|
message: 'Start setup with this configuration?',
|
|
1207
1454
|
default: true,
|
|
@@ -1210,6 +1457,19 @@ async function runNormalSetup(options) {
|
|
|
1210
1457
|
console.log(chalk.yellow('Setup cancelled.'));
|
|
1211
1458
|
return;
|
|
1212
1459
|
}
|
|
1460
|
+
// Save email secrets if configured
|
|
1461
|
+
if (emailConfigNormal.provider === 'resend' && emailConfigNormal.apiKey) {
|
|
1462
|
+
const keysDir = `.keys/${envPrefix}`;
|
|
1463
|
+
await import('node:fs/promises').then(async (fs) => {
|
|
1464
|
+
await fs.mkdir(keysDir, { recursive: true });
|
|
1465
|
+
await fs.writeFile(`${keysDir}/resend_api_key.txt`, emailConfigNormal.apiKey.trim());
|
|
1466
|
+
await fs.writeFile(`${keysDir}/email_from.txt`, emailConfigNormal.fromAddress.trim());
|
|
1467
|
+
if (emailConfigNormal.fromName) {
|
|
1468
|
+
await fs.writeFile(`${keysDir}/email_from_name.txt`, emailConfigNormal.fromName.trim());
|
|
1469
|
+
}
|
|
1470
|
+
});
|
|
1471
|
+
console.log(chalk.gray(`📧 Email secrets saved to ${keysDir}/`));
|
|
1472
|
+
}
|
|
1213
1473
|
await executeSetup(config, cfApiToken, options.keep);
|
|
1214
1474
|
}
|
|
1215
1475
|
// =============================================================================
|
|
@@ -1300,6 +1560,7 @@ async function executeSetup(config, cfApiToken, keepPath) {
|
|
|
1300
1560
|
createKV: true,
|
|
1301
1561
|
createQueues: config.features.queue?.enabled,
|
|
1302
1562
|
createR2: config.features.r2?.enabled,
|
|
1563
|
+
databaseConfig: config.database,
|
|
1303
1564
|
onProgress: (msg) => console.log(` ${msg}`),
|
|
1304
1565
|
});
|
|
1305
1566
|
}
|
|
@@ -1531,6 +1792,7 @@ async function handleRedeploy(config, configPath) {
|
|
|
1531
1792
|
createKV: true,
|
|
1532
1793
|
createQueues: config.features.queue?.enabled,
|
|
1533
1794
|
createR2: config.features.r2?.enabled,
|
|
1795
|
+
databaseConfig: config.database,
|
|
1534
1796
|
onProgress: (msg) => console.log(` ${msg}`),
|
|
1535
1797
|
});
|
|
1536
1798
|
// Create and save lock file
|
|
@@ -1848,7 +2110,12 @@ async function editFeatures(config) {
|
|
|
1848
2110
|
});
|
|
1849
2111
|
config.features.queue = { enabled: queueEnabled };
|
|
1850
2112
|
config.features.r2 = { enabled: r2Enabled };
|
|
1851
|
-
config.features.email = {
|
|
2113
|
+
config.features.email = {
|
|
2114
|
+
provider: emailProvider,
|
|
2115
|
+
configured: config.features.email?.configured || false,
|
|
2116
|
+
fromAddress: config.features.email?.fromAddress,
|
|
2117
|
+
fromName: config.features.email?.fromName,
|
|
2118
|
+
};
|
|
1852
2119
|
return true;
|
|
1853
2120
|
}
|
|
1854
2121
|
// =============================================================================
|