@authrim/setup 0.1.20 → 0.1.24
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.d.ts.map +1 -1
- package/dist/cli/commands/init.js +399 -72
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/core/config.d.ts +46 -8
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +17 -6
- package/dist/core/config.js.map +1 -1
- package/dist/core/wrangler.d.ts.map +1 -1
- package/dist/core/wrangler.js +17 -4
- package/dist/core/wrangler.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +10 -1
- package/dist/web/api.js.map +1 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +213 -24
- package/dist/web/ui.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiDH,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiDH,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAiXD,wBAAsB,WAAW,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAuErE"}
|
|
@@ -24,12 +24,13 @@ function printBanner() {
|
|
|
24
24
|
console.log('');
|
|
25
25
|
console.log(chalk.blue('╔═══════════════════════════════════════════════════════════╗'));
|
|
26
26
|
console.log(chalk.blue('║') +
|
|
27
|
-
chalk.bold.white(' 🔐 Authrim Setup v0.1.
|
|
27
|
+
chalk.bold.white(' 🔐 Authrim Setup v0.1.24 ') +
|
|
28
28
|
chalk.blue('║'));
|
|
29
29
|
console.log(chalk.blue('║') +
|
|
30
30
|
chalk.gray(' OIDC Provider on Cloudflare Workers ') +
|
|
31
31
|
chalk.blue('║'));
|
|
32
32
|
console.log(chalk.blue('╚═══════════════════════════════════════════════════════════╝'));
|
|
33
|
+
console.log(chalk.gray(' Press Ctrl+C at any time to exit'));
|
|
33
34
|
console.log('');
|
|
34
35
|
}
|
|
35
36
|
// =============================================================================
|
|
@@ -396,28 +397,214 @@ export async function initCommand(options) {
|
|
|
396
397
|
// CLI Setup Flow
|
|
397
398
|
// =============================================================================
|
|
398
399
|
async function runCliSetup(options) {
|
|
399
|
-
//
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
400
|
+
// Main menu loop - keeps returning to menu until user exits
|
|
401
|
+
while (true) {
|
|
402
|
+
const setupMode = await select({
|
|
403
|
+
message: 'What would you like to do?',
|
|
404
|
+
choices: [
|
|
405
|
+
{
|
|
406
|
+
value: 'quick',
|
|
407
|
+
name: '⚡ Quick Setup (5 minutes)',
|
|
408
|
+
description: 'Deploy Authrim with minimal configuration',
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
value: 'normal',
|
|
412
|
+
name: '🔧 Custom Setup',
|
|
413
|
+
description: 'Configure all options step by step',
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
value: 'manage',
|
|
417
|
+
name: '📋 View Existing Environments',
|
|
418
|
+
description: 'View, inspect, or delete existing environments',
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
value: 'load',
|
|
422
|
+
name: '📂 Load Existing Configuration',
|
|
423
|
+
description: 'Resume setup from authrim-config.json',
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
value: 'exit',
|
|
427
|
+
name: '❌ Exit',
|
|
428
|
+
description: 'Exit setup',
|
|
429
|
+
},
|
|
430
|
+
],
|
|
431
|
+
});
|
|
432
|
+
if (setupMode === 'exit') {
|
|
433
|
+
console.log('');
|
|
434
|
+
console.log(chalk.gray('Goodbye!'));
|
|
435
|
+
console.log('');
|
|
436
|
+
break;
|
|
437
|
+
}
|
|
438
|
+
if (setupMode === 'quick') {
|
|
439
|
+
await runQuickSetup(options);
|
|
440
|
+
break; // Exit after setup completes
|
|
441
|
+
}
|
|
442
|
+
else if (setupMode === 'normal') {
|
|
443
|
+
await runNormalSetup(options);
|
|
444
|
+
break; // Exit after setup completes
|
|
445
|
+
}
|
|
446
|
+
else if (setupMode === 'manage') {
|
|
447
|
+
await runManageEnvironments();
|
|
448
|
+
// Returns to main menu after manage
|
|
449
|
+
console.log('');
|
|
450
|
+
}
|
|
451
|
+
else if (setupMode === 'load') {
|
|
452
|
+
const shouldContinue = await runLoadConfig();
|
|
453
|
+
if (!shouldContinue) {
|
|
454
|
+
// Returns to main menu
|
|
455
|
+
console.log('');
|
|
456
|
+
}
|
|
457
|
+
else {
|
|
458
|
+
break; // Exit after deploy
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
// =============================================================================
|
|
464
|
+
// Manage Existing Environments
|
|
465
|
+
// =============================================================================
|
|
466
|
+
async function runManageEnvironments() {
|
|
467
|
+
// Loop to allow multiple operations before returning to main menu
|
|
468
|
+
while (true) {
|
|
469
|
+
console.log('');
|
|
470
|
+
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
471
|
+
console.log(chalk.bold('📋 Existing Environments'));
|
|
472
|
+
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
473
|
+
console.log('');
|
|
474
|
+
const spinner = ora('Detecting environments...').start();
|
|
475
|
+
const environments = await detectEnvironments();
|
|
476
|
+
spinner.stop();
|
|
477
|
+
if (environments.length === 0) {
|
|
478
|
+
console.log(chalk.yellow('No Authrim environments found.'));
|
|
479
|
+
console.log('');
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
console.log(chalk.bold('Detected Environments:'));
|
|
483
|
+
console.log('');
|
|
484
|
+
for (const env of environments) {
|
|
485
|
+
console.log(` ${chalk.cyan(env.env)}`);
|
|
486
|
+
console.log(chalk.gray(` Workers: ${env.workers.length}, D1: ${env.d1.length}, KV: ${env.kv.length}`));
|
|
487
|
+
}
|
|
488
|
+
console.log('');
|
|
489
|
+
const action = await select({
|
|
490
|
+
message: 'Select action',
|
|
491
|
+
choices: [
|
|
492
|
+
{
|
|
493
|
+
value: 'info',
|
|
494
|
+
name: '🔍 View Details',
|
|
495
|
+
description: 'Show detailed resource information',
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
value: 'delete',
|
|
499
|
+
name: '🗑️ Delete Environment',
|
|
500
|
+
description: 'Remove environment and resources',
|
|
501
|
+
},
|
|
502
|
+
{ value: 'back', name: '← Back to Main Menu', description: 'Return to main menu' },
|
|
503
|
+
],
|
|
504
|
+
});
|
|
505
|
+
if (action === 'back') {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
const envChoices = environments.map((e) => ({
|
|
509
|
+
name: `${e.env} (${e.workers.length} workers, ${e.d1.length} D1, ${e.kv.length} KV)`,
|
|
510
|
+
value: e.env,
|
|
511
|
+
}));
|
|
512
|
+
envChoices.push({ name: '← Back', value: '__back__' });
|
|
513
|
+
const envName = await select({
|
|
514
|
+
message: 'Select environment',
|
|
515
|
+
choices: envChoices,
|
|
516
|
+
});
|
|
517
|
+
if (envName === '__back__') {
|
|
518
|
+
continue; // Go back to action selection
|
|
519
|
+
}
|
|
520
|
+
if (action === 'info') {
|
|
521
|
+
const { infoCommand } = await import('./info.js');
|
|
522
|
+
await infoCommand({ env: envName });
|
|
523
|
+
}
|
|
524
|
+
else if (action === 'delete') {
|
|
525
|
+
const { deleteCommand } = await import('./delete.js');
|
|
526
|
+
await deleteCommand({ env: envName });
|
|
527
|
+
}
|
|
528
|
+
// After action, ask if user wants to continue managing
|
|
529
|
+
console.log('');
|
|
530
|
+
const continueManaging = await confirm({
|
|
531
|
+
message: 'Continue managing environments?',
|
|
532
|
+
default: true,
|
|
533
|
+
});
|
|
534
|
+
if (!continueManaging) {
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
// =============================================================================
|
|
540
|
+
// Load Existing Configuration
|
|
541
|
+
// =============================================================================
|
|
542
|
+
async function runLoadConfig() {
|
|
543
|
+
console.log('');
|
|
544
|
+
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
545
|
+
console.log(chalk.bold('📂 Load Existing Configuration'));
|
|
546
|
+
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
547
|
+
console.log('');
|
|
548
|
+
// Check for config file in current directory
|
|
549
|
+
const defaultConfigPath = './authrim-config.json';
|
|
550
|
+
const configExists = existsSync(defaultConfigPath);
|
|
551
|
+
let configPath = defaultConfigPath;
|
|
552
|
+
if (configExists) {
|
|
553
|
+
console.log(chalk.green(`✓ Found: ${defaultConfigPath}`));
|
|
554
|
+
console.log('');
|
|
555
|
+
const action = await select({
|
|
556
|
+
message: 'What would you like to do?',
|
|
557
|
+
choices: [
|
|
558
|
+
{ value: 'load', name: '📂 Load this configuration' },
|
|
559
|
+
{ value: 'other', name: '📁 Specify different file' },
|
|
560
|
+
{ value: 'back', name: '← Back to Main Menu' },
|
|
561
|
+
],
|
|
562
|
+
});
|
|
563
|
+
if (action === 'back') {
|
|
564
|
+
return false; // Return to main menu
|
|
565
|
+
}
|
|
566
|
+
if (action === 'other') {
|
|
567
|
+
configPath = await input({
|
|
568
|
+
message: 'Enter configuration file path',
|
|
569
|
+
validate: (value) => {
|
|
570
|
+
if (!value)
|
|
571
|
+
return 'Please enter a path';
|
|
572
|
+
if (!existsSync(value))
|
|
573
|
+
return `File not found: ${value}`;
|
|
574
|
+
return true;
|
|
575
|
+
},
|
|
576
|
+
});
|
|
577
|
+
}
|
|
417
578
|
}
|
|
418
579
|
else {
|
|
419
|
-
|
|
580
|
+
console.log(chalk.yellow('No authrim-config.json found in current directory.'));
|
|
581
|
+
console.log('');
|
|
582
|
+
console.log(chalk.gray('💡 Tip: You can specify a config file with:'));
|
|
583
|
+
console.log(chalk.cyan(' npx @authrim/setup --config /path/to/authrim-config.json'));
|
|
584
|
+
console.log('');
|
|
585
|
+
const action = await select({
|
|
586
|
+
message: 'What would you like to do?',
|
|
587
|
+
choices: [
|
|
588
|
+
{ value: 'specify', name: '📁 Specify file path' },
|
|
589
|
+
{ value: 'back', name: '← Back to Main Menu' },
|
|
590
|
+
],
|
|
591
|
+
});
|
|
592
|
+
if (action === 'back') {
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
configPath = await input({
|
|
596
|
+
message: 'Enter configuration file path',
|
|
597
|
+
validate: (value) => {
|
|
598
|
+
if (!value)
|
|
599
|
+
return 'Please enter a path';
|
|
600
|
+
if (!existsSync(value))
|
|
601
|
+
return `File not found: ${value}`;
|
|
602
|
+
return true;
|
|
603
|
+
},
|
|
604
|
+
});
|
|
420
605
|
}
|
|
606
|
+
await handleExistingConfig(configPath);
|
|
607
|
+
return true; // Config was loaded and processed
|
|
421
608
|
}
|
|
422
609
|
// =============================================================================
|
|
423
610
|
// Quick Setup
|
|
@@ -471,17 +658,25 @@ async function runQuickSetup(options) {
|
|
|
471
658
|
return true;
|
|
472
659
|
},
|
|
473
660
|
});
|
|
474
|
-
// Step 3:
|
|
661
|
+
// Step 3: Show infrastructure info
|
|
662
|
+
console.log('');
|
|
663
|
+
console.log(chalk.gray(' Workers to deploy: ' + envPrefix + '-ar-router, ' + envPrefix + '-ar-auth, ...'));
|
|
664
|
+
console.log(chalk.gray(' Default API: https://' + envPrefix + '-ar-router.workers.dev'));
|
|
665
|
+
console.log('');
|
|
666
|
+
// Step 4: Domain configuration (single-tenant mode only in Quick Setup)
|
|
475
667
|
const useCustomDomain = await confirm({
|
|
476
|
-
message: 'Configure custom domain?',
|
|
668
|
+
message: 'Configure custom domain? (for Issuer URL)',
|
|
477
669
|
default: false,
|
|
478
670
|
});
|
|
479
671
|
let apiDomain = null;
|
|
480
672
|
let loginUiDomain = null;
|
|
481
673
|
let adminUiDomain = null;
|
|
482
674
|
if (useCustomDomain) {
|
|
675
|
+
console.log('');
|
|
676
|
+
console.log(chalk.gray(' In single-tenant mode, Issuer URL = API domain'));
|
|
677
|
+
console.log('');
|
|
483
678
|
apiDomain = await input({
|
|
484
|
-
message: 'API (
|
|
679
|
+
message: 'API / Issuer domain (e.g., auth.example.com)',
|
|
485
680
|
validate: (value) => {
|
|
486
681
|
if (!value)
|
|
487
682
|
return true; // Allow empty for workers.dev fallback
|
|
@@ -505,7 +700,7 @@ async function runQuickSetup(options) {
|
|
|
505
700
|
config.urls = {
|
|
506
701
|
api: {
|
|
507
702
|
custom: apiDomain || null,
|
|
508
|
-
auto: `https://${envPrefix}-ar-router.workers.dev`,
|
|
703
|
+
auto: `https://${envPrefix}-ar-router.workers.dev`,
|
|
509
704
|
},
|
|
510
705
|
loginUi: {
|
|
511
706
|
custom: loginUiDomain || null,
|
|
@@ -522,10 +717,14 @@ async function runQuickSetup(options) {
|
|
|
522
717
|
console.log(chalk.bold('📋 Configuration Summary'));
|
|
523
718
|
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
524
719
|
console.log('');
|
|
525
|
-
console.log(
|
|
526
|
-
console.log(`
|
|
527
|
-
console.log(`
|
|
528
|
-
console.log(
|
|
720
|
+
console.log(chalk.bold('Infrastructure:'));
|
|
721
|
+
console.log(` Environment: ${chalk.cyan(envPrefix)}`);
|
|
722
|
+
console.log(` Worker Prefix: ${chalk.cyan(envPrefix + '-ar-*')}`);
|
|
723
|
+
console.log('');
|
|
724
|
+
console.log(chalk.bold('URLs (Single-tenant):'));
|
|
725
|
+
console.log(` Issuer URL: ${chalk.cyan(config.urls.api.custom || config.urls.api.auto)}`);
|
|
726
|
+
console.log(` Login UI: ${chalk.cyan(config.urls.loginUi.custom || config.urls.loginUi.auto)}`);
|
|
727
|
+
console.log(` Admin UI: ${chalk.cyan(config.urls.adminUi.custom || config.urls.adminUi.auto)}`);
|
|
529
728
|
console.log('');
|
|
530
729
|
const proceed = await confirm({
|
|
531
730
|
message: 'Start setup with this configuration?',
|
|
@@ -612,38 +811,150 @@ async function runNormalSetup(options) {
|
|
|
612
811
|
],
|
|
613
812
|
default: 'basic-op',
|
|
614
813
|
});
|
|
615
|
-
// Step 4:
|
|
616
|
-
|
|
617
|
-
|
|
814
|
+
// Step 4: Infrastructure overview (Workers are auto-generated from env)
|
|
815
|
+
console.log('');
|
|
816
|
+
console.log(chalk.blue('━━━ Infrastructure (Auto-generated) ━━━'));
|
|
817
|
+
console.log('');
|
|
818
|
+
console.log(chalk.gray(' The following Workers will be deployed:'));
|
|
819
|
+
console.log(` Router: ${chalk.cyan(envPrefix + '-ar-router')}`);
|
|
820
|
+
console.log(` Auth: ${chalk.cyan(envPrefix + '-ar-auth')}`);
|
|
821
|
+
console.log(` Token: ${chalk.cyan(envPrefix + '-ar-token')}`);
|
|
822
|
+
console.log(` Management: ${chalk.cyan(envPrefix + '-ar-management')}`);
|
|
823
|
+
console.log(chalk.gray(' ... and other supporting workers'));
|
|
824
|
+
console.log('');
|
|
825
|
+
console.log(chalk.gray(' Default endpoints (without custom domain):'));
|
|
826
|
+
console.log(` API: ${chalk.gray('https://' + envPrefix + '-ar-router.workers.dev')}`);
|
|
827
|
+
console.log(` UI: ${chalk.gray('https://' + envPrefix + '-ar-ui.pages.dev')}`);
|
|
828
|
+
console.log('');
|
|
829
|
+
// Step 5: Tenant configuration
|
|
830
|
+
console.log(chalk.blue('━━━ Tenant Mode ━━━'));
|
|
831
|
+
console.log('');
|
|
832
|
+
const multiTenant = await confirm({
|
|
833
|
+
message: 'Enable multi-tenant mode? (subdomain-based tenant isolation)',
|
|
618
834
|
default: false,
|
|
619
835
|
});
|
|
836
|
+
let tenantName = 'default';
|
|
837
|
+
let tenantDisplayName = 'Default Tenant';
|
|
838
|
+
let baseDomain;
|
|
839
|
+
// Step 6: URL configuration (depends on tenant mode)
|
|
620
840
|
let apiDomain = null;
|
|
621
841
|
let loginUiDomain = null;
|
|
622
842
|
let adminUiDomain = null;
|
|
623
|
-
if (
|
|
624
|
-
|
|
625
|
-
|
|
843
|
+
if (multiTenant) {
|
|
844
|
+
// Multi-tenant mode: base domain is required, becomes the issuer base
|
|
845
|
+
console.log('');
|
|
846
|
+
console.log(chalk.blue('━━━ Multi-tenant URL Configuration ━━━'));
|
|
847
|
+
console.log('');
|
|
848
|
+
console.log(chalk.gray(' In multi-tenant mode:'));
|
|
849
|
+
console.log(chalk.gray(' • Each tenant has a subdomain: https://{tenant}.{base-domain}'));
|
|
850
|
+
console.log(chalk.gray(' • The base domain points to the router Worker'));
|
|
851
|
+
console.log(chalk.gray(' • Issuer URL is dynamically built from Host header'));
|
|
852
|
+
console.log('');
|
|
853
|
+
baseDomain = await input({
|
|
854
|
+
message: 'Base domain (e.g., authrim.com)',
|
|
626
855
|
validate: (value) => {
|
|
627
856
|
if (!value)
|
|
628
|
-
return
|
|
857
|
+
return 'Base domain is required for multi-tenant mode';
|
|
629
858
|
if (!/^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(value)) {
|
|
630
|
-
return 'Please enter a valid domain';
|
|
859
|
+
return 'Please enter a valid domain (e.g., authrim.com)';
|
|
631
860
|
}
|
|
632
861
|
return true;
|
|
633
862
|
},
|
|
634
863
|
});
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
864
|
+
console.log('');
|
|
865
|
+
console.log(chalk.green(' ✓ Issuer URL format: https://{tenant}.' + baseDomain));
|
|
866
|
+
console.log(chalk.gray(' Example: https://acme.' + baseDomain));
|
|
867
|
+
console.log('');
|
|
868
|
+
// API domain in multi-tenant is the base domain (or custom apex)
|
|
869
|
+
apiDomain = baseDomain;
|
|
870
|
+
tenantName = await input({
|
|
871
|
+
message: 'Default tenant name (identifier)',
|
|
872
|
+
default: 'default',
|
|
873
|
+
validate: (value) => {
|
|
874
|
+
if (!/^[a-z][a-z0-9-]*$/.test(value)) {
|
|
875
|
+
return 'Only lowercase alphanumeric and hyphens allowed';
|
|
876
|
+
}
|
|
877
|
+
return true;
|
|
878
|
+
},
|
|
638
879
|
});
|
|
639
|
-
|
|
640
|
-
message: '
|
|
641
|
-
default: '',
|
|
880
|
+
tenantDisplayName = await input({
|
|
881
|
+
message: 'Default tenant display name',
|
|
882
|
+
default: 'Default Tenant',
|
|
883
|
+
});
|
|
884
|
+
// UI domains for multi-tenant
|
|
885
|
+
console.log('');
|
|
886
|
+
console.log(chalk.blue('━━━ UI Domain Configuration ━━━'));
|
|
887
|
+
console.log('');
|
|
888
|
+
const useCustomUiDomain = await confirm({
|
|
889
|
+
message: 'Configure custom UI domains?',
|
|
890
|
+
default: false,
|
|
642
891
|
});
|
|
892
|
+
if (useCustomUiDomain) {
|
|
893
|
+
loginUiDomain = await input({
|
|
894
|
+
message: 'Login UI domain (e.g., login.example.com)',
|
|
895
|
+
default: '',
|
|
896
|
+
});
|
|
897
|
+
adminUiDomain = await input({
|
|
898
|
+
message: 'Admin UI domain (e.g., admin.example.com)',
|
|
899
|
+
default: '',
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
else {
|
|
904
|
+
// Single-tenant mode
|
|
905
|
+
console.log('');
|
|
906
|
+
console.log(chalk.blue('━━━ Single-tenant URL Configuration ━━━'));
|
|
907
|
+
console.log('');
|
|
908
|
+
console.log(chalk.gray(' In single-tenant mode:'));
|
|
909
|
+
console.log(chalk.gray(' • Issuer URL = API custom domain (or workers.dev fallback)'));
|
|
910
|
+
console.log(chalk.gray(' • All clients share the same issuer'));
|
|
911
|
+
console.log('');
|
|
912
|
+
tenantDisplayName = await input({
|
|
913
|
+
message: 'Organization name (display name)',
|
|
914
|
+
default: 'Default Tenant',
|
|
915
|
+
});
|
|
916
|
+
const useCustomDomain = await confirm({
|
|
917
|
+
message: 'Configure custom domain?',
|
|
918
|
+
default: false,
|
|
919
|
+
});
|
|
920
|
+
if (useCustomDomain) {
|
|
921
|
+
console.log('');
|
|
922
|
+
console.log(chalk.gray(' Enter custom domains (leave empty to use Cloudflare defaults)'));
|
|
923
|
+
console.log('');
|
|
924
|
+
apiDomain = await input({
|
|
925
|
+
message: 'API / Issuer domain (e.g., auth.example.com)',
|
|
926
|
+
validate: (value) => {
|
|
927
|
+
if (!value)
|
|
928
|
+
return true;
|
|
929
|
+
if (!/^[a-z0-9][a-z0-9.-]*\.[a-z]{2,}$/.test(value)) {
|
|
930
|
+
return 'Please enter a valid domain';
|
|
931
|
+
}
|
|
932
|
+
return true;
|
|
933
|
+
},
|
|
934
|
+
});
|
|
935
|
+
loginUiDomain = await input({
|
|
936
|
+
message: 'Login UI domain (Enter to skip)',
|
|
937
|
+
default: '',
|
|
938
|
+
});
|
|
939
|
+
adminUiDomain = await input({
|
|
940
|
+
message: 'Admin UI domain (Enter to skip)',
|
|
941
|
+
default: '',
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
if (apiDomain) {
|
|
945
|
+
console.log('');
|
|
946
|
+
console.log(chalk.green(' ✓ Issuer URL: https://' + apiDomain));
|
|
947
|
+
}
|
|
948
|
+
else {
|
|
949
|
+
console.log('');
|
|
950
|
+
console.log(chalk.green(' ✓ Issuer URL: https://' + envPrefix + '-ar-router.workers.dev'));
|
|
951
|
+
console.log(chalk.gray(' (using Cloudflare workers.dev domain)'));
|
|
952
|
+
}
|
|
643
953
|
}
|
|
644
954
|
// Step 5: Optional components
|
|
645
955
|
console.log('');
|
|
646
956
|
console.log(chalk.blue('━━━ Optional Components ━━━'));
|
|
957
|
+
console.log(chalk.gray(' Note: Social Login and Policy Engine are standard components'));
|
|
647
958
|
console.log('');
|
|
648
959
|
const enableSaml = await confirm({
|
|
649
960
|
message: 'Enable SAML support?',
|
|
@@ -653,14 +964,6 @@ async function runNormalSetup(options) {
|
|
|
653
964
|
message: 'Enable Verifiable Credentials?',
|
|
654
965
|
default: false,
|
|
655
966
|
});
|
|
656
|
-
const enableBridge = await confirm({
|
|
657
|
-
message: 'Enable External IdP Bridge?',
|
|
658
|
-
default: false,
|
|
659
|
-
});
|
|
660
|
-
const enablePolicy = await confirm({
|
|
661
|
-
message: 'Enable ReBAC Policy service?',
|
|
662
|
-
default: false,
|
|
663
|
-
});
|
|
664
967
|
// Step 6: Feature flags
|
|
665
968
|
console.log('');
|
|
666
969
|
console.log(chalk.blue('━━━ Feature Flags ━━━'));
|
|
@@ -772,13 +1075,19 @@ async function runNormalSetup(options) {
|
|
|
772
1075
|
// Create configuration
|
|
773
1076
|
const config = createDefaultConfig(envPrefix);
|
|
774
1077
|
config.profile = profile;
|
|
1078
|
+
config.tenant = {
|
|
1079
|
+
name: tenantName,
|
|
1080
|
+
displayName: tenantDisplayName,
|
|
1081
|
+
multiTenant,
|
|
1082
|
+
baseDomain,
|
|
1083
|
+
};
|
|
775
1084
|
config.components = {
|
|
776
1085
|
...config.components,
|
|
777
1086
|
saml: enableSaml,
|
|
778
1087
|
async: enableQueue, // async is tied to queue
|
|
779
1088
|
vc: enableVc,
|
|
780
|
-
bridge:
|
|
781
|
-
policy:
|
|
1089
|
+
bridge: true, // Standard component
|
|
1090
|
+
policy: true, // Standard component
|
|
782
1091
|
};
|
|
783
1092
|
config.urls = {
|
|
784
1093
|
api: {
|
|
@@ -816,20 +1125,43 @@ async function runNormalSetup(options) {
|
|
|
816
1125
|
console.log(chalk.bold('📋 Configuration Summary'));
|
|
817
1126
|
console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
|
|
818
1127
|
console.log('');
|
|
819
|
-
|
|
820
|
-
console.log(
|
|
821
|
-
console.log(`
|
|
1128
|
+
// Infrastructure
|
|
1129
|
+
console.log(chalk.bold('Infrastructure:'));
|
|
1130
|
+
console.log(` Environment: ${chalk.cyan(envPrefix)}`);
|
|
1131
|
+
console.log(` Worker Prefix: ${chalk.cyan(envPrefix + '-ar-*')}`);
|
|
1132
|
+
console.log(` Profile: ${chalk.cyan(profile)}`);
|
|
822
1133
|
console.log('');
|
|
823
|
-
|
|
824
|
-
console.log(
|
|
1134
|
+
// Tenant mode and Issuer
|
|
1135
|
+
console.log(chalk.bold('Tenant & Issuer:'));
|
|
1136
|
+
console.log(` Mode: ${multiTenant ? chalk.cyan('Multi-tenant') : chalk.cyan('Single-tenant')}`);
|
|
1137
|
+
if (multiTenant && baseDomain) {
|
|
1138
|
+
console.log(` Base Domain: ${chalk.cyan(baseDomain)}`);
|
|
1139
|
+
console.log(` Issuer Format: ${chalk.cyan('https://{tenant}.' + baseDomain)}`);
|
|
1140
|
+
console.log(` Example: ${chalk.gray('https://acme.' + baseDomain)}`);
|
|
1141
|
+
}
|
|
1142
|
+
else {
|
|
1143
|
+
const issuerUrl = config.urls.api.custom || config.urls.api.auto;
|
|
1144
|
+
console.log(` Issuer URL: ${chalk.cyan(issuerUrl)}`);
|
|
1145
|
+
}
|
|
1146
|
+
console.log(` Default Tenant: ${chalk.cyan(tenantName)}`);
|
|
1147
|
+
console.log(` Display Name: ${chalk.cyan(tenantDisplayName)}`);
|
|
1148
|
+
console.log('');
|
|
1149
|
+
// Public URLs
|
|
1150
|
+
console.log(chalk.bold('Public URLs:'));
|
|
1151
|
+
if (multiTenant && baseDomain) {
|
|
1152
|
+
console.log(` API Router: ${chalk.cyan('*.' + baseDomain)} → ${chalk.gray(envPrefix + '-ar-router')}`);
|
|
1153
|
+
}
|
|
1154
|
+
else {
|
|
1155
|
+
console.log(` API Router: ${chalk.cyan(config.urls.api.custom || config.urls.api.auto)}`);
|
|
1156
|
+
}
|
|
825
1157
|
console.log(` Login UI: ${chalk.cyan(config.urls.loginUi.custom || config.urls.loginUi.auto)}`);
|
|
826
1158
|
console.log(` Admin UI: ${chalk.cyan(config.urls.adminUi.custom || config.urls.adminUi.auto)}`);
|
|
827
1159
|
console.log('');
|
|
828
1160
|
console.log(chalk.bold('Components:'));
|
|
829
1161
|
console.log(` SAML: ${enableSaml ? chalk.green('Enabled') : chalk.gray('Disabled')}`);
|
|
830
1162
|
console.log(` VC: ${enableVc ? chalk.green('Enabled') : chalk.gray('Disabled')}`);
|
|
831
|
-
console.log(`
|
|
832
|
-
console.log(` Policy:
|
|
1163
|
+
console.log(` Social Login: ${chalk.green('Enabled')} ${chalk.gray('(standard)')}`);
|
|
1164
|
+
console.log(` Policy Engine: ${chalk.green('Enabled')} ${chalk.gray('(standard)')}`);
|
|
833
1165
|
console.log('');
|
|
834
1166
|
console.log(chalk.bold('Feature Flags:'));
|
|
835
1167
|
console.log(` Queue: ${enableQueue ? chalk.green('Enabled') : chalk.gray('Disabled')}`);
|
|
@@ -1356,11 +1688,11 @@ async function editUrls(config) {
|
|
|
1356
1688
|
// =============================================================================
|
|
1357
1689
|
async function editComponents(config) {
|
|
1358
1690
|
console.log(chalk.bold('\nCurrent Component Settings:'));
|
|
1359
|
-
console.log(` SAML:
|
|
1360
|
-
console.log(` Async:
|
|
1361
|
-
console.log(` VC:
|
|
1362
|
-
console.log(`
|
|
1363
|
-
console.log(` Policy:
|
|
1691
|
+
console.log(` SAML: ${config.components.saml ? chalk.green('Enabled') : chalk.gray('Disabled')}`);
|
|
1692
|
+
console.log(` Async: ${config.components.async ? chalk.green('Enabled') : chalk.gray('Disabled')}`);
|
|
1693
|
+
console.log(` VC: ${config.components.vc ? chalk.green('Enabled') : chalk.gray('Disabled')}`);
|
|
1694
|
+
console.log(` Social Login: ${chalk.green('Enabled')} ${chalk.gray('(standard - always on)')}`);
|
|
1695
|
+
console.log(` Policy Engine: ${chalk.green('Enabled')} ${chalk.gray('(standard - always on)')}`);
|
|
1364
1696
|
console.log('');
|
|
1365
1697
|
config.components.saml = await confirm({
|
|
1366
1698
|
message: 'Enable SAML support?',
|
|
@@ -1374,14 +1706,9 @@ async function editComponents(config) {
|
|
|
1374
1706
|
message: 'Enable Verifiable Credentials?',
|
|
1375
1707
|
default: config.components.vc,
|
|
1376
1708
|
});
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
});
|
|
1381
|
-
config.components.policy = await confirm({
|
|
1382
|
-
message: 'Enable ReBAC Policy service?',
|
|
1383
|
-
default: config.components.policy,
|
|
1384
|
-
});
|
|
1709
|
+
// Standard components are always enabled
|
|
1710
|
+
config.components.bridge = true;
|
|
1711
|
+
config.components.policy = true;
|
|
1385
1712
|
return true;
|
|
1386
1713
|
}
|
|
1387
1714
|
// =============================================================================
|