@authrim/setup 0.1.63 → 0.1.64

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.
Files changed (60) hide show
  1. package/dist/__tests__/migrate.test.d.ts +5 -0
  2. package/dist/__tests__/migrate.test.d.ts.map +1 -0
  3. package/dist/__tests__/migrate.test.js +273 -0
  4. package/dist/__tests__/migrate.test.js.map +1 -0
  5. package/dist/__tests__/paths.test.d.ts +2 -0
  6. package/dist/__tests__/paths.test.d.ts.map +1 -0
  7. package/dist/__tests__/paths.test.js +257 -0
  8. package/dist/__tests__/paths.test.js.map +1 -0
  9. package/dist/cli/commands/config.d.ts +1 -0
  10. package/dist/cli/commands/config.d.ts.map +1 -1
  11. package/dist/cli/commands/config.js +41 -7
  12. package/dist/cli/commands/config.js.map +1 -1
  13. package/dist/cli/commands/deploy.d.ts +1 -0
  14. package/dist/cli/commands/deploy.d.ts.map +1 -1
  15. package/dist/cli/commands/deploy.js +181 -19
  16. package/dist/cli/commands/deploy.js.map +1 -1
  17. package/dist/cli/commands/init.d.ts.map +1 -1
  18. package/dist/cli/commands/init.js +267 -82
  19. package/dist/cli/commands/init.js.map +1 -1
  20. package/dist/cli/commands/migrate.d.ts +21 -0
  21. package/dist/cli/commands/migrate.d.ts.map +1 -0
  22. package/dist/cli/commands/migrate.js +166 -0
  23. package/dist/cli/commands/migrate.js.map +1 -0
  24. package/dist/core/admin.d.ts +18 -1
  25. package/dist/core/admin.d.ts.map +1 -1
  26. package/dist/core/admin.js +36 -7
  27. package/dist/core/admin.js.map +1 -1
  28. package/dist/core/config.d.ts +10 -2
  29. package/dist/core/config.d.ts.map +1 -1
  30. package/dist/core/config.js +6 -2
  31. package/dist/core/config.js.map +1 -1
  32. package/dist/core/keys.d.ts +55 -4
  33. package/dist/core/keys.d.ts.map +1 -1
  34. package/dist/core/keys.js +104 -12
  35. package/dist/core/keys.js.map +1 -1
  36. package/dist/core/lock.d.ts +60 -3
  37. package/dist/core/lock.d.ts.map +1 -1
  38. package/dist/core/lock.js +108 -4
  39. package/dist/core/lock.js.map +1 -1
  40. package/dist/core/migrate.d.ts +95 -0
  41. package/dist/core/migrate.d.ts.map +1 -0
  42. package/dist/core/migrate.js +549 -0
  43. package/dist/core/migrate.js.map +1 -0
  44. package/dist/core/paths.d.ts +171 -0
  45. package/dist/core/paths.d.ts.map +1 -0
  46. package/dist/core/paths.js +319 -0
  47. package/dist/core/paths.js.map +1 -0
  48. package/dist/core/wrangler-sync.d.ts +88 -0
  49. package/dist/core/wrangler-sync.d.ts.map +1 -0
  50. package/dist/core/wrangler-sync.js +242 -0
  51. package/dist/core/wrangler-sync.js.map +1 -0
  52. package/dist/index.js +16 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/web/api.d.ts.map +1 -1
  55. package/dist/web/api.js +102 -28
  56. package/dist/web/api.js.map +1 -1
  57. package/dist/web/ui.d.ts.map +1 -1
  58. package/dist/web/ui.js +831 -273
  59. package/dist/web/ui.js.map +1 -1
  60. package/package.json +1 -1
@@ -6,18 +6,17 @@
6
6
  import { input, select, confirm, password } from '@inquirer/prompts';
7
7
  import chalk from 'chalk';
8
8
  import ora from 'ora';
9
- import { readFile, writeFile } from 'node:fs/promises';
9
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
10
10
  import { existsSync } from 'node:fs';
11
11
  import { join, resolve } from 'node:path';
12
12
  import { createRequire } from 'node:module';
13
13
  import { execa } from 'execa';
14
14
  import { createDefaultConfig, parseConfig } from '../../core/config.js';
15
15
  import { generateAllSecrets, saveKeysToDirectory, generateKeyId, keysExistForEnvironment, } from '../../core/keys.js';
16
- import { generateWranglerConfig, toToml } from '../../core/wrangler.js';
17
- import { CORE_WORKER_COMPONENTS, } from '../../core/naming.js';
18
16
  import { isWranglerInstalled, checkAuth, provisionResources, toResourceIds, getAccountId, detectEnvironments, getWorkersSubdomain, } from '../../core/cloudflare.js';
19
- import { createLockFile, saveLockFile, loadLockFile, } from '../../core/lock.js';
20
- import { downloadSource, verifySourceStructure, checkForUpdate, } from '../../core/source.js';
17
+ import { createLockFile, saveLockFile, loadLockFile } from '../../core/lock.js';
18
+ import { getEnvironmentPaths, getRelativeKeysPath, AUTHRIM_DIR, } from '../../core/paths.js';
19
+ import { downloadSource, verifySourceStructure, checkForUpdate } from '../../core/source.js';
21
20
  // =============================================================================
22
21
  // Version
23
22
  // =============================================================================
@@ -293,15 +292,12 @@ async function updateExistingSource(sourceDir, gitRef) {
293
292
  const spinner = ora('Updating source code...').start();
294
293
  try {
295
294
  // Backup existing configuration files
296
- const configFiles = ['authrim-config.json', 'authrim-lock.json', '.keys'];
295
+ // Support both legacy (authrim-*.json, .keys/) and new (.authrim/) structures
296
+ const configFiles = ['authrim-config.json', 'authrim-lock.json'];
297
297
  const backups = [];
298
298
  for (const file of configFiles) {
299
299
  const filePath = join(sourceDir, file);
300
300
  if (existsSync(filePath)) {
301
- if (file === '.keys') {
302
- // Skip backing up .keys - will be preserved
303
- continue;
304
- }
305
301
  const { readFile: rf } = await import('node:fs/promises');
306
302
  const content = await rf(filePath, 'utf-8');
307
303
  backups.push({ file, content });
@@ -318,7 +314,13 @@ async function updateExistingSource(sourceDir, gitRef) {
318
314
  spinner.text = msg;
319
315
  },
320
316
  });
321
- // Preserve .keys directory if it exists
317
+ // Preserve .authrim directory if it exists (new structure)
318
+ const authrimDir = join(sourceDir, AUTHRIM_DIR);
319
+ const tempAuthrimDir = join(tempDir, AUTHRIM_DIR);
320
+ if (existsSync(authrimDir)) {
321
+ await cp(authrimDir, tempAuthrimDir, { recursive: true });
322
+ }
323
+ // Preserve .keys directory if it exists (legacy structure)
322
324
  const keysDir = join(sourceDir, '.keys');
323
325
  const tempKeysDir = join(tempDir, '.keys');
324
326
  if (existsSync(keysDir)) {
@@ -586,42 +588,175 @@ async function runLoadConfig() {
586
588
  console.log(chalk.bold('📂 Load Existing Configuration'));
587
589
  console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
588
590
  console.log('');
589
- // Check for config file in current directory
590
- const defaultConfigPath = './authrim-config.json';
591
- const configExists = existsSync(defaultConfigPath);
592
- let configPath = defaultConfigPath;
593
- if (configExists) {
594
- console.log(chalk.green(`✓ Found: ${defaultConfigPath}`));
591
+ // Check for config files in both new and legacy structures
592
+ const baseDir = process.cwd();
593
+ // Detect existing environments
594
+ const { listEnvironments } = await import('../../core/paths.js');
595
+ const environments = listEnvironments(baseDir);
596
+ // Build list of found configs
597
+ const foundConfigs = [];
598
+ // Check new structure (.authrim/{env}/config.json)
599
+ for (const env of environments) {
600
+ const newPaths = getEnvironmentPaths({ baseDir, env });
601
+ if (existsSync(newPaths.config)) {
602
+ foundConfigs.push({ path: newPaths.config, env, type: 'new' });
603
+ }
604
+ }
605
+ // Check legacy structure (authrim-config.json)
606
+ const legacyConfigPath = './authrim-config.json';
607
+ if (existsSync(legacyConfigPath) && !foundConfigs.some((c) => c.type === 'legacy')) {
608
+ // Try to read env from legacy config
609
+ try {
610
+ const legacyContent = await readFile(legacyConfigPath, 'utf-8');
611
+ const legacyConfig = JSON.parse(legacyContent);
612
+ const legacyEnv = legacyConfig.environment?.prefix || 'unknown';
613
+ foundConfigs.push({ path: legacyConfigPath, env: legacyEnv, type: 'legacy' });
614
+ }
615
+ catch {
616
+ foundConfigs.push({ path: legacyConfigPath, env: 'unknown', type: 'legacy' });
617
+ }
618
+ }
619
+ let configPath;
620
+ if (foundConfigs.length > 0) {
621
+ console.log(chalk.green(`✓ Found ${foundConfigs.length} configuration(s):`));
622
+ for (const cfg of foundConfigs) {
623
+ const typeLabel = cfg.type === 'new' ? chalk.blue('(new)') : chalk.yellow('(legacy)');
624
+ console.log(` • ${cfg.path} ${typeLabel} - env: ${cfg.env}`);
625
+ }
595
626
  console.log('');
596
- const action = await select({
597
- message: 'What would you like to do?',
598
- choices: [
599
- { value: 'load', name: '📂 Load this configuration' },
600
- { value: 'other', name: '📁 Specify different file' },
601
- { value: 'back', name: '← Back to Main Menu' },
602
- ],
603
- });
604
- if (action === 'back') {
605
- return false; // Return to main menu
627
+ // Check if there are legacy configs that could be migrated
628
+ const legacyConfigs = foundConfigs.filter((c) => c.type === 'legacy');
629
+ if (legacyConfigs.length > 0) {
630
+ console.log(chalk.yellow('━━━ Legacy Structure Detected ━━━'));
631
+ console.log(chalk.gray('Legacy files:'));
632
+ console.log(chalk.gray(' authrim-config.json'));
633
+ console.log(chalk.gray(' • authrim-lock.json'));
634
+ console.log(chalk.gray(' • .keys/{env}/'));
635
+ console.log('');
636
+ console.log(chalk.gray('New structure benefits:'));
637
+ console.log(chalk.gray(' • Environment portability (zip .authrim/prod/)'));
638
+ console.log(chalk.gray(' • Version tracking per environment'));
639
+ console.log(chalk.gray(' • Cleaner project structure'));
640
+ console.log('');
641
+ const migrateAction = await select({
642
+ message: 'Would you like to migrate to the new structure?',
643
+ choices: [
644
+ { value: 'migrate', name: '🔄 Migrate to new structure (.authrim/{env}/)' },
645
+ { value: 'continue', name: '📂 Continue with legacy structure' },
646
+ { value: 'back', name: '← Back to Main Menu' },
647
+ ],
648
+ });
649
+ if (migrateAction === 'back') {
650
+ return false;
651
+ }
652
+ if (migrateAction === 'migrate') {
653
+ const { migrateToNewStructure, validateMigration } = await import('../../core/migrate.js');
654
+ console.log('');
655
+ const envToMigrate = legacyConfigs[0].env;
656
+ const result = await migrateToNewStructure({
657
+ baseDir,
658
+ env: envToMigrate,
659
+ onProgress: (msg) => console.log(msg),
660
+ });
661
+ if (result.success) {
662
+ console.log('');
663
+ console.log(chalk.green('✓ Migration completed successfully!'));
664
+ // Validate
665
+ const validation = await validateMigration(baseDir, envToMigrate);
666
+ if (validation.valid) {
667
+ console.log(chalk.green('✓ Validation passed'));
668
+ }
669
+ else {
670
+ console.log(chalk.yellow('⚠ Validation issues:'));
671
+ for (const issue of validation.issues) {
672
+ console.log(chalk.yellow(` • ${issue}`));
673
+ }
674
+ }
675
+ console.log('');
676
+ console.log(chalk.cyan('New configuration location:'));
677
+ console.log(chalk.cyan(` .authrim/${envToMigrate}/config.json`));
678
+ console.log('');
679
+ // Update foundConfigs to use new path
680
+ const newPaths = getEnvironmentPaths({ baseDir, env: envToMigrate });
681
+ foundConfigs.length = 0;
682
+ foundConfigs.push({ path: newPaths.config, env: envToMigrate, type: 'new' });
683
+ }
684
+ else {
685
+ console.log('');
686
+ console.log(chalk.red('✗ Migration failed:'));
687
+ for (const error of result.errors) {
688
+ console.log(chalk.red(` • ${error}`));
689
+ }
690
+ console.log('');
691
+ console.log(chalk.yellow('Continuing with legacy structure...'));
692
+ }
693
+ }
606
694
  }
607
- if (action === 'other') {
608
- configPath = await input({
609
- message: 'Enter configuration file path',
610
- validate: (value) => {
611
- if (!value)
612
- return 'Please enter a path';
613
- if (!existsSync(value))
614
- return `File not found: ${value}`;
615
- return true;
616
- },
695
+ if (foundConfigs.length === 1) {
696
+ configPath = foundConfigs[0].path;
697
+ const action = await select({
698
+ message: 'What would you like to do?',
699
+ choices: [
700
+ { value: 'load', name: '📂 Load this configuration' },
701
+ { value: 'other', name: '📁 Specify different file' },
702
+ { value: 'back', name: '← Back to Main Menu' },
703
+ ],
704
+ });
705
+ if (action === 'back') {
706
+ return false; // Return to main menu
707
+ }
708
+ if (action === 'other') {
709
+ configPath = await input({
710
+ message: 'Enter configuration file path',
711
+ validate: (value) => {
712
+ if (!value)
713
+ return 'Please enter a path';
714
+ if (!existsSync(value))
715
+ return `File not found: ${value}`;
716
+ return true;
717
+ },
718
+ });
719
+ }
720
+ }
721
+ else {
722
+ // Multiple configs found - let user select
723
+ const choices = [
724
+ ...foundConfigs.map((cfg) => ({
725
+ value: cfg.path,
726
+ name: `📂 ${cfg.env} (${cfg.path}) ${cfg.type === 'legacy' ? chalk.yellow('legacy') : ''}`,
727
+ })),
728
+ { value: '__other__', name: '📁 Specify different file' },
729
+ { value: '__back__', name: '← Back to Main Menu' },
730
+ ];
731
+ const selected = await select({
732
+ message: 'Select configuration to load',
733
+ choices,
617
734
  });
735
+ if (selected === '__back__') {
736
+ return false;
737
+ }
738
+ if (selected === '__other__') {
739
+ configPath = await input({
740
+ message: 'Enter configuration file path',
741
+ validate: (value) => {
742
+ if (!value)
743
+ return 'Please enter a path';
744
+ if (!existsSync(value))
745
+ return `File not found: ${value}`;
746
+ return true;
747
+ },
748
+ });
749
+ }
750
+ else {
751
+ configPath = selected;
752
+ }
618
753
  }
619
754
  }
620
755
  else {
621
- console.log(chalk.yellow('No authrim-config.json found in current directory.'));
756
+ console.log(chalk.yellow('No configuration found in current directory.'));
622
757
  console.log('');
623
758
  console.log(chalk.gray('💡 Tip: You can specify a config file with:'));
624
- console.log(chalk.cyan(' npx @authrim/setup --config /path/to/authrim-config.json'));
759
+ console.log(chalk.cyan(' npx @authrim/setup --config /path/to/.authrim/{env}/config.json'));
625
760
  console.log('');
626
761
  const action = await select({
627
762
  message: 'What would you like to do?',
@@ -893,11 +1028,13 @@ async function runQuickSetup(options) {
893
1028
  }
894
1029
  // Save email secrets if configured
895
1030
  if (emailConfig.provider === 'resend' && emailConfig.apiKey) {
896
- const keysDir = `.keys/${envPrefix}`;
1031
+ // Use new structure for fresh setups
1032
+ const paths = getEnvironmentPaths({ baseDir: process.cwd(), env: envPrefix });
1033
+ const keysDir = paths.keys;
897
1034
  await import('node:fs/promises').then(async (fs) => {
898
1035
  await fs.mkdir(keysDir, { recursive: true });
899
- await fs.writeFile(`${keysDir}/resend_api_key.txt`, emailConfig.apiKey.trim());
900
- await fs.writeFile(`${keysDir}/email_from.txt`, emailConfig.fromAddress.trim());
1036
+ await fs.writeFile(paths.keyFiles.resendApiKey, emailConfig.apiKey.trim());
1037
+ await fs.writeFile(paths.keyFiles.emailFrom, emailConfig.fromAddress.trim());
901
1038
  if (emailConfig.fromName) {
902
1039
  await fs.writeFile(`${keysDir}/email_from_name.txt`, emailConfig.fromName.trim());
903
1040
  }
@@ -1476,11 +1613,13 @@ async function runNormalSetup(options) {
1476
1613
  }
1477
1614
  // Save email secrets if configured
1478
1615
  if (emailConfigNormal.provider === 'resend' && emailConfigNormal.apiKey) {
1479
- const keysDir = `.keys/${envPrefix}`;
1616
+ // Use new structure for fresh setups
1617
+ const paths = getEnvironmentPaths({ baseDir: process.cwd(), env: envPrefix });
1618
+ const keysDir = paths.keys;
1480
1619
  await import('node:fs/promises').then(async (fs) => {
1481
1620
  await fs.mkdir(keysDir, { recursive: true });
1482
- await fs.writeFile(`${keysDir}/resend_api_key.txt`, emailConfigNormal.apiKey.trim());
1483
- await fs.writeFile(`${keysDir}/email_from.txt`, emailConfigNormal.fromAddress.trim());
1621
+ await fs.writeFile(paths.keyFiles.resendApiKey, emailConfigNormal.apiKey.trim());
1622
+ await fs.writeFile(paths.keyFiles.emailFrom, emailConfigNormal.fromAddress.trim());
1484
1623
  if (emailConfigNormal.fromName) {
1485
1624
  await fs.writeFile(`${keysDir}/email_from_name.txt`, emailConfigNormal.fromName.trim());
1486
1625
  }
@@ -1549,17 +1688,16 @@ async function executeSetup(config, cfApiToken, keepPath) {
1549
1688
  try {
1550
1689
  const keyId = generateKeyId(env);
1551
1690
  secrets = generateAllSecrets(keyId);
1552
- // Save to environment-specific subdirectory: .keys/{env}/
1553
- const keysBaseDir = join(outputDir, '.keys');
1554
- await saveKeysToDirectory(secrets, keysBaseDir, env);
1555
- const keysDir = join(keysBaseDir, env);
1691
+ // Save to new structure: .authrim/{env}/keys/
1692
+ const envPaths = getEnvironmentPaths({ baseDir: outputDir, env });
1693
+ await saveKeysToDirectory(secrets, { baseDir: outputDir, env });
1556
1694
  config.keys = {
1557
1695
  keyId: secrets.keyPair.keyId,
1558
1696
  publicKeyJwk: secrets.keyPair.publicKeyJwk,
1559
- secretsPath: `./.keys/${env}/`,
1697
+ secretsPath: getRelativeKeysPath(), // './keys/' (relative from config location)
1560
1698
  includeSecrets: false,
1561
1699
  };
1562
- keysSpinner.succeed(`Keys generated (${keysDir})`);
1700
+ keysSpinner.succeed(`Keys generated (${envPaths.keys})`);
1563
1701
  }
1564
1702
  catch (error) {
1565
1703
  keysSpinner.fail('Failed to generate keys');
@@ -1595,53 +1733,89 @@ async function executeSetup(config, cfApiToken, keepPath) {
1595
1733
  // Create empty resources
1596
1734
  provisionedResources = { d1: [], kv: [], queues: [], r2: [] };
1597
1735
  }
1598
- // Step 3: Create lock file
1599
- const lockSpinner = ora('authrim-lock.json generating...').start();
1736
+ // Step 3: Create lock file (save to new structure: .authrim/{env}/lock.json)
1737
+ const envPaths = getEnvironmentPaths({ baseDir: outputDir, env });
1738
+ const lockSpinner = ora('Generating lock file...').start();
1600
1739
  try {
1601
1740
  const lockFile = createLockFile(env, provisionedResources);
1602
- const lockPath = join(outputDir, 'authrim-lock.json');
1603
- await saveLockFile(lockFile, lockPath);
1604
- lockSpinner.succeed(`authrim-lock.json saved (${lockPath})`);
1741
+ await saveLockFile(lockFile, { baseDir: outputDir, env });
1742
+ lockSpinner.succeed(`Lock file saved (${envPaths.lock})`);
1605
1743
  }
1606
1744
  catch (error) {
1607
- lockSpinner.fail('authrim-lock.json save failed');
1745
+ lockSpinner.fail('Lock file save failed');
1608
1746
  console.error(error);
1609
1747
  }
1610
- // Step 4: Save configuration
1748
+ // Step 4: Save configuration (save to new structure: .authrim/{env}/config.json)
1611
1749
  const configSpinner = ora('Saving configuration...').start();
1612
1750
  try {
1613
- const configPath = join(outputDir, 'authrim-config.json');
1751
+ // Ensure environment directory exists
1752
+ await mkdir(envPaths.root, { recursive: true });
1753
+ const configPath = envPaths.config;
1614
1754
  config.updatedAt = new Date().toISOString();
1615
1755
  await writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
1756
+ // Also save version.txt
1757
+ const setupVersion = getVersion();
1758
+ await writeFile(envPaths.version, setupVersion, 'utf-8');
1616
1759
  configSpinner.succeed(`Configuration saved (${configPath})`);
1617
1760
  }
1618
1761
  catch (error) {
1619
1762
  configSpinner.fail('Configuration save failed');
1620
1763
  throw error;
1621
1764
  }
1622
- // Step 5: Generate wrangler.toml files (if keeping source or in existing repo)
1765
+ // Step 5: Generate wrangler.toml files
1623
1766
  const resourceIds = toResourceIds(provisionedResources);
1624
1767
  const packagesDir = join(outputDir, 'packages');
1625
- if (existsSync(packagesDir)) {
1626
- const wranglerSpinner = ora('Generating wrangler.toml files...').start();
1627
- try {
1628
- for (const component of CORE_WORKER_COMPONENTS) {
1629
- const componentDir = join(packagesDir, component);
1630
- if (!existsSync(componentDir)) {
1631
- continue; // Skip if component directory doesn't exist
1632
- }
1633
- const wranglerConfig = generateWranglerConfig(component, config, resourceIds);
1634
- const tomlContent = toToml(wranglerConfig);
1635
- const tomlPath = join(componentDir, `wrangler.${env}.toml`);
1636
- await writeFile(tomlPath, tomlContent, 'utf-8');
1768
+ const baseDir = process.cwd();
1769
+ // Step 5a: Save master wrangler configs to .authrim/{env}/wrangler/
1770
+ const wranglerSpinner = ora('Saving wrangler.toml master configs...').start();
1771
+ try {
1772
+ const { saveMasterWranglerConfigs, syncWranglerConfigs } = await import('../../core/wrangler-sync.js');
1773
+ const masterResult = await saveMasterWranglerConfigs(config, resourceIds, {
1774
+ baseDir,
1775
+ env,
1776
+ dryRun: false,
1777
+ onProgress: (msg) => {
1778
+ wranglerSpinner.text = msg;
1779
+ },
1780
+ });
1781
+ if (masterResult.success) {
1782
+ wranglerSpinner.succeed(`Saved ${masterResult.files.length} wrangler.toml master configs`);
1783
+ }
1784
+ else {
1785
+ wranglerSpinner.warn('Some wrangler configs failed to save');
1786
+ for (const error of masterResult.errors) {
1787
+ console.log(chalk.yellow(` • ${error}`));
1637
1788
  }
1638
- wranglerSpinner.succeed('wrangler.toml files generated');
1639
1789
  }
1640
- catch (error) {
1641
- wranglerSpinner.fail('wrangler.toml generation failed');
1642
- console.error(error);
1790
+ // Step 5b: Sync to deployment locations (if packages directory exists)
1791
+ if (existsSync(packagesDir)) {
1792
+ const syncSpinner = ora('Syncing wrangler configs to packages...').start();
1793
+ const syncResult = await syncWranglerConfigs({
1794
+ baseDir,
1795
+ env,
1796
+ packagesDir,
1797
+ force: true, // First time setup, always overwrite
1798
+ dryRun: false,
1799
+ onProgress: (msg) => {
1800
+ syncSpinner.text = msg;
1801
+ },
1802
+ }, undefined // No manual edit callback for init
1803
+ );
1804
+ if (syncResult.success) {
1805
+ syncSpinner.succeed(`Synced wrangler configs to ${syncResult.synced.length} components`);
1806
+ }
1807
+ else {
1808
+ syncSpinner.fail('wrangler config sync failed');
1809
+ for (const error of syncResult.errors) {
1810
+ console.log(chalk.red(` • ${error}`));
1811
+ }
1812
+ }
1643
1813
  }
1644
1814
  }
1815
+ catch (error) {
1816
+ wranglerSpinner.fail('wrangler.toml generation failed');
1817
+ console.error(error);
1818
+ }
1645
1819
  // Summary
1646
1820
  console.log('');
1647
1821
  console.log(chalk.green('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
@@ -1667,9 +1841,10 @@ async function executeSetup(config, cfApiToken, keepPath) {
1667
1841
  console.log('');
1668
1842
  }
1669
1843
  console.log(chalk.bold('📁 Generated Files:'));
1670
- console.log(` - ${join(outputDir, 'authrim-config.json')}`);
1671
- console.log(` - ${join(outputDir, 'authrim-lock.json')}`);
1672
- console.log(` - ${join(outputDir, '.keys/')} ${chalk.gray('(private keys - add to .gitignore)')}`);
1844
+ console.log(` - ${envPaths.config}`);
1845
+ console.log(` - ${envPaths.lock}`);
1846
+ console.log(` - ${envPaths.version}`);
1847
+ console.log(` - ${envPaths.keys}/ ${chalk.gray('(private keys - add .authrim/ to .gitignore)')}`);
1673
1848
  console.log('');
1674
1849
  // Show URLs
1675
1850
  console.log(chalk.bold('🌐 Endpoints:'));
@@ -1747,7 +1922,17 @@ async function handleExistingConfig(configPath) {
1747
1922
  // =============================================================================
1748
1923
  async function handleRedeploy(config, configPath) {
1749
1924
  const env = config.environment.prefix;
1750
- const lockPath = configPath.replace('authrim-config.json', 'authrim-lock.json');
1925
+ // Determine lock file path based on config file structure
1926
+ // New structure: .authrim/{env}/config.json -> .authrim/{env}/lock.json
1927
+ // Legacy structure: authrim-config.json -> authrim-lock.json
1928
+ let lockPath;
1929
+ const isNewStructure = configPath.includes(`${AUTHRIM_DIR}/`) && configPath.endsWith('/config.json');
1930
+ if (isNewStructure) {
1931
+ lockPath = configPath.replace('/config.json', '/lock.json');
1932
+ }
1933
+ else {
1934
+ lockPath = configPath.replace('authrim-config.json', 'authrim-lock.json');
1935
+ }
1751
1936
  console.log('');
1752
1937
  console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
1753
1938
  console.log(chalk.bold('🚀 Redeploy'));
@@ -1789,7 +1974,7 @@ async function handleRedeploy(config, configPath) {
1789
1974
  const lock = await loadLockFile(lockPath);
1790
1975
  const hasLock = lock !== null;
1791
1976
  if (!hasLock) {
1792
- console.log(chalk.yellow('\n⚠️ authrim-lock.json not found'));
1977
+ console.log(chalk.yellow(`\n⚠️ Lock file not found (${lockPath})`));
1793
1978
  const createResources = await confirm({
1794
1979
  message: 'Create new Cloudflare resources?',
1795
1980
  default: true,
@@ -1815,7 +2000,7 @@ async function handleRedeploy(config, configPath) {
1815
2000
  // Create and save lock file
1816
2001
  const newLock = createLockFile(env, provisionedResources);
1817
2002
  await saveLockFile(newLock, lockPath);
1818
- console.log(chalk.green(`\n✓ authrim-lock.json saved`));
2003
+ console.log(chalk.green(`\n✓ Lock file saved (${lockPath})`));
1819
2004
  }
1820
2005
  catch (error) {
1821
2006
  console.log(chalk.red(' ✗ Failed to create resources'));